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