renderbuffer.c revision d77a165eacc44a7c644b1fe26064d62cba440e70
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 GLubyte *src = (const GLubyte *) 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(GLubyte));
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   _mesa_free(rb);
1521}
1522
1523
1524/**
1525 * Allocate a software-based renderbuffer.  This is called via the
1526 * ctx->Driver.NewRenderbuffer() function when the user creates a new
1527 * renderbuffer.
1528 * This would not be used for hardware-based renderbuffers.
1529 */
1530struct gl_renderbuffer *
1531_mesa_new_soft_renderbuffer(GLcontext *ctx, GLuint name)
1532{
1533   struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, name);
1534   if (rb) {
1535      rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1536      /* Normally, one would setup the PutRow, GetRow, etc functions here.
1537       * But we're doing that in the _mesa_soft_renderbuffer_storage() function
1538       * instead.
1539       */
1540   }
1541   return rb;
1542}
1543
1544
1545/**
1546 * Add software-based color renderbuffers to the given framebuffer.
1547 * This is a helper routine for device drivers when creating a
1548 * window system framebuffer (not a user-created render/framebuffer).
1549 * Once this function is called, you can basically forget about this
1550 * renderbuffer; core Mesa will handle all the buffer management and
1551 * rendering!
1552 */
1553GLboolean
1554_mesa_add_color_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
1555                              GLuint rgbBits, GLuint alphaBits,
1556                              GLboolean frontLeft, GLboolean backLeft,
1557                              GLboolean frontRight, GLboolean backRight)
1558{
1559   GLuint b;
1560
1561   if (rgbBits > 16 || alphaBits > 16) {
1562      _mesa_problem(ctx,
1563                    "Unsupported bit depth in _mesa_add_color_renderbuffers");
1564      return GL_FALSE;
1565   }
1566
1567   assert(MAX_COLOR_ATTACHMENTS >= 4);
1568
1569   for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
1570      struct gl_renderbuffer *rb;
1571
1572      if (b == BUFFER_FRONT_LEFT && !frontLeft)
1573         continue;
1574      else if (b == BUFFER_BACK_LEFT && !backLeft)
1575         continue;
1576      else if (b == BUFFER_FRONT_RIGHT && !frontRight)
1577         continue;
1578      else if (b == BUFFER_BACK_RIGHT && !backRight)
1579         continue;
1580
1581      assert(fb->Attachment[b].Renderbuffer == NULL);
1582
1583      rb = _mesa_new_renderbuffer(ctx, 0);
1584      if (!rb) {
1585         _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer");
1586         return GL_FALSE;
1587      }
1588
1589      if (rgbBits <= 8) {
1590         if (alphaBits)
1591            rb->_ActualFormat = GL_RGBA8;
1592         else
1593            rb->_ActualFormat = GL_RGB8;
1594      }
1595      else {
1596         assert(rgbBits <= 16);
1597         if (alphaBits)
1598            rb->_ActualFormat = GL_RGBA16;
1599         else
1600            rb->_ActualFormat = GL_RGBA16; /* don't really have RGB16 yet */
1601      }
1602      rb->InternalFormat = rb->_ActualFormat;
1603
1604      rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1605      _mesa_add_renderbuffer(fb, b, rb);
1606   }
1607
1608   return GL_TRUE;
1609}
1610
1611
1612/**
1613 * Add software-based color index renderbuffers to the given framebuffer.
1614 * This is a helper routine for device drivers when creating a
1615 * window system framebuffer (not a user-created render/framebuffer).
1616 * Once this function is called, you can basically forget about this
1617 * renderbuffer; core Mesa will handle all the buffer management and
1618 * rendering!
1619 */
1620GLboolean
1621_mesa_add_color_index_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
1622                                    GLuint indexBits,
1623                                    GLboolean frontLeft, GLboolean backLeft,
1624                                    GLboolean frontRight, GLboolean backRight)
1625{
1626   GLuint b;
1627
1628   if (indexBits > 8) {
1629      _mesa_problem(ctx,
1630                "Unsupported bit depth in _mesa_add_color_index_renderbuffers");
1631      return GL_FALSE;
1632   }
1633
1634   assert(MAX_COLOR_ATTACHMENTS >= 4);
1635
1636   for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
1637      struct gl_renderbuffer *rb;
1638
1639      if (b == BUFFER_FRONT_LEFT && !frontLeft)
1640         continue;
1641      else if (b == BUFFER_BACK_LEFT && !backLeft)
1642         continue;
1643      else if (b == BUFFER_FRONT_RIGHT && !frontRight)
1644         continue;
1645      else if (b == BUFFER_BACK_RIGHT && !backRight)
1646         continue;
1647
1648      assert(fb->Attachment[b].Renderbuffer == NULL);
1649
1650      rb = _mesa_new_renderbuffer(ctx, 0);
1651      if (!rb) {
1652         _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer");
1653         return GL_FALSE;
1654      }
1655
1656      if (indexBits <= 8) {
1657         /* only support GLuint for now */
1658         /*rb->InternalFormat = GL_COLOR_INDEX8_EXT;*/
1659         rb->_ActualFormat = COLOR_INDEX32;
1660      }
1661      else {
1662         rb->_ActualFormat = COLOR_INDEX32;
1663      }
1664      rb->InternalFormat = rb->_ActualFormat;
1665
1666      rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1667      _mesa_add_renderbuffer(fb, b, rb);
1668   }
1669
1670   return GL_TRUE;
1671}
1672
1673
1674/**
1675 * Add software-based alpha renderbuffers to the given framebuffer.
1676 * This is a helper routine for device drivers when creating a
1677 * window system framebuffer (not a user-created render/framebuffer).
1678 * Once this function is called, you can basically forget about this
1679 * renderbuffer; core Mesa will handle all the buffer management and
1680 * rendering!
1681 */
1682GLboolean
1683_mesa_add_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
1684                              GLuint alphaBits,
1685                              GLboolean frontLeft, GLboolean backLeft,
1686                              GLboolean frontRight, GLboolean backRight)
1687{
1688   GLuint b;
1689
1690   /* for window system framebuffers only! */
1691   assert(fb->Name == 0);
1692
1693   if (alphaBits > 8) {
1694      _mesa_problem(ctx,
1695                    "Unsupported bit depth in _mesa_add_alpha_renderbuffers");
1696      return GL_FALSE;
1697   }
1698
1699   assert(MAX_COLOR_ATTACHMENTS >= 4);
1700
1701   /* Wrap each of the RGB color buffers with an alpha renderbuffer.
1702    */
1703   for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
1704      struct gl_renderbuffer *arb;
1705
1706      if (b == BUFFER_FRONT_LEFT && !frontLeft)
1707         continue;
1708      else if (b == BUFFER_BACK_LEFT && !backLeft)
1709         continue;
1710      else if (b == BUFFER_FRONT_RIGHT && !frontRight)
1711         continue;
1712      else if (b == BUFFER_BACK_RIGHT && !backRight)
1713         continue;
1714
1715      /* the RGB buffer to wrap must already exist!! */
1716      assert(fb->Attachment[b].Renderbuffer);
1717
1718      /* only GLubyte supported for now */
1719      assert(fb->Attachment[b].Renderbuffer->DataType == GL_UNSIGNED_BYTE);
1720
1721      /* allocate alpha renderbuffer */
1722      arb = _mesa_new_renderbuffer(ctx, 0);
1723      if (!arb) {
1724         _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating alpha buffer");
1725         return GL_FALSE;
1726      }
1727
1728      /* wrap the alpha renderbuffer around the RGB renderbuffer */
1729      arb->Wrapped = fb->Attachment[b].Renderbuffer;
1730
1731      /* Set up my alphabuffer fields and plug in my functions.
1732       * The functions will put/get the alpha values from/to RGBA arrays
1733       * and then call the wrapped buffer's functions to handle the RGB
1734       * values.
1735       */
1736      arb->InternalFormat = arb->Wrapped->InternalFormat;
1737      arb->_ActualFormat  = GL_ALPHA8;
1738      arb->_BaseFormat    = arb->Wrapped->_BaseFormat;
1739      arb->DataType       = arb->Wrapped->DataType;
1740      arb->AllocStorage   = alloc_storage_alpha8;
1741      arb->Delete         = delete_renderbuffer_alpha8;
1742      arb->GetPointer     = get_pointer_alpha8;
1743      arb->GetRow         = get_row_alpha8;
1744      arb->GetValues      = get_values_alpha8;
1745      arb->PutRow         = put_row_alpha8;
1746      arb->PutRowRGB      = put_row_rgb_alpha8;
1747      arb->PutMonoRow     = put_mono_row_alpha8;
1748      arb->PutValues      = put_values_alpha8;
1749      arb->PutMonoValues  = put_mono_values_alpha8;
1750
1751      /* clear the pointer to avoid assertion/sanity check failure later */
1752      fb->Attachment[b].Renderbuffer = NULL;
1753
1754      /* plug the alpha renderbuffer into the colorbuffer attachment */
1755      _mesa_add_renderbuffer(fb, b, arb);
1756   }
1757
1758   return GL_TRUE;
1759}
1760
1761
1762/**
1763 * Add a software-based depth renderbuffer to the given framebuffer.
1764 * This is a helper routine for device drivers when creating a
1765 * window system framebuffer (not a user-created render/framebuffer).
1766 * Once this function is called, you can basically forget about this
1767 * renderbuffer; core Mesa will handle all the buffer management and
1768 * rendering!
1769 */
1770GLboolean
1771_mesa_add_depth_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
1772                             GLuint depthBits)
1773{
1774   struct gl_renderbuffer *rb;
1775
1776   if (depthBits > 32) {
1777      _mesa_problem(ctx,
1778                    "Unsupported depthBits in _mesa_add_depth_renderbuffer");
1779      return GL_FALSE;
1780   }
1781
1782   assert(fb->Attachment[BUFFER_DEPTH].Renderbuffer == NULL);
1783
1784   rb = _mesa_new_renderbuffer(ctx, 0);
1785   if (!rb) {
1786      _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating depth buffer");
1787      return GL_FALSE;
1788   }
1789
1790   if (depthBits <= 16) {
1791      rb->_ActualFormat = GL_DEPTH_COMPONENT16;
1792   }
1793   else if (depthBits <= 24) {
1794      rb->_ActualFormat = GL_DEPTH_COMPONENT24;
1795   }
1796   else {
1797      rb->_ActualFormat = GL_DEPTH_COMPONENT32;
1798   }
1799   rb->InternalFormat = rb->_ActualFormat;
1800
1801   rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1802   _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
1803
1804   return GL_TRUE;
1805}
1806
1807
1808/**
1809 * Add a software-based stencil renderbuffer to the given framebuffer.
1810 * This is a helper routine for device drivers when creating a
1811 * window system framebuffer (not a user-created render/framebuffer).
1812 * Once this function is called, you can basically forget about this
1813 * renderbuffer; core Mesa will handle all the buffer management and
1814 * rendering!
1815 */
1816GLboolean
1817_mesa_add_stencil_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
1818                               GLuint stencilBits)
1819{
1820   struct gl_renderbuffer *rb;
1821
1822   if (stencilBits > 16) {
1823      _mesa_problem(ctx,
1824                  "Unsupported stencilBits in _mesa_add_stencil_renderbuffer");
1825      return GL_FALSE;
1826   }
1827
1828   assert(fb->Attachment[BUFFER_STENCIL].Renderbuffer == NULL);
1829
1830   rb = _mesa_new_renderbuffer(ctx, 0);
1831   if (!rb) {
1832      _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating stencil buffer");
1833      return GL_FALSE;
1834   }
1835
1836   if (stencilBits <= 8) {
1837      rb->_ActualFormat = GL_STENCIL_INDEX8_EXT;
1838   }
1839   else {
1840      /* not really supported (see s_stencil.c code) */
1841      rb->_ActualFormat = GL_STENCIL_INDEX16_EXT;
1842   }
1843   rb->InternalFormat = rb->_ActualFormat;
1844
1845   rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1846   _mesa_add_renderbuffer(fb, BUFFER_STENCIL, rb);
1847
1848   return GL_TRUE;
1849}
1850
1851
1852/**
1853 * Add a software-based accumulation renderbuffer to the given framebuffer.
1854 * This is a helper routine for device drivers when creating a
1855 * window system framebuffer (not a user-created render/framebuffer).
1856 * Once this function is called, you can basically forget about this
1857 * renderbuffer; core Mesa will handle all the buffer management and
1858 * rendering!
1859 */
1860GLboolean
1861_mesa_add_accum_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
1862                             GLuint redBits, GLuint greenBits,
1863                             GLuint blueBits, GLuint alphaBits)
1864{
1865   struct gl_renderbuffer *rb;
1866
1867   if (redBits > 16 || greenBits > 16 || blueBits > 16 || alphaBits > 16) {
1868      _mesa_problem(ctx,
1869                    "Unsupported accumBits in _mesa_add_accum_renderbuffer");
1870      return GL_FALSE;
1871   }
1872
1873   assert(fb->Attachment[BUFFER_ACCUM].Renderbuffer == NULL);
1874
1875   rb = _mesa_new_renderbuffer(ctx, 0);
1876   if (!rb) {
1877      _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer");
1878      return GL_FALSE;
1879   }
1880
1881   rb->_ActualFormat = GL_RGBA16;
1882   rb->InternalFormat = GL_RGBA16;
1883   rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1884   _mesa_add_renderbuffer(fb, BUFFER_ACCUM, rb);
1885
1886   return GL_TRUE;
1887}
1888
1889
1890
1891/**
1892 * Add a software-based accumulation renderbuffer to the given framebuffer.
1893 * This is a helper routine for device drivers when creating a
1894 * window system framebuffer (not a user-created render/framebuffer).
1895 * Once this function is called, you can basically forget about this
1896 * renderbuffer; core Mesa will handle all the buffer management and
1897 * rendering!
1898 *
1899 * NOTE: color-index aux buffers not supported.
1900 */
1901GLboolean
1902_mesa_add_aux_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
1903                            GLuint colorBits, GLuint numBuffers)
1904{
1905   GLuint i;
1906
1907   if (colorBits > 16) {
1908      _mesa_problem(ctx,
1909                    "Unsupported accumBits in _mesa_add_aux_renderbuffers");
1910      return GL_FALSE;
1911   }
1912
1913   assert(numBuffers < MAX_AUX_BUFFERS);
1914
1915   for (i = 0; i < numBuffers; i++) {
1916      struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, 0);
1917
1918      assert(fb->Attachment[BUFFER_AUX0 + i].Renderbuffer == NULL);
1919
1920      if (!rb) {
1921         _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer");
1922         return GL_FALSE;
1923      }
1924
1925      if (colorBits <= 8) {
1926         rb->_ActualFormat = GL_RGBA8;
1927      }
1928      else {
1929         rb->_ActualFormat = GL_RGBA16;
1930      }
1931      rb->InternalFormat = rb->_ActualFormat;
1932
1933      rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1934      _mesa_add_renderbuffer(fb, BUFFER_AUX0 + i, rb);
1935   }
1936   return GL_TRUE;
1937}
1938
1939
1940/**
1941 * Create/attach software-based renderbuffers to the given framebuffer.
1942 * This is a helper routine for device drivers.  Drivers can just as well
1943 * call the individual _mesa_add_*_renderbuffer() routines directly.
1944 */
1945void
1946_mesa_add_soft_renderbuffers(struct gl_framebuffer *fb,
1947                             GLboolean color,
1948                             GLboolean depth,
1949                             GLboolean stencil,
1950                             GLboolean accum,
1951                             GLboolean alpha,
1952                             GLboolean aux)
1953{
1954   GLboolean frontLeft = GL_TRUE;
1955   GLboolean backLeft = fb->Visual.doubleBufferMode;
1956   GLboolean frontRight = fb->Visual.stereoMode;
1957   GLboolean backRight = fb->Visual.stereoMode && fb->Visual.doubleBufferMode;
1958
1959   if (color) {
1960      if (fb->Visual.rgbMode) {
1961         assert(fb->Visual.redBits == fb->Visual.greenBits);
1962         assert(fb->Visual.redBits == fb->Visual.blueBits);
1963         _mesa_add_color_renderbuffers(NULL, fb,
1964                                       fb->Visual.redBits,
1965                                       fb->Visual.alphaBits,
1966                                       frontLeft, backLeft,
1967                                       frontRight, backRight);
1968      }
1969      else {
1970         _mesa_add_color_index_renderbuffers(NULL, fb,
1971                                             fb->Visual.indexBits,
1972                                             frontLeft, backLeft,
1973                                             frontRight, backRight);
1974      }
1975   }
1976
1977   if (depth) {
1978      assert(fb->Visual.depthBits > 0);
1979      _mesa_add_depth_renderbuffer(NULL, fb, fb->Visual.depthBits);
1980   }
1981
1982   if (stencil) {
1983      assert(fb->Visual.stencilBits > 0);
1984      _mesa_add_stencil_renderbuffer(NULL, fb, fb->Visual.stencilBits);
1985   }
1986
1987   if (accum) {
1988      assert(fb->Visual.rgbMode);
1989      assert(fb->Visual.accumRedBits > 0);
1990      assert(fb->Visual.accumGreenBits > 0);
1991      assert(fb->Visual.accumBlueBits > 0);
1992      _mesa_add_accum_renderbuffer(NULL, fb,
1993                                   fb->Visual.accumRedBits,
1994                                   fb->Visual.accumGreenBits,
1995                                   fb->Visual.accumBlueBits,
1996                                   fb->Visual.accumAlphaBits);
1997   }
1998
1999   if (aux) {
2000      assert(fb->Visual.rgbMode);
2001      assert(fb->Visual.numAuxBuffers > 0);
2002      _mesa_add_aux_renderbuffers(NULL, fb, fb->Visual.redBits,
2003                                  fb->Visual.numAuxBuffers);
2004   }
2005
2006   if (alpha) {
2007      assert(fb->Visual.rgbMode);
2008      assert(fb->Visual.alphaBits > 0);
2009      _mesa_add_alpha_renderbuffers(NULL, fb, fb->Visual.alphaBits,
2010                                    frontLeft, backLeft,
2011                                    frontRight, backRight);
2012   }
2013
2014#if 0
2015   if (multisample) {
2016      /* maybe someday */
2017   }
2018#endif
2019}
2020
2021
2022/**
2023 * Attach a renderbuffer to a framebuffer.
2024 */
2025void
2026_mesa_add_renderbuffer(struct gl_framebuffer *fb,
2027                       GLuint bufferName, struct gl_renderbuffer *rb)
2028{
2029   assert(fb);
2030   assert(rb);
2031   assert(bufferName < BUFFER_COUNT);
2032
2033   /* There should be no previous renderbuffer on this attachment point,
2034    * with the exception of depth/stencil since the same renderbuffer may
2035    * be used for both.
2036    */
2037   assert(bufferName == BUFFER_DEPTH ||
2038          bufferName == BUFFER_STENCIL ||
2039          fb->Attachment[bufferName].Renderbuffer == NULL);
2040
2041   /* winsys vs. user-created buffer cross check */
2042   if (fb->Name) {
2043      assert(rb->Name);
2044   }
2045   else {
2046      assert(!rb->Name);
2047   }
2048
2049   fb->Attachment[bufferName].Type = GL_RENDERBUFFER_EXT;
2050   fb->Attachment[bufferName].Complete = GL_TRUE;
2051   fb->Attachment[bufferName].Renderbuffer = rb;
2052}
2053
2054
2055/**
2056 * Create a new combined depth/stencil renderbuffer for implementing
2057 * the GL_EXT_packed_depth_stencil extension.
2058 * \return new depth/stencil renderbuffer
2059 */
2060struct gl_renderbuffer *
2061_mesa_new_depthstencil_renderbuffer(GLcontext *ctx, GLuint name)
2062{
2063   struct gl_renderbuffer *dsrb;
2064
2065   dsrb = _mesa_new_renderbuffer(ctx, name);
2066   if (!dsrb)
2067      return NULL;
2068
2069   /* init fields not covered by _mesa_new_renderbuffer() */
2070   dsrb->InternalFormat = GL_DEPTH24_STENCIL8_EXT;
2071   dsrb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
2072   dsrb->AllocStorage = _mesa_soft_renderbuffer_storage;
2073
2074   return dsrb;
2075}
2076
2077