renderbuffer.c revision 676d0accf5cc43e86057b14cfb8bba9316932582
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 * The alpha_renderbuffer class is used to augment an RGB renderbuffer with
1150 * an alpha channel.  The RGB buffer can be hardware-based.
1151 * We basically wrap the RGB buffer.  When PutRow is called (for example),
1152 * we store the alpha values in this buffer, then pass on the PutRow call
1153 * to the wrapped RGB buffer.
1154 */
1155struct alpha_renderbuffer
1156{
1157   struct gl_renderbuffer Base;        /* the alpha buffer */
1158   struct gl_renderbuffer *RGBbuffer;  /* the wrapped RGB buffer */
1159};
1160
1161
1162static GLboolean
1163alloc_storage_alpha8(GLcontext *ctx, struct gl_renderbuffer *rb,
1164                     GLenum internalFormat, GLuint width, GLuint height)
1165{
1166   struct alpha_renderbuffer *arb = (struct alpha_renderbuffer *) rb;
1167
1168   /* first, pass the call to the wrapped RGB buffer */
1169   if (!arb->RGBbuffer->AllocStorage(ctx, arb->RGBbuffer, internalFormat,
1170                                     width, height)) {
1171      return GL_FALSE;
1172   }
1173
1174   /* next, resize my alpha buffer */
1175   if (arb->Base.Data) {
1176      _mesa_free(arb->Base.Data);
1177   }
1178
1179   arb->Base.Data = _mesa_malloc(width * height * sizeof(GLubyte));
1180   if (arb->Base.Data == NULL) {
1181      arb->Base.Width = 0;
1182      arb->Base.Height = 0;
1183      _mesa_error(ctx, GL_OUT_OF_MEMORY, "software alpha buffer allocation");
1184      return GL_FALSE;
1185   }
1186
1187   arb->Base.Width = width;
1188   arb->Base.Height = height;
1189   arb->Base.InternalFormat = internalFormat;
1190
1191   return GL_TRUE;
1192}
1193
1194
1195/**
1196 * Delete an alpha_renderbuffer object, as well as the wrapped RGB buffer.
1197 */
1198static void
1199delete_renderbuffer_alpha8(struct gl_renderbuffer *rb)
1200{
1201   struct alpha_renderbuffer *arb = (struct alpha_renderbuffer *) rb;
1202   if (arb->Base.Data) {
1203      _mesa_free(arb->Base.Data);
1204   }
1205   assert(arb->RGBbuffer);
1206   arb->RGBbuffer->Delete(arb->RGBbuffer);
1207   arb->RGBbuffer = NULL;
1208   _mesa_free(arb);
1209}
1210
1211
1212static void *
1213get_pointer_alpha8(GLcontext *ctx, struct gl_renderbuffer *rb,
1214                   GLint x, GLint y)
1215{
1216   return NULL;   /* don't allow direct access! */
1217}
1218
1219
1220static void
1221get_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
1222               GLint x, GLint y, void *values)
1223{
1224   /* NOTE: 'values' is RGBA format! */
1225   struct alpha_renderbuffer *arb = (struct alpha_renderbuffer *) rb;
1226   const GLubyte *src = (const GLubyte *) rb->Data + y * rb->Width + x;
1227   GLubyte *dst = (GLubyte *) values;
1228   GLuint i;
1229   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
1230   /* first, pass the call to the wrapped RGB buffer */
1231   arb->RGBbuffer->GetRow(ctx, arb->RGBbuffer, count, x, y, values);
1232   /* second, fill in alpha values from this buffer! */
1233   for (i = 0; i < count; i++) {
1234      dst[i * 4 + 3] = src[i];
1235   }
1236}
1237
1238
1239static void
1240get_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
1241                  const GLint x[], const GLint y[], void *values)
1242{
1243   struct alpha_renderbuffer *arb = (struct alpha_renderbuffer *) rb;
1244   GLubyte *dst = (GLubyte *) values;
1245   GLuint i;
1246   assert(rb->DataType == GL_UNSIGNED_BYTE);
1247   /* first, pass the call to the wrapped RGB buffer */
1248   arb->RGBbuffer->GetValues(ctx, arb->RGBbuffer, count, x, y, values);
1249   /* second, fill in alpha values from this buffer! */
1250   for (i = 0; i < count; i++) {
1251      const GLubyte *src = (GLubyte *) rb->Data + y[i] * rb->Width + x[i];
1252      dst[i * 4 + 3] = *src;
1253   }
1254}
1255
1256
1257static void
1258put_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
1259               GLint x, GLint y, const void *values, const GLubyte *mask)
1260{
1261   struct alpha_renderbuffer *arb = (struct alpha_renderbuffer *) rb;
1262   const GLubyte *src = (const GLubyte *) values;
1263   GLubyte *dst = (GLubyte *) rb->Data + y * rb->Width + x;
1264   GLuint i;
1265   assert(rb->DataType == GL_UNSIGNED_BYTE);
1266   /* first, pass the call to the wrapped RGB buffer */
1267   arb->RGBbuffer->PutRow(ctx, arb->RGBbuffer, count, x, y, values, mask);
1268   /* second, store alpha in our buffer */
1269   for (i = 0; i < count; i++) {
1270      if (!mask || mask[i]) {
1271         dst[i] = src[i * 4 + 3];
1272      }
1273   }
1274}
1275
1276
1277static void
1278put_row_rgb_alpha8(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
1279                   GLint x, GLint y, const void *values, const GLubyte *mask)
1280{
1281   struct alpha_renderbuffer *arb = (struct alpha_renderbuffer *) rb;
1282   const GLubyte *src = (const GLubyte *) values;
1283   GLubyte *dst = (GLubyte *) rb->Data + y * rb->Width + x;
1284   GLuint i;
1285   assert(rb->DataType == GL_UNSIGNED_BYTE);
1286   /* first, pass the call to the wrapped RGB buffer */
1287   arb->RGBbuffer->PutRowRGB(ctx, arb->RGBbuffer, count, x, y, values, mask);
1288   /* second, store alpha in our buffer */
1289   for (i = 0; i < count; i++) {
1290      if (!mask || mask[i]) {
1291         dst[i] = src[i * 4 + 3];
1292      }
1293   }
1294}
1295
1296
1297static void
1298put_mono_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
1299                    GLint x, GLint y, const void *value, const GLubyte *mask)
1300{
1301   struct alpha_renderbuffer *arb = (struct alpha_renderbuffer *) rb;
1302   const GLubyte val = ((const GLubyte *) value)[3];
1303   GLubyte *dst = (GLubyte *) rb->Data + y * rb->Width + x;
1304   assert(rb->DataType == GL_UNSIGNED_BYTE);
1305   /* first, pass the call to the wrapped RGB buffer */
1306   arb->RGBbuffer->PutMonoRow(ctx, arb->RGBbuffer, count, x, y, value, mask);
1307   /* second, store alpha in our buffer */
1308   if (mask) {
1309      GLuint i;
1310      for (i = 0; i < count; i++) {
1311         if (mask[i]) {
1312            dst[i] = val;
1313         }
1314      }
1315   }
1316   else {
1317      _mesa_memset(dst, val, count);
1318   }
1319}
1320
1321
1322static void
1323put_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
1324                  const GLint x[], const GLint y[],
1325                  const void *values, const GLubyte *mask)
1326{
1327   struct alpha_renderbuffer *arb = (struct alpha_renderbuffer *) rb;
1328   const GLubyte *src = (const GLubyte *) values;
1329   GLuint i;
1330   assert(rb->DataType == GL_UNSIGNED_BYTE);
1331   /* first, pass the call to the wrapped RGB buffer */
1332   arb->RGBbuffer->PutValues(ctx, arb->RGBbuffer, count, x, y, values, mask);
1333   /* second, store alpha in our buffer */
1334   for (i = 0; i < count; i++) {
1335      if (!mask || mask[i]) {
1336         GLubyte *dst = (GLubyte *) rb->Data + y[i] * rb->Width + x[i];
1337         *dst = src[i * 4 + 3];
1338      }
1339   }
1340}
1341
1342
1343static void
1344put_mono_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *rb,
1345                       GLuint count, const GLint x[], const GLint y[],
1346                       const void *value, const GLubyte *mask)
1347{
1348   struct alpha_renderbuffer *arb = (struct alpha_renderbuffer *) rb;
1349   const GLubyte val = ((const GLubyte *) value)[3];
1350   GLuint i;
1351   assert(rb->DataType == GL_UNSIGNED_BYTE);
1352   /* first, pass the call to the wrapped RGB buffer */
1353   arb->RGBbuffer->PutValues(ctx, arb->RGBbuffer, count, x, y, value, mask);
1354   /* second, store alpha in our buffer */
1355   for (i = 0; i < count; i++) {
1356      if (!mask || mask[i]) {
1357         GLubyte *dst = (GLubyte *) rb->Data + y[i] * rb->Width + x[i];
1358         *dst = val;
1359      }
1360   }
1361}
1362
1363
1364
1365/**********************************************************************/
1366/**********************************************************************/
1367/**********************************************************************/
1368
1369
1370/**
1371 * Default GetPointer routine.  Always return NULL to indicate that
1372 * direct buffer access is not supported.
1373 */
1374static void *
1375nop_get_pointer(GLcontext *ctx, struct gl_renderbuffer *rb, GLint x, GLint y)
1376{
1377   return NULL;
1378}
1379
1380
1381/**
1382 * Initialize the fields of a gl_renderbuffer to default values.
1383 */
1384void
1385_mesa_init_renderbuffer(struct gl_renderbuffer *rb, GLuint name)
1386{
1387   rb->Name = name;
1388   rb->RefCount = 1;
1389   rb->Delete = _mesa_delete_renderbuffer;
1390
1391   /* The rest of these should be set later by the caller of this function or
1392    * the AllocStorage method:
1393    */
1394   rb->AllocStorage = NULL;
1395
1396   rb->Width = 0;
1397   rb->Height = 0;
1398   rb->InternalFormat = GL_NONE;
1399   rb->_BaseFormat = GL_NONE;
1400   rb->DataType = GL_NONE;
1401   rb->RedBits = rb->GreenBits = rb->BlueBits = rb->AlphaBits = 0;
1402   rb->IndexBits = 0;
1403   rb->DepthBits = 0;
1404   rb->StencilBits = 0;
1405   rb->Data = NULL;
1406
1407   rb->GetPointer = nop_get_pointer;
1408   rb->GetRow = NULL;
1409   rb->GetValues = NULL;
1410   rb->PutRow = NULL;
1411   rb->PutRowRGB = NULL;
1412   rb->PutMonoRow = NULL;
1413   rb->PutValues = NULL;
1414   rb->PutMonoValues = NULL;
1415}
1416
1417
1418/**
1419 * Allocate a new gl_renderbuffer object.  This can be used for user-created
1420 * renderbuffers or window-system renderbuffers.
1421 */
1422struct gl_renderbuffer *
1423_mesa_new_renderbuffer(GLcontext *ctx, GLuint name)
1424{
1425   struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer);
1426   if (rb) {
1427      _mesa_init_renderbuffer(rb, name);
1428   }
1429   return rb;
1430}
1431
1432
1433/**
1434 * Delete a gl_framebuffer.
1435 * This is the default function for framebuffer->Delete().
1436 */
1437void
1438_mesa_delete_renderbuffer(struct gl_renderbuffer *rb)
1439{
1440   if (rb->Data) {
1441      _mesa_free(rb->Data);
1442   }
1443   _mesa_free(rb);
1444}
1445
1446
1447/**
1448 * Allocate a software-based renderbuffer.  This is called via the
1449 * ctx->Driver.NewRenderbuffer() function when the user creates a new
1450 * renderbuffer.
1451 * This would not be used for hardware-based renderbuffers.
1452 */
1453struct gl_renderbuffer *
1454_mesa_new_soft_renderbuffer(GLcontext *ctx, GLuint name)
1455{
1456   struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, name);
1457   if (rb) {
1458      rb->AllocStorage = soft_renderbuffer_storage;
1459      /* Normally, one would setup the PutRow, GetRow, etc functions here.
1460       * But we're doing that in the soft_renderbuffer_storage() function
1461       * instead.
1462       */
1463   }
1464   return rb;
1465}
1466
1467
1468/**
1469 * Add software-based color renderbuffers to the given framebuffer.
1470 * This is a helper routine for device drivers when creating a
1471 * window system framebuffer (not a user-created render/framebuffer).
1472 * Once this function is called, you can basically forget about this
1473 * renderbuffer; core Mesa will handle all the buffer management and
1474 * rendering!
1475 */
1476GLboolean
1477_mesa_add_color_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
1478                              GLuint rgbBits, GLuint alphaBits,
1479                              GLboolean frontLeft, GLboolean backLeft,
1480                              GLboolean frontRight, GLboolean backRight)
1481{
1482   GLuint b;
1483
1484   if (rgbBits > 16 || alphaBits > 16) {
1485      _mesa_problem(ctx,
1486                    "Unsupported bit depth in _mesa_add_color_renderbuffers");
1487      return GL_FALSE;
1488   }
1489
1490   assert(MAX_COLOR_ATTACHMENTS >= 4);
1491
1492   for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
1493      struct gl_renderbuffer *rb;
1494
1495      if (b == BUFFER_FRONT_LEFT && !frontLeft)
1496         continue;
1497      else if (b == BUFFER_BACK_LEFT && !backLeft)
1498         continue;
1499      else if (b == BUFFER_FRONT_RIGHT && !frontRight)
1500         continue;
1501      else if (b == BUFFER_BACK_RIGHT && !backRight)
1502         continue;
1503
1504      assert(fb->Attachment[b].Renderbuffer == NULL);
1505
1506      rb = _mesa_new_renderbuffer(ctx, 0);
1507      if (!rb) {
1508         _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer");
1509         return GL_FALSE;
1510      }
1511
1512      if (rgbBits <= 8) {
1513         if (alphaBits)
1514            rb->InternalFormat = GL_RGBA8;
1515         else
1516            rb->InternalFormat = GL_RGB8;
1517      }
1518      else {
1519         assert(rgbBits <= 16);
1520         if (alphaBits)
1521            rb->InternalFormat = GL_RGBA16;
1522         else
1523            rb->InternalFormat = GL_RGBA16; /* don't really have RGB16 yet */
1524      }
1525
1526      rb->AllocStorage = soft_renderbuffer_storage;
1527      _mesa_add_renderbuffer(fb, b, rb);
1528   }
1529
1530   return GL_TRUE;
1531}
1532
1533
1534/**
1535 * Add software-based color index renderbuffers to the given framebuffer.
1536 * This is a helper routine for device drivers when creating a
1537 * window system framebuffer (not a user-created render/framebuffer).
1538 * Once this function is called, you can basically forget about this
1539 * renderbuffer; core Mesa will handle all the buffer management and
1540 * rendering!
1541 */
1542GLboolean
1543_mesa_add_color_index_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
1544                                    GLuint indexBits,
1545                                    GLboolean frontLeft, GLboolean backLeft,
1546                                    GLboolean frontRight, GLboolean backRight)
1547{
1548   GLuint b;
1549
1550   if (indexBits > 8) {
1551      _mesa_problem(ctx,
1552                "Unsupported bit depth in _mesa_add_color_index_renderbuffers");
1553      return GL_FALSE;
1554   }
1555
1556   assert(MAX_COLOR_ATTACHMENTS >= 4);
1557
1558   for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
1559      struct gl_renderbuffer *rb;
1560
1561      if (b == BUFFER_FRONT_LEFT && !frontLeft)
1562         continue;
1563      else if (b == BUFFER_BACK_LEFT && !backLeft)
1564         continue;
1565      else if (b == BUFFER_FRONT_RIGHT && !frontRight)
1566         continue;
1567      else if (b == BUFFER_BACK_RIGHT && !backRight)
1568         continue;
1569
1570      assert(fb->Attachment[b].Renderbuffer == NULL);
1571
1572      rb = _mesa_new_renderbuffer(ctx, 0);
1573      if (!rb) {
1574         _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer");
1575         return GL_FALSE;
1576      }
1577
1578      if (indexBits <= 8) {
1579         /* only support GLuint for now */
1580         /*rb->InternalFormat = GL_COLOR_INDEX8_EXT;*/
1581         rb->InternalFormat = COLOR_INDEX32;
1582      }
1583      else {
1584         rb->InternalFormat = COLOR_INDEX32;
1585      }
1586      rb->AllocStorage = soft_renderbuffer_storage;
1587      _mesa_add_renderbuffer(fb, b, rb);
1588   }
1589
1590   return GL_TRUE;
1591}
1592
1593
1594/**
1595 * Add software-based alpha renderbuffers to the given framebuffer.
1596 * This is a helper routine for device drivers when creating a
1597 * window system framebuffer (not a user-created render/framebuffer).
1598 * Once this function is called, you can basically forget about this
1599 * renderbuffer; core Mesa will handle all the buffer management and
1600 * rendering!
1601 */
1602GLboolean
1603_mesa_add_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
1604                              GLuint alphaBits,
1605                              GLboolean frontLeft, GLboolean backLeft,
1606                              GLboolean frontRight, GLboolean backRight)
1607{
1608   GLuint b;
1609
1610   /* for window system framebuffers only! */
1611   assert(fb->Name == 0);
1612
1613   if (alphaBits > 8) {
1614      _mesa_problem(ctx,
1615                    "Unsupported bit depth in _mesa_add_alpha_renderbuffers");
1616      return GL_FALSE;
1617   }
1618
1619   assert(MAX_COLOR_ATTACHMENTS >= 4);
1620
1621   for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
1622      struct alpha_renderbuffer *arb;
1623
1624      if (b == BUFFER_FRONT_LEFT && !frontLeft)
1625         continue;
1626      else if (b == BUFFER_BACK_LEFT && !backLeft)
1627         continue;
1628      else if (b == BUFFER_FRONT_RIGHT && !frontRight)
1629         continue;
1630      else if (b == BUFFER_BACK_RIGHT && !backRight)
1631         continue;
1632
1633      /* the RGB buffer to wrap must already exist!! */
1634      assert(fb->Attachment[b].Renderbuffer);
1635
1636      /* only GLubyte supported for now */
1637      assert(fb->Attachment[b].Renderbuffer->DataType == GL_UNSIGNED_BYTE);
1638
1639      arb = CALLOC_STRUCT(alpha_renderbuffer);
1640      if (!arb) {
1641         _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating alpha buffer");
1642         return GL_FALSE;
1643      }
1644
1645      _mesa_init_renderbuffer(&arb->Base, 0);
1646
1647      /* wrap the RGB buffer */
1648      arb->RGBbuffer = fb->Attachment[b].Renderbuffer;
1649
1650      /* plug in my functions */
1651      arb->Base.InternalFormat = arb->RGBbuffer->InternalFormat;
1652      arb->Base._BaseFormat    = arb->RGBbuffer->_BaseFormat;
1653      arb->Base.DataType       = arb->RGBbuffer->DataType;
1654      arb->Base.AllocStorage   = alloc_storage_alpha8;
1655      arb->Base.Delete         = delete_renderbuffer_alpha8;
1656      arb->Base.GetPointer     = get_pointer_alpha8;
1657      arb->Base.GetRow         = get_row_alpha8;
1658      arb->Base.GetValues      = get_values_alpha8;
1659      arb->Base.PutRow         = put_row_alpha8;
1660      arb->Base.PutRowRGB      = put_row_rgb_alpha8;
1661      arb->Base.PutMonoRow     = put_mono_row_alpha8;
1662      arb->Base.PutValues      = put_values_alpha8;
1663      arb->Base.PutMonoValues  = put_mono_values_alpha8;
1664
1665      /* clear the pointer to avoid assertion/sanity check failure later */
1666      fb->Attachment[b].Renderbuffer = NULL;
1667
1668      /* plug the alpha renderbuffer into the colorbuffer attachment */
1669      _mesa_add_renderbuffer(fb, b, &arb->Base);
1670   }
1671
1672   return GL_TRUE;
1673}
1674
1675
1676/**
1677 * Add a software-based depth renderbuffer to the given framebuffer.
1678 * This is a helper routine for device drivers when creating a
1679 * window system framebuffer (not a user-created render/framebuffer).
1680 * Once this function is called, you can basically forget about this
1681 * renderbuffer; core Mesa will handle all the buffer management and
1682 * rendering!
1683 */
1684GLboolean
1685_mesa_add_depth_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
1686                             GLuint depthBits)
1687{
1688   struct gl_renderbuffer *rb;
1689
1690   if (depthBits > 32) {
1691      _mesa_problem(ctx,
1692                    "Unsupported depthBits in _mesa_add_depth_renderbuffer");
1693      return GL_FALSE;
1694   }
1695
1696   assert(fb->Attachment[BUFFER_DEPTH].Renderbuffer == NULL);
1697
1698   rb = _mesa_new_renderbuffer(ctx, 0);
1699   if (!rb) {
1700      _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating depth buffer");
1701      return GL_FALSE;
1702   }
1703
1704   if (depthBits <= 16) {
1705      rb->InternalFormat = GL_DEPTH_COMPONENT16;
1706   }
1707   else {
1708      rb->InternalFormat = GL_DEPTH_COMPONENT32;
1709   }
1710
1711   rb->AllocStorage = soft_renderbuffer_storage;
1712   _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
1713
1714   return GL_TRUE;
1715}
1716
1717
1718/**
1719 * Add a software-based stencil renderbuffer to the given framebuffer.
1720 * This is a helper routine for device drivers when creating a
1721 * window system framebuffer (not a user-created render/framebuffer).
1722 * Once this function is called, you can basically forget about this
1723 * renderbuffer; core Mesa will handle all the buffer management and
1724 * rendering!
1725 */
1726GLboolean
1727_mesa_add_stencil_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
1728                               GLuint stencilBits)
1729{
1730   struct gl_renderbuffer *rb;
1731
1732   if (stencilBits > 16) {
1733      _mesa_problem(ctx,
1734                  "Unsupported stencilBits in _mesa_add_stencil_renderbuffer");
1735      return GL_FALSE;
1736   }
1737
1738   assert(fb->Attachment[BUFFER_STENCIL].Renderbuffer == NULL);
1739
1740   rb = _mesa_new_renderbuffer(ctx, 0);
1741   if (!rb) {
1742      _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating stencil buffer");
1743      return GL_FALSE;
1744   }
1745
1746   if (stencilBits <= 8) {
1747      rb->InternalFormat = GL_STENCIL_INDEX8_EXT;
1748   }
1749   else {
1750      /* not really supported (see s_stencil.c code) */
1751      rb->InternalFormat = GL_STENCIL_INDEX16_EXT;
1752   }
1753
1754   rb->AllocStorage = soft_renderbuffer_storage;
1755   _mesa_add_renderbuffer(fb, BUFFER_STENCIL, rb);
1756
1757   return GL_TRUE;
1758}
1759
1760
1761/**
1762 * Add a software-based accumulation renderbuffer to the given framebuffer.
1763 * This is a helper routine for device drivers when creating a
1764 * window system framebuffer (not a user-created render/framebuffer).
1765 * Once this function is called, you can basically forget about this
1766 * renderbuffer; core Mesa will handle all the buffer management and
1767 * rendering!
1768 */
1769GLboolean
1770_mesa_add_accum_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
1771                             GLuint redBits, GLuint greenBits,
1772                             GLuint blueBits, GLuint alphaBits)
1773{
1774   struct gl_renderbuffer *rb;
1775
1776   if (redBits > 16 || greenBits > 16 || blueBits > 16 || alphaBits > 16) {
1777      _mesa_problem(ctx,
1778                    "Unsupported accumBits in _mesa_add_accum_renderbuffer");
1779      return GL_FALSE;
1780   }
1781
1782   assert(fb->Attachment[BUFFER_ACCUM].Renderbuffer == NULL);
1783
1784   rb = _mesa_new_renderbuffer(ctx, 0);
1785   if (!rb) {
1786      _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer");
1787      return GL_FALSE;
1788   }
1789
1790   rb->InternalFormat = GL_RGBA16;
1791   rb->AllocStorage = soft_renderbuffer_storage;
1792   _mesa_add_renderbuffer(fb, BUFFER_ACCUM, rb);
1793
1794   return GL_TRUE;
1795}
1796
1797
1798
1799/**
1800 * Add a software-based accumulation renderbuffer to the given framebuffer.
1801 * This is a helper routine for device drivers when creating a
1802 * window system framebuffer (not a user-created render/framebuffer).
1803 * Once this function is called, you can basically forget about this
1804 * renderbuffer; core Mesa will handle all the buffer management and
1805 * rendering!
1806 *
1807 * NOTE: color-index aux buffers not supported.
1808 */
1809GLboolean
1810_mesa_add_aux_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
1811                            GLuint colorBits, GLuint numBuffers)
1812{
1813   GLuint i;
1814
1815   if (colorBits > 16) {
1816      _mesa_problem(ctx,
1817                    "Unsupported accumBits in _mesa_add_aux_renderbuffers");
1818      return GL_FALSE;
1819   }
1820
1821   assert(numBuffers < MAX_AUX_BUFFERS);
1822
1823   for (i = 0; i < numBuffers; i++) {
1824      struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, 0);
1825
1826      assert(fb->Attachment[BUFFER_AUX0 + i].Renderbuffer == NULL);
1827
1828      if (!rb) {
1829         _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer");
1830         return GL_FALSE;
1831      }
1832
1833      if (colorBits <= 8) {
1834         rb->InternalFormat = GL_RGBA8;
1835      }
1836      else {
1837         rb->InternalFormat = GL_RGBA16;
1838      }
1839
1840      rb->AllocStorage = soft_renderbuffer_storage;
1841      _mesa_add_renderbuffer(fb, BUFFER_AUX0 + i, rb);
1842   }
1843   return GL_TRUE;
1844}
1845
1846
1847/**
1848 * Create/attach software-based renderbuffers to the given framebuffer.
1849 * This is a helper routine for device drivers.  Drivers can just as well
1850 * call the individual _mesa_add_*_renderbuffer() routines directly.
1851 */
1852void
1853_mesa_add_soft_renderbuffers(struct gl_framebuffer *fb,
1854                             GLboolean color,
1855                             GLboolean depth,
1856                             GLboolean stencil,
1857                             GLboolean accum,
1858                             GLboolean alpha,
1859                             GLboolean aux)
1860{
1861   GLboolean frontLeft = GL_TRUE;
1862   GLboolean backLeft = fb->Visual.doubleBufferMode;
1863   GLboolean frontRight = fb->Visual.stereoMode;
1864   GLboolean backRight = fb->Visual.stereoMode && fb->Visual.doubleBufferMode;
1865
1866   if (color) {
1867      if (fb->Visual.rgbMode) {
1868         assert(fb->Visual.redBits == fb->Visual.greenBits);
1869         assert(fb->Visual.redBits == fb->Visual.blueBits);
1870         _mesa_add_color_renderbuffers(NULL, fb,
1871                                       fb->Visual.redBits,
1872                                       fb->Visual.alphaBits,
1873                                       frontLeft, backLeft,
1874                                       frontRight, backRight);
1875      }
1876      else {
1877         _mesa_add_color_index_renderbuffers(NULL, fb,
1878                                             fb->Visual.indexBits,
1879                                             frontLeft, backLeft,
1880                                             frontRight, backRight);
1881      }
1882   }
1883
1884   if (depth) {
1885      assert(fb->Visual.depthBits > 0);
1886      _mesa_add_depth_renderbuffer(NULL, fb, fb->Visual.depthBits);
1887   }
1888
1889   if (stencil) {
1890      assert(fb->Visual.stencilBits > 0);
1891      _mesa_add_stencil_renderbuffer(NULL, fb, fb->Visual.stencilBits);
1892   }
1893
1894   if (accum) {
1895      assert(fb->Visual.rgbMode);
1896      assert(fb->Visual.accumRedBits > 0);
1897      assert(fb->Visual.accumGreenBits > 0);
1898      assert(fb->Visual.accumBlueBits > 0);
1899      _mesa_add_accum_renderbuffer(NULL, fb,
1900                                   fb->Visual.accumRedBits,
1901                                   fb->Visual.accumGreenBits,
1902                                   fb->Visual.accumBlueBits,
1903                                   fb->Visual.accumAlphaBits);
1904   }
1905
1906   if (aux) {
1907      assert(fb->Visual.rgbMode);
1908      assert(fb->Visual.numAuxBuffers > 0);
1909      _mesa_add_aux_renderbuffers(NULL, fb, fb->Visual.redBits,
1910                                  fb->Visual.numAuxBuffers);
1911   }
1912
1913   if (alpha) {
1914      assert(fb->Visual.rgbMode);
1915      assert(fb->Visual.alphaBits > 0);
1916      _mesa_add_alpha_renderbuffers(NULL, fb, fb->Visual.alphaBits,
1917                                    frontLeft, backLeft,
1918                                    frontRight, backRight);
1919   }
1920
1921#if 0
1922   if (multisample) {
1923      /* maybe someday */
1924   }
1925#endif
1926}
1927
1928
1929/**
1930 * Attach a renderbuffer to a framebuffer.
1931 */
1932void
1933_mesa_add_renderbuffer(struct gl_framebuffer *fb,
1934                       GLuint bufferName, struct gl_renderbuffer *rb)
1935{
1936   assert(fb);
1937   assert(rb);
1938#if 00
1939   /* there should be no previous renderbuffer on this attachment point! */
1940   assert(fb->Attachment[bufferName].Renderbuffer == NULL);
1941#endif
1942   assert(bufferName < BUFFER_COUNT);
1943
1944   /* winsys vs. user-created buffer cross check */
1945   if (fb->Name) {
1946      assert(rb->Name);
1947   }
1948   else {
1949      assert(!rb->Name);
1950   }
1951
1952   fb->Attachment[bufferName].Type = GL_RENDERBUFFER_EXT;
1953   fb->Attachment[bufferName].Complete = GL_TRUE;
1954   fb->Attachment[bufferName].Renderbuffer = rb;
1955}
1956