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