renderbuffer.c revision 91226ce6487e9ea9c21f5a269f63cf98affa8ef4
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->ClassID = 0;
1399   rb->Name = name;
1400   rb->RefCount = 0;
1401   rb->Delete = _mesa_delete_renderbuffer;
1402
1403   /* The rest of these should be set later by the caller of this function or
1404    * the AllocStorage method:
1405    */
1406   rb->AllocStorage = NULL;
1407
1408   rb->Width = 0;
1409   rb->Height = 0;
1410   rb->InternalFormat = GL_NONE;
1411   rb->Format = MESA_FORMAT_NONE;
1412
1413   rb->DataType = GL_NONE;
1414   rb->Data = NULL;
1415
1416   /* Point back to ourself so that we don't have to check for Wrapped==NULL
1417    * all over the drivers.
1418    */
1419   rb->Wrapped = rb;
1420
1421   rb->GetPointer = nop_get_pointer;
1422   rb->GetRow = NULL;
1423   rb->GetValues = NULL;
1424   rb->PutRow = NULL;
1425   rb->PutRowRGB = NULL;
1426   rb->PutMonoRow = NULL;
1427   rb->PutValues = NULL;
1428   rb->PutMonoValues = NULL;
1429}
1430
1431
1432/**
1433 * Allocate a new gl_renderbuffer object.  This can be used for user-created
1434 * renderbuffers or window-system renderbuffers.
1435 */
1436struct gl_renderbuffer *
1437_mesa_new_renderbuffer(struct gl_context *ctx, GLuint name)
1438{
1439   struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer);
1440   if (rb) {
1441      _mesa_init_renderbuffer(rb, name);
1442   }
1443   return rb;
1444}
1445
1446
1447/**
1448 * Delete a gl_framebuffer.
1449 * This is the default function for renderbuffer->Delete().
1450 */
1451void
1452_mesa_delete_renderbuffer(struct gl_renderbuffer *rb)
1453{
1454   if (rb->Data) {
1455      free(rb->Data);
1456   }
1457   free(rb);
1458}
1459
1460
1461/**
1462 * Allocate a software-based renderbuffer.  This is called via the
1463 * ctx->Driver.NewRenderbuffer() function when the user creates a new
1464 * renderbuffer.
1465 * This would not be used for hardware-based renderbuffers.
1466 */
1467struct gl_renderbuffer *
1468_mesa_new_soft_renderbuffer(struct gl_context *ctx, GLuint name)
1469{
1470   struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, name);
1471   if (rb) {
1472      rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1473      /* Normally, one would setup the PutRow, GetRow, etc functions here.
1474       * But we're doing that in the _mesa_soft_renderbuffer_storage() function
1475       * instead.
1476       */
1477   }
1478   return rb;
1479}
1480
1481
1482/**
1483 * Add software-based color renderbuffers to the given framebuffer.
1484 * This is a helper routine for device drivers when creating a
1485 * window system framebuffer (not a user-created render/framebuffer).
1486 * Once this function is called, you can basically forget about this
1487 * renderbuffer; core Mesa will handle all the buffer management and
1488 * rendering!
1489 */
1490GLboolean
1491_mesa_add_color_renderbuffers(struct gl_context *ctx, struct gl_framebuffer *fb,
1492                              GLuint rgbBits, GLuint alphaBits,
1493                              GLboolean frontLeft, GLboolean backLeft,
1494                              GLboolean frontRight, GLboolean backRight)
1495{
1496   gl_buffer_index b;
1497
1498   if (rgbBits > 16 || alphaBits > 16) {
1499      _mesa_problem(ctx,
1500                    "Unsupported bit depth in _mesa_add_color_renderbuffers");
1501      return GL_FALSE;
1502   }
1503
1504   assert(MAX_COLOR_ATTACHMENTS >= 4);
1505
1506   for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
1507      struct gl_renderbuffer *rb;
1508
1509      if (b == BUFFER_FRONT_LEFT && !frontLeft)
1510         continue;
1511      else if (b == BUFFER_BACK_LEFT && !backLeft)
1512         continue;
1513      else if (b == BUFFER_FRONT_RIGHT && !frontRight)
1514         continue;
1515      else if (b == BUFFER_BACK_RIGHT && !backRight)
1516         continue;
1517
1518      assert(fb->Attachment[b].Renderbuffer == NULL);
1519
1520      rb = _mesa_new_renderbuffer(ctx, 0);
1521      if (!rb) {
1522         _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer");
1523         return GL_FALSE;
1524      }
1525
1526      if (rgbBits <= 8) {
1527         if (alphaBits)
1528            rb->Format = MESA_FORMAT_RGBA8888;
1529         else
1530            rb->Format = MESA_FORMAT_RGB888;
1531      }
1532      else {
1533         assert(rgbBits <= 16);
1534         rb->Format = MESA_FORMAT_NONE; /*XXX RGBA16;*/
1535      }
1536      rb->InternalFormat = GL_RGBA;
1537
1538      rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1539      _mesa_add_renderbuffer(fb, b, rb);
1540   }
1541
1542   return GL_TRUE;
1543}
1544
1545
1546/**
1547 * Add software-based alpha renderbuffers to the given framebuffer.
1548 * This is a helper routine for device drivers when creating a
1549 * window system framebuffer (not a user-created render/framebuffer).
1550 * Once this function is called, you can basically forget about this
1551 * renderbuffer; core Mesa will handle all the buffer management and
1552 * rendering!
1553 */
1554GLboolean
1555_mesa_add_alpha_renderbuffers(struct gl_context *ctx, struct gl_framebuffer *fb,
1556                              GLuint alphaBits,
1557                              GLboolean frontLeft, GLboolean backLeft,
1558                              GLboolean frontRight, GLboolean backRight)
1559{
1560   gl_buffer_index b;
1561
1562   /* for window system framebuffers only! */
1563   assert(fb->Name == 0);
1564
1565   if (alphaBits > 8) {
1566      _mesa_problem(ctx,
1567                    "Unsupported bit depth in _mesa_add_alpha_renderbuffers");
1568      return GL_FALSE;
1569   }
1570
1571   assert(MAX_COLOR_ATTACHMENTS >= 4);
1572
1573   /* Wrap each of the RGB color buffers with an alpha renderbuffer.
1574    */
1575   for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
1576      struct gl_renderbuffer *arb;
1577
1578      if (b == BUFFER_FRONT_LEFT && !frontLeft)
1579         continue;
1580      else if (b == BUFFER_BACK_LEFT && !backLeft)
1581         continue;
1582      else if (b == BUFFER_FRONT_RIGHT && !frontRight)
1583         continue;
1584      else if (b == BUFFER_BACK_RIGHT && !backRight)
1585         continue;
1586
1587      /* the RGB buffer to wrap must already exist!! */
1588      assert(fb->Attachment[b].Renderbuffer);
1589
1590      /* only GLubyte supported for now */
1591      assert(fb->Attachment[b].Renderbuffer->DataType == GL_UNSIGNED_BYTE);
1592
1593      /* allocate alpha renderbuffer */
1594      arb = _mesa_new_renderbuffer(ctx, 0);
1595      if (!arb) {
1596         _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating alpha buffer");
1597         return GL_FALSE;
1598      }
1599
1600      /* wrap the alpha renderbuffer around the RGB renderbuffer */
1601      arb->Wrapped = fb->Attachment[b].Renderbuffer;
1602
1603      /* Set up my alphabuffer fields and plug in my functions.
1604       * The functions will put/get the alpha values from/to RGBA arrays
1605       * and then call the wrapped buffer's functions to handle the RGB
1606       * values.
1607       */
1608      arb->InternalFormat = arb->Wrapped->InternalFormat;
1609      arb->Format         = MESA_FORMAT_A8;
1610      arb->DataType       = arb->Wrapped->DataType;
1611      arb->AllocStorage   = alloc_storage_alpha8;
1612      arb->Delete         = delete_renderbuffer_alpha8;
1613      arb->GetPointer     = get_pointer_alpha8;
1614      arb->GetRow         = get_row_alpha8;
1615      arb->GetValues      = get_values_alpha8;
1616      arb->PutRow         = put_row_alpha8;
1617      arb->PutRowRGB      = put_row_rgb_alpha8;
1618      arb->PutMonoRow     = put_mono_row_alpha8;
1619      arb->PutValues      = put_values_alpha8;
1620      arb->PutMonoValues  = put_mono_values_alpha8;
1621
1622      /* clear the pointer to avoid assertion/sanity check failure later */
1623      fb->Attachment[b].Renderbuffer = NULL;
1624
1625      /* plug the alpha renderbuffer into the colorbuffer attachment */
1626      _mesa_add_renderbuffer(fb, b, arb);
1627   }
1628
1629   return GL_TRUE;
1630}
1631
1632
1633/**
1634 * For framebuffers that use a software alpha channel wrapper
1635 * created by _mesa_add_alpha_renderbuffer or _mesa_add_soft_renderbuffers,
1636 * copy the back buffer alpha channel into the front buffer alpha channel.
1637 */
1638void
1639_mesa_copy_soft_alpha_renderbuffers(struct gl_context *ctx, struct gl_framebuffer *fb)
1640{
1641   if (fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer &&
1642       fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer)
1643      copy_buffer_alpha8(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer,
1644                         fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
1645
1646
1647   if (fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer &&
1648       fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer)
1649      copy_buffer_alpha8(fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer,
1650                         fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer);
1651}
1652
1653
1654/**
1655 * Add a software-based depth renderbuffer to the given framebuffer.
1656 * This is a helper routine for device drivers when creating a
1657 * window system framebuffer (not a user-created render/framebuffer).
1658 * Once this function is called, you can basically forget about this
1659 * renderbuffer; core Mesa will handle all the buffer management and
1660 * rendering!
1661 */
1662GLboolean
1663_mesa_add_depth_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
1664                             GLuint depthBits)
1665{
1666   struct gl_renderbuffer *rb;
1667
1668   if (depthBits > 32) {
1669      _mesa_problem(ctx,
1670                    "Unsupported depthBits in _mesa_add_depth_renderbuffer");
1671      return GL_FALSE;
1672   }
1673
1674   assert(fb->Attachment[BUFFER_DEPTH].Renderbuffer == NULL);
1675
1676   rb = _mesa_new_renderbuffer(ctx, 0);
1677   if (!rb) {
1678      _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating depth buffer");
1679      return GL_FALSE;
1680   }
1681
1682   if (depthBits <= 16) {
1683      rb->Format = MESA_FORMAT_Z16;
1684      rb->InternalFormat = GL_DEPTH_COMPONENT16;
1685   }
1686   else if (depthBits <= 24) {
1687      rb->Format = MESA_FORMAT_X8_Z24;
1688      rb->InternalFormat = GL_DEPTH_COMPONENT24;
1689   }
1690   else {
1691      rb->Format = MESA_FORMAT_Z32;
1692      rb->InternalFormat = GL_DEPTH_COMPONENT32;
1693   }
1694
1695   rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1696   _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
1697
1698   return GL_TRUE;
1699}
1700
1701
1702/**
1703 * Add a software-based stencil renderbuffer to the given framebuffer.
1704 * This is a helper routine for device drivers when creating a
1705 * window system framebuffer (not a user-created render/framebuffer).
1706 * Once this function is called, you can basically forget about this
1707 * renderbuffer; core Mesa will handle all the buffer management and
1708 * rendering!
1709 */
1710GLboolean
1711_mesa_add_stencil_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
1712                               GLuint stencilBits)
1713{
1714   struct gl_renderbuffer *rb;
1715
1716   if (stencilBits > 16) {
1717      _mesa_problem(ctx,
1718                  "Unsupported stencilBits in _mesa_add_stencil_renderbuffer");
1719      return GL_FALSE;
1720   }
1721
1722   assert(fb->Attachment[BUFFER_STENCIL].Renderbuffer == NULL);
1723
1724   rb = _mesa_new_renderbuffer(ctx, 0);
1725   if (!rb) {
1726      _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating stencil buffer");
1727      return GL_FALSE;
1728   }
1729
1730   assert(stencilBits <= 8);
1731   rb->Format = MESA_FORMAT_S8;
1732   rb->InternalFormat = GL_STENCIL_INDEX8;
1733
1734   rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1735   _mesa_add_renderbuffer(fb, BUFFER_STENCIL, rb);
1736
1737   return GL_TRUE;
1738}
1739
1740
1741/**
1742 * Add a software-based accumulation renderbuffer to the given framebuffer.
1743 * This is a helper routine for device drivers when creating a
1744 * window system framebuffer (not a user-created render/framebuffer).
1745 * Once this function is called, you can basically forget about this
1746 * renderbuffer; core Mesa will handle all the buffer management and
1747 * rendering!
1748 */
1749GLboolean
1750_mesa_add_accum_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
1751                             GLuint redBits, GLuint greenBits,
1752                             GLuint blueBits, GLuint alphaBits)
1753{
1754   struct gl_renderbuffer *rb;
1755
1756   if (redBits > 16 || greenBits > 16 || blueBits > 16 || alphaBits > 16) {
1757      _mesa_problem(ctx,
1758                    "Unsupported accumBits in _mesa_add_accum_renderbuffer");
1759      return GL_FALSE;
1760   }
1761
1762   assert(fb->Attachment[BUFFER_ACCUM].Renderbuffer == NULL);
1763
1764   rb = _mesa_new_renderbuffer(ctx, 0);
1765   if (!rb) {
1766      _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer");
1767      return GL_FALSE;
1768   }
1769
1770   rb->Format = MESA_FORMAT_SIGNED_RGBA_16;
1771   rb->InternalFormat = GL_RGBA16_SNORM;
1772   rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1773   _mesa_add_renderbuffer(fb, BUFFER_ACCUM, rb);
1774
1775   return GL_TRUE;
1776}
1777
1778
1779
1780/**
1781 * Add a software-based aux renderbuffer to the given framebuffer.
1782 * This is a helper routine for device drivers when creating a
1783 * window system framebuffer (not a user-created render/framebuffer).
1784 * Once this function is called, you can basically forget about this
1785 * renderbuffer; core Mesa will handle all the buffer management and
1786 * rendering!
1787 *
1788 * NOTE: color-index aux buffers not supported.
1789 */
1790GLboolean
1791_mesa_add_aux_renderbuffers(struct gl_context *ctx, struct gl_framebuffer *fb,
1792                            GLuint colorBits, GLuint numBuffers)
1793{
1794   GLuint i;
1795
1796   if (colorBits > 16) {
1797      _mesa_problem(ctx,
1798                    "Unsupported accumBits in _mesa_add_aux_renderbuffers");
1799      return GL_FALSE;
1800   }
1801
1802   assert(numBuffers <= MAX_AUX_BUFFERS);
1803
1804   for (i = 0; i < numBuffers; i++) {
1805      struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, 0);
1806
1807      assert(fb->Attachment[BUFFER_AUX0 + i].Renderbuffer == NULL);
1808
1809      if (!rb) {
1810         _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating aux buffer");
1811         return GL_FALSE;
1812      }
1813
1814      assert (colorBits <= 8);
1815      rb->Format = MESA_FORMAT_RGBA8888;
1816      rb->InternalFormat = GL_RGBA;
1817
1818      rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1819      _mesa_add_renderbuffer(fb, BUFFER_AUX0 + i, rb);
1820   }
1821   return GL_TRUE;
1822}
1823
1824
1825/**
1826 * Create/attach software-based renderbuffers to the given framebuffer.
1827 * This is a helper routine for device drivers.  Drivers can just as well
1828 * call the individual _mesa_add_*_renderbuffer() routines directly.
1829 */
1830void
1831_mesa_add_soft_renderbuffers(struct gl_framebuffer *fb,
1832                             GLboolean color,
1833                             GLboolean depth,
1834                             GLboolean stencil,
1835                             GLboolean accum,
1836                             GLboolean alpha,
1837                             GLboolean aux)
1838{
1839   GLboolean frontLeft = GL_TRUE;
1840   GLboolean backLeft = fb->Visual.doubleBufferMode;
1841   GLboolean frontRight = fb->Visual.stereoMode;
1842   GLboolean backRight = fb->Visual.stereoMode && fb->Visual.doubleBufferMode;
1843
1844   if (color) {
1845      assert(fb->Visual.redBits == fb->Visual.greenBits);
1846      assert(fb->Visual.redBits == fb->Visual.blueBits);
1847      _mesa_add_color_renderbuffers(NULL, fb,
1848				    fb->Visual.redBits,
1849				    fb->Visual.alphaBits,
1850				    frontLeft, backLeft,
1851				    frontRight, backRight);
1852   }
1853
1854   if (depth) {
1855      assert(fb->Visual.depthBits > 0);
1856      _mesa_add_depth_renderbuffer(NULL, fb, fb->Visual.depthBits);
1857   }
1858
1859   if (stencil) {
1860      assert(fb->Visual.stencilBits > 0);
1861      _mesa_add_stencil_renderbuffer(NULL, fb, fb->Visual.stencilBits);
1862   }
1863
1864   if (accum) {
1865      assert(fb->Visual.accumRedBits > 0);
1866      assert(fb->Visual.accumGreenBits > 0);
1867      assert(fb->Visual.accumBlueBits > 0);
1868      _mesa_add_accum_renderbuffer(NULL, fb,
1869                                   fb->Visual.accumRedBits,
1870                                   fb->Visual.accumGreenBits,
1871                                   fb->Visual.accumBlueBits,
1872                                   fb->Visual.accumAlphaBits);
1873   }
1874
1875   if (aux) {
1876      assert(fb->Visual.numAuxBuffers > 0);
1877      _mesa_add_aux_renderbuffers(NULL, fb, fb->Visual.redBits,
1878                                  fb->Visual.numAuxBuffers);
1879   }
1880
1881   if (alpha) {
1882      assert(fb->Visual.alphaBits > 0);
1883      _mesa_add_alpha_renderbuffers(NULL, fb, fb->Visual.alphaBits,
1884                                    frontLeft, backLeft,
1885                                    frontRight, backRight);
1886   }
1887
1888#if 0
1889   if (multisample) {
1890      /* maybe someday */
1891   }
1892#endif
1893}
1894
1895
1896/**
1897 * Attach a renderbuffer to a framebuffer.
1898 * \param bufferName  one of the BUFFER_x tokens
1899 */
1900void
1901_mesa_add_renderbuffer(struct gl_framebuffer *fb,
1902                       gl_buffer_index bufferName, struct gl_renderbuffer *rb)
1903{
1904   assert(fb);
1905   assert(rb);
1906   assert(bufferName < BUFFER_COUNT);
1907
1908   /* There should be no previous renderbuffer on this attachment point,
1909    * with the exception of depth/stencil since the same renderbuffer may
1910    * be used for both.
1911    */
1912   assert(bufferName == BUFFER_DEPTH ||
1913          bufferName == BUFFER_STENCIL ||
1914          fb->Attachment[bufferName].Renderbuffer == NULL);
1915
1916   /* winsys vs. user-created buffer cross check */
1917   if (fb->Name) {
1918      assert(rb->Name);
1919   }
1920   else {
1921      assert(!rb->Name);
1922   }
1923
1924   fb->Attachment[bufferName].Type = GL_RENDERBUFFER_EXT;
1925   fb->Attachment[bufferName].Complete = GL_TRUE;
1926   _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer, rb);
1927}
1928
1929
1930/**
1931 * Remove the named renderbuffer from the given framebuffer.
1932 * \param bufferName  one of the BUFFER_x tokens
1933 */
1934void
1935_mesa_remove_renderbuffer(struct gl_framebuffer *fb,
1936                          gl_buffer_index bufferName)
1937{
1938   struct gl_renderbuffer *rb;
1939
1940   assert(bufferName < BUFFER_COUNT);
1941
1942   rb = fb->Attachment[bufferName].Renderbuffer;
1943   if (!rb)
1944      return;
1945
1946   _mesa_reference_renderbuffer(&rb, NULL);
1947
1948   fb->Attachment[bufferName].Renderbuffer = NULL;
1949}
1950
1951
1952/**
1953 * Set *ptr to point to rb.  If *ptr points to another renderbuffer,
1954 * dereference that buffer first.  The new renderbuffer's refcount will
1955 * be incremented.  The old renderbuffer's refcount will be decremented.
1956 */
1957void
1958_mesa_reference_renderbuffer(struct gl_renderbuffer **ptr,
1959                             struct gl_renderbuffer *rb)
1960{
1961   assert(ptr);
1962   if (*ptr == rb) {
1963      /* no change */
1964      return;
1965   }
1966
1967   if (*ptr) {
1968      /* Unreference the old renderbuffer */
1969      GLboolean deleteFlag = GL_FALSE;
1970      struct gl_renderbuffer *oldRb = *ptr;
1971
1972      _glthread_LOCK_MUTEX(oldRb->Mutex);
1973      ASSERT(oldRb->RefCount > 0);
1974      oldRb->RefCount--;
1975      /*printf("RB DECR %p (%d) to %d\n", (void*) oldRb, oldRb->Name, oldRb->RefCount);*/
1976      deleteFlag = (oldRb->RefCount == 0);
1977      _glthread_UNLOCK_MUTEX(oldRb->Mutex);
1978
1979      if (deleteFlag) {
1980         oldRb->Delete(oldRb);
1981      }
1982
1983      *ptr = NULL;
1984   }
1985   assert(!*ptr);
1986
1987   if (rb) {
1988      /* reference new renderbuffer */
1989      _glthread_LOCK_MUTEX(rb->Mutex);
1990      rb->RefCount++;
1991      /*printf("RB INCR %p (%d) to %d\n", (void*) rb, rb->Name, rb->RefCount);*/
1992      _glthread_UNLOCK_MUTEX(rb->Mutex);
1993      *ptr = rb;
1994   }
1995}
1996
1997
1998/**
1999 * Create a new combined depth/stencil renderbuffer for implementing
2000 * the GL_EXT_packed_depth_stencil extension.
2001 * \return new depth/stencil renderbuffer
2002 */
2003struct gl_renderbuffer *
2004_mesa_new_depthstencil_renderbuffer(struct gl_context *ctx, GLuint name)
2005{
2006   struct gl_renderbuffer *dsrb;
2007
2008   dsrb = _mesa_new_renderbuffer(ctx, name);
2009   if (!dsrb)
2010      return NULL;
2011
2012   /* init fields not covered by _mesa_new_renderbuffer() */
2013   dsrb->InternalFormat = GL_DEPTH24_STENCIL8_EXT;
2014   dsrb->Format = MESA_FORMAT_Z24_S8;
2015   dsrb->AllocStorage = _mesa_soft_renderbuffer_storage;
2016
2017   return dsrb;
2018}
2019