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