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