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