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