renderbuffer.c revision cdc920a0
17117f1b4Smrg/*
27117f1b4Smrg * Mesa 3-D graphics library
37117f1b4Smrg * Version:  6.5
47117f1b4Smrg *
57117f1b4Smrg * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
67117f1b4Smrg *
77117f1b4Smrg * Permission is hereby granted, free of charge, to any person obtaining a
87117f1b4Smrg * copy of this software and associated documentation files (the "Software"),
97117f1b4Smrg * to deal in the Software without restriction, including without limitation
107117f1b4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
117117f1b4Smrg * and/or sell copies of the Software, and to permit persons to whom the
127117f1b4Smrg * Software is furnished to do so, subject to the following conditions:
137117f1b4Smrg *
147117f1b4Smrg * The above copyright notice and this permission notice shall be included
157117f1b4Smrg * in all copies or substantial portions of the Software.
167117f1b4Smrg *
177117f1b4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
187117f1b4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
197117f1b4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
207117f1b4Smrg * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
217117f1b4Smrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
227117f1b4Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
237117f1b4Smrg */
247117f1b4Smrg
257117f1b4Smrg
267117f1b4Smrg/**
277117f1b4Smrg * Functions for allocating/managing renderbuffers.
287117f1b4Smrg * Also, routines for reading/writing software-based renderbuffer data as
297117f1b4Smrg * ubytes, ushorts, uints, etc.
307117f1b4Smrg *
317117f1b4Smrg * The 'alpha8' renderbuffer is interesting.  It's used to add a software-based
327117f1b4Smrg * alpha channel to RGB renderbuffers.  This is done by wrapping the RGB
337117f1b4Smrg * renderbuffer with the alpha renderbuffer.  We can do this because of the
347117f1b4Smrg * OO-nature of renderbuffers.
357117f1b4Smrg *
367117f1b4Smrg * Down the road we'll use this for run-time support of 8, 16 and 32-bit
377117f1b4Smrg * color channels.  For example, Mesa may use 32-bit/float color channels
387117f1b4Smrg * internally (swrast) and use wrapper renderbuffers to convert 32-bit
397117f1b4Smrg * values down to 16 or 8-bit values for whatever kind of framebuffer we have.
407117f1b4Smrg */
417117f1b4Smrg
427117f1b4Smrg
437117f1b4Smrg#include "glheader.h"
447117f1b4Smrg#include "imports.h"
457117f1b4Smrg#include "context.h"
464a49301eSmrg#include "fbobject.h"
474a49301eSmrg#include "formats.h"
487117f1b4Smrg#include "mtypes.h"
497117f1b4Smrg#include "fbobject.h"
507117f1b4Smrg#include "renderbuffer.h"
517117f1b4Smrg
527117f1b4Smrg#include "rbadaptors.h"
537117f1b4Smrg
547117f1b4Smrg
557117f1b4Smrg/* 32-bit color index format.  Not a public format. */
567117f1b4Smrg#define COLOR_INDEX32 0x424243
577117f1b4Smrg
587117f1b4Smrg
597117f1b4Smrg/*
607117f1b4Smrg * Routines for get/put values in common buffer formats follow.
617117f1b4Smrg * Someday add support for arbitrary row stride to make them more
627117f1b4Smrg * flexible.
637117f1b4Smrg */
647117f1b4Smrg
657117f1b4Smrg/**********************************************************************
667117f1b4Smrg * Functions for buffers of 1 X GLubyte values.
677117f1b4Smrg * Typically stencil.
687117f1b4Smrg */
697117f1b4Smrg
707117f1b4Smrgstatic void *
717117f1b4Smrgget_pointer_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb,
727117f1b4Smrg                  GLint x, GLint y)
737117f1b4Smrg{
747117f1b4Smrg   if (!rb->Data)
757117f1b4Smrg      return NULL;
767117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
774a49301eSmrg   /* Can't assert rb->Format since these funcs may be used for serveral
787117f1b4Smrg    * different formats (GL_ALPHA8, GL_STENCIL_INDEX8, etc).
797117f1b4Smrg    */
807117f1b4Smrg   return (GLubyte *) rb->Data + y * rb->Width + x;
817117f1b4Smrg}
827117f1b4Smrg
837117f1b4Smrg
847117f1b4Smrgstatic void
857117f1b4Smrgget_row_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
867117f1b4Smrg              GLint x, GLint y, void *values)
877117f1b4Smrg{
887117f1b4Smrg   const GLubyte *src = (const GLubyte *) rb->Data + y * rb->Width + x;
897117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
90cdc920a0Smrg   memcpy(values, src, count * sizeof(GLubyte));
917117f1b4Smrg}
927117f1b4Smrg
937117f1b4Smrg
947117f1b4Smrgstatic void
957117f1b4Smrgget_values_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
967117f1b4Smrg                 const GLint x[], const GLint y[], void *values)
977117f1b4Smrg{
987117f1b4Smrg   GLubyte *dst = (GLubyte *) values;
997117f1b4Smrg   GLuint i;
1007117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
1017117f1b4Smrg   for (i = 0; i < count; i++) {
1027117f1b4Smrg      const GLubyte *src = (GLubyte *) rb->Data + y[i] * rb->Width + x[i];
1037117f1b4Smrg      dst[i] = *src;
1047117f1b4Smrg   }
1057117f1b4Smrg}
1067117f1b4Smrg
1077117f1b4Smrg
1087117f1b4Smrgstatic void
1097117f1b4Smrgput_row_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
1107117f1b4Smrg              GLint x, GLint y, const void *values, const GLubyte *mask)
1117117f1b4Smrg{
1127117f1b4Smrg   const GLubyte *src = (const GLubyte *) values;
1137117f1b4Smrg   GLubyte *dst = (GLubyte *) rb->Data + y * rb->Width + x;
1147117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
1157117f1b4Smrg   if (mask) {
1167117f1b4Smrg      GLuint i;
1177117f1b4Smrg      for (i = 0; i < count; i++) {
1187117f1b4Smrg         if (mask[i]) {
1197117f1b4Smrg            dst[i] = src[i];
1207117f1b4Smrg         }
1217117f1b4Smrg      }
1227117f1b4Smrg   }
1237117f1b4Smrg   else {
124cdc920a0Smrg      memcpy(dst, values, count * sizeof(GLubyte));
1257117f1b4Smrg   }
1267117f1b4Smrg}
1277117f1b4Smrg
1287117f1b4Smrg
1297117f1b4Smrgstatic void
1307117f1b4Smrgput_mono_row_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
1317117f1b4Smrg                   GLint x, GLint y, const void *value, const GLubyte *mask)
1327117f1b4Smrg{
1337117f1b4Smrg   const GLubyte val = *((const GLubyte *) value);
1347117f1b4Smrg   GLubyte *dst = (GLubyte *) rb->Data + y * rb->Width + x;
1357117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
1367117f1b4Smrg   if (mask) {
1377117f1b4Smrg      GLuint i;
1387117f1b4Smrg      for (i = 0; i < count; i++) {
1397117f1b4Smrg         if (mask[i]) {
1407117f1b4Smrg            dst[i] = val;
1417117f1b4Smrg         }
1427117f1b4Smrg      }
1437117f1b4Smrg   }
1447117f1b4Smrg   else {
1457117f1b4Smrg      GLuint i;
1467117f1b4Smrg      for (i = 0; i < count; i++) {
1477117f1b4Smrg         dst[i] = val;
1487117f1b4Smrg      }
1497117f1b4Smrg   }
1507117f1b4Smrg}
1517117f1b4Smrg
1527117f1b4Smrg
1537117f1b4Smrgstatic void
1547117f1b4Smrgput_values_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
1557117f1b4Smrg                 const GLint x[], const GLint y[],
1567117f1b4Smrg                 const void *values, const GLubyte *mask)
1577117f1b4Smrg{
1587117f1b4Smrg   const GLubyte *src = (const GLubyte *) values;
1597117f1b4Smrg   GLuint i;
1607117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
1617117f1b4Smrg   for (i = 0; i < count; i++) {
1627117f1b4Smrg      if (!mask || mask[i]) {
1637117f1b4Smrg         GLubyte *dst = (GLubyte *) rb->Data + y[i] * rb->Width + x[i];
1647117f1b4Smrg         *dst = src[i];
1657117f1b4Smrg      }
1667117f1b4Smrg   }
1677117f1b4Smrg}
1687117f1b4Smrg
1697117f1b4Smrg
1707117f1b4Smrgstatic void
1717117f1b4Smrgput_mono_values_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
1727117f1b4Smrg                      const GLint x[], const GLint y[],
1737117f1b4Smrg                      const void *value, const GLubyte *mask)
1747117f1b4Smrg{
1757117f1b4Smrg   const GLubyte val = *((const GLubyte *) value);
1767117f1b4Smrg   GLuint i;
1777117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
1787117f1b4Smrg   for (i = 0; i < count; i++) {
1797117f1b4Smrg      if (!mask || mask[i]) {
1807117f1b4Smrg         GLubyte *dst = (GLubyte *) rb->Data + y[i] * rb->Width + x[i];
1817117f1b4Smrg         *dst = val;
1827117f1b4Smrg      }
1837117f1b4Smrg   }
1847117f1b4Smrg}
1857117f1b4Smrg
1867117f1b4Smrg
1877117f1b4Smrg/**********************************************************************
1887117f1b4Smrg * Functions for buffers of 1 X GLushort values.
1897117f1b4Smrg * Typically depth/Z.
1907117f1b4Smrg */
1917117f1b4Smrg
1927117f1b4Smrgstatic void *
1937117f1b4Smrgget_pointer_ushort(GLcontext *ctx, struct gl_renderbuffer *rb,
1947117f1b4Smrg                   GLint x, GLint y)
1957117f1b4Smrg{
1967117f1b4Smrg   if (!rb->Data)
1977117f1b4Smrg      return NULL;
1987117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
1997117f1b4Smrg   ASSERT(rb->Width > 0);
2007117f1b4Smrg   return (GLushort *) rb->Data + y * rb->Width + x;
2017117f1b4Smrg}
2027117f1b4Smrg
2037117f1b4Smrg
2047117f1b4Smrgstatic void
2057117f1b4Smrgget_row_ushort(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
2067117f1b4Smrg               GLint x, GLint y, void *values)
2077117f1b4Smrg{
2087117f1b4Smrg   const void *src = rb->GetPointer(ctx, rb, x, y);
2097117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
210cdc920a0Smrg   memcpy(values, src, count * sizeof(GLushort));
2117117f1b4Smrg}
2127117f1b4Smrg
2137117f1b4Smrg
2147117f1b4Smrgstatic void
2157117f1b4Smrgget_values_ushort(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
2167117f1b4Smrg                  const GLint x[], const GLint y[], void *values)
2177117f1b4Smrg{
2187117f1b4Smrg   GLushort *dst = (GLushort *) values;
2197117f1b4Smrg   GLuint i;
2207117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
2217117f1b4Smrg   for (i = 0; i < count; i++) {
2227117f1b4Smrg      const GLushort *src = (GLushort *) rb->Data + y[i] * rb->Width + x[i];
2237117f1b4Smrg      dst[i] = *src;
2247117f1b4Smrg   }
2257117f1b4Smrg}
2267117f1b4Smrg
2277117f1b4Smrg
2287117f1b4Smrgstatic void
2297117f1b4Smrgput_row_ushort(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
2307117f1b4Smrg               GLint x, GLint y, const void *values, const GLubyte *mask)
2317117f1b4Smrg{
2327117f1b4Smrg   const GLushort *src = (const GLushort *) values;
2337117f1b4Smrg   GLushort *dst = (GLushort *) rb->Data + y * rb->Width + x;
2347117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
2357117f1b4Smrg   if (mask) {
2367117f1b4Smrg      GLuint i;
2377117f1b4Smrg      for (i = 0; i < count; i++) {
2387117f1b4Smrg         if (mask[i]) {
2397117f1b4Smrg            dst[i] = src[i];
2407117f1b4Smrg         }
2417117f1b4Smrg      }
2427117f1b4Smrg   }
2437117f1b4Smrg   else {
244cdc920a0Smrg      memcpy(dst, src, count * sizeof(GLushort));
2457117f1b4Smrg   }
2467117f1b4Smrg}
2477117f1b4Smrg
2487117f1b4Smrg
2497117f1b4Smrgstatic void
2507117f1b4Smrgput_mono_row_ushort(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
2517117f1b4Smrg                    GLint x, GLint y, const void *value, const GLubyte *mask)
2527117f1b4Smrg{
2537117f1b4Smrg   const GLushort val = *((const GLushort *) value);
2547117f1b4Smrg   GLushort *dst = (GLushort *) rb->Data + y * rb->Width + x;
2557117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
2567117f1b4Smrg   if (mask) {
2577117f1b4Smrg      GLuint i;
2587117f1b4Smrg      for (i = 0; i < count; i++) {
2597117f1b4Smrg         if (mask[i]) {
2607117f1b4Smrg            dst[i] = val;
2617117f1b4Smrg         }
2627117f1b4Smrg      }
2637117f1b4Smrg   }
2647117f1b4Smrg   else {
2657117f1b4Smrg      GLuint i;
2667117f1b4Smrg      for (i = 0; i < count; i++) {
2677117f1b4Smrg         dst[i] = val;
2687117f1b4Smrg      }
2697117f1b4Smrg   }
2707117f1b4Smrg}
2717117f1b4Smrg
2727117f1b4Smrg
2737117f1b4Smrgstatic void
2747117f1b4Smrgput_values_ushort(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
2757117f1b4Smrg                  const GLint x[], const GLint y[], const void *values,
2767117f1b4Smrg                  const GLubyte *mask)
2777117f1b4Smrg{
2787117f1b4Smrg   const GLushort *src = (const GLushort *) values;
2797117f1b4Smrg   GLuint i;
2807117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
2817117f1b4Smrg   for (i = 0; i < count; i++) {
2827117f1b4Smrg      if (!mask || mask[i]) {
2837117f1b4Smrg         GLushort *dst = (GLushort *) rb->Data + y[i] * rb->Width + x[i];
2847117f1b4Smrg         *dst = src[i];
2857117f1b4Smrg      }
2867117f1b4Smrg   }
2877117f1b4Smrg}
2887117f1b4Smrg
2897117f1b4Smrg
2907117f1b4Smrgstatic void
2917117f1b4Smrgput_mono_values_ushort(GLcontext *ctx, struct gl_renderbuffer *rb,
2927117f1b4Smrg                       GLuint count, const GLint x[], const GLint y[],
2937117f1b4Smrg                       const void *value, const GLubyte *mask)
2947117f1b4Smrg{
2957117f1b4Smrg   const GLushort val = *((const GLushort *) value);
2967117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
2977117f1b4Smrg   if (mask) {
2987117f1b4Smrg      GLuint i;
2997117f1b4Smrg      for (i = 0; i < count; i++) {
3007117f1b4Smrg         if (mask[i]) {
3017117f1b4Smrg            GLushort *dst = (GLushort *) rb->Data + y[i] * rb->Width + x[i];
3027117f1b4Smrg            *dst = val;
3037117f1b4Smrg         }
3047117f1b4Smrg      }
3057117f1b4Smrg   }
3067117f1b4Smrg   else {
3077117f1b4Smrg      GLuint i;
3087117f1b4Smrg      for (i = 0; i < count; i++) {
3097117f1b4Smrg         GLushort *dst = (GLushort *) rb->Data + y[i] * rb->Width + x[i];
3107117f1b4Smrg         *dst = val;
3117117f1b4Smrg      }
3127117f1b4Smrg   }
3137117f1b4Smrg}
3147117f1b4Smrg
3157117f1b4Smrg
3167117f1b4Smrg/**********************************************************************
3177117f1b4Smrg * Functions for buffers of 1 X GLuint values.
3187117f1b4Smrg * Typically depth/Z or color index.
3197117f1b4Smrg */
3207117f1b4Smrg
3217117f1b4Smrgstatic void *
3227117f1b4Smrgget_pointer_uint(GLcontext *ctx, struct gl_renderbuffer *rb,
3237117f1b4Smrg                 GLint x, GLint y)
3247117f1b4Smrg{
3257117f1b4Smrg   if (!rb->Data)
3267117f1b4Smrg      return NULL;
3277117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_INT ||
3287117f1b4Smrg          rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
3297117f1b4Smrg   return (GLuint *) rb->Data + y * rb->Width + x;
3307117f1b4Smrg}
3317117f1b4Smrg
3327117f1b4Smrg
3337117f1b4Smrgstatic void
3347117f1b4Smrgget_row_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
3357117f1b4Smrg             GLint x, GLint y, void *values)
3367117f1b4Smrg{
3377117f1b4Smrg   const void *src = rb->GetPointer(ctx, rb, x, y);
3387117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_INT ||
3397117f1b4Smrg          rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
340cdc920a0Smrg   memcpy(values, src, count * sizeof(GLuint));
3417117f1b4Smrg}
3427117f1b4Smrg
3437117f1b4Smrg
3447117f1b4Smrgstatic void
3457117f1b4Smrgget_values_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
3467117f1b4Smrg                const GLint x[], const GLint y[], void *values)
3477117f1b4Smrg{
3487117f1b4Smrg   GLuint *dst = (GLuint *) values;
3497117f1b4Smrg   GLuint i;
3507117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_INT ||
3517117f1b4Smrg          rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
3527117f1b4Smrg   for (i = 0; i < count; i++) {
3537117f1b4Smrg      const GLuint *src = (GLuint *) rb->Data + y[i] * rb->Width + x[i];
3547117f1b4Smrg      dst[i] = *src;
3557117f1b4Smrg   }
3567117f1b4Smrg}
3577117f1b4Smrg
3587117f1b4Smrg
3597117f1b4Smrgstatic void
3607117f1b4Smrgput_row_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
3617117f1b4Smrg             GLint x, GLint y, const void *values, const GLubyte *mask)
3627117f1b4Smrg{
3637117f1b4Smrg   const GLuint *src = (const GLuint *) values;
3647117f1b4Smrg   GLuint *dst = (GLuint *) rb->Data + y * rb->Width + x;
3657117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_INT ||
3667117f1b4Smrg          rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
3677117f1b4Smrg   if (mask) {
3687117f1b4Smrg      GLuint i;
3697117f1b4Smrg      for (i = 0; i < count; i++) {
3707117f1b4Smrg         if (mask[i]) {
3717117f1b4Smrg            dst[i] = src[i];
3727117f1b4Smrg         }
3737117f1b4Smrg      }
3747117f1b4Smrg   }
3757117f1b4Smrg   else {
376cdc920a0Smrg      memcpy(dst, src, count * sizeof(GLuint));
3777117f1b4Smrg   }
3787117f1b4Smrg}
3797117f1b4Smrg
3807117f1b4Smrg
3817117f1b4Smrgstatic void
3827117f1b4Smrgput_mono_row_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
3837117f1b4Smrg                  GLint x, GLint y, const void *value, const GLubyte *mask)
3847117f1b4Smrg{
3857117f1b4Smrg   const GLuint val = *((const GLuint *) value);
3867117f1b4Smrg   GLuint *dst = (GLuint *) rb->Data + y * rb->Width + x;
3877117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_INT ||
3887117f1b4Smrg          rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
3897117f1b4Smrg   if (mask) {
3907117f1b4Smrg      GLuint i;
3917117f1b4Smrg      for (i = 0; i < count; i++) {
3927117f1b4Smrg         if (mask[i]) {
3937117f1b4Smrg            dst[i] = val;
3947117f1b4Smrg         }
3957117f1b4Smrg      }
3967117f1b4Smrg   }
3977117f1b4Smrg   else {
3987117f1b4Smrg      GLuint i;
3997117f1b4Smrg      for (i = 0; i < count; i++) {
4007117f1b4Smrg         dst[i] = val;
4017117f1b4Smrg      }
4027117f1b4Smrg   }
4037117f1b4Smrg}
4047117f1b4Smrg
4057117f1b4Smrg
4067117f1b4Smrgstatic void
4077117f1b4Smrgput_values_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
4087117f1b4Smrg                const GLint x[], const GLint y[], const void *values,
4097117f1b4Smrg                const GLubyte *mask)
4107117f1b4Smrg{
4117117f1b4Smrg   const GLuint *src = (const GLuint *) values;
4127117f1b4Smrg   GLuint i;
4137117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_INT ||
4147117f1b4Smrg          rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
4157117f1b4Smrg   for (i = 0; i < count; i++) {
4167117f1b4Smrg      if (!mask || mask[i]) {
4177117f1b4Smrg         GLuint *dst = (GLuint *) rb->Data + y[i] * rb->Width + x[i];
4187117f1b4Smrg         *dst = src[i];
4197117f1b4Smrg      }
4207117f1b4Smrg   }
4217117f1b4Smrg}
4227117f1b4Smrg
4237117f1b4Smrg
4247117f1b4Smrgstatic void
4257117f1b4Smrgput_mono_values_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
4267117f1b4Smrg                     const GLint x[], const GLint y[], const void *value,
4277117f1b4Smrg                     const GLubyte *mask)
4287117f1b4Smrg{
4297117f1b4Smrg   const GLuint val = *((const GLuint *) value);
4307117f1b4Smrg   GLuint i;
4317117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_INT ||
4327117f1b4Smrg          rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
4337117f1b4Smrg   for (i = 0; i < count; i++) {
4347117f1b4Smrg      if (!mask || mask[i]) {
4357117f1b4Smrg         GLuint *dst = (GLuint *) rb->Data + y[i] * rb->Width + x[i];
4367117f1b4Smrg         *dst = val;
4377117f1b4Smrg      }
4387117f1b4Smrg   }
4397117f1b4Smrg}
4407117f1b4Smrg
4417117f1b4Smrg
4427117f1b4Smrg/**********************************************************************
4437117f1b4Smrg * Functions for buffers of 3 X GLubyte (or GLbyte) values.
4447117f1b4Smrg * Typically color buffers.
4457117f1b4Smrg * NOTE: the incoming and outgoing colors are RGBA!  We ignore incoming
4467117f1b4Smrg * alpha values and return 255 for outgoing alpha values.
4477117f1b4Smrg */
4487117f1b4Smrg
4497117f1b4Smrgstatic void *
4507117f1b4Smrgget_pointer_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb,
4517117f1b4Smrg                   GLint x, GLint y)
4527117f1b4Smrg{
4534a49301eSmrg   ASSERT(rb->Format == MESA_FORMAT_RGB888);
4547117f1b4Smrg   /* No direct access since this buffer is RGB but caller will be
4557117f1b4Smrg    * treating it as if it were RGBA.
4567117f1b4Smrg    */
4577117f1b4Smrg   return NULL;
4587117f1b4Smrg}
4597117f1b4Smrg
4607117f1b4Smrg
4617117f1b4Smrgstatic void
4627117f1b4Smrgget_row_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
4637117f1b4Smrg               GLint x, GLint y, void *values)
4647117f1b4Smrg{
4657117f1b4Smrg   const GLubyte *src = (const GLubyte *) rb->Data + 3 * (y * rb->Width + x);
4667117f1b4Smrg   GLubyte *dst = (GLubyte *) values;
4677117f1b4Smrg   GLuint i;
4684a49301eSmrg   ASSERT(rb->Format == MESA_FORMAT_RGB888);
4697117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
4707117f1b4Smrg   for (i = 0; i < count; i++) {
4717117f1b4Smrg      dst[i * 4 + 0] = src[i * 3 + 0];
4727117f1b4Smrg      dst[i * 4 + 1] = src[i * 3 + 1];
4737117f1b4Smrg      dst[i * 4 + 2] = src[i * 3 + 2];
4747117f1b4Smrg      dst[i * 4 + 3] = 255;
4757117f1b4Smrg   }
4767117f1b4Smrg}
4777117f1b4Smrg
4787117f1b4Smrg
4797117f1b4Smrgstatic void
4807117f1b4Smrgget_values_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
4817117f1b4Smrg                  const GLint x[], const GLint y[], void *values)
4827117f1b4Smrg{
4837117f1b4Smrg   GLubyte *dst = (GLubyte *) values;
4847117f1b4Smrg   GLuint i;
4854a49301eSmrg   ASSERT(rb->Format == MESA_FORMAT_RGB888);
4867117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
4877117f1b4Smrg   for (i = 0; i < count; i++) {
4887117f1b4Smrg      const GLubyte *src
4897117f1b4Smrg         = (GLubyte *) rb->Data + 3 * (y[i] * rb->Width + x[i]);
4907117f1b4Smrg      dst[i * 4 + 0] = src[0];
4917117f1b4Smrg      dst[i * 4 + 1] = src[1];
4927117f1b4Smrg      dst[i * 4 + 2] = src[2];
4937117f1b4Smrg      dst[i * 4 + 3] = 255;
4947117f1b4Smrg   }
4957117f1b4Smrg}
4967117f1b4Smrg
4977117f1b4Smrg
4987117f1b4Smrgstatic void
4997117f1b4Smrgput_row_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
5007117f1b4Smrg               GLint x, GLint y, const void *values, const GLubyte *mask)
5017117f1b4Smrg{
5027117f1b4Smrg   /* note: incoming values are RGB+A! */
5037117f1b4Smrg   const GLubyte *src = (const GLubyte *) values;
5047117f1b4Smrg   GLubyte *dst = (GLubyte *) rb->Data + 3 * (y * rb->Width + x);
5057117f1b4Smrg   GLuint i;
5064a49301eSmrg   ASSERT(rb->Format == MESA_FORMAT_RGB888);
5077117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
5087117f1b4Smrg   for (i = 0; i < count; i++) {
5097117f1b4Smrg      if (!mask || mask[i]) {
5107117f1b4Smrg         dst[i * 3 + 0] = src[i * 4 + 0];
5117117f1b4Smrg         dst[i * 3 + 1] = src[i * 4 + 1];
5127117f1b4Smrg         dst[i * 3 + 2] = src[i * 4 + 2];
5137117f1b4Smrg      }
5147117f1b4Smrg   }
5157117f1b4Smrg}
5167117f1b4Smrg
5177117f1b4Smrg
5187117f1b4Smrgstatic void
5197117f1b4Smrgput_row_rgb_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
5207117f1b4Smrg                   GLint x, GLint y, const void *values, const GLubyte *mask)
5217117f1b4Smrg{
5227117f1b4Smrg   /* note: incoming values are RGB+A! */
5237117f1b4Smrg   const GLubyte *src = (const GLubyte *) values;
5247117f1b4Smrg   GLubyte *dst = (GLubyte *) rb->Data + 3 * (y * rb->Width + x);
5257117f1b4Smrg   GLuint i;
5264a49301eSmrg   ASSERT(rb->Format == MESA_FORMAT_RGB888);
5277117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
5287117f1b4Smrg   for (i = 0; i < count; i++) {
5297117f1b4Smrg      if (!mask || mask[i]) {
5307117f1b4Smrg         dst[i * 3 + 0] = src[i * 3 + 0];
5317117f1b4Smrg         dst[i * 3 + 1] = src[i * 3 + 1];
5327117f1b4Smrg         dst[i * 3 + 2] = src[i * 3 + 2];
5337117f1b4Smrg      }
5347117f1b4Smrg   }
5357117f1b4Smrg}
5367117f1b4Smrg
5377117f1b4Smrg
5387117f1b4Smrgstatic void
5397117f1b4Smrgput_mono_row_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
5407117f1b4Smrg                    GLint x, GLint y, const void *value, const GLubyte *mask)
5417117f1b4Smrg{
5427117f1b4Smrg   /* note: incoming value is RGB+A! */
5437117f1b4Smrg   const GLubyte val0 = ((const GLubyte *) value)[0];
5447117f1b4Smrg   const GLubyte val1 = ((const GLubyte *) value)[1];
5457117f1b4Smrg   const GLubyte val2 = ((const GLubyte *) value)[2];
5467117f1b4Smrg   GLubyte *dst = (GLubyte *) rb->Data + 3 * (y * rb->Width + x);
5474a49301eSmrg   ASSERT(rb->Format == MESA_FORMAT_RGB888);
5487117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
5497117f1b4Smrg   if (!mask && val0 == val1 && val1 == val2) {
5507117f1b4Smrg      /* optimized case */
551cdc920a0Smrg      memset(dst, val0, 3 * count);
5527117f1b4Smrg   }
5537117f1b4Smrg   else {
5547117f1b4Smrg      GLuint i;
5557117f1b4Smrg      for (i = 0; i < count; i++) {
5567117f1b4Smrg         if (!mask || mask[i]) {
5577117f1b4Smrg            dst[i * 3 + 0] = val0;
5587117f1b4Smrg            dst[i * 3 + 1] = val1;
5597117f1b4Smrg            dst[i * 3 + 2] = val2;
5607117f1b4Smrg         }
5617117f1b4Smrg      }
5627117f1b4Smrg   }
5637117f1b4Smrg}
5647117f1b4Smrg
5657117f1b4Smrg
5667117f1b4Smrgstatic void
5677117f1b4Smrgput_values_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
5687117f1b4Smrg                  const GLint x[], const GLint y[], const void *values,
5697117f1b4Smrg                  const GLubyte *mask)
5707117f1b4Smrg{
5717117f1b4Smrg   /* note: incoming values are RGB+A! */
5727117f1b4Smrg   const GLubyte *src = (const GLubyte *) values;
5737117f1b4Smrg   GLuint i;
5744a49301eSmrg   ASSERT(rb->Format == MESA_FORMAT_RGB888);
5757117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
5767117f1b4Smrg   for (i = 0; i < count; i++) {
5777117f1b4Smrg      if (!mask || mask[i]) {
5787117f1b4Smrg         GLubyte *dst = (GLubyte *) rb->Data + 3 * (y[i] * rb->Width + x[i]);
5797117f1b4Smrg         dst[0] = src[i * 4 + 0];
5807117f1b4Smrg         dst[1] = src[i * 4 + 1];
5817117f1b4Smrg         dst[2] = src[i * 4 + 2];
5827117f1b4Smrg      }
5837117f1b4Smrg   }
5847117f1b4Smrg}
5857117f1b4Smrg
5867117f1b4Smrg
5877117f1b4Smrgstatic void
5887117f1b4Smrgput_mono_values_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb,
5897117f1b4Smrg                       GLuint count, const GLint x[], const GLint y[],
5907117f1b4Smrg                       const void *value, const GLubyte *mask)
5917117f1b4Smrg{
5927117f1b4Smrg   /* note: incoming value is RGB+A! */
5937117f1b4Smrg   const GLubyte val0 = ((const GLubyte *) value)[0];
5947117f1b4Smrg   const GLubyte val1 = ((const GLubyte *) value)[1];
5957117f1b4Smrg   const GLubyte val2 = ((const GLubyte *) value)[2];
5967117f1b4Smrg   GLuint i;
5974a49301eSmrg   ASSERT(rb->Format == MESA_FORMAT_RGB888);
5987117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
5997117f1b4Smrg   for (i = 0; i < count; i++) {
6007117f1b4Smrg      if (!mask || mask[i]) {
6017117f1b4Smrg         GLubyte *dst = (GLubyte *) rb->Data + 3 * (y[i] * rb->Width + x[i]);
6027117f1b4Smrg         dst[0] = val0;
6037117f1b4Smrg         dst[1] = val1;
6047117f1b4Smrg         dst[2] = val2;
6057117f1b4Smrg      }
6067117f1b4Smrg   }
6077117f1b4Smrg}
6087117f1b4Smrg
6097117f1b4Smrg
6107117f1b4Smrg/**********************************************************************
6117117f1b4Smrg * Functions for buffers of 4 X GLubyte (or GLbyte) values.
6127117f1b4Smrg * Typically color buffers.
6137117f1b4Smrg */
6147117f1b4Smrg
6157117f1b4Smrgstatic void *
6167117f1b4Smrgget_pointer_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb,
6177117f1b4Smrg                   GLint x, GLint y)
6187117f1b4Smrg{
6197117f1b4Smrg   if (!rb->Data)
6207117f1b4Smrg      return NULL;
6217117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
6224a49301eSmrg   ASSERT(rb->Format == MESA_FORMAT_RGBA8888);
6237117f1b4Smrg   return (GLubyte *) rb->Data + 4 * (y * rb->Width + x);
6247117f1b4Smrg}
6257117f1b4Smrg
6267117f1b4Smrg
6277117f1b4Smrgstatic void
6287117f1b4Smrgget_row_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
6297117f1b4Smrg               GLint x, GLint y, void *values)
6307117f1b4Smrg{
6317117f1b4Smrg   const GLubyte *src = (const GLubyte *) rb->Data + 4 * (y * rb->Width + x);
6327117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
6334a49301eSmrg   ASSERT(rb->Format == MESA_FORMAT_RGBA8888);
634cdc920a0Smrg   memcpy(values, src, 4 * count * sizeof(GLubyte));
6357117f1b4Smrg}
6367117f1b4Smrg
6377117f1b4Smrg
6387117f1b4Smrgstatic void
6397117f1b4Smrgget_values_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
6407117f1b4Smrg                  const GLint x[], const GLint y[], void *values)
6417117f1b4Smrg{
6427117f1b4Smrg   /* treat 4*GLubyte as 1*GLuint */
6437117f1b4Smrg   GLuint *dst = (GLuint *) values;
6447117f1b4Smrg   GLuint i;
6457117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
6464a49301eSmrg   ASSERT(rb->Format == MESA_FORMAT_RGBA8888);
6477117f1b4Smrg   for (i = 0; i < count; i++) {
6487117f1b4Smrg      const GLuint *src = (GLuint *) rb->Data + (y[i] * rb->Width + x[i]);
6497117f1b4Smrg      dst[i] = *src;
6507117f1b4Smrg   }
6517117f1b4Smrg}
6527117f1b4Smrg
6537117f1b4Smrg
6547117f1b4Smrgstatic void
6557117f1b4Smrgput_row_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
6567117f1b4Smrg               GLint x, GLint y, const void *values, const GLubyte *mask)
6577117f1b4Smrg{
6587117f1b4Smrg   /* treat 4*GLubyte as 1*GLuint */
6597117f1b4Smrg   const GLuint *src = (const GLuint *) values;
6607117f1b4Smrg   GLuint *dst = (GLuint *) rb->Data + (y * rb->Width + x);
6617117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
6624a49301eSmrg   ASSERT(rb->Format == MESA_FORMAT_RGBA8888);
6637117f1b4Smrg   if (mask) {
6647117f1b4Smrg      GLuint i;
6657117f1b4Smrg      for (i = 0; i < count; i++) {
6667117f1b4Smrg         if (mask[i]) {
6677117f1b4Smrg            dst[i] = src[i];
6687117f1b4Smrg         }
6697117f1b4Smrg      }
6707117f1b4Smrg   }
6717117f1b4Smrg   else {
672cdc920a0Smrg      memcpy(dst, src, 4 * count * sizeof(GLubyte));
6737117f1b4Smrg   }
6747117f1b4Smrg}
6757117f1b4Smrg
6767117f1b4Smrg
6777117f1b4Smrgstatic void
6787117f1b4Smrgput_row_rgb_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
6797117f1b4Smrg                   GLint x, GLint y, const void *values, const GLubyte *mask)
6807117f1b4Smrg{
6817117f1b4Smrg   /* Store RGB values in RGBA buffer */
6827117f1b4Smrg   const GLubyte *src = (const GLubyte *) values;
6837117f1b4Smrg   GLubyte *dst = (GLubyte *) rb->Data + 4 * (y * rb->Width + x);
6847117f1b4Smrg   GLuint i;
6857117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
6864a49301eSmrg   ASSERT(rb->Format == MESA_FORMAT_RGBA8888);
6877117f1b4Smrg   for (i = 0; i < count; i++) {
6887117f1b4Smrg      if (!mask || mask[i]) {
6897117f1b4Smrg         dst[i * 4 + 0] = src[i * 3 + 0];
6907117f1b4Smrg         dst[i * 4 + 1] = src[i * 3 + 1];
6917117f1b4Smrg         dst[i * 4 + 2] = src[i * 3 + 2];
6927117f1b4Smrg         dst[i * 4 + 3] = 0xff;
6937117f1b4Smrg      }
6947117f1b4Smrg   }
6957117f1b4Smrg}
6967117f1b4Smrg
6977117f1b4Smrg
6987117f1b4Smrgstatic void
6997117f1b4Smrgput_mono_row_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
7007117f1b4Smrg                    GLint x, GLint y, const void *value, const GLubyte *mask)
7017117f1b4Smrg{
7027117f1b4Smrg   /* treat 4*GLubyte as 1*GLuint */
7037117f1b4Smrg   const GLuint val = *((const GLuint *) value);
7047117f1b4Smrg   GLuint *dst = (GLuint *) rb->Data + (y * rb->Width + x);
7057117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
7064a49301eSmrg   ASSERT(rb->Format == MESA_FORMAT_RGBA8888);
7077117f1b4Smrg   if (!mask && val == 0) {
7087117f1b4Smrg      /* common case */
709cdc920a0Smrg      memset(dst, 0, count * 4 * sizeof(GLubyte));
7107117f1b4Smrg   }
7117117f1b4Smrg   else {
7127117f1b4Smrg      /* general case */
7137117f1b4Smrg      if (mask) {
7147117f1b4Smrg         GLuint i;
7157117f1b4Smrg         for (i = 0; i < count; i++) {
7167117f1b4Smrg            if (mask[i]) {
7177117f1b4Smrg               dst[i] = val;
7187117f1b4Smrg            }
7197117f1b4Smrg         }
7207117f1b4Smrg      }
7217117f1b4Smrg      else {
7227117f1b4Smrg         GLuint i;
7237117f1b4Smrg         for (i = 0; i < count; i++) {
7247117f1b4Smrg            dst[i] = val;
7257117f1b4Smrg         }
7267117f1b4Smrg      }
7277117f1b4Smrg   }
7287117f1b4Smrg}
7297117f1b4Smrg
7307117f1b4Smrg
7317117f1b4Smrgstatic void
7327117f1b4Smrgput_values_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
7337117f1b4Smrg                  const GLint x[], const GLint y[], const void *values,
7347117f1b4Smrg                  const GLubyte *mask)
7357117f1b4Smrg{
7367117f1b4Smrg   /* treat 4*GLubyte as 1*GLuint */
7377117f1b4Smrg   const GLuint *src = (const GLuint *) values;
7387117f1b4Smrg   GLuint i;
7397117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
7404a49301eSmrg   ASSERT(rb->Format == MESA_FORMAT_RGBA8888);
7417117f1b4Smrg   for (i = 0; i < count; i++) {
7427117f1b4Smrg      if (!mask || mask[i]) {
7437117f1b4Smrg         GLuint *dst = (GLuint *) rb->Data + (y[i] * rb->Width + x[i]);
7447117f1b4Smrg         *dst = src[i];
7457117f1b4Smrg      }
7467117f1b4Smrg   }
7477117f1b4Smrg}
7487117f1b4Smrg
7497117f1b4Smrg
7507117f1b4Smrgstatic void
7517117f1b4Smrgput_mono_values_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb,
7527117f1b4Smrg                       GLuint count, const GLint x[], const GLint y[],
7537117f1b4Smrg                       const void *value, const GLubyte *mask)
7547117f1b4Smrg{
7557117f1b4Smrg   /* treat 4*GLubyte as 1*GLuint */
7567117f1b4Smrg   const GLuint val = *((const GLuint *) value);
7577117f1b4Smrg   GLuint i;
7587117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
7594a49301eSmrg   ASSERT(rb->Format == MESA_FORMAT_RGBA8888);
7607117f1b4Smrg   for (i = 0; i < count; i++) {
7617117f1b4Smrg      if (!mask || mask[i]) {
7627117f1b4Smrg         GLuint *dst = (GLuint *) rb->Data + (y[i] * rb->Width + x[i]);
7637117f1b4Smrg         *dst = val;
7647117f1b4Smrg      }
7657117f1b4Smrg   }
7667117f1b4Smrg}
7677117f1b4Smrg
7687117f1b4Smrg
7697117f1b4Smrg/**********************************************************************
7707117f1b4Smrg * Functions for buffers of 4 X GLushort (or GLshort) values.
7717117f1b4Smrg * Typically accum buffer.
7727117f1b4Smrg */
7737117f1b4Smrg
7747117f1b4Smrgstatic void *
7757117f1b4Smrgget_pointer_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb,
7767117f1b4Smrg                    GLint x, GLint y)
7777117f1b4Smrg{
7787117f1b4Smrg   if (!rb->Data)
7797117f1b4Smrg      return NULL;
7807117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
7817117f1b4Smrg   return (GLushort *) rb->Data + 4 * (y * rb->Width + x);
7827117f1b4Smrg}
7837117f1b4Smrg
7847117f1b4Smrg
7857117f1b4Smrgstatic void
7867117f1b4Smrgget_row_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
7877117f1b4Smrg                GLint x, GLint y, void *values)
7887117f1b4Smrg{
7897117f1b4Smrg   const GLshort *src = (const GLshort *) rb->Data + 4 * (y * rb->Width + x);
7907117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
791cdc920a0Smrg   memcpy(values, src, 4 * count * sizeof(GLshort));
7927117f1b4Smrg}
7937117f1b4Smrg
7947117f1b4Smrg
7957117f1b4Smrgstatic void
7967117f1b4Smrgget_values_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
7977117f1b4Smrg                   const GLint x[], const GLint y[], void *values)
7987117f1b4Smrg{
7997117f1b4Smrg   GLushort *dst = (GLushort *) values;
8007117f1b4Smrg   GLuint i;
8017117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
8027117f1b4Smrg   for (i = 0; i < count; i++) {
8037117f1b4Smrg      const GLushort *src
8047117f1b4Smrg         = (GLushort *) rb->Data + 4 * (y[i] * rb->Width + x[i]);
8057117f1b4Smrg      dst[i] = *src;
8067117f1b4Smrg   }
8077117f1b4Smrg}
8087117f1b4Smrg
8097117f1b4Smrg
8107117f1b4Smrgstatic void
8117117f1b4Smrgput_row_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
8127117f1b4Smrg                GLint x, GLint y, const void *values, const GLubyte *mask)
8137117f1b4Smrg{
8147117f1b4Smrg   const GLushort *src = (const GLushort *) values;
8157117f1b4Smrg   GLushort *dst = (GLushort *) rb->Data + 4 * (y * rb->Width + x);
8167117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
8177117f1b4Smrg   if (mask) {
8187117f1b4Smrg      GLuint i;
8197117f1b4Smrg      for (i = 0; i < count; i++) {
8207117f1b4Smrg         if (mask[i]) {
8217117f1b4Smrg            dst[i * 4 + 0] = src[i * 4 + 0];
8227117f1b4Smrg            dst[i * 4 + 1] = src[i * 4 + 1];
8237117f1b4Smrg            dst[i * 4 + 2] = src[i * 4 + 2];
8247117f1b4Smrg            dst[i * 4 + 3] = src[i * 4 + 3];
8257117f1b4Smrg         }
8267117f1b4Smrg      }
8277117f1b4Smrg   }
8287117f1b4Smrg   else {
829cdc920a0Smrg      memcpy(dst, src, 4 * count * sizeof(GLushort));
8307117f1b4Smrg   }
8317117f1b4Smrg}
8327117f1b4Smrg
8337117f1b4Smrg
8347117f1b4Smrgstatic void
8357117f1b4Smrgput_row_rgb_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
8367117f1b4Smrg                    GLint x, GLint y, const void *values, const GLubyte *mask)
8377117f1b4Smrg{
8387117f1b4Smrg   /* Put RGB values in RGBA buffer */
8397117f1b4Smrg   const GLushort *src = (const GLushort *) values;
8407117f1b4Smrg   GLushort *dst = (GLushort *) rb->Data + 4 * (y * rb->Width + x);
8417117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
8427117f1b4Smrg   if (mask) {
8437117f1b4Smrg      GLuint i;
8447117f1b4Smrg      for (i = 0; i < count; i++) {
8457117f1b4Smrg         if (mask[i]) {
8467117f1b4Smrg            dst[i * 4 + 0] = src[i * 3 + 0];
8477117f1b4Smrg            dst[i * 4 + 1] = src[i * 3 + 1];
8487117f1b4Smrg            dst[i * 4 + 2] = src[i * 3 + 2];
8497117f1b4Smrg            dst[i * 4 + 3] = 0xffff;
8507117f1b4Smrg         }
8517117f1b4Smrg      }
8527117f1b4Smrg   }
8537117f1b4Smrg   else {
854cdc920a0Smrg      memcpy(dst, src, 4 * count * sizeof(GLushort));
8557117f1b4Smrg   }
8567117f1b4Smrg}
8577117f1b4Smrg
8587117f1b4Smrg
8597117f1b4Smrgstatic void
8607117f1b4Smrgput_mono_row_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
8617117f1b4Smrg                     GLint x, GLint y, const void *value, const GLubyte *mask)
8627117f1b4Smrg{
8637117f1b4Smrg   const GLushort val0 = ((const GLushort *) value)[0];
8647117f1b4Smrg   const GLushort val1 = ((const GLushort *) value)[1];
8657117f1b4Smrg   const GLushort val2 = ((const GLushort *) value)[2];
8667117f1b4Smrg   const GLushort val3 = ((const GLushort *) value)[3];
8677117f1b4Smrg   GLushort *dst = (GLushort *) rb->Data + 4 * (y * rb->Width + x);
8687117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
8697117f1b4Smrg   if (!mask && val0 == 0 && val1 == 0 && val2 == 0 && val3 == 0) {
8707117f1b4Smrg      /* common case for clearing accum buffer */
871cdc920a0Smrg      memset(dst, 0, count * 4 * sizeof(GLushort));
8727117f1b4Smrg   }
8737117f1b4Smrg   else {
8747117f1b4Smrg      GLuint i;
8757117f1b4Smrg      for (i = 0; i < count; i++) {
8767117f1b4Smrg         if (!mask || mask[i]) {
8777117f1b4Smrg            dst[i * 4 + 0] = val0;
8787117f1b4Smrg            dst[i * 4 + 1] = val1;
8797117f1b4Smrg            dst[i * 4 + 2] = val2;
8807117f1b4Smrg            dst[i * 4 + 3] = val3;
8817117f1b4Smrg         }
8827117f1b4Smrg      }
8837117f1b4Smrg   }
8847117f1b4Smrg}
8857117f1b4Smrg
8867117f1b4Smrg
8877117f1b4Smrgstatic void
8887117f1b4Smrgput_values_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
8897117f1b4Smrg                   const GLint x[], const GLint y[], const void *values,
8907117f1b4Smrg                   const GLubyte *mask)
8917117f1b4Smrg{
8927117f1b4Smrg   const GLushort *src = (const GLushort *) values;
8937117f1b4Smrg   GLuint i;
8947117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
8957117f1b4Smrg   for (i = 0; i < count; i++) {
8967117f1b4Smrg      if (!mask || mask[i]) {
8977117f1b4Smrg         GLushort *dst = (GLushort *) rb->Data + 4 * (y[i] * rb->Width + x[i]);
8987117f1b4Smrg         dst[0] = src[i * 4 + 0];
8997117f1b4Smrg         dst[1] = src[i * 4 + 1];
9007117f1b4Smrg         dst[2] = src[i * 4 + 2];
9017117f1b4Smrg         dst[3] = src[i * 4 + 3];
9027117f1b4Smrg      }
9037117f1b4Smrg   }
9047117f1b4Smrg}
9057117f1b4Smrg
9067117f1b4Smrg
9077117f1b4Smrgstatic void
9087117f1b4Smrgput_mono_values_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb,
9097117f1b4Smrg                        GLuint count, const GLint x[], const GLint y[],
9107117f1b4Smrg                        const void *value, const GLubyte *mask)
9117117f1b4Smrg{
9127117f1b4Smrg   const GLushort val0 = ((const GLushort *) value)[0];
9137117f1b4Smrg   const GLushort val1 = ((const GLushort *) value)[1];
9147117f1b4Smrg   const GLushort val2 = ((const GLushort *) value)[2];
9157117f1b4Smrg   const GLushort val3 = ((const GLushort *) value)[3];
9167117f1b4Smrg   GLuint i;
9177117f1b4Smrg   ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
9187117f1b4Smrg   for (i = 0; i < count; i++) {
9197117f1b4Smrg      if (!mask || mask[i]) {
9207117f1b4Smrg         GLushort *dst = (GLushort *) rb->Data + 4 * (y[i] * rb->Width + x[i]);
9217117f1b4Smrg         dst[0] = val0;
9227117f1b4Smrg         dst[1] = val1;
9237117f1b4Smrg         dst[2] = val2;
9247117f1b4Smrg         dst[3] = val3;
9257117f1b4Smrg      }
9267117f1b4Smrg   }
9277117f1b4Smrg}
9287117f1b4Smrg
9297117f1b4Smrg
9307117f1b4Smrg
9317117f1b4Smrg/**
9327117f1b4Smrg * This is a software fallback for the gl_renderbuffer->AllocStorage
9337117f1b4Smrg * function.
9347117f1b4Smrg * Device drivers will typically override this function for the buffers
9357117f1b4Smrg * which it manages (typically color buffers, Z and stencil).
9367117f1b4Smrg * Other buffers (like software accumulation and aux buffers) which the driver
9377117f1b4Smrg * doesn't manage can be handled with this function.
9387117f1b4Smrg *
9397117f1b4Smrg * This one multi-purpose function can allocate stencil, depth, accum, color
9407117f1b4Smrg * or color-index buffers!
9417117f1b4Smrg *
9427117f1b4Smrg * This function also plugs in the appropriate GetPointer, Get/PutRow and
9437117f1b4Smrg * Get/PutValues functions.
9447117f1b4Smrg */
9457117f1b4SmrgGLboolean
9467117f1b4Smrg_mesa_soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
9477117f1b4Smrg                                GLenum internalFormat,
9487117f1b4Smrg                                GLuint width, GLuint height)
9497117f1b4Smrg{
9507117f1b4Smrg   GLuint pixelSize;
9517117f1b4Smrg
9527117f1b4Smrg   switch (internalFormat) {
9537117f1b4Smrg   case GL_RGB:
9547117f1b4Smrg   case GL_R3_G3_B2:
9557117f1b4Smrg   case GL_RGB4:
9567117f1b4Smrg   case GL_RGB5:
9577117f1b4Smrg   case GL_RGB8:
9587117f1b4Smrg   case GL_RGB10:
9597117f1b4Smrg   case GL_RGB12:
9607117f1b4Smrg   case GL_RGB16:
9614a49301eSmrg      rb->Format = MESA_FORMAT_RGB888;
9627117f1b4Smrg      rb->DataType = GL_UNSIGNED_BYTE;
9637117f1b4Smrg      rb->GetPointer = get_pointer_ubyte3;
9647117f1b4Smrg      rb->GetRow = get_row_ubyte3;
9657117f1b4Smrg      rb->GetValues = get_values_ubyte3;
9667117f1b4Smrg      rb->PutRow = put_row_ubyte3;
9677117f1b4Smrg      rb->PutRowRGB = put_row_rgb_ubyte3;
9687117f1b4Smrg      rb->PutMonoRow = put_mono_row_ubyte3;
9697117f1b4Smrg      rb->PutValues = put_values_ubyte3;
9707117f1b4Smrg      rb->PutMonoValues = put_mono_values_ubyte3;
9717117f1b4Smrg      pixelSize = 3 * sizeof(GLubyte);
9727117f1b4Smrg      break;
9737117f1b4Smrg   case GL_RGBA:
9747117f1b4Smrg   case GL_RGBA2:
9757117f1b4Smrg   case GL_RGBA4:
9767117f1b4Smrg   case GL_RGB5_A1:
9777117f1b4Smrg   case GL_RGBA8:
9784a49301eSmrg#if 1
9794a49301eSmrg   case GL_RGB10_A2:
9804a49301eSmrg   case GL_RGBA12:
9814a49301eSmrg#endif
9824a49301eSmrg      rb->Format = MESA_FORMAT_RGBA8888;
9837117f1b4Smrg      rb->DataType = GL_UNSIGNED_BYTE;
9847117f1b4Smrg      rb->GetPointer = get_pointer_ubyte4;
9857117f1b4Smrg      rb->GetRow = get_row_ubyte4;
9867117f1b4Smrg      rb->GetValues = get_values_ubyte4;
9877117f1b4Smrg      rb->PutRow = put_row_ubyte4;
9887117f1b4Smrg      rb->PutRowRGB = put_row_rgb_ubyte4;
9897117f1b4Smrg      rb->PutMonoRow = put_mono_row_ubyte4;
9907117f1b4Smrg      rb->PutValues = put_values_ubyte4;
9917117f1b4Smrg      rb->PutMonoValues = put_mono_values_ubyte4;
9927117f1b4Smrg      pixelSize = 4 * sizeof(GLubyte);
9937117f1b4Smrg      break;
9947117f1b4Smrg   case GL_RGBA16:
9954a49301eSmrg      /* for accum buffer */
9964a49301eSmrg      rb->Format = MESA_FORMAT_SIGNED_RGBA_16;
9974a49301eSmrg      rb->DataType = GL_SHORT;
9987117f1b4Smrg      rb->GetPointer = get_pointer_ushort4;
9997117f1b4Smrg      rb->GetRow = get_row_ushort4;
10007117f1b4Smrg      rb->GetValues = get_values_ushort4;
10017117f1b4Smrg      rb->PutRow = put_row_ushort4;
10027117f1b4Smrg      rb->PutRowRGB = put_row_rgb_ushort4;
10037117f1b4Smrg      rb->PutMonoRow = put_mono_row_ushort4;
10047117f1b4Smrg      rb->PutValues = put_values_ushort4;
10057117f1b4Smrg      rb->PutMonoValues = put_mono_values_ushort4;
10067117f1b4Smrg      pixelSize = 4 * sizeof(GLushort);
10077117f1b4Smrg      break;
10084a49301eSmrg#if 0
10097117f1b4Smrg   case GL_ALPHA8:
10104a49301eSmrg      rb->Format = MESA_FORMAT_A8;
10117117f1b4Smrg      rb->DataType = GL_UNSIGNED_BYTE;
10127117f1b4Smrg      rb->GetPointer = get_pointer_alpha8;
10137117f1b4Smrg      rb->GetRow = get_row_alpha8;
10147117f1b4Smrg      rb->GetValues = get_values_alpha8;
10157117f1b4Smrg      rb->PutRow = put_row_alpha8;
10167117f1b4Smrg      rb->PutRowRGB = NULL;
10177117f1b4Smrg      rb->PutMonoRow = put_mono_row_alpha8;
10187117f1b4Smrg      rb->PutValues = put_values_alpha8;
10197117f1b4Smrg      rb->PutMonoValues = put_mono_values_alpha8;
10207117f1b4Smrg      pixelSize = sizeof(GLubyte);
10217117f1b4Smrg      break;
10227117f1b4Smrg#endif
10237117f1b4Smrg   case GL_STENCIL_INDEX:
10247117f1b4Smrg   case GL_STENCIL_INDEX1_EXT:
10257117f1b4Smrg   case GL_STENCIL_INDEX4_EXT:
10267117f1b4Smrg   case GL_STENCIL_INDEX8_EXT:
10274a49301eSmrg   case GL_STENCIL_INDEX16_EXT:
10284a49301eSmrg      rb->Format = MESA_FORMAT_S8;
10297117f1b4Smrg      rb->DataType = GL_UNSIGNED_BYTE;
10307117f1b4Smrg      rb->GetPointer = get_pointer_ubyte;
10317117f1b4Smrg      rb->GetRow = get_row_ubyte;
10327117f1b4Smrg      rb->GetValues = get_values_ubyte;
10337117f1b4Smrg      rb->PutRow = put_row_ubyte;
10347117f1b4Smrg      rb->PutRowRGB = NULL;
10357117f1b4Smrg      rb->PutMonoRow = put_mono_row_ubyte;
10367117f1b4Smrg      rb->PutValues = put_values_ubyte;
10377117f1b4Smrg      rb->PutMonoValues = put_mono_values_ubyte;
10387117f1b4Smrg      pixelSize = sizeof(GLubyte);
10397117f1b4Smrg      break;
10407117f1b4Smrg   case GL_DEPTH_COMPONENT:
10417117f1b4Smrg   case GL_DEPTH_COMPONENT16:
10424a49301eSmrg      rb->Format = MESA_FORMAT_Z16;
10437117f1b4Smrg      rb->DataType = GL_UNSIGNED_SHORT;
10447117f1b4Smrg      rb->GetPointer = get_pointer_ushort;
10457117f1b4Smrg      rb->GetRow = get_row_ushort;
10467117f1b4Smrg      rb->GetValues = get_values_ushort;
10477117f1b4Smrg      rb->PutRow = put_row_ushort;
10487117f1b4Smrg      rb->PutRowRGB = NULL;
10497117f1b4Smrg      rb->PutMonoRow = put_mono_row_ushort;
10507117f1b4Smrg      rb->PutValues = put_values_ushort;
10517117f1b4Smrg      rb->PutMonoValues = put_mono_values_ushort;
10527117f1b4Smrg      pixelSize = sizeof(GLushort);
10537117f1b4Smrg      break;
10547117f1b4Smrg   case GL_DEPTH_COMPONENT24:
10554a49301eSmrg      rb->DataType = GL_UNSIGNED_INT;
10564a49301eSmrg      rb->GetPointer = get_pointer_uint;
10574a49301eSmrg      rb->GetRow = get_row_uint;
10584a49301eSmrg      rb->GetValues = get_values_uint;
10594a49301eSmrg      rb->PutRow = put_row_uint;
10604a49301eSmrg      rb->PutRowRGB = NULL;
10614a49301eSmrg      rb->PutMonoRow = put_mono_row_uint;
10624a49301eSmrg      rb->PutValues = put_values_uint;
10634a49301eSmrg      rb->PutMonoValues = put_mono_values_uint;
10644a49301eSmrg      rb->Format = MESA_FORMAT_X8_Z24;
10654a49301eSmrg      pixelSize = sizeof(GLuint);
10664a49301eSmrg      break;
10677117f1b4Smrg   case GL_DEPTH_COMPONENT32:
10687117f1b4Smrg      rb->DataType = GL_UNSIGNED_INT;
10697117f1b4Smrg      rb->GetPointer = get_pointer_uint;
10707117f1b4Smrg      rb->GetRow = get_row_uint;
10717117f1b4Smrg      rb->GetValues = get_values_uint;
10727117f1b4Smrg      rb->PutRow = put_row_uint;
10737117f1b4Smrg      rb->PutRowRGB = NULL;
10747117f1b4Smrg      rb->PutMonoRow = put_mono_row_uint;
10757117f1b4Smrg      rb->PutValues = put_values_uint;
10767117f1b4Smrg      rb->PutMonoValues = put_mono_values_uint;
10774a49301eSmrg      rb->Format = MESA_FORMAT_Z32;
10787117f1b4Smrg      pixelSize = sizeof(GLuint);
10797117f1b4Smrg      break;
10807117f1b4Smrg   case GL_DEPTH_STENCIL_EXT:
10817117f1b4Smrg   case GL_DEPTH24_STENCIL8_EXT:
10824a49301eSmrg      rb->Format = MESA_FORMAT_Z24_S8;
10837117f1b4Smrg      rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
10847117f1b4Smrg      rb->GetPointer = get_pointer_uint;
10857117f1b4Smrg      rb->GetRow = get_row_uint;
10867117f1b4Smrg      rb->GetValues = get_values_uint;
10877117f1b4Smrg      rb->PutRow = put_row_uint;
10887117f1b4Smrg      rb->PutRowRGB = NULL;
10897117f1b4Smrg      rb->PutMonoRow = put_mono_row_uint;
10907117f1b4Smrg      rb->PutValues = put_values_uint;
10917117f1b4Smrg      rb->PutMonoValues = put_mono_values_uint;
10927117f1b4Smrg      pixelSize = sizeof(GLuint);
10937117f1b4Smrg      break;
10947117f1b4Smrg   case GL_COLOR_INDEX8_EXT:
10954a49301eSmrg   case GL_COLOR_INDEX16_EXT:
10964a49301eSmrg   case COLOR_INDEX32:
10974a49301eSmrg      rb->Format = MESA_FORMAT_CI8;
10987117f1b4Smrg      rb->DataType = GL_UNSIGNED_BYTE;
10997117f1b4Smrg      rb->GetPointer = get_pointer_ubyte;
11007117f1b4Smrg      rb->GetRow = get_row_ubyte;
11017117f1b4Smrg      rb->GetValues = get_values_ubyte;
11027117f1b4Smrg      rb->PutRow = put_row_ubyte;
11037117f1b4Smrg      rb->PutRowRGB = NULL;
11047117f1b4Smrg      rb->PutMonoRow = put_mono_row_ubyte;
11057117f1b4Smrg      rb->PutValues = put_values_ubyte;
11067117f1b4Smrg      rb->PutMonoValues = put_mono_values_ubyte;
11077117f1b4Smrg      pixelSize = sizeof(GLubyte);
11087117f1b4Smrg      break;
11097117f1b4Smrg   default:
11107117f1b4Smrg      _mesa_problem(ctx, "Bad internalFormat in _mesa_soft_renderbuffer_storage");
11117117f1b4Smrg      return GL_FALSE;
11127117f1b4Smrg   }
11137117f1b4Smrg
11147117f1b4Smrg   ASSERT(rb->DataType);
11157117f1b4Smrg   ASSERT(rb->GetPointer);
11167117f1b4Smrg   ASSERT(rb->GetRow);
11177117f1b4Smrg   ASSERT(rb->GetValues);
11187117f1b4Smrg   ASSERT(rb->PutRow);
11197117f1b4Smrg   ASSERT(rb->PutMonoRow);
11207117f1b4Smrg   ASSERT(rb->PutValues);
11217117f1b4Smrg   ASSERT(rb->PutMonoValues);
11227117f1b4Smrg
11237117f1b4Smrg   /* free old buffer storage */
11247117f1b4Smrg   if (rb->Data) {
1125cdc920a0Smrg      free(rb->Data);
11267117f1b4Smrg      rb->Data = NULL;
11277117f1b4Smrg   }
11287117f1b4Smrg
11297117f1b4Smrg   if (width > 0 && height > 0) {
11307117f1b4Smrg      /* allocate new buffer storage */
11314a49301eSmrg      rb->Data = malloc(width * height * pixelSize);
11324a49301eSmrg
11337117f1b4Smrg      if (rb->Data == NULL) {
11347117f1b4Smrg         rb->Width = 0;
11357117f1b4Smrg         rb->Height = 0;
11367117f1b4Smrg         _mesa_error(ctx, GL_OUT_OF_MEMORY,
11377117f1b4Smrg                     "software renderbuffer allocation (%d x %d x %d)",
11387117f1b4Smrg                     width, height, pixelSize);
11397117f1b4Smrg         return GL_FALSE;
11407117f1b4Smrg      }
11417117f1b4Smrg   }
11427117f1b4Smrg
11437117f1b4Smrg   rb->Width = width;
11447117f1b4Smrg   rb->Height = height;
11454a49301eSmrg   rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
11464a49301eSmrg   ASSERT(rb->_BaseFormat);
11477117f1b4Smrg
11487117f1b4Smrg   return GL_TRUE;
11497117f1b4Smrg}
11507117f1b4Smrg
11517117f1b4Smrg
11527117f1b4Smrg
11537117f1b4Smrg/**********************************************************************/
11547117f1b4Smrg/**********************************************************************/
11557117f1b4Smrg/**********************************************************************/
11567117f1b4Smrg
11577117f1b4Smrg
11587117f1b4Smrg/**
11597117f1b4Smrg * Here we utilize the gl_renderbuffer->Wrapper field to put an alpha
11607117f1b4Smrg * buffer wrapper around an existing RGB renderbuffer (hw or sw).
11617117f1b4Smrg *
11627117f1b4Smrg * When PutRow is called (for example), we store the alpha values in
11637117f1b4Smrg * this buffer, then pass on the PutRow call to the wrapped RGB
11647117f1b4Smrg * buffer.
11657117f1b4Smrg */
11667117f1b4Smrg
11677117f1b4Smrg
11687117f1b4Smrgstatic GLboolean
11697117f1b4Smrgalloc_storage_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb,
11707117f1b4Smrg                     GLenum internalFormat, GLuint width, GLuint height)
11717117f1b4Smrg{
11727117f1b4Smrg   ASSERT(arb != arb->Wrapped);
11734a49301eSmrg   ASSERT(arb->Format == MESA_FORMAT_A8);
11747117f1b4Smrg
11757117f1b4Smrg   /* first, pass the call to the wrapped RGB buffer */
11767117f1b4Smrg   if (!arb->Wrapped->AllocStorage(ctx, arb->Wrapped, internalFormat,
11777117f1b4Smrg                                  width, height)) {
11787117f1b4Smrg      return GL_FALSE;
11797117f1b4Smrg   }
11807117f1b4Smrg
11817117f1b4Smrg   /* next, resize my alpha buffer */
11827117f1b4Smrg   if (arb->Data) {
1183cdc920a0Smrg      free(arb->Data);
11847117f1b4Smrg   }
11857117f1b4Smrg
1186cdc920a0Smrg   arb->Data = malloc(width * height * sizeof(GLubyte));
11877117f1b4Smrg   if (arb->Data == NULL) {
11887117f1b4Smrg      arb->Width = 0;
11897117f1b4Smrg      arb->Height = 0;
11907117f1b4Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "software alpha buffer allocation");
11917117f1b4Smrg      return GL_FALSE;
11927117f1b4Smrg   }
11937117f1b4Smrg
11947117f1b4Smrg   arb->Width = width;
11957117f1b4Smrg   arb->Height = height;
11967117f1b4Smrg
11977117f1b4Smrg   return GL_TRUE;
11987117f1b4Smrg}
11997117f1b4Smrg
12007117f1b4Smrg
12017117f1b4Smrg/**
12027117f1b4Smrg * Delete an alpha_renderbuffer object, as well as the wrapped RGB buffer.
12037117f1b4Smrg */
12047117f1b4Smrgstatic void
12057117f1b4Smrgdelete_renderbuffer_alpha8(struct gl_renderbuffer *arb)
12067117f1b4Smrg{
12077117f1b4Smrg   if (arb->Data) {
1208cdc920a0Smrg      free(arb->Data);
12097117f1b4Smrg   }
12107117f1b4Smrg   ASSERT(arb->Wrapped);
12117117f1b4Smrg   ASSERT(arb != arb->Wrapped);
12127117f1b4Smrg   arb->Wrapped->Delete(arb->Wrapped);
12137117f1b4Smrg   arb->Wrapped = NULL;
1214cdc920a0Smrg   free(arb);
12157117f1b4Smrg}
12167117f1b4Smrg
12177117f1b4Smrg
12187117f1b4Smrgstatic void *
12197117f1b4Smrgget_pointer_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb,
12207117f1b4Smrg                   GLint x, GLint y)
12217117f1b4Smrg{
12227117f1b4Smrg   return NULL;   /* don't allow direct access! */
12237117f1b4Smrg}
12247117f1b4Smrg
12257117f1b4Smrg
12267117f1b4Smrgstatic void
12277117f1b4Smrgget_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
12287117f1b4Smrg               GLint x, GLint y, void *values)
12297117f1b4Smrg{
12307117f1b4Smrg   /* NOTE: 'values' is RGBA format! */
12317117f1b4Smrg   const GLubyte *src = (const GLubyte *) arb->Data + y * arb->Width + x;
12327117f1b4Smrg   GLubyte *dst = (GLubyte *) values;
12337117f1b4Smrg   GLuint i;
12347117f1b4Smrg   ASSERT(arb != arb->Wrapped);
12357117f1b4Smrg   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
12367117f1b4Smrg   /* first, pass the call to the wrapped RGB buffer */
12377117f1b4Smrg   arb->Wrapped->GetRow(ctx, arb->Wrapped, count, x, y, values);
12387117f1b4Smrg   /* second, fill in alpha values from this buffer! */
12397117f1b4Smrg   for (i = 0; i < count; i++) {
12407117f1b4Smrg      dst[i * 4 + 3] = src[i];
12417117f1b4Smrg   }
12427117f1b4Smrg}
12437117f1b4Smrg
12447117f1b4Smrg
12457117f1b4Smrgstatic void
12467117f1b4Smrgget_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
12477117f1b4Smrg                  const GLint x[], const GLint y[], void *values)
12487117f1b4Smrg{
12497117f1b4Smrg   GLubyte *dst = (GLubyte *) values;
12507117f1b4Smrg   GLuint i;
12517117f1b4Smrg   ASSERT(arb != arb->Wrapped);
12527117f1b4Smrg   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
12537117f1b4Smrg   /* first, pass the call to the wrapped RGB buffer */
12547117f1b4Smrg   arb->Wrapped->GetValues(ctx, arb->Wrapped, count, x, y, values);
12557117f1b4Smrg   /* second, fill in alpha values from this buffer! */
12567117f1b4Smrg   for (i = 0; i < count; i++) {
12577117f1b4Smrg      const GLubyte *src = (GLubyte *) arb->Data + y[i] * arb->Width + x[i];
12587117f1b4Smrg      dst[i * 4 + 3] = *src;
12597117f1b4Smrg   }
12607117f1b4Smrg}
12617117f1b4Smrg
12627117f1b4Smrg
12637117f1b4Smrgstatic void
12647117f1b4Smrgput_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
12657117f1b4Smrg               GLint x, GLint y, const void *values, const GLubyte *mask)
12667117f1b4Smrg{
12677117f1b4Smrg   const GLubyte *src = (const GLubyte *) values;
12687117f1b4Smrg   GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x;
12697117f1b4Smrg   GLuint i;
12707117f1b4Smrg   ASSERT(arb != arb->Wrapped);
12717117f1b4Smrg   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
12727117f1b4Smrg   /* first, pass the call to the wrapped RGB buffer */
12737117f1b4Smrg   arb->Wrapped->PutRow(ctx, arb->Wrapped, count, x, y, values, mask);
12747117f1b4Smrg   /* second, store alpha in our buffer */
12757117f1b4Smrg   for (i = 0; i < count; i++) {
12767117f1b4Smrg      if (!mask || mask[i]) {
12777117f1b4Smrg         dst[i] = src[i * 4 + 3];
12787117f1b4Smrg      }
12797117f1b4Smrg   }
12807117f1b4Smrg}
12817117f1b4Smrg
12827117f1b4Smrg
12837117f1b4Smrgstatic void
12847117f1b4Smrgput_row_rgb_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
12857117f1b4Smrg                   GLint x, GLint y, const void *values, const GLubyte *mask)
12867117f1b4Smrg{
12877117f1b4Smrg   const GLubyte *src = (const GLubyte *) values;
12887117f1b4Smrg   GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x;
12897117f1b4Smrg   GLuint i;
12907117f1b4Smrg   ASSERT(arb != arb->Wrapped);
12917117f1b4Smrg   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
12927117f1b4Smrg   /* first, pass the call to the wrapped RGB buffer */
12937117f1b4Smrg   arb->Wrapped->PutRowRGB(ctx, arb->Wrapped, count, x, y, values, mask);
12947117f1b4Smrg   /* second, store alpha in our buffer */
12957117f1b4Smrg   for (i = 0; i < count; i++) {
12967117f1b4Smrg      if (!mask || mask[i]) {
12977117f1b4Smrg         dst[i] = src[i * 4 + 3];
12987117f1b4Smrg      }
12997117f1b4Smrg   }
13007117f1b4Smrg}
13017117f1b4Smrg
13027117f1b4Smrg
13037117f1b4Smrgstatic void
13047117f1b4Smrgput_mono_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
13057117f1b4Smrg                    GLint x, GLint y, const void *value, const GLubyte *mask)
13067117f1b4Smrg{
13077117f1b4Smrg   const GLubyte val = ((const GLubyte *) value)[3];
13087117f1b4Smrg   GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x;
13097117f1b4Smrg   ASSERT(arb != arb->Wrapped);
13107117f1b4Smrg   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
13117117f1b4Smrg   /* first, pass the call to the wrapped RGB buffer */
13127117f1b4Smrg   arb->Wrapped->PutMonoRow(ctx, arb->Wrapped, count, x, y, value, mask);
13137117f1b4Smrg   /* second, store alpha in our buffer */
13147117f1b4Smrg   if (mask) {
13157117f1b4Smrg      GLuint i;
13167117f1b4Smrg      for (i = 0; i < count; i++) {
13177117f1b4Smrg         if (mask[i]) {
13187117f1b4Smrg            dst[i] = val;
13197117f1b4Smrg         }
13207117f1b4Smrg      }
13217117f1b4Smrg   }
13227117f1b4Smrg   else {
1323cdc920a0Smrg      memset(dst, val, count);
13247117f1b4Smrg   }
13257117f1b4Smrg}
13267117f1b4Smrg
13277117f1b4Smrg
13287117f1b4Smrgstatic void
13297117f1b4Smrgput_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
13307117f1b4Smrg                  const GLint x[], const GLint y[],
13317117f1b4Smrg                  const void *values, const GLubyte *mask)
13327117f1b4Smrg{
13337117f1b4Smrg   const GLubyte *src = (const GLubyte *) values;
13347117f1b4Smrg   GLuint i;
13357117f1b4Smrg   ASSERT(arb != arb->Wrapped);
13367117f1b4Smrg   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
13377117f1b4Smrg   /* first, pass the call to the wrapped RGB buffer */
13387117f1b4Smrg   arb->Wrapped->PutValues(ctx, arb->Wrapped, count, x, y, values, mask);
13397117f1b4Smrg   /* second, store alpha in our buffer */
13407117f1b4Smrg   for (i = 0; i < count; i++) {
13417117f1b4Smrg      if (!mask || mask[i]) {
13427117f1b4Smrg         GLubyte *dst = (GLubyte *) arb->Data + y[i] * arb->Width + x[i];
13437117f1b4Smrg         *dst = src[i * 4 + 3];
13447117f1b4Smrg      }
13457117f1b4Smrg   }
13467117f1b4Smrg}
13477117f1b4Smrg
13487117f1b4Smrg
13497117f1b4Smrgstatic void
13507117f1b4Smrgput_mono_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb,
13517117f1b4Smrg                       GLuint count, const GLint x[], const GLint y[],
13527117f1b4Smrg                       const void *value, const GLubyte *mask)
13537117f1b4Smrg{
13547117f1b4Smrg   const GLubyte val = ((const GLubyte *) value)[3];
13557117f1b4Smrg   GLuint i;
13567117f1b4Smrg   ASSERT(arb != arb->Wrapped);
13577117f1b4Smrg   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
13587117f1b4Smrg   /* first, pass the call to the wrapped RGB buffer */
13597117f1b4Smrg   arb->Wrapped->PutValues(ctx, arb->Wrapped, count, x, y, value, mask);
13607117f1b4Smrg   /* second, store alpha in our buffer */
13617117f1b4Smrg   for (i = 0; i < count; i++) {
13627117f1b4Smrg      if (!mask || mask[i]) {
13637117f1b4Smrg         GLubyte *dst = (GLubyte *) arb->Data + y[i] * arb->Width + x[i];
13647117f1b4Smrg         *dst = val;
13657117f1b4Smrg      }
13667117f1b4Smrg   }
13677117f1b4Smrg}
13687117f1b4Smrg
13697117f1b4Smrg
13707117f1b4Smrgstatic void
13717117f1b4Smrgcopy_buffer_alpha8(struct gl_renderbuffer* dst, struct gl_renderbuffer* src)
13727117f1b4Smrg{
13734a49301eSmrg   ASSERT(dst->Format == MESA_FORMAT_A8);
13744a49301eSmrg   ASSERT(src->Format == MESA_FORMAT_A8);
13757117f1b4Smrg   ASSERT(dst->Width == src->Width);
13767117f1b4Smrg   ASSERT(dst->Height == src->Height);
13777117f1b4Smrg
1378cdc920a0Smrg   memcpy(dst->Data, src->Data, dst->Width * dst->Height * sizeof(GLubyte));
13797117f1b4Smrg}
13807117f1b4Smrg
13817117f1b4Smrg
13827117f1b4Smrg/**********************************************************************/
13837117f1b4Smrg/**********************************************************************/
13847117f1b4Smrg/**********************************************************************/
13857117f1b4Smrg
13867117f1b4Smrg
13877117f1b4Smrg/**
13887117f1b4Smrg * Default GetPointer routine.  Always return NULL to indicate that
13897117f1b4Smrg * direct buffer access is not supported.
13907117f1b4Smrg */
13917117f1b4Smrgstatic void *
13927117f1b4Smrgnop_get_pointer(GLcontext *ctx, struct gl_renderbuffer *rb, GLint x, GLint y)
13937117f1b4Smrg{
13947117f1b4Smrg   return NULL;
13957117f1b4Smrg}
13967117f1b4Smrg
13977117f1b4Smrg
13987117f1b4Smrg/**
13997117f1b4Smrg * Initialize the fields of a gl_renderbuffer to default values.
14007117f1b4Smrg */
14017117f1b4Smrgvoid
14027117f1b4Smrg_mesa_init_renderbuffer(struct gl_renderbuffer *rb, GLuint name)
14037117f1b4Smrg{
14047117f1b4Smrg   _glthread_INIT_MUTEX(rb->Mutex);
14057117f1b4Smrg
14067117f1b4Smrg   rb->Magic = RB_MAGIC;
14077117f1b4Smrg   rb->ClassID = 0;
14087117f1b4Smrg   rb->Name = name;
14097117f1b4Smrg   rb->RefCount = 0;
14107117f1b4Smrg   rb->Delete = _mesa_delete_renderbuffer;
14117117f1b4Smrg
14127117f1b4Smrg   /* The rest of these should be set later by the caller of this function or
14137117f1b4Smrg    * the AllocStorage method:
14147117f1b4Smrg    */
14157117f1b4Smrg   rb->AllocStorage = NULL;
14167117f1b4Smrg
14177117f1b4Smrg   rb->Width = 0;
14187117f1b4Smrg   rb->Height = 0;
14197117f1b4Smrg   rb->InternalFormat = GL_NONE;
14204a49301eSmrg   rb->Format = MESA_FORMAT_NONE;
14214a49301eSmrg
14227117f1b4Smrg   rb->DataType = GL_NONE;
14237117f1b4Smrg   rb->Data = NULL;
14247117f1b4Smrg
14257117f1b4Smrg   /* Point back to ourself so that we don't have to check for Wrapped==NULL
14267117f1b4Smrg    * all over the drivers.
14277117f1b4Smrg    */
14287117f1b4Smrg   rb->Wrapped = rb;
14297117f1b4Smrg
14307117f1b4Smrg   rb->GetPointer = nop_get_pointer;
14317117f1b4Smrg   rb->GetRow = NULL;
14327117f1b4Smrg   rb->GetValues = NULL;
14337117f1b4Smrg   rb->PutRow = NULL;
14347117f1b4Smrg   rb->PutRowRGB = NULL;
14357117f1b4Smrg   rb->PutMonoRow = NULL;
14367117f1b4Smrg   rb->PutValues = NULL;
14377117f1b4Smrg   rb->PutMonoValues = NULL;
14387117f1b4Smrg}
14397117f1b4Smrg
14407117f1b4Smrg
14417117f1b4Smrg/**
14427117f1b4Smrg * Allocate a new gl_renderbuffer object.  This can be used for user-created
14437117f1b4Smrg * renderbuffers or window-system renderbuffers.
14447117f1b4Smrg */
14457117f1b4Smrgstruct gl_renderbuffer *
14467117f1b4Smrg_mesa_new_renderbuffer(GLcontext *ctx, GLuint name)
14477117f1b4Smrg{
14487117f1b4Smrg   struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer);
14497117f1b4Smrg   if (rb) {
14507117f1b4Smrg      _mesa_init_renderbuffer(rb, name);
14517117f1b4Smrg   }
14527117f1b4Smrg   return rb;
14537117f1b4Smrg}
14547117f1b4Smrg
14557117f1b4Smrg
14567117f1b4Smrg/**
14577117f1b4Smrg * Delete a gl_framebuffer.
14587117f1b4Smrg * This is the default function for renderbuffer->Delete().
14597117f1b4Smrg */
14607117f1b4Smrgvoid
14617117f1b4Smrg_mesa_delete_renderbuffer(struct gl_renderbuffer *rb)
14627117f1b4Smrg{
14637117f1b4Smrg   if (rb->Data) {
1464cdc920a0Smrg      free(rb->Data);
14657117f1b4Smrg   }
1466cdc920a0Smrg   free(rb);
14677117f1b4Smrg}
14687117f1b4Smrg
14697117f1b4Smrg
14707117f1b4Smrg/**
14717117f1b4Smrg * Allocate a software-based renderbuffer.  This is called via the
14727117f1b4Smrg * ctx->Driver.NewRenderbuffer() function when the user creates a new
14737117f1b4Smrg * renderbuffer.
14747117f1b4Smrg * This would not be used for hardware-based renderbuffers.
14757117f1b4Smrg */
14767117f1b4Smrgstruct gl_renderbuffer *
14777117f1b4Smrg_mesa_new_soft_renderbuffer(GLcontext *ctx, GLuint name)
14787117f1b4Smrg{
14797117f1b4Smrg   struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, name);
14807117f1b4Smrg   if (rb) {
14817117f1b4Smrg      rb->AllocStorage = _mesa_soft_renderbuffer_storage;
14827117f1b4Smrg      /* Normally, one would setup the PutRow, GetRow, etc functions here.
14837117f1b4Smrg       * But we're doing that in the _mesa_soft_renderbuffer_storage() function
14847117f1b4Smrg       * instead.
14857117f1b4Smrg       */
14867117f1b4Smrg   }
14877117f1b4Smrg   return rb;
14887117f1b4Smrg}
14897117f1b4Smrg
14907117f1b4Smrg
14917117f1b4Smrg/**
14927117f1b4Smrg * Add software-based color renderbuffers to the given framebuffer.
14937117f1b4Smrg * This is a helper routine for device drivers when creating a
14947117f1b4Smrg * window system framebuffer (not a user-created render/framebuffer).
14957117f1b4Smrg * Once this function is called, you can basically forget about this
14967117f1b4Smrg * renderbuffer; core Mesa will handle all the buffer management and
14977117f1b4Smrg * rendering!
14987117f1b4Smrg */
14997117f1b4SmrgGLboolean
15007117f1b4Smrg_mesa_add_color_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
15017117f1b4Smrg                              GLuint rgbBits, GLuint alphaBits,
15027117f1b4Smrg                              GLboolean frontLeft, GLboolean backLeft,
15037117f1b4Smrg                              GLboolean frontRight, GLboolean backRight)
15047117f1b4Smrg{
15057117f1b4Smrg   GLuint b;
15067117f1b4Smrg
15077117f1b4Smrg   if (rgbBits > 16 || alphaBits > 16) {
15087117f1b4Smrg      _mesa_problem(ctx,
15097117f1b4Smrg                    "Unsupported bit depth in _mesa_add_color_renderbuffers");
15107117f1b4Smrg      return GL_FALSE;
15117117f1b4Smrg   }
15127117f1b4Smrg
15137117f1b4Smrg   assert(MAX_COLOR_ATTACHMENTS >= 4);
15147117f1b4Smrg
15157117f1b4Smrg   for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
15167117f1b4Smrg      struct gl_renderbuffer *rb;
15177117f1b4Smrg
15187117f1b4Smrg      if (b == BUFFER_FRONT_LEFT && !frontLeft)
15197117f1b4Smrg         continue;
15207117f1b4Smrg      else if (b == BUFFER_BACK_LEFT && !backLeft)
15217117f1b4Smrg         continue;
15227117f1b4Smrg      else if (b == BUFFER_FRONT_RIGHT && !frontRight)
15237117f1b4Smrg         continue;
15247117f1b4Smrg      else if (b == BUFFER_BACK_RIGHT && !backRight)
15257117f1b4Smrg         continue;
15267117f1b4Smrg
15277117f1b4Smrg      assert(fb->Attachment[b].Renderbuffer == NULL);
15287117f1b4Smrg
15297117f1b4Smrg      rb = _mesa_new_renderbuffer(ctx, 0);
15307117f1b4Smrg      if (!rb) {
15317117f1b4Smrg         _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer");
15327117f1b4Smrg         return GL_FALSE;
15337117f1b4Smrg      }
15347117f1b4Smrg
15357117f1b4Smrg      if (rgbBits <= 8) {
15367117f1b4Smrg         if (alphaBits)
15374a49301eSmrg            rb->Format = MESA_FORMAT_RGBA8888;
15387117f1b4Smrg         else
15394a49301eSmrg            rb->Format = MESA_FORMAT_RGB888;
15407117f1b4Smrg      }
15417117f1b4Smrg      else {
15427117f1b4Smrg         assert(rgbBits <= 16);
15434a49301eSmrg         rb->Format = MESA_FORMAT_NONE; /*XXX RGBA16;*/
15447117f1b4Smrg      }
15454a49301eSmrg      rb->InternalFormat = GL_RGBA;
15467117f1b4Smrg
15477117f1b4Smrg      rb->AllocStorage = _mesa_soft_renderbuffer_storage;
15487117f1b4Smrg      _mesa_add_renderbuffer(fb, b, rb);
15497117f1b4Smrg   }
15507117f1b4Smrg
15517117f1b4Smrg   return GL_TRUE;
15527117f1b4Smrg}
15537117f1b4Smrg
15547117f1b4Smrg
15557117f1b4Smrg/**
15567117f1b4Smrg * Add software-based alpha renderbuffers to the given framebuffer.
15577117f1b4Smrg * This is a helper routine for device drivers when creating a
15587117f1b4Smrg * window system framebuffer (not a user-created render/framebuffer).
15597117f1b4Smrg * Once this function is called, you can basically forget about this
15607117f1b4Smrg * renderbuffer; core Mesa will handle all the buffer management and
15617117f1b4Smrg * rendering!
15627117f1b4Smrg */
15637117f1b4SmrgGLboolean
15647117f1b4Smrg_mesa_add_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
15657117f1b4Smrg                              GLuint alphaBits,
15667117f1b4Smrg                              GLboolean frontLeft, GLboolean backLeft,
15677117f1b4Smrg                              GLboolean frontRight, GLboolean backRight)
15687117f1b4Smrg{
15697117f1b4Smrg   GLuint b;
15707117f1b4Smrg
15717117f1b4Smrg   /* for window system framebuffers only! */
15727117f1b4Smrg   assert(fb->Name == 0);
15737117f1b4Smrg
15747117f1b4Smrg   if (alphaBits > 8) {
15757117f1b4Smrg      _mesa_problem(ctx,
15767117f1b4Smrg                    "Unsupported bit depth in _mesa_add_alpha_renderbuffers");
15777117f1b4Smrg      return GL_FALSE;
15787117f1b4Smrg   }
15797117f1b4Smrg
15807117f1b4Smrg   assert(MAX_COLOR_ATTACHMENTS >= 4);
15817117f1b4Smrg
15827117f1b4Smrg   /* Wrap each of the RGB color buffers with an alpha renderbuffer.
15837117f1b4Smrg    */
15847117f1b4Smrg   for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
15857117f1b4Smrg      struct gl_renderbuffer *arb;
15867117f1b4Smrg
15877117f1b4Smrg      if (b == BUFFER_FRONT_LEFT && !frontLeft)
15887117f1b4Smrg         continue;
15897117f1b4Smrg      else if (b == BUFFER_BACK_LEFT && !backLeft)
15907117f1b4Smrg         continue;
15917117f1b4Smrg      else if (b == BUFFER_FRONT_RIGHT && !frontRight)
15927117f1b4Smrg         continue;
15937117f1b4Smrg      else if (b == BUFFER_BACK_RIGHT && !backRight)
15947117f1b4Smrg         continue;
15957117f1b4Smrg
15967117f1b4Smrg      /* the RGB buffer to wrap must already exist!! */
15977117f1b4Smrg      assert(fb->Attachment[b].Renderbuffer);
15987117f1b4Smrg
15997117f1b4Smrg      /* only GLubyte supported for now */
16007117f1b4Smrg      assert(fb->Attachment[b].Renderbuffer->DataType == GL_UNSIGNED_BYTE);
16017117f1b4Smrg
16027117f1b4Smrg      /* allocate alpha renderbuffer */
16037117f1b4Smrg      arb = _mesa_new_renderbuffer(ctx, 0);
16047117f1b4Smrg      if (!arb) {
16057117f1b4Smrg         _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating alpha buffer");
16067117f1b4Smrg         return GL_FALSE;
16077117f1b4Smrg      }
16087117f1b4Smrg
16097117f1b4Smrg      /* wrap the alpha renderbuffer around the RGB renderbuffer */
16107117f1b4Smrg      arb->Wrapped = fb->Attachment[b].Renderbuffer;
16117117f1b4Smrg
16127117f1b4Smrg      /* Set up my alphabuffer fields and plug in my functions.
16137117f1b4Smrg       * The functions will put/get the alpha values from/to RGBA arrays
16147117f1b4Smrg       * and then call the wrapped buffer's functions to handle the RGB
16157117f1b4Smrg       * values.
16167117f1b4Smrg       */
16177117f1b4Smrg      arb->InternalFormat = arb->Wrapped->InternalFormat;
16184a49301eSmrg      arb->Format         = MESA_FORMAT_A8;
16197117f1b4Smrg      arb->DataType       = arb->Wrapped->DataType;
16207117f1b4Smrg      arb->AllocStorage   = alloc_storage_alpha8;
16217117f1b4Smrg      arb->Delete         = delete_renderbuffer_alpha8;
16227117f1b4Smrg      arb->GetPointer     = get_pointer_alpha8;
16237117f1b4Smrg      arb->GetRow         = get_row_alpha8;
16247117f1b4Smrg      arb->GetValues      = get_values_alpha8;
16257117f1b4Smrg      arb->PutRow         = put_row_alpha8;
16267117f1b4Smrg      arb->PutRowRGB      = put_row_rgb_alpha8;
16277117f1b4Smrg      arb->PutMonoRow     = put_mono_row_alpha8;
16287117f1b4Smrg      arb->PutValues      = put_values_alpha8;
16297117f1b4Smrg      arb->PutMonoValues  = put_mono_values_alpha8;
16307117f1b4Smrg
16317117f1b4Smrg      /* clear the pointer to avoid assertion/sanity check failure later */
16327117f1b4Smrg      fb->Attachment[b].Renderbuffer = NULL;
16337117f1b4Smrg
16347117f1b4Smrg      /* plug the alpha renderbuffer into the colorbuffer attachment */
16357117f1b4Smrg      _mesa_add_renderbuffer(fb, b, arb);
16367117f1b4Smrg   }
16377117f1b4Smrg
16387117f1b4Smrg   return GL_TRUE;
16397117f1b4Smrg}
16407117f1b4Smrg
16417117f1b4Smrg
16427117f1b4Smrg/**
16437117f1b4Smrg * For framebuffers that use a software alpha channel wrapper
16447117f1b4Smrg * created by _mesa_add_alpha_renderbuffer or _mesa_add_soft_renderbuffers,
16457117f1b4Smrg * copy the back buffer alpha channel into the front buffer alpha channel.
16467117f1b4Smrg */
16477117f1b4Smrgvoid
16487117f1b4Smrg_mesa_copy_soft_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb)
16497117f1b4Smrg{
16507117f1b4Smrg   if (fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer &&
16517117f1b4Smrg       fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer)
16527117f1b4Smrg      copy_buffer_alpha8(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer,
16537117f1b4Smrg                         fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
16547117f1b4Smrg
16557117f1b4Smrg
16567117f1b4Smrg   if (fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer &&
16577117f1b4Smrg       fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer)
16587117f1b4Smrg      copy_buffer_alpha8(fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer,
16597117f1b4Smrg                         fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer);
16607117f1b4Smrg}
16617117f1b4Smrg
16627117f1b4Smrg
16637117f1b4Smrg/**
16647117f1b4Smrg * Add a software-based depth renderbuffer to the given framebuffer.
16657117f1b4Smrg * This is a helper routine for device drivers when creating a
16667117f1b4Smrg * window system framebuffer (not a user-created render/framebuffer).
16677117f1b4Smrg * Once this function is called, you can basically forget about this
16687117f1b4Smrg * renderbuffer; core Mesa will handle all the buffer management and
16697117f1b4Smrg * rendering!
16707117f1b4Smrg */
16717117f1b4SmrgGLboolean
16727117f1b4Smrg_mesa_add_depth_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
16737117f1b4Smrg                             GLuint depthBits)
16747117f1b4Smrg{
16757117f1b4Smrg   struct gl_renderbuffer *rb;
16767117f1b4Smrg
16777117f1b4Smrg   if (depthBits > 32) {
16787117f1b4Smrg      _mesa_problem(ctx,
16797117f1b4Smrg                    "Unsupported depthBits in _mesa_add_depth_renderbuffer");
16807117f1b4Smrg      return GL_FALSE;
16817117f1b4Smrg   }
16827117f1b4Smrg
16837117f1b4Smrg   assert(fb->Attachment[BUFFER_DEPTH].Renderbuffer == NULL);
16847117f1b4Smrg
16857117f1b4Smrg   rb = _mesa_new_renderbuffer(ctx, 0);
16867117f1b4Smrg   if (!rb) {
16877117f1b4Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating depth buffer");
16887117f1b4Smrg      return GL_FALSE;
16897117f1b4Smrg   }
16907117f1b4Smrg
16917117f1b4Smrg   if (depthBits <= 16) {
16924a49301eSmrg      rb->Format = MESA_FORMAT_Z16;
16934a49301eSmrg      rb->InternalFormat = GL_DEPTH_COMPONENT16;
16947117f1b4Smrg   }
16957117f1b4Smrg   else if (depthBits <= 24) {
16964a49301eSmrg      rb->Format = MESA_FORMAT_X8_Z24;
16974a49301eSmrg      rb->InternalFormat = GL_DEPTH_COMPONENT24;
16987117f1b4Smrg   }
16997117f1b4Smrg   else {
17004a49301eSmrg      rb->Format = MESA_FORMAT_Z32;
17014a49301eSmrg      rb->InternalFormat = GL_DEPTH_COMPONENT32;
17027117f1b4Smrg   }
17037117f1b4Smrg
17047117f1b4Smrg   rb->AllocStorage = _mesa_soft_renderbuffer_storage;
17057117f1b4Smrg   _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
17067117f1b4Smrg
17077117f1b4Smrg   return GL_TRUE;
17087117f1b4Smrg}
17097117f1b4Smrg
17107117f1b4Smrg
17117117f1b4Smrg/**
17127117f1b4Smrg * Add a software-based stencil renderbuffer to the given framebuffer.
17137117f1b4Smrg * This is a helper routine for device drivers when creating a
17147117f1b4Smrg * window system framebuffer (not a user-created render/framebuffer).
17157117f1b4Smrg * Once this function is called, you can basically forget about this
17167117f1b4Smrg * renderbuffer; core Mesa will handle all the buffer management and
17177117f1b4Smrg * rendering!
17187117f1b4Smrg */
17197117f1b4SmrgGLboolean
17207117f1b4Smrg_mesa_add_stencil_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
17217117f1b4Smrg                               GLuint stencilBits)
17227117f1b4Smrg{
17237117f1b4Smrg   struct gl_renderbuffer *rb;
17247117f1b4Smrg
17257117f1b4Smrg   if (stencilBits > 16) {
17267117f1b4Smrg      _mesa_problem(ctx,
17277117f1b4Smrg                  "Unsupported stencilBits in _mesa_add_stencil_renderbuffer");
17287117f1b4Smrg      return GL_FALSE;
17297117f1b4Smrg   }
17307117f1b4Smrg
17317117f1b4Smrg   assert(fb->Attachment[BUFFER_STENCIL].Renderbuffer == NULL);
17327117f1b4Smrg
17337117f1b4Smrg   rb = _mesa_new_renderbuffer(ctx, 0);
17347117f1b4Smrg   if (!rb) {
17357117f1b4Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating stencil buffer");
17367117f1b4Smrg      return GL_FALSE;
17377117f1b4Smrg   }
17387117f1b4Smrg
17394a49301eSmrg   assert(stencilBits <= 8);
17404a49301eSmrg   rb->Format = MESA_FORMAT_S8;
17414a49301eSmrg   rb->InternalFormat = GL_STENCIL_INDEX8;
17427117f1b4Smrg
17437117f1b4Smrg   rb->AllocStorage = _mesa_soft_renderbuffer_storage;
17447117f1b4Smrg   _mesa_add_renderbuffer(fb, BUFFER_STENCIL, rb);
17457117f1b4Smrg
17467117f1b4Smrg   return GL_TRUE;
17477117f1b4Smrg}
17487117f1b4Smrg
17497117f1b4Smrg
17507117f1b4Smrg/**
17517117f1b4Smrg * Add a software-based accumulation renderbuffer to the given framebuffer.
17527117f1b4Smrg * This is a helper routine for device drivers when creating a
17537117f1b4Smrg * window system framebuffer (not a user-created render/framebuffer).
17547117f1b4Smrg * Once this function is called, you can basically forget about this
17557117f1b4Smrg * renderbuffer; core Mesa will handle all the buffer management and
17567117f1b4Smrg * rendering!
17577117f1b4Smrg */
17587117f1b4SmrgGLboolean
17597117f1b4Smrg_mesa_add_accum_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
17607117f1b4Smrg                             GLuint redBits, GLuint greenBits,
17617117f1b4Smrg                             GLuint blueBits, GLuint alphaBits)
17627117f1b4Smrg{
17637117f1b4Smrg   struct gl_renderbuffer *rb;
17647117f1b4Smrg
17657117f1b4Smrg   if (redBits > 16 || greenBits > 16 || blueBits > 16 || alphaBits > 16) {
17667117f1b4Smrg      _mesa_problem(ctx,
17677117f1b4Smrg                    "Unsupported accumBits in _mesa_add_accum_renderbuffer");
17687117f1b4Smrg      return GL_FALSE;
17697117f1b4Smrg   }
17707117f1b4Smrg
17717117f1b4Smrg   assert(fb->Attachment[BUFFER_ACCUM].Renderbuffer == NULL);
17727117f1b4Smrg
17737117f1b4Smrg   rb = _mesa_new_renderbuffer(ctx, 0);
17747117f1b4Smrg   if (!rb) {
17757117f1b4Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer");
17767117f1b4Smrg      return GL_FALSE;
17777117f1b4Smrg   }
17787117f1b4Smrg
17794a49301eSmrg   rb->Format = MESA_FORMAT_SIGNED_RGBA_16;
17807117f1b4Smrg   rb->InternalFormat = GL_RGBA16;
17817117f1b4Smrg   rb->AllocStorage = _mesa_soft_renderbuffer_storage;
17827117f1b4Smrg   _mesa_add_renderbuffer(fb, BUFFER_ACCUM, rb);
17837117f1b4Smrg
17847117f1b4Smrg   return GL_TRUE;
17857117f1b4Smrg}
17867117f1b4Smrg
17877117f1b4Smrg
17887117f1b4Smrg
17897117f1b4Smrg/**
17907117f1b4Smrg * Add a software-based accumulation renderbuffer to the given framebuffer.
17917117f1b4Smrg * This is a helper routine for device drivers when creating a
17927117f1b4Smrg * window system framebuffer (not a user-created render/framebuffer).
17937117f1b4Smrg * Once this function is called, you can basically forget about this
17947117f1b4Smrg * renderbuffer; core Mesa will handle all the buffer management and
17957117f1b4Smrg * rendering!
17967117f1b4Smrg *
17977117f1b4Smrg * NOTE: color-index aux buffers not supported.
17987117f1b4Smrg */
17997117f1b4SmrgGLboolean
18007117f1b4Smrg_mesa_add_aux_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
18017117f1b4Smrg                            GLuint colorBits, GLuint numBuffers)
18027117f1b4Smrg{
18037117f1b4Smrg   GLuint i;
18047117f1b4Smrg
18057117f1b4Smrg   if (colorBits > 16) {
18067117f1b4Smrg      _mesa_problem(ctx,
18077117f1b4Smrg                    "Unsupported accumBits in _mesa_add_aux_renderbuffers");
18087117f1b4Smrg      return GL_FALSE;
18097117f1b4Smrg   }
18107117f1b4Smrg
18114a49301eSmrg   assert(numBuffers <= MAX_AUX_BUFFERS);
18127117f1b4Smrg
18137117f1b4Smrg   for (i = 0; i < numBuffers; i++) {
18147117f1b4Smrg      struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, 0);
18157117f1b4Smrg
18167117f1b4Smrg      assert(fb->Attachment[BUFFER_AUX0 + i].Renderbuffer == NULL);
18177117f1b4Smrg
18187117f1b4Smrg      if (!rb) {
18197117f1b4Smrg         _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer");
18207117f1b4Smrg         return GL_FALSE;
18217117f1b4Smrg      }
18227117f1b4Smrg
18234a49301eSmrg      assert (colorBits <= 8);
18244a49301eSmrg      rb->Format = MESA_FORMAT_RGBA8888;
18254a49301eSmrg      rb->InternalFormat = GL_RGBA;
18267117f1b4Smrg
18277117f1b4Smrg      rb->AllocStorage = _mesa_soft_renderbuffer_storage;
18287117f1b4Smrg      _mesa_add_renderbuffer(fb, BUFFER_AUX0 + i, rb);
18297117f1b4Smrg   }
18307117f1b4Smrg   return GL_TRUE;
18317117f1b4Smrg}
18327117f1b4Smrg
18337117f1b4Smrg
18347117f1b4Smrg/**
18357117f1b4Smrg * Create/attach software-based renderbuffers to the given framebuffer.
18367117f1b4Smrg * This is a helper routine for device drivers.  Drivers can just as well
18377117f1b4Smrg * call the individual _mesa_add_*_renderbuffer() routines directly.
18387117f1b4Smrg */
18397117f1b4Smrgvoid
18407117f1b4Smrg_mesa_add_soft_renderbuffers(struct gl_framebuffer *fb,
18417117f1b4Smrg                             GLboolean color,
18427117f1b4Smrg                             GLboolean depth,
18437117f1b4Smrg                             GLboolean stencil,
18447117f1b4Smrg                             GLboolean accum,
18457117f1b4Smrg                             GLboolean alpha,
18467117f1b4Smrg                             GLboolean aux)
18477117f1b4Smrg{
18487117f1b4Smrg   GLboolean frontLeft = GL_TRUE;
18497117f1b4Smrg   GLboolean backLeft = fb->Visual.doubleBufferMode;
18507117f1b4Smrg   GLboolean frontRight = fb->Visual.stereoMode;
18517117f1b4Smrg   GLboolean backRight = fb->Visual.stereoMode && fb->Visual.doubleBufferMode;
18527117f1b4Smrg
18537117f1b4Smrg   if (color) {
1854cdc920a0Smrg      assert(fb->Visual.redBits == fb->Visual.greenBits);
1855cdc920a0Smrg      assert(fb->Visual.redBits == fb->Visual.blueBits);
1856cdc920a0Smrg      _mesa_add_color_renderbuffers(NULL, fb,
1857cdc920a0Smrg				    fb->Visual.redBits,
1858cdc920a0Smrg				    fb->Visual.alphaBits,
1859cdc920a0Smrg				    frontLeft, backLeft,
1860cdc920a0Smrg				    frontRight, backRight);
18617117f1b4Smrg   }
18627117f1b4Smrg
18637117f1b4Smrg   if (depth) {
18647117f1b4Smrg      assert(fb->Visual.depthBits > 0);
18657117f1b4Smrg      _mesa_add_depth_renderbuffer(NULL, fb, fb->Visual.depthBits);
18667117f1b4Smrg   }
18677117f1b4Smrg
18687117f1b4Smrg   if (stencil) {
18697117f1b4Smrg      assert(fb->Visual.stencilBits > 0);
18707117f1b4Smrg      _mesa_add_stencil_renderbuffer(NULL, fb, fb->Visual.stencilBits);
18717117f1b4Smrg   }
18727117f1b4Smrg
18737117f1b4Smrg   if (accum) {
18747117f1b4Smrg      assert(fb->Visual.accumRedBits > 0);
18757117f1b4Smrg      assert(fb->Visual.accumGreenBits > 0);
18767117f1b4Smrg      assert(fb->Visual.accumBlueBits > 0);
18777117f1b4Smrg      _mesa_add_accum_renderbuffer(NULL, fb,
18787117f1b4Smrg                                   fb->Visual.accumRedBits,
18797117f1b4Smrg                                   fb->Visual.accumGreenBits,
18807117f1b4Smrg                                   fb->Visual.accumBlueBits,
18817117f1b4Smrg                                   fb->Visual.accumAlphaBits);
18827117f1b4Smrg   }
18837117f1b4Smrg
18847117f1b4Smrg   if (aux) {
18857117f1b4Smrg      assert(fb->Visual.numAuxBuffers > 0);
18867117f1b4Smrg      _mesa_add_aux_renderbuffers(NULL, fb, fb->Visual.redBits,
18877117f1b4Smrg                                  fb->Visual.numAuxBuffers);
18887117f1b4Smrg   }
18897117f1b4Smrg
18907117f1b4Smrg   if (alpha) {
18917117f1b4Smrg      assert(fb->Visual.alphaBits > 0);
18927117f1b4Smrg      _mesa_add_alpha_renderbuffers(NULL, fb, fb->Visual.alphaBits,
18937117f1b4Smrg                                    frontLeft, backLeft,
18947117f1b4Smrg                                    frontRight, backRight);
18957117f1b4Smrg   }
18967117f1b4Smrg
18977117f1b4Smrg#if 0
18987117f1b4Smrg   if (multisample) {
18997117f1b4Smrg      /* maybe someday */
19007117f1b4Smrg   }
19017117f1b4Smrg#endif
19027117f1b4Smrg}
19037117f1b4Smrg
19047117f1b4Smrg
19057117f1b4Smrg/**
19067117f1b4Smrg * Attach a renderbuffer to a framebuffer.
19077117f1b4Smrg */
19087117f1b4Smrgvoid
19097117f1b4Smrg_mesa_add_renderbuffer(struct gl_framebuffer *fb,
19107117f1b4Smrg                       GLuint bufferName, struct gl_renderbuffer *rb)
19117117f1b4Smrg{
19124a49301eSmrg   GLenum baseFormat;
19134a49301eSmrg
19147117f1b4Smrg   assert(fb);
19157117f1b4Smrg   assert(rb);
19167117f1b4Smrg   assert(bufferName < BUFFER_COUNT);
19177117f1b4Smrg
19187117f1b4Smrg   /* There should be no previous renderbuffer on this attachment point,
19197117f1b4Smrg    * with the exception of depth/stencil since the same renderbuffer may
19207117f1b4Smrg    * be used for both.
19217117f1b4Smrg    */
19227117f1b4Smrg   assert(bufferName == BUFFER_DEPTH ||
19237117f1b4Smrg          bufferName == BUFFER_STENCIL ||
19247117f1b4Smrg          fb->Attachment[bufferName].Renderbuffer == NULL);
19257117f1b4Smrg
19267117f1b4Smrg   /* winsys vs. user-created buffer cross check */
19277117f1b4Smrg   if (fb->Name) {
19287117f1b4Smrg      assert(rb->Name);
19297117f1b4Smrg   }
19307117f1b4Smrg   else {
19317117f1b4Smrg      assert(!rb->Name);
19327117f1b4Smrg   }
19337117f1b4Smrg
19347117f1b4Smrg   /* If Mesa's compiled with deep color channels (16 or 32 bits / channel)
19357117f1b4Smrg    * and the device driver is expecting 8-bit values (GLubyte), we can
19367117f1b4Smrg    * use a "renderbuffer adaptor/wrapper" to do the necessary conversions.
19377117f1b4Smrg    */
19384a49301eSmrg   baseFormat = _mesa_get_format_base_format(rb->Format);
19394a49301eSmrg   if (baseFormat == GL_RGBA) {
19407117f1b4Smrg      if (CHAN_BITS == 16 && rb->DataType == GL_UNSIGNED_BYTE) {
19417117f1b4Smrg         GET_CURRENT_CONTEXT(ctx);
19427117f1b4Smrg         rb = _mesa_new_renderbuffer_16wrap8(ctx, rb);
19437117f1b4Smrg      }
19447117f1b4Smrg      else if (CHAN_BITS == 32 && rb->DataType == GL_UNSIGNED_BYTE) {
19457117f1b4Smrg         GET_CURRENT_CONTEXT(ctx);
19467117f1b4Smrg         rb = _mesa_new_renderbuffer_32wrap8(ctx, rb);
19477117f1b4Smrg      }
19487117f1b4Smrg      else if (CHAN_BITS == 32 && rb->DataType == GL_UNSIGNED_SHORT) {
19497117f1b4Smrg         GET_CURRENT_CONTEXT(ctx);
19507117f1b4Smrg         rb = _mesa_new_renderbuffer_32wrap16(ctx, rb);
19517117f1b4Smrg      }
19527117f1b4Smrg   }
19537117f1b4Smrg
19547117f1b4Smrg   fb->Attachment[bufferName].Type = GL_RENDERBUFFER_EXT;
19557117f1b4Smrg   fb->Attachment[bufferName].Complete = GL_TRUE;
19567117f1b4Smrg   _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer, rb);
19577117f1b4Smrg}
19587117f1b4Smrg
19597117f1b4Smrg
19607117f1b4Smrg/**
19617117f1b4Smrg * Remove the named renderbuffer from the given framebuffer.
19627117f1b4Smrg */
19637117f1b4Smrgvoid
19647117f1b4Smrg_mesa_remove_renderbuffer(struct gl_framebuffer *fb, GLuint bufferName)
19657117f1b4Smrg{
19667117f1b4Smrg   struct gl_renderbuffer *rb;
19677117f1b4Smrg
19687117f1b4Smrg   assert(bufferName < BUFFER_COUNT);
19697117f1b4Smrg
19707117f1b4Smrg   rb = fb->Attachment[bufferName].Renderbuffer;
19717117f1b4Smrg   if (!rb)
19727117f1b4Smrg      return;
19737117f1b4Smrg
19747117f1b4Smrg   _mesa_reference_renderbuffer(&rb, NULL);
19757117f1b4Smrg
19767117f1b4Smrg   fb->Attachment[bufferName].Renderbuffer = NULL;
19777117f1b4Smrg}
19787117f1b4Smrg
19797117f1b4Smrg
19807117f1b4Smrg/**
19817117f1b4Smrg * Set *ptr to point to rb.  If *ptr points to another renderbuffer,
19827117f1b4Smrg * dereference that buffer first.  The new renderbuffer's refcount will
19837117f1b4Smrg * be incremented.  The old renderbuffer's refcount will be decremented.
19847117f1b4Smrg */
19857117f1b4Smrgvoid
19867117f1b4Smrg_mesa_reference_renderbuffer(struct gl_renderbuffer **ptr,
19877117f1b4Smrg                             struct gl_renderbuffer *rb)
19887117f1b4Smrg{
19897117f1b4Smrg   assert(ptr);
19907117f1b4Smrg   if (*ptr == rb) {
19917117f1b4Smrg      /* no change */
19927117f1b4Smrg      return;
19937117f1b4Smrg   }
19947117f1b4Smrg
19957117f1b4Smrg   if (*ptr) {
19967117f1b4Smrg      /* Unreference the old renderbuffer */
19977117f1b4Smrg      GLboolean deleteFlag = GL_FALSE;
19987117f1b4Smrg      struct gl_renderbuffer *oldRb = *ptr;
19997117f1b4Smrg
20007117f1b4Smrg      assert(oldRb->Magic == RB_MAGIC);
20017117f1b4Smrg      _glthread_LOCK_MUTEX(oldRb->Mutex);
20027117f1b4Smrg      assert(oldRb->Magic == RB_MAGIC);
20037117f1b4Smrg      ASSERT(oldRb->RefCount > 0);
20047117f1b4Smrg      oldRb->RefCount--;
20057117f1b4Smrg      /*printf("RB DECR %p (%d) to %d\n", (void*) oldRb, oldRb->Name, oldRb->RefCount);*/
20067117f1b4Smrg      deleteFlag = (oldRb->RefCount == 0);
20077117f1b4Smrg      _glthread_UNLOCK_MUTEX(oldRb->Mutex);
20087117f1b4Smrg
20097117f1b4Smrg      if (deleteFlag) {
20107117f1b4Smrg         oldRb->Magic = 0; /* now invalid memory! */
20117117f1b4Smrg         oldRb->Delete(oldRb);
20127117f1b4Smrg      }
20137117f1b4Smrg
20147117f1b4Smrg      *ptr = NULL;
20157117f1b4Smrg   }
20167117f1b4Smrg   assert(!*ptr);
20177117f1b4Smrg
20187117f1b4Smrg   if (rb) {
20197117f1b4Smrg      assert(rb->Magic == RB_MAGIC);
20207117f1b4Smrg      /* reference new renderbuffer */
20217117f1b4Smrg      _glthread_LOCK_MUTEX(rb->Mutex);
20227117f1b4Smrg      rb->RefCount++;
20237117f1b4Smrg      /*printf("RB INCR %p (%d) to %d\n", (void*) rb, rb->Name, rb->RefCount);*/
20247117f1b4Smrg      _glthread_UNLOCK_MUTEX(rb->Mutex);
20257117f1b4Smrg      *ptr = rb;
20267117f1b4Smrg   }
20277117f1b4Smrg}
20287117f1b4Smrg
20297117f1b4Smrg
20307117f1b4Smrg/**
20317117f1b4Smrg * Create a new combined depth/stencil renderbuffer for implementing
20327117f1b4Smrg * the GL_EXT_packed_depth_stencil extension.
20337117f1b4Smrg * \return new depth/stencil renderbuffer
20347117f1b4Smrg */
20357117f1b4Smrgstruct gl_renderbuffer *
20367117f1b4Smrg_mesa_new_depthstencil_renderbuffer(GLcontext *ctx, GLuint name)
20377117f1b4Smrg{
20387117f1b4Smrg   struct gl_renderbuffer *dsrb;
20397117f1b4Smrg
20407117f1b4Smrg   dsrb = _mesa_new_renderbuffer(ctx, name);
20417117f1b4Smrg   if (!dsrb)
20427117f1b4Smrg      return NULL;
20437117f1b4Smrg
20447117f1b4Smrg   /* init fields not covered by _mesa_new_renderbuffer() */
20457117f1b4Smrg   dsrb->InternalFormat = GL_DEPTH24_STENCIL8_EXT;
20464a49301eSmrg   dsrb->Format = MESA_FORMAT_Z24_S8;
20477117f1b4Smrg   dsrb->AllocStorage = _mesa_soft_renderbuffer_storage;
20487117f1b4Smrg
20497117f1b4Smrg   return dsrb;
20507117f1b4Smrg}
2051