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