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