diff options
author | Brian Paul <[email protected]> | 2005-05-04 20:11:35 +0000 |
---|---|---|
committer | Brian Paul <[email protected]> | 2005-05-04 20:11:35 +0000 |
commit | e4b2356c07d31fbeeabb13b2fb47db703b473080 (patch) | |
tree | d8b7f1c7c9e7c84d84349485f942dd205dd4c16d /src/mesa/main/fbobject.c | |
parent | ebef61f5c0950572f9c6a81b08f447957461675c (diff) |
Major check-in of changes for GL_EXT_framebuffer_object extension.
Main driver impacts:
- new code for creating the Mesa GLframebuffer
- new span/pixel read/write code
Some drivers not yet updated/tested.
Diffstat (limited to 'src/mesa/main/fbobject.c')
-rw-r--r-- | src/mesa/main/fbobject.c | 379 |
1 files changed, 174 insertions, 205 deletions
diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c index 3480beaa47d..beaf4ed942c 100644 --- a/src/mesa/main/fbobject.c +++ b/src/mesa/main/fbobject.c @@ -31,7 +31,9 @@ #include "context.h" #include "fbobject.h" +#include "framebuffer.h" #include "hash.h" +#include "renderbuffer.h" #include "teximage.h" #include "texstore.h" @@ -95,103 +97,6 @@ lookup_framebuffer(GLcontext *ctx, GLuint id) /** - * Allocate a new gl_framebuffer. - * This is the default function for ctx->Driver.NewFramebuffer(). - */ -struct gl_framebuffer * -_mesa_new_framebuffer(GLcontext *ctx, GLuint name) -{ - struct gl_framebuffer *fb = CALLOC_STRUCT(gl_framebuffer); - if (fb) { - fb->Name = name; - fb->RefCount = 1; - fb->Delete = _mesa_delete_framebuffer; - } - return fb; -} - - -/** - * Delete a gl_framebuffer. - * This is the default function for framebuffer->Delete(). - */ -void -_mesa_delete_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb) -{ - (void) ctx; - _mesa_free(fb); -} - - -/** - * Allocate the actual storage for a renderbuffer with the given format - * and dimensions. - * This is the default function for gl_renderbuffer->AllocStorage(). - * All incoming parameters will have already been checked for errors. - * If memory allocate fails, the function must call - * _mesa_error(GL_OUT_OF_MEMORY) and then return. - * \return GL_TRUE for success, GL_FALSE for failure. - */ -static GLboolean -alloc_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb, - GLenum internalFormat, GLuint width, GLuint height) -{ - /* First, free any existing storage */ - if (rb->Data) { - _mesa_free(rb->Data); - } - - /* Now, allocate new storage */ - rb->Data = _mesa_malloc(width * height * 4); /* XXX fix size! */ - if (rb->Data == NULL) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glRenderbufferStorageEXT"); - return GL_FALSE; - } - - /* We set these fields now if the allocation worked */ - rb->Width = width; - rb->Height = height; - rb->InternalFormat = internalFormat; - - return GL_TRUE; -} - - -/** - * Allocate a new gl_renderbuffer. - * This is the default function for ctx->Driver.NewRenderbuffer(). - */ -struct gl_renderbuffer * -_mesa_new_renderbuffer(GLcontext *ctx, GLuint name) -{ - struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer); - if (rb) { - rb->Name = name; - rb->RefCount = 1; - rb->Delete = _mesa_delete_renderbuffer; - rb->AllocStorage = alloc_renderbuffer_storage; - /* other fields are zero */ - } - return rb; -} - - -/** - * Delete a gl_framebuffer. - * This is the default function for framebuffer->Delete(). - */ -void -_mesa_delete_renderbuffer(GLcontext *ctx, struct gl_renderbuffer *rb) -{ - (void) ctx; - if (rb->Data) { - _mesa_free(rb->Data); - } - _mesa_free(rb); -} - - -/** * Given a GL_*_ATTACHMENTn token, return a pointer to the corresponding * gl_renderbuffer_attachment object. */ @@ -221,11 +126,11 @@ get_attachment(GLcontext *ctx, struct gl_framebuffer *fb, GLenum attachment) if (i >= ctx->Const.MaxColorAttachments) { return NULL; } - return &fb->ColorAttachment[i]; + return &fb->Attachment[BUFFER_COLOR0 + i]; case GL_DEPTH_ATTACHMENT_EXT: - return &fb->DepthAttachment; + return &fb->Attachment[BUFFER_DEPTH]; case GL_STENCIL_ATTACHMENT_EXT: - return &fb->StencilAttachment; + return &fb->Attachment[BUFFER_STENCIL]; default: return NULL; } @@ -236,12 +141,17 @@ get_attachment(GLcontext *ctx, struct gl_framebuffer *fb, GLenum attachment) * Remove any texture or renderbuffer attached to the given attachment * point. Update reference counts, etc. */ -static void -remove_attachment(GLcontext *ctx, struct gl_renderbuffer_attachment *att) +void +_mesa_remove_attachment(GLcontext *ctx, struct gl_renderbuffer_attachment *att) { if (att->Type == GL_TEXTURE) { ASSERT(att->Texture); - ASSERT(!att->Renderbuffer); + if (att->Renderbuffer) { + /* delete/remove the 'wrapper' renderbuffer */ + /* XXX do we really want to do this??? */ + att->Renderbuffer->Delete(att->Renderbuffer); + att->Renderbuffer = NULL; + } att->Texture->RefCount--; if (att->Texture->RefCount == 0) { ctx->Driver.DeleteTexture(ctx, att->Texture); @@ -253,7 +163,7 @@ remove_attachment(GLcontext *ctx, struct gl_renderbuffer_attachment *att) ASSERT(!att->Texture); att->Renderbuffer->RefCount--; if (att->Renderbuffer->RefCount == 0) { - att->Renderbuffer->Delete(ctx, att->Renderbuffer); + att->Renderbuffer->Delete(att->Renderbuffer); } att->Renderbuffer = NULL; } @@ -266,13 +176,13 @@ remove_attachment(GLcontext *ctx, struct gl_renderbuffer_attachment *att) * Bind a texture object to an attachment point. * The previous binding, if any, will be removed first. */ -static void -set_texture_attachment(GLcontext *ctx, - struct gl_renderbuffer_attachment *att, - struct gl_texture_object *texObj, - GLenum texTarget, GLuint level, GLuint zoffset) +void +_mesa_set_texture_attachment(GLcontext *ctx, + struct gl_renderbuffer_attachment *att, + struct gl_texture_object *texObj, + GLenum texTarget, GLuint level, GLuint zoffset) { - remove_attachment(ctx, att); + _mesa_remove_attachment(ctx, att); att->Type = GL_TEXTURE; att->Texture = texObj; att->TextureLevel = level; @@ -284,6 +194,7 @@ set_texture_attachment(GLcontext *ctx, } att->Zoffset = zoffset; att->Complete = GL_FALSE; + texObj->RefCount++; /* XXX when we attach to a texture, we should probably set the @@ -297,12 +208,12 @@ set_texture_attachment(GLcontext *ctx, * Bind a renderbuffer to an attachment point. * The previous binding, if any, will be removed first. */ -static void -set_renderbuffer_attachment(GLcontext *ctx, - struct gl_renderbuffer_attachment *att, - struct gl_renderbuffer *rb) +void +_mesa_set_renderbuffer_attachment(GLcontext *ctx, + struct gl_renderbuffer_attachment *att, + struct gl_renderbuffer *rb) { - remove_attachment(ctx, att); + _mesa_remove_attachment(ctx, att); att->Type = GL_RENDERBUFFER_EXT; att->Renderbuffer = rb; att->Texture = NULL; /* just to be safe */ @@ -312,6 +223,26 @@ set_renderbuffer_attachment(GLcontext *ctx, /** + * Fallback for ctx->Driver.FramebufferRenderbuffer() + * Sets a framebuffer attachment to a particular renderbuffer. + * The framebuffer in question is ctx->DrawBuffer. + * \sa _mesa_renderbuffer_texture + */ +void +_mesa_framebuffer_renderbuffer(GLcontext *ctx, + struct gl_renderbuffer_attachment *att, + struct gl_renderbuffer *rb) +{ + if (rb) { + _mesa_set_renderbuffer_attachment(ctx, att, rb); + } + else { + _mesa_remove_attachment(ctx, att); + } +} + + +/** * Test if an attachment point is complete and update its Complete field. * \param format if GL_COLOR, this is a color attachment point, * if GL_DEPTH, this is a depth component attachment point, @@ -326,15 +257,15 @@ test_attachment_completeness(const GLcontext *ctx, GLenum format, /* assume complete */ att->Complete = GL_TRUE; - if (att->Type == GL_NONE) - return; /* complete */ - /* Look for reasons why the attachment might be incomplete */ if (att->Type == GL_TEXTURE) { - struct gl_texture_object *texObj = att->Texture; + const struct gl_texture_object *texObj = att->Texture; struct gl_texture_image *texImage; - assert(texObj); + if (!texObj) { + att->Complete = GL_FALSE; + return; + } texImage = texObj->Image[att->CubeMapFace][att->TextureLevel]; if (!texImage) { @@ -351,13 +282,14 @@ test_attachment_completeness(const GLcontext *ctx, GLenum format, } if (format == GL_COLOR) { - if (texImage->Format != GL_RGB && texImage->Format != GL_RGBA) { + if (texImage->TexFormat->BaseFormat != GL_RGB && + texImage->TexFormat->BaseFormat != GL_RGBA) { att->Complete = GL_FALSE; return; } } else if (format == GL_DEPTH) { - if (texImage->Format != GL_DEPTH_COMPONENT) { + if (texImage->TexFormat->BaseFormat != GL_DEPTH_COMPONENT) { att->Complete = GL_FALSE; return; } @@ -368,9 +300,7 @@ test_attachment_completeness(const GLcontext *ctx, GLenum format, return; } } - else { - assert(att->Type == GL_RENDERBUFFER_EXT); - + else if (att->Type == GL_RENDERBUFFER_EXT) { if (att->Renderbuffer->Width < 1 || att->Renderbuffer->Height < 1) { att->Complete = GL_FALSE; return; @@ -396,53 +326,58 @@ test_attachment_completeness(const GLcontext *ctx, GLenum format, } } } + else { + ASSERT(att->Type == GL_NONE); + /* complete */ + return; + } } /** * Test if the given framebuffer object is complete and update its * Status field with the results. + * Also update the framebuffer's Width and Height fields if the + * framebuffer is complete. */ -static void -test_framebuffer_completeness(GLcontext *ctx, - struct gl_framebuffer *fb) +void +_mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb) { - GLint i; GLuint numImages, width = 0, height = 0; GLenum intFormat = GL_NONE; - - /* Set to COMPLETE status, then try to find reasons for being incomplete */ - fb->Status = GL_FRAMEBUFFER_COMPLETE_EXT; + GLuint w = 0, h = 0; + GLint i; numImages = 0; + fb->Width = 0; + fb->Height = 0; /* Start at -2 to more easily loop over all attachment points */ - for (i = -2; i < ctx->Const.MaxColorAttachments; i++) { + for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) { struct gl_renderbuffer_attachment *att; - GLuint w, h; GLenum f; if (i == -2) { - att = &fb->DepthAttachment; + att = &fb->Attachment[BUFFER_DEPTH]; test_attachment_completeness(ctx, GL_DEPTH, att); if (!att->Complete) { - fb->Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT; + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT; return; } } else if (i == -1) { - att = &fb->StencilAttachment; + att = &fb->Attachment[BUFFER_STENCIL]; test_attachment_completeness(ctx, GL_STENCIL, att); if (!att->Complete) { - fb->Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT; + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT; return; } } else { - att = &fb->ColorAttachment[i]; + att = &fb->Attachment[BUFFER_COLOR0 + i]; test_attachment_completeness(ctx, GL_COLOR, att); if (!att->Complete) { - fb->Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT; + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT; return; } } @@ -474,57 +409,63 @@ test_framebuffer_completeness(GLcontext *ctx, else { /* check that width, height, format are same */ if (w != width || h != height) { - fb->Status = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT; + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT; return; } - if (i >= 0 && f != intFormat) { - fb->Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT; + if (intFormat != GL_NONE && f != intFormat) { + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT; return; } - } } /* Check that all DrawBuffers are present */ for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) { - if (fb->DrawBuffer[i] != GL_NONE) { - struct gl_renderbuffer_attachment *att - = get_attachment(ctx, fb, fb->DrawBuffer[i]); + if (fb->ColorDrawBuffer[i] != GL_NONE) { + const struct gl_renderbuffer_attachment *att + = get_attachment(ctx, fb, fb->ColorDrawBuffer[i]); + assert(att); if (att->Type == GL_NONE) { - fb->Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT; + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT; return; } } } /* Check that the ReadBuffer is present */ - if (fb->ReadBuffer != GL_NONE) { - struct gl_renderbuffer_attachment *att - = get_attachment(ctx, fb, fb->ReadBuffer); + if (fb->ColorReadBuffer != GL_NONE) { + const struct gl_renderbuffer_attachment *att + = get_attachment(ctx, fb, fb->ColorReadBuffer); + assert(att); if (att->Type == GL_NONE) { - fb->Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT; + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT; return; } } if (numImages == 0) { - fb->Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT; + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT; return; } -} + /* + * If we get here, the framebuffer is complete! + */ + fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT; + fb->Width = w; + fb->Height = h; +} GLboolean GLAPIENTRY _mesa_IsRenderbufferEXT(GLuint renderbuffer) { - const struct gl_renderbuffer *rb; GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); - - rb = lookup_renderbuffer(ctx, renderbuffer); - return rb ? GL_TRUE : GL_FALSE; + if (renderbuffer && lookup_renderbuffer(ctx, renderbuffer)) + return GL_TRUE; + else + return GL_FALSE; } @@ -535,6 +476,7 @@ _mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + FLUSH_VERTICES(ctx, _NEW_BUFFERS); if (target != GL_RENDERBUFFER_EXT) { _mesa_error(ctx, GL_INVALID_ENUM, @@ -568,7 +510,7 @@ _mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer) if (oldRb) { oldRb->RefCount--; if (oldRb->RefCount == 0) { - oldRb->Delete(ctx, oldRb); + oldRb->Delete(oldRb); } } @@ -600,7 +542,7 @@ _mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers) */ rb->RefCount--; if (rb->RefCount == 0) { - rb->Delete(ctx, rb); + rb->Delete(rb); } } } @@ -694,6 +636,7 @@ _mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat, GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + FLUSH_VERTICES(ctx, _NEW_BUFFERS); if (target != GL_RENDERBUFFER_EXT) { _mesa_error(ctx, GL_INVALID_ENUM, "glRenderbufferStorageEXT(target)"); @@ -741,6 +684,9 @@ _mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat, rb->_BaseFormat = GL_NONE; } + /* + test_framebuffer_completeness(ctx, fb); + */ /* XXX if this renderbuffer is attached anywhere, invalidate attachment * points??? */ @@ -787,23 +733,23 @@ _mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params) GLboolean GLAPIENTRY _mesa_IsFramebufferEXT(GLuint framebuffer) { - const struct gl_framebuffer *fb; GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); - - fb = lookup_framebuffer(ctx, framebuffer); - return fb ? GL_TRUE : GL_FALSE; + if (framebuffer && lookup_framebuffer(ctx, framebuffer)) + return GL_TRUE; + else + return GL_FALSE; } void GLAPIENTRY _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) { - struct gl_framebuffer *newFb, *oldFb; + struct gl_framebuffer *newFb, *newReadFb, *oldFb; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + FLUSH_VERTICES(ctx, _NEW_BUFFERS); if (target != GL_FRAMEBUFFER_EXT) { _mesa_error(ctx, GL_INVALID_ENUM, @@ -812,6 +758,7 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) } if (framebuffer) { + /* Binding a user-created framebuffer object */ newFb = lookup_framebuffer(ctx, framebuffer); if (newFb == &DummyFramebuffer) { /* ID was reserved, but no real framebuffer object made yet */ @@ -827,22 +774,29 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newFb); } newFb->RefCount++; + newReadFb = newFb; } else { - newFb = NULL; + /* Binding the window system framebuffer (which was originally set + * with MakeCurrent). + */ + newFb = ctx->WinSysDrawBuffer; + newReadFb = ctx->WinSysReadBuffer; } - oldFb = ctx->CurrentFramebuffer; - if (oldFb) { + oldFb = ctx->DrawBuffer; + if (oldFb) { /* AND oldFb->Name != 0 */ oldFb->RefCount--; if (oldFb->RefCount == 0) { - oldFb->Delete(ctx, oldFb); + oldFb->Delete(oldFb); } } ASSERT(newFb != &DummyFramebuffer); - ctx->CurrentFramebuffer = newFb; + /* Note, we set both the GL_DRAW_BUFFER and GL_READ_BUFFER state: */ + ctx->DrawBuffer = newFb; + ctx->ReadBuffer = newReadFb; } @@ -859,6 +813,7 @@ _mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers) struct gl_framebuffer *fb; fb = lookup_framebuffer(ctx, framebuffers[i]); if (fb) { + ASSERT(fb == &DummyFramebuffer || fb->Name == framebuffers[i]); /* remove from hash table immediately, to free the ID */ _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]); @@ -868,7 +823,7 @@ _mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers) */ fb->RefCount--; if (fb->RefCount == 0) { - fb->Delete(ctx, fb); + fb->Delete(fb); } } } @@ -913,20 +868,20 @@ _mesa_CheckFramebufferStatusEXT(GLenum target) { GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FRAMEBUFFER_STATUS_ERROR_EXT); + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0); if (target != GL_FRAMEBUFFER_EXT) { _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)"); - return GL_FRAMEBUFFER_STATUS_ERROR_EXT; + return 0; /* formerly GL_FRAMEBUFFER_STATUS_ERROR_EXT */ } - if (!ctx->CurrentFramebuffer) { + if (ctx->DrawBuffer->Name == 0) { /* The window system / default framebuffer is always complete */ return GL_FRAMEBUFFER_COMPLETE_EXT; } - test_framebuffer_completeness(ctx, ctx->CurrentFramebuffer); - return ctx->CurrentFramebuffer->Status; + _mesa_test_framebuffer_completeness(ctx, ctx->DrawBuffer); + return ctx->DrawBuffer->_Status; } @@ -948,13 +903,14 @@ error_check_framebuffer_texture(GLcontext *ctx, GLuint dims, return GL_TRUE; } - if (ctx->CurrentFramebuffer == NULL) { + /* check framebuffer binding */ + if (ctx->DrawBuffer->Name == 0) { _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferTexture%dDEXT", dims); return GL_TRUE; } - /* only check textarget, level if texture ID is non-zero*/ + /* only check textarget, level if texture ID is non-zero */ if (texture) { if ((dims == 1 && textarget != GL_TEXTURE_1D) || (dims == 3 && textarget != GL_TEXTURE_3D) || @@ -982,9 +938,11 @@ _mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) { struct gl_renderbuffer_attachment *att; + struct gl_texture_object *texObj; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + FLUSH_VERTICES(ctx, _NEW_BUFFERS); /* XXX check */ if (error_check_framebuffer_texture(ctx, 1, target, attachment, textarget, texture, level)) @@ -992,7 +950,7 @@ _mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment, ASSERT(textarget == GL_TEXTURE_1D); - att = get_attachment(ctx, ctx->CurrentFramebuffer, attachment); + att = get_attachment(ctx, ctx->DrawBuffer, attachment); if (att == NULL) { _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferTexture1DEXT(attachment)"); @@ -1000,7 +958,7 @@ _mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment, } if (texture) { - struct gl_texture_object *texObj = (struct gl_texture_object *) + texObj = (struct gl_texture_object *) _mesa_HashLookup(ctx->Shared->TexObjects, texture); if (!texObj) { _mesa_error(ctx, GL_INVALID_VALUE, @@ -1012,13 +970,12 @@ _mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment, "glFramebufferTexture1DEXT(texture target)"); return; } - set_texture_attachment(ctx, att, texObj, textarget, level, 0); } else { - remove_attachment(ctx, att); + /* remove texture attachment */ + texObj = NULL; } - - /* XXX call a driver function to signal new attachment? */ + ctx->Driver.RenderbufferTexture(ctx, att, texObj, textarget, level, 0); } @@ -1027,9 +984,11 @@ _mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) { struct gl_renderbuffer_attachment *att; + struct gl_texture_object *texObj; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + FLUSH_VERTICES(ctx, _NEW_BUFFERS); /* XXX check */ if (error_check_framebuffer_texture(ctx, 2, target, attachment, textarget, texture, level)) @@ -1039,7 +998,7 @@ _mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment, textarget == GL_TEXTURE_RECTANGLE_ARB || IS_CUBE_FACE(textarget)); - att = get_attachment(ctx, ctx->CurrentFramebuffer, attachment); + att = get_attachment(ctx, ctx->DrawBuffer, attachment); if (att == NULL) { _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferTexture2DEXT(attachment)"); @@ -1047,7 +1006,7 @@ _mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment, } if (texture) { - struct gl_texture_object *texObj = (struct gl_texture_object *) + texObj = (struct gl_texture_object *) _mesa_HashLookup(ctx->Shared->TexObjects, texture); if (!texObj) { _mesa_error(ctx, GL_INVALID_VALUE, @@ -1063,12 +1022,12 @@ _mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment, "glFramebufferTexture2DEXT(texture target)"); return; } - set_texture_attachment(ctx, att, texObj, textarget, level, 0); } else { - remove_attachment(ctx, att); + /* remove texture attachment */ + texObj = NULL; } - + ctx->Driver.RenderbufferTexture(ctx, att, texObj, textarget, level, 0); } @@ -1078,9 +1037,11 @@ _mesa_FramebufferTexture3DEXT(GLenum target, GLenum attachment, GLint level, GLint zoffset) { struct gl_renderbuffer_attachment *att; + struct gl_texture_object *texObj; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + FLUSH_VERTICES(ctx, _NEW_BUFFERS); /* XXX check */ if (error_check_framebuffer_texture(ctx, 3, target, attachment, textarget, texture, level)) @@ -1088,7 +1049,7 @@ _mesa_FramebufferTexture3DEXT(GLenum target, GLenum attachment, ASSERT(textarget == GL_TEXTURE_3D); - att = get_attachment(ctx, ctx->CurrentFramebuffer, attachment); + att = get_attachment(ctx, ctx->DrawBuffer, attachment); if (att == NULL) { _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferTexture1DEXT(attachment)"); @@ -1097,7 +1058,7 @@ _mesa_FramebufferTexture3DEXT(GLenum target, GLenum attachment, if (texture) { const GLint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1); - struct gl_texture_object *texObj = (struct gl_texture_object *) + texObj = (struct gl_texture_object *) _mesa_HashLookup(ctx->Shared->TexObjects, texture); if (!texObj) { _mesa_error(ctx, GL_INVALID_VALUE, @@ -1114,11 +1075,13 @@ _mesa_FramebufferTexture3DEXT(GLenum target, GLenum attachment, "glFramebufferTexture3DEXT(zoffset)"); return; } - set_texture_attachment(ctx, att, texObj, textarget, level, zoffset); } else { - remove_attachment(ctx, att); + /* remove texture attachment */ + texObj = NULL; } + ctx->Driver.RenderbufferTexture(ctx, att, texObj, textarget, + level, zoffset); } @@ -1128,9 +1091,11 @@ _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment, GLuint renderbuffer) { struct gl_renderbuffer_attachment *att; + struct gl_renderbuffer *rb; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + FLUSH_VERTICES(ctx, _NEW_BUFFERS); if (target != GL_FRAMEBUFFER_EXT) { _mesa_error(ctx, GL_INVALID_ENUM, @@ -1139,17 +1104,17 @@ _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment, } if (renderbufferTarget != GL_RENDERBUFFER_EXT) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glFramebufferRenderbufferEXT(renderbufferTarget)"); + _mesa_error(ctx, GL_INVALID_ENUM, + "glFramebufferRenderbufferEXT(renderbufferTarget)"); return; } - if (ctx->CurrentFramebuffer == NULL) { + if (ctx->DrawBuffer->Name == 0) { _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbufferEXT"); return; } - att = get_attachment(ctx, ctx->CurrentFramebuffer, attachment); + att = get_attachment(ctx, ctx->DrawBuffer, attachment); if (att == NULL) { _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferRenderbufferEXT(attachment)"); @@ -1157,18 +1122,22 @@ _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment, } if (renderbuffer) { - struct gl_renderbuffer *rb; rb = lookup_renderbuffer(ctx, renderbuffer); if (!rb) { - _mesa_error(ctx, GL_INVALID_VALUE, + _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbufferEXT(renderbuffer)"); return; } - set_renderbuffer_attachment(ctx, att, rb); } else { - remove_attachment(ctx, att); + /* remove renderbuffer attachment */ + rb = NULL; } + + assert(ctx->Driver.FramebufferRenderbuffer); + ctx->Driver.FramebufferRenderbuffer(ctx, att, rb); + + _mesa_update_framebuffer_visual(ctx->DrawBuffer); } @@ -1187,13 +1156,13 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, return; } - if (ctx->CurrentFramebuffer == NULL) { + if (ctx->DrawBuffer->Name == 0) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetFramebufferAttachmentParameterivEXT"); return; } - att = get_attachment(ctx, ctx->CurrentFramebuffer, attachment); + att = get_attachment(ctx, ctx->DrawBuffer, attachment); if (att == NULL) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetFramebufferAttachmentParameterivEXT(attachment)"); |