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