renderbuffer.c revision f5713c7d2e7ba8e1170fd9b1dd95379662ab6117
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 0 1071 if (!rb->surface) 1072 rb->surface = (struct pipe_surface *) 1073 pipe->surface_alloc(pipe, PIPE_FORMAT_U_S8); 1074#endif 1075 break; 1076 case GL_STENCIL_INDEX16_EXT: 1077 rb->_ActualFormat = GL_STENCIL_INDEX16_EXT; 1078 rb->_BaseFormat = GL_STENCIL_INDEX; 1079 rb->DataType = GL_UNSIGNED_SHORT; 1080 rb->GetPointer = get_pointer_ushort; 1081 rb->GetRow = get_row_ushort; 1082 rb->GetValues = get_values_ushort; 1083 rb->PutRow = put_row_ushort; 1084 rb->PutRowRGB = NULL; 1085 rb->PutMonoRow = put_mono_row_ushort; 1086 rb->PutValues = put_values_ushort; 1087 rb->PutMonoValues = put_mono_values_ushort; 1088 rb->StencilBits = 8 * sizeof(GLushort); 1089 pixelSize = sizeof(GLushort); 1090 break; 1091 case GL_DEPTH_COMPONENT: 1092 case GL_DEPTH_COMPONENT16: 1093 rb->_ActualFormat = GL_DEPTH_COMPONENT16; 1094 rb->_BaseFormat = GL_DEPTH_COMPONENT; 1095 rb->DataType = GL_UNSIGNED_SHORT; 1096 rb->GetPointer = get_pointer_ushort; 1097 rb->GetRow = get_row_ushort; 1098 rb->GetValues = get_values_ushort; 1099 rb->PutRow = put_row_ushort; 1100 rb->PutRowRGB = NULL; 1101 rb->PutMonoRow = put_mono_row_ushort; 1102 rb->PutValues = put_values_ushort; 1103 rb->PutMonoValues = put_mono_values_ushort; 1104 rb->DepthBits = 8 * sizeof(GLushort); 1105#if 0 1106 if (!rb->surface) 1107 rb->surface = (struct pipe_surface *) 1108 pipe->surface_alloc(pipe, PIPE_FORMAT_U_Z16); 1109#endif 1110 pixelSize = sizeof(GLushort); 1111 break; 1112 case GL_DEPTH_COMPONENT24: 1113 case GL_DEPTH_COMPONENT32: 1114 rb->_BaseFormat = GL_DEPTH_COMPONENT; 1115 rb->DataType = GL_UNSIGNED_INT; 1116 rb->GetPointer = get_pointer_uint; 1117 rb->GetRow = get_row_uint; 1118 rb->GetValues = get_values_uint; 1119 rb->PutRow = put_row_uint; 1120 rb->PutRowRGB = NULL; 1121 rb->PutMonoRow = put_mono_row_uint; 1122 rb->PutValues = put_values_uint; 1123 rb->PutMonoValues = put_mono_values_uint; 1124 if (internalFormat == GL_DEPTH_COMPONENT24) { 1125 rb->_ActualFormat = GL_DEPTH_COMPONENT24; 1126 rb->DepthBits = 24; 1127 } 1128 else { 1129 rb->_ActualFormat = GL_DEPTH_COMPONENT32; 1130 rb->DepthBits = 32; 1131 } 1132#if 0 1133 if (!rb->surface) 1134 rb->surface = (struct pipe_surface *) 1135 pipe->surface_alloc(pipe, PIPE_FORMAT_U_Z32); 1136#endif 1137 pixelSize = sizeof(GLuint); 1138 break; 1139 case GL_DEPTH_STENCIL_EXT: 1140 case GL_DEPTH24_STENCIL8_EXT: 1141 rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT; 1142 rb->_BaseFormat = GL_DEPTH_STENCIL_EXT; 1143 rb->DataType = GL_UNSIGNED_INT_24_8_EXT; 1144 rb->GetPointer = get_pointer_uint; 1145 rb->GetRow = get_row_uint; 1146 rb->GetValues = get_values_uint; 1147 rb->PutRow = put_row_uint; 1148 rb->PutRowRGB = NULL; 1149 rb->PutMonoRow = put_mono_row_uint; 1150 rb->PutValues = put_values_uint; 1151 rb->PutMonoValues = put_mono_values_uint; 1152 rb->DepthBits = 24; 1153 rb->StencilBits = 8; 1154#if 0 1155 if (!rb->surface) 1156 rb->surface = (struct pipe_surface *) 1157 pipe->surface_alloc(pipe, PIPE_FORMAT_S8_Z24); 1158#endif 1159 pixelSize = sizeof(GLuint); 1160 break; 1161 case GL_COLOR_INDEX8_EXT: 1162 rb->_ActualFormat = GL_COLOR_INDEX8_EXT; 1163 rb->_BaseFormat = GL_COLOR_INDEX; 1164 rb->DataType = GL_UNSIGNED_BYTE; 1165 rb->GetPointer = get_pointer_ubyte; 1166 rb->GetRow = get_row_ubyte; 1167 rb->GetValues = get_values_ubyte; 1168 rb->PutRow = put_row_ubyte; 1169 rb->PutRowRGB = NULL; 1170 rb->PutMonoRow = put_mono_row_ubyte; 1171 rb->PutValues = put_values_ubyte; 1172 rb->PutMonoValues = put_mono_values_ubyte; 1173 rb->IndexBits = 8 * sizeof(GLubyte); 1174 pixelSize = sizeof(GLubyte); 1175 break; 1176 case GL_COLOR_INDEX16_EXT: 1177 rb->_ActualFormat = GL_COLOR_INDEX16_EXT; 1178 rb->_BaseFormat = GL_COLOR_INDEX; 1179 rb->DataType = GL_UNSIGNED_SHORT; 1180 rb->GetPointer = get_pointer_ushort; 1181 rb->GetRow = get_row_ushort; 1182 rb->GetValues = get_values_ushort; 1183 rb->PutRow = put_row_ushort; 1184 rb->PutRowRGB = NULL; 1185 rb->PutMonoRow = put_mono_row_ushort; 1186 rb->PutValues = put_values_ushort; 1187 rb->PutMonoValues = put_mono_values_ushort; 1188 rb->IndexBits = 8 * sizeof(GLushort); 1189 pixelSize = sizeof(GLushort); 1190 break; 1191 case COLOR_INDEX32: 1192 rb->_ActualFormat = COLOR_INDEX32; 1193 rb->_BaseFormat = GL_COLOR_INDEX; 1194 rb->DataType = GL_UNSIGNED_INT; 1195 rb->GetPointer = get_pointer_uint; 1196 rb->GetRow = get_row_uint; 1197 rb->GetValues = get_values_uint; 1198 rb->PutRow = put_row_uint; 1199 rb->PutRowRGB = NULL; 1200 rb->PutMonoRow = put_mono_row_uint; 1201 rb->PutValues = put_values_uint; 1202 rb->PutMonoValues = put_mono_values_uint; 1203 rb->IndexBits = 8 * sizeof(GLuint); 1204 pixelSize = sizeof(GLuint); 1205 break; 1206 default: 1207 _mesa_problem(ctx, "Bad internalFormat in _mesa_soft_renderbuffer_storage"); 1208 return GL_FALSE; 1209 } 1210 1211 ASSERT(rb->DataType); 1212 ASSERT(rb->GetPointer); 1213 ASSERT(rb->GetRow); 1214 ASSERT(rb->GetValues); 1215 ASSERT(rb->PutRow); 1216 ASSERT(rb->PutMonoRow); 1217 ASSERT(rb->PutValues); 1218 ASSERT(rb->PutMonoValues); 1219 1220 /* free old buffer storage */ 1221 if (0/**rb->surface**/) { 1222 /* pipe_surface/region */ 1223 } 1224 else if (rb->Data) { 1225 /* legacy renderbuffer (this will go away) */ 1226 _mesa_free(rb->Data); 1227 } 1228 rb->Data = NULL; 1229 1230 if (width > 0 && height > 0) { 1231 /* allocate new buffer storage */ 1232 if (0/**rb->surface**/) { 1233 /* pipe_surface/region */ 1234#if 0 1235 if (rb->surface->region) { 1236 pipe->region_unmap(pipe, rb->surface->region); 1237 pipe->region_release(pipe, &rb->surface->region); 1238 } 1239 rb->surface->region = pipe->region_alloc(pipe, pixelSize, width, height); 1240 /* XXX probably don't want to really map here */ 1241 pipe->region_map(pipe, rb->surface->region); 1242 rb->Data = rb->surface->region->map; 1243#endif 1244 } 1245 else { 1246 /* legacy renderbuffer (this will go away) */ 1247 rb->Data = malloc(width * height * pixelSize); 1248 } 1249 1250 if (rb->Data == NULL) { 1251 rb->Width = 0; 1252 rb->Height = 0; 1253 _mesa_error(ctx, GL_OUT_OF_MEMORY, 1254 "software renderbuffer allocation (%d x %d x %d)", 1255 width, height, pixelSize); 1256 return GL_FALSE; 1257 } 1258 } 1259 1260 rb->Width = width; 1261 rb->Height = height; 1262 1263 return GL_TRUE; 1264} 1265 1266 1267 1268/**********************************************************************/ 1269/**********************************************************************/ 1270/**********************************************************************/ 1271 1272 1273/** 1274 * Here we utilize the gl_renderbuffer->Wrapper field to put an alpha 1275 * buffer wrapper around an existing RGB renderbuffer (hw or sw). 1276 * 1277 * When PutRow is called (for example), we store the alpha values in 1278 * this buffer, then pass on the PutRow call to the wrapped RGB 1279 * buffer. 1280 */ 1281 1282 1283static GLboolean 1284alloc_storage_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, 1285 GLenum internalFormat, GLuint width, GLuint height) 1286{ 1287 ASSERT(arb != arb->Wrapped); 1288 ASSERT(arb->_ActualFormat == GL_ALPHA8); 1289 1290 /* first, pass the call to the wrapped RGB buffer */ 1291 if (!arb->Wrapped->AllocStorage(ctx, arb->Wrapped, internalFormat, 1292 width, height)) { 1293 return GL_FALSE; 1294 } 1295 1296 /* next, resize my alpha buffer */ 1297 if (arb->Data) { 1298 _mesa_free(arb->Data); 1299 } 1300 1301 arb->Data = _mesa_malloc(width * height * sizeof(GLubyte)); 1302 if (arb->Data == NULL) { 1303 arb->Width = 0; 1304 arb->Height = 0; 1305 _mesa_error(ctx, GL_OUT_OF_MEMORY, "software alpha buffer allocation"); 1306 return GL_FALSE; 1307 } 1308 1309 arb->Width = width; 1310 arb->Height = height; 1311 1312 return GL_TRUE; 1313} 1314 1315 1316/** 1317 * Delete an alpha_renderbuffer object, as well as the wrapped RGB buffer. 1318 */ 1319static void 1320delete_renderbuffer_alpha8(struct gl_renderbuffer *arb) 1321{ 1322 if (arb->Data) { 1323 _mesa_free(arb->Data); 1324 } 1325 ASSERT(arb->Wrapped); 1326 ASSERT(arb != arb->Wrapped); 1327 arb->Wrapped->Delete(arb->Wrapped); 1328 arb->Wrapped = NULL; 1329 _mesa_free(arb); 1330} 1331 1332 1333static void * 1334get_pointer_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, 1335 GLint x, GLint y) 1336{ 1337 return NULL; /* don't allow direct access! */ 1338} 1339 1340 1341static void 1342get_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count, 1343 GLint x, GLint y, void *values) 1344{ 1345 /* NOTE: 'values' is RGBA format! */ 1346 const GLubyte *src = (const GLubyte *) arb->Data + y * arb->Width + x; 1347 GLubyte *dst = (GLubyte *) values; 1348 GLuint i; 1349 ASSERT(arb != arb->Wrapped); 1350 ASSERT(arb->DataType == GL_UNSIGNED_BYTE); 1351 /* first, pass the call to the wrapped RGB buffer */ 1352 arb->Wrapped->GetRow(ctx, arb->Wrapped, count, x, y, values); 1353 /* second, fill in alpha values from this buffer! */ 1354 for (i = 0; i < count; i++) { 1355 dst[i * 4 + 3] = src[i]; 1356 } 1357} 1358 1359 1360static void 1361get_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count, 1362 const GLint x[], const GLint y[], void *values) 1363{ 1364 GLubyte *dst = (GLubyte *) values; 1365 GLuint i; 1366 ASSERT(arb != arb->Wrapped); 1367 ASSERT(arb->DataType == GL_UNSIGNED_BYTE); 1368 /* first, pass the call to the wrapped RGB buffer */ 1369 arb->Wrapped->GetValues(ctx, arb->Wrapped, count, x, y, values); 1370 /* second, fill in alpha values from this buffer! */ 1371 for (i = 0; i < count; i++) { 1372 const GLubyte *src = (GLubyte *) arb->Data + y[i] * arb->Width + x[i]; 1373 dst[i * 4 + 3] = *src; 1374 } 1375} 1376 1377 1378static void 1379put_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count, 1380 GLint x, GLint y, const void *values, const GLubyte *mask) 1381{ 1382 const GLubyte *src = (const GLubyte *) values; 1383 GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x; 1384 GLuint i; 1385 ASSERT(arb != arb->Wrapped); 1386 ASSERT(arb->DataType == GL_UNSIGNED_BYTE); 1387 /* first, pass the call to the wrapped RGB buffer */ 1388 arb->Wrapped->PutRow(ctx, arb->Wrapped, count, x, y, values, mask); 1389 /* second, store alpha in our buffer */ 1390 for (i = 0; i < count; i++) { 1391 if (!mask || mask[i]) { 1392 dst[i] = src[i * 4 + 3]; 1393 } 1394 } 1395} 1396 1397 1398static void 1399put_row_rgb_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count, 1400 GLint x, GLint y, const void *values, const GLubyte *mask) 1401{ 1402 const GLubyte *src = (const GLubyte *) values; 1403 GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x; 1404 GLuint i; 1405 ASSERT(arb != arb->Wrapped); 1406 ASSERT(arb->DataType == GL_UNSIGNED_BYTE); 1407 /* first, pass the call to the wrapped RGB buffer */ 1408 arb->Wrapped->PutRowRGB(ctx, arb->Wrapped, count, x, y, values, mask); 1409 /* second, store alpha in our buffer */ 1410 for (i = 0; i < count; i++) { 1411 if (!mask || mask[i]) { 1412 dst[i] = src[i * 4 + 3]; 1413 } 1414 } 1415} 1416 1417 1418static void 1419put_mono_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count, 1420 GLint x, GLint y, const void *value, const GLubyte *mask) 1421{ 1422 const GLubyte val = ((const GLubyte *) value)[3]; 1423 GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x; 1424 ASSERT(arb != arb->Wrapped); 1425 ASSERT(arb->DataType == GL_UNSIGNED_BYTE); 1426 /* first, pass the call to the wrapped RGB buffer */ 1427 arb->Wrapped->PutMonoRow(ctx, arb->Wrapped, count, x, y, value, mask); 1428 /* second, store alpha in our buffer */ 1429 if (mask) { 1430 GLuint i; 1431 for (i = 0; i < count; i++) { 1432 if (mask[i]) { 1433 dst[i] = val; 1434 } 1435 } 1436 } 1437 else { 1438 _mesa_memset(dst, val, count); 1439 } 1440} 1441 1442 1443static void 1444put_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count, 1445 const GLint x[], const GLint y[], 1446 const void *values, const GLubyte *mask) 1447{ 1448 const GLubyte *src = (const GLubyte *) values; 1449 GLuint i; 1450 ASSERT(arb != arb->Wrapped); 1451 ASSERT(arb->DataType == GL_UNSIGNED_BYTE); 1452 /* first, pass the call to the wrapped RGB buffer */ 1453 arb->Wrapped->PutValues(ctx, arb->Wrapped, count, x, y, values, mask); 1454 /* second, store alpha in our buffer */ 1455 for (i = 0; i < count; i++) { 1456 if (!mask || mask[i]) { 1457 GLubyte *dst = (GLubyte *) arb->Data + y[i] * arb->Width + x[i]; 1458 *dst = src[i * 4 + 3]; 1459 } 1460 } 1461} 1462 1463 1464static void 1465put_mono_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, 1466 GLuint count, const GLint x[], const GLint y[], 1467 const void *value, const GLubyte *mask) 1468{ 1469 const GLubyte val = ((const GLubyte *) value)[3]; 1470 GLuint i; 1471 ASSERT(arb != arb->Wrapped); 1472 ASSERT(arb->DataType == GL_UNSIGNED_BYTE); 1473 /* first, pass the call to the wrapped RGB buffer */ 1474 arb->Wrapped->PutValues(ctx, arb->Wrapped, count, x, y, value, mask); 1475 /* second, store alpha in our buffer */ 1476 for (i = 0; i < count; i++) { 1477 if (!mask || mask[i]) { 1478 GLubyte *dst = (GLubyte *) arb->Data + y[i] * arb->Width + x[i]; 1479 *dst = val; 1480 } 1481 } 1482} 1483 1484 1485static void 1486copy_buffer_alpha8(struct gl_renderbuffer* dst, struct gl_renderbuffer* src) 1487{ 1488 ASSERT(dst->_ActualFormat == GL_ALPHA8); 1489 ASSERT(src->_ActualFormat == GL_ALPHA8); 1490 ASSERT(dst->Width == src->Width); 1491 ASSERT(dst->Height == src->Height); 1492 1493 _mesa_memcpy(dst->Data, src->Data, dst->Width * dst->Height * sizeof(GLubyte)); 1494} 1495 1496 1497/**********************************************************************/ 1498/**********************************************************************/ 1499/**********************************************************************/ 1500 1501 1502/** 1503 * Default GetPointer routine. Always return NULL to indicate that 1504 * direct buffer access is not supported. 1505 */ 1506static void * 1507nop_get_pointer(GLcontext *ctx, struct gl_renderbuffer *rb, GLint x, GLint y) 1508{ 1509 return NULL; 1510} 1511 1512 1513/** 1514 * Initialize the fields of a gl_renderbuffer to default values. 1515 */ 1516void 1517_mesa_init_renderbuffer(struct gl_renderbuffer *rb, GLuint name) 1518{ 1519 _glthread_INIT_MUTEX(rb->Mutex); 1520 1521 rb->Magic = RB_MAGIC; 1522 rb->ClassID = 0; 1523 rb->Name = name; 1524 rb->RefCount = 0; 1525 rb->Delete = _mesa_delete_renderbuffer; 1526 1527 /* The rest of these should be set later by the caller of this function or 1528 * the AllocStorage method: 1529 */ 1530 rb->AllocStorage = NULL; 1531 1532 rb->Width = 0; 1533 rb->Height = 0; 1534 rb->InternalFormat = GL_NONE; 1535 rb->_ActualFormat = GL_NONE; 1536 rb->_BaseFormat = GL_NONE; 1537 rb->DataType = GL_NONE; 1538 rb->RedBits = rb->GreenBits = rb->BlueBits = rb->AlphaBits = 0; 1539 rb->IndexBits = 0; 1540 rb->DepthBits = 0; 1541 rb->StencilBits = 0; 1542 rb->Data = NULL; 1543 1544 /* Point back to ourself so that we don't have to check for Wrapped==NULL 1545 * all over the drivers. 1546 */ 1547 rb->Wrapped = rb; 1548 1549 rb->GetPointer = nop_get_pointer; 1550 rb->GetRow = NULL; 1551 rb->GetValues = NULL; 1552 rb->PutRow = NULL; 1553 rb->PutRowRGB = NULL; 1554 rb->PutMonoRow = NULL; 1555 rb->PutValues = NULL; 1556 rb->PutMonoValues = NULL; 1557} 1558 1559 1560/** 1561 * Allocate a new gl_renderbuffer object. This can be used for user-created 1562 * renderbuffers or window-system renderbuffers. 1563 */ 1564struct gl_renderbuffer * 1565_mesa_new_renderbuffer(GLcontext *ctx, GLuint name) 1566{ 1567 struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer); 1568 if (rb) { 1569 _mesa_init_renderbuffer(rb, name); 1570 } 1571 return rb; 1572} 1573 1574 1575/** 1576 * Delete a gl_framebuffer. 1577 * This is the default function for renderbuffer->Delete(). 1578 */ 1579void 1580_mesa_delete_renderbuffer(struct gl_renderbuffer *rb) 1581{ 1582 if (rb->Data) { 1583 _mesa_free(rb->Data); 1584 } 1585 _mesa_free(rb); 1586} 1587 1588 1589/** 1590 * Allocate a software-based renderbuffer. This is called via the 1591 * ctx->Driver.NewRenderbuffer() function when the user creates a new 1592 * renderbuffer. 1593 * This would not be used for hardware-based renderbuffers. 1594 */ 1595struct gl_renderbuffer * 1596_mesa_new_soft_renderbuffer(GLcontext *ctx, GLuint name) 1597{ 1598 struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, name); 1599 if (rb) { 1600 rb->AllocStorage = _mesa_soft_renderbuffer_storage; 1601 /* Normally, one would setup the PutRow, GetRow, etc functions here. 1602 * But we're doing that in the _mesa_soft_renderbuffer_storage() function 1603 * instead. 1604 */ 1605 } 1606 return rb; 1607} 1608 1609 1610/** 1611 * Add software-based color renderbuffers to the given framebuffer. 1612 * This is a helper routine for device drivers when creating a 1613 * window system framebuffer (not a user-created render/framebuffer). 1614 * Once this function is called, you can basically forget about this 1615 * renderbuffer; core Mesa will handle all the buffer management and 1616 * rendering! 1617 */ 1618GLboolean 1619_mesa_add_color_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb, 1620 GLuint rgbBits, GLuint alphaBits, 1621 GLboolean frontLeft, GLboolean backLeft, 1622 GLboolean frontRight, GLboolean backRight) 1623{ 1624 GLuint b; 1625 1626 if (rgbBits > 16 || alphaBits > 16) { 1627 _mesa_problem(ctx, 1628 "Unsupported bit depth in _mesa_add_color_renderbuffers"); 1629 return GL_FALSE; 1630 } 1631 1632 assert(MAX_COLOR_ATTACHMENTS >= 4); 1633 1634 for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) { 1635 struct gl_renderbuffer *rb; 1636 1637 if (b == BUFFER_FRONT_LEFT && !frontLeft) 1638 continue; 1639 else if (b == BUFFER_BACK_LEFT && !backLeft) 1640 continue; 1641 else if (b == BUFFER_FRONT_RIGHT && !frontRight) 1642 continue; 1643 else if (b == BUFFER_BACK_RIGHT && !backRight) 1644 continue; 1645 1646 assert(fb->Attachment[b].Renderbuffer == NULL); 1647 1648 rb = _mesa_new_renderbuffer(ctx, 0); 1649 if (!rb) { 1650 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer"); 1651 return GL_FALSE; 1652 } 1653 1654 if (rgbBits <= 8) { 1655 if (alphaBits) 1656 rb->_ActualFormat = GL_RGBA8; 1657 else 1658 rb->_ActualFormat = GL_RGB8; 1659 } 1660 else { 1661 assert(rgbBits <= 16); 1662 if (alphaBits) 1663 rb->_ActualFormat = GL_RGBA16; 1664 else 1665 rb->_ActualFormat = GL_RGBA16; /* don't really have RGB16 yet */ 1666 } 1667 rb->InternalFormat = rb->_ActualFormat; 1668 1669 rb->AllocStorage = _mesa_soft_renderbuffer_storage; 1670 _mesa_add_renderbuffer(fb, b, rb); 1671 } 1672 1673 return GL_TRUE; 1674} 1675 1676 1677/** 1678 * Add software-based color index renderbuffers to the given framebuffer. 1679 * This is a helper routine for device drivers when creating a 1680 * window system framebuffer (not a user-created render/framebuffer). 1681 * Once this function is called, you can basically forget about this 1682 * renderbuffer; core Mesa will handle all the buffer management and 1683 * rendering! 1684 */ 1685GLboolean 1686_mesa_add_color_index_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb, 1687 GLuint indexBits, 1688 GLboolean frontLeft, GLboolean backLeft, 1689 GLboolean frontRight, GLboolean backRight) 1690{ 1691 GLuint b; 1692 1693 if (indexBits > 8) { 1694 _mesa_problem(ctx, 1695 "Unsupported bit depth in _mesa_add_color_index_renderbuffers"); 1696 return GL_FALSE; 1697 } 1698 1699 assert(MAX_COLOR_ATTACHMENTS >= 4); 1700 1701 for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) { 1702 struct gl_renderbuffer *rb; 1703 1704 if (b == BUFFER_FRONT_LEFT && !frontLeft) 1705 continue; 1706 else if (b == BUFFER_BACK_LEFT && !backLeft) 1707 continue; 1708 else if (b == BUFFER_FRONT_RIGHT && !frontRight) 1709 continue; 1710 else if (b == BUFFER_BACK_RIGHT && !backRight) 1711 continue; 1712 1713 assert(fb->Attachment[b].Renderbuffer == NULL); 1714 1715 rb = _mesa_new_renderbuffer(ctx, 0); 1716 if (!rb) { 1717 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer"); 1718 return GL_FALSE; 1719 } 1720 1721 if (indexBits <= 8) { 1722 /* only support GLuint for now */ 1723 /*rb->InternalFormat = GL_COLOR_INDEX8_EXT;*/ 1724 rb->_ActualFormat = COLOR_INDEX32; 1725 } 1726 else { 1727 rb->_ActualFormat = COLOR_INDEX32; 1728 } 1729 rb->InternalFormat = rb->_ActualFormat; 1730 1731 rb->AllocStorage = _mesa_soft_renderbuffer_storage; 1732 _mesa_add_renderbuffer(fb, b, rb); 1733 } 1734 1735 return GL_TRUE; 1736} 1737 1738 1739/** 1740 * Add software-based alpha renderbuffers to the given framebuffer. 1741 * This is a helper routine for device drivers when creating a 1742 * window system framebuffer (not a user-created render/framebuffer). 1743 * Once this function is called, you can basically forget about this 1744 * renderbuffer; core Mesa will handle all the buffer management and 1745 * rendering! 1746 */ 1747GLboolean 1748_mesa_add_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb, 1749 GLuint alphaBits, 1750 GLboolean frontLeft, GLboolean backLeft, 1751 GLboolean frontRight, GLboolean backRight) 1752{ 1753 GLuint b; 1754 1755 /* for window system framebuffers only! */ 1756 assert(fb->Name == 0); 1757 1758 if (alphaBits > 8) { 1759 _mesa_problem(ctx, 1760 "Unsupported bit depth in _mesa_add_alpha_renderbuffers"); 1761 return GL_FALSE; 1762 } 1763 1764 assert(MAX_COLOR_ATTACHMENTS >= 4); 1765 1766 /* Wrap each of the RGB color buffers with an alpha renderbuffer. 1767 */ 1768 for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) { 1769 struct gl_renderbuffer *arb; 1770 1771 if (b == BUFFER_FRONT_LEFT && !frontLeft) 1772 continue; 1773 else if (b == BUFFER_BACK_LEFT && !backLeft) 1774 continue; 1775 else if (b == BUFFER_FRONT_RIGHT && !frontRight) 1776 continue; 1777 else if (b == BUFFER_BACK_RIGHT && !backRight) 1778 continue; 1779 1780 /* the RGB buffer to wrap must already exist!! */ 1781 assert(fb->Attachment[b].Renderbuffer); 1782 1783 /* only GLubyte supported for now */ 1784 assert(fb->Attachment[b].Renderbuffer->DataType == GL_UNSIGNED_BYTE); 1785 1786 /* allocate alpha renderbuffer */ 1787 arb = _mesa_new_renderbuffer(ctx, 0); 1788 if (!arb) { 1789 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating alpha buffer"); 1790 return GL_FALSE; 1791 } 1792 1793 /* wrap the alpha renderbuffer around the RGB renderbuffer */ 1794 arb->Wrapped = fb->Attachment[b].Renderbuffer; 1795 1796 /* Set up my alphabuffer fields and plug in my functions. 1797 * The functions will put/get the alpha values from/to RGBA arrays 1798 * and then call the wrapped buffer's functions to handle the RGB 1799 * values. 1800 */ 1801 arb->InternalFormat = arb->Wrapped->InternalFormat; 1802 arb->_ActualFormat = GL_ALPHA8; 1803 arb->_BaseFormat = arb->Wrapped->_BaseFormat; 1804 arb->DataType = arb->Wrapped->DataType; 1805 arb->AllocStorage = alloc_storage_alpha8; 1806 arb->Delete = delete_renderbuffer_alpha8; 1807 arb->GetPointer = get_pointer_alpha8; 1808 arb->GetRow = get_row_alpha8; 1809 arb->GetValues = get_values_alpha8; 1810 arb->PutRow = put_row_alpha8; 1811 arb->PutRowRGB = put_row_rgb_alpha8; 1812 arb->PutMonoRow = put_mono_row_alpha8; 1813 arb->PutValues = put_values_alpha8; 1814 arb->PutMonoValues = put_mono_values_alpha8; 1815 1816 /* clear the pointer to avoid assertion/sanity check failure later */ 1817 fb->Attachment[b].Renderbuffer = NULL; 1818 1819 /* plug the alpha renderbuffer into the colorbuffer attachment */ 1820 _mesa_add_renderbuffer(fb, b, arb); 1821 } 1822 1823 return GL_TRUE; 1824} 1825 1826 1827/** 1828 * For framebuffers that use a software alpha channel wrapper 1829 * created by _mesa_add_alpha_renderbuffer or _mesa_add_soft_renderbuffers, 1830 * copy the back buffer alpha channel into the front buffer alpha channel. 1831 */ 1832void 1833_mesa_copy_soft_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb) 1834{ 1835 if (fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer && 1836 fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer) 1837 copy_buffer_alpha8(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer, 1838 fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer); 1839 1840 1841 if (fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer && 1842 fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer) 1843 copy_buffer_alpha8(fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer, 1844 fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer); 1845} 1846 1847 1848/** 1849 * Add a software-based depth renderbuffer to the given framebuffer. 1850 * This is a helper routine for device drivers when creating a 1851 * window system framebuffer (not a user-created render/framebuffer). 1852 * Once this function is called, you can basically forget about this 1853 * renderbuffer; core Mesa will handle all the buffer management and 1854 * rendering! 1855 */ 1856GLboolean 1857_mesa_add_depth_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb, 1858 GLuint depthBits) 1859{ 1860 struct gl_renderbuffer *rb; 1861 1862 if (depthBits > 32) { 1863 _mesa_problem(ctx, 1864 "Unsupported depthBits in _mesa_add_depth_renderbuffer"); 1865 return GL_FALSE; 1866 } 1867 1868 assert(fb->Attachment[BUFFER_DEPTH].Renderbuffer == NULL); 1869 1870 rb = _mesa_new_renderbuffer(ctx, 0); 1871 if (!rb) { 1872 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating depth buffer"); 1873 return GL_FALSE; 1874 } 1875 1876 if (depthBits <= 16) { 1877 rb->_ActualFormat = GL_DEPTH_COMPONENT16; 1878 } 1879 else if (depthBits <= 24) { 1880 rb->_ActualFormat = GL_DEPTH_COMPONENT24; 1881 } 1882 else { 1883 rb->_ActualFormat = GL_DEPTH_COMPONENT32; 1884 } 1885 rb->InternalFormat = rb->_ActualFormat; 1886 1887 rb->AllocStorage = _mesa_soft_renderbuffer_storage; 1888 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb); 1889 1890 return GL_TRUE; 1891} 1892 1893 1894/** 1895 * Add a software-based stencil renderbuffer to the given framebuffer. 1896 * This is a helper routine for device drivers when creating a 1897 * window system framebuffer (not a user-created render/framebuffer). 1898 * Once this function is called, you can basically forget about this 1899 * renderbuffer; core Mesa will handle all the buffer management and 1900 * rendering! 1901 */ 1902GLboolean 1903_mesa_add_stencil_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb, 1904 GLuint stencilBits) 1905{ 1906 struct gl_renderbuffer *rb; 1907 1908 if (stencilBits > 16) { 1909 _mesa_problem(ctx, 1910 "Unsupported stencilBits in _mesa_add_stencil_renderbuffer"); 1911 return GL_FALSE; 1912 } 1913 1914 assert(fb->Attachment[BUFFER_STENCIL].Renderbuffer == NULL); 1915 1916 rb = _mesa_new_renderbuffer(ctx, 0); 1917 if (!rb) { 1918 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating stencil buffer"); 1919 return GL_FALSE; 1920 } 1921 1922 if (stencilBits <= 8) { 1923 rb->_ActualFormat = GL_STENCIL_INDEX8_EXT; 1924 } 1925 else { 1926 /* not really supported (see s_stencil.c code) */ 1927 rb->_ActualFormat = GL_STENCIL_INDEX16_EXT; 1928 } 1929 rb->InternalFormat = rb->_ActualFormat; 1930 1931 rb->AllocStorage = _mesa_soft_renderbuffer_storage; 1932 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, rb); 1933 1934 return GL_TRUE; 1935} 1936 1937 1938/** 1939 * Add a software-based accumulation renderbuffer to the given framebuffer. 1940 * This is a helper routine for device drivers when creating a 1941 * window system framebuffer (not a user-created render/framebuffer). 1942 * Once this function is called, you can basically forget about this 1943 * renderbuffer; core Mesa will handle all the buffer management and 1944 * rendering! 1945 */ 1946GLboolean 1947_mesa_add_accum_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb, 1948 GLuint redBits, GLuint greenBits, 1949 GLuint blueBits, GLuint alphaBits) 1950{ 1951 struct gl_renderbuffer *rb; 1952 1953 if (redBits > 16 || greenBits > 16 || blueBits > 16 || alphaBits > 16) { 1954 _mesa_problem(ctx, 1955 "Unsupported accumBits in _mesa_add_accum_renderbuffer"); 1956 return GL_FALSE; 1957 } 1958 1959 assert(fb->Attachment[BUFFER_ACCUM].Renderbuffer == NULL); 1960 1961 rb = _mesa_new_renderbuffer(ctx, 0); 1962 if (!rb) { 1963 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer"); 1964 return GL_FALSE; 1965 } 1966 1967 rb->_ActualFormat = GL_RGBA16; 1968 rb->InternalFormat = GL_RGBA16; 1969 rb->AllocStorage = _mesa_soft_renderbuffer_storage; 1970 _mesa_add_renderbuffer(fb, BUFFER_ACCUM, rb); 1971 1972 return GL_TRUE; 1973} 1974 1975 1976 1977/** 1978 * Add a software-based accumulation renderbuffer to the given framebuffer. 1979 * This is a helper routine for device drivers when creating a 1980 * window system framebuffer (not a user-created render/framebuffer). 1981 * Once this function is called, you can basically forget about this 1982 * renderbuffer; core Mesa will handle all the buffer management and 1983 * rendering! 1984 * 1985 * NOTE: color-index aux buffers not supported. 1986 */ 1987GLboolean 1988_mesa_add_aux_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb, 1989 GLuint colorBits, GLuint numBuffers) 1990{ 1991 GLuint i; 1992 1993 if (colorBits > 16) { 1994 _mesa_problem(ctx, 1995 "Unsupported accumBits in _mesa_add_aux_renderbuffers"); 1996 return GL_FALSE; 1997 } 1998 1999 assert(numBuffers < MAX_AUX_BUFFERS); 2000 2001 for (i = 0; i < numBuffers; i++) { 2002 struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, 0); 2003 2004 assert(fb->Attachment[BUFFER_AUX0 + i].Renderbuffer == NULL); 2005 2006 if (!rb) { 2007 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer"); 2008 return GL_FALSE; 2009 } 2010 2011 if (colorBits <= 8) { 2012 rb->_ActualFormat = GL_RGBA8; 2013 } 2014 else { 2015 rb->_ActualFormat = GL_RGBA16; 2016 } 2017 rb->InternalFormat = rb->_ActualFormat; 2018 2019 rb->AllocStorage = _mesa_soft_renderbuffer_storage; 2020 _mesa_add_renderbuffer(fb, BUFFER_AUX0 + i, rb); 2021 } 2022 return GL_TRUE; 2023} 2024 2025 2026/** 2027 * Create/attach software-based renderbuffers to the given framebuffer. 2028 * This is a helper routine for device drivers. Drivers can just as well 2029 * call the individual _mesa_add_*_renderbuffer() routines directly. 2030 */ 2031void 2032_mesa_add_soft_renderbuffers(struct gl_framebuffer *fb, 2033 GLboolean color, 2034 GLboolean depth, 2035 GLboolean stencil, 2036 GLboolean accum, 2037 GLboolean alpha, 2038 GLboolean aux) 2039{ 2040 GLboolean frontLeft = GL_TRUE; 2041 GLboolean backLeft = fb->Visual.doubleBufferMode; 2042 GLboolean frontRight = fb->Visual.stereoMode; 2043 GLboolean backRight = fb->Visual.stereoMode && fb->Visual.doubleBufferMode; 2044 2045 if (color) { 2046 if (fb->Visual.rgbMode) { 2047 assert(fb->Visual.redBits == fb->Visual.greenBits); 2048 assert(fb->Visual.redBits == fb->Visual.blueBits); 2049 _mesa_add_color_renderbuffers(NULL, fb, 2050 fb->Visual.redBits, 2051 fb->Visual.alphaBits, 2052 frontLeft, backLeft, 2053 frontRight, backRight); 2054 } 2055 else { 2056 _mesa_add_color_index_renderbuffers(NULL, fb, 2057 fb->Visual.indexBits, 2058 frontLeft, backLeft, 2059 frontRight, backRight); 2060 } 2061 } 2062 2063 if (depth) { 2064 assert(fb->Visual.depthBits > 0); 2065 _mesa_add_depth_renderbuffer(NULL, fb, fb->Visual.depthBits); 2066 } 2067 2068 if (stencil) { 2069 assert(fb->Visual.stencilBits > 0); 2070 _mesa_add_stencil_renderbuffer(NULL, fb, fb->Visual.stencilBits); 2071 } 2072 2073 if (accum) { 2074 assert(fb->Visual.rgbMode); 2075 assert(fb->Visual.accumRedBits > 0); 2076 assert(fb->Visual.accumGreenBits > 0); 2077 assert(fb->Visual.accumBlueBits > 0); 2078 _mesa_add_accum_renderbuffer(NULL, fb, 2079 fb->Visual.accumRedBits, 2080 fb->Visual.accumGreenBits, 2081 fb->Visual.accumBlueBits, 2082 fb->Visual.accumAlphaBits); 2083 } 2084 2085 if (aux) { 2086 assert(fb->Visual.rgbMode); 2087 assert(fb->Visual.numAuxBuffers > 0); 2088 _mesa_add_aux_renderbuffers(NULL, fb, fb->Visual.redBits, 2089 fb->Visual.numAuxBuffers); 2090 } 2091 2092 if (alpha) { 2093 assert(fb->Visual.rgbMode); 2094 assert(fb->Visual.alphaBits > 0); 2095 _mesa_add_alpha_renderbuffers(NULL, fb, fb->Visual.alphaBits, 2096 frontLeft, backLeft, 2097 frontRight, backRight); 2098 } 2099 2100#if 0 2101 if (multisample) { 2102 /* maybe someday */ 2103 } 2104#endif 2105} 2106 2107 2108/** 2109 * Attach a renderbuffer to a framebuffer. 2110 */ 2111void 2112_mesa_add_renderbuffer(struct gl_framebuffer *fb, 2113 GLuint bufferName, struct gl_renderbuffer *rb) 2114{ 2115 assert(fb); 2116 assert(rb); 2117 assert(bufferName < BUFFER_COUNT); 2118 2119 /* There should be no previous renderbuffer on this attachment point, 2120 * with the exception of depth/stencil since the same renderbuffer may 2121 * be used for both. 2122 */ 2123 assert(bufferName == BUFFER_DEPTH || 2124 bufferName == BUFFER_STENCIL || 2125 fb->Attachment[bufferName].Renderbuffer == NULL); 2126 2127 /* winsys vs. user-created buffer cross check */ 2128 if (fb->Name) { 2129 assert(rb->Name); 2130 } 2131 else { 2132 assert(!rb->Name); 2133 } 2134 2135 /* If Mesa's compiled with deep color channels (16 or 32 bits / channel) 2136 * and the device driver is expecting 8-bit values (GLubyte), we can 2137 * use a "renderbuffer adaptor/wrapper" to do the necessary conversions. 2138 */ 2139 if (rb->_BaseFormat == GL_RGBA) { 2140 if (CHAN_BITS == 16 && rb->DataType == GL_UNSIGNED_BYTE) { 2141 GET_CURRENT_CONTEXT(ctx); 2142 rb = _mesa_new_renderbuffer_16wrap8(ctx, rb); 2143 } 2144 else if (CHAN_BITS == 32 && rb->DataType == GL_UNSIGNED_BYTE) { 2145 GET_CURRENT_CONTEXT(ctx); 2146 rb = _mesa_new_renderbuffer_32wrap8(ctx, rb); 2147 } 2148 else if (CHAN_BITS == 32 && rb->DataType == GL_UNSIGNED_SHORT) { 2149 GET_CURRENT_CONTEXT(ctx); 2150 rb = _mesa_new_renderbuffer_32wrap16(ctx, rb); 2151 } 2152 } 2153 2154 fb->Attachment[bufferName].Type = GL_RENDERBUFFER_EXT; 2155 fb->Attachment[bufferName].Complete = GL_TRUE; 2156 _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer, rb); 2157} 2158 2159 2160/** 2161 * Remove the named renderbuffer from the given framebuffer. 2162 */ 2163void 2164_mesa_remove_renderbuffer(struct gl_framebuffer *fb, GLuint bufferName) 2165{ 2166 struct gl_renderbuffer *rb; 2167 2168 assert(bufferName < BUFFER_COUNT); 2169 2170 rb = fb->Attachment[bufferName].Renderbuffer; 2171 if (!rb) 2172 return; 2173 2174 _mesa_reference_renderbuffer(&rb, NULL); 2175 2176 fb->Attachment[bufferName].Renderbuffer = NULL; 2177} 2178 2179 2180/** 2181 * Set *ptr to point to rb. If *ptr points to another renderbuffer, 2182 * dereference that buffer first. The new renderbuffer's refcount will 2183 * be incremented. The old renderbuffer's refcount will be decremented. 2184 */ 2185void 2186_mesa_reference_renderbuffer(struct gl_renderbuffer **ptr, 2187 struct gl_renderbuffer *rb) 2188{ 2189 assert(ptr); 2190 if (*ptr == rb) { 2191 /* no change */ 2192 return; 2193 } 2194 2195 if (*ptr) { 2196 /* Unreference the old renderbuffer */ 2197 GLboolean deleteFlag = GL_FALSE; 2198 struct gl_renderbuffer *oldRb = *ptr; 2199 2200 assert(oldRb->Magic == RB_MAGIC); 2201 _glthread_LOCK_MUTEX(oldRb->Mutex); 2202 assert(oldRb->Magic == RB_MAGIC); 2203 ASSERT(oldRb->RefCount > 0); 2204 oldRb->RefCount--; 2205 /*printf("RB DECR %p (%d) to %d\n", (void*) oldRb, oldRb->Name, oldRb->RefCount);*/ 2206 deleteFlag = (oldRb->RefCount == 0); 2207 _glthread_UNLOCK_MUTEX(oldRb->Mutex); 2208 2209 if (deleteFlag) { 2210 oldRb->Magic = 0; /* now invalid memory! */ 2211 oldRb->Delete(oldRb); 2212 } 2213 2214 *ptr = NULL; 2215 } 2216 assert(!*ptr); 2217 2218 if (rb) { 2219 assert(rb->Magic == RB_MAGIC); 2220 /* reference new renderbuffer */ 2221 _glthread_LOCK_MUTEX(rb->Mutex); 2222 rb->RefCount++; 2223 /*printf("RB INCR %p (%d) to %d\n", (void*) rb, rb->Name, rb->RefCount);*/ 2224 _glthread_UNLOCK_MUTEX(rb->Mutex); 2225 *ptr = rb; 2226 } 2227} 2228 2229 2230/** 2231 * Create a new combined depth/stencil renderbuffer for implementing 2232 * the GL_EXT_packed_depth_stencil extension. 2233 * \return new depth/stencil renderbuffer 2234 */ 2235struct gl_renderbuffer * 2236_mesa_new_depthstencil_renderbuffer(GLcontext *ctx, GLuint name) 2237{ 2238 struct gl_renderbuffer *dsrb; 2239 2240 dsrb = _mesa_new_renderbuffer(ctx, name); 2241 if (!dsrb) 2242 return NULL; 2243 2244 /* init fields not covered by _mesa_new_renderbuffer() */ 2245 dsrb->InternalFormat = GL_DEPTH24_STENCIL8_EXT; 2246 dsrb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT; 2247 dsrb->AllocStorage = _mesa_soft_renderbuffer_storage; 2248 2249 return dsrb; 2250} 2251