summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland Scheidegger <sroland@tungstengraphics.com>2007-07-18 20:17:14 +0200
committerRoland Scheidegger <sroland@tungstengraphics.com>2007-07-19 17:59:59 +0200
commita1bc0d0f51c2aa248a349283c3b86ae2c72af4aa (patch)
tree302c0269c002d49ce1e1d31e9e562308d1a2bfa9
parent6075df53b5435ddada989d776d989132def363a6 (diff)
fix mesa's handling of fbo's / window fb (again)
Make sure the relevant fields in window fbs get updated at appropriate time (those are NOT the same as fbos!!!), and fix up related code accordingly. This is a bit ugly, but there's a reason the issues section in EXT_fbo is a couple hundred pages long... Hopefully correct now.
-rw-r--r--src/mesa/main/attrib.c4
-rw-r--r--src/mesa/main/buffers.c72
-rw-r--r--src/mesa/main/buffers.h3
-rw-r--r--src/mesa/main/context.c12
-rw-r--r--src/mesa/main/fbobject.c24
-rw-r--r--src/mesa/main/framebuffer.c3
6 files changed, 77 insertions, 41 deletions
diff --git a/src/mesa/main/attrib.c b/src/mesa/main/attrib.c
index 1aa0a02fc7..b422198f92 100644
--- a/src/mesa/main/attrib.c
+++ b/src/mesa/main/attrib.c
@@ -98,9 +98,13 @@ _mesa_PushAttrib(GLbitfield mask)
}
if (mask & GL_COLOR_BUFFER_BIT) {
+ GLuint i;
struct gl_colorbuffer_attrib *attr;
attr = MALLOC_STRUCT( gl_colorbuffer_attrib );
MEMCPY( attr, &ctx->Color, sizeof(struct gl_colorbuffer_attrib) );
+ /* push the Draw FBO's DrawBuffer[] state, not ctx->Color.DrawBuffer[] */
+ for (i = 0; i < ctx->Const.MaxDrawBuffers; i ++)
+ attr->DrawBuffer[i] = ctx->DrawBuffer->ColorDrawBuffer[i];
newnode = new_attrib_node( GL_COLOR_BUFFER_BIT );
newnode->data = attr;
newnode->next = head;
diff --git a/src/mesa/main/buffers.c b/src/mesa/main/buffers.c
index 68a0575d93..7764a5d3b2 100644
--- a/src/mesa/main/buffers.c
+++ b/src/mesa/main/buffers.c
@@ -370,6 +370,14 @@ _mesa_DrawBuffer(GLenum buffer)
/* if we get here, there's no error so set new state */
_mesa_drawbuffers(ctx, 1, &buffer, &destMask);
+
+ /*
+ * Call device driver function.
+ */
+ if (ctx->Driver.DrawBuffers)
+ ctx->Driver.DrawBuffers(ctx, 1, &buffer);
+ else if (ctx->Driver.DrawBuffer)
+ ctx->Driver.DrawBuffer(ctx, buffer);
}
@@ -435,6 +443,14 @@ _mesa_DrawBuffersARB(GLsizei n, const GLenum *buffers)
/* OK, if we get here, there were no errors so set the new state */
_mesa_drawbuffers(ctx, n, buffers, destMask);
+
+ /*
+ * Call device driver function.
+ */
+ if (ctx->Driver.DrawBuffers)
+ ctx->Driver.DrawBuffers(ctx, n, buffers);
+ else if (ctx->Driver.DrawBuffer)
+ ctx->Driver.DrawBuffer(ctx, buffers[0]);
}
@@ -463,14 +479,15 @@ set_color_output(GLcontext *ctx, GLuint output, GLenum buffer,
/* not really needed, will be set later */
fb->_NumColorDrawBuffers[output] = 0;
+ if (fb->Name == 0)
/* Set traditional state var */
- ctx->Color.DrawBuffer[output] = buffer;
+ ctx->Color.DrawBuffer[output] = buffer;
}
/**
* Helper routine used by _mesa_DrawBuffer, _mesa_DrawBuffersARB and
- * _mesa_PopAttrib to set drawbuffer state.
+ * other places (window fbo fixup) to set fbo (and the old ctx) fields.
* All error checking will have been done prior to calling this function
* so nothing should go wrong at this point.
* \param ctx current context
@@ -479,6 +496,7 @@ set_color_output(GLcontext *ctx, GLuint output, GLenum buffer,
* \param destMask array[n] of BUFFER_* bitmasks which correspond to the
* colorbuffer names. (i.e. GL_FRONT_AND_BACK =>
* BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT).
+ * \param callDriver call driver or not (bad idea sometimes this is called)
*/
void
_mesa_drawbuffers(GLcontext *ctx, GLuint n, const GLenum *buffers,
@@ -509,30 +527,15 @@ _mesa_drawbuffers(GLcontext *ctx, GLuint n, const GLenum *buffers,
}
ctx->NewState |= _NEW_COLOR;
-
- /*
- * Call device driver function.
- */
- if (ctx->Driver.DrawBuffers)
- ctx->Driver.DrawBuffers(ctx, n, buffers);
- else if (ctx->Driver.DrawBuffer)
- ctx->Driver.DrawBuffer(ctx, buffers[0]);
}
-
-/**
- * Called by glReadBuffer to set the source renderbuffer for reading pixels.
- * \param mode color buffer such as GL_FRONT, GL_BACK, etc.
- */
-void GLAPIENTRY
-_mesa_ReadBuffer(GLenum buffer)
+GLboolean
+_mesa_readbuffer_update_fields(GLcontext *ctx, GLenum buffer)
{
struct gl_framebuffer *fb;
GLbitfield supportedMask;
GLint srcBuffer;
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
fb = ctx->ReadBuffer;
@@ -548,20 +551,43 @@ _mesa_ReadBuffer(GLenum buffer)
srcBuffer = read_buffer_enum_to_index(buffer);
if (srcBuffer == -1) {
_mesa_error(ctx, GL_INVALID_ENUM, "glReadBuffer(buffer=0x%x)", buffer);
- return;
+ return GL_FALSE;
}
supportedMask = supported_buffer_bitmask(ctx, fb);
if (((1 << srcBuffer) & supportedMask) == 0) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glReadBuffer(buffer=0x%x)", buffer);
- return;
+ return GL_FALSE;
}
}
- ctx->Pixel.ReadBuffer = buffer;
-
+ if (fb->Name == 0) {
+ ctx->Pixel.ReadBuffer = buffer;
+ }
fb->ColorReadBuffer = buffer;
fb->_ColorReadBufferIndex = srcBuffer;
+ return GL_TRUE;
+}
+
+
+
+/**
+ * Called by glReadBuffer to set the source renderbuffer for reading pixels.
+ * \param mode color buffer such as GL_FRONT, GL_BACK, etc.
+ * \param callDriver call driver or not (bad idea sometimes this is called)
+ */
+void GLAPIENTRY
+_mesa_ReadBuffer(GLenum buffer)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer));
+
+ if (!_mesa_readbuffer_update_fields(ctx, buffer))
+ return;
+
ctx->NewState |= _NEW_PIXEL;
/*
diff --git a/src/mesa/main/buffers.h b/src/mesa/main/buffers.h
index fcc2152342..208e7af2b9 100644
--- a/src/mesa/main/buffers.h
+++ b/src/mesa/main/buffers.h
@@ -56,6 +56,9 @@ extern void
_mesa_drawbuffers(GLcontext *ctx, GLuint n, const GLenum *buffers,
const GLbitfield *destMask);
+extern GLboolean
+_mesa_readbuffer_update_fields(GLcontext *ctx, GLenum buffer);
+
extern void GLAPIENTRY
_mesa_ReadBuffer( GLenum mode );
diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c
index 4e6732dc7a..00e4c8328e 100644
--- a/src/mesa/main/context.c
+++ b/src/mesa/main/context.c
@@ -1496,14 +1496,8 @@ _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer,
if (!newCtx->DrawBuffer || newCtx->DrawBuffer->Name == 0) {
_mesa_reference_framebuffer(&newCtx->DrawBuffer, drawBuffer);
/* fix up the fb fields - these will end up wrong otherwise
- if the DRIdrawable changes, and someone may rely on them.
- */
- /* What a mess!?! */
- /* XXX this is still not quite correct. Imagine a user-created fbo
- bound on a context. Now rebind with a completely new drawable.
- Upon rebinding to the window-framebuffer, we have no idea what
- the read and write buffers should be (front, back, ...) - that
- information was only available in the previously used drawable... */
+ if the DRIdrawable changes, and everything relies on them.
+ This is a bit messy (same as needed in _mesa_BindFramebufferEXT) */
int i;
GLenum buffers[MAX_DRAW_BUFFERS];
for(i = 0; i < newCtx->Const.MaxDrawBuffers; i++) {
@@ -1513,7 +1507,7 @@ _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer,
}
if (!newCtx->ReadBuffer || newCtx->ReadBuffer->Name == 0) {
_mesa_reference_framebuffer(&newCtx->ReadBuffer, readBuffer);
- _mesa_ReadBuffer(newCtx->Pixel.ReadBuffer);
+ _mesa_readbuffer_update_fields(newCtx, newCtx->Pixel.ReadBuffer);
}
newCtx->NewState |= _NEW_BUFFERS;
diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c
index f300e481ce..6f7effcce7 100644
--- a/src/mesa/main/fbobject.c
+++ b/src/mesa/main/fbobject.c
@@ -29,6 +29,7 @@
*/
+#include "buffers.h"
#include "context.h"
#include "fbobject.h"
#include "framebuffer.h"
@@ -1001,23 +1002,32 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
* XXX check if re-binding same buffer and skip some of this code.
*/
+ /* for window-framebuffers, re-initialize the fbo values, as they
+ could be wrong (makecurrent with a new drawable while still a fbo
+ was bound will lead to default init fbo values).
+ note that therefore the context ReadBuffer/DrawBuffer values are not
+ valid while fbo's are bound!!! */
if (bindReadBuf) {
_mesa_reference_framebuffer(&ctx->ReadBuffer, newFbread);
- /* set context value */
- ctx->Pixel.ReadBuffer = newFbread->ColorReadBuffer;
+ if (!newFbread->Name) {
+ _mesa_readbuffer_update_fields(ctx, ctx->Pixel.ReadBuffer);
+ }
}
if (bindDrawBuf) {
- GLuint i;
/* check if old FB had any texture attachments */
check_end_texture_render(ctx, ctx->DrawBuffer);
/* check if time to delete this framebuffer */
_mesa_reference_framebuffer(&ctx->DrawBuffer, newFb);
- /* set context value */
- for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
- ctx->Color.DrawBuffer[i] = newFb->ColorDrawBuffer[i];
+ if (!newFb->Name) {
+ GLuint i;
+ GLenum buffers[MAX_DRAW_BUFFERS];
+ for(i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
+ buffers[i] = ctx->Color.DrawBuffer[i];
+ }
+ _mesa_drawbuffers(ctx, ctx->Const.MaxDrawBuffers, buffers, NULL);
}
- if (newFb->Name != 0) {
+ else {
/* check if newly bound framebuffer has any texture attachments */
check_begin_texture_render(ctx, newFb);
}
diff --git a/src/mesa/main/framebuffer.c b/src/mesa/main/framebuffer.c
index 2ff067164b..c9b30d3252 100644
--- a/src/mesa/main/framebuffer.c
+++ b/src/mesa/main/framebuffer.c
@@ -695,8 +695,7 @@ _mesa_update_framebuffer(GLcontext *ctx)
struct gl_framebuffer *fbread = ctx->ReadBuffer;
update_framebuffer(ctx, fb);
- if (fbread != fb && fbread != NULL /* can happen at make_current -
- core/driver circular dependencies, should be fixed up */)
+ if (fbread != fb)
update_framebuffer(ctx, fbread);
}