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