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