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