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