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