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