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