diff options
Diffstat (limited to 'src/mesa/main/buffers.c')
-rw-r--r-- | src/mesa/main/buffers.c | 97 |
1 files changed, 77 insertions, 20 deletions
diff --git a/src/mesa/main/buffers.c b/src/mesa/main/buffers.c index c280f89e1d1..d9c18bfaafc 100644 --- a/src/mesa/main/buffers.c +++ b/src/mesa/main/buffers.c @@ -140,7 +140,9 @@ _mesa_Clear( GLbitfield mask ) return; } - if (ctx->DrawBuffer->Width == 0 || ctx->DrawBuffer->Height == 0) + if (ctx->DrawBuffer->Width == 0 || ctx->DrawBuffer->Height == 0 || + ctx->DrawBuffer->_Xmin >= ctx->DrawBuffer->_Xmax || + ctx->DrawBuffer->_Ymin >= ctx->DrawBuffer->_Ymax) return; if (ctx->RenderMode == GL_RENDER) { @@ -336,6 +338,20 @@ read_buffer_enum_to_index(GLenum buffer) * \sa _mesa_DrawBuffersARB * * \param buffer buffer token such as GL_LEFT or GL_FRONT_AND_BACK, etc. + * + * Note that the behaviour of this function depends on whether the + * current ctx->DrawBuffer is a window-system framebuffer (Name=0) or + * a user-created framebuffer object (Name!=0). + * In the former case, we update the per-context ctx->Color.DrawBuffer + * state var _and_ the FB's ColorDrawBuffer state. + * In the later case, we update the FB's ColorDrawBuffer state only. + * + * Furthermore, upon a MakeCurrent() or BindFramebuffer() call, if the + * new FB is a window system FB, we need to re-update the FB's + * ColorDrawBuffer state to match the context. This is handled in + * _mesa_update_framebuffer(). + * + * See the GL_EXT_framebuffer_object spec for more info. */ void GLAPIENTRY _mesa_DrawBuffer(GLenum buffer) @@ -370,6 +386,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 +459,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,16 +495,22 @@ set_color_output(GLcontext *ctx, GLuint output, GLenum buffer, /* not really needed, will be set later */ fb->_NumColorDrawBuffers[output] = 0; - /* Set traditional state var */ - ctx->Color.DrawBuffer[output] = buffer; + if (fb->Name == 0) { + /* Only set the per-context DrawBuffer state if we're currently + * drawing to a window system framebuffer. + */ + ctx->Color.DrawBuffer[output] = buffer; + } } /** - * Helper routine used by _mesa_DrawBuffer, _mesa_DrawBuffersARB and - * _mesa_PopAttrib to set drawbuffer state. + * Helper function to set the GL_DRAW_BUFFER state in the context and + * current FBO. + * * All error checking will have been done prior to calling this function * so nothing should go wrong at this point. + * * \param ctx current context * \param n number of color outputs to set * \param buffers array[n] of colorbuffer names, like GL_LEFT. @@ -509,14 +547,32 @@ _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]); + +/** + * Like \sa _mesa_drawbuffers(), this is a helper function for setting + * GL_READ_BUFFER state in the context and current FBO. + * \param ctx the rendering context + * \param buffer GL_FRONT, GL_BACK, GL_COLOR_ATTACHMENT0, etc. + * \param bufferIndex the numerical index corresponding to 'buffer' + */ +void +_mesa_readbuffer(GLcontext *ctx, GLenum buffer, GLint bufferIndex) +{ + struct gl_framebuffer *fb = ctx->ReadBuffer; + + if (fb->Name == 0) { + /* Only update the per-context READ_BUFFER state if we're bound to + * a window-system framebuffer. + */ + ctx->Pixel.ReadBuffer = buffer; + } + + fb->ColorReadBuffer = buffer; + fb->_ColorReadBufferIndex = bufferIndex; + + ctx->NewState |= _NEW_PIXEL; } @@ -534,6 +590,9 @@ _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)); + fb = ctx->ReadBuffer; if (MESA_VERBOSE & VERBOSE_API) @@ -547,23 +606,21 @@ _mesa_ReadBuffer(GLenum buffer) /* general case / window-system framebuffer */ srcBuffer = read_buffer_enum_to_index(buffer); if (srcBuffer == -1) { - _mesa_error(ctx, GL_INVALID_ENUM, "glReadBuffer(buffer=0x%x)", buffer); + _mesa_error(ctx, GL_INVALID_ENUM, + "glReadBuffer(buffer=0x%x)", buffer); return; } supportedMask = supported_buffer_bitmask(ctx, fb); if (((1 << srcBuffer) & supportedMask) == 0) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glReadBuffer(buffer=0x%x)", buffer); + _mesa_error(ctx, GL_INVALID_OPERATION, + "glReadBuffer(buffer=0x%x)", buffer); return; } } - if (fb->Name == 0) { - ctx->Pixel.ReadBuffer = buffer; - } - fb->ColorReadBuffer = buffer; - fb->_ColorReadBufferIndex = srcBuffer; + /* OK, all error checking has been completed now */ - ctx->NewState |= _NEW_PIXEL; + _mesa_readbuffer(ctx, buffer, srcBuffer); /* * Call device driver function. |