merge of glsl-compiler-1 branch
[mesa.git] / src / mesa / main / renderbuffer.c
index 4ebaa1f6118b49d3dbfda87625b36e5d1a63c23f..49706b52516405b04e7e8648c6328a4c13446dfd 100644 (file)
@@ -2,7 +2,7 @@
  * Mesa 3-D graphics library
  * Version:  6.5
  *
- * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -47,6 +47,8 @@
 #include "fbobject.h"
 #include "renderbuffer.h"
 
+#include "rbadaptors.h"
+
 
 /* 32-bit color index format.  Not a public format. */
 #define COLOR_INDEX32 0x424243
@@ -70,6 +72,9 @@ get_pointer_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb,
    if (!rb->Data)
       return NULL;
    ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+   /* Can't assert _ActualFormat since these funcs may be used for serveral
+    * different formats (GL_ALPHA8, GL_STENCIL_INDEX8, etc).
+    */
    return (GLubyte *) rb->Data + y * rb->Width + x;
 }
 
@@ -90,7 +95,7 @@ get_values_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
 {
    GLubyte *dst = (GLubyte *) values;
    GLuint i;
-   assert(rb->DataType == GL_UNSIGNED_BYTE);
+   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
    for (i = 0; i < count; i++) {
       const GLubyte *src = (GLubyte *) rb->Data + y[i] * rb->Width + x[i];
       dst[i] = *src;
@@ -104,7 +109,7 @@ put_row_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
 {
    const GLubyte *src = (const GLubyte *) values;
    GLubyte *dst = (GLubyte *) rb->Data + y * rb->Width + x;
-   assert(rb->DataType == GL_UNSIGNED_BYTE);
+   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
    if (mask) {
       GLuint i;
       for (i = 0; i < count; i++) {
@@ -125,7 +130,7 @@ put_mono_row_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
 {
    const GLubyte val = *((const GLubyte *) value);
    GLubyte *dst = (GLubyte *) rb->Data + y * rb->Width + x;
-   assert(rb->DataType == GL_UNSIGNED_BYTE);
+   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
    if (mask) {
       GLuint i;
       for (i = 0; i < count; i++) {
@@ -150,7 +155,7 @@ put_values_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
 {
    const GLubyte *src = (const GLubyte *) values;
    GLuint i;
-   assert(rb->DataType == GL_UNSIGNED_BYTE);
+   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
    for (i = 0; i < count; i++) {
       if (!mask || mask[i]) {
          GLubyte *dst = (GLubyte *) rb->Data + y[i] * rb->Width + x[i];
@@ -167,7 +172,7 @@ put_mono_values_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
 {
    const GLubyte val = *((const GLubyte *) value);
    GLuint i;
-   assert(rb->DataType == GL_UNSIGNED_BYTE);
+   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
    for (i = 0; i < count; i++) {
       if (!mask || mask[i]) {
          GLubyte *dst = (GLubyte *) rb->Data + y[i] * rb->Width + x[i];
@@ -313,11 +318,12 @@ put_mono_values_ushort(GLcontext *ctx, struct gl_renderbuffer *rb,
 
 static void *
 get_pointer_uint(GLcontext *ctx, struct gl_renderbuffer *rb,
-                    GLint x, GLint y)
+                 GLint x, GLint y)
 {
    if (!rb->Data)
       return NULL;
-   ASSERT(rb->DataType == GL_UNSIGNED_INT);
+   ASSERT(rb->DataType == GL_UNSIGNED_INT ||
+          rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
    return (GLuint *) rb->Data + y * rb->Width + x;
 }
 
@@ -327,7 +333,8 @@ get_row_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
              GLint x, GLint y, void *values)
 {
    const void *src = rb->GetPointer(ctx, rb, x, y);
-   ASSERT(rb->DataType == GL_UNSIGNED_INT);
+   ASSERT(rb->DataType == GL_UNSIGNED_INT ||
+          rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
    _mesa_memcpy(values, src, count * sizeof(GLuint));
 }
 
@@ -338,7 +345,8 @@ get_values_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
 {
    GLuint *dst = (GLuint *) values;
    GLuint i;
-   ASSERT(rb->DataType == GL_UNSIGNED_INT);
+   ASSERT(rb->DataType == GL_UNSIGNED_INT ||
+          rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
    for (i = 0; i < count; i++) {
       const GLuint *src = (GLuint *) rb->Data + y[i] * rb->Width + x[i];
       dst[i] = *src;
@@ -352,7 +360,8 @@ put_row_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
 {
    const GLuint *src = (const GLuint *) values;
    GLuint *dst = (GLuint *) rb->Data + y * rb->Width + x;
-   ASSERT(rb->DataType == GL_UNSIGNED_INT);
+   ASSERT(rb->DataType == GL_UNSIGNED_INT ||
+          rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
    if (mask) {
       GLuint i;
       for (i = 0; i < count; i++) {
@@ -373,7 +382,8 @@ put_mono_row_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
 {
    const GLuint val = *((const GLuint *) value);
    GLuint *dst = (GLuint *) rb->Data + y * rb->Width + x;
-   ASSERT(rb->DataType == GL_UNSIGNED_INT);
+   ASSERT(rb->DataType == GL_UNSIGNED_INT ||
+          rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
    if (mask) {
       GLuint i;
       for (i = 0; i < count; i++) {
@@ -398,7 +408,8 @@ put_values_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
 {
    const GLuint *src = (const GLuint *) values;
    GLuint i;
-   ASSERT(rb->DataType == GL_UNSIGNED_INT);
+   ASSERT(rb->DataType == GL_UNSIGNED_INT ||
+          rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
    for (i = 0; i < count; i++) {
       if (!mask || mask[i]) {
          GLuint *dst = (GLuint *) rb->Data + y[i] * rb->Width + x[i];
@@ -415,7 +426,8 @@ put_mono_values_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
 {
    const GLuint val = *((const GLuint *) value);
    GLuint i;
-   ASSERT(rb->DataType == GL_UNSIGNED_INT);
+   ASSERT(rb->DataType == GL_UNSIGNED_INT ||
+          rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
    for (i = 0; i < count; i++) {
       if (!mask || mask[i]) {
          GLuint *dst = (GLuint *) rb->Data + y[i] * rb->Width + x[i];
@@ -436,6 +448,7 @@ static void *
 get_pointer_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb,
                    GLint x, GLint y)
 {
+   ASSERT(rb->_ActualFormat == GL_RGB8);
    /* No direct access since this buffer is RGB but caller will be
     * treating it as if it were RGBA.
     */
@@ -450,6 +463,7 @@ get_row_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
    const GLubyte *src = (const GLubyte *) rb->Data + 3 * (y * rb->Width + x);
    GLubyte *dst = (GLubyte *) values;
    GLuint i;
+   ASSERT(rb->_ActualFormat == GL_RGB8);
    ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
    for (i = 0; i < count; i++) {
       dst[i * 4 + 0] = src[i * 3 + 0];
@@ -466,7 +480,8 @@ get_values_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
 {
    GLubyte *dst = (GLubyte *) values;
    GLuint i;
-   assert(rb->DataType == GL_UNSIGNED_BYTE);
+   ASSERT(rb->_ActualFormat == GL_RGB8);
+   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
    for (i = 0; i < count; i++) {
       const GLubyte *src
          = (GLubyte *) rb->Data + 3 * (y[i] * rb->Width + x[i]);
@@ -486,7 +501,8 @@ put_row_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
    const GLubyte *src = (const GLubyte *) values;
    GLubyte *dst = (GLubyte *) rb->Data + 3 * (y * rb->Width + x);
    GLuint i;
-   assert(rb->DataType == GL_UNSIGNED_BYTE);
+   ASSERT(rb->_ActualFormat == GL_RGB8);
+   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
    for (i = 0; i < count; i++) {
       if (!mask || mask[i]) {
          dst[i * 3 + 0] = src[i * 4 + 0];
@@ -505,7 +521,8 @@ put_row_rgb_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
    const GLubyte *src = (const GLubyte *) values;
    GLubyte *dst = (GLubyte *) rb->Data + 3 * (y * rb->Width + x);
    GLuint i;
-   assert(rb->DataType == GL_UNSIGNED_BYTE);
+   ASSERT(rb->_ActualFormat == GL_RGB8);
+   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
    for (i = 0; i < count; i++) {
       if (!mask || mask[i]) {
          dst[i * 3 + 0] = src[i * 3 + 0];
@@ -525,7 +542,8 @@ put_mono_row_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
    const GLubyte val1 = ((const GLubyte *) value)[1];
    const GLubyte val2 = ((const GLubyte *) value)[2];
    GLubyte *dst = (GLubyte *) rb->Data + 3 * (y * rb->Width + x);
-   assert(rb->DataType == GL_UNSIGNED_BYTE);
+   ASSERT(rb->_ActualFormat == GL_RGB8);
+   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
    if (!mask && val0 == val1 && val1 == val2) {
       /* optimized case */
       _mesa_memset(dst, val0, 3 * count);
@@ -551,7 +569,8 @@ put_values_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
    /* note: incoming values are RGB+A! */
    const GLubyte *src = (const GLubyte *) values;
    GLuint i;
-   assert(rb->DataType == GL_UNSIGNED_BYTE);
+   ASSERT(rb->_ActualFormat == GL_RGB8);
+   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
    for (i = 0; i < count; i++) {
       if (!mask || mask[i]) {
          GLubyte *dst = (GLubyte *) rb->Data + 3 * (y[i] * rb->Width + x[i]);
@@ -573,7 +592,8 @@ put_mono_values_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb,
    const GLubyte val1 = ((const GLubyte *) value)[1];
    const GLubyte val2 = ((const GLubyte *) value)[2];
    GLuint i;
-   assert(rb->DataType == GL_UNSIGNED_BYTE);
+   ASSERT(rb->_ActualFormat == GL_RGB8);
+   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
    for (i = 0; i < count; i++) {
       if (!mask || mask[i]) {
          GLubyte *dst = (GLubyte *) rb->Data + 3 * (y[i] * rb->Width + x[i]);
@@ -597,6 +617,7 @@ get_pointer_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb,
    if (!rb->Data)
       return NULL;
    ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+   ASSERT(rb->_ActualFormat == GL_RGBA8);
    return (GLubyte *) rb->Data + 4 * (y * rb->Width + x);
 }
 
@@ -605,9 +626,10 @@ static void
 get_row_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
                GLint x, GLint y, void *values)
 {
-   const GLbyte *src = (const GLbyte *) rb->Data + 4 * (y * rb->Width + x);
+   const GLubyte *src = (const GLubyte *) rb->Data + 4 * (y * rb->Width + x);
    ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
-   _mesa_memcpy(values, src, 4 * count * sizeof(GLbyte));
+   ASSERT(rb->_ActualFormat == GL_RGBA8);
+   _mesa_memcpy(values, src, 4 * count * sizeof(GLubyte));
 }
 
 
@@ -618,7 +640,8 @@ get_values_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
    /* treat 4*GLubyte as 1*GLuint */
    GLuint *dst = (GLuint *) values;
    GLuint i;
-   assert(rb->DataType == GL_UNSIGNED_BYTE);
+   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+   ASSERT(rb->_ActualFormat == GL_RGBA8);
    for (i = 0; i < count; i++) {
       const GLuint *src = (GLuint *) rb->Data + (y[i] * rb->Width + x[i]);
       dst[i] = *src;
@@ -633,7 +656,8 @@ put_row_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
    /* treat 4*GLubyte as 1*GLuint */
    const GLuint *src = (const GLuint *) values;
    GLuint *dst = (GLuint *) rb->Data + (y * rb->Width + x);
-   assert(rb->DataType == GL_UNSIGNED_BYTE);
+   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+   ASSERT(rb->_ActualFormat == GL_RGBA8);
    if (mask) {
       GLuint i;
       for (i = 0; i < count; i++) {
@@ -656,7 +680,8 @@ put_row_rgb_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
    const GLubyte *src = (const GLubyte *) values;
    GLubyte *dst = (GLubyte *) rb->Data + 4 * (y * rb->Width + x);
    GLuint i;
-   assert(rb->DataType == GL_UNSIGNED_BYTE);
+   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+   ASSERT(rb->_ActualFormat == GL_RGBA8);
    for (i = 0; i < count; i++) {
       if (!mask || mask[i]) {
          dst[i * 4 + 0] = src[i * 3 + 0];
@@ -675,7 +700,8 @@ put_mono_row_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
    /* treat 4*GLubyte as 1*GLuint */
    const GLuint val = *((const GLuint *) value);
    GLuint *dst = (GLuint *) rb->Data + (y * rb->Width + x);
-   assert(rb->DataType == GL_UNSIGNED_BYTE);
+   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+   ASSERT(rb->_ActualFormat == GL_RGBA8);
    if (!mask && val == 0) {
       /* common case */
       _mesa_bzero(dst, count * 4 * sizeof(GLubyte));
@@ -708,7 +734,8 @@ put_values_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
    /* treat 4*GLubyte as 1*GLuint */
    const GLuint *src = (const GLuint *) values;
    GLuint i;
-   assert(rb->DataType == GL_UNSIGNED_BYTE);
+   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+   ASSERT(rb->_ActualFormat == GL_RGBA8);
    for (i = 0; i < count; i++) {
       if (!mask || mask[i]) {
          GLuint *dst = (GLuint *) rb->Data + (y[i] * rb->Width + x[i]);
@@ -726,7 +753,8 @@ put_mono_values_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb,
    /* treat 4*GLubyte as 1*GLuint */
    const GLuint val = *((const GLuint *) value);
    GLuint i;
-   assert(rb->DataType == GL_UNSIGNED_BYTE);
+   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+   ASSERT(rb->_ActualFormat == GL_RGBA8);
    for (i = 0; i < count; i++) {
       if (!mask || mask[i]) {
          GLuint *dst = (GLuint *) rb->Data + (y[i] * rb->Width + x[i]);
@@ -912,12 +940,22 @@ put_mono_values_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb,
  * This function also plugs in the appropriate GetPointer, Get/PutRow and
  * Get/PutValues functions.
  */
-static GLboolean
-soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
-                          GLenum internalFormat, GLuint width, GLuint height)
+GLboolean
+_mesa_soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
+                                GLenum internalFormat,
+                                GLuint width, GLuint height)
 {
    GLuint pixelSize;
 
+   /* first clear these fields */
+   rb->RedBits =
+   rb->GreenBits =
+   rb->BlueBits =
+   rb->AlphaBits =
+   rb->IndexBits =
+   rb->DepthBits =
+   rb->StencilBits = 0;
+
    switch (internalFormat) {
    case GL_RGB:
    case GL_R3_G3_B2:
@@ -927,6 +965,7 @@ soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
    case GL_RGB10:
    case GL_RGB12:
    case GL_RGB16:
+      rb->_ActualFormat = GL_RGB8;
       rb->_BaseFormat = GL_RGB;
       rb->DataType = GL_UNSIGNED_BYTE;
       rb->GetPointer = get_pointer_ubyte3;
@@ -948,6 +987,7 @@ soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
    case GL_RGBA4:
    case GL_RGB5_A1:
    case GL_RGBA8:
+      rb->_ActualFormat = GL_RGBA8;
       rb->_BaseFormat = GL_RGBA;
       rb->DataType = GL_UNSIGNED_BYTE;
       rb->GetPointer = get_pointer_ubyte4;
@@ -967,6 +1007,7 @@ soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
    case GL_RGB10_A2:
    case GL_RGBA12:
    case GL_RGBA16:
+      rb->_ActualFormat = GL_RGBA16;
       rb->_BaseFormat = GL_RGBA;
       rb->DataType = GL_UNSIGNED_SHORT;
       rb->GetPointer = get_pointer_ushort4;
@@ -984,7 +1025,8 @@ soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
       pixelSize = 4 * sizeof(GLushort);
       break;
 #if 00
-   case ALPHA8:
+   case GL_ALPHA8:
+      rb->_ActualFormat = GL_ALPHA8;
       rb->_BaseFormat = GL_RGBA; /* Yes, not GL_ALPHA! */
       rb->DataType = GL_UNSIGNED_BYTE;
       rb->GetPointer = get_pointer_alpha8;
@@ -1006,6 +1048,7 @@ soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
    case GL_STENCIL_INDEX1_EXT:
    case GL_STENCIL_INDEX4_EXT:
    case GL_STENCIL_INDEX8_EXT:
+      rb->_ActualFormat = GL_STENCIL_INDEX8_EXT;
       rb->_BaseFormat = GL_STENCIL_INDEX;
       rb->DataType = GL_UNSIGNED_BYTE;
       rb->GetPointer = get_pointer_ubyte;
@@ -1020,6 +1063,7 @@ soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
       pixelSize = sizeof(GLubyte);
       break;
    case GL_STENCIL_INDEX16_EXT:
+      rb->_ActualFormat = GL_STENCIL_INDEX16_EXT;
       rb->_BaseFormat = GL_STENCIL_INDEX;
       rb->DataType = GL_UNSIGNED_SHORT;
       rb->GetPointer = get_pointer_ushort;
@@ -1035,6 +1079,7 @@ soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
       break;
    case GL_DEPTH_COMPONENT:
    case GL_DEPTH_COMPONENT16:
+      rb->_ActualFormat = GL_DEPTH_COMPONENT16;
       rb->_BaseFormat = GL_DEPTH_COMPONENT;
       rb->DataType = GL_UNSIGNED_SHORT;
       rb->GetPointer = get_pointer_ushort;
@@ -1060,10 +1105,35 @@ soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
       rb->PutMonoRow = put_mono_row_uint;
       rb->PutValues = put_values_uint;
       rb->PutMonoValues = put_mono_values_uint;
-      rb->DepthBits = 8 * sizeof(GLuint);
+      if (internalFormat == GL_DEPTH_COMPONENT24) {
+         rb->_ActualFormat = GL_DEPTH_COMPONENT24;
+         rb->DepthBits = 24;
+      }
+      else {
+         rb->_ActualFormat = GL_DEPTH_COMPONENT32;
+         rb->DepthBits = 32;
+      }
+      pixelSize = sizeof(GLuint);
+      break;
+   case GL_DEPTH_STENCIL_EXT:
+   case GL_DEPTH24_STENCIL8_EXT:
+      rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
+      rb->_BaseFormat = GL_DEPTH_STENCIL_EXT;
+      rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
+      rb->GetPointer = get_pointer_uint;
+      rb->GetRow = get_row_uint;
+      rb->GetValues = get_values_uint;
+      rb->PutRow = put_row_uint;
+      rb->PutRowRGB = NULL;
+      rb->PutMonoRow = put_mono_row_uint;
+      rb->PutValues = put_values_uint;
+      rb->PutMonoValues = put_mono_values_uint;
+      rb->DepthBits = 24;
+      rb->StencilBits = 8;
       pixelSize = sizeof(GLuint);
       break;
    case GL_COLOR_INDEX8_EXT:
+      rb->_ActualFormat = GL_COLOR_INDEX8_EXT;
       rb->_BaseFormat = GL_COLOR_INDEX;
       rb->DataType = GL_UNSIGNED_BYTE;
       rb->GetPointer = get_pointer_ubyte;
@@ -1078,6 +1148,7 @@ soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
       pixelSize = sizeof(GLubyte);
       break;
    case GL_COLOR_INDEX16_EXT:
+      rb->_ActualFormat = GL_COLOR_INDEX16_EXT;
       rb->_BaseFormat = GL_COLOR_INDEX;
       rb->DataType = GL_UNSIGNED_SHORT;
       rb->GetPointer = get_pointer_ushort;
@@ -1092,6 +1163,7 @@ soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
       pixelSize = sizeof(GLushort);
       break;
    case COLOR_INDEX32:
+      rb->_ActualFormat = COLOR_INDEX32;
       rb->_BaseFormat = GL_COLOR_INDEX;
       rb->DataType = GL_UNSIGNED_INT;
       rb->GetPointer = get_pointer_uint;
@@ -1106,7 +1178,7 @@ soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
       pixelSize = sizeof(GLuint);
       break;
    default:
-      _mesa_problem(ctx, "Bad internalFormat in soft_renderbuffer_storage");
+      _mesa_problem(ctx, "Bad internalFormat in _mesa_soft_renderbuffer_storage");
       return GL_FALSE;
    }
 
@@ -1120,73 +1192,75 @@ soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
    ASSERT(rb->PutMonoValues);
 
    /* free old buffer storage */
-   if (rb->Data)
+   if (rb->Data) {
       _mesa_free(rb->Data);
-
-   /* allocate new buffer storage */
-   rb->Data = _mesa_malloc(width * height * pixelSize);
-   if (rb->Data == NULL) {
-      rb->Width = 0;
-      rb->Height = 0;
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "software renderbuffer allocation");
-      return GL_FALSE;
+      rb->Data = NULL;
+   }
+
+   if (width > 0 && height > 0) {
+      /* allocate new buffer storage */
+      rb->Data = _mesa_malloc(width * height * pixelSize);
+      if (rb->Data == NULL) {
+         rb->Width = 0;
+         rb->Height = 0;
+         _mesa_error(ctx, GL_OUT_OF_MEMORY,
+                     "software renderbuffer allocation (%d x %d x %d)",
+                     width, height, pixelSize);
+         return GL_FALSE;
+      }
    }
 
    rb->Width = width;
    rb->Height = height;
-   rb->InternalFormat = internalFormat;
 
    return GL_TRUE;
 }
 
 
+
 /**********************************************************************/
 /**********************************************************************/
 /**********************************************************************/
 
 
 /**
- * The alpha_renderbuffer class is used to augment an RGB renderbuffer with
- * an alpha channel.  The RGB buffer can be hardware-based.
- * We basically wrap the RGB buffer.  When PutRow is called (for example),
- * we store the alpha values in this buffer, then pass on the PutRow call
- * to the wrapped RGB buffer.
+ * Here we utilize the gl_renderbuffer->Wrapper field to put an alpha
+ * buffer wrapper around an existing RGB renderbuffer (hw or sw).
+ *
+ * When PutRow is called (for example), we store the alpha values in
+ * this buffer, then pass on the PutRow call to the wrapped RGB
+ * buffer.
  */
-struct alpha_renderbuffer
-{
-   struct gl_renderbuffer Base;        /* the alpha buffer */
-   struct gl_renderbuffer *RGBbuffer;  /* the wrapped RGB buffer */
-};
 
 
 static GLboolean
-alloc_storage_alpha8(GLcontext *ctx, struct gl_renderbuffer *rb,
+alloc_storage_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb,
                      GLenum internalFormat, GLuint width, GLuint height)
 {
-   struct alpha_renderbuffer *arb = (struct alpha_renderbuffer *) rb;
+   ASSERT(arb != arb->Wrapped);
+   ASSERT(arb->_ActualFormat == GL_ALPHA8);
 
    /* first, pass the call to the wrapped RGB buffer */
-   if (!arb->RGBbuffer->AllocStorage(ctx, arb->RGBbuffer, internalFormat,
-                                     width, height)) {
+   if (!arb->Wrapped->AllocStorage(ctx, arb->Wrapped, internalFormat,
+                                  width, height)) {
       return GL_FALSE;
    }
 
    /* next, resize my alpha buffer */
-   if (arb->Base.Data) {
-      _mesa_free(arb->Base.Data);
+   if (arb->Data) {
+      _mesa_free(arb->Data);
    }
 
-   arb->Base.Data = _mesa_malloc(width * height * sizeof(GLubyte));
-   if (arb->Base.Data == NULL) {
-      arb->Base.Width = 0;
-      arb->Base.Height = 0;
+   arb->Data = _mesa_malloc(width * height * sizeof(GLubyte));
+   if (arb->Data == NULL) {
+      arb->Width = 0;
+      arb->Height = 0;
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "software alpha buffer allocation");
       return GL_FALSE;
    }
 
-   arb->Base.Width = width;
-   arb->Base.Height = height;
-   arb->Base.InternalFormat = internalFormat;
+   arb->Width = width;
+   arb->Height = height;
 
    return GL_TRUE;
 }
@@ -1196,21 +1270,21 @@ alloc_storage_alpha8(GLcontext *ctx, struct gl_renderbuffer *rb,
  * Delete an alpha_renderbuffer object, as well as the wrapped RGB buffer.
  */
 static void
-delete_renderbuffer_alpha8(struct gl_renderbuffer *rb)
+delete_renderbuffer_alpha8(struct gl_renderbuffer *arb)
 {
-   struct alpha_renderbuffer *arb = (struct alpha_renderbuffer *) rb;
-   if (arb->Base.Data) {
-      _mesa_free(arb->Base.Data);
+   if (arb->Data) {
+      _mesa_free(arb->Data);
    }
-   assert(arb->RGBbuffer);
-   arb->RGBbuffer->Delete(arb->RGBbuffer);
-   arb->RGBbuffer = NULL;
+   ASSERT(arb->Wrapped);
+   ASSERT(arb != arb->Wrapped);
+   arb->Wrapped->Delete(arb->Wrapped);
+   arb->Wrapped = NULL;
    _mesa_free(arb);
 }
 
 
 static void *
-get_pointer_alpha8(GLcontext *ctx, struct gl_renderbuffer *rb,
+get_pointer_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb,
                    GLint x, GLint y)
 {
    return NULL;   /* don't allow direct access! */
@@ -1218,17 +1292,17 @@ get_pointer_alpha8(GLcontext *ctx, struct gl_renderbuffer *rb,
 
 
 static void
-get_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+get_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
                GLint x, GLint y, void *values)
 {
    /* NOTE: 'values' is RGBA format! */
-   struct alpha_renderbuffer *arb = (struct alpha_renderbuffer *) rb;
-   const GLubyte *src = (const GLubyte *) rb->Data + y * rb->Width + x;
+   const GLubyte *src = (const GLubyte *) arb->Data + y * arb->Width + x;
    GLubyte *dst = (GLubyte *) values;
    GLuint i;
-   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+   ASSERT(arb != arb->Wrapped);
+   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
    /* first, pass the call to the wrapped RGB buffer */
-   arb->RGBbuffer->GetRow(ctx, arb->RGBbuffer, count, x, y, values);
+   arb->Wrapped->GetRow(ctx, arb->Wrapped, count, x, y, values);
    /* second, fill in alpha values from this buffer! */
    for (i = 0; i < count; i++) {
       dst[i * 4 + 3] = src[i];
@@ -1237,34 +1311,34 @@ get_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
 
 
 static void
-get_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+get_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
                   const GLint x[], const GLint y[], void *values)
 {
-   struct alpha_renderbuffer *arb = (struct alpha_renderbuffer *) rb;
    GLubyte *dst = (GLubyte *) values;
    GLuint i;
-   assert(rb->DataType == GL_UNSIGNED_BYTE);
+   ASSERT(arb != arb->Wrapped);
+   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
    /* first, pass the call to the wrapped RGB buffer */
-   arb->RGBbuffer->GetValues(ctx, arb->RGBbuffer, count, x, y, values);
+   arb->Wrapped->GetValues(ctx, arb->Wrapped, count, x, y, values);
    /* second, fill in alpha values from this buffer! */
    for (i = 0; i < count; i++) {
-      const GLubyte *src = (GLubyte *) rb->Data + y[i] * rb->Width + x[i];
+      const GLubyte *src = (GLubyte *) arb->Data + y[i] * arb->Width + x[i];
       dst[i * 4 + 3] = *src;
    }
 }
 
 
 static void
-put_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+put_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
                GLint x, GLint y, const void *values, const GLubyte *mask)
 {
-   struct alpha_renderbuffer *arb = (struct alpha_renderbuffer *) rb;
    const GLubyte *src = (const GLubyte *) values;
-   GLubyte *dst = (GLubyte *) rb->Data + y * rb->Width + x;
+   GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x;
    GLuint i;
-   assert(rb->DataType == GL_UNSIGNED_BYTE);
+   ASSERT(arb != arb->Wrapped);
+   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
    /* first, pass the call to the wrapped RGB buffer */
-   arb->RGBbuffer->PutRow(ctx, arb->RGBbuffer, count, x, y, values, mask);
+   arb->Wrapped->PutRow(ctx, arb->Wrapped, count, x, y, values, mask);
    /* second, store alpha in our buffer */
    for (i = 0; i < count; i++) {
       if (!mask || mask[i]) {
@@ -1275,16 +1349,16 @@ put_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
 
 
 static void
-put_row_rgb_alpha8(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+put_row_rgb_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
                    GLint x, GLint y, const void *values, const GLubyte *mask)
 {
-   struct alpha_renderbuffer *arb = (struct alpha_renderbuffer *) rb;
    const GLubyte *src = (const GLubyte *) values;
-   GLubyte *dst = (GLubyte *) rb->Data + y * rb->Width + x;
+   GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x;
    GLuint i;
-   assert(rb->DataType == GL_UNSIGNED_BYTE);
+   ASSERT(arb != arb->Wrapped);
+   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
    /* first, pass the call to the wrapped RGB buffer */
-   arb->RGBbuffer->PutRowRGB(ctx, arb->RGBbuffer, count, x, y, values, mask);
+   arb->Wrapped->PutRowRGB(ctx, arb->Wrapped, count, x, y, values, mask);
    /* second, store alpha in our buffer */
    for (i = 0; i < count; i++) {
       if (!mask || mask[i]) {
@@ -1295,15 +1369,15 @@ put_row_rgb_alpha8(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
 
 
 static void
-put_mono_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+put_mono_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
                     GLint x, GLint y, const void *value, const GLubyte *mask)
 {
-   struct alpha_renderbuffer *arb = (struct alpha_renderbuffer *) rb;
    const GLubyte val = ((const GLubyte *) value)[3];
-   GLubyte *dst = (GLubyte *) rb->Data + y * rb->Width + x;
-   assert(rb->DataType == GL_UNSIGNED_BYTE);
+   GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x;
+   ASSERT(arb != arb->Wrapped);
+   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
    /* first, pass the call to the wrapped RGB buffer */
-   arb->RGBbuffer->PutMonoRow(ctx, arb->RGBbuffer, count, x, y, value, mask);
+   arb->Wrapped->PutMonoRow(ctx, arb->Wrapped, count, x, y, value, mask);
    /* second, store alpha in our buffer */
    if (mask) {
       GLuint i;
@@ -1320,20 +1394,20 @@ put_mono_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
 
 
 static void
-put_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+put_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
                   const GLint x[], const GLint y[],
                   const void *values, const GLubyte *mask)
 {
-   struct alpha_renderbuffer *arb = (struct alpha_renderbuffer *) rb;
    const GLubyte *src = (const GLubyte *) values;
    GLuint i;
-   assert(rb->DataType == GL_UNSIGNED_BYTE);
+   ASSERT(arb != arb->Wrapped);
+   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
    /* first, pass the call to the wrapped RGB buffer */
-   arb->RGBbuffer->PutValues(ctx, arb->RGBbuffer, count, x, y, values, mask);
+   arb->Wrapped->PutValues(ctx, arb->Wrapped, count, x, y, values, mask);
    /* second, store alpha in our buffer */
    for (i = 0; i < count; i++) {
       if (!mask || mask[i]) {
-         GLubyte *dst = (GLubyte *) rb->Data + y[i] * rb->Width + x[i];
+         GLubyte *dst = (GLubyte *) arb->Data + y[i] * arb->Width + x[i];
          *dst = src[i * 4 + 3];
       }
    }
@@ -1341,26 +1415,37 @@ put_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
 
 
 static void
-put_mono_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *rb,
+put_mono_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb,
                        GLuint count, const GLint x[], const GLint y[],
                        const void *value, const GLubyte *mask)
 {
-   struct alpha_renderbuffer *arb = (struct alpha_renderbuffer *) rb;
    const GLubyte val = ((const GLubyte *) value)[3];
    GLuint i;
-   assert(rb->DataType == GL_UNSIGNED_BYTE);
+   ASSERT(arb != arb->Wrapped);
+   ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
    /* first, pass the call to the wrapped RGB buffer */
-   arb->RGBbuffer->PutValues(ctx, arb->RGBbuffer, count, x, y, value, mask);
+   arb->Wrapped->PutValues(ctx, arb->Wrapped, count, x, y, value, mask);
    /* second, store alpha in our buffer */
    for (i = 0; i < count; i++) {
       if (!mask || mask[i]) {
-         GLubyte *dst = (GLubyte *) rb->Data + y[i] * rb->Width + x[i];
+         GLubyte *dst = (GLubyte *) arb->Data + y[i] * arb->Width + x[i];
          *dst = val;
       }
    }
 }
 
 
+static void
+copy_buffer_alpha8(struct gl_renderbuffer* dst, struct gl_renderbuffer* src)
+{
+   ASSERT(dst->_ActualFormat == GL_ALPHA8);
+   ASSERT(src->_ActualFormat == GL_ALPHA8);
+   ASSERT(dst->Width == src->Width);
+   ASSERT(dst->Height == src->Height);
+
+   _mesa_memcpy(dst->Data, src->Data, dst->Width * dst->Height * sizeof(GLubyte));
+}
+
 
 /**********************************************************************/
 /**********************************************************************/
@@ -1384,8 +1469,11 @@ nop_get_pointer(GLcontext *ctx, struct gl_renderbuffer *rb, GLint x, GLint y)
 void
 _mesa_init_renderbuffer(struct gl_renderbuffer *rb, GLuint name)
 {
+   _glthread_INIT_MUTEX(rb->Mutex);
+
+   rb->ClassID = 0;
    rb->Name = name;
-   rb->RefCount = 1;
+   rb->RefCount = 0;
    rb->Delete = _mesa_delete_renderbuffer;
 
    /* The rest of these should be set later by the caller of this function or
@@ -1396,6 +1484,7 @@ _mesa_init_renderbuffer(struct gl_renderbuffer *rb, GLuint name)
    rb->Width = 0;
    rb->Height = 0;
    rb->InternalFormat = GL_NONE;
+   rb->_ActualFormat = GL_NONE;
    rb->_BaseFormat = GL_NONE;
    rb->DataType = GL_NONE;
    rb->RedBits = rb->GreenBits = rb->BlueBits = rb->AlphaBits = 0;
@@ -1404,6 +1493,11 @@ _mesa_init_renderbuffer(struct gl_renderbuffer *rb, GLuint name)
    rb->StencilBits = 0;
    rb->Data = NULL;
 
+   /* Point back to ourself so that we don't have to check for Wrapped==NULL
+    * all over the drivers.
+    */
+   rb->Wrapped = rb;
+
    rb->GetPointer = nop_get_pointer;
    rb->GetRow = NULL;
    rb->GetValues = NULL;
@@ -1432,7 +1526,7 @@ _mesa_new_renderbuffer(GLcontext *ctx, GLuint name)
 
 /**
  * Delete a gl_framebuffer.
- * This is the default function for framebuffer->Delete().
+ * This is the default function for renderbuffer->Delete().
  */
 void
 _mesa_delete_renderbuffer(struct gl_renderbuffer *rb)
@@ -1455,9 +1549,9 @@ _mesa_new_soft_renderbuffer(GLcontext *ctx, GLuint name)
 {
    struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, name);
    if (rb) {
-      rb->AllocStorage = soft_renderbuffer_storage;
+      rb->AllocStorage = _mesa_soft_renderbuffer_storage;
       /* Normally, one would setup the PutRow, GetRow, etc functions here.
-       * But we're doing that in the soft_renderbuffer_storage() function
+       * But we're doing that in the _mesa_soft_renderbuffer_storage() function
        * instead.
        */
    }
@@ -1511,19 +1605,20 @@ _mesa_add_color_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
 
       if (rgbBits <= 8) {
          if (alphaBits)
-            rb->InternalFormat = GL_RGBA8;
+            rb->_ActualFormat = GL_RGBA8;
          else
-            rb->InternalFormat = GL_RGB8;
+            rb->_ActualFormat = GL_RGB8;
       }
       else {
          assert(rgbBits <= 16);
          if (alphaBits)
-            rb->InternalFormat = GL_RGBA16;
+            rb->_ActualFormat = GL_RGBA16;
          else
-            rb->InternalFormat = GL_RGBA16; /* don't really have RGB16 yet */
+            rb->_ActualFormat = GL_RGBA16; /* don't really have RGB16 yet */
       }
+      rb->InternalFormat = rb->_ActualFormat;
 
-      rb->AllocStorage = soft_renderbuffer_storage;
+      rb->AllocStorage = _mesa_soft_renderbuffer_storage;
       _mesa_add_renderbuffer(fb, b, rb);
    }
 
@@ -1578,12 +1673,14 @@ _mesa_add_color_index_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
       if (indexBits <= 8) {
          /* only support GLuint for now */
          /*rb->InternalFormat = GL_COLOR_INDEX8_EXT;*/
-         rb->InternalFormat = COLOR_INDEX32;
+         rb->_ActualFormat = COLOR_INDEX32;
       }
       else {
-         rb->InternalFormat = COLOR_INDEX32;
+         rb->_ActualFormat = COLOR_INDEX32;
       }
-      rb->AllocStorage = soft_renderbuffer_storage;
+      rb->InternalFormat = rb->_ActualFormat;
+
+      rb->AllocStorage = _mesa_soft_renderbuffer_storage;
       _mesa_add_renderbuffer(fb, b, rb);
    }
 
@@ -1618,8 +1715,10 @@ _mesa_add_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
 
    assert(MAX_COLOR_ATTACHMENTS >= 4);
 
+   /* Wrap each of the RGB color buffers with an alpha renderbuffer.
+    */
    for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
-      struct alpha_renderbuffer *arb;
+      struct gl_renderbuffer *arb;
 
       if (b == BUFFER_FRONT_LEFT && !frontLeft)
          continue;
@@ -1636,43 +1735,68 @@ _mesa_add_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
       /* only GLubyte supported for now */
       assert(fb->Attachment[b].Renderbuffer->DataType == GL_UNSIGNED_BYTE);
 
-      arb = CALLOC_STRUCT(alpha_renderbuffer);
+      /* allocate alpha renderbuffer */
+      arb = _mesa_new_renderbuffer(ctx, 0);
       if (!arb) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating alpha buffer");
          return GL_FALSE;
       }
 
-      _mesa_init_renderbuffer(&arb->Base, 0);
-
-      /* wrap the RGB buffer */
-      arb->RGBbuffer = fb->Attachment[b].Renderbuffer;
-
-      /* plug in my functions */
-      arb->Base.InternalFormat = arb->RGBbuffer->InternalFormat;
-      arb->Base._BaseFormat    = arb->RGBbuffer->_BaseFormat;
-      arb->Base.DataType       = arb->RGBbuffer->DataType;
-      arb->Base.AllocStorage   = alloc_storage_alpha8;
-      arb->Base.Delete         = delete_renderbuffer_alpha8;
-      arb->Base.GetPointer     = get_pointer_alpha8;
-      arb->Base.GetRow         = get_row_alpha8;
-      arb->Base.GetValues      = get_values_alpha8;
-      arb->Base.PutRow         = put_row_alpha8;
-      arb->Base.PutRowRGB      = put_row_rgb_alpha8;
-      arb->Base.PutMonoRow     = put_mono_row_alpha8;
-      arb->Base.PutValues      = put_values_alpha8;
-      arb->Base.PutMonoValues  = put_mono_values_alpha8;
+      /* wrap the alpha renderbuffer around the RGB renderbuffer */
+      arb->Wrapped = fb->Attachment[b].Renderbuffer;
+
+      /* Set up my alphabuffer fields and plug in my functions.
+       * The functions will put/get the alpha values from/to RGBA arrays
+       * and then call the wrapped buffer's functions to handle the RGB
+       * values.
+       */
+      arb->InternalFormat = arb->Wrapped->InternalFormat;
+      arb->_ActualFormat  = GL_ALPHA8;
+      arb->_BaseFormat    = arb->Wrapped->_BaseFormat;
+      arb->DataType       = arb->Wrapped->DataType;
+      arb->AllocStorage   = alloc_storage_alpha8;
+      arb->Delete         = delete_renderbuffer_alpha8;
+      arb->GetPointer     = get_pointer_alpha8;
+      arb->GetRow         = get_row_alpha8;
+      arb->GetValues      = get_values_alpha8;
+      arb->PutRow         = put_row_alpha8;
+      arb->PutRowRGB      = put_row_rgb_alpha8;
+      arb->PutMonoRow     = put_mono_row_alpha8;
+      arb->PutValues      = put_values_alpha8;
+      arb->PutMonoValues  = put_mono_values_alpha8;
 
       /* clear the pointer to avoid assertion/sanity check failure later */
       fb->Attachment[b].Renderbuffer = NULL;
 
       /* plug the alpha renderbuffer into the colorbuffer attachment */
-      _mesa_add_renderbuffer(fb, b, &arb->Base);
+      _mesa_add_renderbuffer(fb, b, arb);
    }
 
    return GL_TRUE;
 }
 
 
+/**
+ * For framebuffers that use a software alpha channel wrapper
+ * created by _mesa_add_alpha_renderbuffer or _mesa_add_soft_renderbuffers,
+ * copy the back buffer alpha channel into the front buffer alpha channel.
+ */
+void
+_mesa_copy_soft_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb)
+{
+   if (fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer &&
+       fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer)
+      copy_buffer_alpha8(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer,
+                         fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
+
+
+   if (fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer &&
+       fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer)
+      copy_buffer_alpha8(fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer,
+                         fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer);
+}
+
+
 /**
  * Add a software-based depth renderbuffer to the given framebuffer.
  * This is a helper routine for device drivers when creating a
@@ -1702,13 +1826,17 @@ _mesa_add_depth_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
    }
 
    if (depthBits <= 16) {
-      rb->InternalFormat = GL_DEPTH_COMPONENT16;
+      rb->_ActualFormat = GL_DEPTH_COMPONENT16;
+   }
+   else if (depthBits <= 24) {
+      rb->_ActualFormat = GL_DEPTH_COMPONENT24;
    }
    else {
-      rb->InternalFormat = GL_DEPTH_COMPONENT32;
+      rb->_ActualFormat = GL_DEPTH_COMPONENT32;
    }
+   rb->InternalFormat = rb->_ActualFormat;
 
-   rb->AllocStorage = soft_renderbuffer_storage;
+   rb->AllocStorage = _mesa_soft_renderbuffer_storage;
    _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
 
    return GL_TRUE;
@@ -1744,14 +1872,15 @@ _mesa_add_stencil_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
    }
 
    if (stencilBits <= 8) {
-      rb->InternalFormat = GL_STENCIL_INDEX8_EXT;
+      rb->_ActualFormat = GL_STENCIL_INDEX8_EXT;
    }
    else {
       /* not really supported (see s_stencil.c code) */
-      rb->InternalFormat = GL_STENCIL_INDEX16_EXT;
+      rb->_ActualFormat = GL_STENCIL_INDEX16_EXT;
    }
+   rb->InternalFormat = rb->_ActualFormat;
 
-   rb->AllocStorage = soft_renderbuffer_storage;
+   rb->AllocStorage = _mesa_soft_renderbuffer_storage;
    _mesa_add_renderbuffer(fb, BUFFER_STENCIL, rb);
 
    return GL_TRUE;
@@ -1787,8 +1916,9 @@ _mesa_add_accum_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
       return GL_FALSE;
    }
 
+   rb->_ActualFormat = GL_RGBA16;
    rb->InternalFormat = GL_RGBA16;
-   rb->AllocStorage = soft_renderbuffer_storage;
+   rb->AllocStorage = _mesa_soft_renderbuffer_storage;
    _mesa_add_renderbuffer(fb, BUFFER_ACCUM, rb);
 
    return GL_TRUE;
@@ -1831,13 +1961,14 @@ _mesa_add_aux_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
       }
 
       if (colorBits <= 8) {
-         rb->InternalFormat = GL_RGBA8;
+         rb->_ActualFormat = GL_RGBA8;
       }
       else {
-         rb->InternalFormat = GL_RGBA16;
+         rb->_ActualFormat = GL_RGBA16;
       }
+      rb->InternalFormat = rb->_ActualFormat;
 
-      rb->AllocStorage = soft_renderbuffer_storage;
+      rb->AllocStorage = _mesa_soft_renderbuffer_storage;
       _mesa_add_renderbuffer(fb, BUFFER_AUX0 + i, rb);
    }
    return GL_TRUE;
@@ -1935,12 +2066,16 @@ _mesa_add_renderbuffer(struct gl_framebuffer *fb,
 {
    assert(fb);
    assert(rb);
-#if 00
-   /* there should be no previous renderbuffer on this attachment point! */
-   assert(fb->Attachment[bufferName].Renderbuffer == NULL);
-#endif
    assert(bufferName < BUFFER_COUNT);
 
+   /* There should be no previous renderbuffer on this attachment point,
+    * with the exception of depth/stencil since the same renderbuffer may
+    * be used for both.
+    */
+   assert(bufferName == BUFFER_DEPTH ||
+          bufferName == BUFFER_STENCIL ||
+          fb->Attachment[bufferName].Renderbuffer == NULL);
+
    /* winsys vs. user-created buffer cross check */
    if (fb->Name) {
       assert(rb->Name);
@@ -1949,7 +2084,114 @@ _mesa_add_renderbuffer(struct gl_framebuffer *fb,
       assert(!rb->Name);
    }
 
+   /* If Mesa's compiled with deep color channels (16 or 32 bits / channel)
+    * and the device driver is expecting 8-bit values (GLubyte), we can
+    * use a "renderbuffer adaptor/wrapper" to do the necessary conversions.
+    */
+   if (rb->_BaseFormat == GL_RGBA) {
+      if (CHAN_BITS == 16 && rb->DataType == GL_UNSIGNED_BYTE) {
+         GET_CURRENT_CONTEXT(ctx);
+         rb = _mesa_new_renderbuffer_16wrap8(ctx, rb);
+      }
+      else if (CHAN_BITS == 32 && rb->DataType == GL_UNSIGNED_BYTE) {
+         GET_CURRENT_CONTEXT(ctx);
+         rb = _mesa_new_renderbuffer_32wrap8(ctx, rb);
+      }
+      else if (CHAN_BITS == 32 && rb->DataType == GL_UNSIGNED_SHORT) {
+         GET_CURRENT_CONTEXT(ctx);
+         rb = _mesa_new_renderbuffer_32wrap16(ctx, rb);
+      }
+   }
+
    fb->Attachment[bufferName].Type = GL_RENDERBUFFER_EXT;
    fb->Attachment[bufferName].Complete = GL_TRUE;
-   fb->Attachment[bufferName].Renderbuffer = rb;
+   _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer, rb);
+}
+
+
+/**
+ * Remove the named renderbuffer from the given framebuffer.
+ */
+void
+_mesa_remove_renderbuffer(struct gl_framebuffer *fb, GLuint bufferName)
+{
+   struct gl_renderbuffer *rb;
+
+   assert(bufferName < BUFFER_COUNT);
+
+   rb = fb->Attachment[bufferName].Renderbuffer;
+   if (!rb)
+      return;
+
+   _mesa_reference_renderbuffer(&rb, NULL);
+
+   fb->Attachment[bufferName].Renderbuffer = NULL;
+}
+
+
+/**
+ * Set *ptr to point to rb.  If *ptr points to another renderbuffer,
+ * dereference that buffer first.  The new renderbuffer's refcount will
+ * be incremented.  The old renderbuffer's refcount will be decremented.
+ */
+void
+_mesa_reference_renderbuffer(struct gl_renderbuffer **ptr,
+                             struct gl_renderbuffer *rb)
+{
+   assert(ptr);
+   if (*ptr == rb) {
+      /* no change */
+      return;
+   }
+
+   if (*ptr) {
+      /* Unreference the old renderbuffer */
+      GLboolean deleteFlag = GL_FALSE;
+      struct gl_renderbuffer *oldRb = *ptr;
+
+      _glthread_LOCK_MUTEX(oldRb->Mutex);
+      ASSERT(oldRb->RefCount > 0);
+      oldRb->RefCount--;
+      /*printf("RB DECR %p to %d\n", (void*) oldRb, oldRb->RefCount);*/
+      deleteFlag = (oldRb->RefCount == 0);
+      _glthread_UNLOCK_MUTEX(oldRb->Mutex);
+
+      if (deleteFlag)
+         oldRb->Delete(oldRb);
+
+      *ptr = NULL;
+   }
+   assert(!*ptr);
+
+   if (rb) {
+      /* reference new renderbuffer */
+      _glthread_LOCK_MUTEX(rb->Mutex);
+      rb->RefCount++;
+      /*printf("RB REF  %p to %d\n", (void*)rb, rb->RefCount);*/
+      _glthread_UNLOCK_MUTEX(rb->Mutex);
+      *ptr = rb;
+   }
+}
+
+
+/**
+ * Create a new combined depth/stencil renderbuffer for implementing
+ * the GL_EXT_packed_depth_stencil extension.
+ * \return new depth/stencil renderbuffer
+ */
+struct gl_renderbuffer *
+_mesa_new_depthstencil_renderbuffer(GLcontext *ctx, GLuint name)
+{
+   struct gl_renderbuffer *dsrb;
+
+   dsrb = _mesa_new_renderbuffer(ctx, name);
+   if (!dsrb)
+      return NULL;
+
+   /* init fields not covered by _mesa_new_renderbuffer() */
+   dsrb->InternalFormat = GL_DEPTH24_STENCIL8_EXT;
+   dsrb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
+   dsrb->AllocStorage = _mesa_soft_renderbuffer_storage;
+
+   return dsrb;
 }