renderbuffer.c revision 45e76d2665b38ba3787548310efc59e969124c01
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 _mesa_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 _mesa_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 _mesa_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 _mesa_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 _mesa_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 _mesa_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 _mesa_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 _mesa_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 _mesa_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 _mesa_bzero(dst, 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 _mesa_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 _mesa_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 _mesa_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 _mesa_bzero(dst, 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 case GL_DEPTH_COMPONENT32: 1056 rb->DataType = GL_UNSIGNED_INT; 1057 rb->GetPointer = get_pointer_uint; 1058 rb->GetRow = get_row_uint; 1059 rb->GetValues = get_values_uint; 1060 rb->PutRow = put_row_uint; 1061 rb->PutRowRGB = NULL; 1062 rb->PutMonoRow = put_mono_row_uint; 1063 rb->PutValues = put_values_uint; 1064 rb->PutMonoValues = put_mono_values_uint; 1065 rb->Format = MESA_FORMAT_Z32; 1066 pixelSize = sizeof(GLuint); 1067 break; 1068 case GL_DEPTH_STENCIL_EXT: 1069 case GL_DEPTH24_STENCIL8_EXT: 1070 rb->Format = MESA_FORMAT_Z24_S8; 1071 rb->DataType = GL_UNSIGNED_INT_24_8_EXT; 1072 rb->GetPointer = get_pointer_uint; 1073 rb->GetRow = get_row_uint; 1074 rb->GetValues = get_values_uint; 1075 rb->PutRow = put_row_uint; 1076 rb->PutRowRGB = NULL; 1077 rb->PutMonoRow = put_mono_row_uint; 1078 rb->PutValues = put_values_uint; 1079 rb->PutMonoValues = put_mono_values_uint; 1080 pixelSize = sizeof(GLuint); 1081 break; 1082 case GL_COLOR_INDEX8_EXT: 1083 case GL_COLOR_INDEX16_EXT: 1084 case COLOR_INDEX32: 1085 rb->Format = MESA_FORMAT_CI8; 1086 rb->DataType = GL_UNSIGNED_BYTE; 1087 rb->GetPointer = get_pointer_ubyte; 1088 rb->GetRow = get_row_ubyte; 1089 rb->GetValues = get_values_ubyte; 1090 rb->PutRow = put_row_ubyte; 1091 rb->PutRowRGB = NULL; 1092 rb->PutMonoRow = put_mono_row_ubyte; 1093 rb->PutValues = put_values_ubyte; 1094 rb->PutMonoValues = put_mono_values_ubyte; 1095 pixelSize = sizeof(GLubyte); 1096 break; 1097 default: 1098 _mesa_problem(ctx, "Bad internalFormat in _mesa_soft_renderbuffer_storage"); 1099 return GL_FALSE; 1100 } 1101 1102 ASSERT(rb->DataType); 1103 ASSERT(rb->GetPointer); 1104 ASSERT(rb->GetRow); 1105 ASSERT(rb->GetValues); 1106 ASSERT(rb->PutRow); 1107 ASSERT(rb->PutMonoRow); 1108 ASSERT(rb->PutValues); 1109 ASSERT(rb->PutMonoValues); 1110 1111 /* free old buffer storage */ 1112 if (rb->Data) { 1113 _mesa_free(rb->Data); 1114 rb->Data = NULL; 1115 } 1116 1117 if (width > 0 && height > 0) { 1118 /* allocate new buffer storage */ 1119 rb->Data = malloc(width * height * pixelSize); 1120 1121 if (rb->Data == NULL) { 1122 rb->Width = 0; 1123 rb->Height = 0; 1124 _mesa_error(ctx, GL_OUT_OF_MEMORY, 1125 "software renderbuffer allocation (%d x %d x %d)", 1126 width, height, pixelSize); 1127 return GL_FALSE; 1128 } 1129 } 1130 1131 rb->Width = width; 1132 rb->Height = height; 1133 rb->_BaseFormat = _mesa_base_fbo_format(ctx, rb->InternalFormat); 1134 1135 return GL_TRUE; 1136} 1137 1138 1139 1140/**********************************************************************/ 1141/**********************************************************************/ 1142/**********************************************************************/ 1143 1144 1145/** 1146 * Here we utilize the gl_renderbuffer->Wrapper field to put an alpha 1147 * buffer wrapper around an existing RGB renderbuffer (hw or sw). 1148 * 1149 * When PutRow is called (for example), we store the alpha values in 1150 * this buffer, then pass on the PutRow call to the wrapped RGB 1151 * buffer. 1152 */ 1153 1154 1155static GLboolean 1156alloc_storage_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, 1157 GLenum internalFormat, GLuint width, GLuint height) 1158{ 1159 ASSERT(arb != arb->Wrapped); 1160 ASSERT(arb->Format == MESA_FORMAT_A8); 1161 1162 /* first, pass the call to the wrapped RGB buffer */ 1163 if (!arb->Wrapped->AllocStorage(ctx, arb->Wrapped, internalFormat, 1164 width, height)) { 1165 return GL_FALSE; 1166 } 1167 1168 /* next, resize my alpha buffer */ 1169 if (arb->Data) { 1170 _mesa_free(arb->Data); 1171 } 1172 1173 arb->Data = _mesa_malloc(width * height * sizeof(GLubyte)); 1174 if (arb->Data == NULL) { 1175 arb->Width = 0; 1176 arb->Height = 0; 1177 _mesa_error(ctx, GL_OUT_OF_MEMORY, "software alpha buffer allocation"); 1178 return GL_FALSE; 1179 } 1180 1181 arb->Width = width; 1182 arb->Height = height; 1183 1184 return GL_TRUE; 1185} 1186 1187 1188/** 1189 * Delete an alpha_renderbuffer object, as well as the wrapped RGB buffer. 1190 */ 1191static void 1192delete_renderbuffer_alpha8(struct gl_renderbuffer *arb) 1193{ 1194 if (arb->Data) { 1195 _mesa_free(arb->Data); 1196 } 1197 ASSERT(arb->Wrapped); 1198 ASSERT(arb != arb->Wrapped); 1199 arb->Wrapped->Delete(arb->Wrapped); 1200 arb->Wrapped = NULL; 1201 _mesa_free(arb); 1202} 1203 1204 1205static void * 1206get_pointer_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, 1207 GLint x, GLint y) 1208{ 1209 return NULL; /* don't allow direct access! */ 1210} 1211 1212 1213static void 1214get_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count, 1215 GLint x, GLint y, void *values) 1216{ 1217 /* NOTE: 'values' is RGBA format! */ 1218 const GLubyte *src = (const GLubyte *) arb->Data + y * arb->Width + x; 1219 GLubyte *dst = (GLubyte *) values; 1220 GLuint i; 1221 ASSERT(arb != arb->Wrapped); 1222 ASSERT(arb->DataType == GL_UNSIGNED_BYTE); 1223 /* first, pass the call to the wrapped RGB buffer */ 1224 arb->Wrapped->GetRow(ctx, arb->Wrapped, count, x, y, values); 1225 /* second, fill in alpha values from this buffer! */ 1226 for (i = 0; i < count; i++) { 1227 dst[i * 4 + 3] = src[i]; 1228 } 1229} 1230 1231 1232static void 1233get_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count, 1234 const GLint x[], const GLint y[], void *values) 1235{ 1236 GLubyte *dst = (GLubyte *) values; 1237 GLuint i; 1238 ASSERT(arb != arb->Wrapped); 1239 ASSERT(arb->DataType == GL_UNSIGNED_BYTE); 1240 /* first, pass the call to the wrapped RGB buffer */ 1241 arb->Wrapped->GetValues(ctx, arb->Wrapped, count, x, y, values); 1242 /* second, fill in alpha values from this buffer! */ 1243 for (i = 0; i < count; i++) { 1244 const GLubyte *src = (GLubyte *) arb->Data + y[i] * arb->Width + x[i]; 1245 dst[i * 4 + 3] = *src; 1246 } 1247} 1248 1249 1250static void 1251put_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count, 1252 GLint x, GLint y, const void *values, const GLubyte *mask) 1253{ 1254 const GLubyte *src = (const GLubyte *) values; 1255 GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x; 1256 GLuint i; 1257 ASSERT(arb != arb->Wrapped); 1258 ASSERT(arb->DataType == GL_UNSIGNED_BYTE); 1259 /* first, pass the call to the wrapped RGB buffer */ 1260 arb->Wrapped->PutRow(ctx, arb->Wrapped, count, x, y, values, mask); 1261 /* second, store alpha in our buffer */ 1262 for (i = 0; i < count; i++) { 1263 if (!mask || mask[i]) { 1264 dst[i] = src[i * 4 + 3]; 1265 } 1266 } 1267} 1268 1269 1270static void 1271put_row_rgb_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count, 1272 GLint x, GLint y, const void *values, const GLubyte *mask) 1273{ 1274 const GLubyte *src = (const GLubyte *) values; 1275 GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x; 1276 GLuint i; 1277 ASSERT(arb != arb->Wrapped); 1278 ASSERT(arb->DataType == GL_UNSIGNED_BYTE); 1279 /* first, pass the call to the wrapped RGB buffer */ 1280 arb->Wrapped->PutRowRGB(ctx, arb->Wrapped, count, x, y, values, mask); 1281 /* second, store alpha in our buffer */ 1282 for (i = 0; i < count; i++) { 1283 if (!mask || mask[i]) { 1284 dst[i] = src[i * 4 + 3]; 1285 } 1286 } 1287} 1288 1289 1290static void 1291put_mono_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count, 1292 GLint x, GLint y, const void *value, const GLubyte *mask) 1293{ 1294 const GLubyte val = ((const GLubyte *) value)[3]; 1295 GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x; 1296 ASSERT(arb != arb->Wrapped); 1297 ASSERT(arb->DataType == GL_UNSIGNED_BYTE); 1298 /* first, pass the call to the wrapped RGB buffer */ 1299 arb->Wrapped->PutMonoRow(ctx, arb->Wrapped, count, x, y, value, mask); 1300 /* second, store alpha in our buffer */ 1301 if (mask) { 1302 GLuint i; 1303 for (i = 0; i < count; i++) { 1304 if (mask[i]) { 1305 dst[i] = val; 1306 } 1307 } 1308 } 1309 else { 1310 _mesa_memset(dst, val, count); 1311 } 1312} 1313 1314 1315static void 1316put_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count, 1317 const GLint x[], const GLint y[], 1318 const void *values, const GLubyte *mask) 1319{ 1320 const GLubyte *src = (const GLubyte *) values; 1321 GLuint i; 1322 ASSERT(arb != arb->Wrapped); 1323 ASSERT(arb->DataType == GL_UNSIGNED_BYTE); 1324 /* first, pass the call to the wrapped RGB buffer */ 1325 arb->Wrapped->PutValues(ctx, arb->Wrapped, count, x, y, values, mask); 1326 /* second, store alpha in our buffer */ 1327 for (i = 0; i < count; i++) { 1328 if (!mask || mask[i]) { 1329 GLubyte *dst = (GLubyte *) arb->Data + y[i] * arb->Width + x[i]; 1330 *dst = src[i * 4 + 3]; 1331 } 1332 } 1333} 1334 1335 1336static void 1337put_mono_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, 1338 GLuint count, const GLint x[], const GLint y[], 1339 const void *value, const GLubyte *mask) 1340{ 1341 const GLubyte val = ((const GLubyte *) value)[3]; 1342 GLuint i; 1343 ASSERT(arb != arb->Wrapped); 1344 ASSERT(arb->DataType == GL_UNSIGNED_BYTE); 1345 /* first, pass the call to the wrapped RGB buffer */ 1346 arb->Wrapped->PutValues(ctx, arb->Wrapped, count, x, y, value, mask); 1347 /* second, store alpha in our buffer */ 1348 for (i = 0; i < count; i++) { 1349 if (!mask || mask[i]) { 1350 GLubyte *dst = (GLubyte *) arb->Data + y[i] * arb->Width + x[i]; 1351 *dst = val; 1352 } 1353 } 1354} 1355 1356 1357static void 1358copy_buffer_alpha8(struct gl_renderbuffer* dst, struct gl_renderbuffer* src) 1359{ 1360 ASSERT(dst->Format == MESA_FORMAT_A8); 1361 ASSERT(src->Format == MESA_FORMAT_A8); 1362 ASSERT(dst->Width == src->Width); 1363 ASSERT(dst->Height == src->Height); 1364 1365 _mesa_memcpy(dst->Data, src->Data, dst->Width * dst->Height * sizeof(GLubyte)); 1366} 1367 1368 1369/**********************************************************************/ 1370/**********************************************************************/ 1371/**********************************************************************/ 1372 1373 1374/** 1375 * Default GetPointer routine. Always return NULL to indicate that 1376 * direct buffer access is not supported. 1377 */ 1378static void * 1379nop_get_pointer(GLcontext *ctx, struct gl_renderbuffer *rb, GLint x, GLint y) 1380{ 1381 return NULL; 1382} 1383 1384 1385/** 1386 * Initialize the fields of a gl_renderbuffer to default values. 1387 */ 1388void 1389_mesa_init_renderbuffer(struct gl_renderbuffer *rb, GLuint name) 1390{ 1391 _glthread_INIT_MUTEX(rb->Mutex); 1392 1393 rb->Magic = RB_MAGIC; 1394 rb->ClassID = 0; 1395 rb->Name = name; 1396 rb->RefCount = 0; 1397 rb->Delete = _mesa_delete_renderbuffer; 1398 1399 /* The rest of these should be set later by the caller of this function or 1400 * the AllocStorage method: 1401 */ 1402 rb->AllocStorage = NULL; 1403 1404 rb->Width = 0; 1405 rb->Height = 0; 1406 rb->InternalFormat = GL_NONE; 1407 rb->Format = MESA_FORMAT_NONE; 1408 1409 rb->DataType = GL_NONE; 1410 rb->Data = NULL; 1411 1412 /* Point back to ourself so that we don't have to check for Wrapped==NULL 1413 * all over the drivers. 1414 */ 1415 rb->Wrapped = rb; 1416 1417 rb->GetPointer = nop_get_pointer; 1418 rb->GetRow = NULL; 1419 rb->GetValues = NULL; 1420 rb->PutRow = NULL; 1421 rb->PutRowRGB = NULL; 1422 rb->PutMonoRow = NULL; 1423 rb->PutValues = NULL; 1424 rb->PutMonoValues = NULL; 1425} 1426 1427 1428/** 1429 * Allocate a new gl_renderbuffer object. This can be used for user-created 1430 * renderbuffers or window-system renderbuffers. 1431 */ 1432struct gl_renderbuffer * 1433_mesa_new_renderbuffer(GLcontext *ctx, GLuint name) 1434{ 1435 struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer); 1436 if (rb) { 1437 _mesa_init_renderbuffer(rb, name); 1438 } 1439 return rb; 1440} 1441 1442 1443/** 1444 * Delete a gl_framebuffer. 1445 * This is the default function for renderbuffer->Delete(). 1446 */ 1447void 1448_mesa_delete_renderbuffer(struct gl_renderbuffer *rb) 1449{ 1450 if (rb->Data) { 1451 _mesa_free(rb->Data); 1452 } 1453 _mesa_free(rb); 1454} 1455 1456 1457/** 1458 * Allocate a software-based renderbuffer. This is called via the 1459 * ctx->Driver.NewRenderbuffer() function when the user creates a new 1460 * renderbuffer. 1461 * This would not be used for hardware-based renderbuffers. 1462 */ 1463struct gl_renderbuffer * 1464_mesa_new_soft_renderbuffer(GLcontext *ctx, GLuint name) 1465{ 1466 struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, name); 1467 if (rb) { 1468 rb->AllocStorage = _mesa_soft_renderbuffer_storage; 1469 /* Normally, one would setup the PutRow, GetRow, etc functions here. 1470 * But we're doing that in the _mesa_soft_renderbuffer_storage() function 1471 * instead. 1472 */ 1473 } 1474 return rb; 1475} 1476 1477 1478/** 1479 * Add software-based color renderbuffers to the given framebuffer. 1480 * This is a helper routine for device drivers when creating a 1481 * window system framebuffer (not a user-created render/framebuffer). 1482 * Once this function is called, you can basically forget about this 1483 * renderbuffer; core Mesa will handle all the buffer management and 1484 * rendering! 1485 */ 1486GLboolean 1487_mesa_add_color_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb, 1488 GLuint rgbBits, GLuint alphaBits, 1489 GLboolean frontLeft, GLboolean backLeft, 1490 GLboolean frontRight, GLboolean backRight) 1491{ 1492 GLuint b; 1493 1494 if (rgbBits > 16 || alphaBits > 16) { 1495 _mesa_problem(ctx, 1496 "Unsupported bit depth in _mesa_add_color_renderbuffers"); 1497 return GL_FALSE; 1498 } 1499 1500 assert(MAX_COLOR_ATTACHMENTS >= 4); 1501 1502 for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) { 1503 struct gl_renderbuffer *rb; 1504 1505 if (b == BUFFER_FRONT_LEFT && !frontLeft) 1506 continue; 1507 else if (b == BUFFER_BACK_LEFT && !backLeft) 1508 continue; 1509 else if (b == BUFFER_FRONT_RIGHT && !frontRight) 1510 continue; 1511 else if (b == BUFFER_BACK_RIGHT && !backRight) 1512 continue; 1513 1514 assert(fb->Attachment[b].Renderbuffer == NULL); 1515 1516 rb = _mesa_new_renderbuffer(ctx, 0); 1517 if (!rb) { 1518 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer"); 1519 return GL_FALSE; 1520 } 1521 1522 if (rgbBits <= 8) { 1523 if (alphaBits) 1524 rb->Format = MESA_FORMAT_RGBA8888; 1525 else 1526 rb->Format = MESA_FORMAT_RGB888; 1527 } 1528 else { 1529 assert(rgbBits <= 16); 1530 rb->Format = MESA_FORMAT_NONE; /*XXX RGBA16;*/ 1531 } 1532 rb->InternalFormat = GL_RGBA; 1533 1534 rb->AllocStorage = _mesa_soft_renderbuffer_storage; 1535 _mesa_add_renderbuffer(fb, b, rb); 1536 } 1537 1538 return GL_TRUE; 1539} 1540 1541 1542/** 1543 * Add software-based color index renderbuffers to the given framebuffer. 1544 * This is a helper routine for device drivers when creating a 1545 * window system framebuffer (not a user-created render/framebuffer). 1546 * Once this function is called, you can basically forget about this 1547 * renderbuffer; core Mesa will handle all the buffer management and 1548 * rendering! 1549 */ 1550GLboolean 1551_mesa_add_color_index_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb, 1552 GLuint indexBits, 1553 GLboolean frontLeft, GLboolean backLeft, 1554 GLboolean frontRight, GLboolean backRight) 1555{ 1556 GLuint b; 1557 1558 if (indexBits > 8) { 1559 _mesa_problem(ctx, 1560 "Unsupported bit depth in _mesa_add_color_index_renderbuffers"); 1561 return GL_FALSE; 1562 } 1563 1564 assert(MAX_COLOR_ATTACHMENTS >= 4); 1565 1566 for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) { 1567 struct gl_renderbuffer *rb; 1568 1569 if (b == BUFFER_FRONT_LEFT && !frontLeft) 1570 continue; 1571 else if (b == BUFFER_BACK_LEFT && !backLeft) 1572 continue; 1573 else if (b == BUFFER_FRONT_RIGHT && !frontRight) 1574 continue; 1575 else if (b == BUFFER_BACK_RIGHT && !backRight) 1576 continue; 1577 1578 assert(fb->Attachment[b].Renderbuffer == NULL); 1579 1580 rb = _mesa_new_renderbuffer(ctx, 0); 1581 if (!rb) { 1582 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer"); 1583 return GL_FALSE; 1584 } 1585 1586 assert(indexBits <= 8); 1587 rb->Format = MESA_FORMAT_CI8; 1588 rb->InternalFormat = GL_COLOR_INDEX; 1589 1590 rb->AllocStorage = _mesa_soft_renderbuffer_storage; 1591 _mesa_add_renderbuffer(fb, b, rb); 1592 } 1593 1594 return GL_TRUE; 1595} 1596 1597 1598/** 1599 * Add software-based alpha renderbuffers to the given framebuffer. 1600 * This is a helper routine for device drivers when creating a 1601 * window system framebuffer (not a user-created render/framebuffer). 1602 * Once this function is called, you can basically forget about this 1603 * renderbuffer; core Mesa will handle all the buffer management and 1604 * rendering! 1605 */ 1606GLboolean 1607_mesa_add_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb, 1608 GLuint alphaBits, 1609 GLboolean frontLeft, GLboolean backLeft, 1610 GLboolean frontRight, GLboolean backRight) 1611{ 1612 GLuint b; 1613 1614 /* for window system framebuffers only! */ 1615 assert(fb->Name == 0); 1616 1617 if (alphaBits > 8) { 1618 _mesa_problem(ctx, 1619 "Unsupported bit depth in _mesa_add_alpha_renderbuffers"); 1620 return GL_FALSE; 1621 } 1622 1623 assert(MAX_COLOR_ATTACHMENTS >= 4); 1624 1625 /* Wrap each of the RGB color buffers with an alpha renderbuffer. 1626 */ 1627 for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) { 1628 struct gl_renderbuffer *arb; 1629 1630 if (b == BUFFER_FRONT_LEFT && !frontLeft) 1631 continue; 1632 else if (b == BUFFER_BACK_LEFT && !backLeft) 1633 continue; 1634 else if (b == BUFFER_FRONT_RIGHT && !frontRight) 1635 continue; 1636 else if (b == BUFFER_BACK_RIGHT && !backRight) 1637 continue; 1638 1639 /* the RGB buffer to wrap must already exist!! */ 1640 assert(fb->Attachment[b].Renderbuffer); 1641 1642 /* only GLubyte supported for now */ 1643 assert(fb->Attachment[b].Renderbuffer->DataType == GL_UNSIGNED_BYTE); 1644 1645 /* allocate alpha renderbuffer */ 1646 arb = _mesa_new_renderbuffer(ctx, 0); 1647 if (!arb) { 1648 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating alpha buffer"); 1649 return GL_FALSE; 1650 } 1651 1652 /* wrap the alpha renderbuffer around the RGB renderbuffer */ 1653 arb->Wrapped = fb->Attachment[b].Renderbuffer; 1654 1655 /* Set up my alphabuffer fields and plug in my functions. 1656 * The functions will put/get the alpha values from/to RGBA arrays 1657 * and then call the wrapped buffer's functions to handle the RGB 1658 * values. 1659 */ 1660 arb->InternalFormat = arb->Wrapped->InternalFormat; 1661 arb->Format = MESA_FORMAT_A8; 1662 arb->DataType = arb->Wrapped->DataType; 1663 arb->AllocStorage = alloc_storage_alpha8; 1664 arb->Delete = delete_renderbuffer_alpha8; 1665 arb->GetPointer = get_pointer_alpha8; 1666 arb->GetRow = get_row_alpha8; 1667 arb->GetValues = get_values_alpha8; 1668 arb->PutRow = put_row_alpha8; 1669 arb->PutRowRGB = put_row_rgb_alpha8; 1670 arb->PutMonoRow = put_mono_row_alpha8; 1671 arb->PutValues = put_values_alpha8; 1672 arb->PutMonoValues = put_mono_values_alpha8; 1673 1674 /* clear the pointer to avoid assertion/sanity check failure later */ 1675 fb->Attachment[b].Renderbuffer = NULL; 1676 1677 /* plug the alpha renderbuffer into the colorbuffer attachment */ 1678 _mesa_add_renderbuffer(fb, b, arb); 1679 } 1680 1681 return GL_TRUE; 1682} 1683 1684 1685/** 1686 * For framebuffers that use a software alpha channel wrapper 1687 * created by _mesa_add_alpha_renderbuffer or _mesa_add_soft_renderbuffers, 1688 * copy the back buffer alpha channel into the front buffer alpha channel. 1689 */ 1690void 1691_mesa_copy_soft_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb) 1692{ 1693 if (fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer && 1694 fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer) 1695 copy_buffer_alpha8(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer, 1696 fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer); 1697 1698 1699 if (fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer && 1700 fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer) 1701 copy_buffer_alpha8(fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer, 1702 fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer); 1703} 1704 1705 1706/** 1707 * Add a software-based depth renderbuffer to the given framebuffer. 1708 * This is a helper routine for device drivers when creating a 1709 * window system framebuffer (not a user-created render/framebuffer). 1710 * Once this function is called, you can basically forget about this 1711 * renderbuffer; core Mesa will handle all the buffer management and 1712 * rendering! 1713 */ 1714GLboolean 1715_mesa_add_depth_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb, 1716 GLuint depthBits) 1717{ 1718 struct gl_renderbuffer *rb; 1719 1720 if (depthBits > 32) { 1721 _mesa_problem(ctx, 1722 "Unsupported depthBits in _mesa_add_depth_renderbuffer"); 1723 return GL_FALSE; 1724 } 1725 1726 assert(fb->Attachment[BUFFER_DEPTH].Renderbuffer == NULL); 1727 1728 rb = _mesa_new_renderbuffer(ctx, 0); 1729 if (!rb) { 1730 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating depth buffer"); 1731 return GL_FALSE; 1732 } 1733 1734 if (depthBits <= 16) { 1735 rb->Format = MESA_FORMAT_Z16; 1736 rb->InternalFormat = GL_DEPTH_COMPONENT16; 1737 } 1738 else { 1739 rb->Format = MESA_FORMAT_Z32; 1740 rb->InternalFormat = GL_DEPTH_COMPONENT32; 1741 } 1742 1743 rb->AllocStorage = _mesa_soft_renderbuffer_storage; 1744 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb); 1745 1746 return GL_TRUE; 1747} 1748 1749 1750/** 1751 * Add a software-based stencil renderbuffer to the given framebuffer. 1752 * This is a helper routine for device drivers when creating a 1753 * window system framebuffer (not a user-created render/framebuffer). 1754 * Once this function is called, you can basically forget about this 1755 * renderbuffer; core Mesa will handle all the buffer management and 1756 * rendering! 1757 */ 1758GLboolean 1759_mesa_add_stencil_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb, 1760 GLuint stencilBits) 1761{ 1762 struct gl_renderbuffer *rb; 1763 1764 if (stencilBits > 16) { 1765 _mesa_problem(ctx, 1766 "Unsupported stencilBits in _mesa_add_stencil_renderbuffer"); 1767 return GL_FALSE; 1768 } 1769 1770 assert(fb->Attachment[BUFFER_STENCIL].Renderbuffer == NULL); 1771 1772 rb = _mesa_new_renderbuffer(ctx, 0); 1773 if (!rb) { 1774 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating stencil buffer"); 1775 return GL_FALSE; 1776 } 1777 1778 assert(stencilBits <= 8); 1779 rb->Format = MESA_FORMAT_S8; 1780 rb->InternalFormat = GL_STENCIL_INDEX8; 1781 1782 rb->AllocStorage = _mesa_soft_renderbuffer_storage; 1783 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, rb); 1784 1785 return GL_TRUE; 1786} 1787 1788 1789/** 1790 * Add a software-based accumulation renderbuffer to the given framebuffer. 1791 * This is a helper routine for device drivers when creating a 1792 * window system framebuffer (not a user-created render/framebuffer). 1793 * Once this function is called, you can basically forget about this 1794 * renderbuffer; core Mesa will handle all the buffer management and 1795 * rendering! 1796 */ 1797GLboolean 1798_mesa_add_accum_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb, 1799 GLuint redBits, GLuint greenBits, 1800 GLuint blueBits, GLuint alphaBits) 1801{ 1802 struct gl_renderbuffer *rb; 1803 1804 if (redBits > 16 || greenBits > 16 || blueBits > 16 || alphaBits > 16) { 1805 _mesa_problem(ctx, 1806 "Unsupported accumBits in _mesa_add_accum_renderbuffer"); 1807 return GL_FALSE; 1808 } 1809 1810 assert(fb->Attachment[BUFFER_ACCUM].Renderbuffer == NULL); 1811 1812 rb = _mesa_new_renderbuffer(ctx, 0); 1813 if (!rb) { 1814 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer"); 1815 return GL_FALSE; 1816 } 1817 1818 rb->Format = MESA_FORMAT_SIGNED_RGBA_16; 1819 rb->InternalFormat = GL_RGBA16; 1820 rb->AllocStorage = _mesa_soft_renderbuffer_storage; 1821 _mesa_add_renderbuffer(fb, BUFFER_ACCUM, rb); 1822 1823 return GL_TRUE; 1824} 1825 1826 1827 1828/** 1829 * Add a software-based accumulation renderbuffer to the given framebuffer. 1830 * This is a helper routine for device drivers when creating a 1831 * window system framebuffer (not a user-created render/framebuffer). 1832 * Once this function is called, you can basically forget about this 1833 * renderbuffer; core Mesa will handle all the buffer management and 1834 * rendering! 1835 * 1836 * NOTE: color-index aux buffers not supported. 1837 */ 1838GLboolean 1839_mesa_add_aux_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb, 1840 GLuint colorBits, GLuint numBuffers) 1841{ 1842 GLuint i; 1843 1844 if (colorBits > 16) { 1845 _mesa_problem(ctx, 1846 "Unsupported accumBits in _mesa_add_aux_renderbuffers"); 1847 return GL_FALSE; 1848 } 1849 1850 assert(numBuffers < MAX_AUX_BUFFERS); 1851 1852 for (i = 0; i < numBuffers; i++) { 1853 struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, 0); 1854 1855 assert(fb->Attachment[BUFFER_AUX0 + i].Renderbuffer == NULL); 1856 1857 if (!rb) { 1858 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer"); 1859 return GL_FALSE; 1860 } 1861 1862 assert (colorBits <= 8); 1863 rb->Format = MESA_FORMAT_RGBA8888; 1864 rb->InternalFormat = GL_RGBA; 1865 1866 rb->AllocStorage = _mesa_soft_renderbuffer_storage; 1867 _mesa_add_renderbuffer(fb, BUFFER_AUX0 + i, rb); 1868 } 1869 return GL_TRUE; 1870} 1871 1872 1873/** 1874 * Create/attach software-based renderbuffers to the given framebuffer. 1875 * This is a helper routine for device drivers. Drivers can just as well 1876 * call the individual _mesa_add_*_renderbuffer() routines directly. 1877 */ 1878void 1879_mesa_add_soft_renderbuffers(struct gl_framebuffer *fb, 1880 GLboolean color, 1881 GLboolean depth, 1882 GLboolean stencil, 1883 GLboolean accum, 1884 GLboolean alpha, 1885 GLboolean aux) 1886{ 1887 GLboolean frontLeft = GL_TRUE; 1888 GLboolean backLeft = fb->Visual.doubleBufferMode; 1889 GLboolean frontRight = fb->Visual.stereoMode; 1890 GLboolean backRight = fb->Visual.stereoMode && fb->Visual.doubleBufferMode; 1891 1892 if (color) { 1893 if (fb->Visual.rgbMode) { 1894 assert(fb->Visual.redBits == fb->Visual.greenBits); 1895 assert(fb->Visual.redBits == fb->Visual.blueBits); 1896 _mesa_add_color_renderbuffers(NULL, fb, 1897 fb->Visual.redBits, 1898 fb->Visual.alphaBits, 1899 frontLeft, backLeft, 1900 frontRight, backRight); 1901 } 1902 else { 1903 _mesa_add_color_index_renderbuffers(NULL, fb, 1904 fb->Visual.indexBits, 1905 frontLeft, backLeft, 1906 frontRight, backRight); 1907 } 1908 } 1909 1910 if (depth) { 1911 assert(fb->Visual.depthBits > 0); 1912 _mesa_add_depth_renderbuffer(NULL, fb, fb->Visual.depthBits); 1913 } 1914 1915 if (stencil) { 1916 assert(fb->Visual.stencilBits > 0); 1917 _mesa_add_stencil_renderbuffer(NULL, fb, fb->Visual.stencilBits); 1918 } 1919 1920 if (accum) { 1921 assert(fb->Visual.rgbMode); 1922 assert(fb->Visual.accumRedBits > 0); 1923 assert(fb->Visual.accumGreenBits > 0); 1924 assert(fb->Visual.accumBlueBits > 0); 1925 _mesa_add_accum_renderbuffer(NULL, fb, 1926 fb->Visual.accumRedBits, 1927 fb->Visual.accumGreenBits, 1928 fb->Visual.accumBlueBits, 1929 fb->Visual.accumAlphaBits); 1930 } 1931 1932 if (aux) { 1933 assert(fb->Visual.rgbMode); 1934 assert(fb->Visual.numAuxBuffers > 0); 1935 _mesa_add_aux_renderbuffers(NULL, fb, fb->Visual.redBits, 1936 fb->Visual.numAuxBuffers); 1937 } 1938 1939 if (alpha) { 1940 assert(fb->Visual.rgbMode); 1941 assert(fb->Visual.alphaBits > 0); 1942 _mesa_add_alpha_renderbuffers(NULL, fb, fb->Visual.alphaBits, 1943 frontLeft, backLeft, 1944 frontRight, backRight); 1945 } 1946 1947#if 0 1948 if (multisample) { 1949 /* maybe someday */ 1950 } 1951#endif 1952} 1953 1954 1955/** 1956 * Attach a renderbuffer to a framebuffer. 1957 */ 1958void 1959_mesa_add_renderbuffer(struct gl_framebuffer *fb, 1960 GLuint bufferName, struct gl_renderbuffer *rb) 1961{ 1962 GLenum baseFormat; 1963 1964 assert(fb); 1965 assert(rb); 1966 assert(bufferName < BUFFER_COUNT); 1967 1968 /* There should be no previous renderbuffer on this attachment point, 1969 * with the exception of depth/stencil since the same renderbuffer may 1970 * be used for both. 1971 */ 1972 assert(bufferName == BUFFER_DEPTH || 1973 bufferName == BUFFER_STENCIL || 1974 fb->Attachment[bufferName].Renderbuffer == NULL); 1975 1976 /* winsys vs. user-created buffer cross check */ 1977 if (fb->Name) { 1978 assert(rb->Name); 1979 } 1980 else { 1981 assert(!rb->Name); 1982 } 1983 1984 /* If Mesa's compiled with deep color channels (16 or 32 bits / channel) 1985 * and the device driver is expecting 8-bit values (GLubyte), we can 1986 * use a "renderbuffer adaptor/wrapper" to do the necessary conversions. 1987 */ 1988 baseFormat = _mesa_get_format_base_format(rb->Format); 1989 if (baseFormat == GL_RGBA) { 1990 if (CHAN_BITS == 16 && rb->DataType == GL_UNSIGNED_BYTE) { 1991 GET_CURRENT_CONTEXT(ctx); 1992 rb = _mesa_new_renderbuffer_16wrap8(ctx, rb); 1993 } 1994 else if (CHAN_BITS == 32 && rb->DataType == GL_UNSIGNED_BYTE) { 1995 GET_CURRENT_CONTEXT(ctx); 1996 rb = _mesa_new_renderbuffer_32wrap8(ctx, rb); 1997 } 1998 else if (CHAN_BITS == 32 && rb->DataType == GL_UNSIGNED_SHORT) { 1999 GET_CURRENT_CONTEXT(ctx); 2000 rb = _mesa_new_renderbuffer_32wrap16(ctx, rb); 2001 } 2002 } 2003 2004 fb->Attachment[bufferName].Type = GL_RENDERBUFFER_EXT; 2005 fb->Attachment[bufferName].Complete = GL_TRUE; 2006 _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer, rb); 2007} 2008 2009 2010/** 2011 * Remove the named renderbuffer from the given framebuffer. 2012 */ 2013void 2014_mesa_remove_renderbuffer(struct gl_framebuffer *fb, GLuint bufferName) 2015{ 2016 struct gl_renderbuffer *rb; 2017 2018 assert(bufferName < BUFFER_COUNT); 2019 2020 rb = fb->Attachment[bufferName].Renderbuffer; 2021 if (!rb) 2022 return; 2023 2024 _mesa_reference_renderbuffer(&rb, NULL); 2025 2026 fb->Attachment[bufferName].Renderbuffer = NULL; 2027} 2028 2029 2030/** 2031 * Set *ptr to point to rb. If *ptr points to another renderbuffer, 2032 * dereference that buffer first. The new renderbuffer's refcount will 2033 * be incremented. The old renderbuffer's refcount will be decremented. 2034 */ 2035void 2036_mesa_reference_renderbuffer(struct gl_renderbuffer **ptr, 2037 struct gl_renderbuffer *rb) 2038{ 2039 assert(ptr); 2040 if (*ptr == rb) { 2041 /* no change */ 2042 return; 2043 } 2044 2045 if (*ptr) { 2046 /* Unreference the old renderbuffer */ 2047 GLboolean deleteFlag = GL_FALSE; 2048 struct gl_renderbuffer *oldRb = *ptr; 2049 2050 assert(oldRb->Magic == RB_MAGIC); 2051 _glthread_LOCK_MUTEX(oldRb->Mutex); 2052 assert(oldRb->Magic == RB_MAGIC); 2053 ASSERT(oldRb->RefCount > 0); 2054 oldRb->RefCount--; 2055 /*printf("RB DECR %p (%d) to %d\n", (void*) oldRb, oldRb->Name, oldRb->RefCount);*/ 2056 deleteFlag = (oldRb->RefCount == 0); 2057 _glthread_UNLOCK_MUTEX(oldRb->Mutex); 2058 2059 if (deleteFlag) { 2060 oldRb->Magic = 0; /* now invalid memory! */ 2061 oldRb->Delete(oldRb); 2062 } 2063 2064 *ptr = NULL; 2065 } 2066 assert(!*ptr); 2067 2068 if (rb) { 2069 assert(rb->Magic == RB_MAGIC); 2070 /* reference new renderbuffer */ 2071 _glthread_LOCK_MUTEX(rb->Mutex); 2072 rb->RefCount++; 2073 /*printf("RB INCR %p (%d) to %d\n", (void*) rb, rb->Name, rb->RefCount);*/ 2074 _glthread_UNLOCK_MUTEX(rb->Mutex); 2075 *ptr = rb; 2076 } 2077} 2078 2079 2080/** 2081 * Create a new combined depth/stencil renderbuffer for implementing 2082 * the GL_EXT_packed_depth_stencil extension. 2083 * \return new depth/stencil renderbuffer 2084 */ 2085struct gl_renderbuffer * 2086_mesa_new_depthstencil_renderbuffer(GLcontext *ctx, GLuint name) 2087{ 2088 struct gl_renderbuffer *dsrb; 2089 2090 dsrb = _mesa_new_renderbuffer(ctx, name); 2091 if (!dsrb) 2092 return NULL; 2093 2094 /* init fields not covered by _mesa_new_renderbuffer() */ 2095 dsrb->InternalFormat = GL_DEPTH24_STENCIL8_EXT; 2096 dsrb->Format = MESA_FORMAT_Z24_S8; 2097 dsrb->AllocStorage = _mesa_soft_renderbuffer_storage; 2098 2099 return dsrb; 2100} 2101