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