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