X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Frenderbuffer.c;h=d576a7a121595c36011fc3ad83803104bb1707d7;hb=09fbb3837b6aa5dfc6c94f41ab5443820177c569;hp=4ebaa1f6118b49d3dbfda87625b36e5d1a63c23f;hpb=676d0accf5cc43e86057b14cfb8bba9316932582;p=mesa.git diff --git a/src/mesa/main/renderbuffer.c b/src/mesa/main/renderbuffer.c index 4ebaa1f6118..d576a7a1215 100644 --- a/src/mesa/main/renderbuffer.c +++ b/src/mesa/main/renderbuffer.c @@ -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,10 @@ #include "fbobject.h" #include "renderbuffer.h" +#include "rbadaptors.h" + +#include "state_tracker/st_context.h" + /* 32-bit color index format. Not a public format. */ #define COLOR_INDEX32 0x424243 @@ -70,6 +74,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 +97,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 +111,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 +132,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 +157,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 +174,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 +320,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 +335,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 +347,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 +362,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 +384,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 +410,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 +428,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 +450,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 +465,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 +482,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 +503,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 +523,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 +544,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 +571,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 +594,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 +619,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 +628,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 +642,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 +658,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 +682,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 +702,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 +736,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 +755,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 +942,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 +967,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 +989,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 +1009,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 +1027,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 +1050,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 +1065,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 +1081,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 +1107,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 +1150,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 +1165,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 +1180,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 +1194,76 @@ 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); + rb->Data = NULL; + } - /* 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; + if (width > 0 && height > 0) { + /* allocate new buffer storage */ + rb->Data = 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 +1273,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 +1295,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 +1314,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 +1352,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 +1372,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 +1397,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 +1418,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 +1472,12 @@ 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->Magic = RB_MAGIC; + 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 +1488,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 +1497,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 +1530,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 +1553,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 +1609,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 +1677,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 +1719,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 +1739,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 +1830,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 +1876,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 +1920,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 +1965,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 +2070,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 +2088,119 @@ _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; + + assert(oldRb->Magic == RB_MAGIC); + _glthread_LOCK_MUTEX(oldRb->Mutex); + assert(oldRb->Magic == RB_MAGIC); + ASSERT(oldRb->RefCount > 0); + oldRb->RefCount--; + /*printf("RB DECR %p (%d) to %d\n", (void*) oldRb, oldRb->Name, oldRb->RefCount);*/ + deleteFlag = (oldRb->RefCount == 0); + _glthread_UNLOCK_MUTEX(oldRb->Mutex); + + if (deleteFlag) { + oldRb->Magic = 0; /* now invalid memory! */ + oldRb->Delete(oldRb); + } + + *ptr = NULL; + } + assert(!*ptr); + + if (rb) { + assert(rb->Magic == RB_MAGIC); + /* reference new renderbuffer */ + _glthread_LOCK_MUTEX(rb->Mutex); + rb->RefCount++; + /*printf("RB INCR %p (%d) to %d\n", (void*) rb, rb->Name, 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; }