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