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