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