Implement alpha buffer copy for SwapBuffers().

Nicolai writes:
When the pixmap pixel format has no alpha channel, the x11 driver
(software rendering) adds a wrapped alpha channel on request.

During SwapBuffers, this alpha channel is not copied from back to
front, which means that the front buffer doesn't really contain the
contents that the back buffer previously contained.

A subsequent glReadPixels from the front buffer will return an
incorrect result. The following patch attempts to fix this.
This commit is contained in:
Brian 2007-03-23 18:01:31 -06:00
parent 654a308439
commit 8e1c3bd0b4
4 changed files with 43 additions and 5 deletions

View file

@ -363,7 +363,6 @@ static XMesaBuffer
create_xmesa_buffer(XMesaDrawable d, BufferType type,
XMesaVisual vis, XMesaColormap cmap)
{
GLboolean swAlpha;
XMesaBuffer b;
ASSERT(type == WINDOW || type == PIXMAP || type == PBUFFER);
@ -421,10 +420,10 @@ create_xmesa_buffer(XMesaDrawable d, BufferType type,
/* Visual has alpha, but pixel format doesn't support it.
* We'll use an alpha renderbuffer wrapper.
*/
swAlpha = GL_TRUE;
b->swAlpha = GL_TRUE;
}
else {
swAlpha = GL_FALSE;
b->swAlpha = GL_FALSE;
}
/*
@ -435,9 +434,9 @@ create_xmesa_buffer(XMesaDrawable d, BufferType type,
vis->mesa_visual.haveDepthBuffer,
vis->mesa_visual.haveStencilBuffer,
vis->mesa_visual.haveAccumBuffer,
swAlpha,
b->swAlpha,
vis->mesa_visual.numAuxBuffers > 0 );
/* insert buffer into linked list */
b->Next = XMesaBufferList;
XMesaBufferList = b;
@ -2211,6 +2210,9 @@ void XMesaSwapBuffers( XMesaBuffer b )
);
/*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
}
if (b->swAlpha)
_mesa_copy_soft_alpha_renderbuffers(ctx, &b->mesa_buffer);
}
#if !defined(XFree86Server)
XSync( b->xm_visual->display, False );

View file

@ -224,6 +224,7 @@ struct xmesa_buffer {
GLint db_mode; /* 0 = single buffered */
/* BACK_PIXMAP = use Pixmap for back buffer */
/* BACK_XIMAGE = use XImage for back buffer */
GLboolean swAlpha;
GLuint shm; /* X Shared Memory extension status: */
/* 0 = not available */

View file

@ -1435,6 +1435,17 @@ put_mono_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb,
}
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));
}
/**********************************************************************/
/**********************************************************************/
@ -1765,6 +1776,27 @@ _mesa_add_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
}
/**
* 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

View file

@ -64,6 +64,9 @@ _mesa_add_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
GLboolean frontLeft, GLboolean backLeft,
GLboolean frontRight, GLboolean backRight);
extern void
_mesa_copy_soft_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb);
extern GLboolean
_mesa_add_depth_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
GLuint depthBits);