Added FinishRenderTexture() device driver function to indicate when
authorBrian Paul <brian.paul@tungstengraphics.com>
Thu, 1 Dec 2005 00:25:00 +0000 (00:25 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Thu, 1 Dec 2005 00:25:00 +0000 (00:25 +0000)
rendering to a texture has likely completed.
Fixed refcount issue in texture renderbuffer wrapper.

src/mesa/main/dd.h
src/mesa/main/fbobject.c
src/mesa/main/texrender.c

index 1e7a93e939aa5591672791f4f8f6adcfdb5f867b..8c7549162c493f8ba236165e843e150f53276f05 100644 (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
index 43e4793d55412373bb868d453b7aebd027401c3f..3e425bd6724ec122357c439759dbf67c23fcee26 100644 (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);
index 9c21e03515aeebc0bf5a8bc988cf8979ceb12553..a4efe64038246498e6853390db9231819b533a80 100644 (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);