From fb7e3cd89767f9e99c335390dcd9db74369b5d37 Mon Sep 17 00:00:00 2001
From: Dave Airlie <airlied@redhat.com>
Date: Sat, 24 Apr 2010 18:53:55 +1000
Subject: [PATCH] st/mesa: attempt to fix TFP by using sampler views (v1)

not fully working.

open issues:
1. can sampler view go from any to any? or are there compatiblity limitations on what formats can be represented in different views? if so where is the spelt out?

2. should the views be dealt with inside finalize_texture and not update_textures?
---
 src/mesa/state_tracker/st_atom_texture.c |   28 +++++++++++++++++++------
 src/mesa/state_tracker/st_cb_texture.c   |    2 +-
 src/mesa/state_tracker/st_format.c       |   33 ++++++++++++++++++++++++++++++
 src/mesa/state_tracker/st_format.h       |    4 +++
 src/mesa/state_tracker/st_manager.c      |    6 +++-
 5 files changed, 63 insertions(+), 10 deletions(-)

diff --git a/src/mesa/state_tracker/st_atom_texture.c b/src/mesa/state_tracker/st_atom_texture.c
index 65b57f1..895681c 100644
--- a/src/mesa/state_tracker/st_atom_texture.c
+++ b/src/mesa/state_tracker/st_atom_texture.c
@@ -38,6 +38,7 @@
 #include "st_context.h"
 #include "st_atom.h"
 #include "st_texture.h"
+#include "st_format.h"
 #include "st_cb_texture.h"
 #include "pipe/p_context.h"
 #include "util/u_inlines.h"
@@ -56,14 +57,15 @@ static boolean check_sampler_swizzle(struct pipe_sampler_view *sv,
 
 static INLINE struct pipe_sampler_view *
 st_create_texture_sampler_view_from_stobj(struct pipe_context *pipe,
-					  struct st_texture_object *stObj)
+					  struct st_texture_object *stObj,
+					  enum pipe_format format)
 					  
 {
    struct pipe_sampler_view templ;
 
    u_sampler_view_default_template(&templ,
                                    stObj->pt,
-                                   stObj->pt->format);
+                                   format);
 
    if (stObj->base._Swizzle != SWIZZLE_NOOP) {
       templ.swizzle_r = GET_SWZ(stObj->base._Swizzle, 0);
@@ -78,7 +80,8 @@ st_create_texture_sampler_view_from_stobj(struct pipe_context *pipe,
 
 static INLINE struct pipe_sampler_view *
 st_get_texture_sampler_view_from_stobj(struct st_texture_object *stObj,
-				       struct pipe_context *pipe)
+				       struct pipe_context *pipe,
+				       enum pipe_format format)
 
 {
    if (!stObj || !stObj->pt) {
@@ -86,7 +89,7 @@ st_get_texture_sampler_view_from_stobj(struct st_texture_object *stObj,
    }
 
    if (!stObj->sampler_view) {
-      stObj->sampler_view = st_create_texture_sampler_view_from_stobj(pipe, stObj);
+      stObj->sampler_view = st_create_texture_sampler_view_from_stobj(pipe, stObj, format);
    }
 
    return stObj->sampler_view;
@@ -107,7 +110,7 @@ update_textures(struct st_context *st)
    /* loop over sampler units (aka tex image units) */
    for (su = 0; su < st->ctx->Const.MaxTextureImageUnits; su++) {
       struct pipe_sampler_view *sampler_view = NULL;
-
+      enum pipe_format st_view_format;
       if (samplersUsed & (1 << su)) {
          struct gl_texture_object *texObj;
          struct st_texture_object *stObj;
@@ -132,14 +135,25 @@ update_textures(struct st_context *st)
             continue;
          }
 
+	 st_view_format = stObj->pt->format;
+	 {
+	    struct st_texture_image *firstImage;
+	    enum pipe_format firstImageFormat;
+	    firstImage = st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]);
+
+	    firstImageFormat = st_mesa_format_to_pipe_format(firstImage->base.TexFormat);
+	    if (firstImageFormat != stObj->pt->format)
+	       st_view_format = firstImageFormat;
+
+	 }
          st->state.num_textures = su + 1;
 
 	 /* if sampler view has changed dereference it */
 	 if (stObj->sampler_view)
-	    if (check_sampler_swizzle(stObj->sampler_view, stObj->base._Swizzle))
+	    if (check_sampler_swizzle(stObj->sampler_view, stObj->base._Swizzle) || (st_view_format != stObj->sampler_view->format))
 	       pipe_sampler_view_reference(&stObj->sampler_view, NULL);
 
-         sampler_view = st_get_texture_sampler_view_from_stobj(stObj, pipe);
+         sampler_view = st_get_texture_sampler_view_from_stobj(stObj, pipe, st_view_format);
       }
       pipe_sampler_view_reference(&st->state.sampler_views[su], sampler_view);
    }
diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c
index 647898e..2101b9b 100644
--- a/src/mesa/state_tracker/st_cb_texture.c
+++ b/src/mesa/state_tracker/st_cb_texture.c
@@ -1850,7 +1850,7 @@ st_finalize_texture(GLcontext *ctx,
     */
    if (stObj->pt) {
       if (stObj->pt->target != gl_target_to_pipe(stObj->base.Target) ||
-          stObj->pt->format != firstImageFormat ||
+          !st_sampler_compat_formats(stObj->pt->format, firstImageFormat) ||
           stObj->pt->last_level < stObj->lastLevel ||
           stObj->pt->width0 != stObj->width0 ||
           stObj->pt->height0 != stObj->height0 ||
diff --git a/src/mesa/state_tracker/st_format.c b/src/mesa/state_tracker/st_format.c
index f7b10ea..c9fa7a6 100644
--- a/src/mesa/state_tracker/st_format.c
+++ b/src/mesa/state_tracker/st_format.c
@@ -767,3 +767,36 @@ st_equal_formats(enum pipe_format pFormat, GLenum format, GLenum type)
       return GL_FALSE;
    }
 }
+
+GLboolean
+st_sampler_compat_formats(enum pipe_format format1, enum pipe_format format2)
+{
+   if (format1 == format2)
+      return GL_TRUE;
+
+   if (format1 == PIPE_FORMAT_B8G8R8A8_UNORM &&
+       format2 == PIPE_FORMAT_B8G8R8X8_UNORM)
+      return GL_TRUE;
+
+   if (format1 == PIPE_FORMAT_B8G8R8X8_UNORM &&
+       format2 == PIPE_FORMAT_B8G8R8A8_UNORM)
+      return GL_TRUE;
+
+   if (format1 == PIPE_FORMAT_A8B8G8R8_UNORM &&
+       format2 == PIPE_FORMAT_X8B8G8R8_UNORM)
+      return GL_TRUE;
+
+   if (format1 == PIPE_FORMAT_X8B8G8R8_UNORM &&
+       format2 == PIPE_FORMAT_A8B8G8R8_UNORM)
+      return GL_TRUE;
+
+   if (format1 == PIPE_FORMAT_A8R8G8B8_UNORM &&
+       format2 == PIPE_FORMAT_X8R8G8B8_UNORM)
+      return GL_TRUE;
+
+   if (format1 == PIPE_FORMAT_X8R8G8B8_UNORM &&
+       format2 == PIPE_FORMAT_A8R8G8B8_UNORM)
+      return GL_TRUE;
+
+   return GL_FALSE;
+}
diff --git a/src/mesa/state_tracker/st_format.h b/src/mesa/state_tracker/st_format.h
index 3288225..29768f2 100644
--- a/src/mesa/state_tracker/st_format.h
+++ b/src/mesa/state_tracker/st_format.h
@@ -62,5 +62,9 @@ st_ChooseTextureFormat(GLcontext * ctx, GLint internalFormat,
 extern GLboolean
 st_equal_formats(enum pipe_format pFormat, GLenum format, GLenum type);
 
+/* can we use a sampler view to translate these formats
+   only used to make TFP so far */
+extern GLboolean
+st_sampler_compat_formats(enum pipe_format format1, enum pipe_format format2);
 
 #endif /* ST_FORMAT_H */
diff --git a/src/mesa/state_tracker/st_manager.c b/src/mesa/state_tracker/st_manager.c
index 8c3dfb3..ccfb1f4 100644
--- a/src/mesa/state_tracker/st_manager.c
+++ b/src/mesa/state_tracker/st_manager.c
@@ -550,12 +550,14 @@ st_context_teximage(struct st_context_iface *stctxi, enum st_texture_type target
        * To avoid that, internal_format is (wrongly) ignored here.  A sane fix
        * is to use a sampler view.
        */
-      if (util_format_get_component_bits(tex->format,
+      if (!st_sampler_compat_formats(tex->format, internal_format))
+	 internal_format = tex->format;
+     
+      if (util_format_get_component_bits(internal_format,
                UTIL_FORMAT_COLORSPACE_RGB, 3) > 0)
          internalFormat = GL_RGBA;
       else
          internalFormat = GL_RGB;
-
       _mesa_init_teximage_fields(ctx, target, texImage,
             tex->width0, tex->height0, 1, 0, internalFormat);
       texImage->TexFormat = st_ChooseTextureFormat(ctx, internalFormat,
-- 
1.6.6.1

