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