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