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