瀏覽代碼

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.
tags/mesa_20060201
Brian Paul 20 年之前
父節點
當前提交
0efc17c105
共有 4 個檔案被更改,包括 100 行新增92 行删除
  1. 1
    1
      src/mesa/drivers/x11/xm_line.c
  2. 2
    3
      src/mesa/drivers/x11/xm_tri.c
  3. 3
    0
      src/mesa/main/mtypes.h
  4. 94
    88
      src/mesa/main/renderbuffer.c

+ 1
- 1
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


/*

+ 2
- 3
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;

+ 3
- 0
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);


+ 94
- 88
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;

Loading…
取消
儲存