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