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