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