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