From: Brian Paul Date: Thu, 1 Dec 2005 00:25:00 +0000 (+0000) Subject: Added FinishRenderTexture() device driver function to indicate when X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=0e31e02aef4fe44b1196d0bf6e351250d9d8f68c;p=mesa.git Added FinishRenderTexture() device driver function to indicate when rendering to a texture has likely completed. Fixed refcount issue in texture renderbuffer wrapper. --- diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h index 1e7a93e939a..8c7549162c4 100644 --- a/src/mesa/main/dd.h +++ b/src/mesa/main/dd.h @@ -809,6 +809,9 @@ struct dd_function_table { struct gl_renderbuffer_attachment *att, struct gl_texture_object *texObj, GLenum texTarget, GLuint level, GLuint zoffset); + void (*FinishRenderTexture)(GLcontext *ctx, + struct gl_texture_object *texObj, + GLuint face, GLuint level); /*@}*/ #endif #if FEATURE_EXT_framebuffer_blit diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c index 43e4793d554..3e425bd6724 100644 --- a/src/mesa/main/fbobject.c +++ b/src/mesa/main/fbobject.c @@ -154,19 +154,21 @@ _mesa_remove_attachment(GLcontext *ctx, struct gl_renderbuffer_attachment *att) { if (att->Type == GL_TEXTURE) { ASSERT(att->Texture); - 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); } + else { + /* tell driver that we're done rendering to this texture. */ + if (ctx->Driver.FinishRenderTexture) { + ctx->Driver.FinishRenderTexture(ctx, att->Texture, + att->CubeMapFace, + att->TextureLevel); + } + } att->Texture = NULL; } - else if (att->Type == GL_RENDERBUFFER_EXT) { + if (att->Type == GL_TEXTURE || att->Type == GL_RENDERBUFFER_EXT) { ASSERT(att->Renderbuffer); ASSERT(!att->Texture); att->Renderbuffer->RefCount--; @@ -190,9 +192,19 @@ _mesa_set_texture_attachment(GLcontext *ctx, struct gl_texture_object *texObj, GLenum texTarget, GLuint level, GLuint zoffset) { - _mesa_remove_attachment(ctx, att); - att->Type = GL_TEXTURE; - att->Texture = texObj; + if (att->Texture == texObj) { + /* re-attaching same texture */ + ASSERT(att->Type == GL_TEXTURE); + } + else { + /* new attachment */ + _mesa_remove_attachment(ctx, att); + att->Type = GL_TEXTURE; + att->Texture = texObj; + texObj->RefCount++; + } + + /* always update these fields */ att->TextureLevel = level; if (IS_CUBE_FACE(texTarget)) { att->CubeMapFace = texTarget - GL_TEXTURE_CUBE_MAP_POSITIVE_X; @@ -202,13 +214,6 @@ _mesa_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 - * att->Renderbuffer pointer to a "wrapper renderbuffer" which - * makes the texture image look like renderbuffer. - */ } @@ -758,6 +763,8 @@ _mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat, 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->_BaseFormat = baseFormat; } else { @@ -766,6 +773,13 @@ _mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat, rb->Height = 0; rb->InternalFormat = GL_NONE; rb->_BaseFormat = GL_NONE; + rb->RedBits = + rb->GreenBits = + rb->BlueBits = + rb->AlphaBits = + rb->IndexBits = + rb->DepthBits = + rb->StencilBits = 0; } /* @@ -848,6 +862,28 @@ _mesa_IsFramebufferEXT(GLuint framebuffer) } +/** + * 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) +{ + if (ctx->Driver.FinishRenderTexture) { + GLuint i; + 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.FinishRenderTexture(ctx, texObj, att->CubeMapFace, + att->TextureLevel); + } + } + } +} + + void GLAPIENTRY _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) { @@ -931,6 +967,11 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) if (bindDrawBuf) { 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 if time to delete this framebuffer */ oldFb->RefCount--; if (oldFb->RefCount == 0) { oldFb->Delete(oldFb); diff --git a/src/mesa/main/texrender.c b/src/mesa/main/texrender.c index 9c21e03515a..a4efe640382 100644 --- a/src/mesa/main/texrender.c +++ b/src/mesa/main/texrender.c @@ -124,6 +124,7 @@ texture_put_mono_values(GLcontext *ctx, struct gl_renderbuffer *rb, static void delete_texture_wrapper(struct gl_renderbuffer *rb) { + ASSERT(rb->RefCount == 0); _mesa_free(rb); } @@ -162,6 +163,7 @@ wrap_texture(GLcontext *ctx, struct gl_renderbuffer_attachment *att) trb->Zoffset = att->Zoffset; + trb->Base.RefCount = 1; trb->Base.Width = trb->TexImage->Width; trb->Base.Height = trb->TexImage->Height; trb->Base.InternalFormat = trb->TexImage->InternalFormat; /* XXX fix? */ @@ -213,8 +215,8 @@ _mesa_renderbuffer_texture(GLcontext *ctx, if (texObj) { _mesa_set_texture_attachment(ctx, att, texObj, texTarget, level, zoffset); - - wrap_texture(ctx, att); + if (!att->Renderbuffer) + wrap_texture(ctx, att); } else { _mesa_remove_attachment(ctx, att);