diff options
author | Brian Paul <[email protected]> | 2006-03-26 05:22:17 +0000 |
---|---|---|
committer | Brian Paul <[email protected]> | 2006-03-26 05:22:17 +0000 |
commit | ea4fe661d7f3a95d9db17e1475076f1badf8e1a6 (patch) | |
tree | ffc663f1a02dea07254e08620f8ad872fb1a3e20 /src/mesa/main/fbobject.c | |
parent | 4cbd16ed3ffecd743b4921fab3a65f8510d151c9 (diff) |
merge from texman branchmesa_20060325
Diffstat (limited to 'src/mesa/main/fbobject.c')
-rw-r--r-- | src/mesa/main/fbobject.c | 346 |
1 files changed, 177 insertions, 169 deletions
diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c index 53c4d27e81a..ec690bdbf7f 100644 --- a/src/mesa/main/fbobject.c +++ b/src/mesa/main/fbobject.c @@ -36,6 +36,7 @@ #include "renderbuffer.h" #include "state.h" #include "teximage.h" +#include "texobj.h" #include "texstore.h" @@ -66,8 +67,8 @@ static struct gl_renderbuffer DummyRenderbuffer; /** * Helper routine for getting a gl_renderbuffer. */ -static struct gl_renderbuffer * -lookup_renderbuffer(GLcontext *ctx, GLuint id) +struct gl_renderbuffer * +_mesa_lookup_renderbuffer(GLcontext *ctx, GLuint id) { struct gl_renderbuffer *rb; @@ -83,8 +84,8 @@ lookup_renderbuffer(GLcontext *ctx, GLuint id) /** * Helper routine for getting a gl_framebuffer. */ -static struct gl_framebuffer * -lookup_framebuffer(GLcontext *ctx, GLuint id) +struct gl_framebuffer * +_mesa_lookup_framebuffer(GLcontext *ctx, GLuint id) { struct gl_framebuffer *fb; @@ -209,7 +210,7 @@ _mesa_set_texture_attachment(GLcontext *ctx, att->Complete = GL_FALSE; if (att->Texture->Image[att->CubeMapFace][att->TextureLevel]) { - ctx->Driver.RenderbufferTexture(ctx, fb, att); + ctx->Driver.RenderTexture(ctx, fb, att); } } @@ -223,6 +224,7 @@ _mesa_set_renderbuffer_attachment(GLcontext *ctx, struct gl_renderbuffer_attachment *att, struct gl_renderbuffer *rb) { + /* XXX check if re-doing same attachment, exit early */ _mesa_remove_attachment(ctx, att); att->Type = GL_RENDERBUFFER_EXT; att->Renderbuffer = rb; @@ -242,6 +244,10 @@ _mesa_framebuffer_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb, { struct gl_renderbuffer_attachment *att; + _glthread_LOCK_MUTEX(fb->Mutex); + if (rb) + _glthread_LOCK_MUTEX(rb->Mutex); + att = _mesa_get_attachment(ctx, fb, attachment); ASSERT(att); @@ -251,6 +257,10 @@ _mesa_framebuffer_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb, else { _mesa_remove_attachment(ctx, att); } + + if (rb) + _glthread_UNLOCK_MUTEX(rb->Mutex); + _glthread_UNLOCK_MUTEX(fb->Mutex); } @@ -554,7 +564,7 @@ _mesa_IsRenderbufferEXT(GLuint renderbuffer) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); if (renderbuffer) { - struct gl_renderbuffer *rb = lookup_renderbuffer(ctx, renderbuffer); + struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer); if (rb != NULL && rb != &DummyRenderbuffer) return GL_TRUE; } @@ -579,7 +589,7 @@ _mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer) FLUSH_VERTICES(ctx, _NEW_BUFFERS); if (renderbuffer) { - newRb = lookup_renderbuffer(ctx, renderbuffer); + newRb = _mesa_lookup_renderbuffer(ctx, renderbuffer); if (newRb == &DummyRenderbuffer) { /* ID was reserved, but no real renderbuffer object made yet */ newRb = NULL; @@ -626,7 +636,7 @@ _mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers) for (i = 0; i < n; i++) { if (renderbuffers[i] > 0) { struct gl_renderbuffer *rb; - rb = lookup_renderbuffer(ctx, renderbuffers[i]); + rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]); if (rb) { /* check if deleting currently bound renderbuffer object */ if (rb == ctx->CurrentRenderbuffer) { @@ -786,15 +796,26 @@ _mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat, return; } + /* These MUST get set by the AllocStorage func */ + rb->_ActualFormat = 0; + rb->RedBits = + rb->GreenBits = + rb->BlueBits = + rb->AlphaBits = + rb->IndexBits = + rb->DepthBits = + rb->StencilBits = 0; + /* Now allocate the storage */ ASSERT(rb->AllocStorage); if (rb->AllocStorage(ctx, rb, internalFormat, width, height)) { /* No error - check/set fields now */ + assert(rb->_ActualFormat); assert(rb->Width == width); assert(rb->Height == height); - assert(rb->InternalFormat); assert(rb->RedBits || rb->GreenBits || rb->BlueBits || rb->AlphaBits || rb->DepthBits || rb->StencilBits || rb->IndexBits); + rb->InternalFormat = internalFormat; rb->_BaseFormat = baseFormat; } else { @@ -802,6 +823,7 @@ _mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat, rb->Width = 0; rb->Height = 0; rb->InternalFormat = GL_NONE; + rb->_ActualFormat = GL_NONE; rb->_BaseFormat = GL_NONE; rb->RedBits = rb->GreenBits = @@ -884,7 +906,7 @@ _mesa_IsFramebufferEXT(GLuint framebuffer) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); if (framebuffer) { - struct gl_framebuffer *rb = lookup_framebuffer(ctx, framebuffer); + struct gl_framebuffer *rb = _mesa_lookup_framebuffer(ctx, framebuffer); if (rb != NULL && rb != &DummyFramebuffer) return GL_TRUE; } @@ -892,13 +914,28 @@ _mesa_IsFramebufferEXT(GLuint framebuffer) } +static void +check_begin_texture_render(GLcontext *ctx, struct gl_framebuffer *fb) +{ + GLuint i; + ASSERT(ctx->Driver.RenderTexture); + for (i = 0; i < BUFFER_COUNT; i++) { + struct gl_renderbuffer_attachment *att = fb->Attachment + i; + struct gl_texture_object *texObj = att->Texture; + if (texObj) { + ctx->Driver.RenderTexture(ctx, fb, att); + } + } +} + + /** * Examine all the framebuffer's attachments to see if any are textures. * If so, call ctx->Driver.FinishRenderTexture() for each texture to * notify the device driver that the texture image may have changed. */ static void -check_texture_render(GLcontext *ctx, struct gl_framebuffer *fb) +check_end_texture_render(GLcontext *ctx, struct gl_framebuffer *fb) { if (ctx->Driver.FinishRenderTexture) { GLuint i; @@ -922,6 +959,12 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) ASSERT_OUTSIDE_BEGIN_END(ctx); + if (!ctx->Extensions.EXT_framebuffer_object) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBindFramebufferEXT(unsupported)"); + return; + } + switch (target) { #if FEATURE_EXT_framebuffer_blit case GL_DRAW_FRAMEBUFFER_EXT: @@ -954,7 +997,7 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) if (framebuffer) { /* Binding a user-created framebuffer object */ - newFb = lookup_framebuffer(ctx, framebuffer); + newFb = _mesa_lookup_framebuffer(ctx, framebuffer); if (newFb == &DummyFramebuffer) { /* ID was reserved, but no real framebuffer object made yet */ newFb = NULL; @@ -968,10 +1011,12 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) } _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newFb); } + _glthread_LOCK_MUTEX(newFb->Mutex); if (bindReadBuf) newFb->RefCount++; if (bindDrawBuf) newFb->RefCount++; + _glthread_UNLOCK_MUTEX(newFb->Mutex); } else { /* Binding the window system framebuffer (which was originally set @@ -980,12 +1025,19 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) newFb = ctx->WinSysDrawBuffer; } + ASSERT(newFb); ASSERT(newFb != &DummyFramebuffer); + /* + * XXX check if re-binding same buffer and skip some of this code. + */ + if (bindReadBuf) { oldFb = ctx->ReadBuffer; if (oldFb && oldFb->Name != 0) { + _glthread_LOCK_MUTEX(oldFb->Mutex); oldFb->RefCount--; + _glthread_UNLOCK_MUTEX(oldFb->Mutex); if (oldFb->RefCount == 0) { oldFb->Delete(oldFb); } @@ -997,16 +1049,20 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) oldFb = ctx->DrawBuffer; if (oldFb && oldFb->Name != 0) { /* check if old FB had any texture attachments */ - if (ctx->Driver.FinishRenderTexture) { - check_texture_render(ctx, oldFb); - } + check_end_texture_render(ctx, oldFb); /* check if time to delete this framebuffer */ + _glthread_LOCK_MUTEX(oldFb->Mutex); oldFb->RefCount--; if (oldFb->RefCount == 0) { oldFb->Delete(oldFb); } + _glthread_UNLOCK_MUTEX(oldFb->Mutex); } ctx->DrawBuffer = newFb; + if (newFb->Name != 0) { + /* check if newly bound framebuffer has any texture attachments */ + check_begin_texture_render(ctx, newFb); + } } if (ctx->Driver.BindFramebuffer) { @@ -1027,7 +1083,7 @@ _mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers) for (i = 0; i < n; i++) { if (framebuffers[i] > 0) { struct gl_framebuffer *fb; - fb = lookup_framebuffer(ctx, framebuffers[i]); + fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]); if (fb) { ASSERT(fb == &DummyFramebuffer || fb->Name == framebuffers[i]); @@ -1045,7 +1101,9 @@ _mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers) /* But the object will not be freed until it's no longer * bound in any context. */ + _glthread_LOCK_MUTEX(fb->Mutex); fb->RefCount--; + _glthread_UNLOCK_MUTEX(fb->Mutex); if (fb->RefCount == 0) { fb->Delete(fb); } @@ -1134,152 +1192,144 @@ _mesa_CheckFramebufferStatusEXT(GLenum target) /** - * Do error checking common to glFramebufferTexture1D/2D/3DEXT. - * \return GL_TRUE if any error, GL_FALSE otherwise + * Common code called by glFramebufferTexture1D/2D/3DEXT(). */ -static GLboolean -error_check_framebuffer_texture(GLcontext *ctx, GLuint dims, - GLenum target, GLenum attachment, - GLenum textarget, GLuint texture, GLint level) +static void +framebuffer_texture(GLuint dims, GLenum target, GLenum attachment, + GLenum textarget, GLuint texture, + GLint level, GLint zoffset) { - ASSERT(dims >= 1 && dims <= 3); + struct gl_renderbuffer_attachment *att; + struct gl_texture_object *texObj = NULL; + struct gl_framebuffer *fb; + GET_CURRENT_CONTEXT(ctx); + + ASSERT_OUTSIDE_BEGIN_END(ctx); if (target != GL_FRAMEBUFFER_EXT) { _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferTexture%dDEXT(target)", dims); - return GL_TRUE; + return; } + fb = ctx->DrawBuffer; + ASSERT(fb); + /* check framebuffer binding */ - if (ctx->DrawBuffer->Name == 0) { + if (fb->Name == 0) { _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferTexture%dDEXT", dims); - return GL_TRUE; + return; } - /* 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) || - (dims == 2 && textarget != GL_TEXTURE_2D && - textarget != GL_TEXTURE_RECTANGLE_ARB && - !IS_CUBE_FACE(textarget))) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glFramebufferTexture%dDEXT(textarget)", dims); - return GL_TRUE; - } + texObj = _mesa_lookup_texture(ctx, texture); + } - if ((level < 0) || level >= _mesa_max_texture_levels(ctx, textarget)) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glFramebufferTexture%dDEXT(level)", dims); - return GL_TRUE; + /* Check dimension-dependent things */ + switch (dims) { + case 1: + if (textarget != GL_TEXTURE_1D) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glFramebufferTexture1DEXT(textarget)"); + return; } + if (texObj && texObj->Target != GL_TEXTURE_1D) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glFramebufferTexture1DEXT(texture target mismatch)"); + return; + } + break; + case 2: + if (textarget != GL_TEXTURE_2D && + textarget != GL_TEXTURE_RECTANGLE_ARB && + !IS_CUBE_FACE(textarget)) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glFramebufferTexture2DEXT(textarget)"); + return; + } + if (texObj) { + if ((texObj->Target == GL_TEXTURE_2D && textarget != GL_TEXTURE_2D) || + (texObj->Target == GL_TEXTURE_RECTANGLE_ARB + && textarget != GL_TEXTURE_RECTANGLE_ARB) || + (texObj->Target == GL_TEXTURE_CUBE_MAP + && !IS_CUBE_FACE(textarget))) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glFramebufferTexture1DEXT(texture target mismatch)"); + return; + } + } + break; + case 3: + if (textarget != GL_TEXTURE_3D) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glFramebufferTexture3DEXT(textarget)"); + return; + } + if (texObj && texObj->Target != GL_TEXTURE_3D) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glFramebufferTexture3DEXT(texture target mismatch)"); + return; + } + { + const GLint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1); + if (zoffset < 0 || zoffset >= maxSize) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glFramebufferTexture3DEXT(zoffset)"); + return; + } + } + break; + default: + _mesa_problem(ctx, "Unexpected dims in error_check_framebuffer_texture"); + return; } - return GL_FALSE; -} - - -/** - * XXX The code in _mesa_FramebufferTexture1/2/3DEXT could be probably - * be combined into one function. - */ -void GLAPIENTRY -_mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment, - GLenum textarget, GLuint texture, GLint level) -{ - struct gl_renderbuffer_attachment *att; - GET_CURRENT_CONTEXT(ctx); - - ASSERT_OUTSIDE_BEGIN_END(ctx); - - if (error_check_framebuffer_texture(ctx, 1, target, attachment, - textarget, texture, level)) + if ((level < 0) || level >= _mesa_max_texture_levels(ctx, textarget)) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glFramebufferTexture%dDEXT(level)", dims); return; + } - ASSERT(textarget == GL_TEXTURE_1D); - - /* XXX read blit */ - att = _mesa_get_attachment(ctx, ctx->DrawBuffer, attachment); + att = _mesa_get_attachment(ctx, fb, attachment); if (att == NULL) { _mesa_error(ctx, GL_INVALID_ENUM, - "glFramebufferTexture1DEXT(attachment)"); + "glFramebufferTexture%dDEXT(attachment)", dims); return; } FLUSH_VERTICES(ctx, _NEW_BUFFERS); - if (texture) { - struct gl_texture_object *texObj = (struct gl_texture_object *) - _mesa_HashLookup(ctx->Shared->TexObjects, texture); - if (!texObj) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glFramebufferTexture1DEXT(texture)"); - return; - } - if (texObj->Target != textarget) { - _mesa_error(ctx, GL_INVALID_OPERATION, /* XXX correct error? */ - "glFramebufferTexture1DEXT(texture target)"); - return; - } - _mesa_set_texture_attachment(ctx, ctx->DrawBuffer, att, - texObj, textarget, level, 0); + _glthread_LOCK_MUTEX(fb->Mutex); + if (texObj) { + _mesa_set_texture_attachment(ctx, fb, att, texObj, textarget, + level, zoffset); } else { _mesa_remove_attachment(ctx, att); } + _glthread_UNLOCK_MUTEX(fb->Mutex); } + void GLAPIENTRY -_mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment, +_mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) { - struct gl_renderbuffer_attachment *att; - GET_CURRENT_CONTEXT(ctx); - - ASSERT_OUTSIDE_BEGIN_END(ctx); - - if (error_check_framebuffer_texture(ctx, 2, target, attachment, - textarget, texture, level)) - return; + const GLint zoffset = 0; + framebuffer_texture(1, target, attachment, textarget, texture, + level, zoffset); +} - ASSERT(textarget == GL_TEXTURE_2D || - textarget == GL_TEXTURE_RECTANGLE_ARB || - IS_CUBE_FACE(textarget)); - att = _mesa_get_attachment(ctx, ctx->DrawBuffer, attachment); - if (att == NULL) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glFramebufferTexture2DEXT(attachment)"); - return; - } - - FLUSH_VERTICES(ctx, _NEW_BUFFERS); - - if (texture) { - struct gl_texture_object *texObj = (struct gl_texture_object *) - _mesa_HashLookup(ctx->Shared->TexObjects, texture); - if (!texObj) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glFramebufferTexture2DEXT(texture)"); - return; - } - if ((texObj->Target == GL_TEXTURE_2D && textarget != GL_TEXTURE_2D) || - (texObj->Target == GL_TEXTURE_RECTANGLE_ARB - && textarget != GL_TEXTURE_RECTANGLE_ARB) || - (texObj->Target == GL_TEXTURE_CUBE_MAP - && !IS_CUBE_FACE(textarget))) { - _mesa_error(ctx, GL_INVALID_OPERATION, /* XXX correct error? */ - "glFramebufferTexture2DEXT(texture target)"); - return; - } - _mesa_set_texture_attachment(ctx, ctx->DrawBuffer, att, - texObj, textarget, level, 0); - } - else { - _mesa_remove_attachment(ctx, att); - } +void GLAPIENTRY +_mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment, + GLenum textarget, GLuint texture, GLint level) +{ + const GLint zoffset = 0; + framebuffer_texture(2, target, attachment, textarget, texture, + level, zoffset); } @@ -1288,54 +1338,12 @@ _mesa_FramebufferTexture3DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) { - struct gl_renderbuffer_attachment *att; - GET_CURRENT_CONTEXT(ctx); - - ASSERT_OUTSIDE_BEGIN_END(ctx); - - if (error_check_framebuffer_texture(ctx, 3, target, attachment, - textarget, texture, level)) - return; - - ASSERT(textarget == GL_TEXTURE_3D); - - att = _mesa_get_attachment(ctx, ctx->DrawBuffer, attachment); - if (att == NULL) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glFramebufferTexture1DEXT(attachment)"); - return; - } - - FLUSH_VERTICES(ctx, _NEW_BUFFERS); - - if (texture) { - const GLint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1); - struct gl_texture_object *texObj = (struct gl_texture_object *) - _mesa_HashLookup(ctx->Shared->TexObjects, texture); - if (!texObj) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glFramebufferTexture3DEXT(texture)"); - return; - } - if (texObj->Target != textarget) { - _mesa_error(ctx, GL_INVALID_OPERATION, /* XXX correct error? */ - "glFramebufferTexture3DEXT(texture target)"); - return; - } - if (zoffset < 0 || zoffset >= maxSize) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glFramebufferTexture3DEXT(zoffset)"); - return; - } - _mesa_set_texture_attachment(ctx, ctx->DrawBuffer, att, - texObj, textarget, level,zoffset); - } - else { - _mesa_remove_attachment(ctx, att); - } + framebuffer_texture(3, target, attachment, textarget, texture, + level, zoffset); } + void GLAPIENTRY _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment, GLenum renderbufferTarget, @@ -1396,7 +1404,7 @@ _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment, } if (renderbuffer) { - rb = lookup_renderbuffer(ctx, renderbuffer); + rb = _mesa_lookup_renderbuffer(ctx, renderbuffer); if (!rb) { _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbufferEXT(renderbuffer)"); |