renderbuffer.c revision a52803e1087749bfa571c29fc4c1a73fa9b7bf8e
1/* 2 * Mesa 3-D graphics library 3 * Version: 6.5 4 * 5 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25 26/** 27 * Functions for allocating/managing renderbuffers. 28 * Also, routines for reading/writing software-based renderbuffer data as 29 * ubytes, ushorts, uints, etc. 30 * 31 * The 'alpha8' renderbuffer is interesting. It's used to add a software-based 32 * alpha channel to RGB renderbuffers. This is done by wrapping the RGB 33 * renderbuffer with the alpha renderbuffer. We can do this because of the 34 * OO-nature of renderbuffers. 35 * 36 * Down the road we'll use this for run-time support of 8, 16 and 32-bit 37 * color channels. For example, Mesa may use 32-bit/float color channels 38 * internally (swrast) and use wrapper renderbuffers to convert 32-bit 39 * values down to 16 or 8-bit values for whatever kind of framebuffer we have. 40 */ 41 42 43#include "glheader.h" 44#include "imports.h" 45#include "context.h" 46#include "fbobject.h" 47#include "formats.h" 48#include "mtypes.h" 49#include "renderbuffer.h" 50 51 52/* 53 * Routines for get/put values in common buffer formats follow. 54 */ 55 56static void * 57get_pointer_generic(struct gl_context *ctx, struct gl_renderbuffer *rb, 58 GLint x, GLint y) 59{ 60 if (!rb->Data) 61 return NULL; 62 63 return (rb->Data + 64 (y * rb->RowStride + x) * _mesa_get_format_bytes(rb->Format)); 65} 66 67/* GetRow() implementation for formats where DataType matches the rb->Format. 68 */ 69static void 70get_row_generic(struct gl_context *ctx, struct gl_renderbuffer *rb, 71 GLuint count, GLint x, GLint y, void *values) 72{ 73 void *src = rb->GetPointer(ctx, rb, x, y); 74 memcpy(values, src, count * _mesa_get_format_bytes(rb->Format)); 75} 76 77/********************************************************************** 78 * Functions for buffers of 1 X GLubyte values. 79 * Typically stencil. 80 */ 81 82static void 83get_values_ubyte(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 84 const GLint x[], const GLint y[], void *values) 85{ 86 GLubyte *dst = (GLubyte *) values; 87 GLuint i; 88 ASSERT(rb->DataType == GL_UNSIGNED_BYTE); 89 for (i = 0; i < count; i++) { 90 const GLubyte *src = (GLubyte *) rb->Data + y[i] * rb->RowStride + x[i]; 91 dst[i] = *src; 92 } 93} 94 95 96static void 97put_row_ubyte(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 98 GLint x, GLint y, const void *values, const GLubyte *mask) 99{ 100 const GLubyte *src = (const GLubyte *) values; 101 GLubyte *dst = (GLubyte *) rb->Data + y * rb->RowStride + x; 102 ASSERT(rb->DataType == GL_UNSIGNED_BYTE); 103 if (mask) { 104 GLuint i; 105 for (i = 0; i < count; i++) { 106 if (mask[i]) { 107 dst[i] = src[i]; 108 } 109 } 110 } 111 else { 112 memcpy(dst, values, count * sizeof(GLubyte)); 113 } 114} 115 116 117static void 118put_mono_row_ubyte(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 119 GLint x, GLint y, const void *value, const GLubyte *mask) 120{ 121 const GLubyte val = *((const GLubyte *) value); 122 GLubyte *dst = (GLubyte *) rb->Data + y * rb->RowStride + x; 123 ASSERT(rb->DataType == GL_UNSIGNED_BYTE); 124 if (mask) { 125 GLuint i; 126 for (i = 0; i < count; i++) { 127 if (mask[i]) { 128 dst[i] = val; 129 } 130 } 131 } 132 else { 133 GLuint i; 134 for (i = 0; i < count; i++) { 135 dst[i] = val; 136 } 137 } 138} 139 140 141static void 142put_values_ubyte(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 143 const GLint x[], const GLint y[], 144 const void *values, const GLubyte *mask) 145{ 146 const GLubyte *src = (const GLubyte *) values; 147 GLuint i; 148 ASSERT(rb->DataType == GL_UNSIGNED_BYTE); 149 for (i = 0; i < count; i++) { 150 if (!mask || mask[i]) { 151 GLubyte *dst = (GLubyte *) rb->Data + y[i] * rb->RowStride + x[i]; 152 *dst = src[i]; 153 } 154 } 155} 156 157 158static void 159put_mono_values_ubyte(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 160 const GLint x[], const GLint y[], 161 const void *value, const GLubyte *mask) 162{ 163 const GLubyte val = *((const GLubyte *) value); 164 GLuint i; 165 ASSERT(rb->DataType == GL_UNSIGNED_BYTE); 166 for (i = 0; i < count; i++) { 167 if (!mask || mask[i]) { 168 GLubyte *dst = (GLubyte *) rb->Data + y[i] * rb->RowStride + x[i]; 169 *dst = val; 170 } 171 } 172} 173 174 175/********************************************************************** 176 * Functions for buffers of 1 X GLushort values. 177 * Typically depth/Z. 178 */ 179 180static void 181get_values_ushort(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 182 const GLint x[], const GLint y[], void *values) 183{ 184 GLushort *dst = (GLushort *) values; 185 GLuint i; 186 ASSERT(rb->DataType == GL_UNSIGNED_SHORT); 187 for (i = 0; i < count; i++) { 188 const GLushort *src = (GLushort *) rb->Data + y[i] * rb->RowStride + x[i]; 189 dst[i] = *src; 190 } 191} 192 193 194static void 195put_row_ushort(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 196 GLint x, GLint y, const void *values, const GLubyte *mask) 197{ 198 const GLushort *src = (const GLushort *) values; 199 GLushort *dst = (GLushort *) rb->Data + y * rb->RowStride + x; 200 ASSERT(rb->DataType == GL_UNSIGNED_SHORT); 201 if (mask) { 202 GLuint i; 203 for (i = 0; i < count; i++) { 204 if (mask[i]) { 205 dst[i] = src[i]; 206 } 207 } 208 } 209 else { 210 memcpy(dst, src, count * sizeof(GLushort)); 211 } 212} 213 214 215static void 216put_mono_row_ushort(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 217 GLint x, GLint y, const void *value, const GLubyte *mask) 218{ 219 const GLushort val = *((const GLushort *) value); 220 GLushort *dst = (GLushort *) rb->Data + y * rb->RowStride + x; 221 ASSERT(rb->DataType == GL_UNSIGNED_SHORT); 222 if (mask) { 223 GLuint i; 224 for (i = 0; i < count; i++) { 225 if (mask[i]) { 226 dst[i] = val; 227 } 228 } 229 } 230 else { 231 GLuint i; 232 for (i = 0; i < count; i++) { 233 dst[i] = val; 234 } 235 } 236} 237 238 239static void 240put_values_ushort(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 241 const GLint x[], const GLint y[], const void *values, 242 const GLubyte *mask) 243{ 244 const GLushort *src = (const GLushort *) values; 245 GLuint i; 246 ASSERT(rb->DataType == GL_UNSIGNED_SHORT); 247 for (i = 0; i < count; i++) { 248 if (!mask || mask[i]) { 249 GLushort *dst = (GLushort *) rb->Data + y[i] * rb->RowStride + x[i]; 250 *dst = src[i]; 251 } 252 } 253} 254 255 256static void 257put_mono_values_ushort(struct gl_context *ctx, struct gl_renderbuffer *rb, 258 GLuint count, const GLint x[], const GLint y[], 259 const void *value, const GLubyte *mask) 260{ 261 const GLushort val = *((const GLushort *) value); 262 ASSERT(rb->DataType == GL_UNSIGNED_SHORT); 263 if (mask) { 264 GLuint i; 265 for (i = 0; i < count; i++) { 266 if (mask[i]) { 267 GLushort *dst = (GLushort *) rb->Data + y[i] * rb->RowStride + x[i]; 268 *dst = val; 269 } 270 } 271 } 272 else { 273 GLuint i; 274 for (i = 0; i < count; i++) { 275 GLushort *dst = (GLushort *) rb->Data + y[i] * rb->RowStride + x[i]; 276 *dst = val; 277 } 278 } 279} 280 281 282/********************************************************************** 283 * Functions for buffers of 1 X GLuint values. 284 * Typically depth/Z or color index. 285 */ 286 287static void 288get_values_uint(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 289 const GLint x[], const GLint y[], void *values) 290{ 291 GLuint *dst = (GLuint *) values; 292 GLuint i; 293 ASSERT(rb->DataType == GL_UNSIGNED_INT || 294 rb->DataType == GL_UNSIGNED_INT_24_8_EXT); 295 for (i = 0; i < count; i++) { 296 const GLuint *src = (GLuint *) rb->Data + y[i] * rb->RowStride + x[i]; 297 dst[i] = *src; 298 } 299} 300 301 302static void 303put_row_uint(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 304 GLint x, GLint y, const void *values, const GLubyte *mask) 305{ 306 const GLuint *src = (const GLuint *) values; 307 GLuint *dst = (GLuint *) rb->Data + y * rb->RowStride + x; 308 ASSERT(rb->DataType == GL_UNSIGNED_INT || 309 rb->DataType == GL_UNSIGNED_INT_24_8_EXT); 310 if (mask) { 311 GLuint i; 312 for (i = 0; i < count; i++) { 313 if (mask[i]) { 314 dst[i] = src[i]; 315 } 316 } 317 } 318 else { 319 memcpy(dst, src, count * sizeof(GLuint)); 320 } 321} 322 323 324static void 325put_mono_row_uint(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 326 GLint x, GLint y, const void *value, const GLubyte *mask) 327{ 328 const GLuint val = *((const GLuint *) value); 329 GLuint *dst = (GLuint *) rb->Data + y * rb->RowStride + x; 330 ASSERT(rb->DataType == GL_UNSIGNED_INT || 331 rb->DataType == GL_UNSIGNED_INT_24_8_EXT); 332 if (mask) { 333 GLuint i; 334 for (i = 0; i < count; i++) { 335 if (mask[i]) { 336 dst[i] = val; 337 } 338 } 339 } 340 else { 341 GLuint i; 342 for (i = 0; i < count; i++) { 343 dst[i] = val; 344 } 345 } 346} 347 348 349static void 350put_values_uint(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 351 const GLint x[], const GLint y[], const void *values, 352 const GLubyte *mask) 353{ 354 const GLuint *src = (const GLuint *) values; 355 GLuint i; 356 ASSERT(rb->DataType == GL_UNSIGNED_INT || 357 rb->DataType == GL_UNSIGNED_INT_24_8_EXT); 358 for (i = 0; i < count; i++) { 359 if (!mask || mask[i]) { 360 GLuint *dst = (GLuint *) rb->Data + y[i] * rb->RowStride + x[i]; 361 *dst = src[i]; 362 } 363 } 364} 365 366 367static void 368put_mono_values_uint(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 369 const GLint x[], const GLint y[], const void *value, 370 const GLubyte *mask) 371{ 372 const GLuint val = *((const GLuint *) value); 373 GLuint i; 374 ASSERT(rb->DataType == GL_UNSIGNED_INT || 375 rb->DataType == GL_UNSIGNED_INT_24_8_EXT); 376 for (i = 0; i < count; i++) { 377 if (!mask || mask[i]) { 378 GLuint *dst = (GLuint *) rb->Data + y[i] * rb->RowStride + x[i]; 379 *dst = val; 380 } 381 } 382} 383 384 385/********************************************************************** 386 * Functions for buffers of 3 X GLubyte (or GLbyte) values. 387 * Typically color buffers. 388 * NOTE: the incoming and outgoing colors are RGBA! We ignore incoming 389 * alpha values and return 255 for outgoing alpha values. 390 */ 391 392static void * 393get_pointer_ubyte3(struct gl_context *ctx, struct gl_renderbuffer *rb, 394 GLint x, GLint y) 395{ 396 ASSERT(rb->Format == MESA_FORMAT_RGB888); 397 /* No direct access since this buffer is RGB but caller will be 398 * treating it as if it were RGBA. 399 */ 400 return NULL; 401} 402 403 404static void 405get_row_ubyte3(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 406 GLint x, GLint y, void *values) 407{ 408 const GLubyte *src = (const GLubyte *) (rb->Data + 409 3 * (y * rb->RowStride + x)); 410 GLubyte *dst = (GLubyte *) values; 411 GLuint i; 412 ASSERT(rb->Format == MESA_FORMAT_RGB888); 413 ASSERT(rb->DataType == GL_UNSIGNED_BYTE); 414 for (i = 0; i < count; i++) { 415 dst[i * 4 + 0] = src[i * 3 + 0]; 416 dst[i * 4 + 1] = src[i * 3 + 1]; 417 dst[i * 4 + 2] = src[i * 3 + 2]; 418 dst[i * 4 + 3] = 255; 419 } 420} 421 422 423static void 424get_values_ubyte3(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 425 const GLint x[], const GLint y[], void *values) 426{ 427 GLubyte *dst = (GLubyte *) values; 428 GLuint i; 429 ASSERT(rb->Format == MESA_FORMAT_RGB888); 430 ASSERT(rb->DataType == GL_UNSIGNED_BYTE); 431 for (i = 0; i < count; i++) { 432 const GLubyte *src 433 = (GLubyte *) rb->Data + 3 * (y[i] * rb->RowStride + x[i]); 434 dst[i * 4 + 0] = src[0]; 435 dst[i * 4 + 1] = src[1]; 436 dst[i * 4 + 2] = src[2]; 437 dst[i * 4 + 3] = 255; 438 } 439} 440 441 442static void 443put_row_ubyte3(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 444 GLint x, GLint y, const void *values, const GLubyte *mask) 445{ 446 /* note: incoming values are RGB+A! */ 447 const GLubyte *src = (const GLubyte *) values; 448 GLubyte *dst = (GLubyte *) rb->Data + 3 * (y * rb->RowStride + x); 449 GLuint i; 450 ASSERT(rb->Format == MESA_FORMAT_RGB888); 451 ASSERT(rb->DataType == GL_UNSIGNED_BYTE); 452 for (i = 0; i < count; i++) { 453 if (!mask || mask[i]) { 454 dst[i * 3 + 0] = src[i * 4 + 0]; 455 dst[i * 3 + 1] = src[i * 4 + 1]; 456 dst[i * 3 + 2] = src[i * 4 + 2]; 457 } 458 } 459} 460 461 462static void 463put_row_rgb_ubyte3(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 464 GLint x, GLint y, const void *values, const GLubyte *mask) 465{ 466 /* note: incoming values are RGB+A! */ 467 const GLubyte *src = (const GLubyte *) values; 468 GLubyte *dst = (GLubyte *) rb->Data + 3 * (y * rb->RowStride + x); 469 GLuint i; 470 ASSERT(rb->Format == MESA_FORMAT_RGB888); 471 ASSERT(rb->DataType == GL_UNSIGNED_BYTE); 472 for (i = 0; i < count; i++) { 473 if (!mask || mask[i]) { 474 dst[i * 3 + 0] = src[i * 3 + 0]; 475 dst[i * 3 + 1] = src[i * 3 + 1]; 476 dst[i * 3 + 2] = src[i * 3 + 2]; 477 } 478 } 479} 480 481 482static void 483put_mono_row_ubyte3(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 484 GLint x, GLint y, const void *value, const GLubyte *mask) 485{ 486 /* note: incoming value is RGB+A! */ 487 const GLubyte val0 = ((const GLubyte *) value)[0]; 488 const GLubyte val1 = ((const GLubyte *) value)[1]; 489 const GLubyte val2 = ((const GLubyte *) value)[2]; 490 GLubyte *dst = (GLubyte *) rb->Data + 3 * (y * rb->RowStride + x); 491 ASSERT(rb->Format == MESA_FORMAT_RGB888); 492 ASSERT(rb->DataType == GL_UNSIGNED_BYTE); 493 if (!mask && val0 == val1 && val1 == val2) { 494 /* optimized case */ 495 memset(dst, val0, 3 * count); 496 } 497 else { 498 GLuint i; 499 for (i = 0; i < count; i++) { 500 if (!mask || mask[i]) { 501 dst[i * 3 + 0] = val0; 502 dst[i * 3 + 1] = val1; 503 dst[i * 3 + 2] = val2; 504 } 505 } 506 } 507} 508 509 510static void 511put_values_ubyte3(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 512 const GLint x[], const GLint y[], const void *values, 513 const GLubyte *mask) 514{ 515 /* note: incoming values are RGB+A! */ 516 const GLubyte *src = (const GLubyte *) values; 517 GLuint i; 518 ASSERT(rb->Format == MESA_FORMAT_RGB888); 519 ASSERT(rb->DataType == GL_UNSIGNED_BYTE); 520 for (i = 0; i < count; i++) { 521 if (!mask || mask[i]) { 522 GLubyte *dst = (GLubyte *) rb->Data + 3 * (y[i] * rb->RowStride + x[i]); 523 dst[0] = src[i * 4 + 0]; 524 dst[1] = src[i * 4 + 1]; 525 dst[2] = src[i * 4 + 2]; 526 } 527 } 528} 529 530 531static void 532put_mono_values_ubyte3(struct gl_context *ctx, struct gl_renderbuffer *rb, 533 GLuint count, const GLint x[], const GLint y[], 534 const void *value, const GLubyte *mask) 535{ 536 /* note: incoming value is RGB+A! */ 537 const GLubyte val0 = ((const GLubyte *) value)[0]; 538 const GLubyte val1 = ((const GLubyte *) value)[1]; 539 const GLubyte val2 = ((const GLubyte *) value)[2]; 540 GLuint i; 541 ASSERT(rb->Format == MESA_FORMAT_RGB888); 542 ASSERT(rb->DataType == GL_UNSIGNED_BYTE); 543 for (i = 0; i < count; i++) { 544 if (!mask || mask[i]) { 545 GLubyte *dst = (GLubyte *) (rb->Data + 546 3 * (y[i] * rb->RowStride + x[i])); 547 dst[0] = val0; 548 dst[1] = val1; 549 dst[2] = val2; 550 } 551 } 552} 553 554 555/********************************************************************** 556 * Functions for buffers of 4 X GLubyte (or GLbyte) values. 557 * Typically color buffers. 558 */ 559 560static void 561get_values_ubyte4(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 562 const GLint x[], const GLint y[], void *values) 563{ 564 /* treat 4*GLubyte as 1*GLuint */ 565 GLuint *dst = (GLuint *) values; 566 GLuint i; 567 ASSERT(rb->DataType == GL_UNSIGNED_BYTE); 568 ASSERT(rb->Format == MESA_FORMAT_RGBA8888); 569 for (i = 0; i < count; i++) { 570 const GLuint *src = (GLuint *) rb->Data + (y[i] * rb->RowStride + x[i]); 571 dst[i] = *src; 572 } 573} 574 575 576static void 577put_row_ubyte4(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 578 GLint x, GLint y, const void *values, const GLubyte *mask) 579{ 580 /* treat 4*GLubyte as 1*GLuint */ 581 const GLuint *src = (const GLuint *) values; 582 GLuint *dst = (GLuint *) rb->Data + (y * rb->RowStride + x); 583 ASSERT(rb->DataType == GL_UNSIGNED_BYTE); 584 ASSERT(rb->Format == MESA_FORMAT_RGBA8888); 585 if (mask) { 586 GLuint i; 587 for (i = 0; i < count; i++) { 588 if (mask[i]) { 589 dst[i] = src[i]; 590 } 591 } 592 } 593 else { 594 memcpy(dst, src, 4 * count * sizeof(GLubyte)); 595 } 596} 597 598 599static void 600put_row_rgb_ubyte4(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 601 GLint x, GLint y, const void *values, const GLubyte *mask) 602{ 603 /* Store RGB values in RGBA buffer */ 604 const GLubyte *src = (const GLubyte *) values; 605 GLubyte *dst = (GLubyte *) rb->Data + 4 * (y * rb->RowStride + x); 606 GLuint i; 607 ASSERT(rb->DataType == GL_UNSIGNED_BYTE); 608 ASSERT(rb->Format == MESA_FORMAT_RGBA8888); 609 for (i = 0; i < count; i++) { 610 if (!mask || mask[i]) { 611 dst[i * 4 + 0] = src[i * 3 + 0]; 612 dst[i * 4 + 1] = src[i * 3 + 1]; 613 dst[i * 4 + 2] = src[i * 3 + 2]; 614 dst[i * 4 + 3] = 0xff; 615 } 616 } 617} 618 619 620static void 621put_mono_row_ubyte4(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 622 GLint x, GLint y, const void *value, const GLubyte *mask) 623{ 624 /* treat 4*GLubyte as 1*GLuint */ 625 const GLuint val = *((const GLuint *) value); 626 GLuint *dst = (GLuint *) rb->Data + (y * rb->RowStride + x); 627 ASSERT(rb->DataType == GL_UNSIGNED_BYTE); 628 ASSERT(rb->Format == MESA_FORMAT_RGBA8888); 629 if (!mask && val == 0) { 630 /* common case */ 631 memset(dst, 0, count * 4 * sizeof(GLubyte)); 632 } 633 else { 634 /* general case */ 635 if (mask) { 636 GLuint i; 637 for (i = 0; i < count; i++) { 638 if (mask[i]) { 639 dst[i] = val; 640 } 641 } 642 } 643 else { 644 GLuint i; 645 for (i = 0; i < count; i++) { 646 dst[i] = val; 647 } 648 } 649 } 650} 651 652 653static void 654put_values_ubyte4(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 655 const GLint x[], const GLint y[], const void *values, 656 const GLubyte *mask) 657{ 658 /* treat 4*GLubyte as 1*GLuint */ 659 const GLuint *src = (const GLuint *) values; 660 GLuint i; 661 ASSERT(rb->DataType == GL_UNSIGNED_BYTE); 662 ASSERT(rb->Format == MESA_FORMAT_RGBA8888); 663 for (i = 0; i < count; i++) { 664 if (!mask || mask[i]) { 665 GLuint *dst = (GLuint *) rb->Data + (y[i] * rb->RowStride + x[i]); 666 *dst = src[i]; 667 } 668 } 669} 670 671 672static void 673put_mono_values_ubyte4(struct gl_context *ctx, struct gl_renderbuffer *rb, 674 GLuint count, const GLint x[], const GLint y[], 675 const void *value, const GLubyte *mask) 676{ 677 /* treat 4*GLubyte as 1*GLuint */ 678 const GLuint val = *((const GLuint *) value); 679 GLuint i; 680 ASSERT(rb->DataType == GL_UNSIGNED_BYTE); 681 ASSERT(rb->Format == MESA_FORMAT_RGBA8888); 682 for (i = 0; i < count; i++) { 683 if (!mask || mask[i]) { 684 GLuint *dst = (GLuint *) rb->Data + (y[i] * rb->RowStride + x[i]); 685 *dst = val; 686 } 687 } 688} 689 690 691/********************************************************************** 692 * Functions for buffers of 4 X GLushort (or GLshort) values. 693 * Typically accum buffer. 694 */ 695 696static void 697get_values_ushort4(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 698 const GLint x[], const GLint y[], void *values) 699{ 700 GLushort *dst = (GLushort *) values; 701 GLuint i; 702 ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT); 703 for (i = 0; i < count; i++) { 704 const GLushort *src 705 = (GLushort *) rb->Data + 4 * (y[i] * rb->RowStride + x[i]); 706 dst[i] = *src; 707 } 708} 709 710 711static void 712put_row_ushort4(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 713 GLint x, GLint y, const void *values, const GLubyte *mask) 714{ 715 const GLushort *src = (const GLushort *) values; 716 GLushort *dst = (GLushort *) rb->Data + 4 * (y * rb->RowStride + x); 717 ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT); 718 if (mask) { 719 GLuint i; 720 for (i = 0; i < count; i++) { 721 if (mask[i]) { 722 dst[i * 4 + 0] = src[i * 4 + 0]; 723 dst[i * 4 + 1] = src[i * 4 + 1]; 724 dst[i * 4 + 2] = src[i * 4 + 2]; 725 dst[i * 4 + 3] = src[i * 4 + 3]; 726 } 727 } 728 } 729 else { 730 memcpy(dst, src, 4 * count * sizeof(GLushort)); 731 } 732} 733 734 735static void 736put_row_rgb_ushort4(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 737 GLint x, GLint y, const void *values, const GLubyte *mask) 738{ 739 /* Put RGB values in RGBA buffer */ 740 const GLushort *src = (const GLushort *) values; 741 GLushort *dst = (GLushort *) rb->Data + 4 * (y * rb->RowStride + x); 742 ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT); 743 if (mask) { 744 GLuint i; 745 for (i = 0; i < count; i++) { 746 if (mask[i]) { 747 dst[i * 4 + 0] = src[i * 3 + 0]; 748 dst[i * 4 + 1] = src[i * 3 + 1]; 749 dst[i * 4 + 2] = src[i * 3 + 2]; 750 dst[i * 4 + 3] = 0xffff; 751 } 752 } 753 } 754 else { 755 memcpy(dst, src, 4 * count * sizeof(GLushort)); 756 } 757} 758 759 760static void 761put_mono_row_ushort4(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 762 GLint x, GLint y, const void *value, const GLubyte *mask) 763{ 764 const GLushort val0 = ((const GLushort *) value)[0]; 765 const GLushort val1 = ((const GLushort *) value)[1]; 766 const GLushort val2 = ((const GLushort *) value)[2]; 767 const GLushort val3 = ((const GLushort *) value)[3]; 768 GLushort *dst = (GLushort *) rb->Data + 4 * (y * rb->RowStride + x); 769 ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT); 770 if (!mask && val0 == 0 && val1 == 0 && val2 == 0 && val3 == 0) { 771 /* common case for clearing accum buffer */ 772 memset(dst, 0, count * 4 * sizeof(GLushort)); 773 } 774 else { 775 GLuint i; 776 for (i = 0; i < count; i++) { 777 if (!mask || mask[i]) { 778 dst[i * 4 + 0] = val0; 779 dst[i * 4 + 1] = val1; 780 dst[i * 4 + 2] = val2; 781 dst[i * 4 + 3] = val3; 782 } 783 } 784 } 785} 786 787 788static void 789put_values_ushort4(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 790 const GLint x[], const GLint y[], const void *values, 791 const GLubyte *mask) 792{ 793 const GLushort *src = (const GLushort *) values; 794 GLuint i; 795 ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT); 796 for (i = 0; i < count; i++) { 797 if (!mask || mask[i]) { 798 GLushort *dst = (GLushort *) (rb->Data + 4 * 799 (y[i] * rb->RowStride + x[i])); 800 dst[0] = src[i * 4 + 0]; 801 dst[1] = src[i * 4 + 1]; 802 dst[2] = src[i * 4 + 2]; 803 dst[3] = src[i * 4 + 3]; 804 } 805 } 806} 807 808 809static void 810put_mono_values_ushort4(struct gl_context *ctx, struct gl_renderbuffer *rb, 811 GLuint count, const GLint x[], const GLint y[], 812 const void *value, const GLubyte *mask) 813{ 814 const GLushort val0 = ((const GLushort *) value)[0]; 815 const GLushort val1 = ((const GLushort *) value)[1]; 816 const GLushort val2 = ((const GLushort *) value)[2]; 817 const GLushort val3 = ((const GLushort *) value)[3]; 818 GLuint i; 819 ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT); 820 for (i = 0; i < count; i++) { 821 if (!mask || mask[i]) { 822 GLushort *dst = (GLushort *) (rb->Data + 823 4 * (y[i] * rb->RowStride + x[i])); 824 dst[0] = val0; 825 dst[1] = val1; 826 dst[2] = val2; 827 dst[3] = val3; 828 } 829 } 830} 831 832/** 833 * This is the default software fallback for gl_renderbuffer's span 834 * access functions. 835 * 836 * The assumptions are that rb->Data will be a pointer to (0,0), that pixels 837 * are packed in the type of rb->Format, and that subsequent rows appear 838 * rb->RowStride pixels later. 839 */ 840void 841_mesa_set_renderbuffer_accessors(struct gl_renderbuffer *rb) 842{ 843 rb->GetPointer = get_pointer_generic; 844 rb->GetRow = get_row_generic; 845 846 switch (rb->Format) { 847 case MESA_FORMAT_RGB888: 848 rb->DataType = GL_UNSIGNED_BYTE; 849 rb->GetPointer = get_pointer_ubyte3; 850 rb->GetRow = get_row_ubyte3; 851 rb->GetValues = get_values_ubyte3; 852 rb->PutRow = put_row_ubyte3; 853 rb->PutRowRGB = put_row_rgb_ubyte3; 854 rb->PutMonoRow = put_mono_row_ubyte3; 855 rb->PutValues = put_values_ubyte3; 856 rb->PutMonoValues = put_mono_values_ubyte3; 857 break; 858 859 case MESA_FORMAT_RGBA8888: 860 rb->DataType = GL_UNSIGNED_BYTE; 861 rb->GetValues = get_values_ubyte4; 862 rb->PutRow = put_row_ubyte4; 863 rb->PutRowRGB = put_row_rgb_ubyte4; 864 rb->PutMonoRow = put_mono_row_ubyte4; 865 rb->PutValues = put_values_ubyte4; 866 rb->PutMonoValues = put_mono_values_ubyte4; 867 break; 868 869 case MESA_FORMAT_SIGNED_RGBA_16: 870 rb->DataType = GL_SHORT; 871 rb->GetValues = get_values_ushort4; 872 rb->PutRow = put_row_ushort4; 873 rb->PutRowRGB = put_row_rgb_ushort4; 874 rb->PutMonoRow = put_mono_row_ushort4; 875 rb->PutValues = put_values_ushort4; 876 rb->PutMonoValues = put_mono_values_ushort4; 877 break; 878 879#if 0 880 case MESA_FORMAT_A8: 881 rb->DataType = GL_UNSIGNED_BYTE; 882 rb->GetValues = get_values_alpha8; 883 rb->PutRow = put_row_alpha8; 884 rb->PutRowRGB = NULL; 885 rb->PutMonoRow = put_mono_row_alpha8; 886 rb->PutValues = put_values_alpha8; 887 rb->PutMonoValues = put_mono_values_alpha8; 888 break; 889#endif 890 891 case MESA_FORMAT_S8: 892 rb->DataType = GL_UNSIGNED_BYTE; 893 rb->GetValues = get_values_ubyte; 894 rb->PutRow = put_row_ubyte; 895 rb->PutRowRGB = NULL; 896 rb->PutMonoRow = put_mono_row_ubyte; 897 rb->PutValues = put_values_ubyte; 898 rb->PutMonoValues = put_mono_values_ubyte; 899 break; 900 901 case MESA_FORMAT_Z16: 902 rb->DataType = GL_UNSIGNED_SHORT; 903 rb->GetValues = get_values_ushort; 904 rb->PutRow = put_row_ushort; 905 rb->PutRowRGB = NULL; 906 rb->PutMonoRow = put_mono_row_ushort; 907 rb->PutValues = put_values_ushort; 908 rb->PutMonoValues = put_mono_values_ushort; 909 break; 910 911 case MESA_FORMAT_Z32: 912 case MESA_FORMAT_X8_Z24: 913 case MESA_FORMAT_Z24_X8: 914 rb->DataType = GL_UNSIGNED_INT; 915 rb->GetValues = get_values_uint; 916 rb->PutRow = put_row_uint; 917 rb->PutRowRGB = NULL; 918 rb->PutMonoRow = put_mono_row_uint; 919 rb->PutValues = put_values_uint; 920 rb->PutMonoValues = put_mono_values_uint; 921 break; 922 923 case MESA_FORMAT_Z24_S8: 924 case MESA_FORMAT_S8_Z24: 925 rb->DataType = GL_UNSIGNED_INT_24_8_EXT; 926 rb->GetValues = get_values_uint; 927 rb->PutRow = put_row_uint; 928 rb->PutRowRGB = NULL; 929 rb->PutMonoRow = put_mono_row_uint; 930 rb->PutValues = put_values_uint; 931 rb->PutMonoValues = put_mono_values_uint; 932 break; 933 934 default: 935 break; 936 } 937} 938 939/** 940 * This is a software fallback for the gl_renderbuffer->AllocStorage 941 * function. 942 * Device drivers will typically override this function for the buffers 943 * which it manages (typically color buffers, Z and stencil). 944 * Other buffers (like software accumulation and aux buffers) which the driver 945 * doesn't manage can be handled with this function. 946 * 947 * This one multi-purpose function can allocate stencil, depth, accum, color 948 * or color-index buffers! 949 * 950 * This function also plugs in the appropriate GetPointer, Get/PutRow and 951 * Get/PutValues functions. 952 */ 953GLboolean 954_mesa_soft_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb, 955 GLenum internalFormat, 956 GLuint width, GLuint height) 957{ 958 switch (internalFormat) { 959 case GL_RGB: 960 case GL_R3_G3_B2: 961 case GL_RGB4: 962 case GL_RGB5: 963 case GL_RGB8: 964 case GL_RGB10: 965 case GL_RGB12: 966 case GL_RGB16: 967 rb->Format = MESA_FORMAT_RGB888; 968 break; 969 case GL_RGBA: 970 case GL_RGBA2: 971 case GL_RGBA4: 972 case GL_RGB5_A1: 973 case GL_RGBA8: 974#if 1 975 case GL_RGB10_A2: 976 case GL_RGBA12: 977#endif 978 rb->Format = MESA_FORMAT_RGBA8888; 979 break; 980 case GL_RGBA16: 981 case GL_RGBA16_SNORM: 982 /* for accum buffer */ 983 rb->Format = MESA_FORMAT_SIGNED_RGBA_16; 984 break; 985#if 0 986 case GL_ALPHA8: 987 rb->Format = MESA_FORMAT_A8; 988 break; 989#endif 990 case GL_STENCIL_INDEX: 991 case GL_STENCIL_INDEX1_EXT: 992 case GL_STENCIL_INDEX4_EXT: 993 case GL_STENCIL_INDEX8_EXT: 994 case GL_STENCIL_INDEX16_EXT: 995 rb->Format = MESA_FORMAT_S8; 996 break; 997 case GL_DEPTH_COMPONENT: 998 case GL_DEPTH_COMPONENT16: 999 rb->Format = MESA_FORMAT_Z16; 1000 break; 1001 case GL_DEPTH_COMPONENT24: 1002 rb->Format = MESA_FORMAT_X8_Z24; 1003 break; 1004 case GL_DEPTH_COMPONENT32: 1005 rb->Format = MESA_FORMAT_Z32; 1006 break; 1007 case GL_DEPTH_STENCIL_EXT: 1008 case GL_DEPTH24_STENCIL8_EXT: 1009 rb->Format = MESA_FORMAT_Z24_S8; 1010 break; 1011 default: 1012 /* unsupported format */ 1013 return GL_FALSE; 1014 } 1015 1016 _mesa_set_renderbuffer_accessors(rb); 1017 1018 ASSERT(rb->DataType); 1019 ASSERT(rb->GetPointer); 1020 ASSERT(rb->GetRow); 1021 ASSERT(rb->GetValues); 1022 ASSERT(rb->PutRow); 1023 ASSERT(rb->PutMonoRow); 1024 ASSERT(rb->PutValues); 1025 ASSERT(rb->PutMonoValues); 1026 1027 /* free old buffer storage */ 1028 if (rb->Data) { 1029 free(rb->Data); 1030 rb->Data = NULL; 1031 } 1032 1033 rb->RowStride = width; 1034 1035 if (width > 0 && height > 0) { 1036 /* allocate new buffer storage */ 1037 rb->Data = malloc(width * height * _mesa_get_format_bytes(rb->Format)); 1038 1039 if (rb->Data == NULL) { 1040 rb->Width = 0; 1041 rb->Height = 0; 1042 rb->RowStride = 0; 1043 _mesa_error(ctx, GL_OUT_OF_MEMORY, 1044 "software renderbuffer allocation (%d x %d x %d)", 1045 width, height, _mesa_get_format_bytes(rb->Format)); 1046 return GL_FALSE; 1047 } 1048 } 1049 1050 rb->Width = width; 1051 rb->Height = height; 1052 rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat); 1053 1054 if (rb->Name == 0 && 1055 internalFormat == GL_RGBA16_SNORM && 1056 rb->_BaseFormat == 0) { 1057 /* NOTE: This is a special case just for accumulation buffers. 1058 * This is a very limited use case- there's no snorm texturing or 1059 * rendering going on. 1060 */ 1061 rb->_BaseFormat = GL_RGBA; 1062 } 1063 else { 1064 /* the internalFormat should have been error checked long ago */ 1065 ASSERT(rb->_BaseFormat); 1066 } 1067 1068 return GL_TRUE; 1069} 1070 1071 1072 1073/**********************************************************************/ 1074/**********************************************************************/ 1075/**********************************************************************/ 1076 1077 1078/** 1079 * Here we utilize the gl_renderbuffer->Wrapper field to put an alpha 1080 * buffer wrapper around an existing RGB renderbuffer (hw or sw). 1081 * 1082 * When PutRow is called (for example), we store the alpha values in 1083 * this buffer, then pass on the PutRow call to the wrapped RGB 1084 * buffer. 1085 */ 1086 1087 1088static GLboolean 1089alloc_storage_alpha8(struct gl_context *ctx, struct gl_renderbuffer *arb, 1090 GLenum internalFormat, GLuint width, GLuint height) 1091{ 1092 ASSERT(arb != arb->Wrapped); 1093 ASSERT(arb->Format == MESA_FORMAT_A8); 1094 1095 /* first, pass the call to the wrapped RGB buffer */ 1096 if (!arb->Wrapped->AllocStorage(ctx, arb->Wrapped, internalFormat, 1097 width, height)) { 1098 return GL_FALSE; 1099 } 1100 1101 /* next, resize my alpha buffer */ 1102 if (arb->Data) { 1103 free(arb->Data); 1104 } 1105 1106 arb->Data = malloc(width * height * sizeof(GLubyte)); 1107 if (arb->Data == NULL) { 1108 arb->Width = 0; 1109 arb->Height = 0; 1110 _mesa_error(ctx, GL_OUT_OF_MEMORY, "software alpha buffer allocation"); 1111 return GL_FALSE; 1112 } 1113 1114 arb->Width = width; 1115 arb->Height = height; 1116 arb->RowStride = width; 1117 1118 return GL_TRUE; 1119} 1120 1121 1122/** 1123 * Delete an alpha_renderbuffer object, as well as the wrapped RGB buffer. 1124 */ 1125static void 1126delete_renderbuffer_alpha8(struct gl_renderbuffer *arb) 1127{ 1128 if (arb->Data) { 1129 free(arb->Data); 1130 } 1131 ASSERT(arb->Wrapped); 1132 ASSERT(arb != arb->Wrapped); 1133 arb->Wrapped->Delete(arb->Wrapped); 1134 arb->Wrapped = NULL; 1135 free(arb); 1136} 1137 1138 1139static void * 1140get_pointer_alpha8(struct gl_context *ctx, struct gl_renderbuffer *arb, 1141 GLint x, GLint y) 1142{ 1143 return NULL; /* don't allow direct access! */ 1144} 1145 1146 1147static void 1148get_row_alpha8(struct gl_context *ctx, struct gl_renderbuffer *arb, GLuint count, 1149 GLint x, GLint y, void *values) 1150{ 1151 /* NOTE: 'values' is RGBA format! */ 1152 const GLubyte *src = (const GLubyte *) arb->Data + y * arb->RowStride + x; 1153 GLubyte *dst = (GLubyte *) values; 1154 GLuint i; 1155 ASSERT(arb != arb->Wrapped); 1156 ASSERT(arb->DataType == GL_UNSIGNED_BYTE); 1157 /* first, pass the call to the wrapped RGB buffer */ 1158 arb->Wrapped->GetRow(ctx, arb->Wrapped, count, x, y, values); 1159 /* second, fill in alpha values from this buffer! */ 1160 for (i = 0; i < count; i++) { 1161 dst[i * 4 + 3] = src[i]; 1162 } 1163} 1164 1165 1166static void 1167get_values_alpha8(struct gl_context *ctx, struct gl_renderbuffer *arb, GLuint count, 1168 const GLint x[], const GLint y[], void *values) 1169{ 1170 GLubyte *dst = (GLubyte *) values; 1171 GLuint i; 1172 ASSERT(arb != arb->Wrapped); 1173 ASSERT(arb->DataType == GL_UNSIGNED_BYTE); 1174 /* first, pass the call to the wrapped RGB buffer */ 1175 arb->Wrapped->GetValues(ctx, arb->Wrapped, count, x, y, values); 1176 /* second, fill in alpha values from this buffer! */ 1177 for (i = 0; i < count; i++) { 1178 const GLubyte *src = (GLubyte *) arb->Data + y[i] * arb->RowStride + x[i]; 1179 dst[i * 4 + 3] = *src; 1180 } 1181} 1182 1183 1184static void 1185put_row_alpha8(struct gl_context *ctx, struct gl_renderbuffer *arb, GLuint count, 1186 GLint x, GLint y, const void *values, const GLubyte *mask) 1187{ 1188 const GLubyte *src = (const GLubyte *) values; 1189 GLubyte *dst = (GLubyte *) arb->Data + y * arb->RowStride + x; 1190 GLuint i; 1191 ASSERT(arb != arb->Wrapped); 1192 ASSERT(arb->DataType == GL_UNSIGNED_BYTE); 1193 /* first, pass the call to the wrapped RGB buffer */ 1194 arb->Wrapped->PutRow(ctx, arb->Wrapped, count, x, y, values, mask); 1195 /* second, store alpha in our buffer */ 1196 for (i = 0; i < count; i++) { 1197 if (!mask || mask[i]) { 1198 dst[i] = src[i * 4 + 3]; 1199 } 1200 } 1201} 1202 1203 1204static void 1205put_row_rgb_alpha8(struct gl_context *ctx, struct gl_renderbuffer *arb, GLuint count, 1206 GLint x, GLint y, const void *values, const GLubyte *mask) 1207{ 1208 const GLubyte *src = (const GLubyte *) values; 1209 GLubyte *dst = (GLubyte *) arb->Data + y * arb->RowStride + x; 1210 GLuint i; 1211 ASSERT(arb != arb->Wrapped); 1212 ASSERT(arb->DataType == GL_UNSIGNED_BYTE); 1213 /* first, pass the call to the wrapped RGB buffer */ 1214 arb->Wrapped->PutRowRGB(ctx, arb->Wrapped, count, x, y, values, mask); 1215 /* second, store alpha in our buffer */ 1216 for (i = 0; i < count; i++) { 1217 if (!mask || mask[i]) { 1218 dst[i] = src[i * 4 + 3]; 1219 } 1220 } 1221} 1222 1223 1224static void 1225put_mono_row_alpha8(struct gl_context *ctx, struct gl_renderbuffer *arb, GLuint count, 1226 GLint x, GLint y, const void *value, const GLubyte *mask) 1227{ 1228 const GLubyte val = ((const GLubyte *) value)[3]; 1229 GLubyte *dst = (GLubyte *) arb->Data + y * arb->RowStride + x; 1230 ASSERT(arb != arb->Wrapped); 1231 ASSERT(arb->DataType == GL_UNSIGNED_BYTE); 1232 /* first, pass the call to the wrapped RGB buffer */ 1233 arb->Wrapped->PutMonoRow(ctx, arb->Wrapped, count, x, y, value, mask); 1234 /* second, store alpha in our buffer */ 1235 if (mask) { 1236 GLuint i; 1237 for (i = 0; i < count; i++) { 1238 if (mask[i]) { 1239 dst[i] = val; 1240 } 1241 } 1242 } 1243 else { 1244 memset(dst, val, count); 1245 } 1246} 1247 1248 1249static void 1250put_values_alpha8(struct gl_context *ctx, struct gl_renderbuffer *arb, GLuint count, 1251 const GLint x[], const GLint y[], 1252 const void *values, const GLubyte *mask) 1253{ 1254 const GLubyte *src = (const GLubyte *) values; 1255 GLuint i; 1256 ASSERT(arb != arb->Wrapped); 1257 ASSERT(arb->DataType == GL_UNSIGNED_BYTE); 1258 /* first, pass the call to the wrapped RGB buffer */ 1259 arb->Wrapped->PutValues(ctx, arb->Wrapped, count, x, y, values, mask); 1260 /* second, store alpha in our buffer */ 1261 for (i = 0; i < count; i++) { 1262 if (!mask || mask[i]) { 1263 GLubyte *dst = (GLubyte *) arb->Data + y[i] * arb->RowStride + x[i]; 1264 *dst = src[i * 4 + 3]; 1265 } 1266 } 1267} 1268 1269 1270static void 1271put_mono_values_alpha8(struct gl_context *ctx, struct gl_renderbuffer *arb, 1272 GLuint count, const GLint x[], const GLint y[], 1273 const void *value, const GLubyte *mask) 1274{ 1275 const GLubyte val = ((const GLubyte *) value)[3]; 1276 GLuint i; 1277 ASSERT(arb != arb->Wrapped); 1278 ASSERT(arb->DataType == GL_UNSIGNED_BYTE); 1279 /* first, pass the call to the wrapped RGB buffer */ 1280 arb->Wrapped->PutValues(ctx, arb->Wrapped, count, x, y, value, mask); 1281 /* second, store alpha in our buffer */ 1282 for (i = 0; i < count; i++) { 1283 if (!mask || mask[i]) { 1284 GLubyte *dst = (GLubyte *) arb->Data + y[i] * arb->RowStride + x[i]; 1285 *dst = val; 1286 } 1287 } 1288} 1289 1290 1291static void 1292copy_buffer_alpha8(struct gl_renderbuffer* dst, struct gl_renderbuffer* src) 1293{ 1294 ASSERT(dst->Format == MESA_FORMAT_A8); 1295 ASSERT(src->Format == MESA_FORMAT_A8); 1296 ASSERT(dst->Width == src->Width); 1297 ASSERT(dst->Height == src->Height); 1298 ASSERT(dst->RowStride == src->RowStride); 1299 1300 memcpy(dst->Data, src->Data, dst->RowStride * dst->Height * sizeof(GLubyte)); 1301} 1302 1303 1304/**********************************************************************/ 1305/**********************************************************************/ 1306/**********************************************************************/ 1307 1308 1309/** 1310 * Default GetPointer routine. Always return NULL to indicate that 1311 * direct buffer access is not supported. 1312 */ 1313static void * 1314nop_get_pointer(struct gl_context *ctx, struct gl_renderbuffer *rb, GLint x, GLint y) 1315{ 1316 return NULL; 1317} 1318 1319 1320/** 1321 * Initialize the fields of a gl_renderbuffer to default values. 1322 */ 1323void 1324_mesa_init_renderbuffer(struct gl_renderbuffer *rb, GLuint name) 1325{ 1326 _glthread_INIT_MUTEX(rb->Mutex); 1327 1328 rb->ClassID = 0; 1329 rb->Name = name; 1330 rb->RefCount = 0; 1331 rb->Delete = _mesa_delete_renderbuffer; 1332 1333 /* The rest of these should be set later by the caller of this function or 1334 * the AllocStorage method: 1335 */ 1336 rb->AllocStorage = NULL; 1337 1338 rb->Width = 0; 1339 rb->Height = 0; 1340 rb->InternalFormat = GL_NONE; 1341 rb->Format = MESA_FORMAT_NONE; 1342 1343 rb->DataType = GL_NONE; 1344 rb->Data = NULL; 1345 1346 /* Point back to ourself so that we don't have to check for Wrapped==NULL 1347 * all over the drivers. 1348 */ 1349 rb->Wrapped = rb; 1350 1351 rb->GetPointer = nop_get_pointer; 1352 rb->GetRow = NULL; 1353 rb->GetValues = NULL; 1354 rb->PutRow = NULL; 1355 rb->PutRowRGB = NULL; 1356 rb->PutMonoRow = NULL; 1357 rb->PutValues = NULL; 1358 rb->PutMonoValues = NULL; 1359} 1360 1361 1362/** 1363 * Allocate a new gl_renderbuffer object. This can be used for user-created 1364 * renderbuffers or window-system renderbuffers. 1365 */ 1366struct gl_renderbuffer * 1367_mesa_new_renderbuffer(struct gl_context *ctx, GLuint name) 1368{ 1369 struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer); 1370 if (rb) { 1371 _mesa_init_renderbuffer(rb, name); 1372 } 1373 return rb; 1374} 1375 1376 1377/** 1378 * Delete a gl_framebuffer. 1379 * This is the default function for renderbuffer->Delete(). 1380 */ 1381void 1382_mesa_delete_renderbuffer(struct gl_renderbuffer *rb) 1383{ 1384 if (rb->Data) { 1385 free(rb->Data); 1386 } 1387 free(rb); 1388} 1389 1390 1391/** 1392 * Allocate a software-based renderbuffer. This is called via the 1393 * ctx->Driver.NewRenderbuffer() function when the user creates a new 1394 * renderbuffer. 1395 * This would not be used for hardware-based renderbuffers. 1396 */ 1397struct gl_renderbuffer * 1398_mesa_new_soft_renderbuffer(struct gl_context *ctx, GLuint name) 1399{ 1400 struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, name); 1401 if (rb) { 1402 rb->AllocStorage = _mesa_soft_renderbuffer_storage; 1403 /* Normally, one would setup the PutRow, GetRow, etc functions here. 1404 * But we're doing that in the _mesa_soft_renderbuffer_storage() function 1405 * instead. 1406 */ 1407 } 1408 return rb; 1409} 1410 1411 1412/** 1413 * Add software-based color renderbuffers to the given framebuffer. 1414 * This is a helper routine for device drivers when creating a 1415 * window system framebuffer (not a user-created render/framebuffer). 1416 * Once this function is called, you can basically forget about this 1417 * renderbuffer; core Mesa will handle all the buffer management and 1418 * rendering! 1419 */ 1420GLboolean 1421_mesa_add_color_renderbuffers(struct gl_context *ctx, struct gl_framebuffer *fb, 1422 GLuint rgbBits, GLuint alphaBits, 1423 GLboolean frontLeft, GLboolean backLeft, 1424 GLboolean frontRight, GLboolean backRight) 1425{ 1426 gl_buffer_index b; 1427 1428 if (rgbBits > 16 || alphaBits > 16) { 1429 _mesa_problem(ctx, 1430 "Unsupported bit depth in _mesa_add_color_renderbuffers"); 1431 return GL_FALSE; 1432 } 1433 1434 assert(MAX_COLOR_ATTACHMENTS >= 4); 1435 1436 for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) { 1437 struct gl_renderbuffer *rb; 1438 1439 if (b == BUFFER_FRONT_LEFT && !frontLeft) 1440 continue; 1441 else if (b == BUFFER_BACK_LEFT && !backLeft) 1442 continue; 1443 else if (b == BUFFER_FRONT_RIGHT && !frontRight) 1444 continue; 1445 else if (b == BUFFER_BACK_RIGHT && !backRight) 1446 continue; 1447 1448 assert(fb->Attachment[b].Renderbuffer == NULL); 1449 1450 rb = _mesa_new_renderbuffer(ctx, 0); 1451 if (!rb) { 1452 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer"); 1453 return GL_FALSE; 1454 } 1455 1456 if (rgbBits <= 8) { 1457 if (alphaBits) 1458 rb->Format = MESA_FORMAT_RGBA8888; 1459 else 1460 rb->Format = MESA_FORMAT_RGB888; 1461 } 1462 else { 1463 assert(rgbBits <= 16); 1464 rb->Format = MESA_FORMAT_NONE; /*XXX RGBA16;*/ 1465 } 1466 rb->InternalFormat = GL_RGBA; 1467 1468 rb->AllocStorage = _mesa_soft_renderbuffer_storage; 1469 _mesa_add_renderbuffer(fb, b, rb); 1470 } 1471 1472 return GL_TRUE; 1473} 1474 1475 1476/** 1477 * Add software-based alpha renderbuffers to the given framebuffer. 1478 * This is a helper routine for device drivers when creating a 1479 * window system framebuffer (not a user-created render/framebuffer). 1480 * Once this function is called, you can basically forget about this 1481 * renderbuffer; core Mesa will handle all the buffer management and 1482 * rendering! 1483 */ 1484GLboolean 1485_mesa_add_alpha_renderbuffers(struct gl_context *ctx, struct gl_framebuffer *fb, 1486 GLuint alphaBits, 1487 GLboolean frontLeft, GLboolean backLeft, 1488 GLboolean frontRight, GLboolean backRight) 1489{ 1490 gl_buffer_index b; 1491 1492 /* for window system framebuffers only! */ 1493 assert(fb->Name == 0); 1494 1495 if (alphaBits > 8) { 1496 _mesa_problem(ctx, 1497 "Unsupported bit depth in _mesa_add_alpha_renderbuffers"); 1498 return GL_FALSE; 1499 } 1500 1501 assert(MAX_COLOR_ATTACHMENTS >= 4); 1502 1503 /* Wrap each of the RGB color buffers with an alpha renderbuffer. 1504 */ 1505 for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) { 1506 struct gl_renderbuffer *arb; 1507 1508 if (b == BUFFER_FRONT_LEFT && !frontLeft) 1509 continue; 1510 else if (b == BUFFER_BACK_LEFT && !backLeft) 1511 continue; 1512 else if (b == BUFFER_FRONT_RIGHT && !frontRight) 1513 continue; 1514 else if (b == BUFFER_BACK_RIGHT && !backRight) 1515 continue; 1516 1517 /* the RGB buffer to wrap must already exist!! */ 1518 assert(fb->Attachment[b].Renderbuffer); 1519 1520 /* only GLubyte supported for now */ 1521 assert(fb->Attachment[b].Renderbuffer->DataType == GL_UNSIGNED_BYTE); 1522 1523 /* allocate alpha renderbuffer */ 1524 arb = _mesa_new_renderbuffer(ctx, 0); 1525 if (!arb) { 1526 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating alpha buffer"); 1527 return GL_FALSE; 1528 } 1529 1530 /* wrap the alpha renderbuffer around the RGB renderbuffer */ 1531 arb->Wrapped = fb->Attachment[b].Renderbuffer; 1532 1533 /* Set up my alphabuffer fields and plug in my functions. 1534 * The functions will put/get the alpha values from/to RGBA arrays 1535 * and then call the wrapped buffer's functions to handle the RGB 1536 * values. 1537 */ 1538 arb->InternalFormat = arb->Wrapped->InternalFormat; 1539 arb->Format = MESA_FORMAT_A8; 1540 arb->DataType = arb->Wrapped->DataType; 1541 arb->AllocStorage = alloc_storage_alpha8; 1542 arb->Delete = delete_renderbuffer_alpha8; 1543 arb->GetPointer = get_pointer_alpha8; 1544 arb->GetRow = get_row_alpha8; 1545 arb->GetValues = get_values_alpha8; 1546 arb->PutRow = put_row_alpha8; 1547 arb->PutRowRGB = put_row_rgb_alpha8; 1548 arb->PutMonoRow = put_mono_row_alpha8; 1549 arb->PutValues = put_values_alpha8; 1550 arb->PutMonoValues = put_mono_values_alpha8; 1551 1552 /* clear the pointer to avoid assertion/sanity check failure later */ 1553 fb->Attachment[b].Renderbuffer = NULL; 1554 1555 /* plug the alpha renderbuffer into the colorbuffer attachment */ 1556 _mesa_add_renderbuffer(fb, b, arb); 1557 } 1558 1559 return GL_TRUE; 1560} 1561 1562 1563/** 1564 * For framebuffers that use a software alpha channel wrapper 1565 * created by _mesa_add_alpha_renderbuffer or _mesa_add_soft_renderbuffers, 1566 * copy the back buffer alpha channel into the front buffer alpha channel. 1567 */ 1568void 1569_mesa_copy_soft_alpha_renderbuffers(struct gl_context *ctx, struct gl_framebuffer *fb) 1570{ 1571 if (fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer && 1572 fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer) 1573 copy_buffer_alpha8(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer, 1574 fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer); 1575 1576 1577 if (fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer && 1578 fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer) 1579 copy_buffer_alpha8(fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer, 1580 fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer); 1581} 1582 1583 1584/** 1585 * Add a software-based depth renderbuffer to the given framebuffer. 1586 * This is a helper routine for device drivers when creating a 1587 * window system framebuffer (not a user-created render/framebuffer). 1588 * Once this function is called, you can basically forget about this 1589 * renderbuffer; core Mesa will handle all the buffer management and 1590 * rendering! 1591 */ 1592GLboolean 1593_mesa_add_depth_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb, 1594 GLuint depthBits) 1595{ 1596 struct gl_renderbuffer *rb; 1597 1598 if (depthBits > 32) { 1599 _mesa_problem(ctx, 1600 "Unsupported depthBits in _mesa_add_depth_renderbuffer"); 1601 return GL_FALSE; 1602 } 1603 1604 assert(fb->Attachment[BUFFER_DEPTH].Renderbuffer == NULL); 1605 1606 rb = _mesa_new_renderbuffer(ctx, 0); 1607 if (!rb) { 1608 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating depth buffer"); 1609 return GL_FALSE; 1610 } 1611 1612 if (depthBits <= 16) { 1613 rb->Format = MESA_FORMAT_Z16; 1614 rb->InternalFormat = GL_DEPTH_COMPONENT16; 1615 } 1616 else if (depthBits <= 24) { 1617 rb->Format = MESA_FORMAT_X8_Z24; 1618 rb->InternalFormat = GL_DEPTH_COMPONENT24; 1619 } 1620 else { 1621 rb->Format = MESA_FORMAT_Z32; 1622 rb->InternalFormat = GL_DEPTH_COMPONENT32; 1623 } 1624 1625 rb->AllocStorage = _mesa_soft_renderbuffer_storage; 1626 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb); 1627 1628 return GL_TRUE; 1629} 1630 1631 1632/** 1633 * Add a software-based stencil renderbuffer to the given framebuffer. 1634 * This is a helper routine for device drivers when creating a 1635 * window system framebuffer (not a user-created render/framebuffer). 1636 * Once this function is called, you can basically forget about this 1637 * renderbuffer; core Mesa will handle all the buffer management and 1638 * rendering! 1639 */ 1640GLboolean 1641_mesa_add_stencil_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb, 1642 GLuint stencilBits) 1643{ 1644 struct gl_renderbuffer *rb; 1645 1646 if (stencilBits > 16) { 1647 _mesa_problem(ctx, 1648 "Unsupported stencilBits in _mesa_add_stencil_renderbuffer"); 1649 return GL_FALSE; 1650 } 1651 1652 assert(fb->Attachment[BUFFER_STENCIL].Renderbuffer == NULL); 1653 1654 rb = _mesa_new_renderbuffer(ctx, 0); 1655 if (!rb) { 1656 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating stencil buffer"); 1657 return GL_FALSE; 1658 } 1659 1660 assert(stencilBits <= 8); 1661 rb->Format = MESA_FORMAT_S8; 1662 rb->InternalFormat = GL_STENCIL_INDEX8; 1663 1664 rb->AllocStorage = _mesa_soft_renderbuffer_storage; 1665 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, rb); 1666 1667 return GL_TRUE; 1668} 1669 1670 1671/** 1672 * Add a software-based accumulation renderbuffer to the given framebuffer. 1673 * This is a helper routine for device drivers when creating a 1674 * window system framebuffer (not a user-created render/framebuffer). 1675 * Once this function is called, you can basically forget about this 1676 * renderbuffer; core Mesa will handle all the buffer management and 1677 * rendering! 1678 */ 1679GLboolean 1680_mesa_add_accum_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb, 1681 GLuint redBits, GLuint greenBits, 1682 GLuint blueBits, GLuint alphaBits) 1683{ 1684 struct gl_renderbuffer *rb; 1685 1686 if (redBits > 16 || greenBits > 16 || blueBits > 16 || alphaBits > 16) { 1687 _mesa_problem(ctx, 1688 "Unsupported accumBits in _mesa_add_accum_renderbuffer"); 1689 return GL_FALSE; 1690 } 1691 1692 assert(fb->Attachment[BUFFER_ACCUM].Renderbuffer == NULL); 1693 1694 rb = _mesa_new_renderbuffer(ctx, 0); 1695 if (!rb) { 1696 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer"); 1697 return GL_FALSE; 1698 } 1699 1700 rb->Format = MESA_FORMAT_SIGNED_RGBA_16; 1701 rb->InternalFormat = GL_RGBA16_SNORM; 1702 rb->AllocStorage = _mesa_soft_renderbuffer_storage; 1703 _mesa_add_renderbuffer(fb, BUFFER_ACCUM, rb); 1704 1705 return GL_TRUE; 1706} 1707 1708 1709 1710/** 1711 * Add a software-based aux renderbuffer to the given framebuffer. 1712 * This is a helper routine for device drivers when creating a 1713 * window system framebuffer (not a user-created render/framebuffer). 1714 * Once this function is called, you can basically forget about this 1715 * renderbuffer; core Mesa will handle all the buffer management and 1716 * rendering! 1717 * 1718 * NOTE: color-index aux buffers not supported. 1719 */ 1720GLboolean 1721_mesa_add_aux_renderbuffers(struct gl_context *ctx, struct gl_framebuffer *fb, 1722 GLuint colorBits, GLuint numBuffers) 1723{ 1724 GLuint i; 1725 1726 if (colorBits > 16) { 1727 _mesa_problem(ctx, 1728 "Unsupported accumBits in _mesa_add_aux_renderbuffers"); 1729 return GL_FALSE; 1730 } 1731 1732 assert(numBuffers <= MAX_AUX_BUFFERS); 1733 1734 for (i = 0; i < numBuffers; i++) { 1735 struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, 0); 1736 1737 assert(fb->Attachment[BUFFER_AUX0 + i].Renderbuffer == NULL); 1738 1739 if (!rb) { 1740 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating aux buffer"); 1741 return GL_FALSE; 1742 } 1743 1744 assert (colorBits <= 8); 1745 rb->Format = MESA_FORMAT_RGBA8888; 1746 rb->InternalFormat = GL_RGBA; 1747 1748 rb->AllocStorage = _mesa_soft_renderbuffer_storage; 1749 _mesa_add_renderbuffer(fb, BUFFER_AUX0 + i, rb); 1750 } 1751 return GL_TRUE; 1752} 1753 1754 1755/** 1756 * Create/attach software-based renderbuffers to the given framebuffer. 1757 * This is a helper routine for device drivers. Drivers can just as well 1758 * call the individual _mesa_add_*_renderbuffer() routines directly. 1759 */ 1760void 1761_mesa_add_soft_renderbuffers(struct gl_framebuffer *fb, 1762 GLboolean color, 1763 GLboolean depth, 1764 GLboolean stencil, 1765 GLboolean accum, 1766 GLboolean alpha, 1767 GLboolean aux) 1768{ 1769 GLboolean frontLeft = GL_TRUE; 1770 GLboolean backLeft = fb->Visual.doubleBufferMode; 1771 GLboolean frontRight = fb->Visual.stereoMode; 1772 GLboolean backRight = fb->Visual.stereoMode && fb->Visual.doubleBufferMode; 1773 1774 if (color) { 1775 assert(fb->Visual.redBits == fb->Visual.greenBits); 1776 assert(fb->Visual.redBits == fb->Visual.blueBits); 1777 _mesa_add_color_renderbuffers(NULL, fb, 1778 fb->Visual.redBits, 1779 fb->Visual.alphaBits, 1780 frontLeft, backLeft, 1781 frontRight, backRight); 1782 } 1783 1784 if (depth) { 1785 assert(fb->Visual.depthBits > 0); 1786 _mesa_add_depth_renderbuffer(NULL, fb, fb->Visual.depthBits); 1787 } 1788 1789 if (stencil) { 1790 assert(fb->Visual.stencilBits > 0); 1791 _mesa_add_stencil_renderbuffer(NULL, fb, fb->Visual.stencilBits); 1792 } 1793 1794 if (accum) { 1795 assert(fb->Visual.accumRedBits > 0); 1796 assert(fb->Visual.accumGreenBits > 0); 1797 assert(fb->Visual.accumBlueBits > 0); 1798 _mesa_add_accum_renderbuffer(NULL, fb, 1799 fb->Visual.accumRedBits, 1800 fb->Visual.accumGreenBits, 1801 fb->Visual.accumBlueBits, 1802 fb->Visual.accumAlphaBits); 1803 } 1804 1805 if (aux) { 1806 assert(fb->Visual.numAuxBuffers > 0); 1807 _mesa_add_aux_renderbuffers(NULL, fb, fb->Visual.redBits, 1808 fb->Visual.numAuxBuffers); 1809 } 1810 1811 if (alpha) { 1812 assert(fb->Visual.alphaBits > 0); 1813 _mesa_add_alpha_renderbuffers(NULL, fb, fb->Visual.alphaBits, 1814 frontLeft, backLeft, 1815 frontRight, backRight); 1816 } 1817 1818#if 0 1819 if (multisample) { 1820 /* maybe someday */ 1821 } 1822#endif 1823} 1824 1825 1826/** 1827 * Attach a renderbuffer to a framebuffer. 1828 * \param bufferName one of the BUFFER_x tokens 1829 */ 1830void 1831_mesa_add_renderbuffer(struct gl_framebuffer *fb, 1832 gl_buffer_index bufferName, struct gl_renderbuffer *rb) 1833{ 1834 assert(fb); 1835 assert(rb); 1836 assert(bufferName < BUFFER_COUNT); 1837 1838 /* There should be no previous renderbuffer on this attachment point, 1839 * with the exception of depth/stencil since the same renderbuffer may 1840 * be used for both. 1841 */ 1842 assert(bufferName == BUFFER_DEPTH || 1843 bufferName == BUFFER_STENCIL || 1844 fb->Attachment[bufferName].Renderbuffer == NULL); 1845 1846 /* winsys vs. user-created buffer cross check */ 1847 if (fb->Name) { 1848 assert(rb->Name); 1849 } 1850 else { 1851 assert(!rb->Name); 1852 } 1853 1854 fb->Attachment[bufferName].Type = GL_RENDERBUFFER_EXT; 1855 fb->Attachment[bufferName].Complete = GL_TRUE; 1856 _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer, rb); 1857} 1858 1859 1860/** 1861 * Remove the named renderbuffer from the given framebuffer. 1862 * \param bufferName one of the BUFFER_x tokens 1863 */ 1864void 1865_mesa_remove_renderbuffer(struct gl_framebuffer *fb, 1866 gl_buffer_index bufferName) 1867{ 1868 struct gl_renderbuffer *rb; 1869 1870 assert(bufferName < BUFFER_COUNT); 1871 1872 rb = fb->Attachment[bufferName].Renderbuffer; 1873 if (!rb) 1874 return; 1875 1876 _mesa_reference_renderbuffer(&rb, NULL); 1877 1878 fb->Attachment[bufferName].Renderbuffer = NULL; 1879} 1880 1881 1882/** 1883 * Set *ptr to point to rb. If *ptr points to another renderbuffer, 1884 * dereference that buffer first. The new renderbuffer's refcount will 1885 * be incremented. The old renderbuffer's refcount will be decremented. 1886 */ 1887void 1888_mesa_reference_renderbuffer(struct gl_renderbuffer **ptr, 1889 struct gl_renderbuffer *rb) 1890{ 1891 assert(ptr); 1892 if (*ptr == rb) { 1893 /* no change */ 1894 return; 1895 } 1896 1897 if (*ptr) { 1898 /* Unreference the old renderbuffer */ 1899 GLboolean deleteFlag = GL_FALSE; 1900 struct gl_renderbuffer *oldRb = *ptr; 1901 1902 _glthread_LOCK_MUTEX(oldRb->Mutex); 1903 ASSERT(oldRb->RefCount > 0); 1904 oldRb->RefCount--; 1905 /*printf("RB DECR %p (%d) to %d\n", (void*) oldRb, oldRb->Name, oldRb->RefCount);*/ 1906 deleteFlag = (oldRb->RefCount == 0); 1907 _glthread_UNLOCK_MUTEX(oldRb->Mutex); 1908 1909 if (deleteFlag) { 1910 oldRb->Delete(oldRb); 1911 } 1912 1913 *ptr = NULL; 1914 } 1915 assert(!*ptr); 1916 1917 if (rb) { 1918 /* reference new renderbuffer */ 1919 _glthread_LOCK_MUTEX(rb->Mutex); 1920 rb->RefCount++; 1921 /*printf("RB INCR %p (%d) to %d\n", (void*) rb, rb->Name, rb->RefCount);*/ 1922 _glthread_UNLOCK_MUTEX(rb->Mutex); 1923 *ptr = rb; 1924 } 1925} 1926 1927 1928/** 1929 * Create a new combined depth/stencil renderbuffer for implementing 1930 * the GL_EXT_packed_depth_stencil extension. 1931 * \return new depth/stencil renderbuffer 1932 */ 1933struct gl_renderbuffer * 1934_mesa_new_depthstencil_renderbuffer(struct gl_context *ctx, GLuint name) 1935{ 1936 struct gl_renderbuffer *dsrb; 1937 1938 dsrb = _mesa_new_renderbuffer(ctx, name); 1939 if (!dsrb) 1940 return NULL; 1941 1942 /* init fields not covered by _mesa_new_renderbuffer() */ 1943 dsrb->InternalFormat = GL_DEPTH24_STENCIL8_EXT; 1944 dsrb->Format = MESA_FORMAT_Z24_S8; 1945 dsrb->AllocStorage = _mesa_soft_renderbuffer_storage; 1946 1947 return dsrb; 1948} 1949