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