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