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