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