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