renderbuffer.c revision 76d1275474d7b5ac2f0edf5856ae1c5fc234f0d9
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/* Returns a bytes per pixel of the DataType in the get/put span
57 * functions for at least a subset of the available combinations a
58 * renderbuffer can have.
59 *
60 * It would be nice to see gl_renderbuffer start talking about a
61 * gl_format instead of a GLenum DataType.
62 */
63static int
64get_datatype_bytes(struct gl_renderbuffer *rb)
65{
66   int component_size;
67
68   switch (rb->DataType) {
69   case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
70      component_size = 8;
71      break;
72   case GL_FLOAT:
73   case GL_UNSIGNED_INT:
74   case GL_UNSIGNED_INT_24_8_EXT:
75      component_size = 4;
76      break;
77   case GL_UNSIGNED_SHORT:
78      component_size = 2;
79      break;
80   case GL_UNSIGNED_BYTE:
81      component_size = 1;
82      break;
83   default:
84      component_size = 1;
85      assert(0);
86   }
87
88   switch (rb->_BaseFormat) {
89   case GL_DEPTH_COMPONENT:
90   case GL_DEPTH_STENCIL:
91      return component_size;
92   default:
93      return 4 * component_size;
94   }
95}
96
97/* This is commonly used by most of the accessors. */
98static void *
99get_pointer_generic(struct gl_context *ctx, struct gl_renderbuffer *rb,
100		    GLint x, GLint y)
101{
102   if (!rb->Data)
103      return NULL;
104
105   return ((char *) rb->Data +
106	   (y * rb->RowStride + x) * _mesa_get_format_bytes(rb->Format));
107}
108
109/* GetRow() implementation for formats where DataType matches the rb->Format.
110 */
111static void
112get_row_generic(struct gl_context *ctx, struct gl_renderbuffer *rb,
113		GLuint count, GLint x, GLint y, void *values)
114{
115   void *src = rb->GetPointer(ctx, rb, x, y);
116   memcpy(values, src, count * _mesa_get_format_bytes(rb->Format));
117}
118
119/* Only used for float textures currently, but might also be used for
120 * RGBA8888, RGBA16, etc.
121 */
122static void
123get_values_generic(struct gl_context *ctx, struct gl_renderbuffer *rb,
124		   GLuint count, const GLint x[], const GLint y[], void *values)
125{
126   int format_bytes = _mesa_get_format_bytes(rb->Format) / sizeof(GLfloat);
127   GLuint i;
128
129   for (i = 0; i < count; i++) {
130      const void *src = rb->GetPointer(ctx, rb, x[i], y[i]);
131      char *dst = (char *) values + i * format_bytes;
132      memcpy(dst, src, format_bytes);
133   }
134}
135
136/* For the GL_RED/GL_RG/GL_RGB format/DataType combinations (and
137 * GL_LUMINANCE/GL_INTENSITY?), the Put functions are a matter of
138 * storing those initial components of the value per pixel into the
139 * destination.
140 */
141static void
142put_row_generic(struct gl_context *ctx, struct gl_renderbuffer *rb,
143		GLuint count, GLint x, GLint y,
144		const void *values, const GLubyte *mask)
145{
146   void *row = rb->GetPointer(ctx, rb, x, y);
147   int format_bytes = _mesa_get_format_bytes(rb->Format) / sizeof(GLfloat);
148   int datatype_bytes = get_datatype_bytes(rb);
149   unsigned int i;
150
151   if (mask) {
152      for (i = 0; i < count; i++) {
153	 char *dst = (char *) row + i * format_bytes;
154	 const char *src = (const char *) values + i * datatype_bytes;
155
156         if (mask[i]) {
157	    memcpy(dst, src, format_bytes);
158         }
159      }
160   }
161   else {
162      for (i = 0; i < count; i++) {
163	 char *dst = (char *) row + i * format_bytes;
164	 const char *src = (const char *) values + i * datatype_bytes;
165	 memcpy(dst, src, format_bytes);
166      }
167   }
168}
169
170static void
171put_mono_row_generic(struct gl_context *ctx, struct gl_renderbuffer *rb,
172		     GLuint count, GLint x, GLint y,
173		     const void *value, const GLubyte *mask)
174{
175   void *row = rb->GetPointer(ctx, rb, x, y);
176   int format_bytes = _mesa_get_format_bytes(rb->Format) / sizeof(GLfloat);
177   unsigned int i;
178
179   if (mask) {
180      for (i = 0; i < count; i++) {
181	 char *dst = (char *) row + i * format_bytes;
182         if (mask[i]) {
183	    memcpy(dst, value, format_bytes);
184         }
185      }
186   }
187   else {
188      for (i = 0; i < count; i++) {
189	 char *dst = (char *) row + i * format_bytes;
190	 memcpy(dst, value, format_bytes);
191      }
192   }
193}
194
195
196static void
197put_values_generic(struct gl_context *ctx, struct gl_renderbuffer *rb,
198		   GLuint count, const GLint x[], const GLint y[],
199		   const void *values, const GLubyte *mask)
200{
201   int format_bytes = _mesa_get_format_bytes(rb->Format) / sizeof(GLfloat);
202   int datatype_bytes = get_datatype_bytes(rb);
203   unsigned int i;
204
205   for (i = 0; i < count; i++) {
206      if (!mask || mask[i]) {
207	 void *dst = rb->GetPointer(ctx, rb, x[i], y[i]);
208	 const char *src = (const char *) values + i * datatype_bytes;
209	 memcpy(dst, src, format_bytes);
210      }
211   }
212}
213
214
215static void
216put_mono_values_generic(struct gl_context *ctx,
217			struct gl_renderbuffer *rb,
218			GLuint count, const GLint x[], const GLint y[],
219			const void *value, const GLubyte *mask)
220{
221   int format_bytes = _mesa_get_format_bytes(rb->Format) / sizeof(GLfloat);
222   unsigned int i;
223
224   for (i = 0; i < count; i++) {
225      if (!mask || mask[i]) {
226	 void *dst = rb->GetPointer(ctx, rb, x[i], y[i]);
227	 memcpy(dst, value, format_bytes);
228      }
229   }
230}
231
232/**********************************************************************
233 * Functions for buffers of 1 X GLubyte values.
234 * Typically stencil.
235 */
236
237static void
238get_values_ubyte(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
239                 const GLint x[], const GLint y[], void *values)
240{
241   GLubyte *dst = (GLubyte *) values;
242   GLuint i;
243   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
244   for (i = 0; i < count; i++) {
245      const GLubyte *src = (GLubyte *) rb->Data + y[i] * rb->RowStride + x[i];
246      dst[i] = *src;
247   }
248}
249
250
251static void
252put_row_ubyte(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
253              GLint x, GLint y, const void *values, const GLubyte *mask)
254{
255   const GLubyte *src = (const GLubyte *) values;
256   GLubyte *dst = (GLubyte *) rb->Data + y * rb->RowStride + x;
257   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
258   if (mask) {
259      GLuint i;
260      for (i = 0; i < count; i++) {
261         if (mask[i]) {
262            dst[i] = src[i];
263         }
264      }
265   }
266   else {
267      memcpy(dst, values, count * sizeof(GLubyte));
268   }
269}
270
271
272static void
273put_mono_row_ubyte(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
274                   GLint x, GLint y, const void *value, const GLubyte *mask)
275{
276   const GLubyte val = *((const GLubyte *) value);
277   GLubyte *dst = (GLubyte *) rb->Data + y * rb->RowStride + x;
278   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
279   if (mask) {
280      GLuint i;
281      for (i = 0; i < count; i++) {
282         if (mask[i]) {
283            dst[i] = val;
284         }
285      }
286   }
287   else {
288      GLuint i;
289      for (i = 0; i < count; i++) {
290         dst[i] = val;
291      }
292   }
293}
294
295
296static void
297put_values_ubyte(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
298                 const GLint x[], const GLint y[],
299                 const void *values, const GLubyte *mask)
300{
301   const GLubyte *src = (const GLubyte *) values;
302   GLuint i;
303   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
304   for (i = 0; i < count; i++) {
305      if (!mask || mask[i]) {
306         GLubyte *dst = (GLubyte *) rb->Data + y[i] * rb->RowStride + x[i];
307         *dst = src[i];
308      }
309   }
310}
311
312
313static void
314put_mono_values_ubyte(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
315                      const GLint x[], const GLint y[],
316                      const void *value, const GLubyte *mask)
317{
318   const GLubyte val = *((const GLubyte *) value);
319   GLuint i;
320   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
321   for (i = 0; i < count; i++) {
322      if (!mask || mask[i]) {
323         GLubyte *dst = (GLubyte *) rb->Data + y[i] * rb->RowStride + x[i];
324         *dst = val;
325      }
326   }
327}
328
329
330/**********************************************************************
331 * Functions for buffers of 1 X GLushort values.
332 * Typically depth/Z.
333 */
334
335static void
336get_values_ushort(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
337                  const GLint x[], const GLint y[], void *values)
338{
339   GLushort *dst = (GLushort *) values;
340   GLuint i;
341   ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
342   for (i = 0; i < count; i++) {
343      const GLushort *src = (GLushort *) rb->Data + y[i] * rb->RowStride + x[i];
344      dst[i] = *src;
345   }
346}
347
348
349static void
350put_row_ushort(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
351               GLint x, GLint y, const void *values, const GLubyte *mask)
352{
353   const GLushort *src = (const GLushort *) values;
354   GLushort *dst = (GLushort *) rb->Data + y * rb->RowStride + x;
355   ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
356   if (mask) {
357      GLuint i;
358      for (i = 0; i < count; i++) {
359         if (mask[i]) {
360            dst[i] = src[i];
361         }
362      }
363   }
364   else {
365      memcpy(dst, src, count * sizeof(GLushort));
366   }
367}
368
369
370static void
371put_mono_row_ushort(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
372                    GLint x, GLint y, const void *value, const GLubyte *mask)
373{
374   const GLushort val = *((const GLushort *) value);
375   GLushort *dst = (GLushort *) rb->Data + y * rb->RowStride + x;
376   ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
377   if (mask) {
378      GLuint i;
379      for (i = 0; i < count; i++) {
380         if (mask[i]) {
381            dst[i] = val;
382         }
383      }
384   }
385   else {
386      GLuint i;
387      for (i = 0; i < count; i++) {
388         dst[i] = val;
389      }
390   }
391}
392
393
394static void
395put_values_ushort(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
396                  const GLint x[], const GLint y[], const void *values,
397                  const GLubyte *mask)
398{
399   const GLushort *src = (const GLushort *) values;
400   GLuint i;
401   ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
402   for (i = 0; i < count; i++) {
403      if (!mask || mask[i]) {
404         GLushort *dst = (GLushort *) rb->Data + y[i] * rb->RowStride + x[i];
405         *dst = src[i];
406      }
407   }
408}
409
410
411static void
412put_mono_values_ushort(struct gl_context *ctx, struct gl_renderbuffer *rb,
413                       GLuint count, const GLint x[], const GLint y[],
414                       const void *value, const GLubyte *mask)
415{
416   const GLushort val = *((const GLushort *) value);
417   ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
418   if (mask) {
419      GLuint i;
420      for (i = 0; i < count; i++) {
421         if (mask[i]) {
422            GLushort *dst = (GLushort *) rb->Data + y[i] * rb->RowStride + x[i];
423            *dst = val;
424         }
425      }
426   }
427   else {
428      GLuint i;
429      for (i = 0; i < count; i++) {
430         GLushort *dst = (GLushort *) rb->Data + y[i] * rb->RowStride + x[i];
431         *dst = val;
432      }
433   }
434}
435
436
437/**********************************************************************
438 * Functions for buffers of 1 X GLuint values.
439 * Typically depth/Z or color index.
440 */
441
442static void
443get_values_uint(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
444                const GLint x[], const GLint y[], void *values)
445{
446   GLuint *dst = (GLuint *) values;
447   GLuint i;
448   ASSERT(rb->DataType == GL_UNSIGNED_INT ||
449          rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
450   for (i = 0; i < count; i++) {
451      const GLuint *src = (GLuint *) rb->Data + y[i] * rb->RowStride + x[i];
452      dst[i] = *src;
453   }
454}
455
456
457static void
458put_row_uint(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
459             GLint x, GLint y, const void *values, const GLubyte *mask)
460{
461   const GLuint *src = (const GLuint *) values;
462   GLuint *dst = (GLuint *) rb->Data + y * rb->RowStride + x;
463   ASSERT(rb->DataType == GL_UNSIGNED_INT ||
464          rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
465   if (mask) {
466      GLuint i;
467      for (i = 0; i < count; i++) {
468         if (mask[i]) {
469            dst[i] = src[i];
470         }
471      }
472   }
473   else {
474      memcpy(dst, src, count * sizeof(GLuint));
475   }
476}
477
478
479static void
480put_mono_row_uint(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
481                  GLint x, GLint y, const void *value, const GLubyte *mask)
482{
483   const GLuint val = *((const GLuint *) value);
484   GLuint *dst = (GLuint *) rb->Data + y * rb->RowStride + x;
485   ASSERT(rb->DataType == GL_UNSIGNED_INT ||
486          rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
487   if (mask) {
488      GLuint i;
489      for (i = 0; i < count; i++) {
490         if (mask[i]) {
491            dst[i] = val;
492         }
493      }
494   }
495   else {
496      GLuint i;
497      for (i = 0; i < count; i++) {
498         dst[i] = val;
499      }
500   }
501}
502
503
504static void
505put_values_uint(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
506                const GLint x[], const GLint y[], const void *values,
507                const GLubyte *mask)
508{
509   const GLuint *src = (const GLuint *) values;
510   GLuint i;
511   ASSERT(rb->DataType == GL_UNSIGNED_INT ||
512          rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
513   for (i = 0; i < count; i++) {
514      if (!mask || mask[i]) {
515         GLuint *dst = (GLuint *) rb->Data + y[i] * rb->RowStride + x[i];
516         *dst = src[i];
517      }
518   }
519}
520
521
522static void
523put_mono_values_uint(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
524                     const GLint x[], const GLint y[], const void *value,
525                     const GLubyte *mask)
526{
527   const GLuint val = *((const GLuint *) value);
528   GLuint i;
529   ASSERT(rb->DataType == GL_UNSIGNED_INT ||
530          rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
531   for (i = 0; i < count; i++) {
532      if (!mask || mask[i]) {
533         GLuint *dst = (GLuint *) rb->Data + y[i] * rb->RowStride + x[i];
534         *dst = val;
535      }
536   }
537}
538
539
540/**********************************************************************
541 * Functions for buffers of 3 X GLubyte (or GLbyte) values.
542 * Typically color buffers.
543 * NOTE: the incoming and outgoing colors are RGBA!  We ignore incoming
544 * alpha values and return 255 for outgoing alpha values.
545 */
546
547static void *
548get_pointer_ubyte3(struct gl_context *ctx, struct gl_renderbuffer *rb,
549                   GLint x, GLint y)
550{
551   ASSERT(rb->Format == MESA_FORMAT_RGB888);
552   /* No direct access since this buffer is RGB but caller will be
553    * treating it as if it were RGBA.
554    */
555   return NULL;
556}
557
558
559static void
560get_row_ubyte3(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
561               GLint x, GLint y, void *values)
562{
563   const GLubyte *src = ((const GLubyte *) rb->Data) +
564					   3 * (y * rb->RowStride + x);
565   GLubyte *dst = (GLubyte *) values;
566   GLuint i;
567   ASSERT(rb->Format == MESA_FORMAT_RGB888);
568   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
569   for (i = 0; i < count; i++) {
570      dst[i * 4 + 0] = src[i * 3 + 0];
571      dst[i * 4 + 1] = src[i * 3 + 1];
572      dst[i * 4 + 2] = src[i * 3 + 2];
573      dst[i * 4 + 3] = 255;
574   }
575}
576
577
578static void
579get_values_ubyte3(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
580                  const GLint x[], const GLint y[], void *values)
581{
582   GLubyte *dst = (GLubyte *) values;
583   GLuint i;
584   ASSERT(rb->Format == MESA_FORMAT_RGB888);
585   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
586   for (i = 0; i < count; i++) {
587      const GLubyte *src
588         = (GLubyte *) rb->Data + 3 * (y[i] * rb->RowStride + x[i]);
589      dst[i * 4 + 0] = src[0];
590      dst[i * 4 + 1] = src[1];
591      dst[i * 4 + 2] = src[2];
592      dst[i * 4 + 3] = 255;
593   }
594}
595
596
597static void
598put_row_ubyte3(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
599               GLint x, GLint y, const void *values, const GLubyte *mask)
600{
601   /* note: incoming values are RGB+A! */
602   const GLubyte *src = (const GLubyte *) values;
603   GLubyte *dst = (GLubyte *) rb->Data + 3 * (y * rb->RowStride + x);
604   GLuint i;
605   ASSERT(rb->Format == MESA_FORMAT_RGB888);
606   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
607   for (i = 0; i < count; i++) {
608      if (!mask || mask[i]) {
609         dst[i * 3 + 0] = src[i * 4 + 0];
610         dst[i * 3 + 1] = src[i * 4 + 1];
611         dst[i * 3 + 2] = src[i * 4 + 2];
612      }
613   }
614}
615
616
617static void
618put_row_rgb_ubyte3(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
619                   GLint x, GLint y, const void *values, const GLubyte *mask)
620{
621   /* note: incoming values are RGB+A! */
622   const GLubyte *src = (const GLubyte *) values;
623   GLubyte *dst = (GLubyte *) rb->Data + 3 * (y * rb->RowStride + x);
624   GLuint i;
625   ASSERT(rb->Format == MESA_FORMAT_RGB888);
626   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
627   for (i = 0; i < count; i++) {
628      if (!mask || mask[i]) {
629         dst[i * 3 + 0] = src[i * 3 + 0];
630         dst[i * 3 + 1] = src[i * 3 + 1];
631         dst[i * 3 + 2] = src[i * 3 + 2];
632      }
633   }
634}
635
636
637static void
638put_mono_row_ubyte3(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
639                    GLint x, GLint y, const void *value, const GLubyte *mask)
640{
641   /* note: incoming value is RGB+A! */
642   const GLubyte val0 = ((const GLubyte *) value)[0];
643   const GLubyte val1 = ((const GLubyte *) value)[1];
644   const GLubyte val2 = ((const GLubyte *) value)[2];
645   GLubyte *dst = (GLubyte *) rb->Data + 3 * (y * rb->RowStride + x);
646   ASSERT(rb->Format == MESA_FORMAT_RGB888);
647   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
648   if (!mask && val0 == val1 && val1 == val2) {
649      /* optimized case */
650      memset(dst, val0, 3 * count);
651   }
652   else {
653      GLuint i;
654      for (i = 0; i < count; i++) {
655         if (!mask || mask[i]) {
656            dst[i * 3 + 0] = val0;
657            dst[i * 3 + 1] = val1;
658            dst[i * 3 + 2] = val2;
659         }
660      }
661   }
662}
663
664
665static void
666put_values_ubyte3(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
667                  const GLint x[], const GLint y[], const void *values,
668                  const GLubyte *mask)
669{
670   /* note: incoming values are RGB+A! */
671   const GLubyte *src = (const GLubyte *) values;
672   GLuint i;
673   ASSERT(rb->Format == MESA_FORMAT_RGB888);
674   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
675   for (i = 0; i < count; i++) {
676      if (!mask || mask[i]) {
677         GLubyte *dst = (GLubyte *) rb->Data + 3 * (y[i] * rb->RowStride + x[i]);
678         dst[0] = src[i * 4 + 0];
679         dst[1] = src[i * 4 + 1];
680         dst[2] = src[i * 4 + 2];
681      }
682   }
683}
684
685
686static void
687put_mono_values_ubyte3(struct gl_context *ctx, struct gl_renderbuffer *rb,
688                       GLuint count, const GLint x[], const GLint y[],
689                       const void *value, const GLubyte *mask)
690{
691   /* note: incoming value is RGB+A! */
692   const GLubyte val0 = ((const GLubyte *) value)[0];
693   const GLubyte val1 = ((const GLubyte *) value)[1];
694   const GLubyte val2 = ((const GLubyte *) value)[2];
695   GLuint i;
696   ASSERT(rb->Format == MESA_FORMAT_RGB888);
697   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
698   for (i = 0; i < count; i++) {
699      if (!mask || mask[i]) {
700         GLubyte *dst = ((GLubyte *) rb->Data) +
701				     3 * (y[i] * rb->RowStride + x[i]);
702         dst[0] = val0;
703         dst[1] = val1;
704         dst[2] = val2;
705      }
706   }
707}
708
709
710/**********************************************************************
711 * Functions for buffers of 4 X GLubyte (or GLbyte) values.
712 * Typically color buffers.
713 */
714
715static void
716get_values_ubyte4(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
717                  const GLint x[], const GLint y[], void *values)
718{
719   /* treat 4*GLubyte as 1*GLuint */
720   GLuint *dst = (GLuint *) values;
721   GLuint i;
722   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
723   ASSERT(rb->Format == MESA_FORMAT_RGBA8888);
724   for (i = 0; i < count; i++) {
725      const GLuint *src = (GLuint *) rb->Data + (y[i] * rb->RowStride + x[i]);
726      dst[i] = *src;
727   }
728}
729
730
731static void
732put_row_ubyte4(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
733               GLint x, GLint y, const void *values, const GLubyte *mask)
734{
735   /* treat 4*GLubyte as 1*GLuint */
736   const GLuint *src = (const GLuint *) values;
737   GLuint *dst = (GLuint *) rb->Data + (y * rb->RowStride + x);
738   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
739   ASSERT(rb->Format == MESA_FORMAT_RGBA8888);
740   if (mask) {
741      GLuint i;
742      for (i = 0; i < count; i++) {
743         if (mask[i]) {
744            dst[i] = src[i];
745         }
746      }
747   }
748   else {
749      memcpy(dst, src, 4 * count * sizeof(GLubyte));
750   }
751}
752
753
754static void
755put_row_rgb_ubyte4(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
756                   GLint x, GLint y, const void *values, const GLubyte *mask)
757{
758   /* Store RGB values in RGBA buffer */
759   const GLubyte *src = (const GLubyte *) values;
760   GLubyte *dst = (GLubyte *) rb->Data + 4 * (y * rb->RowStride + x);
761   GLuint i;
762   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
763   ASSERT(rb->Format == MESA_FORMAT_RGBA8888);
764   for (i = 0; i < count; i++) {
765      if (!mask || mask[i]) {
766         dst[i * 4 + 0] = src[i * 3 + 0];
767         dst[i * 4 + 1] = src[i * 3 + 1];
768         dst[i * 4 + 2] = src[i * 3 + 2];
769         dst[i * 4 + 3] = 0xff;
770      }
771   }
772}
773
774
775static void
776put_mono_row_ubyte4(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
777                    GLint x, GLint y, const void *value, const GLubyte *mask)
778{
779   /* treat 4*GLubyte as 1*GLuint */
780   const GLuint val = *((const GLuint *) value);
781   GLuint *dst = (GLuint *) rb->Data + (y * rb->RowStride + x);
782   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
783   ASSERT(rb->Format == MESA_FORMAT_RGBA8888);
784   if (!mask && val == 0) {
785      /* common case */
786      memset(dst, 0, count * 4 * sizeof(GLubyte));
787   }
788   else {
789      /* general case */
790      if (mask) {
791         GLuint i;
792         for (i = 0; i < count; i++) {
793            if (mask[i]) {
794               dst[i] = val;
795            }
796         }
797      }
798      else {
799         GLuint i;
800         for (i = 0; i < count; i++) {
801            dst[i] = val;
802         }
803      }
804   }
805}
806
807
808static void
809put_values_ubyte4(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
810                  const GLint x[], const GLint y[], const void *values,
811                  const GLubyte *mask)
812{
813   /* treat 4*GLubyte as 1*GLuint */
814   const GLuint *src = (const GLuint *) values;
815   GLuint i;
816   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
817   ASSERT(rb->Format == MESA_FORMAT_RGBA8888);
818   for (i = 0; i < count; i++) {
819      if (!mask || mask[i]) {
820         GLuint *dst = (GLuint *) rb->Data + (y[i] * rb->RowStride + x[i]);
821         *dst = src[i];
822      }
823   }
824}
825
826
827static void
828put_mono_values_ubyte4(struct gl_context *ctx, struct gl_renderbuffer *rb,
829                       GLuint count, const GLint x[], const GLint y[],
830                       const void *value, const GLubyte *mask)
831{
832   /* treat 4*GLubyte as 1*GLuint */
833   const GLuint val = *((const GLuint *) value);
834   GLuint i;
835   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
836   ASSERT(rb->Format == MESA_FORMAT_RGBA8888);
837   for (i = 0; i < count; i++) {
838      if (!mask || mask[i]) {
839         GLuint *dst = (GLuint *) rb->Data + (y[i] * rb->RowStride + x[i]);
840         *dst = val;
841      }
842   }
843}
844
845
846/**********************************************************************
847 * Functions for buffers of 4 X GLushort (or GLshort) values.
848 * Typically accum buffer.
849 */
850
851static void
852get_values_ushort4(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
853                   const GLint x[], const GLint y[], void *values)
854{
855   GLushort *dst = (GLushort *) values;
856   GLuint i;
857   ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
858   for (i = 0; i < count; i++) {
859      const GLushort *src
860         = (GLushort *) rb->Data + 4 * (y[i] * rb->RowStride + x[i]);
861      dst[i] = *src;
862   }
863}
864
865
866static void
867put_row_ushort4(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
868                GLint x, GLint y, const void *values, const GLubyte *mask)
869{
870   const GLushort *src = (const GLushort *) values;
871   GLushort *dst = (GLushort *) rb->Data + 4 * (y * rb->RowStride + x);
872   ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
873   if (mask) {
874      GLuint i;
875      for (i = 0; i < count; i++) {
876         if (mask[i]) {
877            dst[i * 4 + 0] = src[i * 4 + 0];
878            dst[i * 4 + 1] = src[i * 4 + 1];
879            dst[i * 4 + 2] = src[i * 4 + 2];
880            dst[i * 4 + 3] = src[i * 4 + 3];
881         }
882      }
883   }
884   else {
885      memcpy(dst, src, 4 * count * sizeof(GLushort));
886   }
887}
888
889
890static void
891put_row_rgb_ushort4(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
892                    GLint x, GLint y, const void *values, const GLubyte *mask)
893{
894   /* Put RGB values in RGBA buffer */
895   const GLushort *src = (const GLushort *) values;
896   GLushort *dst = (GLushort *) rb->Data + 4 * (y * rb->RowStride + x);
897   ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
898   if (mask) {
899      GLuint i;
900      for (i = 0; i < count; i++) {
901         if (mask[i]) {
902            dst[i * 4 + 0] = src[i * 3 + 0];
903            dst[i * 4 + 1] = src[i * 3 + 1];
904            dst[i * 4 + 2] = src[i * 3 + 2];
905            dst[i * 4 + 3] = 0xffff;
906         }
907      }
908   }
909   else {
910      memcpy(dst, src, 4 * count * sizeof(GLushort));
911   }
912}
913
914
915static void
916put_mono_row_ushort4(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
917                     GLint x, GLint y, const void *value, const GLubyte *mask)
918{
919   const GLushort val0 = ((const GLushort *) value)[0];
920   const GLushort val1 = ((const GLushort *) value)[1];
921   const GLushort val2 = ((const GLushort *) value)[2];
922   const GLushort val3 = ((const GLushort *) value)[3];
923   GLushort *dst = (GLushort *) rb->Data + 4 * (y * rb->RowStride + x);
924   ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
925   if (!mask && val0 == 0 && val1 == 0 && val2 == 0 && val3 == 0) {
926      /* common case for clearing accum buffer */
927      memset(dst, 0, count * 4 * sizeof(GLushort));
928   }
929   else {
930      GLuint i;
931      for (i = 0; i < count; i++) {
932         if (!mask || mask[i]) {
933            dst[i * 4 + 0] = val0;
934            dst[i * 4 + 1] = val1;
935            dst[i * 4 + 2] = val2;
936            dst[i * 4 + 3] = val3;
937         }
938      }
939   }
940}
941
942
943static void
944put_values_ushort4(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
945                   const GLint x[], const GLint y[], const void *values,
946                   const GLubyte *mask)
947{
948   const GLushort *src = (const GLushort *) values;
949   GLuint i;
950   ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
951   for (i = 0; i < count; i++) {
952      if (!mask || mask[i]) {
953         GLushort *dst =
954            ((GLushort *) rb->Data) + 4 * (y[i] * rb->RowStride + x[i]);
955         dst[0] = src[i * 4 + 0];
956         dst[1] = src[i * 4 + 1];
957         dst[2] = src[i * 4 + 2];
958         dst[3] = src[i * 4 + 3];
959      }
960   }
961}
962
963
964static void
965put_mono_values_ushort4(struct gl_context *ctx, struct gl_renderbuffer *rb,
966                        GLuint count, const GLint x[], const GLint y[],
967                        const void *value, const GLubyte *mask)
968{
969   const GLushort val0 = ((const GLushort *) value)[0];
970   const GLushort val1 = ((const GLushort *) value)[1];
971   const GLushort val2 = ((const GLushort *) value)[2];
972   const GLushort val3 = ((const GLushort *) value)[3];
973   GLuint i;
974   ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
975   for (i = 0; i < count; i++) {
976      if (!mask || mask[i]) {
977         GLushort *dst = ((GLushort *) rb->Data) +
978				       4 * (y[i] * rb->RowStride + x[i]);
979         dst[0] = val0;
980         dst[1] = val1;
981         dst[2] = val2;
982         dst[3] = val3;
983      }
984   }
985}
986
987/**********************************************************************
988 * Functions for MESA_FORMAT_R8.
989 */
990static void
991get_row_r8(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
992	   GLint x, GLint y, void *values)
993{
994   const GLubyte *src = rb->GetPointer(ctx, rb, x, y);
995   GLuint *dst = values;
996   GLuint i;
997
998   for (i = 0; i < count; i++) {
999      dst[i] = 0xff000000 | src[i];
1000   }
1001}
1002
1003static void
1004get_values_r8(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
1005	      const GLint x[], const GLint y[], void *values)
1006{
1007   GLuint *dst = (GLuint *) values;
1008   GLuint i;
1009
1010   for (i = 0; i < count; i++) {
1011      const GLubyte *src = rb->GetPointer(ctx, rb, x[i], y[i]);
1012      dst[i] = 0xff000000 | *src;
1013   }
1014}
1015
1016/**********************************************************************
1017 * Functions for MESA_FORMAT_RG88.
1018 */
1019static void
1020get_row_rg88(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
1021	     GLint x, GLint y, void *values)
1022{
1023   const GLushort *src = rb->GetPointer(ctx, rb, x, y);
1024   GLuint *dst = values;
1025   GLuint i;
1026
1027   for (i = 0; i < count; i++) {
1028      dst[i] = 0xff000000 | src[i];
1029   }
1030}
1031
1032static void
1033get_values_rg88(struct gl_context *ctx, struct gl_renderbuffer *rb,
1034		GLuint count, const GLint x[], const GLint y[], void *values)
1035{
1036   GLuint *dst = (GLuint *) values;
1037   GLuint i;
1038
1039   for (i = 0; i < count; i++) {
1040      const GLshort *src = rb->GetPointer(ctx, rb, x[i], y[i]);
1041      dst[i] = 0xff000000 | *src;
1042   }
1043}
1044
1045/**********************************************************************
1046 * Functions for MESA_FORMAT_R16.
1047 */
1048static void
1049get_row_r16(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
1050	    GLint x, GLint y, void *values)
1051{
1052   const GLushort *src = rb->GetPointer(ctx, rb, x, y);
1053   GLushort *dst = values;
1054   GLuint i;
1055
1056   for (i = 0; i < count; i++) {
1057      dst[i * 4 + RCOMP] = src[i];
1058      dst[i * 4 + GCOMP] = 0;
1059      dst[i * 4 + BCOMP] = 0;
1060      dst[i * 4 + ACOMP] = 0xffff;
1061   }
1062}
1063
1064static void
1065get_values_r16(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
1066	       const GLint x[], const GLint y[], void *values)
1067{
1068   GLushort *dst = values;
1069   GLuint i;
1070
1071   for (i = 0; i < count; i++) {
1072      const GLushort *src = rb->GetPointer(ctx, rb, x[i], y[i]);
1073      dst[i * 4 + RCOMP] = *src;
1074      dst[i * 4 + GCOMP] = 0;
1075      dst[i * 4 + BCOMP] = 0;
1076      dst[i * 4 + ACOMP] = 0xffff;
1077   }
1078}
1079
1080/**********************************************************************
1081 * Functions for MESA_FORMAT_RG1616.
1082 */
1083static void
1084get_row_rg1616(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
1085	       GLint x, GLint y, void *values)
1086{
1087   const GLushort *src = rb->GetPointer(ctx, rb, x, y);
1088   GLushort *dst = values;
1089   GLuint i;
1090
1091   for (i = 0; i < count; i++) {
1092      dst[i * 4 + RCOMP] = src[i * 2];
1093      dst[i * 4 + GCOMP] = src[i * 2 + 1];
1094      dst[i * 4 + BCOMP] = 0;
1095      dst[i * 4 + ACOMP] = 0xffff;
1096   }
1097}
1098
1099static void
1100get_values_rg1616(struct gl_context *ctx, struct gl_renderbuffer *rb,
1101		  GLuint count, const GLint x[], const GLint y[], void *values)
1102{
1103   GLushort *dst = values;
1104   GLuint i;
1105
1106   for (i = 0; i < count; i++) {
1107      const GLshort *src = rb->GetPointer(ctx, rb, x[i], y[i]);
1108      dst[i * 4 + RCOMP] = src[0];
1109      dst[i * 4 + GCOMP] = src[1];
1110      dst[i * 4 + BCOMP] = 0;
1111      dst[i * 4 + ACOMP] = 0xffff;
1112   }
1113}
1114
1115/**********************************************************************
1116 * Functions for MESA_FORMAT_INTENSITY_FLOAT32.
1117 */
1118static void
1119get_row_i_float32(struct gl_context *ctx, struct gl_renderbuffer *rb,
1120		  GLuint count, GLint x, GLint y, void *values)
1121{
1122   const GLfloat *src = rb->GetPointer(ctx, rb, x, y);
1123   GLfloat *dst = values;
1124   GLuint i;
1125
1126   for (i = 0; i < count; i++) {
1127      dst[i * 4 + RCOMP] =
1128      dst[i * 4 + GCOMP] =
1129      dst[i * 4 + BCOMP] =
1130      dst[i * 4 + ACOMP] = src[i];
1131   }
1132}
1133
1134static void
1135get_values_i_float32(struct gl_context *ctx, struct gl_renderbuffer *rb,
1136		     GLuint count, const GLint x[], const GLint y[],
1137		     void *values)
1138{
1139   GLfloat *dst = values;
1140   GLuint i;
1141
1142   for (i = 0; i < count; i++) {
1143      const GLfloat *src = rb->GetPointer(ctx, rb, x[i], y[i]);
1144      dst[i * 4 + RCOMP] =
1145      dst[i * 4 + GCOMP] =
1146      dst[i * 4 + BCOMP] =
1147      dst[i * 4 + ACOMP] = src[0];
1148   }
1149}
1150
1151/**********************************************************************
1152 * Functions for MESA_FORMAT_LUMINANCE_FLOAT32.
1153 */
1154static void
1155get_row_l_float32(struct gl_context *ctx, struct gl_renderbuffer *rb,
1156		  GLuint count, GLint x, GLint y, void *values)
1157{
1158   const GLfloat *src = rb->GetPointer(ctx, rb, x, y);
1159   GLfloat *dst = values;
1160   GLuint i;
1161
1162   for (i = 0; i < count; i++) {
1163      dst[i * 4 + RCOMP] =
1164      dst[i * 4 + GCOMP] =
1165      dst[i * 4 + BCOMP] = src[i];
1166      dst[i * 4 + ACOMP] = 1.0;
1167   }
1168}
1169
1170static void
1171get_values_l_float32(struct gl_context *ctx, struct gl_renderbuffer *rb,
1172		     GLuint count, const GLint x[], const GLint y[],
1173		     void *values)
1174{
1175   GLfloat *dst = values;
1176   GLuint i;
1177
1178   for (i = 0; i < count; i++) {
1179      const GLfloat *src = rb->GetPointer(ctx, rb, x[i], y[i]);
1180      dst[i * 4 + RCOMP] =
1181      dst[i * 4 + GCOMP] =
1182      dst[i * 4 + BCOMP] = src[0];
1183      dst[i * 4 + ACOMP] = 1.0;
1184   }
1185}
1186
1187/**********************************************************************
1188 * Functions for MESA_FORMAT_ALPHA_FLOAT32.
1189 */
1190static void
1191get_row_a_float32(struct gl_context *ctx, struct gl_renderbuffer *rb,
1192		  GLuint count, GLint x, GLint y, void *values)
1193{
1194   const GLfloat *src = rb->GetPointer(ctx, rb, x, y);
1195   GLfloat *dst = values;
1196   GLuint i;
1197
1198   for (i = 0; i < count; i++) {
1199      dst[i * 4 + RCOMP] = 0.0;
1200      dst[i * 4 + GCOMP] = 0.0;
1201      dst[i * 4 + BCOMP] = 0.0;
1202      dst[i * 4 + ACOMP] = src[i];
1203   }
1204}
1205
1206static void
1207get_values_a_float32(struct gl_context *ctx, struct gl_renderbuffer *rb,
1208		     GLuint count, const GLint x[], const GLint y[],
1209		     void *values)
1210{
1211   GLfloat *dst = values;
1212   GLuint i;
1213
1214   for (i = 0; i < count; i++) {
1215      const GLfloat *src = rb->GetPointer(ctx, rb, x[i], y[i]);
1216      dst[i * 4 + RCOMP] = 0.0;
1217      dst[i * 4 + GCOMP] = 0.0;
1218      dst[i * 4 + BCOMP] = 0.0;
1219      dst[i * 4 + ACOMP] = src[0];
1220   }
1221}
1222
1223static void
1224put_row_a_float32(struct gl_context *ctx, struct gl_renderbuffer *rb,
1225		  GLuint count, GLint x, GLint y,
1226		  const void *values, const GLubyte *mask)
1227{
1228   float *dst = rb->GetPointer(ctx, rb, x, y);
1229   const float *src = values;
1230   unsigned int i;
1231
1232   if (mask) {
1233      for (i = 0; i < count; i++) {
1234         if (mask[i]) {
1235	    dst[i] = src[i * 4 + ACOMP];
1236         }
1237      }
1238   }
1239   else {
1240      for (i = 0; i < count; i++) {
1241	 dst[i] = src[i * 4 + ACOMP];
1242      }
1243   }
1244}
1245
1246static void
1247put_mono_row_a_float32(struct gl_context *ctx, struct gl_renderbuffer *rb,
1248		       GLuint count, GLint x, GLint y,
1249		       const void *value, const GLubyte *mask)
1250{
1251   float *dst = rb->GetPointer(ctx, rb, x, y);
1252   const float *src = value;
1253   unsigned int i;
1254
1255   if (mask) {
1256      for (i = 0; i < count; i++) {
1257         if (mask[i]) {
1258	    dst[i] = src[ACOMP];
1259         }
1260      }
1261   }
1262   else {
1263      for (i = 0; i < count; i++) {
1264	 dst[i] = src[ACOMP];
1265      }
1266   }
1267}
1268
1269static void
1270put_values_a_float32(struct gl_context *ctx, struct gl_renderbuffer *rb,
1271		     GLuint count, const GLint x[], const GLint y[],
1272		     const void *values, const GLubyte *mask)
1273{
1274   const float *src = values;
1275   unsigned int i;
1276
1277   for (i = 0; i < count; i++) {
1278      if (!mask || mask[i]) {
1279	 float *dst = rb->GetPointer(ctx, rb, x[i], y[i]);
1280
1281	 *dst = src[i * 4 + ACOMP];
1282      }
1283   }
1284}
1285
1286static void
1287put_mono_values_a_float32(struct gl_context *ctx,
1288			  struct gl_renderbuffer *rb,
1289			  GLuint count, const GLint x[], const GLint y[],
1290			  const void *value, const GLubyte *mask)
1291{
1292   const float *src = value;
1293   unsigned int i;
1294
1295   for (i = 0; i < count; i++) {
1296      if (!mask || mask[i]) {
1297	 float *dst = rb->GetPointer(ctx, rb, x[i], y[i]);
1298	 *dst = src[ACOMP];
1299      }
1300   }
1301}
1302
1303/**********************************************************************
1304 * Functions for MESA_FORMAT_R_FLOAT32.
1305 */
1306static void
1307get_row_r_float32(struct gl_context *ctx, struct gl_renderbuffer *rb,
1308		  GLuint count, GLint x, GLint y, void *values)
1309{
1310   const GLfloat *src = rb->GetPointer(ctx, rb, x, y);
1311   GLfloat *dst = values;
1312   GLuint i;
1313
1314   for (i = 0; i < count; i++) {
1315      dst[i * 4 + RCOMP] = src[i];
1316      dst[i * 4 + GCOMP] = 0.0;
1317      dst[i * 4 + BCOMP] = 0.0;
1318      dst[i * 4 + ACOMP] = 1.0;
1319   }
1320}
1321
1322static void
1323get_values_r_float32(struct gl_context *ctx, struct gl_renderbuffer *rb,
1324		     GLuint count, const GLint x[], const GLint y[],
1325		     void *values)
1326{
1327   GLfloat *dst = values;
1328   GLuint i;
1329
1330   for (i = 0; i < count; i++) {
1331      const GLfloat *src = rb->GetPointer(ctx, rb, x[i], y[i]);
1332      dst[i * 4 + RCOMP] = src[0];
1333      dst[i * 4 + GCOMP] = 0.0;
1334      dst[i * 4 + BCOMP] = 0.0;
1335      dst[i * 4 + ACOMP] = 1.0;
1336   }
1337}
1338
1339/**********************************************************************
1340 * Functions for MESA_FORMAT_RG_FLOAT32.
1341 */
1342static void
1343get_row_rg_float32(struct gl_context *ctx, struct gl_renderbuffer *rb,
1344		   GLuint count, GLint x, GLint y, void *values)
1345{
1346   const GLfloat *src = rb->GetPointer(ctx, rb, x, y);
1347   GLfloat *dst = values;
1348   GLuint i;
1349
1350   for (i = 0; i < count; i++) {
1351      dst[i * 4 + RCOMP] = src[i * 2 + 0];
1352      dst[i * 4 + GCOMP] = src[i * 2 + 1];
1353      dst[i * 4 + BCOMP] = 0.0;
1354      dst[i * 4 + ACOMP] = 1.0;
1355   }
1356}
1357
1358static void
1359get_values_rg_float32(struct gl_context *ctx, struct gl_renderbuffer *rb,
1360		      GLuint count, const GLint x[], const GLint y[],
1361		      void *values)
1362{
1363   GLfloat *dst = values;
1364   GLuint i;
1365
1366   for (i = 0; i < count; i++) {
1367      const GLfloat *src = rb->GetPointer(ctx, rb, x[i], y[i]);
1368      dst[i * 4 + RCOMP] = src[0];
1369      dst[i * 4 + GCOMP] = src[1];
1370      dst[i * 4 + BCOMP] = 0.0;
1371      dst[i * 4 + ACOMP] = 1.0;
1372   }
1373}
1374
1375/**
1376 * This is the default software fallback for gl_renderbuffer's span
1377 * access functions.
1378 *
1379 * The assumptions are that rb->Data will be a pointer to (0,0), that pixels
1380 * are packed in the type of rb->Format, and that subsequent rows appear
1381 * rb->RowStride pixels later.
1382 */
1383void
1384_mesa_set_renderbuffer_accessors(struct gl_renderbuffer *rb)
1385{
1386   rb->GetPointer = get_pointer_generic;
1387   rb->GetRow = get_row_generic;
1388
1389   switch (rb->Format) {
1390   case MESA_FORMAT_RGB888:
1391      rb->DataType = GL_UNSIGNED_BYTE;
1392      rb->GetPointer = get_pointer_ubyte3;
1393      rb->GetRow = get_row_ubyte3;
1394      rb->GetValues = get_values_ubyte3;
1395      rb->PutRow = put_row_ubyte3;
1396      rb->PutRowRGB = put_row_rgb_ubyte3;
1397      rb->PutMonoRow = put_mono_row_ubyte3;
1398      rb->PutValues = put_values_ubyte3;
1399      rb->PutMonoValues = put_mono_values_ubyte3;
1400      break;
1401
1402   case MESA_FORMAT_RGBA8888:
1403      rb->DataType = GL_UNSIGNED_BYTE;
1404      rb->GetValues = get_values_ubyte4;
1405      rb->PutRow = put_row_ubyte4;
1406      rb->PutRowRGB = put_row_rgb_ubyte4;
1407      rb->PutMonoRow = put_mono_row_ubyte4;
1408      rb->PutValues = put_values_ubyte4;
1409      rb->PutMonoValues = put_mono_values_ubyte4;
1410      break;
1411
1412   case MESA_FORMAT_R8:
1413      rb->DataType = GL_UNSIGNED_BYTE;
1414      rb->GetValues = get_values_r8;
1415      rb->GetRow = get_row_r8;
1416      rb->PutRow = put_row_generic;
1417      rb->PutRowRGB = put_row_generic;
1418      rb->PutMonoRow = put_mono_row_generic;
1419      rb->PutValues = put_values_generic;
1420      rb->PutMonoValues = put_mono_values_generic;
1421      break;
1422
1423   case MESA_FORMAT_RG88:
1424      rb->DataType = GL_UNSIGNED_BYTE;
1425      rb->GetValues = get_values_rg88;
1426      rb->GetRow = get_row_rg88;
1427      rb->PutRow = put_row_generic;
1428      rb->PutRowRGB = put_row_generic;
1429      rb->PutMonoRow = put_mono_row_generic;
1430      rb->PutValues = put_values_generic;
1431      rb->PutMonoValues = put_mono_values_generic;
1432      break;
1433
1434   case MESA_FORMAT_R16:
1435      rb->DataType = GL_UNSIGNED_SHORT;
1436      rb->GetValues = get_values_r16;
1437      rb->GetRow = get_row_r16;
1438      rb->PutRow = put_row_generic;
1439      rb->PutRowRGB = put_row_generic;
1440      rb->PutMonoRow = put_mono_row_generic;
1441      rb->PutValues = put_values_generic;
1442      rb->PutMonoValues = put_mono_values_generic;
1443      break;
1444
1445   case MESA_FORMAT_RG1616:
1446      rb->DataType = GL_UNSIGNED_SHORT;
1447      rb->GetValues = get_values_rg1616;
1448      rb->GetRow = get_row_rg1616;
1449      rb->PutRow = put_row_generic;
1450      rb->PutRowRGB = put_row_generic;
1451      rb->PutMonoRow = put_mono_row_generic;
1452      rb->PutValues = put_values_generic;
1453      rb->PutMonoValues = put_mono_values_generic;
1454      break;
1455
1456   case MESA_FORMAT_SIGNED_RGBA_16:
1457      rb->DataType = GL_SHORT;
1458      rb->GetValues = get_values_ushort4;
1459      rb->PutRow = put_row_ushort4;
1460      rb->PutRowRGB = put_row_rgb_ushort4;
1461      rb->PutMonoRow = put_mono_row_ushort4;
1462      rb->PutValues = put_values_ushort4;
1463      rb->PutMonoValues = put_mono_values_ushort4;
1464      break;
1465
1466#if 0
1467   case MESA_FORMAT_A8:
1468      rb->DataType = GL_UNSIGNED_BYTE;
1469      rb->GetValues = get_values_alpha8;
1470      rb->PutRow = put_row_alpha8;
1471      rb->PutRowRGB = NULL;
1472      rb->PutMonoRow = put_mono_row_alpha8;
1473      rb->PutValues = put_values_alpha8;
1474      rb->PutMonoValues = put_mono_values_alpha8;
1475      break;
1476#endif
1477
1478   case MESA_FORMAT_S8:
1479      rb->DataType = GL_UNSIGNED_BYTE;
1480      rb->GetValues = get_values_ubyte;
1481      rb->PutRow = put_row_ubyte;
1482      rb->PutRowRGB = NULL;
1483      rb->PutMonoRow = put_mono_row_ubyte;
1484      rb->PutValues = put_values_ubyte;
1485      rb->PutMonoValues = put_mono_values_ubyte;
1486      break;
1487
1488   case MESA_FORMAT_Z16:
1489      rb->DataType = GL_UNSIGNED_SHORT;
1490      rb->GetValues = get_values_ushort;
1491      rb->PutRow = put_row_ushort;
1492      rb->PutRowRGB = NULL;
1493      rb->PutMonoRow = put_mono_row_ushort;
1494      rb->PutValues = put_values_ushort;
1495      rb->PutMonoValues = put_mono_values_ushort;
1496      break;
1497
1498   case MESA_FORMAT_Z32:
1499   case MESA_FORMAT_X8_Z24:
1500   case MESA_FORMAT_Z24_X8:
1501      rb->DataType = GL_UNSIGNED_INT;
1502      rb->GetValues = get_values_uint;
1503      rb->PutRow = put_row_uint;
1504      rb->PutRowRGB = NULL;
1505      rb->PutMonoRow = put_mono_row_uint;
1506      rb->PutValues = put_values_uint;
1507      rb->PutMonoValues = put_mono_values_uint;
1508      break;
1509
1510   case MESA_FORMAT_Z24_S8:
1511   case MESA_FORMAT_S8_Z24:
1512      rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
1513      rb->GetValues = get_values_uint;
1514      rb->PutRow = put_row_uint;
1515      rb->PutRowRGB = NULL;
1516      rb->PutMonoRow = put_mono_row_uint;
1517      rb->PutValues = put_values_uint;
1518      rb->PutMonoValues = put_mono_values_uint;
1519      break;
1520
1521   case MESA_FORMAT_RGBA_FLOAT32:
1522      rb->GetRow = get_row_generic;
1523      rb->GetValues = get_values_generic;
1524      rb->PutRow = put_row_generic;
1525      rb->PutRowRGB = NULL;
1526      rb->PutMonoRow = put_mono_row_generic;
1527      rb->PutValues = put_values_generic;
1528      rb->PutMonoValues = put_mono_values_generic;
1529      break;
1530
1531   case MESA_FORMAT_INTENSITY_FLOAT32:
1532      rb->GetRow = get_row_i_float32;
1533      rb->GetValues = get_values_i_float32;
1534      rb->PutRow = put_row_generic;
1535      rb->PutRowRGB = NULL;
1536      rb->PutMonoRow = put_mono_row_generic;
1537      rb->PutValues = put_values_generic;
1538      rb->PutMonoValues = put_mono_values_generic;
1539      break;
1540
1541   case MESA_FORMAT_LUMINANCE_FLOAT32:
1542      rb->GetRow = get_row_l_float32;
1543      rb->GetValues = get_values_l_float32;
1544      rb->PutRow = put_row_generic;
1545      rb->PutRowRGB = NULL;
1546      rb->PutMonoRow = put_mono_row_generic;
1547      rb->PutValues = put_values_generic;
1548      rb->PutMonoValues = put_mono_values_generic;
1549      break;
1550
1551   case MESA_FORMAT_ALPHA_FLOAT32:
1552      rb->GetRow = get_row_a_float32;
1553      rb->GetValues = get_values_a_float32;
1554      rb->PutRow = put_row_a_float32;
1555      rb->PutRowRGB = NULL;
1556      rb->PutMonoRow = put_mono_row_a_float32;
1557      rb->PutValues = put_values_a_float32;
1558      rb->PutMonoValues = put_mono_values_a_float32;
1559      break;
1560
1561   case MESA_FORMAT_RG_FLOAT32:
1562      rb->GetRow = get_row_rg_float32;
1563      rb->GetValues = get_values_rg_float32;
1564      rb->PutRow = put_row_generic;
1565      rb->PutRowRGB = NULL;
1566      rb->PutMonoRow = put_mono_row_generic;
1567      rb->PutValues = put_values_generic;
1568      rb->PutMonoValues = put_mono_values_generic;
1569      break;
1570
1571   case MESA_FORMAT_R_FLOAT32:
1572      rb->GetRow = get_row_r_float32;
1573      rb->GetValues = get_values_r_float32;
1574      rb->PutRow = put_row_generic;
1575      rb->PutRowRGB = NULL;
1576      rb->PutMonoRow = put_mono_row_generic;
1577      rb->PutValues = put_values_generic;
1578      rb->PutMonoValues = put_mono_values_generic;
1579      break;
1580
1581   default:
1582      break;
1583   }
1584}
1585
1586/**
1587 * This is a software fallback for the gl_renderbuffer->AllocStorage
1588 * function.
1589 * Device drivers will typically override this function for the buffers
1590 * which it manages (typically color buffers, Z and stencil).
1591 * Other buffers (like software accumulation and aux buffers) which the driver
1592 * doesn't manage can be handled with this function.
1593 *
1594 * This one multi-purpose function can allocate stencil, depth, accum, color
1595 * or color-index buffers!
1596 *
1597 * This function also plugs in the appropriate GetPointer, Get/PutRow and
1598 * Get/PutValues functions.
1599 */
1600GLboolean
1601_mesa_soft_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
1602                                GLenum internalFormat,
1603                                GLuint width, GLuint height)
1604{
1605   switch (internalFormat) {
1606   case GL_RGB:
1607   case GL_R3_G3_B2:
1608   case GL_RGB4:
1609   case GL_RGB5:
1610   case GL_RGB8:
1611   case GL_RGB10:
1612   case GL_RGB12:
1613   case GL_RGB16:
1614      rb->Format = MESA_FORMAT_RGB888;
1615      break;
1616   case GL_RGBA:
1617   case GL_RGBA2:
1618   case GL_RGBA4:
1619   case GL_RGB5_A1:
1620   case GL_RGBA8:
1621#if 1
1622   case GL_RGB10_A2:
1623   case GL_RGBA12:
1624#endif
1625      rb->Format = MESA_FORMAT_RGBA8888;
1626      break;
1627   case GL_RGBA16:
1628   case GL_RGBA16_SNORM:
1629      /* for accum buffer */
1630      rb->Format = MESA_FORMAT_SIGNED_RGBA_16;
1631      break;
1632#if 0
1633   case GL_ALPHA8:
1634      rb->Format = MESA_FORMAT_A8;
1635      break;
1636#endif
1637   case GL_STENCIL_INDEX:
1638   case GL_STENCIL_INDEX1_EXT:
1639   case GL_STENCIL_INDEX4_EXT:
1640   case GL_STENCIL_INDEX8_EXT:
1641   case GL_STENCIL_INDEX16_EXT:
1642      rb->Format = MESA_FORMAT_S8;
1643      break;
1644   case GL_DEPTH_COMPONENT:
1645   case GL_DEPTH_COMPONENT16:
1646      rb->Format = MESA_FORMAT_Z16;
1647      break;
1648   case GL_DEPTH_COMPONENT24:
1649      rb->Format = MESA_FORMAT_X8_Z24;
1650      break;
1651   case GL_DEPTH_COMPONENT32:
1652      rb->Format = MESA_FORMAT_Z32;
1653      break;
1654   case GL_DEPTH_STENCIL_EXT:
1655   case GL_DEPTH24_STENCIL8_EXT:
1656      rb->Format = MESA_FORMAT_Z24_S8;
1657      break;
1658   default:
1659      /* unsupported format */
1660      return GL_FALSE;
1661   }
1662
1663   _mesa_set_renderbuffer_accessors(rb);
1664
1665   ASSERT(rb->DataType);
1666   ASSERT(rb->GetPointer);
1667   ASSERT(rb->GetRow);
1668   ASSERT(rb->GetValues);
1669   ASSERT(rb->PutRow);
1670   ASSERT(rb->PutMonoRow);
1671   ASSERT(rb->PutValues);
1672   ASSERT(rb->PutMonoValues);
1673
1674   /* free old buffer storage */
1675   if (rb->Data) {
1676      free(rb->Data);
1677      rb->Data = NULL;
1678   }
1679
1680   rb->RowStride = width;
1681
1682   if (width > 0 && height > 0) {
1683      /* allocate new buffer storage */
1684      rb->Data = malloc(width * height * _mesa_get_format_bytes(rb->Format));
1685
1686      if (rb->Data == NULL) {
1687         rb->Width = 0;
1688         rb->Height = 0;
1689	 rb->RowStride = 0;
1690         _mesa_error(ctx, GL_OUT_OF_MEMORY,
1691                     "software renderbuffer allocation (%d x %d x %d)",
1692                     width, height, _mesa_get_format_bytes(rb->Format));
1693         return GL_FALSE;
1694      }
1695   }
1696
1697   rb->Width = width;
1698   rb->Height = height;
1699   rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
1700
1701   if (rb->Name == 0 &&
1702       internalFormat == GL_RGBA16_SNORM &&
1703       rb->_BaseFormat == 0) {
1704      /* NOTE: This is a special case just for accumulation buffers.
1705       * This is a very limited use case- there's no snorm texturing or
1706       * rendering going on.
1707       */
1708      rb->_BaseFormat = GL_RGBA;
1709   }
1710   else {
1711      /* the internalFormat should have been error checked long ago */
1712      ASSERT(rb->_BaseFormat);
1713   }
1714
1715   return GL_TRUE;
1716}
1717
1718
1719void
1720_mesa_map_soft_renderbuffer(struct gl_context *ctx,
1721			    struct gl_renderbuffer *rb,
1722			    GLuint x, GLuint y, GLuint w, GLuint h,
1723			    GLbitfield mode,
1724			    GLubyte **out_map,
1725			    GLint *out_stride)
1726{
1727   GLubyte *map = rb->Data;
1728   int cpp = _mesa_get_format_bytes(rb->Format);
1729   int stride = rb->RowStride * cpp;
1730
1731   ASSERT(rb->Data);
1732
1733   map += y * stride;
1734   map += x * cpp;
1735
1736   *out_map = map;
1737   *out_stride = stride;
1738}
1739
1740void
1741_mesa_unmap_soft_renderbuffer(struct gl_context *ctx,
1742			      struct gl_renderbuffer *rb)
1743{
1744}
1745
1746
1747/**********************************************************************/
1748/**********************************************************************/
1749/**********************************************************************/
1750
1751
1752/**
1753 * Here we utilize the gl_renderbuffer->Wrapper field to put an alpha
1754 * buffer wrapper around an existing RGB renderbuffer (hw or sw).
1755 *
1756 * When PutRow is called (for example), we store the alpha values in
1757 * this buffer, then pass on the PutRow call to the wrapped RGB
1758 * buffer.
1759 */
1760
1761
1762static GLboolean
1763alloc_storage_alpha8(struct gl_context *ctx, struct gl_renderbuffer *arb,
1764                     GLenum internalFormat, GLuint width, GLuint height)
1765{
1766   ASSERT(arb != arb->Wrapped);
1767   ASSERT(arb->Format == MESA_FORMAT_A8);
1768
1769   /* first, pass the call to the wrapped RGB buffer */
1770   if (!arb->Wrapped->AllocStorage(ctx, arb->Wrapped, internalFormat,
1771                                  width, height)) {
1772      return GL_FALSE;
1773   }
1774
1775   /* next, resize my alpha buffer */
1776   if (arb->Data) {
1777      free(arb->Data);
1778   }
1779
1780   arb->Data = malloc(width * height * sizeof(GLubyte));
1781   if (arb->Data == NULL) {
1782      arb->Width = 0;
1783      arb->Height = 0;
1784      _mesa_error(ctx, GL_OUT_OF_MEMORY, "software alpha buffer allocation");
1785      return GL_FALSE;
1786   }
1787
1788   arb->Width = width;
1789   arb->Height = height;
1790   arb->RowStride = width;
1791
1792   return GL_TRUE;
1793}
1794
1795
1796/**
1797 * Delete an alpha_renderbuffer object, as well as the wrapped RGB buffer.
1798 */
1799static void
1800delete_renderbuffer_alpha8(struct gl_renderbuffer *arb)
1801{
1802   if (arb->Data) {
1803      free(arb->Data);
1804   }
1805   ASSERT(arb->Wrapped);
1806   ASSERT(arb != arb->Wrapped);
1807   arb->Wrapped->Delete(arb->Wrapped);
1808   arb->Wrapped = NULL;
1809   free(arb);
1810}
1811
1812
1813static void *
1814get_pointer_alpha8(struct gl_context *ctx, struct gl_renderbuffer *arb,
1815                   GLint x, GLint y)
1816{
1817   return NULL;   /* don't allow direct access! */
1818}
1819
1820
1821static void
1822get_row_alpha8(struct gl_context *ctx, struct gl_renderbuffer *arb, GLuint count,
1823               GLint x, GLint y, void *values)
1824{
1825   /* NOTE: 'values' is RGBA format! */
1826   const GLubyte *src = (const GLubyte *) arb->Data + y * arb->RowStride + x;
1827   GLubyte *dst = (GLubyte *) values;
1828   GLuint i;
1829   ASSERT(arb != arb->Wrapped);
1830   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1831   /* first, pass the call to the wrapped RGB buffer */
1832   arb->Wrapped->GetRow(ctx, arb->Wrapped, count, x, y, values);
1833   /* second, fill in alpha values from this buffer! */
1834   for (i = 0; i < count; i++) {
1835      dst[i * 4 + 3] = src[i];
1836   }
1837}
1838
1839
1840static void
1841get_values_alpha8(struct gl_context *ctx, struct gl_renderbuffer *arb, GLuint count,
1842                  const GLint x[], const GLint y[], void *values)
1843{
1844   GLubyte *dst = (GLubyte *) values;
1845   GLuint i;
1846   ASSERT(arb != arb->Wrapped);
1847   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1848   /* first, pass the call to the wrapped RGB buffer */
1849   arb->Wrapped->GetValues(ctx, arb->Wrapped, count, x, y, values);
1850   /* second, fill in alpha values from this buffer! */
1851   for (i = 0; i < count; i++) {
1852      const GLubyte *src = (GLubyte *) arb->Data + y[i] * arb->RowStride + x[i];
1853      dst[i * 4 + 3] = *src;
1854   }
1855}
1856
1857
1858static void
1859put_row_alpha8(struct gl_context *ctx, struct gl_renderbuffer *arb, GLuint count,
1860               GLint x, GLint y, const void *values, const GLubyte *mask)
1861{
1862   const GLubyte *src = (const GLubyte *) values;
1863   GLubyte *dst = (GLubyte *) arb->Data + y * arb->RowStride + x;
1864   GLuint i;
1865   ASSERT(arb != arb->Wrapped);
1866   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1867   /* first, pass the call to the wrapped RGB buffer */
1868   arb->Wrapped->PutRow(ctx, arb->Wrapped, count, x, y, values, mask);
1869   /* second, store alpha in our buffer */
1870   for (i = 0; i < count; i++) {
1871      if (!mask || mask[i]) {
1872         dst[i] = src[i * 4 + 3];
1873      }
1874   }
1875}
1876
1877
1878static void
1879put_row_rgb_alpha8(struct gl_context *ctx, struct gl_renderbuffer *arb, GLuint count,
1880                   GLint x, GLint y, const void *values, const GLubyte *mask)
1881{
1882   const GLubyte *src = (const GLubyte *) values;
1883   GLubyte *dst = (GLubyte *) arb->Data + y * arb->RowStride + x;
1884   GLuint i;
1885   ASSERT(arb != arb->Wrapped);
1886   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1887   /* first, pass the call to the wrapped RGB buffer */
1888   arb->Wrapped->PutRowRGB(ctx, arb->Wrapped, count, x, y, values, mask);
1889   /* second, store alpha in our buffer */
1890   for (i = 0; i < count; i++) {
1891      if (!mask || mask[i]) {
1892         dst[i] = src[i * 4 + 3];
1893      }
1894   }
1895}
1896
1897
1898static void
1899put_mono_row_alpha8(struct gl_context *ctx, struct gl_renderbuffer *arb, GLuint count,
1900                    GLint x, GLint y, const void *value, const GLubyte *mask)
1901{
1902   const GLubyte val = ((const GLubyte *) value)[3];
1903   GLubyte *dst = (GLubyte *) arb->Data + y * arb->RowStride + x;
1904   ASSERT(arb != arb->Wrapped);
1905   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1906   /* first, pass the call to the wrapped RGB buffer */
1907   arb->Wrapped->PutMonoRow(ctx, arb->Wrapped, count, x, y, value, mask);
1908   /* second, store alpha in our buffer */
1909   if (mask) {
1910      GLuint i;
1911      for (i = 0; i < count; i++) {
1912         if (mask[i]) {
1913            dst[i] = val;
1914         }
1915      }
1916   }
1917   else {
1918      memset(dst, val, count);
1919   }
1920}
1921
1922
1923static void
1924put_values_alpha8(struct gl_context *ctx, struct gl_renderbuffer *arb, GLuint count,
1925                  const GLint x[], const GLint y[],
1926                  const void *values, const GLubyte *mask)
1927{
1928   const GLubyte *src = (const GLubyte *) values;
1929   GLuint i;
1930   ASSERT(arb != arb->Wrapped);
1931   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1932   /* first, pass the call to the wrapped RGB buffer */
1933   arb->Wrapped->PutValues(ctx, arb->Wrapped, count, x, y, values, mask);
1934   /* second, store alpha in our buffer */
1935   for (i = 0; i < count; i++) {
1936      if (!mask || mask[i]) {
1937         GLubyte *dst = (GLubyte *) arb->Data + y[i] * arb->RowStride + x[i];
1938         *dst = src[i * 4 + 3];
1939      }
1940   }
1941}
1942
1943
1944static void
1945put_mono_values_alpha8(struct gl_context *ctx, struct gl_renderbuffer *arb,
1946                       GLuint count, const GLint x[], const GLint y[],
1947                       const void *value, const GLubyte *mask)
1948{
1949   const GLubyte val = ((const GLubyte *) value)[3];
1950   GLuint i;
1951   ASSERT(arb != arb->Wrapped);
1952   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1953   /* first, pass the call to the wrapped RGB buffer */
1954   arb->Wrapped->PutValues(ctx, arb->Wrapped, count, x, y, value, mask);
1955   /* second, store alpha in our buffer */
1956   for (i = 0; i < count; i++) {
1957      if (!mask || mask[i]) {
1958         GLubyte *dst = (GLubyte *) arb->Data + y[i] * arb->RowStride + x[i];
1959         *dst = val;
1960      }
1961   }
1962}
1963
1964
1965static void
1966copy_buffer_alpha8(struct gl_renderbuffer* dst, struct gl_renderbuffer* src)
1967{
1968   ASSERT(dst->Format == MESA_FORMAT_A8);
1969   ASSERT(src->Format == MESA_FORMAT_A8);
1970   ASSERT(dst->Width == src->Width);
1971   ASSERT(dst->Height == src->Height);
1972   ASSERT(dst->RowStride == src->RowStride);
1973
1974   memcpy(dst->Data, src->Data, dst->RowStride * dst->Height * sizeof(GLubyte));
1975}
1976
1977
1978/**********************************************************************/
1979/**********************************************************************/
1980/**********************************************************************/
1981
1982
1983/**
1984 * Default GetPointer routine.  Always return NULL to indicate that
1985 * direct buffer access is not supported.
1986 */
1987static void *
1988nop_get_pointer(struct gl_context *ctx, struct gl_renderbuffer *rb, GLint x, GLint y)
1989{
1990   return NULL;
1991}
1992
1993
1994/**
1995 * Initialize the fields of a gl_renderbuffer to default values.
1996 */
1997void
1998_mesa_init_renderbuffer(struct gl_renderbuffer *rb, GLuint name)
1999{
2000   _glthread_INIT_MUTEX(rb->Mutex);
2001
2002   rb->ClassID = 0;
2003   rb->Name = name;
2004   rb->RefCount = 0;
2005   rb->Delete = _mesa_delete_renderbuffer;
2006
2007   /* The rest of these should be set later by the caller of this function or
2008    * the AllocStorage method:
2009    */
2010   rb->AllocStorage = NULL;
2011
2012   rb->Width = 0;
2013   rb->Height = 0;
2014   rb->InternalFormat = GL_NONE;
2015   rb->Format = MESA_FORMAT_NONE;
2016
2017   rb->DataType = GL_NONE;
2018   rb->Data = NULL;
2019
2020   /* Point back to ourself so that we don't have to check for Wrapped==NULL
2021    * all over the drivers.
2022    */
2023   rb->Wrapped = rb;
2024
2025   rb->GetPointer = nop_get_pointer;
2026   rb->GetRow = NULL;
2027   rb->GetValues = NULL;
2028   rb->PutRow = NULL;
2029   rb->PutRowRGB = NULL;
2030   rb->PutMonoRow = NULL;
2031   rb->PutValues = NULL;
2032   rb->PutMonoValues = NULL;
2033}
2034
2035
2036/**
2037 * Allocate a new gl_renderbuffer object.  This can be used for user-created
2038 * renderbuffers or window-system renderbuffers.
2039 */
2040struct gl_renderbuffer *
2041_mesa_new_renderbuffer(struct gl_context *ctx, GLuint name)
2042{
2043   struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer);
2044   if (rb) {
2045      _mesa_init_renderbuffer(rb, name);
2046   }
2047   return rb;
2048}
2049
2050
2051/**
2052 * Delete a gl_framebuffer.
2053 * This is the default function for renderbuffer->Delete().
2054 */
2055void
2056_mesa_delete_renderbuffer(struct gl_renderbuffer *rb)
2057{
2058   if (rb->Data) {
2059      free(rb->Data);
2060   }
2061   free(rb);
2062}
2063
2064
2065/**
2066 * Allocate a software-based renderbuffer.  This is called via the
2067 * ctx->Driver.NewRenderbuffer() function when the user creates a new
2068 * renderbuffer.
2069 * This would not be used for hardware-based renderbuffers.
2070 */
2071struct gl_renderbuffer *
2072_mesa_new_soft_renderbuffer(struct gl_context *ctx, GLuint name)
2073{
2074   struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, name);
2075   if (rb) {
2076      rb->AllocStorage = _mesa_soft_renderbuffer_storage;
2077      /* Normally, one would setup the PutRow, GetRow, etc functions here.
2078       * But we're doing that in the _mesa_soft_renderbuffer_storage() function
2079       * instead.
2080       */
2081   }
2082   return rb;
2083}
2084
2085
2086/**
2087 * Add software-based color renderbuffers to the given framebuffer.
2088 * This is a helper routine for device drivers when creating a
2089 * window system framebuffer (not a user-created render/framebuffer).
2090 * Once this function is called, you can basically forget about this
2091 * renderbuffer; core Mesa will handle all the buffer management and
2092 * rendering!
2093 */
2094GLboolean
2095_mesa_add_color_renderbuffers(struct gl_context *ctx, struct gl_framebuffer *fb,
2096                              GLuint rgbBits, GLuint alphaBits,
2097                              GLboolean frontLeft, GLboolean backLeft,
2098                              GLboolean frontRight, GLboolean backRight)
2099{
2100   gl_buffer_index b;
2101
2102   if (rgbBits > 16 || alphaBits > 16) {
2103      _mesa_problem(ctx,
2104                    "Unsupported bit depth in _mesa_add_color_renderbuffers");
2105      return GL_FALSE;
2106   }
2107
2108   assert(MAX_COLOR_ATTACHMENTS >= 4);
2109
2110   for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
2111      struct gl_renderbuffer *rb;
2112
2113      if (b == BUFFER_FRONT_LEFT && !frontLeft)
2114         continue;
2115      else if (b == BUFFER_BACK_LEFT && !backLeft)
2116         continue;
2117      else if (b == BUFFER_FRONT_RIGHT && !frontRight)
2118         continue;
2119      else if (b == BUFFER_BACK_RIGHT && !backRight)
2120         continue;
2121
2122      assert(fb->Attachment[b].Renderbuffer == NULL);
2123
2124      rb = _mesa_new_renderbuffer(ctx, 0);
2125      if (!rb) {
2126         _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer");
2127         return GL_FALSE;
2128      }
2129
2130      if (rgbBits <= 8) {
2131         if (alphaBits)
2132            rb->Format = MESA_FORMAT_RGBA8888;
2133         else
2134            rb->Format = MESA_FORMAT_RGB888;
2135      }
2136      else {
2137         assert(rgbBits <= 16);
2138         rb->Format = MESA_FORMAT_NONE; /*XXX RGBA16;*/
2139      }
2140      rb->InternalFormat = GL_RGBA;
2141
2142      rb->AllocStorage = _mesa_soft_renderbuffer_storage;
2143      _mesa_add_renderbuffer(fb, b, rb);
2144   }
2145
2146   return GL_TRUE;
2147}
2148
2149
2150/**
2151 * Add software-based alpha renderbuffers to the given framebuffer.
2152 * This is a helper routine for device drivers when creating a
2153 * window system framebuffer (not a user-created render/framebuffer).
2154 * Once this function is called, you can basically forget about this
2155 * renderbuffer; core Mesa will handle all the buffer management and
2156 * rendering!
2157 */
2158GLboolean
2159_mesa_add_alpha_renderbuffers(struct gl_context *ctx, struct gl_framebuffer *fb,
2160                              GLuint alphaBits,
2161                              GLboolean frontLeft, GLboolean backLeft,
2162                              GLboolean frontRight, GLboolean backRight)
2163{
2164   gl_buffer_index b;
2165
2166   /* for window system framebuffers only! */
2167   assert(fb->Name == 0);
2168
2169   if (alphaBits > 8) {
2170      _mesa_problem(ctx,
2171                    "Unsupported bit depth in _mesa_add_alpha_renderbuffers");
2172      return GL_FALSE;
2173   }
2174
2175   assert(MAX_COLOR_ATTACHMENTS >= 4);
2176
2177   /* Wrap each of the RGB color buffers with an alpha renderbuffer.
2178    */
2179   for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
2180      struct gl_renderbuffer *arb;
2181
2182      if (b == BUFFER_FRONT_LEFT && !frontLeft)
2183         continue;
2184      else if (b == BUFFER_BACK_LEFT && !backLeft)
2185         continue;
2186      else if (b == BUFFER_FRONT_RIGHT && !frontRight)
2187         continue;
2188      else if (b == BUFFER_BACK_RIGHT && !backRight)
2189         continue;
2190
2191      /* the RGB buffer to wrap must already exist!! */
2192      assert(fb->Attachment[b].Renderbuffer);
2193
2194      /* only GLubyte supported for now */
2195      assert(fb->Attachment[b].Renderbuffer->DataType == GL_UNSIGNED_BYTE);
2196
2197      /* allocate alpha renderbuffer */
2198      arb = _mesa_new_renderbuffer(ctx, 0);
2199      if (!arb) {
2200         _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating alpha buffer");
2201         return GL_FALSE;
2202      }
2203
2204      /* wrap the alpha renderbuffer around the RGB renderbuffer */
2205      arb->Wrapped = fb->Attachment[b].Renderbuffer;
2206
2207      /* Set up my alphabuffer fields and plug in my functions.
2208       * The functions will put/get the alpha values from/to RGBA arrays
2209       * and then call the wrapped buffer's functions to handle the RGB
2210       * values.
2211       */
2212      arb->InternalFormat = arb->Wrapped->InternalFormat;
2213      arb->Format         = MESA_FORMAT_A8;
2214      arb->DataType       = arb->Wrapped->DataType;
2215      arb->AllocStorage   = alloc_storage_alpha8;
2216      arb->Delete         = delete_renderbuffer_alpha8;
2217      arb->GetPointer     = get_pointer_alpha8;
2218      arb->GetRow         = get_row_alpha8;
2219      arb->GetValues      = get_values_alpha8;
2220      arb->PutRow         = put_row_alpha8;
2221      arb->PutRowRGB      = put_row_rgb_alpha8;
2222      arb->PutMonoRow     = put_mono_row_alpha8;
2223      arb->PutValues      = put_values_alpha8;
2224      arb->PutMonoValues  = put_mono_values_alpha8;
2225
2226      /* clear the pointer to avoid assertion/sanity check failure later */
2227      fb->Attachment[b].Renderbuffer = NULL;
2228
2229      /* plug the alpha renderbuffer into the colorbuffer attachment */
2230      _mesa_add_renderbuffer(fb, b, arb);
2231   }
2232
2233   return GL_TRUE;
2234}
2235
2236
2237/**
2238 * For framebuffers that use a software alpha channel wrapper
2239 * created by _mesa_add_alpha_renderbuffer or _mesa_add_soft_renderbuffers,
2240 * copy the back buffer alpha channel into the front buffer alpha channel.
2241 */
2242void
2243_mesa_copy_soft_alpha_renderbuffers(struct gl_context *ctx, struct gl_framebuffer *fb)
2244{
2245   if (fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer &&
2246       fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer)
2247      copy_buffer_alpha8(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer,
2248                         fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
2249
2250
2251   if (fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer &&
2252       fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer)
2253      copy_buffer_alpha8(fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer,
2254                         fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer);
2255}
2256
2257
2258/**
2259 * Add a software-based depth renderbuffer to the given framebuffer.
2260 * This is a helper routine for device drivers when creating a
2261 * window system framebuffer (not a user-created render/framebuffer).
2262 * Once this function is called, you can basically forget about this
2263 * renderbuffer; core Mesa will handle all the buffer management and
2264 * rendering!
2265 */
2266GLboolean
2267_mesa_add_depth_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
2268                             GLuint depthBits)
2269{
2270   struct gl_renderbuffer *rb;
2271
2272   if (depthBits > 32) {
2273      _mesa_problem(ctx,
2274                    "Unsupported depthBits in _mesa_add_depth_renderbuffer");
2275      return GL_FALSE;
2276   }
2277
2278   assert(fb->Attachment[BUFFER_DEPTH].Renderbuffer == NULL);
2279
2280   rb = _mesa_new_renderbuffer(ctx, 0);
2281   if (!rb) {
2282      _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating depth buffer");
2283      return GL_FALSE;
2284   }
2285
2286   if (depthBits <= 16) {
2287      rb->Format = MESA_FORMAT_Z16;
2288      rb->InternalFormat = GL_DEPTH_COMPONENT16;
2289   }
2290   else if (depthBits <= 24) {
2291      rb->Format = MESA_FORMAT_X8_Z24;
2292      rb->InternalFormat = GL_DEPTH_COMPONENT24;
2293   }
2294   else {
2295      rb->Format = MESA_FORMAT_Z32;
2296      rb->InternalFormat = GL_DEPTH_COMPONENT32;
2297   }
2298
2299   rb->AllocStorage = _mesa_soft_renderbuffer_storage;
2300   _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
2301
2302   return GL_TRUE;
2303}
2304
2305
2306/**
2307 * Add a software-based stencil renderbuffer to the given framebuffer.
2308 * This is a helper routine for device drivers when creating a
2309 * window system framebuffer (not a user-created render/framebuffer).
2310 * Once this function is called, you can basically forget about this
2311 * renderbuffer; core Mesa will handle all the buffer management and
2312 * rendering!
2313 */
2314GLboolean
2315_mesa_add_stencil_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
2316                               GLuint stencilBits)
2317{
2318   struct gl_renderbuffer *rb;
2319
2320   if (stencilBits > 16) {
2321      _mesa_problem(ctx,
2322                  "Unsupported stencilBits in _mesa_add_stencil_renderbuffer");
2323      return GL_FALSE;
2324   }
2325
2326   assert(fb->Attachment[BUFFER_STENCIL].Renderbuffer == NULL);
2327
2328   rb = _mesa_new_renderbuffer(ctx, 0);
2329   if (!rb) {
2330      _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating stencil buffer");
2331      return GL_FALSE;
2332   }
2333
2334   assert(stencilBits <= 8);
2335   rb->Format = MESA_FORMAT_S8;
2336   rb->InternalFormat = GL_STENCIL_INDEX8;
2337
2338   rb->AllocStorage = _mesa_soft_renderbuffer_storage;
2339   _mesa_add_renderbuffer(fb, BUFFER_STENCIL, rb);
2340
2341   return GL_TRUE;
2342}
2343
2344
2345/**
2346 * Add a software-based accumulation renderbuffer to the given framebuffer.
2347 * This is a helper routine for device drivers when creating a
2348 * window system framebuffer (not a user-created render/framebuffer).
2349 * Once this function is called, you can basically forget about this
2350 * renderbuffer; core Mesa will handle all the buffer management and
2351 * rendering!
2352 */
2353GLboolean
2354_mesa_add_accum_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
2355                             GLuint redBits, GLuint greenBits,
2356                             GLuint blueBits, GLuint alphaBits)
2357{
2358   struct gl_renderbuffer *rb;
2359
2360   if (redBits > 16 || greenBits > 16 || blueBits > 16 || alphaBits > 16) {
2361      _mesa_problem(ctx,
2362                    "Unsupported accumBits in _mesa_add_accum_renderbuffer");
2363      return GL_FALSE;
2364   }
2365
2366   assert(fb->Attachment[BUFFER_ACCUM].Renderbuffer == NULL);
2367
2368   rb = _mesa_new_renderbuffer(ctx, 0);
2369   if (!rb) {
2370      _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer");
2371      return GL_FALSE;
2372   }
2373
2374   rb->Format = MESA_FORMAT_SIGNED_RGBA_16;
2375   rb->InternalFormat = GL_RGBA16_SNORM;
2376   rb->AllocStorage = _mesa_soft_renderbuffer_storage;
2377   _mesa_add_renderbuffer(fb, BUFFER_ACCUM, rb);
2378
2379   return GL_TRUE;
2380}
2381
2382
2383
2384/**
2385 * Add a software-based aux renderbuffer to the given framebuffer.
2386 * This is a helper routine for device drivers when creating a
2387 * window system framebuffer (not a user-created render/framebuffer).
2388 * Once this function is called, you can basically forget about this
2389 * renderbuffer; core Mesa will handle all the buffer management and
2390 * rendering!
2391 *
2392 * NOTE: color-index aux buffers not supported.
2393 */
2394GLboolean
2395_mesa_add_aux_renderbuffers(struct gl_context *ctx, struct gl_framebuffer *fb,
2396                            GLuint colorBits, GLuint numBuffers)
2397{
2398   GLuint i;
2399
2400   if (colorBits > 16) {
2401      _mesa_problem(ctx,
2402                    "Unsupported accumBits in _mesa_add_aux_renderbuffers");
2403      return GL_FALSE;
2404   }
2405
2406   assert(numBuffers <= MAX_AUX_BUFFERS);
2407
2408   for (i = 0; i < numBuffers; i++) {
2409      struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, 0);
2410
2411      assert(fb->Attachment[BUFFER_AUX0 + i].Renderbuffer == NULL);
2412
2413      if (!rb) {
2414         _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating aux buffer");
2415         return GL_FALSE;
2416      }
2417
2418      assert (colorBits <= 8);
2419      rb->Format = MESA_FORMAT_RGBA8888;
2420      rb->InternalFormat = GL_RGBA;
2421
2422      rb->AllocStorage = _mesa_soft_renderbuffer_storage;
2423      _mesa_add_renderbuffer(fb, BUFFER_AUX0 + i, rb);
2424   }
2425   return GL_TRUE;
2426}
2427
2428
2429/**
2430 * Create/attach software-based renderbuffers to the given framebuffer.
2431 * This is a helper routine for device drivers.  Drivers can just as well
2432 * call the individual _mesa_add_*_renderbuffer() routines directly.
2433 */
2434void
2435_mesa_add_soft_renderbuffers(struct gl_framebuffer *fb,
2436                             GLboolean color,
2437                             GLboolean depth,
2438                             GLboolean stencil,
2439                             GLboolean accum,
2440                             GLboolean alpha,
2441                             GLboolean aux)
2442{
2443   GLboolean frontLeft = GL_TRUE;
2444   GLboolean backLeft = fb->Visual.doubleBufferMode;
2445   GLboolean frontRight = fb->Visual.stereoMode;
2446   GLboolean backRight = fb->Visual.stereoMode && fb->Visual.doubleBufferMode;
2447
2448   if (color) {
2449      assert(fb->Visual.redBits == fb->Visual.greenBits);
2450      assert(fb->Visual.redBits == fb->Visual.blueBits);
2451      _mesa_add_color_renderbuffers(NULL, fb,
2452				    fb->Visual.redBits,
2453				    fb->Visual.alphaBits,
2454				    frontLeft, backLeft,
2455				    frontRight, backRight);
2456   }
2457
2458   if (depth) {
2459      assert(fb->Visual.depthBits > 0);
2460      _mesa_add_depth_renderbuffer(NULL, fb, fb->Visual.depthBits);
2461   }
2462
2463   if (stencil) {
2464      assert(fb->Visual.stencilBits > 0);
2465      _mesa_add_stencil_renderbuffer(NULL, fb, fb->Visual.stencilBits);
2466   }
2467
2468   if (accum) {
2469      assert(fb->Visual.accumRedBits > 0);
2470      assert(fb->Visual.accumGreenBits > 0);
2471      assert(fb->Visual.accumBlueBits > 0);
2472      _mesa_add_accum_renderbuffer(NULL, fb,
2473                                   fb->Visual.accumRedBits,
2474                                   fb->Visual.accumGreenBits,
2475                                   fb->Visual.accumBlueBits,
2476                                   fb->Visual.accumAlphaBits);
2477   }
2478
2479   if (aux) {
2480      assert(fb->Visual.numAuxBuffers > 0);
2481      _mesa_add_aux_renderbuffers(NULL, fb, fb->Visual.redBits,
2482                                  fb->Visual.numAuxBuffers);
2483   }
2484
2485   if (alpha) {
2486      assert(fb->Visual.alphaBits > 0);
2487      _mesa_add_alpha_renderbuffers(NULL, fb, fb->Visual.alphaBits,
2488                                    frontLeft, backLeft,
2489                                    frontRight, backRight);
2490   }
2491
2492#if 0
2493   if (multisample) {
2494      /* maybe someday */
2495   }
2496#endif
2497}
2498
2499
2500/**
2501 * Attach a renderbuffer to a framebuffer.
2502 * \param bufferName  one of the BUFFER_x tokens
2503 */
2504void
2505_mesa_add_renderbuffer(struct gl_framebuffer *fb,
2506                       gl_buffer_index bufferName, struct gl_renderbuffer *rb)
2507{
2508   assert(fb);
2509   assert(rb);
2510   assert(bufferName < BUFFER_COUNT);
2511
2512   /* There should be no previous renderbuffer on this attachment point,
2513    * with the exception of depth/stencil since the same renderbuffer may
2514    * be used for both.
2515    */
2516   assert(bufferName == BUFFER_DEPTH ||
2517          bufferName == BUFFER_STENCIL ||
2518          fb->Attachment[bufferName].Renderbuffer == NULL);
2519
2520   /* winsys vs. user-created buffer cross check */
2521   if (fb->Name) {
2522      assert(rb->Name);
2523   }
2524   else {
2525      assert(!rb->Name);
2526   }
2527
2528   fb->Attachment[bufferName].Type = GL_RENDERBUFFER_EXT;
2529   fb->Attachment[bufferName].Complete = GL_TRUE;
2530   _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer, rb);
2531}
2532
2533
2534/**
2535 * Remove the named renderbuffer from the given framebuffer.
2536 * \param bufferName  one of the BUFFER_x tokens
2537 */
2538void
2539_mesa_remove_renderbuffer(struct gl_framebuffer *fb,
2540                          gl_buffer_index bufferName)
2541{
2542   struct gl_renderbuffer *rb;
2543
2544   assert(bufferName < BUFFER_COUNT);
2545
2546   rb = fb->Attachment[bufferName].Renderbuffer;
2547   if (!rb)
2548      return;
2549
2550   _mesa_reference_renderbuffer(&rb, NULL);
2551
2552   fb->Attachment[bufferName].Renderbuffer = NULL;
2553}
2554
2555
2556/**
2557 * Set *ptr to point to rb.  If *ptr points to another renderbuffer,
2558 * dereference that buffer first.  The new renderbuffer's refcount will
2559 * be incremented.  The old renderbuffer's refcount will be decremented.
2560 * This is normally only called from the _mesa_reference_renderbuffer() macro
2561 * when there's a real pointer change.
2562 */
2563void
2564_mesa_reference_renderbuffer_(struct gl_renderbuffer **ptr,
2565                              struct gl_renderbuffer *rb)
2566{
2567   if (*ptr) {
2568      /* Unreference the old renderbuffer */
2569      GLboolean deleteFlag = GL_FALSE;
2570      struct gl_renderbuffer *oldRb = *ptr;
2571
2572      _glthread_LOCK_MUTEX(oldRb->Mutex);
2573      ASSERT(oldRb->RefCount > 0);
2574      oldRb->RefCount--;
2575      /*printf("RB DECR %p (%d) to %d\n", (void*) oldRb, oldRb->Name, oldRb->RefCount);*/
2576      deleteFlag = (oldRb->RefCount == 0);
2577      _glthread_UNLOCK_MUTEX(oldRb->Mutex);
2578
2579      if (deleteFlag) {
2580         oldRb->Delete(oldRb);
2581      }
2582
2583      *ptr = NULL;
2584   }
2585   assert(!*ptr);
2586
2587   if (rb) {
2588      /* reference new renderbuffer */
2589      _glthread_LOCK_MUTEX(rb->Mutex);
2590      rb->RefCount++;
2591      /*printf("RB INCR %p (%d) to %d\n", (void*) rb, rb->Name, rb->RefCount);*/
2592      _glthread_UNLOCK_MUTEX(rb->Mutex);
2593      *ptr = rb;
2594   }
2595}
2596