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