renderbuffer.c revision 6349bd3112116841326885550188224af87ec15c
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 "mtypes.h"
47#include "fbobject.h"
48#include "renderbuffer.h"
49
50#include "rbadaptors.h"
51
52#include "state_tracker/st_context.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 _ActualFormat 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   _mesa_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      _mesa_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   _mesa_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      _mesa_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   _mesa_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      _mesa_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->_ActualFormat == GL_RGB8);
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->_ActualFormat == GL_RGB8);
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->_ActualFormat == GL_RGB8);
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->_ActualFormat == GL_RGB8);
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->_ActualFormat == GL_RGB8);
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->_ActualFormat == GL_RGB8);
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->_ActualFormat == GL_RGB8);
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->_ActualFormat == GL_RGB8);
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->_ActualFormat == GL_RGBA8);
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->_ActualFormat == GL_RGBA8);
634   _mesa_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->_ActualFormat == GL_RGBA8);
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->_ActualFormat == GL_RGBA8);
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      _mesa_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->_ActualFormat == GL_RGBA8);
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->_ActualFormat == GL_RGBA8);
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->_ActualFormat == GL_RGBA8);
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->_ActualFormat == GL_RGBA8);
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   _mesa_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      _mesa_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      _mesa_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   /* first clear these fields */
953   rb->RedBits =
954   rb->GreenBits =
955   rb->BlueBits =
956   rb->AlphaBits =
957   rb->IndexBits =
958   rb->DepthBits =
959   rb->StencilBits = 0;
960
961   switch (internalFormat) {
962   case GL_RGB:
963   case GL_R3_G3_B2:
964   case GL_RGB4:
965   case GL_RGB5:
966   case GL_RGB8:
967   case GL_RGB10:
968   case GL_RGB12:
969   case GL_RGB16:
970      rb->_ActualFormat = GL_RGB8;
971      rb->_BaseFormat = GL_RGB;
972      rb->DataType = GL_UNSIGNED_BYTE;
973      rb->GetPointer = get_pointer_ubyte3;
974      rb->GetRow = get_row_ubyte3;
975      rb->GetValues = get_values_ubyte3;
976      rb->PutRow = put_row_ubyte3;
977      rb->PutRowRGB = put_row_rgb_ubyte3;
978      rb->PutMonoRow = put_mono_row_ubyte3;
979      rb->PutValues = put_values_ubyte3;
980      rb->PutMonoValues = put_mono_values_ubyte3;
981      rb->RedBits   = 8 * sizeof(GLubyte);
982      rb->GreenBits = 8 * sizeof(GLubyte);
983      rb->BlueBits  = 8 * sizeof(GLubyte);
984      rb->AlphaBits = 0;
985      pixelSize = 3 * sizeof(GLubyte);
986      break;
987   case GL_RGBA:
988   case GL_RGBA2:
989   case GL_RGBA4:
990   case GL_RGB5_A1:
991   case GL_RGBA8:
992      rb->_ActualFormat = GL_RGBA8;
993      rb->_BaseFormat = GL_RGBA;
994      rb->DataType = GL_UNSIGNED_BYTE;
995      rb->GetPointer = get_pointer_ubyte4;
996      rb->GetRow = get_row_ubyte4;
997      rb->GetValues = get_values_ubyte4;
998      rb->PutRow = put_row_ubyte4;
999      rb->PutRowRGB = put_row_rgb_ubyte4;
1000      rb->PutMonoRow = put_mono_row_ubyte4;
1001      rb->PutValues = put_values_ubyte4;
1002      rb->PutMonoValues = put_mono_values_ubyte4;
1003      rb->RedBits   = 8 * sizeof(GLubyte);
1004      rb->GreenBits = 8 * sizeof(GLubyte);
1005      rb->BlueBits  = 8 * sizeof(GLubyte);
1006      rb->AlphaBits = 8 * sizeof(GLubyte);
1007      pixelSize = 4 * sizeof(GLubyte);
1008      break;
1009   case GL_RGB10_A2:
1010   case GL_RGBA12:
1011   case GL_RGBA16:
1012      rb->_ActualFormat = GL_RGBA16;
1013      rb->_BaseFormat = GL_RGBA;
1014      rb->DataType = GL_UNSIGNED_SHORT;
1015      rb->GetPointer = get_pointer_ushort4;
1016      rb->GetRow = get_row_ushort4;
1017      rb->GetValues = get_values_ushort4;
1018      rb->PutRow = put_row_ushort4;
1019      rb->PutRowRGB = put_row_rgb_ushort4;
1020      rb->PutMonoRow = put_mono_row_ushort4;
1021      rb->PutValues = put_values_ushort4;
1022      rb->PutMonoValues = put_mono_values_ushort4;
1023      rb->RedBits   = 8 * sizeof(GLushort);
1024      rb->GreenBits = 8 * sizeof(GLushort);
1025      rb->BlueBits  = 8 * sizeof(GLushort);
1026      rb->AlphaBits = 8 * sizeof(GLushort);
1027      pixelSize = 4 * sizeof(GLushort);
1028      break;
1029#if 00
1030   case GL_ALPHA8:
1031      rb->_ActualFormat = GL_ALPHA8;
1032      rb->_BaseFormat = GL_RGBA; /* Yes, not GL_ALPHA! */
1033      rb->DataType = GL_UNSIGNED_BYTE;
1034      rb->GetPointer = get_pointer_alpha8;
1035      rb->GetRow = get_row_alpha8;
1036      rb->GetValues = get_values_alpha8;
1037      rb->PutRow = put_row_alpha8;
1038      rb->PutRowRGB = NULL;
1039      rb->PutMonoRow = put_mono_row_alpha8;
1040      rb->PutValues = put_values_alpha8;
1041      rb->PutMonoValues = put_mono_values_alpha8;
1042      rb->RedBits   = 0; /*red*/
1043      rb->GreenBits = 0; /*green*/
1044      rb->BlueBits  = 0; /*blue*/
1045      rb->AlphaBits = 8 * sizeof(GLubyte);
1046      pixelSize = sizeof(GLubyte);
1047      break;
1048#endif
1049   case GL_STENCIL_INDEX:
1050   case GL_STENCIL_INDEX1_EXT:
1051   case GL_STENCIL_INDEX4_EXT:
1052   case GL_STENCIL_INDEX8_EXT:
1053      rb->_ActualFormat = GL_STENCIL_INDEX8_EXT;
1054      rb->_BaseFormat = GL_STENCIL_INDEX;
1055      rb->DataType = GL_UNSIGNED_BYTE;
1056      rb->GetPointer = get_pointer_ubyte;
1057      rb->GetRow = get_row_ubyte;
1058      rb->GetValues = get_values_ubyte;
1059      rb->PutRow = put_row_ubyte;
1060      rb->PutRowRGB = NULL;
1061      rb->PutMonoRow = put_mono_row_ubyte;
1062      rb->PutValues = put_values_ubyte;
1063      rb->PutMonoValues = put_mono_values_ubyte;
1064      rb->StencilBits = 8 * sizeof(GLubyte);
1065      pixelSize = sizeof(GLubyte);
1066      break;
1067   case GL_STENCIL_INDEX16_EXT:
1068      rb->_ActualFormat = GL_STENCIL_INDEX16_EXT;
1069      rb->_BaseFormat = GL_STENCIL_INDEX;
1070      rb->DataType = GL_UNSIGNED_SHORT;
1071      rb->GetPointer = get_pointer_ushort;
1072      rb->GetRow = get_row_ushort;
1073      rb->GetValues = get_values_ushort;
1074      rb->PutRow = put_row_ushort;
1075      rb->PutRowRGB = NULL;
1076      rb->PutMonoRow = put_mono_row_ushort;
1077      rb->PutValues = put_values_ushort;
1078      rb->PutMonoValues = put_mono_values_ushort;
1079      rb->StencilBits = 8 * sizeof(GLushort);
1080      pixelSize = sizeof(GLushort);
1081      break;
1082   case GL_DEPTH_COMPONENT:
1083   case GL_DEPTH_COMPONENT16:
1084      rb->_ActualFormat = GL_DEPTH_COMPONENT16;
1085      rb->_BaseFormat = GL_DEPTH_COMPONENT;
1086      rb->DataType = GL_UNSIGNED_SHORT;
1087      rb->GetPointer = get_pointer_ushort;
1088      rb->GetRow = get_row_ushort;
1089      rb->GetValues = get_values_ushort;
1090      rb->PutRow = put_row_ushort;
1091      rb->PutRowRGB = NULL;
1092      rb->PutMonoRow = put_mono_row_ushort;
1093      rb->PutValues = put_values_ushort;
1094      rb->PutMonoValues = put_mono_values_ushort;
1095      rb->DepthBits = 8 * sizeof(GLushort);
1096      pixelSize = sizeof(GLushort);
1097      break;
1098   case GL_DEPTH_COMPONENT24:
1099   case GL_DEPTH_COMPONENT32:
1100      rb->_BaseFormat = GL_DEPTH_COMPONENT;
1101      rb->DataType = GL_UNSIGNED_INT;
1102      rb->GetPointer = get_pointer_uint;
1103      rb->GetRow = get_row_uint;
1104      rb->GetValues = get_values_uint;
1105      rb->PutRow = put_row_uint;
1106      rb->PutRowRGB = NULL;
1107      rb->PutMonoRow = put_mono_row_uint;
1108      rb->PutValues = put_values_uint;
1109      rb->PutMonoValues = put_mono_values_uint;
1110      if (internalFormat == GL_DEPTH_COMPONENT24) {
1111         rb->_ActualFormat = GL_DEPTH_COMPONENT24;
1112         rb->DepthBits = 24;
1113      }
1114      else {
1115         rb->_ActualFormat = GL_DEPTH_COMPONENT32;
1116         rb->DepthBits = 32;
1117      }
1118      pixelSize = sizeof(GLuint);
1119      break;
1120   case GL_DEPTH_STENCIL_EXT:
1121   case GL_DEPTH24_STENCIL8_EXT:
1122      rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
1123      rb->_BaseFormat = GL_DEPTH_STENCIL_EXT;
1124      rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
1125      rb->GetPointer = get_pointer_uint;
1126      rb->GetRow = get_row_uint;
1127      rb->GetValues = get_values_uint;
1128      rb->PutRow = put_row_uint;
1129      rb->PutRowRGB = NULL;
1130      rb->PutMonoRow = put_mono_row_uint;
1131      rb->PutValues = put_values_uint;
1132      rb->PutMonoValues = put_mono_values_uint;
1133      rb->DepthBits = 24;
1134      rb->StencilBits = 8;
1135      pixelSize = sizeof(GLuint);
1136      break;
1137   case GL_COLOR_INDEX8_EXT:
1138      rb->_ActualFormat = GL_COLOR_INDEX8_EXT;
1139      rb->_BaseFormat = GL_COLOR_INDEX;
1140      rb->DataType = GL_UNSIGNED_BYTE;
1141      rb->GetPointer = get_pointer_ubyte;
1142      rb->GetRow = get_row_ubyte;
1143      rb->GetValues = get_values_ubyte;
1144      rb->PutRow = put_row_ubyte;
1145      rb->PutRowRGB = NULL;
1146      rb->PutMonoRow = put_mono_row_ubyte;
1147      rb->PutValues = put_values_ubyte;
1148      rb->PutMonoValues = put_mono_values_ubyte;
1149      rb->IndexBits = 8 * sizeof(GLubyte);
1150      pixelSize = sizeof(GLubyte);
1151      break;
1152   case GL_COLOR_INDEX16_EXT:
1153      rb->_ActualFormat = GL_COLOR_INDEX16_EXT;
1154      rb->_BaseFormat = GL_COLOR_INDEX;
1155      rb->DataType = GL_UNSIGNED_SHORT;
1156      rb->GetPointer = get_pointer_ushort;
1157      rb->GetRow = get_row_ushort;
1158      rb->GetValues = get_values_ushort;
1159      rb->PutRow = put_row_ushort;
1160      rb->PutRowRGB = NULL;
1161      rb->PutMonoRow = put_mono_row_ushort;
1162      rb->PutValues = put_values_ushort;
1163      rb->PutMonoValues = put_mono_values_ushort;
1164      rb->IndexBits = 8 * sizeof(GLushort);
1165      pixelSize = sizeof(GLushort);
1166      break;
1167   case COLOR_INDEX32:
1168      rb->_ActualFormat = COLOR_INDEX32;
1169      rb->_BaseFormat = GL_COLOR_INDEX;
1170      rb->DataType = GL_UNSIGNED_INT;
1171      rb->GetPointer = get_pointer_uint;
1172      rb->GetRow = get_row_uint;
1173      rb->GetValues = get_values_uint;
1174      rb->PutRow = put_row_uint;
1175      rb->PutRowRGB = NULL;
1176      rb->PutMonoRow = put_mono_row_uint;
1177      rb->PutValues = put_values_uint;
1178      rb->PutMonoValues = put_mono_values_uint;
1179      rb->IndexBits = 8 * sizeof(GLuint);
1180      pixelSize = sizeof(GLuint);
1181      break;
1182   default:
1183      _mesa_problem(ctx, "Bad internalFormat in _mesa_soft_renderbuffer_storage");
1184      return GL_FALSE;
1185   }
1186
1187   ASSERT(rb->DataType);
1188   ASSERT(rb->GetPointer);
1189   ASSERT(rb->GetRow);
1190   ASSERT(rb->GetValues);
1191   ASSERT(rb->PutRow);
1192   ASSERT(rb->PutMonoRow);
1193   ASSERT(rb->PutValues);
1194   ASSERT(rb->PutMonoValues);
1195
1196   /* free old buffer storage */
1197   if (rb->Data) {
1198      _mesa_free(rb->Data);
1199      rb->Data = NULL;
1200   }
1201
1202   if (width > 0 && height > 0) {
1203      /* allocate new buffer storage */
1204      rb->Data = malloc(width * height * pixelSize);
1205
1206      if (rb->Data == NULL) {
1207         rb->Width = 0;
1208         rb->Height = 0;
1209         _mesa_error(ctx, GL_OUT_OF_MEMORY,
1210                     "software renderbuffer allocation (%d x %d x %d)",
1211                     width, height, pixelSize);
1212         return GL_FALSE;
1213      }
1214   }
1215
1216   rb->Width = width;
1217   rb->Height = height;
1218
1219   return GL_TRUE;
1220}
1221
1222
1223
1224/**********************************************************************/
1225/**********************************************************************/
1226/**********************************************************************/
1227
1228
1229/**
1230 * Here we utilize the gl_renderbuffer->Wrapper field to put an alpha
1231 * buffer wrapper around an existing RGB renderbuffer (hw or sw).
1232 *
1233 * When PutRow is called (for example), we store the alpha values in
1234 * this buffer, then pass on the PutRow call to the wrapped RGB
1235 * buffer.
1236 */
1237
1238
1239static GLboolean
1240alloc_storage_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb,
1241                     GLenum internalFormat, GLuint width, GLuint height)
1242{
1243   ASSERT(arb != arb->Wrapped);
1244   ASSERT(arb->_ActualFormat == GL_ALPHA8);
1245
1246   /* first, pass the call to the wrapped RGB buffer */
1247   if (!arb->Wrapped->AllocStorage(ctx, arb->Wrapped, internalFormat,
1248                                  width, height)) {
1249      return GL_FALSE;
1250   }
1251
1252   /* next, resize my alpha buffer */
1253   if (arb->Data) {
1254      _mesa_free(arb->Data);
1255   }
1256
1257   arb->Data = _mesa_malloc(width * height * sizeof(GLubyte));
1258   if (arb->Data == NULL) {
1259      arb->Width = 0;
1260      arb->Height = 0;
1261      _mesa_error(ctx, GL_OUT_OF_MEMORY, "software alpha buffer allocation");
1262      return GL_FALSE;
1263   }
1264
1265   arb->Width = width;
1266   arb->Height = height;
1267
1268   return GL_TRUE;
1269}
1270
1271
1272/**
1273 * Delete an alpha_renderbuffer object, as well as the wrapped RGB buffer.
1274 */
1275static void
1276delete_renderbuffer_alpha8(struct gl_renderbuffer *arb)
1277{
1278   if (arb->Data) {
1279      _mesa_free(arb->Data);
1280   }
1281   ASSERT(arb->Wrapped);
1282   ASSERT(arb != arb->Wrapped);
1283   arb->Wrapped->Delete(arb->Wrapped);
1284   arb->Wrapped = NULL;
1285   _mesa_free(arb);
1286}
1287
1288
1289static void *
1290get_pointer_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb,
1291                   GLint x, GLint y)
1292{
1293   return NULL;   /* don't allow direct access! */
1294}
1295
1296
1297static void
1298get_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1299               GLint x, GLint y, void *values)
1300{
1301   /* NOTE: 'values' is RGBA format! */
1302   const GLubyte *src = (const GLubyte *) arb->Data + y * arb->Width + x;
1303   GLubyte *dst = (GLubyte *) values;
1304   GLuint i;
1305   ASSERT(arb != arb->Wrapped);
1306   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1307   /* first, pass the call to the wrapped RGB buffer */
1308   arb->Wrapped->GetRow(ctx, arb->Wrapped, count, x, y, values);
1309   /* second, fill in alpha values from this buffer! */
1310   for (i = 0; i < count; i++) {
1311      dst[i * 4 + 3] = src[i];
1312   }
1313}
1314
1315
1316static void
1317get_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1318                  const GLint x[], const GLint y[], void *values)
1319{
1320   GLubyte *dst = (GLubyte *) values;
1321   GLuint i;
1322   ASSERT(arb != arb->Wrapped);
1323   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1324   /* first, pass the call to the wrapped RGB buffer */
1325   arb->Wrapped->GetValues(ctx, arb->Wrapped, count, x, y, values);
1326   /* second, fill in alpha values from this buffer! */
1327   for (i = 0; i < count; i++) {
1328      const GLubyte *src = (GLubyte *) arb->Data + y[i] * arb->Width + x[i];
1329      dst[i * 4 + 3] = *src;
1330   }
1331}
1332
1333
1334static void
1335put_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1336               GLint x, GLint y, const void *values, const GLubyte *mask)
1337{
1338   const GLubyte *src = (const GLubyte *) values;
1339   GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x;
1340   GLuint i;
1341   ASSERT(arb != arb->Wrapped);
1342   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1343   /* first, pass the call to the wrapped RGB buffer */
1344   arb->Wrapped->PutRow(ctx, arb->Wrapped, count, x, y, values, mask);
1345   /* second, store alpha in our buffer */
1346   for (i = 0; i < count; i++) {
1347      if (!mask || mask[i]) {
1348         dst[i] = src[i * 4 + 3];
1349      }
1350   }
1351}
1352
1353
1354static void
1355put_row_rgb_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1356                   GLint x, GLint y, const void *values, const GLubyte *mask)
1357{
1358   const GLubyte *src = (const GLubyte *) values;
1359   GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x;
1360   GLuint i;
1361   ASSERT(arb != arb->Wrapped);
1362   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1363   /* first, pass the call to the wrapped RGB buffer */
1364   arb->Wrapped->PutRowRGB(ctx, arb->Wrapped, count, x, y, values, mask);
1365   /* second, store alpha in our buffer */
1366   for (i = 0; i < count; i++) {
1367      if (!mask || mask[i]) {
1368         dst[i] = src[i * 4 + 3];
1369      }
1370   }
1371}
1372
1373
1374static void
1375put_mono_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1376                    GLint x, GLint y, const void *value, const GLubyte *mask)
1377{
1378   const GLubyte val = ((const GLubyte *) value)[3];
1379   GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x;
1380   ASSERT(arb != arb->Wrapped);
1381   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1382   /* first, pass the call to the wrapped RGB buffer */
1383   arb->Wrapped->PutMonoRow(ctx, arb->Wrapped, count, x, y, value, mask);
1384   /* second, store alpha in our buffer */
1385   if (mask) {
1386      GLuint i;
1387      for (i = 0; i < count; i++) {
1388         if (mask[i]) {
1389            dst[i] = val;
1390         }
1391      }
1392   }
1393   else {
1394      _mesa_memset(dst, val, count);
1395   }
1396}
1397
1398
1399static void
1400put_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1401                  const GLint x[], const GLint y[],
1402                  const void *values, const GLubyte *mask)
1403{
1404   const GLubyte *src = (const GLubyte *) values;
1405   GLuint i;
1406   ASSERT(arb != arb->Wrapped);
1407   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1408   /* first, pass the call to the wrapped RGB buffer */
1409   arb->Wrapped->PutValues(ctx, arb->Wrapped, count, x, y, values, mask);
1410   /* second, store alpha in our buffer */
1411   for (i = 0; i < count; i++) {
1412      if (!mask || mask[i]) {
1413         GLubyte *dst = (GLubyte *) arb->Data + y[i] * arb->Width + x[i];
1414         *dst = src[i * 4 + 3];
1415      }
1416   }
1417}
1418
1419
1420static void
1421put_mono_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb,
1422                       GLuint count, const GLint x[], const GLint y[],
1423                       const void *value, const GLubyte *mask)
1424{
1425   const GLubyte val = ((const GLubyte *) value)[3];
1426   GLuint i;
1427   ASSERT(arb != arb->Wrapped);
1428   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1429   /* first, pass the call to the wrapped RGB buffer */
1430   arb->Wrapped->PutValues(ctx, arb->Wrapped, count, x, y, value, mask);
1431   /* second, store alpha in our buffer */
1432   for (i = 0; i < count; i++) {
1433      if (!mask || mask[i]) {
1434         GLubyte *dst = (GLubyte *) arb->Data + y[i] * arb->Width + x[i];
1435         *dst = val;
1436      }
1437   }
1438}
1439
1440
1441static void
1442copy_buffer_alpha8(struct gl_renderbuffer* dst, struct gl_renderbuffer* src)
1443{
1444   ASSERT(dst->_ActualFormat == GL_ALPHA8);
1445   ASSERT(src->_ActualFormat == GL_ALPHA8);
1446   ASSERT(dst->Width == src->Width);
1447   ASSERT(dst->Height == src->Height);
1448
1449   _mesa_memcpy(dst->Data, src->Data, dst->Width * dst->Height * sizeof(GLubyte));
1450}
1451
1452
1453/**********************************************************************/
1454/**********************************************************************/
1455/**********************************************************************/
1456
1457
1458/**
1459 * Default GetPointer routine.  Always return NULL to indicate that
1460 * direct buffer access is not supported.
1461 */
1462static void *
1463nop_get_pointer(GLcontext *ctx, struct gl_renderbuffer *rb, GLint x, GLint y)
1464{
1465   return NULL;
1466}
1467
1468
1469/**
1470 * Initialize the fields of a gl_renderbuffer to default values.
1471 */
1472void
1473_mesa_init_renderbuffer(struct gl_renderbuffer *rb, GLuint name)
1474{
1475   _glthread_INIT_MUTEX(rb->Mutex);
1476
1477   rb->Magic = RB_MAGIC;
1478   rb->ClassID = 0;
1479   rb->Name = name;
1480   rb->RefCount = 0;
1481   rb->Delete = _mesa_delete_renderbuffer;
1482
1483   /* The rest of these should be set later by the caller of this function or
1484    * the AllocStorage method:
1485    */
1486   rb->AllocStorage = NULL;
1487
1488   rb->Width = 0;
1489   rb->Height = 0;
1490   rb->InternalFormat = GL_NONE;
1491   rb->_ActualFormat = GL_NONE;
1492   rb->_BaseFormat = GL_NONE;
1493   rb->DataType = GL_NONE;
1494   rb->RedBits = rb->GreenBits = rb->BlueBits = rb->AlphaBits = 0;
1495   rb->IndexBits = 0;
1496   rb->DepthBits = 0;
1497   rb->StencilBits = 0;
1498   rb->Data = NULL;
1499
1500   /* Point back to ourself so that we don't have to check for Wrapped==NULL
1501    * all over the drivers.
1502    */
1503   rb->Wrapped = rb;
1504
1505   rb->GetPointer = nop_get_pointer;
1506   rb->GetRow = NULL;
1507   rb->GetValues = NULL;
1508   rb->PutRow = NULL;
1509   rb->PutRowRGB = NULL;
1510   rb->PutMonoRow = NULL;
1511   rb->PutValues = NULL;
1512   rb->PutMonoValues = NULL;
1513}
1514
1515
1516/**
1517 * Allocate a new gl_renderbuffer object.  This can be used for user-created
1518 * renderbuffers or window-system renderbuffers.
1519 */
1520struct gl_renderbuffer *
1521_mesa_new_renderbuffer(GLcontext *ctx, GLuint name)
1522{
1523   struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer);
1524   if (rb) {
1525      _mesa_init_renderbuffer(rb, name);
1526   }
1527   return rb;
1528}
1529
1530
1531/**
1532 * Delete a gl_framebuffer.
1533 * This is the default function for renderbuffer->Delete().
1534 */
1535void
1536_mesa_delete_renderbuffer(struct gl_renderbuffer *rb)
1537{
1538   if (rb->Data) {
1539      _mesa_free(rb->Data);
1540   }
1541   _mesa_free(rb);
1542}
1543
1544
1545/**
1546 * Allocate a software-based renderbuffer.  This is called via the
1547 * ctx->Driver.NewRenderbuffer() function when the user creates a new
1548 * renderbuffer.
1549 * This would not be used for hardware-based renderbuffers.
1550 */
1551struct gl_renderbuffer *
1552_mesa_new_soft_renderbuffer(GLcontext *ctx, GLuint name)
1553{
1554   struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, name);
1555   if (rb) {
1556      rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1557      /* Normally, one would setup the PutRow, GetRow, etc functions here.
1558       * But we're doing that in the _mesa_soft_renderbuffer_storage() function
1559       * instead.
1560       */
1561   }
1562   return rb;
1563}
1564
1565
1566/**
1567 * Add software-based color renderbuffers to the given framebuffer.
1568 * This is a helper routine for device drivers when creating a
1569 * window system framebuffer (not a user-created render/framebuffer).
1570 * Once this function is called, you can basically forget about this
1571 * renderbuffer; core Mesa will handle all the buffer management and
1572 * rendering!
1573 */
1574GLboolean
1575_mesa_add_color_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
1576                              GLuint rgbBits, GLuint alphaBits,
1577                              GLboolean frontLeft, GLboolean backLeft,
1578                              GLboolean frontRight, GLboolean backRight)
1579{
1580   GLuint b;
1581
1582   if (rgbBits > 16 || alphaBits > 16) {
1583      _mesa_problem(ctx,
1584                    "Unsupported bit depth in _mesa_add_color_renderbuffers");
1585      return GL_FALSE;
1586   }
1587
1588   assert(MAX_COLOR_ATTACHMENTS >= 4);
1589
1590   for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
1591      struct gl_renderbuffer *rb;
1592
1593      if (b == BUFFER_FRONT_LEFT && !frontLeft)
1594         continue;
1595      else if (b == BUFFER_BACK_LEFT && !backLeft)
1596         continue;
1597      else if (b == BUFFER_FRONT_RIGHT && !frontRight)
1598         continue;
1599      else if (b == BUFFER_BACK_RIGHT && !backRight)
1600         continue;
1601
1602      assert(fb->Attachment[b].Renderbuffer == NULL);
1603
1604      rb = _mesa_new_renderbuffer(ctx, 0);
1605      if (!rb) {
1606         _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer");
1607         return GL_FALSE;
1608      }
1609
1610      if (rgbBits <= 8) {
1611         if (alphaBits)
1612            rb->_ActualFormat = GL_RGBA8;
1613         else
1614            rb->_ActualFormat = GL_RGB8;
1615      }
1616      else {
1617         assert(rgbBits <= 16);
1618         if (alphaBits)
1619            rb->_ActualFormat = GL_RGBA16;
1620         else
1621            rb->_ActualFormat = GL_RGBA16; /* don't really have RGB16 yet */
1622      }
1623      rb->InternalFormat = rb->_ActualFormat;
1624
1625      rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1626      _mesa_add_renderbuffer(fb, b, rb);
1627   }
1628
1629   return GL_TRUE;
1630}
1631
1632
1633/**
1634 * Add software-based color index renderbuffers to the given framebuffer.
1635 * This is a helper routine for device drivers when creating a
1636 * window system framebuffer (not a user-created render/framebuffer).
1637 * Once this function is called, you can basically forget about this
1638 * renderbuffer; core Mesa will handle all the buffer management and
1639 * rendering!
1640 */
1641GLboolean
1642_mesa_add_color_index_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
1643                                    GLuint indexBits,
1644                                    GLboolean frontLeft, GLboolean backLeft,
1645                                    GLboolean frontRight, GLboolean backRight)
1646{
1647   GLuint b;
1648
1649   if (indexBits > 8) {
1650      _mesa_problem(ctx,
1651                "Unsupported bit depth in _mesa_add_color_index_renderbuffers");
1652      return GL_FALSE;
1653   }
1654
1655   assert(MAX_COLOR_ATTACHMENTS >= 4);
1656
1657   for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
1658      struct gl_renderbuffer *rb;
1659
1660      if (b == BUFFER_FRONT_LEFT && !frontLeft)
1661         continue;
1662      else if (b == BUFFER_BACK_LEFT && !backLeft)
1663         continue;
1664      else if (b == BUFFER_FRONT_RIGHT && !frontRight)
1665         continue;
1666      else if (b == BUFFER_BACK_RIGHT && !backRight)
1667         continue;
1668
1669      assert(fb->Attachment[b].Renderbuffer == NULL);
1670
1671      rb = _mesa_new_renderbuffer(ctx, 0);
1672      if (!rb) {
1673         _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer");
1674         return GL_FALSE;
1675      }
1676
1677      if (indexBits <= 8) {
1678         /* only support GLuint for now */
1679         /*rb->InternalFormat = GL_COLOR_INDEX8_EXT;*/
1680         rb->_ActualFormat = COLOR_INDEX32;
1681      }
1682      else {
1683         rb->_ActualFormat = COLOR_INDEX32;
1684      }
1685      rb->InternalFormat = rb->_ActualFormat;
1686
1687      rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1688      _mesa_add_renderbuffer(fb, b, rb);
1689   }
1690
1691   return GL_TRUE;
1692}
1693
1694
1695/**
1696 * Add software-based alpha renderbuffers to the given framebuffer.
1697 * This is a helper routine for device drivers when creating a
1698 * window system framebuffer (not a user-created render/framebuffer).
1699 * Once this function is called, you can basically forget about this
1700 * renderbuffer; core Mesa will handle all the buffer management and
1701 * rendering!
1702 */
1703GLboolean
1704_mesa_add_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
1705                              GLuint alphaBits,
1706                              GLboolean frontLeft, GLboolean backLeft,
1707                              GLboolean frontRight, GLboolean backRight)
1708{
1709   GLuint b;
1710
1711   /* for window system framebuffers only! */
1712   assert(fb->Name == 0);
1713
1714   if (alphaBits > 8) {
1715      _mesa_problem(ctx,
1716                    "Unsupported bit depth in _mesa_add_alpha_renderbuffers");
1717      return GL_FALSE;
1718   }
1719
1720   assert(MAX_COLOR_ATTACHMENTS >= 4);
1721
1722   /* Wrap each of the RGB color buffers with an alpha renderbuffer.
1723    */
1724   for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
1725      struct gl_renderbuffer *arb;
1726
1727      if (b == BUFFER_FRONT_LEFT && !frontLeft)
1728         continue;
1729      else if (b == BUFFER_BACK_LEFT && !backLeft)
1730         continue;
1731      else if (b == BUFFER_FRONT_RIGHT && !frontRight)
1732         continue;
1733      else if (b == BUFFER_BACK_RIGHT && !backRight)
1734         continue;
1735
1736      /* the RGB buffer to wrap must already exist!! */
1737      assert(fb->Attachment[b].Renderbuffer);
1738
1739      /* only GLubyte supported for now */
1740      assert(fb->Attachment[b].Renderbuffer->DataType == GL_UNSIGNED_BYTE);
1741
1742      /* allocate alpha renderbuffer */
1743      arb = _mesa_new_renderbuffer(ctx, 0);
1744      if (!arb) {
1745         _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating alpha buffer");
1746         return GL_FALSE;
1747      }
1748
1749      /* wrap the alpha renderbuffer around the RGB renderbuffer */
1750      arb->Wrapped = fb->Attachment[b].Renderbuffer;
1751
1752      /* Set up my alphabuffer fields and plug in my functions.
1753       * The functions will put/get the alpha values from/to RGBA arrays
1754       * and then call the wrapped buffer's functions to handle the RGB
1755       * values.
1756       */
1757      arb->InternalFormat = arb->Wrapped->InternalFormat;
1758      arb->_ActualFormat  = GL_ALPHA8;
1759      arb->_BaseFormat    = arb->Wrapped->_BaseFormat;
1760      arb->DataType       = arb->Wrapped->DataType;
1761      arb->AllocStorage   = alloc_storage_alpha8;
1762      arb->Delete         = delete_renderbuffer_alpha8;
1763      arb->GetPointer     = get_pointer_alpha8;
1764      arb->GetRow         = get_row_alpha8;
1765      arb->GetValues      = get_values_alpha8;
1766      arb->PutRow         = put_row_alpha8;
1767      arb->PutRowRGB      = put_row_rgb_alpha8;
1768      arb->PutMonoRow     = put_mono_row_alpha8;
1769      arb->PutValues      = put_values_alpha8;
1770      arb->PutMonoValues  = put_mono_values_alpha8;
1771
1772      /* clear the pointer to avoid assertion/sanity check failure later */
1773      fb->Attachment[b].Renderbuffer = NULL;
1774
1775      /* plug the alpha renderbuffer into the colorbuffer attachment */
1776      _mesa_add_renderbuffer(fb, b, arb);
1777   }
1778
1779   return GL_TRUE;
1780}
1781
1782
1783/**
1784 * For framebuffers that use a software alpha channel wrapper
1785 * created by _mesa_add_alpha_renderbuffer or _mesa_add_soft_renderbuffers,
1786 * copy the back buffer alpha channel into the front buffer alpha channel.
1787 */
1788void
1789_mesa_copy_soft_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb)
1790{
1791   if (fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer &&
1792       fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer)
1793      copy_buffer_alpha8(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer,
1794                         fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
1795
1796
1797   if (fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer &&
1798       fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer)
1799      copy_buffer_alpha8(fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer,
1800                         fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer);
1801}
1802
1803
1804/**
1805 * Add a software-based depth renderbuffer to the given framebuffer.
1806 * This is a helper routine for device drivers when creating a
1807 * window system framebuffer (not a user-created render/framebuffer).
1808 * Once this function is called, you can basically forget about this
1809 * renderbuffer; core Mesa will handle all the buffer management and
1810 * rendering!
1811 */
1812GLboolean
1813_mesa_add_depth_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
1814                             GLuint depthBits)
1815{
1816   struct gl_renderbuffer *rb;
1817
1818   if (depthBits > 32) {
1819      _mesa_problem(ctx,
1820                    "Unsupported depthBits in _mesa_add_depth_renderbuffer");
1821      return GL_FALSE;
1822   }
1823
1824   assert(fb->Attachment[BUFFER_DEPTH].Renderbuffer == NULL);
1825
1826   rb = _mesa_new_renderbuffer(ctx, 0);
1827   if (!rb) {
1828      _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating depth buffer");
1829      return GL_FALSE;
1830   }
1831
1832   if (depthBits <= 16) {
1833      rb->_ActualFormat = GL_DEPTH_COMPONENT16;
1834   }
1835   else if (depthBits <= 24) {
1836      rb->_ActualFormat = GL_DEPTH_COMPONENT24;
1837   }
1838   else {
1839      rb->_ActualFormat = GL_DEPTH_COMPONENT32;
1840   }
1841   rb->InternalFormat = rb->_ActualFormat;
1842
1843   rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1844   _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
1845
1846   return GL_TRUE;
1847}
1848
1849
1850/**
1851 * Add a software-based stencil renderbuffer to the given framebuffer.
1852 * This is a helper routine for device drivers when creating a
1853 * window system framebuffer (not a user-created render/framebuffer).
1854 * Once this function is called, you can basically forget about this
1855 * renderbuffer; core Mesa will handle all the buffer management and
1856 * rendering!
1857 */
1858GLboolean
1859_mesa_add_stencil_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
1860                               GLuint stencilBits)
1861{
1862   struct gl_renderbuffer *rb;
1863
1864   if (stencilBits > 16) {
1865      _mesa_problem(ctx,
1866                  "Unsupported stencilBits in _mesa_add_stencil_renderbuffer");
1867      return GL_FALSE;
1868   }
1869
1870   assert(fb->Attachment[BUFFER_STENCIL].Renderbuffer == NULL);
1871
1872   rb = _mesa_new_renderbuffer(ctx, 0);
1873   if (!rb) {
1874      _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating stencil buffer");
1875      return GL_FALSE;
1876   }
1877
1878   if (stencilBits <= 8) {
1879      rb->_ActualFormat = GL_STENCIL_INDEX8_EXT;
1880   }
1881   else {
1882      /* not really supported (see s_stencil.c code) */
1883      rb->_ActualFormat = GL_STENCIL_INDEX16_EXT;
1884   }
1885   rb->InternalFormat = rb->_ActualFormat;
1886
1887   rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1888   _mesa_add_renderbuffer(fb, BUFFER_STENCIL, rb);
1889
1890   return GL_TRUE;
1891}
1892
1893
1894/**
1895 * Add a software-based accumulation renderbuffer to the given framebuffer.
1896 * This is a helper routine for device drivers when creating a
1897 * window system framebuffer (not a user-created render/framebuffer).
1898 * Once this function is called, you can basically forget about this
1899 * renderbuffer; core Mesa will handle all the buffer management and
1900 * rendering!
1901 */
1902GLboolean
1903_mesa_add_accum_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
1904                             GLuint redBits, GLuint greenBits,
1905                             GLuint blueBits, GLuint alphaBits)
1906{
1907   struct gl_renderbuffer *rb;
1908
1909   if (redBits > 16 || greenBits > 16 || blueBits > 16 || alphaBits > 16) {
1910      _mesa_problem(ctx,
1911                    "Unsupported accumBits in _mesa_add_accum_renderbuffer");
1912      return GL_FALSE;
1913   }
1914
1915   assert(fb->Attachment[BUFFER_ACCUM].Renderbuffer == NULL);
1916
1917   rb = _mesa_new_renderbuffer(ctx, 0);
1918   if (!rb) {
1919      _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer");
1920      return GL_FALSE;
1921   }
1922
1923   rb->_ActualFormat = GL_RGBA16;
1924   rb->InternalFormat = GL_RGBA16;
1925   rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1926   _mesa_add_renderbuffer(fb, BUFFER_ACCUM, rb);
1927
1928   return GL_TRUE;
1929}
1930
1931
1932
1933/**
1934 * Add a software-based accumulation renderbuffer to the given framebuffer.
1935 * This is a helper routine for device drivers when creating a
1936 * window system framebuffer (not a user-created render/framebuffer).
1937 * Once this function is called, you can basically forget about this
1938 * renderbuffer; core Mesa will handle all the buffer management and
1939 * rendering!
1940 *
1941 * NOTE: color-index aux buffers not supported.
1942 */
1943GLboolean
1944_mesa_add_aux_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
1945                            GLuint colorBits, GLuint numBuffers)
1946{
1947   GLuint i;
1948
1949   if (colorBits > 16) {
1950      _mesa_problem(ctx,
1951                    "Unsupported accumBits in _mesa_add_aux_renderbuffers");
1952      return GL_FALSE;
1953   }
1954
1955   assert(numBuffers < MAX_AUX_BUFFERS);
1956
1957   for (i = 0; i < numBuffers; i++) {
1958      struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, 0);
1959
1960      assert(fb->Attachment[BUFFER_AUX0 + i].Renderbuffer == NULL);
1961
1962      if (!rb) {
1963         _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer");
1964         return GL_FALSE;
1965      }
1966
1967      if (colorBits <= 8) {
1968         rb->_ActualFormat = GL_RGBA8;
1969      }
1970      else {
1971         rb->_ActualFormat = GL_RGBA16;
1972      }
1973      rb->InternalFormat = rb->_ActualFormat;
1974
1975      rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1976      _mesa_add_renderbuffer(fb, BUFFER_AUX0 + i, rb);
1977   }
1978   return GL_TRUE;
1979}
1980
1981
1982/**
1983 * Create/attach software-based renderbuffers to the given framebuffer.
1984 * This is a helper routine for device drivers.  Drivers can just as well
1985 * call the individual _mesa_add_*_renderbuffer() routines directly.
1986 */
1987void
1988_mesa_add_soft_renderbuffers(struct gl_framebuffer *fb,
1989                             GLboolean color,
1990                             GLboolean depth,
1991                             GLboolean stencil,
1992                             GLboolean accum,
1993                             GLboolean alpha,
1994                             GLboolean aux)
1995{
1996   GLboolean frontLeft = GL_TRUE;
1997   GLboolean backLeft = fb->Visual.doubleBufferMode;
1998   GLboolean frontRight = fb->Visual.stereoMode;
1999   GLboolean backRight = fb->Visual.stereoMode && fb->Visual.doubleBufferMode;
2000
2001   if (color) {
2002      if (fb->Visual.rgbMode) {
2003         assert(fb->Visual.redBits == fb->Visual.greenBits);
2004         assert(fb->Visual.redBits == fb->Visual.blueBits);
2005         _mesa_add_color_renderbuffers(NULL, fb,
2006                                       fb->Visual.redBits,
2007                                       fb->Visual.alphaBits,
2008                                       frontLeft, backLeft,
2009                                       frontRight, backRight);
2010      }
2011      else {
2012         _mesa_add_color_index_renderbuffers(NULL, fb,
2013                                             fb->Visual.indexBits,
2014                                             frontLeft, backLeft,
2015                                             frontRight, backRight);
2016      }
2017   }
2018
2019   if (depth) {
2020      assert(fb->Visual.depthBits > 0);
2021      _mesa_add_depth_renderbuffer(NULL, fb, fb->Visual.depthBits);
2022   }
2023
2024   if (stencil) {
2025      assert(fb->Visual.stencilBits > 0);
2026      _mesa_add_stencil_renderbuffer(NULL, fb, fb->Visual.stencilBits);
2027   }
2028
2029   if (accum) {
2030      assert(fb->Visual.rgbMode);
2031      assert(fb->Visual.accumRedBits > 0);
2032      assert(fb->Visual.accumGreenBits > 0);
2033      assert(fb->Visual.accumBlueBits > 0);
2034      _mesa_add_accum_renderbuffer(NULL, fb,
2035                                   fb->Visual.accumRedBits,
2036                                   fb->Visual.accumGreenBits,
2037                                   fb->Visual.accumBlueBits,
2038                                   fb->Visual.accumAlphaBits);
2039   }
2040
2041   if (aux) {
2042      assert(fb->Visual.rgbMode);
2043      assert(fb->Visual.numAuxBuffers > 0);
2044      _mesa_add_aux_renderbuffers(NULL, fb, fb->Visual.redBits,
2045                                  fb->Visual.numAuxBuffers);
2046   }
2047
2048   if (alpha) {
2049      assert(fb->Visual.rgbMode);
2050      assert(fb->Visual.alphaBits > 0);
2051      _mesa_add_alpha_renderbuffers(NULL, fb, fb->Visual.alphaBits,
2052                                    frontLeft, backLeft,
2053                                    frontRight, backRight);
2054   }
2055
2056#if 0
2057   if (multisample) {
2058      /* maybe someday */
2059   }
2060#endif
2061}
2062
2063
2064/**
2065 * Attach a renderbuffer to a framebuffer.
2066 */
2067void
2068_mesa_add_renderbuffer(struct gl_framebuffer *fb,
2069                       GLuint bufferName, struct gl_renderbuffer *rb)
2070{
2071   assert(fb);
2072   assert(rb);
2073   assert(bufferName < BUFFER_COUNT);
2074
2075   /* There should be no previous renderbuffer on this attachment point,
2076    * with the exception of depth/stencil since the same renderbuffer may
2077    * be used for both.
2078    */
2079   assert(bufferName == BUFFER_DEPTH ||
2080          bufferName == BUFFER_STENCIL ||
2081          fb->Attachment[bufferName].Renderbuffer == NULL);
2082
2083   /* winsys vs. user-created buffer cross check */
2084   if (fb->Name) {
2085      assert(rb->Name);
2086   }
2087   else {
2088      assert(!rb->Name);
2089   }
2090
2091   /* If Mesa's compiled with deep color channels (16 or 32 bits / channel)
2092    * and the device driver is expecting 8-bit values (GLubyte), we can
2093    * use a "renderbuffer adaptor/wrapper" to do the necessary conversions.
2094    */
2095   if (rb->_BaseFormat == GL_RGBA) {
2096      if (CHAN_BITS == 16 && rb->DataType == GL_UNSIGNED_BYTE) {
2097         GET_CURRENT_CONTEXT(ctx);
2098         rb = _mesa_new_renderbuffer_16wrap8(ctx, rb);
2099      }
2100      else if (CHAN_BITS == 32 && rb->DataType == GL_UNSIGNED_BYTE) {
2101         GET_CURRENT_CONTEXT(ctx);
2102         rb = _mesa_new_renderbuffer_32wrap8(ctx, rb);
2103      }
2104      else if (CHAN_BITS == 32 && rb->DataType == GL_UNSIGNED_SHORT) {
2105         GET_CURRENT_CONTEXT(ctx);
2106         rb = _mesa_new_renderbuffer_32wrap16(ctx, rb);
2107      }
2108   }
2109
2110   fb->Attachment[bufferName].Type = GL_RENDERBUFFER_EXT;
2111   fb->Attachment[bufferName].Complete = GL_TRUE;
2112   _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer, rb);
2113}
2114
2115
2116/**
2117 * Remove the named renderbuffer from the given framebuffer.
2118 */
2119void
2120_mesa_remove_renderbuffer(struct gl_framebuffer *fb, GLuint bufferName)
2121{
2122   struct gl_renderbuffer *rb;
2123
2124   assert(bufferName < BUFFER_COUNT);
2125
2126   rb = fb->Attachment[bufferName].Renderbuffer;
2127   if (!rb)
2128      return;
2129
2130   _mesa_reference_renderbuffer(&rb, NULL);
2131
2132   fb->Attachment[bufferName].Renderbuffer = NULL;
2133}
2134
2135
2136/**
2137 * Set *ptr to point to rb.  If *ptr points to another renderbuffer,
2138 * dereference that buffer first.  The new renderbuffer's refcount will
2139 * be incremented.  The old renderbuffer's refcount will be decremented.
2140 */
2141void
2142_mesa_reference_renderbuffer(struct gl_renderbuffer **ptr,
2143                             struct gl_renderbuffer *rb)
2144{
2145   assert(ptr);
2146   if (*ptr == rb) {
2147      /* no change */
2148      return;
2149   }
2150
2151   if (*ptr) {
2152      /* Unreference the old renderbuffer */
2153      GLboolean deleteFlag = GL_FALSE;
2154      struct gl_renderbuffer *oldRb = *ptr;
2155
2156      assert(oldRb->Magic == RB_MAGIC);
2157      _glthread_LOCK_MUTEX(oldRb->Mutex);
2158      assert(oldRb->Magic == RB_MAGIC);
2159      ASSERT(oldRb->RefCount > 0);
2160      oldRb->RefCount--;
2161      /*printf("RB DECR %p (%d) to %d\n", (void*) oldRb, oldRb->Name, oldRb->RefCount);*/
2162      deleteFlag = (oldRb->RefCount == 0);
2163      _glthread_UNLOCK_MUTEX(oldRb->Mutex);
2164
2165      if (deleteFlag) {
2166         oldRb->Magic = 0; /* now invalid memory! */
2167         oldRb->Delete(oldRb);
2168      }
2169
2170      *ptr = NULL;
2171   }
2172   assert(!*ptr);
2173
2174   if (rb) {
2175      assert(rb->Magic == RB_MAGIC);
2176      /* reference new renderbuffer */
2177      _glthread_LOCK_MUTEX(rb->Mutex);
2178      rb->RefCount++;
2179      /*printf("RB INCR %p (%d) to %d\n", (void*) rb, rb->Name, rb->RefCount);*/
2180      _glthread_UNLOCK_MUTEX(rb->Mutex);
2181      *ptr = rb;
2182   }
2183}
2184
2185
2186/**
2187 * Create a new combined depth/stencil renderbuffer for implementing
2188 * the GL_EXT_packed_depth_stencil extension.
2189 * \return new depth/stencil renderbuffer
2190 */
2191struct gl_renderbuffer *
2192_mesa_new_depthstencil_renderbuffer(GLcontext *ctx, GLuint name)
2193{
2194   struct gl_renderbuffer *dsrb;
2195
2196   dsrb = _mesa_new_renderbuffer(ctx, name);
2197   if (!dsrb)
2198      return NULL;
2199
2200   /* init fields not covered by _mesa_new_renderbuffer() */
2201   dsrb->InternalFormat = GL_DEPTH24_STENCIL8_EXT;
2202   dsrb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
2203   dsrb->AllocStorage = _mesa_soft_renderbuffer_storage;
2204
2205   return dsrb;
2206}
2207