renderbuffer.c revision 45e76d2665b38ba3787548310efc59e969124c01
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
70static void *
71get_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
84static void
85get_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   _mesa_memcpy(values, src, count * sizeof(GLubyte));
91}
92
93
94static void
95get_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
108static void
109put_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      _mesa_memcpy(dst, values, count * sizeof(GLubyte));
125   }
126}
127
128
129static void
130put_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
153static void
154put_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
170static void
171put_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
192static void *
193get_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
204static void
205get_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   _mesa_memcpy(values, src, count * sizeof(GLushort));
211}
212
213
214static void
215get_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
228static void
229put_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      _mesa_memcpy(dst, src, count * sizeof(GLushort));
245   }
246}
247
248
249static void
250put_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
273static void
274put_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
290static void
291put_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
321static void *
322get_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
333static void
334get_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   _mesa_memcpy(values, src, count * sizeof(GLuint));
341}
342
343
344static void
345get_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
359static void
360put_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      _mesa_memcpy(dst, src, count * sizeof(GLuint));
377   }
378}
379
380
381static void
382put_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
406static void
407put_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
424static void
425put_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
449static void *
450get_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
461static void
462get_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
479static void
480get_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
498static void
499put_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
518static void
519put_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
538static void
539put_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      _mesa_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
566static void
567put_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
587static void
588put_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
615static void *
616get_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
627static void
628get_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   _mesa_memcpy(values, src, 4 * count * sizeof(GLubyte));
635}
636
637
638static void
639get_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
654static void
655put_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      _mesa_memcpy(dst, src, 4 * count * sizeof(GLubyte));
673   }
674}
675
676
677static void
678put_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
698static void
699put_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      _mesa_bzero(dst, 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
731static void
732put_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
750static void
751put_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
774static void *
775get_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
785static void
786get_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   _mesa_memcpy(values, src, 4 * count * sizeof(GLshort));
792}
793
794
795static void
796get_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
810static void
811put_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      _mesa_memcpy(dst, src, 4 * count * sizeof(GLushort));
830   }
831}
832
833
834static void
835put_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      _mesa_memcpy(dst, src, 4 * count * sizeof(GLushort));
855   }
856}
857
858
859static void
860put_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      _mesa_bzero(dst, 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
887static void
888put_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
907static void
908put_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 */
945GLboolean
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   case GL_DEPTH_COMPONENT32:
1056      rb->DataType = GL_UNSIGNED_INT;
1057      rb->GetPointer = get_pointer_uint;
1058      rb->GetRow = get_row_uint;
1059      rb->GetValues = get_values_uint;
1060      rb->PutRow = put_row_uint;
1061      rb->PutRowRGB = NULL;
1062      rb->PutMonoRow = put_mono_row_uint;
1063      rb->PutValues = put_values_uint;
1064      rb->PutMonoValues = put_mono_values_uint;
1065      rb->Format = MESA_FORMAT_Z32;
1066      pixelSize = sizeof(GLuint);
1067      break;
1068   case GL_DEPTH_STENCIL_EXT:
1069   case GL_DEPTH24_STENCIL8_EXT:
1070      rb->Format = MESA_FORMAT_Z24_S8;
1071      rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
1072      rb->GetPointer = get_pointer_uint;
1073      rb->GetRow = get_row_uint;
1074      rb->GetValues = get_values_uint;
1075      rb->PutRow = put_row_uint;
1076      rb->PutRowRGB = NULL;
1077      rb->PutMonoRow = put_mono_row_uint;
1078      rb->PutValues = put_values_uint;
1079      rb->PutMonoValues = put_mono_values_uint;
1080      pixelSize = sizeof(GLuint);
1081      break;
1082   case GL_COLOR_INDEX8_EXT:
1083   case GL_COLOR_INDEX16_EXT:
1084   case COLOR_INDEX32:
1085      rb->Format = MESA_FORMAT_CI8;
1086      rb->DataType = GL_UNSIGNED_BYTE;
1087      rb->GetPointer = get_pointer_ubyte;
1088      rb->GetRow = get_row_ubyte;
1089      rb->GetValues = get_values_ubyte;
1090      rb->PutRow = put_row_ubyte;
1091      rb->PutRowRGB = NULL;
1092      rb->PutMonoRow = put_mono_row_ubyte;
1093      rb->PutValues = put_values_ubyte;
1094      rb->PutMonoValues = put_mono_values_ubyte;
1095      pixelSize = sizeof(GLubyte);
1096      break;
1097   default:
1098      _mesa_problem(ctx, "Bad internalFormat in _mesa_soft_renderbuffer_storage");
1099      return GL_FALSE;
1100   }
1101
1102   ASSERT(rb->DataType);
1103   ASSERT(rb->GetPointer);
1104   ASSERT(rb->GetRow);
1105   ASSERT(rb->GetValues);
1106   ASSERT(rb->PutRow);
1107   ASSERT(rb->PutMonoRow);
1108   ASSERT(rb->PutValues);
1109   ASSERT(rb->PutMonoValues);
1110
1111   /* free old buffer storage */
1112   if (rb->Data) {
1113      _mesa_free(rb->Data);
1114      rb->Data = NULL;
1115   }
1116
1117   if (width > 0 && height > 0) {
1118      /* allocate new buffer storage */
1119      rb->Data = malloc(width * height * pixelSize);
1120
1121      if (rb->Data == NULL) {
1122         rb->Width = 0;
1123         rb->Height = 0;
1124         _mesa_error(ctx, GL_OUT_OF_MEMORY,
1125                     "software renderbuffer allocation (%d x %d x %d)",
1126                     width, height, pixelSize);
1127         return GL_FALSE;
1128      }
1129   }
1130
1131   rb->Width = width;
1132   rb->Height = height;
1133   rb->_BaseFormat = _mesa_base_fbo_format(ctx, rb->InternalFormat);
1134
1135   return GL_TRUE;
1136}
1137
1138
1139
1140/**********************************************************************/
1141/**********************************************************************/
1142/**********************************************************************/
1143
1144
1145/**
1146 * Here we utilize the gl_renderbuffer->Wrapper field to put an alpha
1147 * buffer wrapper around an existing RGB renderbuffer (hw or sw).
1148 *
1149 * When PutRow is called (for example), we store the alpha values in
1150 * this buffer, then pass on the PutRow call to the wrapped RGB
1151 * buffer.
1152 */
1153
1154
1155static GLboolean
1156alloc_storage_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb,
1157                     GLenum internalFormat, GLuint width, GLuint height)
1158{
1159   ASSERT(arb != arb->Wrapped);
1160   ASSERT(arb->Format == MESA_FORMAT_A8);
1161
1162   /* first, pass the call to the wrapped RGB buffer */
1163   if (!arb->Wrapped->AllocStorage(ctx, arb->Wrapped, internalFormat,
1164                                  width, height)) {
1165      return GL_FALSE;
1166   }
1167
1168   /* next, resize my alpha buffer */
1169   if (arb->Data) {
1170      _mesa_free(arb->Data);
1171   }
1172
1173   arb->Data = _mesa_malloc(width * height * sizeof(GLubyte));
1174   if (arb->Data == NULL) {
1175      arb->Width = 0;
1176      arb->Height = 0;
1177      _mesa_error(ctx, GL_OUT_OF_MEMORY, "software alpha buffer allocation");
1178      return GL_FALSE;
1179   }
1180
1181   arb->Width = width;
1182   arb->Height = height;
1183
1184   return GL_TRUE;
1185}
1186
1187
1188/**
1189 * Delete an alpha_renderbuffer object, as well as the wrapped RGB buffer.
1190 */
1191static void
1192delete_renderbuffer_alpha8(struct gl_renderbuffer *arb)
1193{
1194   if (arb->Data) {
1195      _mesa_free(arb->Data);
1196   }
1197   ASSERT(arb->Wrapped);
1198   ASSERT(arb != arb->Wrapped);
1199   arb->Wrapped->Delete(arb->Wrapped);
1200   arb->Wrapped = NULL;
1201   _mesa_free(arb);
1202}
1203
1204
1205static void *
1206get_pointer_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb,
1207                   GLint x, GLint y)
1208{
1209   return NULL;   /* don't allow direct access! */
1210}
1211
1212
1213static void
1214get_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1215               GLint x, GLint y, void *values)
1216{
1217   /* NOTE: 'values' is RGBA format! */
1218   const GLubyte *src = (const GLubyte *) arb->Data + y * arb->Width + x;
1219   GLubyte *dst = (GLubyte *) values;
1220   GLuint i;
1221   ASSERT(arb != arb->Wrapped);
1222   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1223   /* first, pass the call to the wrapped RGB buffer */
1224   arb->Wrapped->GetRow(ctx, arb->Wrapped, count, x, y, values);
1225   /* second, fill in alpha values from this buffer! */
1226   for (i = 0; i < count; i++) {
1227      dst[i * 4 + 3] = src[i];
1228   }
1229}
1230
1231
1232static void
1233get_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1234                  const GLint x[], const GLint y[], void *values)
1235{
1236   GLubyte *dst = (GLubyte *) values;
1237   GLuint i;
1238   ASSERT(arb != arb->Wrapped);
1239   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1240   /* first, pass the call to the wrapped RGB buffer */
1241   arb->Wrapped->GetValues(ctx, arb->Wrapped, count, x, y, values);
1242   /* second, fill in alpha values from this buffer! */
1243   for (i = 0; i < count; i++) {
1244      const GLubyte *src = (GLubyte *) arb->Data + y[i] * arb->Width + x[i];
1245      dst[i * 4 + 3] = *src;
1246   }
1247}
1248
1249
1250static void
1251put_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1252               GLint x, GLint y, const void *values, const GLubyte *mask)
1253{
1254   const GLubyte *src = (const GLubyte *) values;
1255   GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x;
1256   GLuint i;
1257   ASSERT(arb != arb->Wrapped);
1258   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1259   /* first, pass the call to the wrapped RGB buffer */
1260   arb->Wrapped->PutRow(ctx, arb->Wrapped, count, x, y, values, mask);
1261   /* second, store alpha in our buffer */
1262   for (i = 0; i < count; i++) {
1263      if (!mask || mask[i]) {
1264         dst[i] = src[i * 4 + 3];
1265      }
1266   }
1267}
1268
1269
1270static void
1271put_row_rgb_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1272                   GLint x, GLint y, const void *values, const GLubyte *mask)
1273{
1274   const GLubyte *src = (const GLubyte *) values;
1275   GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x;
1276   GLuint i;
1277   ASSERT(arb != arb->Wrapped);
1278   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1279   /* first, pass the call to the wrapped RGB buffer */
1280   arb->Wrapped->PutRowRGB(ctx, arb->Wrapped, count, x, y, values, mask);
1281   /* second, store alpha in our buffer */
1282   for (i = 0; i < count; i++) {
1283      if (!mask || mask[i]) {
1284         dst[i] = src[i * 4 + 3];
1285      }
1286   }
1287}
1288
1289
1290static void
1291put_mono_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1292                    GLint x, GLint y, const void *value, const GLubyte *mask)
1293{
1294   const GLubyte val = ((const GLubyte *) value)[3];
1295   GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x;
1296   ASSERT(arb != arb->Wrapped);
1297   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1298   /* first, pass the call to the wrapped RGB buffer */
1299   arb->Wrapped->PutMonoRow(ctx, arb->Wrapped, count, x, y, value, mask);
1300   /* second, store alpha in our buffer */
1301   if (mask) {
1302      GLuint i;
1303      for (i = 0; i < count; i++) {
1304         if (mask[i]) {
1305            dst[i] = val;
1306         }
1307      }
1308   }
1309   else {
1310      _mesa_memset(dst, val, count);
1311   }
1312}
1313
1314
1315static void
1316put_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1317                  const GLint x[], const GLint y[],
1318                  const void *values, const GLubyte *mask)
1319{
1320   const GLubyte *src = (const GLubyte *) values;
1321   GLuint i;
1322   ASSERT(arb != arb->Wrapped);
1323   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1324   /* first, pass the call to the wrapped RGB buffer */
1325   arb->Wrapped->PutValues(ctx, arb->Wrapped, count, x, y, values, mask);
1326   /* second, store alpha in our buffer */
1327   for (i = 0; i < count; i++) {
1328      if (!mask || mask[i]) {
1329         GLubyte *dst = (GLubyte *) arb->Data + y[i] * arb->Width + x[i];
1330         *dst = src[i * 4 + 3];
1331      }
1332   }
1333}
1334
1335
1336static void
1337put_mono_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb,
1338                       GLuint count, const GLint x[], const GLint y[],
1339                       const void *value, const GLubyte *mask)
1340{
1341   const GLubyte val = ((const GLubyte *) value)[3];
1342   GLuint i;
1343   ASSERT(arb != arb->Wrapped);
1344   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1345   /* first, pass the call to the wrapped RGB buffer */
1346   arb->Wrapped->PutValues(ctx, arb->Wrapped, count, x, y, value, mask);
1347   /* second, store alpha in our buffer */
1348   for (i = 0; i < count; i++) {
1349      if (!mask || mask[i]) {
1350         GLubyte *dst = (GLubyte *) arb->Data + y[i] * arb->Width + x[i];
1351         *dst = val;
1352      }
1353   }
1354}
1355
1356
1357static void
1358copy_buffer_alpha8(struct gl_renderbuffer* dst, struct gl_renderbuffer* src)
1359{
1360   ASSERT(dst->Format == MESA_FORMAT_A8);
1361   ASSERT(src->Format == MESA_FORMAT_A8);
1362   ASSERT(dst->Width == src->Width);
1363   ASSERT(dst->Height == src->Height);
1364
1365   _mesa_memcpy(dst->Data, src->Data, dst->Width * dst->Height * sizeof(GLubyte));
1366}
1367
1368
1369/**********************************************************************/
1370/**********************************************************************/
1371/**********************************************************************/
1372
1373
1374/**
1375 * Default GetPointer routine.  Always return NULL to indicate that
1376 * direct buffer access is not supported.
1377 */
1378static void *
1379nop_get_pointer(GLcontext *ctx, struct gl_renderbuffer *rb, GLint x, GLint y)
1380{
1381   return NULL;
1382}
1383
1384
1385/**
1386 * Initialize the fields of a gl_renderbuffer to default values.
1387 */
1388void
1389_mesa_init_renderbuffer(struct gl_renderbuffer *rb, GLuint name)
1390{
1391   _glthread_INIT_MUTEX(rb->Mutex);
1392
1393   rb->Magic = RB_MAGIC;
1394   rb->ClassID = 0;
1395   rb->Name = name;
1396   rb->RefCount = 0;
1397   rb->Delete = _mesa_delete_renderbuffer;
1398
1399   /* The rest of these should be set later by the caller of this function or
1400    * the AllocStorage method:
1401    */
1402   rb->AllocStorage = NULL;
1403
1404   rb->Width = 0;
1405   rb->Height = 0;
1406   rb->InternalFormat = GL_NONE;
1407   rb->Format = MESA_FORMAT_NONE;
1408
1409   rb->DataType = GL_NONE;
1410   rb->Data = NULL;
1411
1412   /* Point back to ourself so that we don't have to check for Wrapped==NULL
1413    * all over the drivers.
1414    */
1415   rb->Wrapped = rb;
1416
1417   rb->GetPointer = nop_get_pointer;
1418   rb->GetRow = NULL;
1419   rb->GetValues = NULL;
1420   rb->PutRow = NULL;
1421   rb->PutRowRGB = NULL;
1422   rb->PutMonoRow = NULL;
1423   rb->PutValues = NULL;
1424   rb->PutMonoValues = NULL;
1425}
1426
1427
1428/**
1429 * Allocate a new gl_renderbuffer object.  This can be used for user-created
1430 * renderbuffers or window-system renderbuffers.
1431 */
1432struct gl_renderbuffer *
1433_mesa_new_renderbuffer(GLcontext *ctx, GLuint name)
1434{
1435   struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer);
1436   if (rb) {
1437      _mesa_init_renderbuffer(rb, name);
1438   }
1439   return rb;
1440}
1441
1442
1443/**
1444 * Delete a gl_framebuffer.
1445 * This is the default function for renderbuffer->Delete().
1446 */
1447void
1448_mesa_delete_renderbuffer(struct gl_renderbuffer *rb)
1449{
1450   if (rb->Data) {
1451      _mesa_free(rb->Data);
1452   }
1453   _mesa_free(rb);
1454}
1455
1456
1457/**
1458 * Allocate a software-based renderbuffer.  This is called via the
1459 * ctx->Driver.NewRenderbuffer() function when the user creates a new
1460 * renderbuffer.
1461 * This would not be used for hardware-based renderbuffers.
1462 */
1463struct gl_renderbuffer *
1464_mesa_new_soft_renderbuffer(GLcontext *ctx, GLuint name)
1465{
1466   struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, name);
1467   if (rb) {
1468      rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1469      /* Normally, one would setup the PutRow, GetRow, etc functions here.
1470       * But we're doing that in the _mesa_soft_renderbuffer_storage() function
1471       * instead.
1472       */
1473   }
1474   return rb;
1475}
1476
1477
1478/**
1479 * Add software-based color renderbuffers to the given framebuffer.
1480 * This is a helper routine for device drivers when creating a
1481 * window system framebuffer (not a user-created render/framebuffer).
1482 * Once this function is called, you can basically forget about this
1483 * renderbuffer; core Mesa will handle all the buffer management and
1484 * rendering!
1485 */
1486GLboolean
1487_mesa_add_color_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
1488                              GLuint rgbBits, GLuint alphaBits,
1489                              GLboolean frontLeft, GLboolean backLeft,
1490                              GLboolean frontRight, GLboolean backRight)
1491{
1492   GLuint b;
1493
1494   if (rgbBits > 16 || alphaBits > 16) {
1495      _mesa_problem(ctx,
1496                    "Unsupported bit depth in _mesa_add_color_renderbuffers");
1497      return GL_FALSE;
1498   }
1499
1500   assert(MAX_COLOR_ATTACHMENTS >= 4);
1501
1502   for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
1503      struct gl_renderbuffer *rb;
1504
1505      if (b == BUFFER_FRONT_LEFT && !frontLeft)
1506         continue;
1507      else if (b == BUFFER_BACK_LEFT && !backLeft)
1508         continue;
1509      else if (b == BUFFER_FRONT_RIGHT && !frontRight)
1510         continue;
1511      else if (b == BUFFER_BACK_RIGHT && !backRight)
1512         continue;
1513
1514      assert(fb->Attachment[b].Renderbuffer == NULL);
1515
1516      rb = _mesa_new_renderbuffer(ctx, 0);
1517      if (!rb) {
1518         _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer");
1519         return GL_FALSE;
1520      }
1521
1522      if (rgbBits <= 8) {
1523         if (alphaBits)
1524            rb->Format = MESA_FORMAT_RGBA8888;
1525         else
1526            rb->Format = MESA_FORMAT_RGB888;
1527      }
1528      else {
1529         assert(rgbBits <= 16);
1530         rb->Format = MESA_FORMAT_NONE; /*XXX RGBA16;*/
1531      }
1532      rb->InternalFormat = GL_RGBA;
1533
1534      rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1535      _mesa_add_renderbuffer(fb, b, rb);
1536   }
1537
1538   return GL_TRUE;
1539}
1540
1541
1542/**
1543 * Add software-based color index renderbuffers to the given framebuffer.
1544 * This is a helper routine for device drivers when creating a
1545 * window system framebuffer (not a user-created render/framebuffer).
1546 * Once this function is called, you can basically forget about this
1547 * renderbuffer; core Mesa will handle all the buffer management and
1548 * rendering!
1549 */
1550GLboolean
1551_mesa_add_color_index_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
1552                                    GLuint indexBits,
1553                                    GLboolean frontLeft, GLboolean backLeft,
1554                                    GLboolean frontRight, GLboolean backRight)
1555{
1556   GLuint b;
1557
1558   if (indexBits > 8) {
1559      _mesa_problem(ctx,
1560                "Unsupported bit depth in _mesa_add_color_index_renderbuffers");
1561      return GL_FALSE;
1562   }
1563
1564   assert(MAX_COLOR_ATTACHMENTS >= 4);
1565
1566   for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
1567      struct gl_renderbuffer *rb;
1568
1569      if (b == BUFFER_FRONT_LEFT && !frontLeft)
1570         continue;
1571      else if (b == BUFFER_BACK_LEFT && !backLeft)
1572         continue;
1573      else if (b == BUFFER_FRONT_RIGHT && !frontRight)
1574         continue;
1575      else if (b == BUFFER_BACK_RIGHT && !backRight)
1576         continue;
1577
1578      assert(fb->Attachment[b].Renderbuffer == NULL);
1579
1580      rb = _mesa_new_renderbuffer(ctx, 0);
1581      if (!rb) {
1582         _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer");
1583         return GL_FALSE;
1584      }
1585
1586      assert(indexBits <= 8);
1587      rb->Format = MESA_FORMAT_CI8;
1588      rb->InternalFormat = GL_COLOR_INDEX;
1589
1590      rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1591      _mesa_add_renderbuffer(fb, b, rb);
1592   }
1593
1594   return GL_TRUE;
1595}
1596
1597
1598/**
1599 * Add software-based alpha renderbuffers to the given framebuffer.
1600 * This is a helper routine for device drivers when creating a
1601 * window system framebuffer (not a user-created render/framebuffer).
1602 * Once this function is called, you can basically forget about this
1603 * renderbuffer; core Mesa will handle all the buffer management and
1604 * rendering!
1605 */
1606GLboolean
1607_mesa_add_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
1608                              GLuint alphaBits,
1609                              GLboolean frontLeft, GLboolean backLeft,
1610                              GLboolean frontRight, GLboolean backRight)
1611{
1612   GLuint b;
1613
1614   /* for window system framebuffers only! */
1615   assert(fb->Name == 0);
1616
1617   if (alphaBits > 8) {
1618      _mesa_problem(ctx,
1619                    "Unsupported bit depth in _mesa_add_alpha_renderbuffers");
1620      return GL_FALSE;
1621   }
1622
1623   assert(MAX_COLOR_ATTACHMENTS >= 4);
1624
1625   /* Wrap each of the RGB color buffers with an alpha renderbuffer.
1626    */
1627   for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
1628      struct gl_renderbuffer *arb;
1629
1630      if (b == BUFFER_FRONT_LEFT && !frontLeft)
1631         continue;
1632      else if (b == BUFFER_BACK_LEFT && !backLeft)
1633         continue;
1634      else if (b == BUFFER_FRONT_RIGHT && !frontRight)
1635         continue;
1636      else if (b == BUFFER_BACK_RIGHT && !backRight)
1637         continue;
1638
1639      /* the RGB buffer to wrap must already exist!! */
1640      assert(fb->Attachment[b].Renderbuffer);
1641
1642      /* only GLubyte supported for now */
1643      assert(fb->Attachment[b].Renderbuffer->DataType == GL_UNSIGNED_BYTE);
1644
1645      /* allocate alpha renderbuffer */
1646      arb = _mesa_new_renderbuffer(ctx, 0);
1647      if (!arb) {
1648         _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating alpha buffer");
1649         return GL_FALSE;
1650      }
1651
1652      /* wrap the alpha renderbuffer around the RGB renderbuffer */
1653      arb->Wrapped = fb->Attachment[b].Renderbuffer;
1654
1655      /* Set up my alphabuffer fields and plug in my functions.
1656       * The functions will put/get the alpha values from/to RGBA arrays
1657       * and then call the wrapped buffer's functions to handle the RGB
1658       * values.
1659       */
1660      arb->InternalFormat = arb->Wrapped->InternalFormat;
1661      arb->Format         = MESA_FORMAT_A8;
1662      arb->DataType       = arb->Wrapped->DataType;
1663      arb->AllocStorage   = alloc_storage_alpha8;
1664      arb->Delete         = delete_renderbuffer_alpha8;
1665      arb->GetPointer     = get_pointer_alpha8;
1666      arb->GetRow         = get_row_alpha8;
1667      arb->GetValues      = get_values_alpha8;
1668      arb->PutRow         = put_row_alpha8;
1669      arb->PutRowRGB      = put_row_rgb_alpha8;
1670      arb->PutMonoRow     = put_mono_row_alpha8;
1671      arb->PutValues      = put_values_alpha8;
1672      arb->PutMonoValues  = put_mono_values_alpha8;
1673
1674      /* clear the pointer to avoid assertion/sanity check failure later */
1675      fb->Attachment[b].Renderbuffer = NULL;
1676
1677      /* plug the alpha renderbuffer into the colorbuffer attachment */
1678      _mesa_add_renderbuffer(fb, b, arb);
1679   }
1680
1681   return GL_TRUE;
1682}
1683
1684
1685/**
1686 * For framebuffers that use a software alpha channel wrapper
1687 * created by _mesa_add_alpha_renderbuffer or _mesa_add_soft_renderbuffers,
1688 * copy the back buffer alpha channel into the front buffer alpha channel.
1689 */
1690void
1691_mesa_copy_soft_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb)
1692{
1693   if (fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer &&
1694       fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer)
1695      copy_buffer_alpha8(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer,
1696                         fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
1697
1698
1699   if (fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer &&
1700       fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer)
1701      copy_buffer_alpha8(fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer,
1702                         fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer);
1703}
1704
1705
1706/**
1707 * Add a software-based depth renderbuffer to the given framebuffer.
1708 * This is a helper routine for device drivers when creating a
1709 * window system framebuffer (not a user-created render/framebuffer).
1710 * Once this function is called, you can basically forget about this
1711 * renderbuffer; core Mesa will handle all the buffer management and
1712 * rendering!
1713 */
1714GLboolean
1715_mesa_add_depth_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
1716                             GLuint depthBits)
1717{
1718   struct gl_renderbuffer *rb;
1719
1720   if (depthBits > 32) {
1721      _mesa_problem(ctx,
1722                    "Unsupported depthBits in _mesa_add_depth_renderbuffer");
1723      return GL_FALSE;
1724   }
1725
1726   assert(fb->Attachment[BUFFER_DEPTH].Renderbuffer == NULL);
1727
1728   rb = _mesa_new_renderbuffer(ctx, 0);
1729   if (!rb) {
1730      _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating depth buffer");
1731      return GL_FALSE;
1732   }
1733
1734   if (depthBits <= 16) {
1735      rb->Format = MESA_FORMAT_Z16;
1736      rb->InternalFormat = GL_DEPTH_COMPONENT16;
1737   }
1738   else {
1739      rb->Format = MESA_FORMAT_Z32;
1740      rb->InternalFormat = GL_DEPTH_COMPONENT32;
1741   }
1742
1743   rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1744   _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
1745
1746   return GL_TRUE;
1747}
1748
1749
1750/**
1751 * Add a software-based stencil 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 */
1758GLboolean
1759_mesa_add_stencil_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
1760                               GLuint stencilBits)
1761{
1762   struct gl_renderbuffer *rb;
1763
1764   if (stencilBits > 16) {
1765      _mesa_problem(ctx,
1766                  "Unsupported stencilBits in _mesa_add_stencil_renderbuffer");
1767      return GL_FALSE;
1768   }
1769
1770   assert(fb->Attachment[BUFFER_STENCIL].Renderbuffer == NULL);
1771
1772   rb = _mesa_new_renderbuffer(ctx, 0);
1773   if (!rb) {
1774      _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating stencil buffer");
1775      return GL_FALSE;
1776   }
1777
1778   assert(stencilBits <= 8);
1779   rb->Format = MESA_FORMAT_S8;
1780   rb->InternalFormat = GL_STENCIL_INDEX8;
1781
1782   rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1783   _mesa_add_renderbuffer(fb, BUFFER_STENCIL, rb);
1784
1785   return GL_TRUE;
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 */
1797GLboolean
1798_mesa_add_accum_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
1799                             GLuint redBits, GLuint greenBits,
1800                             GLuint blueBits, GLuint alphaBits)
1801{
1802   struct gl_renderbuffer *rb;
1803
1804   if (redBits > 16 || greenBits > 16 || blueBits > 16 || alphaBits > 16) {
1805      _mesa_problem(ctx,
1806                    "Unsupported accumBits in _mesa_add_accum_renderbuffer");
1807      return GL_FALSE;
1808   }
1809
1810   assert(fb->Attachment[BUFFER_ACCUM].Renderbuffer == NULL);
1811
1812   rb = _mesa_new_renderbuffer(ctx, 0);
1813   if (!rb) {
1814      _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer");
1815      return GL_FALSE;
1816   }
1817
1818   rb->Format = MESA_FORMAT_SIGNED_RGBA_16;
1819   rb->InternalFormat = GL_RGBA16;
1820   rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1821   _mesa_add_renderbuffer(fb, BUFFER_ACCUM, rb);
1822
1823   return GL_TRUE;
1824}
1825
1826
1827
1828/**
1829 * Add a software-based accumulation renderbuffer to the given framebuffer.
1830 * This is a helper routine for device drivers when creating a
1831 * window system framebuffer (not a user-created render/framebuffer).
1832 * Once this function is called, you can basically forget about this
1833 * renderbuffer; core Mesa will handle all the buffer management and
1834 * rendering!
1835 *
1836 * NOTE: color-index aux buffers not supported.
1837 */
1838GLboolean
1839_mesa_add_aux_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
1840                            GLuint colorBits, GLuint numBuffers)
1841{
1842   GLuint i;
1843
1844   if (colorBits > 16) {
1845      _mesa_problem(ctx,
1846                    "Unsupported accumBits in _mesa_add_aux_renderbuffers");
1847      return GL_FALSE;
1848   }
1849
1850   assert(numBuffers < MAX_AUX_BUFFERS);
1851
1852   for (i = 0; i < numBuffers; i++) {
1853      struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, 0);
1854
1855      assert(fb->Attachment[BUFFER_AUX0 + i].Renderbuffer == NULL);
1856
1857      if (!rb) {
1858         _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer");
1859         return GL_FALSE;
1860      }
1861
1862      assert (colorBits <= 8);
1863      rb->Format = MESA_FORMAT_RGBA8888;
1864      rb->InternalFormat = GL_RGBA;
1865
1866      rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1867      _mesa_add_renderbuffer(fb, BUFFER_AUX0 + i, rb);
1868   }
1869   return GL_TRUE;
1870}
1871
1872
1873/**
1874 * Create/attach software-based renderbuffers to the given framebuffer.
1875 * This is a helper routine for device drivers.  Drivers can just as well
1876 * call the individual _mesa_add_*_renderbuffer() routines directly.
1877 */
1878void
1879_mesa_add_soft_renderbuffers(struct gl_framebuffer *fb,
1880                             GLboolean color,
1881                             GLboolean depth,
1882                             GLboolean stencil,
1883                             GLboolean accum,
1884                             GLboolean alpha,
1885                             GLboolean aux)
1886{
1887   GLboolean frontLeft = GL_TRUE;
1888   GLboolean backLeft = fb->Visual.doubleBufferMode;
1889   GLboolean frontRight = fb->Visual.stereoMode;
1890   GLboolean backRight = fb->Visual.stereoMode && fb->Visual.doubleBufferMode;
1891
1892   if (color) {
1893      if (fb->Visual.rgbMode) {
1894         assert(fb->Visual.redBits == fb->Visual.greenBits);
1895         assert(fb->Visual.redBits == fb->Visual.blueBits);
1896         _mesa_add_color_renderbuffers(NULL, fb,
1897                                       fb->Visual.redBits,
1898                                       fb->Visual.alphaBits,
1899                                       frontLeft, backLeft,
1900                                       frontRight, backRight);
1901      }
1902      else {
1903         _mesa_add_color_index_renderbuffers(NULL, fb,
1904                                             fb->Visual.indexBits,
1905                                             frontLeft, backLeft,
1906                                             frontRight, backRight);
1907      }
1908   }
1909
1910   if (depth) {
1911      assert(fb->Visual.depthBits > 0);
1912      _mesa_add_depth_renderbuffer(NULL, fb, fb->Visual.depthBits);
1913   }
1914
1915   if (stencil) {
1916      assert(fb->Visual.stencilBits > 0);
1917      _mesa_add_stencil_renderbuffer(NULL, fb, fb->Visual.stencilBits);
1918   }
1919
1920   if (accum) {
1921      assert(fb->Visual.rgbMode);
1922      assert(fb->Visual.accumRedBits > 0);
1923      assert(fb->Visual.accumGreenBits > 0);
1924      assert(fb->Visual.accumBlueBits > 0);
1925      _mesa_add_accum_renderbuffer(NULL, fb,
1926                                   fb->Visual.accumRedBits,
1927                                   fb->Visual.accumGreenBits,
1928                                   fb->Visual.accumBlueBits,
1929                                   fb->Visual.accumAlphaBits);
1930   }
1931
1932   if (aux) {
1933      assert(fb->Visual.rgbMode);
1934      assert(fb->Visual.numAuxBuffers > 0);
1935      _mesa_add_aux_renderbuffers(NULL, fb, fb->Visual.redBits,
1936                                  fb->Visual.numAuxBuffers);
1937   }
1938
1939   if (alpha) {
1940      assert(fb->Visual.rgbMode);
1941      assert(fb->Visual.alphaBits > 0);
1942      _mesa_add_alpha_renderbuffers(NULL, fb, fb->Visual.alphaBits,
1943                                    frontLeft, backLeft,
1944                                    frontRight, backRight);
1945   }
1946
1947#if 0
1948   if (multisample) {
1949      /* maybe someday */
1950   }
1951#endif
1952}
1953
1954
1955/**
1956 * Attach a renderbuffer to a framebuffer.
1957 */
1958void
1959_mesa_add_renderbuffer(struct gl_framebuffer *fb,
1960                       GLuint bufferName, struct gl_renderbuffer *rb)
1961{
1962   GLenum baseFormat;
1963
1964   assert(fb);
1965   assert(rb);
1966   assert(bufferName < BUFFER_COUNT);
1967
1968   /* There should be no previous renderbuffer on this attachment point,
1969    * with the exception of depth/stencil since the same renderbuffer may
1970    * be used for both.
1971    */
1972   assert(bufferName == BUFFER_DEPTH ||
1973          bufferName == BUFFER_STENCIL ||
1974          fb->Attachment[bufferName].Renderbuffer == NULL);
1975
1976   /* winsys vs. user-created buffer cross check */
1977   if (fb->Name) {
1978      assert(rb->Name);
1979   }
1980   else {
1981      assert(!rb->Name);
1982   }
1983
1984   /* If Mesa's compiled with deep color channels (16 or 32 bits / channel)
1985    * and the device driver is expecting 8-bit values (GLubyte), we can
1986    * use a "renderbuffer adaptor/wrapper" to do the necessary conversions.
1987    */
1988   baseFormat = _mesa_get_format_base_format(rb->Format);
1989   if (baseFormat == GL_RGBA) {
1990      if (CHAN_BITS == 16 && rb->DataType == GL_UNSIGNED_BYTE) {
1991         GET_CURRENT_CONTEXT(ctx);
1992         rb = _mesa_new_renderbuffer_16wrap8(ctx, rb);
1993      }
1994      else if (CHAN_BITS == 32 && rb->DataType == GL_UNSIGNED_BYTE) {
1995         GET_CURRENT_CONTEXT(ctx);
1996         rb = _mesa_new_renderbuffer_32wrap8(ctx, rb);
1997      }
1998      else if (CHAN_BITS == 32 && rb->DataType == GL_UNSIGNED_SHORT) {
1999         GET_CURRENT_CONTEXT(ctx);
2000         rb = _mesa_new_renderbuffer_32wrap16(ctx, rb);
2001      }
2002   }
2003
2004   fb->Attachment[bufferName].Type = GL_RENDERBUFFER_EXT;
2005   fb->Attachment[bufferName].Complete = GL_TRUE;
2006   _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer, rb);
2007}
2008
2009
2010/**
2011 * Remove the named renderbuffer from the given framebuffer.
2012 */
2013void
2014_mesa_remove_renderbuffer(struct gl_framebuffer *fb, GLuint bufferName)
2015{
2016   struct gl_renderbuffer *rb;
2017
2018   assert(bufferName < BUFFER_COUNT);
2019
2020   rb = fb->Attachment[bufferName].Renderbuffer;
2021   if (!rb)
2022      return;
2023
2024   _mesa_reference_renderbuffer(&rb, NULL);
2025
2026   fb->Attachment[bufferName].Renderbuffer = NULL;
2027}
2028
2029
2030/**
2031 * Set *ptr to point to rb.  If *ptr points to another renderbuffer,
2032 * dereference that buffer first.  The new renderbuffer's refcount will
2033 * be incremented.  The old renderbuffer's refcount will be decremented.
2034 */
2035void
2036_mesa_reference_renderbuffer(struct gl_renderbuffer **ptr,
2037                             struct gl_renderbuffer *rb)
2038{
2039   assert(ptr);
2040   if (*ptr == rb) {
2041      /* no change */
2042      return;
2043   }
2044
2045   if (*ptr) {
2046      /* Unreference the old renderbuffer */
2047      GLboolean deleteFlag = GL_FALSE;
2048      struct gl_renderbuffer *oldRb = *ptr;
2049
2050      assert(oldRb->Magic == RB_MAGIC);
2051      _glthread_LOCK_MUTEX(oldRb->Mutex);
2052      assert(oldRb->Magic == RB_MAGIC);
2053      ASSERT(oldRb->RefCount > 0);
2054      oldRb->RefCount--;
2055      /*printf("RB DECR %p (%d) to %d\n", (void*) oldRb, oldRb->Name, oldRb->RefCount);*/
2056      deleteFlag = (oldRb->RefCount == 0);
2057      _glthread_UNLOCK_MUTEX(oldRb->Mutex);
2058
2059      if (deleteFlag) {
2060         oldRb->Magic = 0; /* now invalid memory! */
2061         oldRb->Delete(oldRb);
2062      }
2063
2064      *ptr = NULL;
2065   }
2066   assert(!*ptr);
2067
2068   if (rb) {
2069      assert(rb->Magic == RB_MAGIC);
2070      /* reference new renderbuffer */
2071      _glthread_LOCK_MUTEX(rb->Mutex);
2072      rb->RefCount++;
2073      /*printf("RB INCR %p (%d) to %d\n", (void*) rb, rb->Name, rb->RefCount);*/
2074      _glthread_UNLOCK_MUTEX(rb->Mutex);
2075      *ptr = rb;
2076   }
2077}
2078
2079
2080/**
2081 * Create a new combined depth/stencil renderbuffer for implementing
2082 * the GL_EXT_packed_depth_stencil extension.
2083 * \return new depth/stencil renderbuffer
2084 */
2085struct gl_renderbuffer *
2086_mesa_new_depthstencil_renderbuffer(GLcontext *ctx, GLuint name)
2087{
2088   struct gl_renderbuffer *dsrb;
2089
2090   dsrb = _mesa_new_renderbuffer(ctx, name);
2091   if (!dsrb)
2092      return NULL;
2093
2094   /* init fields not covered by _mesa_new_renderbuffer() */
2095   dsrb->InternalFormat = GL_DEPTH24_STENCIL8_EXT;
2096   dsrb->Format = MESA_FORMAT_Z24_S8;
2097   dsrb->AllocStorage = _mesa_soft_renderbuffer_storage;
2098
2099   return dsrb;
2100}
2101