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