Added FinishRenderTexture() device driver function to indicate when

rendering to a texture has likely completed.
Fixed refcount issue in texture renderbuffer wrapper.
This commit is contained in:
Brian Paul 2005-12-01 00:25:00 +00:00
parent cf2702e3db
commit 0e31e02aef
3 changed files with 65 additions and 19 deletions

View file

@ -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

View file

@ -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);

View file

@ -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);