From 0efc17c105f8239bf4fb128d570f2d343c45d430 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Fri, 23 Sep 2005 01:20:09 +0000 Subject: [PATCH] Add Wrapper field to gl_renderbuffer. Used for wrapping one renderbuffer with another, such as wrapping a hardware/win-sys RGB renderbuffer with a software-based alpha buffer. Previous alpha buffer wrapping was conflicting with the X driver's xmesa_renderbuffer structure containment/inheritance. That lead to memory corruption. --- src/mesa/drivers/x11/xm_line.c | 2 +- src/mesa/drivers/x11/xm_tri.c | 5 +- src/mesa/main/mtypes.h | 3 + src/mesa/main/renderbuffer.c | 182 +++++++++++++++++---------------- 4 files changed, 100 insertions(+), 92 deletions(-) diff --git a/src/mesa/drivers/x11/xm_line.c b/src/mesa/drivers/x11/xm_line.c index 43de9a98ab7..6a045c85e6c 100644 --- a/src/mesa/drivers/x11/xm_line.c +++ b/src/mesa/drivers/x11/xm_line.c @@ -118,7 +118,7 @@ void xmesa_choose_point( GLcontext *ctx ) #define GET_XRB(XRB) struct xmesa_renderbuffer *XRB = \ - (struct xmesa_renderbuffer *) ctx->DrawBuffer->_ColorDrawBuffers[0][0] + (struct xmesa_renderbuffer *) ctx->DrawBuffer->_ColorDrawBuffers[0][0]->Wrapped /* diff --git a/src/mesa/drivers/x11/xm_tri.c b/src/mesa/drivers/x11/xm_tri.c index 9340ea49743..87989f46f89 100644 --- a/src/mesa/drivers/x11/xm_tri.c +++ b/src/mesa/drivers/x11/xm_tri.c @@ -45,7 +45,7 @@ #define GET_XRB(XRB) struct xmesa_renderbuffer *XRB = \ - (struct xmesa_renderbuffer *) ctx->DrawBuffer->_ColorDrawBuffers[0][0] + (struct xmesa_renderbuffer *) ctx->DrawBuffer->_ColorDrawBuffers[0][0]->Wrapped /**********************************************************************/ @@ -1430,8 +1430,7 @@ static swrast_tri_func get_triangle_func( GLcontext *ctx ) SWcontext *swrast = SWRAST_CONTEXT(ctx); XMesaContext xmesa = XMESA_CONTEXT(ctx); int depth = GET_VISUAL_DEPTH(xmesa->xm_visual); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) - ctx->DrawBuffer->_ColorDrawBuffers[0][0]; + GET_XRB(xrb); #ifdef DEBUG triFuncName = NULL; diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index e63082948cb..f8f9c137c85 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -2064,6 +2064,9 @@ struct gl_renderbuffer GLubyte StencilBits; GLvoid *Data; + /* Used to wrap one renderbuffer around another: */ + struct gl_renderbuffer *Wrapped; + /* Delete this renderbuffer */ void (*Delete)(struct gl_renderbuffer *rb); diff --git a/src/mesa/main/renderbuffer.c b/src/mesa/main/renderbuffer.c index 4ebaa1f6118..4a0a63c56f4 100644 --- a/src/mesa/main/renderbuffer.c +++ b/src/mesa/main/renderbuffer.c @@ -1146,47 +1146,43 @@ soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb, /** - * 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); /* 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; + arb->InternalFormat = internalFormat; return GL_TRUE; } @@ -1196,21 +1192,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 +1214,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 +1233,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 +1271,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 +1291,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 +1316,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,20 +1337,20 @@ 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; } } @@ -1404,6 +1400,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; @@ -1618,8 +1619,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,37 +1639,40 @@ _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->_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; -- 2.30.2