From 24f7050dd447df52d3cbf53b4594a95f2ea637b6 Mon Sep 17 00:00:00 2001
From: Fabian Bieler <der.f...@gmx.net>
Date: Sat, 2 Apr 2011 12:19:49 +0200
Subject: [PATCH 2/3] st/mesa: Finalize fbo texture attachments

This patch tries to make sure that the texture image that should be attached to
the fbo actually lives in the gallium texture object that is attached,
i.e. that they have the same pipe resource.

You can still construct some pathological example where this fails.
E.g.: If you have a 2D texture object with only level 1 specified which has a
width of 1, guess_base_leve_size fails and the texture object can't be created.

In such cases the fbo will be marked as incomplete (GL_UNSUPPORTED).
---
 src/mesa/state_tracker/st_cb_fbo.c     |   19 ++++++++++--
 src/mesa/state_tracker/st_cb_texture.c |   50 ++++++++++++++++++++++++++++++++
 src/mesa/state_tracker/st_cb_texture.h |    4 ++
 3 files changed, 70 insertions(+), 3 deletions(-)

diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c
index 7ffee90..31348a6 100644
--- a/src/mesa/state_tracker/st_cb_fbo.c
+++ b/src/mesa/state_tracker/st_cb_fbo.c
@@ -48,6 +48,7 @@
 #include "st_cb_fbo.h"
 #include "st_cb_flush.h"
 #include "st_format.h"
+#include "st_cb_texture.h"
 #include "st_texture.h"
 #include "st_manager.h"
 
@@ -343,14 +344,20 @@ st_render_texture(struct gl_context *ctx,
    struct pipe_context *pipe = st->pipe;
    struct st_renderbuffer *strb;
    struct gl_renderbuffer *rb;
-   struct pipe_resource *pt = st_get_texobj_resource(att->Texture);
+   struct pipe_resource *pt;
    struct st_texture_object *stObj;
    const struct gl_texture_image *texImage;
    struct pipe_surface surf_tmpl;
 
-   /* When would this fail?  Perhaps assert? */
-   if (!pt) 
+   /* Make sure the gallium texture exists and that the texture image is in it.
+    */
+   if (!st_finalize_fbo_tex(ctx, att->Texture,
+                            att->CubeMapFace, att->TextureLevel)) {
+      st_invalidate_state(ctx, _NEW_BUFFERS);
       return;
+   }
+
+   pt = st_get_texobj_resource(att->Texture);
 
    /* get pointer to texture image we're rendeing to */
    texImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
@@ -457,6 +464,7 @@ st_validate_attachment(struct gl_context *ctx,
 		       unsigned bindings)
 {
    const struct st_texture_object *stObj = st_texture_object(att->Texture);
+   const struct st_texture_image *stImage;
    enum pipe_format format;
    gl_format texFormat;
 
@@ -470,6 +478,11 @@ st_validate_attachment(struct gl_context *ctx,
    if (!stObj)
       return GL_FALSE;
 
+   stImage =
+      st_texture_image(stObj->base.Image[att->CubeMapFace][att->TextureLevel]);
+   if (!stObj->pt || stObj->pt != stImage->pt)
+      return GL_FALSE;
+
    format = stObj->pt->format;
    texFormat =
       stObj->base.Image[att->CubeMapFace][att->TextureLevel]->TexFormat;
diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c
index 9d5eb11..4a0c087 100644
--- a/src/mesa/state_tracker/st_cb_texture.c
+++ b/src/mesa/state_tracker/st_cb_texture.c
@@ -1845,6 +1845,56 @@ st_finalize_texture(struct gl_context *ctx,
 
 
 /**
+ * Called when attaching a texture to a fbo.  When this function is finished,
+ * the via face and level specified image of the texture object should be ready
+ * to be rendered to.
+ * \return GL_TRUE for success, GL_FALSE for failure.
+ */
+GLboolean
+st_finalize_fbo_tex(struct gl_context *ctx,
+		    struct gl_texture_object *tObj,
+		    GLuint face, GLuint level)
+{
+   struct st_context *st = st_context(ctx);
+
+   struct st_texture_object *stObj = st_texture_object(tObj);
+   struct gl_texture_image *image = tObj->Image[face][level];
+   struct st_texture_image *stImage = st_texture_image(image);
+
+   if (stObj->pt && stObj->pt == stImage->pt)
+      return GL_TRUE; /* Nothing to do. */
+
+   /* Check if the texture image is compatible with the texture object.
+    */
+   if (stObj->pt && level <= (GLint) stObj->pt->last_level &&
+       st_texture_match_image(stObj->pt, image, face, level)) {
+      copy_image_data_to_texture(st, stObj, level, stImage);
+      return GL_TRUE;
+   }
+
+   /* We have to create a new texture object for the texture image.
+    * First, delete the old texture object if necessary.
+    */
+   if (stObj->pt) {
+      pipe_resource_reference(&stObj->pt, NULL);
+      pipe_sampler_view_reference(&stObj->sampler_view, NULL);
+      st->dirty.st |= ST_NEW_FRAMEBUFFER;
+   }
+
+   if (!guess_and_alloc_texture(st, stObj, stImage)) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture");
+      return GL_FALSE;
+   }
+
+   if (!stObj->pt)
+      return GL_FALSE;
+
+   copy_image_data_to_texture(st, stObj, level, stImage);
+   return GL_TRUE;
+}
+
+
+/**
  * Returns pointer to a default/dummy texture.
  * This is typically used when the current shader has tex/sample instructions
  * but the user has not provided a (any) texture(s).
diff --git a/src/mesa/state_tracker/st_cb_texture.h b/src/mesa/state_tracker/st_cb_texture.h
index f1502bd..10a48cd 100644
--- a/src/mesa/state_tracker/st_cb_texture.h
+++ b/src/mesa/state_tracker/st_cb_texture.h
@@ -43,6 +43,10 @@ st_finalize_texture(struct gl_context *ctx,
 		    struct pipe_context *pipe, 
 		    struct gl_texture_object *tObj);
 
+extern GLboolean
+st_finalize_fbo_tex(struct gl_context *ctx,
+		    struct gl_texture_object *tObj,
+		    GLuint face, GLuint level);
 
 extern struct gl_texture_object *
 st_get_default_texture(struct st_context *st);
-- 
1.7.4.1

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to