renderbuffer.c revision f5713c7d2e7ba8e1170fd9b1dd95379662ab6117
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 0
1071      if (!rb->surface)
1072         rb->surface = (struct pipe_surface *)
1073            pipe->surface_alloc(pipe, PIPE_FORMAT_U_S8);
1074#endif
1075      break;
1076   case GL_STENCIL_INDEX16_EXT:
1077      rb->_ActualFormat = GL_STENCIL_INDEX16_EXT;
1078      rb->_BaseFormat = GL_STENCIL_INDEX;
1079      rb->DataType = GL_UNSIGNED_SHORT;
1080      rb->GetPointer = get_pointer_ushort;
1081      rb->GetRow = get_row_ushort;
1082      rb->GetValues = get_values_ushort;
1083      rb->PutRow = put_row_ushort;
1084      rb->PutRowRGB = NULL;
1085      rb->PutMonoRow = put_mono_row_ushort;
1086      rb->PutValues = put_values_ushort;
1087      rb->PutMonoValues = put_mono_values_ushort;
1088      rb->StencilBits = 8 * sizeof(GLushort);
1089      pixelSize = sizeof(GLushort);
1090      break;
1091   case GL_DEPTH_COMPONENT:
1092   case GL_DEPTH_COMPONENT16:
1093      rb->_ActualFormat = GL_DEPTH_COMPONENT16;
1094      rb->_BaseFormat = GL_DEPTH_COMPONENT;
1095      rb->DataType = GL_UNSIGNED_SHORT;
1096      rb->GetPointer = get_pointer_ushort;
1097      rb->GetRow = get_row_ushort;
1098      rb->GetValues = get_values_ushort;
1099      rb->PutRow = put_row_ushort;
1100      rb->PutRowRGB = NULL;
1101      rb->PutMonoRow = put_mono_row_ushort;
1102      rb->PutValues = put_values_ushort;
1103      rb->PutMonoValues = put_mono_values_ushort;
1104      rb->DepthBits = 8 * sizeof(GLushort);
1105#if 0
1106      if (!rb->surface)
1107         rb->surface = (struct pipe_surface *)
1108            pipe->surface_alloc(pipe, PIPE_FORMAT_U_Z16);
1109#endif
1110      pixelSize = sizeof(GLushort);
1111      break;
1112   case GL_DEPTH_COMPONENT24:
1113   case GL_DEPTH_COMPONENT32:
1114      rb->_BaseFormat = GL_DEPTH_COMPONENT;
1115      rb->DataType = GL_UNSIGNED_INT;
1116      rb->GetPointer = get_pointer_uint;
1117      rb->GetRow = get_row_uint;
1118      rb->GetValues = get_values_uint;
1119      rb->PutRow = put_row_uint;
1120      rb->PutRowRGB = NULL;
1121      rb->PutMonoRow = put_mono_row_uint;
1122      rb->PutValues = put_values_uint;
1123      rb->PutMonoValues = put_mono_values_uint;
1124      if (internalFormat == GL_DEPTH_COMPONENT24) {
1125         rb->_ActualFormat = GL_DEPTH_COMPONENT24;
1126         rb->DepthBits = 24;
1127      }
1128      else {
1129         rb->_ActualFormat = GL_DEPTH_COMPONENT32;
1130         rb->DepthBits = 32;
1131      }
1132#if 0
1133      if (!rb->surface)
1134         rb->surface = (struct pipe_surface *)
1135            pipe->surface_alloc(pipe, PIPE_FORMAT_U_Z32);
1136#endif
1137      pixelSize = sizeof(GLuint);
1138      break;
1139   case GL_DEPTH_STENCIL_EXT:
1140   case GL_DEPTH24_STENCIL8_EXT:
1141      rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
1142      rb->_BaseFormat = GL_DEPTH_STENCIL_EXT;
1143      rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
1144      rb->GetPointer = get_pointer_uint;
1145      rb->GetRow = get_row_uint;
1146      rb->GetValues = get_values_uint;
1147      rb->PutRow = put_row_uint;
1148      rb->PutRowRGB = NULL;
1149      rb->PutMonoRow = put_mono_row_uint;
1150      rb->PutValues = put_values_uint;
1151      rb->PutMonoValues = put_mono_values_uint;
1152      rb->DepthBits = 24;
1153      rb->StencilBits = 8;
1154#if 0
1155      if (!rb->surface)
1156         rb->surface = (struct pipe_surface *)
1157            pipe->surface_alloc(pipe, PIPE_FORMAT_S8_Z24);
1158#endif
1159      pixelSize = sizeof(GLuint);
1160      break;
1161   case GL_COLOR_INDEX8_EXT:
1162      rb->_ActualFormat = GL_COLOR_INDEX8_EXT;
1163      rb->_BaseFormat = GL_COLOR_INDEX;
1164      rb->DataType = GL_UNSIGNED_BYTE;
1165      rb->GetPointer = get_pointer_ubyte;
1166      rb->GetRow = get_row_ubyte;
1167      rb->GetValues = get_values_ubyte;
1168      rb->PutRow = put_row_ubyte;
1169      rb->PutRowRGB = NULL;
1170      rb->PutMonoRow = put_mono_row_ubyte;
1171      rb->PutValues = put_values_ubyte;
1172      rb->PutMonoValues = put_mono_values_ubyte;
1173      rb->IndexBits = 8 * sizeof(GLubyte);
1174      pixelSize = sizeof(GLubyte);
1175      break;
1176   case GL_COLOR_INDEX16_EXT:
1177      rb->_ActualFormat = GL_COLOR_INDEX16_EXT;
1178      rb->_BaseFormat = GL_COLOR_INDEX;
1179      rb->DataType = GL_UNSIGNED_SHORT;
1180      rb->GetPointer = get_pointer_ushort;
1181      rb->GetRow = get_row_ushort;
1182      rb->GetValues = get_values_ushort;
1183      rb->PutRow = put_row_ushort;
1184      rb->PutRowRGB = NULL;
1185      rb->PutMonoRow = put_mono_row_ushort;
1186      rb->PutValues = put_values_ushort;
1187      rb->PutMonoValues = put_mono_values_ushort;
1188      rb->IndexBits = 8 * sizeof(GLushort);
1189      pixelSize = sizeof(GLushort);
1190      break;
1191   case COLOR_INDEX32:
1192      rb->_ActualFormat = COLOR_INDEX32;
1193      rb->_BaseFormat = GL_COLOR_INDEX;
1194      rb->DataType = GL_UNSIGNED_INT;
1195      rb->GetPointer = get_pointer_uint;
1196      rb->GetRow = get_row_uint;
1197      rb->GetValues = get_values_uint;
1198      rb->PutRow = put_row_uint;
1199      rb->PutRowRGB = NULL;
1200      rb->PutMonoRow = put_mono_row_uint;
1201      rb->PutValues = put_values_uint;
1202      rb->PutMonoValues = put_mono_values_uint;
1203      rb->IndexBits = 8 * sizeof(GLuint);
1204      pixelSize = sizeof(GLuint);
1205      break;
1206   default:
1207      _mesa_problem(ctx, "Bad internalFormat in _mesa_soft_renderbuffer_storage");
1208      return GL_FALSE;
1209   }
1210
1211   ASSERT(rb->DataType);
1212   ASSERT(rb->GetPointer);
1213   ASSERT(rb->GetRow);
1214   ASSERT(rb->GetValues);
1215   ASSERT(rb->PutRow);
1216   ASSERT(rb->PutMonoRow);
1217   ASSERT(rb->PutValues);
1218   ASSERT(rb->PutMonoValues);
1219
1220   /* free old buffer storage */
1221   if (0/**rb->surface**/) {
1222      /* pipe_surface/region */
1223   }
1224   else if (rb->Data) {
1225      /* legacy renderbuffer (this will go away) */
1226      _mesa_free(rb->Data);
1227   }
1228   rb->Data = NULL;
1229
1230   if (width > 0 && height > 0) {
1231      /* allocate new buffer storage */
1232      if (0/**rb->surface**/) {
1233         /* pipe_surface/region */
1234#if 0
1235         if (rb->surface->region) {
1236            pipe->region_unmap(pipe, rb->surface->region);
1237            pipe->region_release(pipe, &rb->surface->region);
1238         }
1239         rb->surface->region = pipe->region_alloc(pipe, pixelSize, width, height);
1240         /* XXX probably don't want to really map here */
1241         pipe->region_map(pipe, rb->surface->region);
1242         rb->Data = rb->surface->region->map;
1243#endif
1244      }
1245      else {
1246         /* legacy renderbuffer (this will go away) */
1247         rb->Data = malloc(width * height * pixelSize);
1248      }
1249
1250      if (rb->Data == NULL) {
1251         rb->Width = 0;
1252         rb->Height = 0;
1253         _mesa_error(ctx, GL_OUT_OF_MEMORY,
1254                     "software renderbuffer allocation (%d x %d x %d)",
1255                     width, height, pixelSize);
1256         return GL_FALSE;
1257      }
1258   }
1259
1260   rb->Width = width;
1261   rb->Height = height;
1262
1263   return GL_TRUE;
1264}
1265
1266
1267
1268/**********************************************************************/
1269/**********************************************************************/
1270/**********************************************************************/
1271
1272
1273/**
1274 * Here we utilize the gl_renderbuffer->Wrapper field to put an alpha
1275 * buffer wrapper around an existing RGB renderbuffer (hw or sw).
1276 *
1277 * When PutRow is called (for example), we store the alpha values in
1278 * this buffer, then pass on the PutRow call to the wrapped RGB
1279 * buffer.
1280 */
1281
1282
1283static GLboolean
1284alloc_storage_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb,
1285                     GLenum internalFormat, GLuint width, GLuint height)
1286{
1287   ASSERT(arb != arb->Wrapped);
1288   ASSERT(arb->_ActualFormat == GL_ALPHA8);
1289
1290   /* first, pass the call to the wrapped RGB buffer */
1291   if (!arb->Wrapped->AllocStorage(ctx, arb->Wrapped, internalFormat,
1292                                  width, height)) {
1293      return GL_FALSE;
1294   }
1295
1296   /* next, resize my alpha buffer */
1297   if (arb->Data) {
1298      _mesa_free(arb->Data);
1299   }
1300
1301   arb->Data = _mesa_malloc(width * height * sizeof(GLubyte));
1302   if (arb->Data == NULL) {
1303      arb->Width = 0;
1304      arb->Height = 0;
1305      _mesa_error(ctx, GL_OUT_OF_MEMORY, "software alpha buffer allocation");
1306      return GL_FALSE;
1307   }
1308
1309   arb->Width = width;
1310   arb->Height = height;
1311
1312   return GL_TRUE;
1313}
1314
1315
1316/**
1317 * Delete an alpha_renderbuffer object, as well as the wrapped RGB buffer.
1318 */
1319static void
1320delete_renderbuffer_alpha8(struct gl_renderbuffer *arb)
1321{
1322   if (arb->Data) {
1323      _mesa_free(arb->Data);
1324   }
1325   ASSERT(arb->Wrapped);
1326   ASSERT(arb != arb->Wrapped);
1327   arb->Wrapped->Delete(arb->Wrapped);
1328   arb->Wrapped = NULL;
1329   _mesa_free(arb);
1330}
1331
1332
1333static void *
1334get_pointer_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb,
1335                   GLint x, GLint y)
1336{
1337   return NULL;   /* don't allow direct access! */
1338}
1339
1340
1341static void
1342get_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1343               GLint x, GLint y, void *values)
1344{
1345   /* NOTE: 'values' is RGBA format! */
1346   const GLubyte *src = (const GLubyte *) arb->Data + y * arb->Width + x;
1347   GLubyte *dst = (GLubyte *) values;
1348   GLuint i;
1349   ASSERT(arb != arb->Wrapped);
1350   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1351   /* first, pass the call to the wrapped RGB buffer */
1352   arb->Wrapped->GetRow(ctx, arb->Wrapped, count, x, y, values);
1353   /* second, fill in alpha values from this buffer! */
1354   for (i = 0; i < count; i++) {
1355      dst[i * 4 + 3] = src[i];
1356   }
1357}
1358
1359
1360static void
1361get_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1362                  const GLint x[], const GLint y[], void *values)
1363{
1364   GLubyte *dst = (GLubyte *) values;
1365   GLuint i;
1366   ASSERT(arb != arb->Wrapped);
1367   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1368   /* first, pass the call to the wrapped RGB buffer */
1369   arb->Wrapped->GetValues(ctx, arb->Wrapped, count, x, y, values);
1370   /* second, fill in alpha values from this buffer! */
1371   for (i = 0; i < count; i++) {
1372      const GLubyte *src = (GLubyte *) arb->Data + y[i] * arb->Width + x[i];
1373      dst[i * 4 + 3] = *src;
1374   }
1375}
1376
1377
1378static void
1379put_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1380               GLint x, GLint y, const void *values, const GLubyte *mask)
1381{
1382   const GLubyte *src = (const GLubyte *) values;
1383   GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x;
1384   GLuint i;
1385   ASSERT(arb != arb->Wrapped);
1386   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1387   /* first, pass the call to the wrapped RGB buffer */
1388   arb->Wrapped->PutRow(ctx, arb->Wrapped, count, x, y, values, mask);
1389   /* second, store alpha in our buffer */
1390   for (i = 0; i < count; i++) {
1391      if (!mask || mask[i]) {
1392         dst[i] = src[i * 4 + 3];
1393      }
1394   }
1395}
1396
1397
1398static void
1399put_row_rgb_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1400                   GLint x, GLint y, const void *values, const GLubyte *mask)
1401{
1402   const GLubyte *src = (const GLubyte *) values;
1403   GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x;
1404   GLuint i;
1405   ASSERT(arb != arb->Wrapped);
1406   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1407   /* first, pass the call to the wrapped RGB buffer */
1408   arb->Wrapped->PutRowRGB(ctx, arb->Wrapped, count, x, y, values, mask);
1409   /* second, store alpha in our buffer */
1410   for (i = 0; i < count; i++) {
1411      if (!mask || mask[i]) {
1412         dst[i] = src[i * 4 + 3];
1413      }
1414   }
1415}
1416
1417
1418static void
1419put_mono_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1420                    GLint x, GLint y, const void *value, const GLubyte *mask)
1421{
1422   const GLubyte val = ((const GLubyte *) value)[3];
1423   GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x;
1424   ASSERT(arb != arb->Wrapped);
1425   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1426   /* first, pass the call to the wrapped RGB buffer */
1427   arb->Wrapped->PutMonoRow(ctx, arb->Wrapped, count, x, y, value, mask);
1428   /* second, store alpha in our buffer */
1429   if (mask) {
1430      GLuint i;
1431      for (i = 0; i < count; i++) {
1432         if (mask[i]) {
1433            dst[i] = val;
1434         }
1435      }
1436   }
1437   else {
1438      _mesa_memset(dst, val, count);
1439   }
1440}
1441
1442
1443static void
1444put_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1445                  const GLint x[], const GLint y[],
1446                  const void *values, const GLubyte *mask)
1447{
1448   const GLubyte *src = (const GLubyte *) values;
1449   GLuint i;
1450   ASSERT(arb != arb->Wrapped);
1451   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1452   /* first, pass the call to the wrapped RGB buffer */
1453   arb->Wrapped->PutValues(ctx, arb->Wrapped, count, x, y, values, mask);
1454   /* second, store alpha in our buffer */
1455   for (i = 0; i < count; i++) {
1456      if (!mask || mask[i]) {
1457         GLubyte *dst = (GLubyte *) arb->Data + y[i] * arb->Width + x[i];
1458         *dst = src[i * 4 + 3];
1459      }
1460   }
1461}
1462
1463
1464static void
1465put_mono_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb,
1466                       GLuint count, const GLint x[], const GLint y[],
1467                       const void *value, const GLubyte *mask)
1468{
1469   const GLubyte val = ((const GLubyte *) value)[3];
1470   GLuint i;
1471   ASSERT(arb != arb->Wrapped);
1472   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1473   /* first, pass the call to the wrapped RGB buffer */
1474   arb->Wrapped->PutValues(ctx, arb->Wrapped, count, x, y, value, mask);
1475   /* second, store alpha in our buffer */
1476   for (i = 0; i < count; i++) {
1477      if (!mask || mask[i]) {
1478         GLubyte *dst = (GLubyte *) arb->Data + y[i] * arb->Width + x[i];
1479         *dst = val;
1480      }
1481   }
1482}
1483
1484
1485static void
1486copy_buffer_alpha8(struct gl_renderbuffer* dst, struct gl_renderbuffer* src)
1487{
1488   ASSERT(dst->_ActualFormat == GL_ALPHA8);
1489   ASSERT(src->_ActualFormat == GL_ALPHA8);
1490   ASSERT(dst->Width == src->Width);
1491   ASSERT(dst->Height == src->Height);
1492
1493   _mesa_memcpy(dst->Data, src->Data, dst->Width * dst->Height * sizeof(GLubyte));
1494}
1495
1496
1497/**********************************************************************/
1498/**********************************************************************/
1499/**********************************************************************/
1500
1501
1502/**
1503 * Default GetPointer routine.  Always return NULL to indicate that
1504 * direct buffer access is not supported.
1505 */
1506static void *
1507nop_get_pointer(GLcontext *ctx, struct gl_renderbuffer *rb, GLint x, GLint y)
1508{
1509   return NULL;
1510}
1511
1512
1513/**
1514 * Initialize the fields of a gl_renderbuffer to default values.
1515 */
1516void
1517_mesa_init_renderbuffer(struct gl_renderbuffer *rb, GLuint name)
1518{
1519   _glthread_INIT_MUTEX(rb->Mutex);
1520
1521   rb->Magic = RB_MAGIC;
1522   rb->ClassID = 0;
1523   rb->Name = name;
1524   rb->RefCount = 0;
1525   rb->Delete = _mesa_delete_renderbuffer;
1526
1527   /* The rest of these should be set later by the caller of this function or
1528    * the AllocStorage method:
1529    */
1530   rb->AllocStorage = NULL;
1531
1532   rb->Width = 0;
1533   rb->Height = 0;
1534   rb->InternalFormat = GL_NONE;
1535   rb->_ActualFormat = GL_NONE;
1536   rb->_BaseFormat = GL_NONE;
1537   rb->DataType = GL_NONE;
1538   rb->RedBits = rb->GreenBits = rb->BlueBits = rb->AlphaBits = 0;
1539   rb->IndexBits = 0;
1540   rb->DepthBits = 0;
1541   rb->StencilBits = 0;
1542   rb->Data = NULL;
1543
1544   /* Point back to ourself so that we don't have to check for Wrapped==NULL
1545    * all over the drivers.
1546    */
1547   rb->Wrapped = rb;
1548
1549   rb->GetPointer = nop_get_pointer;
1550   rb->GetRow = NULL;
1551   rb->GetValues = NULL;
1552   rb->PutRow = NULL;
1553   rb->PutRowRGB = NULL;
1554   rb->PutMonoRow = NULL;
1555   rb->PutValues = NULL;
1556   rb->PutMonoValues = NULL;
1557}
1558
1559
1560/**
1561 * Allocate a new gl_renderbuffer object.  This can be used for user-created
1562 * renderbuffers or window-system renderbuffers.
1563 */
1564struct gl_renderbuffer *
1565_mesa_new_renderbuffer(GLcontext *ctx, GLuint name)
1566{
1567   struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer);
1568   if (rb) {
1569      _mesa_init_renderbuffer(rb, name);
1570   }
1571   return rb;
1572}
1573
1574
1575/**
1576 * Delete a gl_framebuffer.
1577 * This is the default function for renderbuffer->Delete().
1578 */
1579void
1580_mesa_delete_renderbuffer(struct gl_renderbuffer *rb)
1581{
1582   if (rb->Data) {
1583      _mesa_free(rb->Data);
1584   }
1585   _mesa_free(rb);
1586}
1587
1588
1589/**
1590 * Allocate a software-based renderbuffer.  This is called via the
1591 * ctx->Driver.NewRenderbuffer() function when the user creates a new
1592 * renderbuffer.
1593 * This would not be used for hardware-based renderbuffers.
1594 */
1595struct gl_renderbuffer *
1596_mesa_new_soft_renderbuffer(GLcontext *ctx, GLuint name)
1597{
1598   struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, name);
1599   if (rb) {
1600      rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1601      /* Normally, one would setup the PutRow, GetRow, etc functions here.
1602       * But we're doing that in the _mesa_soft_renderbuffer_storage() function
1603       * instead.
1604       */
1605   }
1606   return rb;
1607}
1608
1609
1610/**
1611 * Add software-based color renderbuffers to the given framebuffer.
1612 * This is a helper routine for device drivers when creating a
1613 * window system framebuffer (not a user-created render/framebuffer).
1614 * Once this function is called, you can basically forget about this
1615 * renderbuffer; core Mesa will handle all the buffer management and
1616 * rendering!
1617 */
1618GLboolean
1619_mesa_add_color_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
1620                              GLuint rgbBits, GLuint alphaBits,
1621                              GLboolean frontLeft, GLboolean backLeft,
1622                              GLboolean frontRight, GLboolean backRight)
1623{
1624   GLuint b;
1625
1626   if (rgbBits > 16 || alphaBits > 16) {
1627      _mesa_problem(ctx,
1628                    "Unsupported bit depth in _mesa_add_color_renderbuffers");
1629      return GL_FALSE;
1630   }
1631
1632   assert(MAX_COLOR_ATTACHMENTS >= 4);
1633
1634   for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
1635      struct gl_renderbuffer *rb;
1636
1637      if (b == BUFFER_FRONT_LEFT && !frontLeft)
1638         continue;
1639      else if (b == BUFFER_BACK_LEFT && !backLeft)
1640         continue;
1641      else if (b == BUFFER_FRONT_RIGHT && !frontRight)
1642         continue;
1643      else if (b == BUFFER_BACK_RIGHT && !backRight)
1644         continue;
1645
1646      assert(fb->Attachment[b].Renderbuffer == NULL);
1647
1648      rb = _mesa_new_renderbuffer(ctx, 0);
1649      if (!rb) {
1650         _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer");
1651         return GL_FALSE;
1652      }
1653
1654      if (rgbBits <= 8) {
1655         if (alphaBits)
1656            rb->_ActualFormat = GL_RGBA8;
1657         else
1658            rb->_ActualFormat = GL_RGB8;
1659      }
1660      else {
1661         assert(rgbBits <= 16);
1662         if (alphaBits)
1663            rb->_ActualFormat = GL_RGBA16;
1664         else
1665            rb->_ActualFormat = GL_RGBA16; /* don't really have RGB16 yet */
1666      }
1667      rb->InternalFormat = rb->_ActualFormat;
1668
1669      rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1670      _mesa_add_renderbuffer(fb, b, rb);
1671   }
1672
1673   return GL_TRUE;
1674}
1675
1676
1677/**
1678 * Add software-based color index renderbuffers to the given framebuffer.
1679 * This is a helper routine for device drivers when creating a
1680 * window system framebuffer (not a user-created render/framebuffer).
1681 * Once this function is called, you can basically forget about this
1682 * renderbuffer; core Mesa will handle all the buffer management and
1683 * rendering!
1684 */
1685GLboolean
1686_mesa_add_color_index_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
1687                                    GLuint indexBits,
1688                                    GLboolean frontLeft, GLboolean backLeft,
1689                                    GLboolean frontRight, GLboolean backRight)
1690{
1691   GLuint b;
1692
1693   if (indexBits > 8) {
1694      _mesa_problem(ctx,
1695                "Unsupported bit depth in _mesa_add_color_index_renderbuffers");
1696      return GL_FALSE;
1697   }
1698
1699   assert(MAX_COLOR_ATTACHMENTS >= 4);
1700
1701   for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
1702      struct gl_renderbuffer *rb;
1703
1704      if (b == BUFFER_FRONT_LEFT && !frontLeft)
1705         continue;
1706      else if (b == BUFFER_BACK_LEFT && !backLeft)
1707         continue;
1708      else if (b == BUFFER_FRONT_RIGHT && !frontRight)
1709         continue;
1710      else if (b == BUFFER_BACK_RIGHT && !backRight)
1711         continue;
1712
1713      assert(fb->Attachment[b].Renderbuffer == NULL);
1714
1715      rb = _mesa_new_renderbuffer(ctx, 0);
1716      if (!rb) {
1717         _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer");
1718         return GL_FALSE;
1719      }
1720
1721      if (indexBits <= 8) {
1722         /* only support GLuint for now */
1723         /*rb->InternalFormat = GL_COLOR_INDEX8_EXT;*/
1724         rb->_ActualFormat = COLOR_INDEX32;
1725      }
1726      else {
1727         rb->_ActualFormat = COLOR_INDEX32;
1728      }
1729      rb->InternalFormat = rb->_ActualFormat;
1730
1731      rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1732      _mesa_add_renderbuffer(fb, b, rb);
1733   }
1734
1735   return GL_TRUE;
1736}
1737
1738
1739/**
1740 * Add software-based alpha renderbuffers to the given framebuffer.
1741 * This is a helper routine for device drivers when creating a
1742 * window system framebuffer (not a user-created render/framebuffer).
1743 * Once this function is called, you can basically forget about this
1744 * renderbuffer; core Mesa will handle all the buffer management and
1745 * rendering!
1746 */
1747GLboolean
1748_mesa_add_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
1749                              GLuint alphaBits,
1750                              GLboolean frontLeft, GLboolean backLeft,
1751                              GLboolean frontRight, GLboolean backRight)
1752{
1753   GLuint b;
1754
1755   /* for window system framebuffers only! */
1756   assert(fb->Name == 0);
1757
1758   if (alphaBits > 8) {
1759      _mesa_problem(ctx,
1760                    "Unsupported bit depth in _mesa_add_alpha_renderbuffers");
1761      return GL_FALSE;
1762   }
1763
1764   assert(MAX_COLOR_ATTACHMENTS >= 4);
1765
1766   /* Wrap each of the RGB color buffers with an alpha renderbuffer.
1767    */
1768   for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
1769      struct gl_renderbuffer *arb;
1770
1771      if (b == BUFFER_FRONT_LEFT && !frontLeft)
1772         continue;
1773      else if (b == BUFFER_BACK_LEFT && !backLeft)
1774         continue;
1775      else if (b == BUFFER_FRONT_RIGHT && !frontRight)
1776         continue;
1777      else if (b == BUFFER_BACK_RIGHT && !backRight)
1778         continue;
1779
1780      /* the RGB buffer to wrap must already exist!! */
1781      assert(fb->Attachment[b].Renderbuffer);
1782
1783      /* only GLubyte supported for now */
1784      assert(fb->Attachment[b].Renderbuffer->DataType == GL_UNSIGNED_BYTE);
1785
1786      /* allocate alpha renderbuffer */
1787      arb = _mesa_new_renderbuffer(ctx, 0);
1788      if (!arb) {
1789         _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating alpha buffer");
1790         return GL_FALSE;
1791      }
1792
1793      /* wrap the alpha renderbuffer around the RGB renderbuffer */
1794      arb->Wrapped = fb->Attachment[b].Renderbuffer;
1795
1796      /* Set up my alphabuffer fields and plug in my functions.
1797       * The functions will put/get the alpha values from/to RGBA arrays
1798       * and then call the wrapped buffer's functions to handle the RGB
1799       * values.
1800       */
1801      arb->InternalFormat = arb->Wrapped->InternalFormat;
1802      arb->_ActualFormat  = GL_ALPHA8;
1803      arb->_BaseFormat    = arb->Wrapped->_BaseFormat;
1804      arb->DataType       = arb->Wrapped->DataType;
1805      arb->AllocStorage   = alloc_storage_alpha8;
1806      arb->Delete         = delete_renderbuffer_alpha8;
1807      arb->GetPointer     = get_pointer_alpha8;
1808      arb->GetRow         = get_row_alpha8;
1809      arb->GetValues      = get_values_alpha8;
1810      arb->PutRow         = put_row_alpha8;
1811      arb->PutRowRGB      = put_row_rgb_alpha8;
1812      arb->PutMonoRow     = put_mono_row_alpha8;
1813      arb->PutValues      = put_values_alpha8;
1814      arb->PutMonoValues  = put_mono_values_alpha8;
1815
1816      /* clear the pointer to avoid assertion/sanity check failure later */
1817      fb->Attachment[b].Renderbuffer = NULL;
1818
1819      /* plug the alpha renderbuffer into the colorbuffer attachment */
1820      _mesa_add_renderbuffer(fb, b, arb);
1821   }
1822
1823   return GL_TRUE;
1824}
1825
1826
1827/**
1828 * For framebuffers that use a software alpha channel wrapper
1829 * created by _mesa_add_alpha_renderbuffer or _mesa_add_soft_renderbuffers,
1830 * copy the back buffer alpha channel into the front buffer alpha channel.
1831 */
1832void
1833_mesa_copy_soft_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb)
1834{
1835   if (fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer &&
1836       fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer)
1837      copy_buffer_alpha8(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer,
1838                         fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
1839
1840
1841   if (fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer &&
1842       fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer)
1843      copy_buffer_alpha8(fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer,
1844                         fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer);
1845}
1846
1847
1848/**
1849 * Add a software-based depth renderbuffer to the given framebuffer.
1850 * This is a helper routine for device drivers when creating a
1851 * window system framebuffer (not a user-created render/framebuffer).
1852 * Once this function is called, you can basically forget about this
1853 * renderbuffer; core Mesa will handle all the buffer management and
1854 * rendering!
1855 */
1856GLboolean
1857_mesa_add_depth_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
1858                             GLuint depthBits)
1859{
1860   struct gl_renderbuffer *rb;
1861
1862   if (depthBits > 32) {
1863      _mesa_problem(ctx,
1864                    "Unsupported depthBits in _mesa_add_depth_renderbuffer");
1865      return GL_FALSE;
1866   }
1867
1868   assert(fb->Attachment[BUFFER_DEPTH].Renderbuffer == NULL);
1869
1870   rb = _mesa_new_renderbuffer(ctx, 0);
1871   if (!rb) {
1872      _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating depth buffer");
1873      return GL_FALSE;
1874   }
1875
1876   if (depthBits <= 16) {
1877      rb->_ActualFormat = GL_DEPTH_COMPONENT16;
1878   }
1879   else if (depthBits <= 24) {
1880      rb->_ActualFormat = GL_DEPTH_COMPONENT24;
1881   }
1882   else {
1883      rb->_ActualFormat = GL_DEPTH_COMPONENT32;
1884   }
1885   rb->InternalFormat = rb->_ActualFormat;
1886
1887   rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1888   _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
1889
1890   return GL_TRUE;
1891}
1892
1893
1894/**
1895 * Add a software-based stencil renderbuffer to the given framebuffer.
1896 * This is a helper routine for device drivers when creating a
1897 * window system framebuffer (not a user-created render/framebuffer).
1898 * Once this function is called, you can basically forget about this
1899 * renderbuffer; core Mesa will handle all the buffer management and
1900 * rendering!
1901 */
1902GLboolean
1903_mesa_add_stencil_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
1904                               GLuint stencilBits)
1905{
1906   struct gl_renderbuffer *rb;
1907
1908   if (stencilBits > 16) {
1909      _mesa_problem(ctx,
1910                  "Unsupported stencilBits in _mesa_add_stencil_renderbuffer");
1911      return GL_FALSE;
1912   }
1913
1914   assert(fb->Attachment[BUFFER_STENCIL].Renderbuffer == NULL);
1915
1916   rb = _mesa_new_renderbuffer(ctx, 0);
1917   if (!rb) {
1918      _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating stencil buffer");
1919      return GL_FALSE;
1920   }
1921
1922   if (stencilBits <= 8) {
1923      rb->_ActualFormat = GL_STENCIL_INDEX8_EXT;
1924   }
1925   else {
1926      /* not really supported (see s_stencil.c code) */
1927      rb->_ActualFormat = GL_STENCIL_INDEX16_EXT;
1928   }
1929   rb->InternalFormat = rb->_ActualFormat;
1930
1931   rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1932   _mesa_add_renderbuffer(fb, BUFFER_STENCIL, rb);
1933
1934   return GL_TRUE;
1935}
1936
1937
1938/**
1939 * Add a software-based accumulation renderbuffer to the given framebuffer.
1940 * This is a helper routine for device drivers when creating a
1941 * window system framebuffer (not a user-created render/framebuffer).
1942 * Once this function is called, you can basically forget about this
1943 * renderbuffer; core Mesa will handle all the buffer management and
1944 * rendering!
1945 */
1946GLboolean
1947_mesa_add_accum_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
1948                             GLuint redBits, GLuint greenBits,
1949                             GLuint blueBits, GLuint alphaBits)
1950{
1951   struct gl_renderbuffer *rb;
1952
1953   if (redBits > 16 || greenBits > 16 || blueBits > 16 || alphaBits > 16) {
1954      _mesa_problem(ctx,
1955                    "Unsupported accumBits in _mesa_add_accum_renderbuffer");
1956      return GL_FALSE;
1957   }
1958
1959   assert(fb->Attachment[BUFFER_ACCUM].Renderbuffer == NULL);
1960
1961   rb = _mesa_new_renderbuffer(ctx, 0);
1962   if (!rb) {
1963      _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer");
1964      return GL_FALSE;
1965   }
1966
1967   rb->_ActualFormat = GL_RGBA16;
1968   rb->InternalFormat = GL_RGBA16;
1969   rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1970   _mesa_add_renderbuffer(fb, BUFFER_ACCUM, rb);
1971
1972   return GL_TRUE;
1973}
1974
1975
1976
1977/**
1978 * Add a software-based accumulation renderbuffer to the given framebuffer.
1979 * This is a helper routine for device drivers when creating a
1980 * window system framebuffer (not a user-created render/framebuffer).
1981 * Once this function is called, you can basically forget about this
1982 * renderbuffer; core Mesa will handle all the buffer management and
1983 * rendering!
1984 *
1985 * NOTE: color-index aux buffers not supported.
1986 */
1987GLboolean
1988_mesa_add_aux_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
1989                            GLuint colorBits, GLuint numBuffers)
1990{
1991   GLuint i;
1992
1993   if (colorBits > 16) {
1994      _mesa_problem(ctx,
1995                    "Unsupported accumBits in _mesa_add_aux_renderbuffers");
1996      return GL_FALSE;
1997   }
1998
1999   assert(numBuffers < MAX_AUX_BUFFERS);
2000
2001   for (i = 0; i < numBuffers; i++) {
2002      struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, 0);
2003
2004      assert(fb->Attachment[BUFFER_AUX0 + i].Renderbuffer == NULL);
2005
2006      if (!rb) {
2007         _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer");
2008         return GL_FALSE;
2009      }
2010
2011      if (colorBits <= 8) {
2012         rb->_ActualFormat = GL_RGBA8;
2013      }
2014      else {
2015         rb->_ActualFormat = GL_RGBA16;
2016      }
2017      rb->InternalFormat = rb->_ActualFormat;
2018
2019      rb->AllocStorage = _mesa_soft_renderbuffer_storage;
2020      _mesa_add_renderbuffer(fb, BUFFER_AUX0 + i, rb);
2021   }
2022   return GL_TRUE;
2023}
2024
2025
2026/**
2027 * Create/attach software-based renderbuffers to the given framebuffer.
2028 * This is a helper routine for device drivers.  Drivers can just as well
2029 * call the individual _mesa_add_*_renderbuffer() routines directly.
2030 */
2031void
2032_mesa_add_soft_renderbuffers(struct gl_framebuffer *fb,
2033                             GLboolean color,
2034                             GLboolean depth,
2035                             GLboolean stencil,
2036                             GLboolean accum,
2037                             GLboolean alpha,
2038                             GLboolean aux)
2039{
2040   GLboolean frontLeft = GL_TRUE;
2041   GLboolean backLeft = fb->Visual.doubleBufferMode;
2042   GLboolean frontRight = fb->Visual.stereoMode;
2043   GLboolean backRight = fb->Visual.stereoMode && fb->Visual.doubleBufferMode;
2044
2045   if (color) {
2046      if (fb->Visual.rgbMode) {
2047         assert(fb->Visual.redBits == fb->Visual.greenBits);
2048         assert(fb->Visual.redBits == fb->Visual.blueBits);
2049         _mesa_add_color_renderbuffers(NULL, fb,
2050                                       fb->Visual.redBits,
2051                                       fb->Visual.alphaBits,
2052                                       frontLeft, backLeft,
2053                                       frontRight, backRight);
2054      }
2055      else {
2056         _mesa_add_color_index_renderbuffers(NULL, fb,
2057                                             fb->Visual.indexBits,
2058                                             frontLeft, backLeft,
2059                                             frontRight, backRight);
2060      }
2061   }
2062
2063   if (depth) {
2064      assert(fb->Visual.depthBits > 0);
2065      _mesa_add_depth_renderbuffer(NULL, fb, fb->Visual.depthBits);
2066   }
2067
2068   if (stencil) {
2069      assert(fb->Visual.stencilBits > 0);
2070      _mesa_add_stencil_renderbuffer(NULL, fb, fb->Visual.stencilBits);
2071   }
2072
2073   if (accum) {
2074      assert(fb->Visual.rgbMode);
2075      assert(fb->Visual.accumRedBits > 0);
2076      assert(fb->Visual.accumGreenBits > 0);
2077      assert(fb->Visual.accumBlueBits > 0);
2078      _mesa_add_accum_renderbuffer(NULL, fb,
2079                                   fb->Visual.accumRedBits,
2080                                   fb->Visual.accumGreenBits,
2081                                   fb->Visual.accumBlueBits,
2082                                   fb->Visual.accumAlphaBits);
2083   }
2084
2085   if (aux) {
2086      assert(fb->Visual.rgbMode);
2087      assert(fb->Visual.numAuxBuffers > 0);
2088      _mesa_add_aux_renderbuffers(NULL, fb, fb->Visual.redBits,
2089                                  fb->Visual.numAuxBuffers);
2090   }
2091
2092   if (alpha) {
2093      assert(fb->Visual.rgbMode);
2094      assert(fb->Visual.alphaBits > 0);
2095      _mesa_add_alpha_renderbuffers(NULL, fb, fb->Visual.alphaBits,
2096                                    frontLeft, backLeft,
2097                                    frontRight, backRight);
2098   }
2099
2100#if 0
2101   if (multisample) {
2102      /* maybe someday */
2103   }
2104#endif
2105}
2106
2107
2108/**
2109 * Attach a renderbuffer to a framebuffer.
2110 */
2111void
2112_mesa_add_renderbuffer(struct gl_framebuffer *fb,
2113                       GLuint bufferName, struct gl_renderbuffer *rb)
2114{
2115   assert(fb);
2116   assert(rb);
2117   assert(bufferName < BUFFER_COUNT);
2118
2119   /* There should be no previous renderbuffer on this attachment point,
2120    * with the exception of depth/stencil since the same renderbuffer may
2121    * be used for both.
2122    */
2123   assert(bufferName == BUFFER_DEPTH ||
2124          bufferName == BUFFER_STENCIL ||
2125          fb->Attachment[bufferName].Renderbuffer == NULL);
2126
2127   /* winsys vs. user-created buffer cross check */
2128   if (fb->Name) {
2129      assert(rb->Name);
2130   }
2131   else {
2132      assert(!rb->Name);
2133   }
2134
2135   /* If Mesa's compiled with deep color channels (16 or 32 bits / channel)
2136    * and the device driver is expecting 8-bit values (GLubyte), we can
2137    * use a "renderbuffer adaptor/wrapper" to do the necessary conversions.
2138    */
2139   if (rb->_BaseFormat == GL_RGBA) {
2140      if (CHAN_BITS == 16 && rb->DataType == GL_UNSIGNED_BYTE) {
2141         GET_CURRENT_CONTEXT(ctx);
2142         rb = _mesa_new_renderbuffer_16wrap8(ctx, rb);
2143      }
2144      else if (CHAN_BITS == 32 && rb->DataType == GL_UNSIGNED_BYTE) {
2145         GET_CURRENT_CONTEXT(ctx);
2146         rb = _mesa_new_renderbuffer_32wrap8(ctx, rb);
2147      }
2148      else if (CHAN_BITS == 32 && rb->DataType == GL_UNSIGNED_SHORT) {
2149         GET_CURRENT_CONTEXT(ctx);
2150         rb = _mesa_new_renderbuffer_32wrap16(ctx, rb);
2151      }
2152   }
2153
2154   fb->Attachment[bufferName].Type = GL_RENDERBUFFER_EXT;
2155   fb->Attachment[bufferName].Complete = GL_TRUE;
2156   _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer, rb);
2157}
2158
2159
2160/**
2161 * Remove the named renderbuffer from the given framebuffer.
2162 */
2163void
2164_mesa_remove_renderbuffer(struct gl_framebuffer *fb, GLuint bufferName)
2165{
2166   struct gl_renderbuffer *rb;
2167
2168   assert(bufferName < BUFFER_COUNT);
2169
2170   rb = fb->Attachment[bufferName].Renderbuffer;
2171   if (!rb)
2172      return;
2173
2174   _mesa_reference_renderbuffer(&rb, NULL);
2175
2176   fb->Attachment[bufferName].Renderbuffer = NULL;
2177}
2178
2179
2180/**
2181 * Set *ptr to point to rb.  If *ptr points to another renderbuffer,
2182 * dereference that buffer first.  The new renderbuffer's refcount will
2183 * be incremented.  The old renderbuffer's refcount will be decremented.
2184 */
2185void
2186_mesa_reference_renderbuffer(struct gl_renderbuffer **ptr,
2187                             struct gl_renderbuffer *rb)
2188{
2189   assert(ptr);
2190   if (*ptr == rb) {
2191      /* no change */
2192      return;
2193   }
2194
2195   if (*ptr) {
2196      /* Unreference the old renderbuffer */
2197      GLboolean deleteFlag = GL_FALSE;
2198      struct gl_renderbuffer *oldRb = *ptr;
2199
2200      assert(oldRb->Magic == RB_MAGIC);
2201      _glthread_LOCK_MUTEX(oldRb->Mutex);
2202      assert(oldRb->Magic == RB_MAGIC);
2203      ASSERT(oldRb->RefCount > 0);
2204      oldRb->RefCount--;
2205      /*printf("RB DECR %p (%d) to %d\n", (void*) oldRb, oldRb->Name, oldRb->RefCount);*/
2206      deleteFlag = (oldRb->RefCount == 0);
2207      _glthread_UNLOCK_MUTEX(oldRb->Mutex);
2208
2209      if (deleteFlag) {
2210         oldRb->Magic = 0; /* now invalid memory! */
2211         oldRb->Delete(oldRb);
2212      }
2213
2214      *ptr = NULL;
2215   }
2216   assert(!*ptr);
2217
2218   if (rb) {
2219      assert(rb->Magic == RB_MAGIC);
2220      /* reference new renderbuffer */
2221      _glthread_LOCK_MUTEX(rb->Mutex);
2222      rb->RefCount++;
2223      /*printf("RB INCR %p (%d) to %d\n", (void*) rb, rb->Name, rb->RefCount);*/
2224      _glthread_UNLOCK_MUTEX(rb->Mutex);
2225      *ptr = rb;
2226   }
2227}
2228
2229
2230/**
2231 * Create a new combined depth/stencil renderbuffer for implementing
2232 * the GL_EXT_packed_depth_stencil extension.
2233 * \return new depth/stencil renderbuffer
2234 */
2235struct gl_renderbuffer *
2236_mesa_new_depthstencil_renderbuffer(GLcontext *ctx, GLuint name)
2237{
2238   struct gl_renderbuffer *dsrb;
2239
2240   dsrb = _mesa_new_renderbuffer(ctx, name);
2241   if (!dsrb)
2242      return NULL;
2243
2244   /* init fields not covered by _mesa_new_renderbuffer() */
2245   dsrb->InternalFormat = GL_DEPTH24_STENCIL8_EXT;
2246   dsrb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
2247   dsrb->AllocStorage = _mesa_soft_renderbuffer_storage;
2248
2249   return dsrb;
2250}
2251