renderbuffer.c revision bad08969b50bc5b2d014043d55b30323d408e080
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 * Functions for MESA_FORMAT_R_FLOAT32. 1114 */ 1115static void 1116get_row_r_float32(struct gl_context *ctx, struct gl_renderbuffer *rb, 1117 GLuint count, GLint x, GLint y, void *values) 1118{ 1119 const GLfloat *src = rb->GetPointer(ctx, rb, x, y); 1120 GLfloat *dst = values; 1121 GLuint i; 1122 1123 for (i = 0; i < count; i++) { 1124 dst[i * 4 + RCOMP] = src[i]; 1125 dst[i * 4 + GCOMP] = 0.0; 1126 dst[i * 4 + BCOMP] = 0.0; 1127 dst[i * 4 + ACOMP] = 1.0; 1128 } 1129} 1130 1131static void 1132get_values_r_float32(struct gl_context *ctx, struct gl_renderbuffer *rb, 1133 GLuint count, const GLint x[], const GLint y[], 1134 void *values) 1135{ 1136 GLfloat *dst = values; 1137 GLuint i; 1138 1139 for (i = 0; i < count; i++) { 1140 const GLfloat *src = rb->GetPointer(ctx, rb, x[i], y[i]); 1141 dst[i * 4 + RCOMP] = src[0]; 1142 dst[i * 4 + GCOMP] = 0.0; 1143 dst[i * 4 + BCOMP] = 0.0; 1144 dst[i * 4 + ACOMP] = 1.0; 1145 } 1146} 1147 1148/********************************************************************** 1149 * Functions for MESA_FORMAT_RG_FLOAT32. 1150 */ 1151static void 1152get_row_rg_float32(struct gl_context *ctx, struct gl_renderbuffer *rb, 1153 GLuint count, GLint x, GLint y, void *values) 1154{ 1155 const GLfloat *src = rb->GetPointer(ctx, rb, x, y); 1156 GLfloat *dst = values; 1157 GLuint i; 1158 1159 for (i = 0; i < count; i++) { 1160 dst[i * 4 + RCOMP] = src[i * 2 + 0]; 1161 dst[i * 4 + GCOMP] = src[i * 2 + 1]; 1162 dst[i * 4 + BCOMP] = 0.0; 1163 dst[i * 4 + ACOMP] = 1.0; 1164 } 1165} 1166 1167static void 1168get_values_rg_float32(struct gl_context *ctx, struct gl_renderbuffer *rb, 1169 GLuint count, const GLint x[], const GLint y[], 1170 void *values) 1171{ 1172 GLfloat *dst = values; 1173 GLuint i; 1174 1175 for (i = 0; i < count; i++) { 1176 const GLfloat *src = rb->GetPointer(ctx, rb, x[i], y[i]); 1177 dst[i * 4 + RCOMP] = src[0]; 1178 dst[i * 4 + GCOMP] = src[1]; 1179 dst[i * 4 + BCOMP] = 0.0; 1180 dst[i * 4 + ACOMP] = 1.0; 1181 } 1182} 1183 1184/** 1185 * This is the default software fallback for gl_renderbuffer's span 1186 * access functions. 1187 * 1188 * The assumptions are that rb->Data will be a pointer to (0,0), that pixels 1189 * are packed in the type of rb->Format, and that subsequent rows appear 1190 * rb->RowStride pixels later. 1191 */ 1192void 1193_mesa_set_renderbuffer_accessors(struct gl_renderbuffer *rb) 1194{ 1195 rb->GetPointer = get_pointer_generic; 1196 rb->GetRow = get_row_generic; 1197 1198 switch (rb->Format) { 1199 case MESA_FORMAT_RGB888: 1200 rb->DataType = GL_UNSIGNED_BYTE; 1201 rb->GetPointer = get_pointer_ubyte3; 1202 rb->GetRow = get_row_ubyte3; 1203 rb->GetValues = get_values_ubyte3; 1204 rb->PutRow = put_row_ubyte3; 1205 rb->PutRowRGB = put_row_rgb_ubyte3; 1206 rb->PutMonoRow = put_mono_row_ubyte3; 1207 rb->PutValues = put_values_ubyte3; 1208 rb->PutMonoValues = put_mono_values_ubyte3; 1209 break; 1210 1211 case MESA_FORMAT_RGBA8888: 1212 rb->DataType = GL_UNSIGNED_BYTE; 1213 rb->GetValues = get_values_ubyte4; 1214 rb->PutRow = put_row_ubyte4; 1215 rb->PutRowRGB = put_row_rgb_ubyte4; 1216 rb->PutMonoRow = put_mono_row_ubyte4; 1217 rb->PutValues = put_values_ubyte4; 1218 rb->PutMonoValues = put_mono_values_ubyte4; 1219 break; 1220 1221 case MESA_FORMAT_R8: 1222 rb->DataType = GL_UNSIGNED_BYTE; 1223 rb->GetValues = get_values_r8; 1224 rb->GetRow = get_row_r8; 1225 rb->PutRow = put_row_generic; 1226 rb->PutRowRGB = put_row_generic; 1227 rb->PutMonoRow = put_mono_row_generic; 1228 rb->PutValues = put_values_generic; 1229 rb->PutMonoValues = put_mono_values_generic; 1230 break; 1231 1232 case MESA_FORMAT_RG88: 1233 rb->DataType = GL_UNSIGNED_BYTE; 1234 rb->GetValues = get_values_rg88; 1235 rb->GetRow = get_row_rg88; 1236 rb->PutRow = put_row_generic; 1237 rb->PutRowRGB = put_row_generic; 1238 rb->PutMonoRow = put_mono_row_generic; 1239 rb->PutValues = put_values_generic; 1240 rb->PutMonoValues = put_mono_values_generic; 1241 break; 1242 1243 case MESA_FORMAT_R16: 1244 rb->DataType = GL_UNSIGNED_SHORT; 1245 rb->GetValues = get_values_r16; 1246 rb->GetRow = get_row_r16; 1247 rb->PutRow = put_row_generic; 1248 rb->PutRowRGB = put_row_generic; 1249 rb->PutMonoRow = put_mono_row_generic; 1250 rb->PutValues = put_values_generic; 1251 rb->PutMonoValues = put_mono_values_generic; 1252 break; 1253 1254 case MESA_FORMAT_RG1616: 1255 rb->DataType = GL_UNSIGNED_SHORT; 1256 rb->GetValues = get_values_rg1616; 1257 rb->GetRow = get_row_rg1616; 1258 rb->PutRow = put_row_generic; 1259 rb->PutRowRGB = put_row_generic; 1260 rb->PutMonoRow = put_mono_row_generic; 1261 rb->PutValues = put_values_generic; 1262 rb->PutMonoValues = put_mono_values_generic; 1263 break; 1264 1265 case MESA_FORMAT_SIGNED_RGBA_16: 1266 rb->DataType = GL_SHORT; 1267 rb->GetValues = get_values_ushort4; 1268 rb->PutRow = put_row_ushort4; 1269 rb->PutRowRGB = put_row_rgb_ushort4; 1270 rb->PutMonoRow = put_mono_row_ushort4; 1271 rb->PutValues = put_values_ushort4; 1272 rb->PutMonoValues = put_mono_values_ushort4; 1273 break; 1274 1275#if 0 1276 case MESA_FORMAT_A8: 1277 rb->DataType = GL_UNSIGNED_BYTE; 1278 rb->GetValues = get_values_alpha8; 1279 rb->PutRow = put_row_alpha8; 1280 rb->PutRowRGB = NULL; 1281 rb->PutMonoRow = put_mono_row_alpha8; 1282 rb->PutValues = put_values_alpha8; 1283 rb->PutMonoValues = put_mono_values_alpha8; 1284 break; 1285#endif 1286 1287 case MESA_FORMAT_S8: 1288 rb->DataType = GL_UNSIGNED_BYTE; 1289 rb->GetValues = get_values_ubyte; 1290 rb->PutRow = put_row_ubyte; 1291 rb->PutRowRGB = NULL; 1292 rb->PutMonoRow = put_mono_row_ubyte; 1293 rb->PutValues = put_values_ubyte; 1294 rb->PutMonoValues = put_mono_values_ubyte; 1295 break; 1296 1297 case MESA_FORMAT_Z16: 1298 rb->DataType = GL_UNSIGNED_SHORT; 1299 rb->GetValues = get_values_ushort; 1300 rb->PutRow = put_row_ushort; 1301 rb->PutRowRGB = NULL; 1302 rb->PutMonoRow = put_mono_row_ushort; 1303 rb->PutValues = put_values_ushort; 1304 rb->PutMonoValues = put_mono_values_ushort; 1305 break; 1306 1307 case MESA_FORMAT_Z32: 1308 case MESA_FORMAT_X8_Z24: 1309 case MESA_FORMAT_Z24_X8: 1310 rb->DataType = GL_UNSIGNED_INT; 1311 rb->GetValues = get_values_uint; 1312 rb->PutRow = put_row_uint; 1313 rb->PutRowRGB = NULL; 1314 rb->PutMonoRow = put_mono_row_uint; 1315 rb->PutValues = put_values_uint; 1316 rb->PutMonoValues = put_mono_values_uint; 1317 break; 1318 1319 case MESA_FORMAT_Z24_S8: 1320 case MESA_FORMAT_S8_Z24: 1321 rb->DataType = GL_UNSIGNED_INT_24_8_EXT; 1322 rb->GetValues = get_values_uint; 1323 rb->PutRow = put_row_uint; 1324 rb->PutRowRGB = NULL; 1325 rb->PutMonoRow = put_mono_row_uint; 1326 rb->PutValues = put_values_uint; 1327 rb->PutMonoValues = put_mono_values_uint; 1328 break; 1329 1330 case MESA_FORMAT_RGBA_FLOAT32: 1331 rb->GetRow = get_row_generic; 1332 rb->GetValues = get_values_generic; 1333 rb->PutRow = put_row_generic; 1334 rb->PutRowRGB = NULL; 1335 rb->PutMonoRow = put_mono_row_generic; 1336 rb->PutValues = put_values_generic; 1337 rb->PutMonoValues = put_mono_values_generic; 1338 break; 1339 1340 case MESA_FORMAT_RG_FLOAT32: 1341 rb->GetRow = get_row_rg_float32; 1342 rb->GetValues = get_values_rg_float32; 1343 rb->PutRow = put_row_generic; 1344 rb->PutRowRGB = NULL; 1345 rb->PutMonoRow = put_mono_row_generic; 1346 rb->PutValues = put_values_generic; 1347 rb->PutMonoValues = put_mono_values_generic; 1348 break; 1349 1350 case MESA_FORMAT_R_FLOAT32: 1351 rb->GetRow = get_row_r_float32; 1352 rb->GetValues = get_values_r_float32; 1353 rb->PutRow = put_row_generic; 1354 rb->PutRowRGB = NULL; 1355 rb->PutMonoRow = put_mono_row_generic; 1356 rb->PutValues = put_values_generic; 1357 rb->PutMonoValues = put_mono_values_generic; 1358 break; 1359 1360 default: 1361 break; 1362 } 1363} 1364 1365/** 1366 * This is a software fallback for the gl_renderbuffer->AllocStorage 1367 * function. 1368 * Device drivers will typically override this function for the buffers 1369 * which it manages (typically color buffers, Z and stencil). 1370 * Other buffers (like software accumulation and aux buffers) which the driver 1371 * doesn't manage can be handled with this function. 1372 * 1373 * This one multi-purpose function can allocate stencil, depth, accum, color 1374 * or color-index buffers! 1375 * 1376 * This function also plugs in the appropriate GetPointer, Get/PutRow and 1377 * Get/PutValues functions. 1378 */ 1379GLboolean 1380_mesa_soft_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb, 1381 GLenum internalFormat, 1382 GLuint width, GLuint height) 1383{ 1384 switch (internalFormat) { 1385 case GL_RGB: 1386 case GL_R3_G3_B2: 1387 case GL_RGB4: 1388 case GL_RGB5: 1389 case GL_RGB8: 1390 case GL_RGB10: 1391 case GL_RGB12: 1392 case GL_RGB16: 1393 rb->Format = MESA_FORMAT_RGB888; 1394 break; 1395 case GL_RGBA: 1396 case GL_RGBA2: 1397 case GL_RGBA4: 1398 case GL_RGB5_A1: 1399 case GL_RGBA8: 1400#if 1 1401 case GL_RGB10_A2: 1402 case GL_RGBA12: 1403#endif 1404 rb->Format = MESA_FORMAT_RGBA8888; 1405 break; 1406 case GL_RGBA16: 1407 case GL_RGBA16_SNORM: 1408 /* for accum buffer */ 1409 rb->Format = MESA_FORMAT_SIGNED_RGBA_16; 1410 break; 1411#if 0 1412 case GL_ALPHA8: 1413 rb->Format = MESA_FORMAT_A8; 1414 break; 1415#endif 1416 case GL_STENCIL_INDEX: 1417 case GL_STENCIL_INDEX1_EXT: 1418 case GL_STENCIL_INDEX4_EXT: 1419 case GL_STENCIL_INDEX8_EXT: 1420 case GL_STENCIL_INDEX16_EXT: 1421 rb->Format = MESA_FORMAT_S8; 1422 break; 1423 case GL_DEPTH_COMPONENT: 1424 case GL_DEPTH_COMPONENT16: 1425 rb->Format = MESA_FORMAT_Z16; 1426 break; 1427 case GL_DEPTH_COMPONENT24: 1428 rb->Format = MESA_FORMAT_X8_Z24; 1429 break; 1430 case GL_DEPTH_COMPONENT32: 1431 rb->Format = MESA_FORMAT_Z32; 1432 break; 1433 case GL_DEPTH_STENCIL_EXT: 1434 case GL_DEPTH24_STENCIL8_EXT: 1435 rb->Format = MESA_FORMAT_Z24_S8; 1436 break; 1437 default: 1438 /* unsupported format */ 1439 return GL_FALSE; 1440 } 1441 1442 _mesa_set_renderbuffer_accessors(rb); 1443 1444 ASSERT(rb->DataType); 1445 ASSERT(rb->GetPointer); 1446 ASSERT(rb->GetRow); 1447 ASSERT(rb->GetValues); 1448 ASSERT(rb->PutRow); 1449 ASSERT(rb->PutMonoRow); 1450 ASSERT(rb->PutValues); 1451 ASSERT(rb->PutMonoValues); 1452 1453 /* free old buffer storage */ 1454 if (rb->Data) { 1455 free(rb->Data); 1456 rb->Data = NULL; 1457 } 1458 1459 rb->RowStride = width; 1460 1461 if (width > 0 && height > 0) { 1462 /* allocate new buffer storage */ 1463 rb->Data = malloc(width * height * _mesa_get_format_bytes(rb->Format)); 1464 1465 if (rb->Data == NULL) { 1466 rb->Width = 0; 1467 rb->Height = 0; 1468 rb->RowStride = 0; 1469 _mesa_error(ctx, GL_OUT_OF_MEMORY, 1470 "software renderbuffer allocation (%d x %d x %d)", 1471 width, height, _mesa_get_format_bytes(rb->Format)); 1472 return GL_FALSE; 1473 } 1474 } 1475 1476 rb->Width = width; 1477 rb->Height = height; 1478 rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat); 1479 1480 if (rb->Name == 0 && 1481 internalFormat == GL_RGBA16_SNORM && 1482 rb->_BaseFormat == 0) { 1483 /* NOTE: This is a special case just for accumulation buffers. 1484 * This is a very limited use case- there's no snorm texturing or 1485 * rendering going on. 1486 */ 1487 rb->_BaseFormat = GL_RGBA; 1488 } 1489 else { 1490 /* the internalFormat should have been error checked long ago */ 1491 ASSERT(rb->_BaseFormat); 1492 } 1493 1494 return GL_TRUE; 1495} 1496 1497 1498 1499/**********************************************************************/ 1500/**********************************************************************/ 1501/**********************************************************************/ 1502 1503 1504/** 1505 * Here we utilize the gl_renderbuffer->Wrapper field to put an alpha 1506 * buffer wrapper around an existing RGB renderbuffer (hw or sw). 1507 * 1508 * When PutRow is called (for example), we store the alpha values in 1509 * this buffer, then pass on the PutRow call to the wrapped RGB 1510 * buffer. 1511 */ 1512 1513 1514static GLboolean 1515alloc_storage_alpha8(struct gl_context *ctx, struct gl_renderbuffer *arb, 1516 GLenum internalFormat, GLuint width, GLuint height) 1517{ 1518 ASSERT(arb != arb->Wrapped); 1519 ASSERT(arb->Format == MESA_FORMAT_A8); 1520 1521 /* first, pass the call to the wrapped RGB buffer */ 1522 if (!arb->Wrapped->AllocStorage(ctx, arb->Wrapped, internalFormat, 1523 width, height)) { 1524 return GL_FALSE; 1525 } 1526 1527 /* next, resize my alpha buffer */ 1528 if (arb->Data) { 1529 free(arb->Data); 1530 } 1531 1532 arb->Data = malloc(width * height * sizeof(GLubyte)); 1533 if (arb->Data == NULL) { 1534 arb->Width = 0; 1535 arb->Height = 0; 1536 _mesa_error(ctx, GL_OUT_OF_MEMORY, "software alpha buffer allocation"); 1537 return GL_FALSE; 1538 } 1539 1540 arb->Width = width; 1541 arb->Height = height; 1542 arb->RowStride = width; 1543 1544 return GL_TRUE; 1545} 1546 1547 1548/** 1549 * Delete an alpha_renderbuffer object, as well as the wrapped RGB buffer. 1550 */ 1551static void 1552delete_renderbuffer_alpha8(struct gl_renderbuffer *arb) 1553{ 1554 if (arb->Data) { 1555 free(arb->Data); 1556 } 1557 ASSERT(arb->Wrapped); 1558 ASSERT(arb != arb->Wrapped); 1559 arb->Wrapped->Delete(arb->Wrapped); 1560 arb->Wrapped = NULL; 1561 free(arb); 1562} 1563 1564 1565static void * 1566get_pointer_alpha8(struct gl_context *ctx, struct gl_renderbuffer *arb, 1567 GLint x, GLint y) 1568{ 1569 return NULL; /* don't allow direct access! */ 1570} 1571 1572 1573static void 1574get_row_alpha8(struct gl_context *ctx, struct gl_renderbuffer *arb, GLuint count, 1575 GLint x, GLint y, void *values) 1576{ 1577 /* NOTE: 'values' is RGBA format! */ 1578 const GLubyte *src = (const GLubyte *) arb->Data + y * arb->RowStride + x; 1579 GLubyte *dst = (GLubyte *) values; 1580 GLuint i; 1581 ASSERT(arb != arb->Wrapped); 1582 ASSERT(arb->DataType == GL_UNSIGNED_BYTE); 1583 /* first, pass the call to the wrapped RGB buffer */ 1584 arb->Wrapped->GetRow(ctx, arb->Wrapped, count, x, y, values); 1585 /* second, fill in alpha values from this buffer! */ 1586 for (i = 0; i < count; i++) { 1587 dst[i * 4 + 3] = src[i]; 1588 } 1589} 1590 1591 1592static void 1593get_values_alpha8(struct gl_context *ctx, struct gl_renderbuffer *arb, GLuint count, 1594 const GLint x[], const GLint y[], void *values) 1595{ 1596 GLubyte *dst = (GLubyte *) values; 1597 GLuint i; 1598 ASSERT(arb != arb->Wrapped); 1599 ASSERT(arb->DataType == GL_UNSIGNED_BYTE); 1600 /* first, pass the call to the wrapped RGB buffer */ 1601 arb->Wrapped->GetValues(ctx, arb->Wrapped, count, x, y, values); 1602 /* second, fill in alpha values from this buffer! */ 1603 for (i = 0; i < count; i++) { 1604 const GLubyte *src = (GLubyte *) arb->Data + y[i] * arb->RowStride + x[i]; 1605 dst[i * 4 + 3] = *src; 1606 } 1607} 1608 1609 1610static void 1611put_row_alpha8(struct gl_context *ctx, struct gl_renderbuffer *arb, GLuint count, 1612 GLint x, GLint y, const void *values, const GLubyte *mask) 1613{ 1614 const GLubyte *src = (const GLubyte *) values; 1615 GLubyte *dst = (GLubyte *) arb->Data + y * arb->RowStride + x; 1616 GLuint i; 1617 ASSERT(arb != arb->Wrapped); 1618 ASSERT(arb->DataType == GL_UNSIGNED_BYTE); 1619 /* first, pass the call to the wrapped RGB buffer */ 1620 arb->Wrapped->PutRow(ctx, arb->Wrapped, count, x, y, values, mask); 1621 /* second, store alpha in our buffer */ 1622 for (i = 0; i < count; i++) { 1623 if (!mask || mask[i]) { 1624 dst[i] = src[i * 4 + 3]; 1625 } 1626 } 1627} 1628 1629 1630static void 1631put_row_rgb_alpha8(struct gl_context *ctx, struct gl_renderbuffer *arb, GLuint count, 1632 GLint x, GLint y, const void *values, const GLubyte *mask) 1633{ 1634 const GLubyte *src = (const GLubyte *) values; 1635 GLubyte *dst = (GLubyte *) arb->Data + y * arb->RowStride + x; 1636 GLuint i; 1637 ASSERT(arb != arb->Wrapped); 1638 ASSERT(arb->DataType == GL_UNSIGNED_BYTE); 1639 /* first, pass the call to the wrapped RGB buffer */ 1640 arb->Wrapped->PutRowRGB(ctx, arb->Wrapped, count, x, y, values, mask); 1641 /* second, store alpha in our buffer */ 1642 for (i = 0; i < count; i++) { 1643 if (!mask || mask[i]) { 1644 dst[i] = src[i * 4 + 3]; 1645 } 1646 } 1647} 1648 1649 1650static void 1651put_mono_row_alpha8(struct gl_context *ctx, struct gl_renderbuffer *arb, GLuint count, 1652 GLint x, GLint y, const void *value, const GLubyte *mask) 1653{ 1654 const GLubyte val = ((const GLubyte *) value)[3]; 1655 GLubyte *dst = (GLubyte *) arb->Data + y * arb->RowStride + x; 1656 ASSERT(arb != arb->Wrapped); 1657 ASSERT(arb->DataType == GL_UNSIGNED_BYTE); 1658 /* first, pass the call to the wrapped RGB buffer */ 1659 arb->Wrapped->PutMonoRow(ctx, arb->Wrapped, count, x, y, value, mask); 1660 /* second, store alpha in our buffer */ 1661 if (mask) { 1662 GLuint i; 1663 for (i = 0; i < count; i++) { 1664 if (mask[i]) { 1665 dst[i] = val; 1666 } 1667 } 1668 } 1669 else { 1670 memset(dst, val, count); 1671 } 1672} 1673 1674 1675static void 1676put_values_alpha8(struct gl_context *ctx, struct gl_renderbuffer *arb, GLuint count, 1677 const GLint x[], const GLint y[], 1678 const void *values, const GLubyte *mask) 1679{ 1680 const GLubyte *src = (const GLubyte *) values; 1681 GLuint i; 1682 ASSERT(arb != arb->Wrapped); 1683 ASSERT(arb->DataType == GL_UNSIGNED_BYTE); 1684 /* first, pass the call to the wrapped RGB buffer */ 1685 arb->Wrapped->PutValues(ctx, arb->Wrapped, count, x, y, values, mask); 1686 /* second, store alpha in our buffer */ 1687 for (i = 0; i < count; i++) { 1688 if (!mask || mask[i]) { 1689 GLubyte *dst = (GLubyte *) arb->Data + y[i] * arb->RowStride + x[i]; 1690 *dst = src[i * 4 + 3]; 1691 } 1692 } 1693} 1694 1695 1696static void 1697put_mono_values_alpha8(struct gl_context *ctx, struct gl_renderbuffer *arb, 1698 GLuint count, const GLint x[], const GLint y[], 1699 const void *value, const GLubyte *mask) 1700{ 1701 const GLubyte val = ((const GLubyte *) value)[3]; 1702 GLuint i; 1703 ASSERT(arb != arb->Wrapped); 1704 ASSERT(arb->DataType == GL_UNSIGNED_BYTE); 1705 /* first, pass the call to the wrapped RGB buffer */ 1706 arb->Wrapped->PutValues(ctx, arb->Wrapped, count, x, y, value, mask); 1707 /* second, store alpha in our buffer */ 1708 for (i = 0; i < count; i++) { 1709 if (!mask || mask[i]) { 1710 GLubyte *dst = (GLubyte *) arb->Data + y[i] * arb->RowStride + x[i]; 1711 *dst = val; 1712 } 1713 } 1714} 1715 1716 1717static void 1718copy_buffer_alpha8(struct gl_renderbuffer* dst, struct gl_renderbuffer* src) 1719{ 1720 ASSERT(dst->Format == MESA_FORMAT_A8); 1721 ASSERT(src->Format == MESA_FORMAT_A8); 1722 ASSERT(dst->Width == src->Width); 1723 ASSERT(dst->Height == src->Height); 1724 ASSERT(dst->RowStride == src->RowStride); 1725 1726 memcpy(dst->Data, src->Data, dst->RowStride * dst->Height * sizeof(GLubyte)); 1727} 1728 1729 1730/**********************************************************************/ 1731/**********************************************************************/ 1732/**********************************************************************/ 1733 1734 1735/** 1736 * Default GetPointer routine. Always return NULL to indicate that 1737 * direct buffer access is not supported. 1738 */ 1739static void * 1740nop_get_pointer(struct gl_context *ctx, struct gl_renderbuffer *rb, GLint x, GLint y) 1741{ 1742 return NULL; 1743} 1744 1745 1746/** 1747 * Initialize the fields of a gl_renderbuffer to default values. 1748 */ 1749void 1750_mesa_init_renderbuffer(struct gl_renderbuffer *rb, GLuint name) 1751{ 1752 _glthread_INIT_MUTEX(rb->Mutex); 1753 1754 rb->ClassID = 0; 1755 rb->Name = name; 1756 rb->RefCount = 0; 1757 rb->Delete = _mesa_delete_renderbuffer; 1758 1759 /* The rest of these should be set later by the caller of this function or 1760 * the AllocStorage method: 1761 */ 1762 rb->AllocStorage = NULL; 1763 1764 rb->Width = 0; 1765 rb->Height = 0; 1766 rb->InternalFormat = GL_NONE; 1767 rb->Format = MESA_FORMAT_NONE; 1768 1769 rb->DataType = GL_NONE; 1770 rb->Data = NULL; 1771 1772 /* Point back to ourself so that we don't have to check for Wrapped==NULL 1773 * all over the drivers. 1774 */ 1775 rb->Wrapped = rb; 1776 1777 rb->GetPointer = nop_get_pointer; 1778 rb->GetRow = NULL; 1779 rb->GetValues = NULL; 1780 rb->PutRow = NULL; 1781 rb->PutRowRGB = NULL; 1782 rb->PutMonoRow = NULL; 1783 rb->PutValues = NULL; 1784 rb->PutMonoValues = NULL; 1785} 1786 1787 1788/** 1789 * Allocate a new gl_renderbuffer object. This can be used for user-created 1790 * renderbuffers or window-system renderbuffers. 1791 */ 1792struct gl_renderbuffer * 1793_mesa_new_renderbuffer(struct gl_context *ctx, GLuint name) 1794{ 1795 struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer); 1796 if (rb) { 1797 _mesa_init_renderbuffer(rb, name); 1798 } 1799 return rb; 1800} 1801 1802 1803/** 1804 * Delete a gl_framebuffer. 1805 * This is the default function for renderbuffer->Delete(). 1806 */ 1807void 1808_mesa_delete_renderbuffer(struct gl_renderbuffer *rb) 1809{ 1810 if (rb->Data) { 1811 free(rb->Data); 1812 } 1813 free(rb); 1814} 1815 1816 1817/** 1818 * Allocate a software-based renderbuffer. This is called via the 1819 * ctx->Driver.NewRenderbuffer() function when the user creates a new 1820 * renderbuffer. 1821 * This would not be used for hardware-based renderbuffers. 1822 */ 1823struct gl_renderbuffer * 1824_mesa_new_soft_renderbuffer(struct gl_context *ctx, GLuint name) 1825{ 1826 struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, name); 1827 if (rb) { 1828 rb->AllocStorage = _mesa_soft_renderbuffer_storage; 1829 /* Normally, one would setup the PutRow, GetRow, etc functions here. 1830 * But we're doing that in the _mesa_soft_renderbuffer_storage() function 1831 * instead. 1832 */ 1833 } 1834 return rb; 1835} 1836 1837 1838/** 1839 * Add software-based color renderbuffers to the given framebuffer. 1840 * This is a helper routine for device drivers when creating a 1841 * window system framebuffer (not a user-created render/framebuffer). 1842 * Once this function is called, you can basically forget about this 1843 * renderbuffer; core Mesa will handle all the buffer management and 1844 * rendering! 1845 */ 1846GLboolean 1847_mesa_add_color_renderbuffers(struct gl_context *ctx, struct gl_framebuffer *fb, 1848 GLuint rgbBits, GLuint alphaBits, 1849 GLboolean frontLeft, GLboolean backLeft, 1850 GLboolean frontRight, GLboolean backRight) 1851{ 1852 gl_buffer_index b; 1853 1854 if (rgbBits > 16 || alphaBits > 16) { 1855 _mesa_problem(ctx, 1856 "Unsupported bit depth in _mesa_add_color_renderbuffers"); 1857 return GL_FALSE; 1858 } 1859 1860 assert(MAX_COLOR_ATTACHMENTS >= 4); 1861 1862 for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) { 1863 struct gl_renderbuffer *rb; 1864 1865 if (b == BUFFER_FRONT_LEFT && !frontLeft) 1866 continue; 1867 else if (b == BUFFER_BACK_LEFT && !backLeft) 1868 continue; 1869 else if (b == BUFFER_FRONT_RIGHT && !frontRight) 1870 continue; 1871 else if (b == BUFFER_BACK_RIGHT && !backRight) 1872 continue; 1873 1874 assert(fb->Attachment[b].Renderbuffer == NULL); 1875 1876 rb = _mesa_new_renderbuffer(ctx, 0); 1877 if (!rb) { 1878 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer"); 1879 return GL_FALSE; 1880 } 1881 1882 if (rgbBits <= 8) { 1883 if (alphaBits) 1884 rb->Format = MESA_FORMAT_RGBA8888; 1885 else 1886 rb->Format = MESA_FORMAT_RGB888; 1887 } 1888 else { 1889 assert(rgbBits <= 16); 1890 rb->Format = MESA_FORMAT_NONE; /*XXX RGBA16;*/ 1891 } 1892 rb->InternalFormat = GL_RGBA; 1893 1894 rb->AllocStorage = _mesa_soft_renderbuffer_storage; 1895 _mesa_add_renderbuffer(fb, b, rb); 1896 } 1897 1898 return GL_TRUE; 1899} 1900 1901 1902/** 1903 * Add software-based alpha renderbuffers to the given framebuffer. 1904 * This is a helper routine for device drivers when creating a 1905 * window system framebuffer (not a user-created render/framebuffer). 1906 * Once this function is called, you can basically forget about this 1907 * renderbuffer; core Mesa will handle all the buffer management and 1908 * rendering! 1909 */ 1910GLboolean 1911_mesa_add_alpha_renderbuffers(struct gl_context *ctx, struct gl_framebuffer *fb, 1912 GLuint alphaBits, 1913 GLboolean frontLeft, GLboolean backLeft, 1914 GLboolean frontRight, GLboolean backRight) 1915{ 1916 gl_buffer_index b; 1917 1918 /* for window system framebuffers only! */ 1919 assert(fb->Name == 0); 1920 1921 if (alphaBits > 8) { 1922 _mesa_problem(ctx, 1923 "Unsupported bit depth in _mesa_add_alpha_renderbuffers"); 1924 return GL_FALSE; 1925 } 1926 1927 assert(MAX_COLOR_ATTACHMENTS >= 4); 1928 1929 /* Wrap each of the RGB color buffers with an alpha renderbuffer. 1930 */ 1931 for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) { 1932 struct gl_renderbuffer *arb; 1933 1934 if (b == BUFFER_FRONT_LEFT && !frontLeft) 1935 continue; 1936 else if (b == BUFFER_BACK_LEFT && !backLeft) 1937 continue; 1938 else if (b == BUFFER_FRONT_RIGHT && !frontRight) 1939 continue; 1940 else if (b == BUFFER_BACK_RIGHT && !backRight) 1941 continue; 1942 1943 /* the RGB buffer to wrap must already exist!! */ 1944 assert(fb->Attachment[b].Renderbuffer); 1945 1946 /* only GLubyte supported for now */ 1947 assert(fb->Attachment[b].Renderbuffer->DataType == GL_UNSIGNED_BYTE); 1948 1949 /* allocate alpha renderbuffer */ 1950 arb = _mesa_new_renderbuffer(ctx, 0); 1951 if (!arb) { 1952 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating alpha buffer"); 1953 return GL_FALSE; 1954 } 1955 1956 /* wrap the alpha renderbuffer around the RGB renderbuffer */ 1957 arb->Wrapped = fb->Attachment[b].Renderbuffer; 1958 1959 /* Set up my alphabuffer fields and plug in my functions. 1960 * The functions will put/get the alpha values from/to RGBA arrays 1961 * and then call the wrapped buffer's functions to handle the RGB 1962 * values. 1963 */ 1964 arb->InternalFormat = arb->Wrapped->InternalFormat; 1965 arb->Format = MESA_FORMAT_A8; 1966 arb->DataType = arb->Wrapped->DataType; 1967 arb->AllocStorage = alloc_storage_alpha8; 1968 arb->Delete = delete_renderbuffer_alpha8; 1969 arb->GetPointer = get_pointer_alpha8; 1970 arb->GetRow = get_row_alpha8; 1971 arb->GetValues = get_values_alpha8; 1972 arb->PutRow = put_row_alpha8; 1973 arb->PutRowRGB = put_row_rgb_alpha8; 1974 arb->PutMonoRow = put_mono_row_alpha8; 1975 arb->PutValues = put_values_alpha8; 1976 arb->PutMonoValues = put_mono_values_alpha8; 1977 1978 /* clear the pointer to avoid assertion/sanity check failure later */ 1979 fb->Attachment[b].Renderbuffer = NULL; 1980 1981 /* plug the alpha renderbuffer into the colorbuffer attachment */ 1982 _mesa_add_renderbuffer(fb, b, arb); 1983 } 1984 1985 return GL_TRUE; 1986} 1987 1988 1989/** 1990 * For framebuffers that use a software alpha channel wrapper 1991 * created by _mesa_add_alpha_renderbuffer or _mesa_add_soft_renderbuffers, 1992 * copy the back buffer alpha channel into the front buffer alpha channel. 1993 */ 1994void 1995_mesa_copy_soft_alpha_renderbuffers(struct gl_context *ctx, struct gl_framebuffer *fb) 1996{ 1997 if (fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer && 1998 fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer) 1999 copy_buffer_alpha8(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer, 2000 fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer); 2001 2002 2003 if (fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer && 2004 fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer) 2005 copy_buffer_alpha8(fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer, 2006 fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer); 2007} 2008 2009 2010/** 2011 * Add a software-based depth renderbuffer to the given framebuffer. 2012 * This is a helper routine for device drivers when creating a 2013 * window system framebuffer (not a user-created render/framebuffer). 2014 * Once this function is called, you can basically forget about this 2015 * renderbuffer; core Mesa will handle all the buffer management and 2016 * rendering! 2017 */ 2018GLboolean 2019_mesa_add_depth_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb, 2020 GLuint depthBits) 2021{ 2022 struct gl_renderbuffer *rb; 2023 2024 if (depthBits > 32) { 2025 _mesa_problem(ctx, 2026 "Unsupported depthBits in _mesa_add_depth_renderbuffer"); 2027 return GL_FALSE; 2028 } 2029 2030 assert(fb->Attachment[BUFFER_DEPTH].Renderbuffer == NULL); 2031 2032 rb = _mesa_new_renderbuffer(ctx, 0); 2033 if (!rb) { 2034 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating depth buffer"); 2035 return GL_FALSE; 2036 } 2037 2038 if (depthBits <= 16) { 2039 rb->Format = MESA_FORMAT_Z16; 2040 rb->InternalFormat = GL_DEPTH_COMPONENT16; 2041 } 2042 else if (depthBits <= 24) { 2043 rb->Format = MESA_FORMAT_X8_Z24; 2044 rb->InternalFormat = GL_DEPTH_COMPONENT24; 2045 } 2046 else { 2047 rb->Format = MESA_FORMAT_Z32; 2048 rb->InternalFormat = GL_DEPTH_COMPONENT32; 2049 } 2050 2051 rb->AllocStorage = _mesa_soft_renderbuffer_storage; 2052 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb); 2053 2054 return GL_TRUE; 2055} 2056 2057 2058/** 2059 * Add a software-based stencil renderbuffer to the given framebuffer. 2060 * This is a helper routine for device drivers when creating a 2061 * window system framebuffer (not a user-created render/framebuffer). 2062 * Once this function is called, you can basically forget about this 2063 * renderbuffer; core Mesa will handle all the buffer management and 2064 * rendering! 2065 */ 2066GLboolean 2067_mesa_add_stencil_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb, 2068 GLuint stencilBits) 2069{ 2070 struct gl_renderbuffer *rb; 2071 2072 if (stencilBits > 16) { 2073 _mesa_problem(ctx, 2074 "Unsupported stencilBits in _mesa_add_stencil_renderbuffer"); 2075 return GL_FALSE; 2076 } 2077 2078 assert(fb->Attachment[BUFFER_STENCIL].Renderbuffer == NULL); 2079 2080 rb = _mesa_new_renderbuffer(ctx, 0); 2081 if (!rb) { 2082 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating stencil buffer"); 2083 return GL_FALSE; 2084 } 2085 2086 assert(stencilBits <= 8); 2087 rb->Format = MESA_FORMAT_S8; 2088 rb->InternalFormat = GL_STENCIL_INDEX8; 2089 2090 rb->AllocStorage = _mesa_soft_renderbuffer_storage; 2091 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, rb); 2092 2093 return GL_TRUE; 2094} 2095 2096 2097/** 2098 * Add a software-based accumulation renderbuffer to the given framebuffer. 2099 * This is a helper routine for device drivers when creating a 2100 * window system framebuffer (not a user-created render/framebuffer). 2101 * Once this function is called, you can basically forget about this 2102 * renderbuffer; core Mesa will handle all the buffer management and 2103 * rendering! 2104 */ 2105GLboolean 2106_mesa_add_accum_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb, 2107 GLuint redBits, GLuint greenBits, 2108 GLuint blueBits, GLuint alphaBits) 2109{ 2110 struct gl_renderbuffer *rb; 2111 2112 if (redBits > 16 || greenBits > 16 || blueBits > 16 || alphaBits > 16) { 2113 _mesa_problem(ctx, 2114 "Unsupported accumBits in _mesa_add_accum_renderbuffer"); 2115 return GL_FALSE; 2116 } 2117 2118 assert(fb->Attachment[BUFFER_ACCUM].Renderbuffer == NULL); 2119 2120 rb = _mesa_new_renderbuffer(ctx, 0); 2121 if (!rb) { 2122 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer"); 2123 return GL_FALSE; 2124 } 2125 2126 rb->Format = MESA_FORMAT_SIGNED_RGBA_16; 2127 rb->InternalFormat = GL_RGBA16_SNORM; 2128 rb->AllocStorage = _mesa_soft_renderbuffer_storage; 2129 _mesa_add_renderbuffer(fb, BUFFER_ACCUM, rb); 2130 2131 return GL_TRUE; 2132} 2133 2134 2135 2136/** 2137 * Add a software-based aux renderbuffer to the given framebuffer. 2138 * This is a helper routine for device drivers when creating a 2139 * window system framebuffer (not a user-created render/framebuffer). 2140 * Once this function is called, you can basically forget about this 2141 * renderbuffer; core Mesa will handle all the buffer management and 2142 * rendering! 2143 * 2144 * NOTE: color-index aux buffers not supported. 2145 */ 2146GLboolean 2147_mesa_add_aux_renderbuffers(struct gl_context *ctx, struct gl_framebuffer *fb, 2148 GLuint colorBits, GLuint numBuffers) 2149{ 2150 GLuint i; 2151 2152 if (colorBits > 16) { 2153 _mesa_problem(ctx, 2154 "Unsupported accumBits in _mesa_add_aux_renderbuffers"); 2155 return GL_FALSE; 2156 } 2157 2158 assert(numBuffers <= MAX_AUX_BUFFERS); 2159 2160 for (i = 0; i < numBuffers; i++) { 2161 struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, 0); 2162 2163 assert(fb->Attachment[BUFFER_AUX0 + i].Renderbuffer == NULL); 2164 2165 if (!rb) { 2166 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating aux buffer"); 2167 return GL_FALSE; 2168 } 2169 2170 assert (colorBits <= 8); 2171 rb->Format = MESA_FORMAT_RGBA8888; 2172 rb->InternalFormat = GL_RGBA; 2173 2174 rb->AllocStorage = _mesa_soft_renderbuffer_storage; 2175 _mesa_add_renderbuffer(fb, BUFFER_AUX0 + i, rb); 2176 } 2177 return GL_TRUE; 2178} 2179 2180 2181/** 2182 * Create/attach software-based renderbuffers to the given framebuffer. 2183 * This is a helper routine for device drivers. Drivers can just as well 2184 * call the individual _mesa_add_*_renderbuffer() routines directly. 2185 */ 2186void 2187_mesa_add_soft_renderbuffers(struct gl_framebuffer *fb, 2188 GLboolean color, 2189 GLboolean depth, 2190 GLboolean stencil, 2191 GLboolean accum, 2192 GLboolean alpha, 2193 GLboolean aux) 2194{ 2195 GLboolean frontLeft = GL_TRUE; 2196 GLboolean backLeft = fb->Visual.doubleBufferMode; 2197 GLboolean frontRight = fb->Visual.stereoMode; 2198 GLboolean backRight = fb->Visual.stereoMode && fb->Visual.doubleBufferMode; 2199 2200 if (color) { 2201 assert(fb->Visual.redBits == fb->Visual.greenBits); 2202 assert(fb->Visual.redBits == fb->Visual.blueBits); 2203 _mesa_add_color_renderbuffers(NULL, fb, 2204 fb->Visual.redBits, 2205 fb->Visual.alphaBits, 2206 frontLeft, backLeft, 2207 frontRight, backRight); 2208 } 2209 2210 if (depth) { 2211 assert(fb->Visual.depthBits > 0); 2212 _mesa_add_depth_renderbuffer(NULL, fb, fb->Visual.depthBits); 2213 } 2214 2215 if (stencil) { 2216 assert(fb->Visual.stencilBits > 0); 2217 _mesa_add_stencil_renderbuffer(NULL, fb, fb->Visual.stencilBits); 2218 } 2219 2220 if (accum) { 2221 assert(fb->Visual.accumRedBits > 0); 2222 assert(fb->Visual.accumGreenBits > 0); 2223 assert(fb->Visual.accumBlueBits > 0); 2224 _mesa_add_accum_renderbuffer(NULL, fb, 2225 fb->Visual.accumRedBits, 2226 fb->Visual.accumGreenBits, 2227 fb->Visual.accumBlueBits, 2228 fb->Visual.accumAlphaBits); 2229 } 2230 2231 if (aux) { 2232 assert(fb->Visual.numAuxBuffers > 0); 2233 _mesa_add_aux_renderbuffers(NULL, fb, fb->Visual.redBits, 2234 fb->Visual.numAuxBuffers); 2235 } 2236 2237 if (alpha) { 2238 assert(fb->Visual.alphaBits > 0); 2239 _mesa_add_alpha_renderbuffers(NULL, fb, fb->Visual.alphaBits, 2240 frontLeft, backLeft, 2241 frontRight, backRight); 2242 } 2243 2244#if 0 2245 if (multisample) { 2246 /* maybe someday */ 2247 } 2248#endif 2249} 2250 2251 2252/** 2253 * Attach a renderbuffer to a framebuffer. 2254 * \param bufferName one of the BUFFER_x tokens 2255 */ 2256void 2257_mesa_add_renderbuffer(struct gl_framebuffer *fb, 2258 gl_buffer_index bufferName, struct gl_renderbuffer *rb) 2259{ 2260 assert(fb); 2261 assert(rb); 2262 assert(bufferName < BUFFER_COUNT); 2263 2264 /* There should be no previous renderbuffer on this attachment point, 2265 * with the exception of depth/stencil since the same renderbuffer may 2266 * be used for both. 2267 */ 2268 assert(bufferName == BUFFER_DEPTH || 2269 bufferName == BUFFER_STENCIL || 2270 fb->Attachment[bufferName].Renderbuffer == NULL); 2271 2272 /* winsys vs. user-created buffer cross check */ 2273 if (fb->Name) { 2274 assert(rb->Name); 2275 } 2276 else { 2277 assert(!rb->Name); 2278 } 2279 2280 fb->Attachment[bufferName].Type = GL_RENDERBUFFER_EXT; 2281 fb->Attachment[bufferName].Complete = GL_TRUE; 2282 _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer, rb); 2283} 2284 2285 2286/** 2287 * Remove the named renderbuffer from the given framebuffer. 2288 * \param bufferName one of the BUFFER_x tokens 2289 */ 2290void 2291_mesa_remove_renderbuffer(struct gl_framebuffer *fb, 2292 gl_buffer_index bufferName) 2293{ 2294 struct gl_renderbuffer *rb; 2295 2296 assert(bufferName < BUFFER_COUNT); 2297 2298 rb = fb->Attachment[bufferName].Renderbuffer; 2299 if (!rb) 2300 return; 2301 2302 _mesa_reference_renderbuffer(&rb, NULL); 2303 2304 fb->Attachment[bufferName].Renderbuffer = NULL; 2305} 2306 2307 2308/** 2309 * Set *ptr to point to rb. If *ptr points to another renderbuffer, 2310 * dereference that buffer first. The new renderbuffer's refcount will 2311 * be incremented. The old renderbuffer's refcount will be decremented. 2312 */ 2313void 2314_mesa_reference_renderbuffer(struct gl_renderbuffer **ptr, 2315 struct gl_renderbuffer *rb) 2316{ 2317 assert(ptr); 2318 if (*ptr == rb) { 2319 /* no change */ 2320 return; 2321 } 2322 2323 if (*ptr) { 2324 /* Unreference the old renderbuffer */ 2325 GLboolean deleteFlag = GL_FALSE; 2326 struct gl_renderbuffer *oldRb = *ptr; 2327 2328 _glthread_LOCK_MUTEX(oldRb->Mutex); 2329 ASSERT(oldRb->RefCount > 0); 2330 oldRb->RefCount--; 2331 /*printf("RB DECR %p (%d) to %d\n", (void*) oldRb, oldRb->Name, oldRb->RefCount);*/ 2332 deleteFlag = (oldRb->RefCount == 0); 2333 _glthread_UNLOCK_MUTEX(oldRb->Mutex); 2334 2335 if (deleteFlag) { 2336 oldRb->Delete(oldRb); 2337 } 2338 2339 *ptr = NULL; 2340 } 2341 assert(!*ptr); 2342 2343 if (rb) { 2344 /* reference new renderbuffer */ 2345 _glthread_LOCK_MUTEX(rb->Mutex); 2346 rb->RefCount++; 2347 /*printf("RB INCR %p (%d) to %d\n", (void*) rb, rb->Name, rb->RefCount);*/ 2348 _glthread_UNLOCK_MUTEX(rb->Mutex); 2349 *ptr = rb; 2350 } 2351} 2352 2353 2354/** 2355 * Create a new combined depth/stencil renderbuffer for implementing 2356 * the GL_EXT_packed_depth_stencil extension. 2357 * \return new depth/stencil renderbuffer 2358 */ 2359struct gl_renderbuffer * 2360_mesa_new_depthstencil_renderbuffer(struct gl_context *ctx, GLuint name) 2361{ 2362 struct gl_renderbuffer *dsrb; 2363 2364 dsrb = _mesa_new_renderbuffer(ctx, name); 2365 if (!dsrb) 2366 return NULL; 2367 2368 /* init fields not covered by _mesa_new_renderbuffer() */ 2369 dsrb->InternalFormat = GL_DEPTH24_STENCIL8_EXT; 2370 dsrb->Format = MESA_FORMAT_Z24_S8; 2371 dsrb->AllocStorage = _mesa_soft_renderbuffer_storage; 2372 2373 return dsrb; 2374} 2375