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