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