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