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