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