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