st/mesa: optionally apply texture swizzle to border color v2
authorChristoph Bumiller <christoph.bumiller@speed.at>
Fri, 12 Apr 2013 11:42:01 +0000 (13:42 +0200)
committerChristoph Bumiller <e0425955@student.tuwien.ac.at>
Thu, 18 Apr 2013 18:35:40 +0000 (20:35 +0200)
This is the only sane solution for nv50 and nvc0 (really, trust me),
but since on other hardware the border colour is tightly coupled with
texture state they'd have to undo the swizzle, so I've added a cap.

The dependency of update_sampler on the texture updates was
introduced to avoid doing the apply_depthmode to the swizzle twice.

v2: Moved swizzling helper to u_format.c, extended the CAP to
provide more accurate information.

20 files changed:
src/gallium/auxiliary/util/u_format.c
src/gallium/auxiliary/util/u_format.h
src/gallium/docs/source/cso/sampler.rst
src/gallium/docs/source/screen.rst
src/gallium/drivers/freedreno/freedreno_screen.c
src/gallium/drivers/i915/i915_screen.c
src/gallium/drivers/llvmpipe/lp_screen.c
src/gallium/drivers/nv30/nv30_screen.c
src/gallium/drivers/nv50/nv50_screen.c
src/gallium/drivers/nvc0/nvc0_screen.c
src/gallium/drivers/r300/r300_screen.c
src/gallium/drivers/r600/r600_pipe.c
src/gallium/drivers/radeonsi/radeonsi_pipe.c
src/gallium/drivers/softpipe/sp_screen.c
src/gallium/drivers/svga/svga_screen.c
src/gallium/include/pipe/p_defines.h
src/mesa/state_tracker/st_atom.c
src/mesa/state_tracker/st_atom_sampler.c
src/mesa/state_tracker/st_context.c
src/mesa/state_tracker/st_context.h

index 18456371c0af011c9db198f28720c451964aab57..9bdc2eabf11502ec5825cb4ca7a9f8d1fbb0dbd7 100644 (file)
@@ -632,6 +632,40 @@ void util_format_compose_swizzles(const unsigned char swz1[4],
    }
 }
 
+void util_format_apply_color_swizzle(union pipe_color_union *dst,
+                                     const union pipe_color_union *src,
+                                     const unsigned char swz[4],
+                                     const boolean is_integer)
+{
+   unsigned c;
+
+   if (is_integer) {
+      for (c = 0; c < 4; ++c) {
+         switch (swz[c]) {
+         case PIPE_SWIZZLE_RED:   dst->ui[c] = src->ui[0]; break;
+         case PIPE_SWIZZLE_GREEN: dst->ui[c] = src->ui[1]; break;
+         case PIPE_SWIZZLE_BLUE:  dst->ui[c] = src->ui[2]; break;
+         case PIPE_SWIZZLE_ALPHA: dst->ui[c] = src->ui[3]; break;
+         default:
+            dst->ui[c] = (swz[c] == PIPE_SWIZZLE_ONE) ? 1 : 0;
+            break;
+         }
+      }
+   } else {
+      for (c = 0; c < 4; ++c) {
+         switch (swz[c]) {
+         case PIPE_SWIZZLE_RED:   dst->f[c] = src->f[0]; break;
+         case PIPE_SWIZZLE_GREEN: dst->f[c] = src->f[1]; break;
+         case PIPE_SWIZZLE_BLUE:  dst->f[c] = src->f[2]; break;
+         case PIPE_SWIZZLE_ALPHA: dst->f[c] = src->f[3]; break;
+         default:
+            dst->f[c] = (swz[c] == PIPE_SWIZZLE_ONE) ? 1.0f : 0.0f;
+            break;
+         }
+      }
+   }
+}
+
 void util_format_swizzle_4f(float *dst, const float *src,
                             const unsigned char swz[4])
 {
index ed942fb1658fb669674852d6c787e087377273b5..e4b9c365c977b18ad844abd5a4c38ca0e7f6267f 100644 (file)
@@ -33,6 +33,9 @@
 #include "pipe/p_format.h"
 #include "util/u_debug.h"
 
+union pipe_color_union;
+
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -1117,6 +1120,15 @@ void util_format_compose_swizzles(const unsigned char swz1[4],
                                   const unsigned char swz2[4],
                                   unsigned char dst[4]);
 
+/* Apply the swizzle provided in \param swz (which is one of PIPE_SWIZZLE_x)
+ * to \param src and store the result in \param dst.
+ * \param is_integer determines the value written for PIPE_SWIZZLE_ONE.
+ */
+void util_format_apply_color_swizzle(union pipe_color_union *dst,
+                                     const union pipe_color_union *src,
+                                     const unsigned char swz[4],
+                                     const boolean is_integer);
+
 void util_format_swizzle_4f(float *dst, const float *src,
                             const unsigned char swz[4]);
 
index 26ffc1810310d7b098e080679aa46e7f58a688f0..9959793a33252eb86f4bd4e5095c0cde9c71aafe 100644 (file)
@@ -101,7 +101,9 @@ max_lod
 border_color
     Color union used for texel coordinates that are outside the [0,width-1],
     [0, height-1] or [0, depth-1] ranges. Interpreted according to sampler
-    view format.
+    view format, unless the driver reports
+    PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK, in which case special care has to be
+    taken (see description of the cap).
 max_anisotropy
     Maximum anistropy ratio to use when sampling from textures.  For example,
     if max_anistropy=4, a region of up to 1 by 4 texels will be sampled.
@@ -111,4 +113,4 @@ max_anisotropy
 seamless_cube_map
     If set, the bilinear filter of a cube map may take samples from adjacent
     cube map faces when sampled near a texture border to produce a seamless
-    look.
\ No newline at end of file
+    look.
index 4b01d77322e501161a99ee7fb2fedb381f32d9f6..3ab7e9e6906d49cdcf68602829a135537c152691 100644 (file)
@@ -151,6 +151,17 @@ The integer capabilities:
   dedicated memory should return 1 and all software rasterizers should return 0.
 * ``PIPE_CAP_QUERY_PIPELINE_STATISTICS``: Whether PIPE_QUERY_PIPELINE_STATISTICS
   is supported.
+* ``PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK``: Bitmask indicating whether special
+  considerations have to be given to the interaction between the border color
+  in the sampler object and the sampler view used with it.
+  If PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_R600 is set, the border color
+  may be affected in undefined ways for any kind of permutational swizzle
+  (any swizzle XYZW where X/Y/Z/W are not ZERO, ONE, or R/G/B/A respectively)
+  in the sampler view.
+  If PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50 is set, the border color
+  state should be swizzled manually according to the swizzle in the sampler
+  view it is intended to be used with, or herein undefined results may occur
+  for permutational swizzles.
 
 
 .. _pipe_capf:
index 283d07f12e41e35fd40cb989737e71a89da875ee..4a9a54e3aea9d719eda286eb45c06e4d00782801 100644 (file)
@@ -200,6 +200,7 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
        case PIPE_CAP_USER_VERTEX_BUFFERS:
        case PIPE_CAP_USER_INDEX_BUFFERS:
        case PIPE_CAP_QUERY_PIPELINE_STATISTICS:
+       case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK:
                return 0;
 
        /* Stream output. */
index 54b21549ba5fefe7100624fcaf3fab2d52b6ed23..dfb76b3e98cf9113a9b589a9903ca2e96b436491 100644 (file)
@@ -213,6 +213,7 @@ i915_get_param(struct pipe_screen *screen, enum pipe_cap cap)
    case PIPE_CAP_QUERY_PIPELINE_STATISTICS:
    case PIPE_CAP_TEXTURE_MULTISAMPLE:
    case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT:
+   case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK:
       return 0;
 
    case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
index 7152c3e8bcad246f283df01f61f7eaaac50f96d1..5535f8523a777c701e6ac1f4afb9b1cffddeb445 100644 (file)
@@ -138,6 +138,8 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
       return 1;
    case PIPE_CAP_TEXTURE_SWIZZLE:
       return 1;
+   case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK:
+      return 0;
    case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
       return LP_MAX_TEXTURE_2D_LEVELS;
    case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
index e33710e71f74e6a39fcdf5a42c0360efcc98357a..5b3b470cc4e63b069d04da5840edfeeaaedf33aa 100644 (file)
@@ -123,6 +123,7 @@ nv30_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
    case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
    case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
    case PIPE_CAP_QUERY_PIPELINE_STATISTICS:
+   case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK:
       return 0;
    case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY:
    case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:
index 55081beb300f8ffa2eb42d7be329ec27ae232be1..5aa8ef32e657f9e2ecc72359e32ee6b181d48f4e 100644 (file)
@@ -186,6 +186,8 @@ nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
       return 1;
    case PIPE_CAP_QUERY_PIPELINE_STATISTICS:
       return 0;
+   case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK:
+      return PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50;
    default:
       NOUVEAU_ERR("unknown PIPE_CAP %d\n", param);
       return 0;
index ccdf2cde84bbca0d37d414b8fd266480f0435bab..8dfd4d12a0242291a5ee388fd48bd9ecaf90f2c1 100644 (file)
@@ -176,6 +176,8 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
       return (class_3d >= NVE4_3D_CLASS) ? 1 : 0;
    case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER:
       return 1;
+   case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK:
+      return PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50;
    default:
       NOUVEAU_ERR("unknown PIPE_CAP %d\n", param);
       return 0;
index 3175b3bdd40d287a4974c0fd24150a9c0e9b9e41..a932be9b41d54b9582552a7435e9a2c1aee49b09 100644 (file)
@@ -162,6 +162,7 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
         case PIPE_CAP_CUBE_MAP_ARRAY:
         case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
         case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
+        case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK:
             return 0;
 
         /* SWTCL-only features. */
index 9b43cef27373e18b082fb021e5874d30874bc9d5..4948dddae741892dbe112b1baba4d352e0070ebe 100644 (file)
@@ -654,6 +654,9 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
 
        case PIPE_CAP_MAX_TEXEL_OFFSET:
                return 7;
+
+       case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK:
+               return PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_R600;
        }
        return 0;
 }
index 5c25b2f98b3a6506924f2b734d26e2a0a7d1a9e1..4e97f51dbdc56e759ad8c040c074fed9dd8c29ec 100644 (file)
@@ -380,6 +380,7 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
        case PIPE_CAP_CUBE_MAP_ARRAY:
        case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
        case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
+       case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK:
                return 0;
 
        /* Stream output. */
index b2b7f2e32087b056c511c4ff60b96ddfd508a33a..53ee7d31cab6b2952b1235bae03400545ed51df7 100644 (file)
@@ -94,6 +94,8 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
       return 1;
    case PIPE_CAP_TEXTURE_SWIZZLE:
       return 1;
+   case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK:
+      return 0;
    case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
       return SP_MAX_TEXTURE_2D_LEVELS;
    case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
index 6213535a23ee68a1d4402e6a301b289c2c4fb739..60e0442944b67859588e29cb18f5bbf07883238e 100644 (file)
@@ -166,6 +166,8 @@ svga_get_param(struct pipe_screen *screen, enum pipe_cap param)
       return 1;
    case PIPE_CAP_TEXTURE_SWIZZLE:
       return 1;
+   case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK:
+      return 0;
    case PIPE_CAP_USER_VERTEX_BUFFERS:
    case PIPE_CAP_USER_INDEX_BUFFERS:
       return 0;
index 5b00acc7418a9991c8c135d400da76b39fc230da..2d38ce1a8c4a8edfc9f0a14504730039a2eb5cc5 100644 (file)
@@ -505,9 +505,14 @@ enum pipe_cap {
    PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT = 78,
    PIPE_CAP_TGSI_TEXCOORD = 79,
    PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER = 80,
-   PIPE_CAP_QUERY_PIPELINE_STATISTICS = 81
+   PIPE_CAP_QUERY_PIPELINE_STATISTICS = 81,
+   PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK = 82
 };
 
+#define PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50 (1 << 0)
+#define PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_R600 (1 << 1)
+
+
 /**
  * Implementation limits which are queried through
  * pipe_screen::get_paramf()
index 32bcc266a344725a376e6b9831716345edecc4d9..7d3839243004bb83eedbf7ca27885f78d2e88ef5 100644 (file)
@@ -55,10 +55,10 @@ static const struct st_tracked_state *atoms[] =
    &st_update_viewport,
    &st_update_scissor,
    &st_update_blend,
-   &st_update_sampler,
    &st_update_vertex_texture,
    &st_update_fragment_texture,
    &st_update_geometry_texture,
+   &st_update_sampler, /* depends on update_*_texture for swizzle */
    &st_update_framebuffer,
    &st_update_msaa,
    &st_update_vs_constants,
index 3eba5b13cae1bfe0965847422687d80e59fb3175..db51eead16b65b85ce4975b92875443ab91fbd8f 100644 (file)
@@ -48,6 +48,8 @@
 
 #include "cso_cache/cso_context.h"
 
+#include "util/u_format.h"
+
 
 /**
  * Convert GLenum texcoord wrap tokens to pipe tokens.
@@ -172,8 +174,10 @@ convert_sampler(struct st_context *st,
        msamp->BorderColor.ui[1] ||
        msamp->BorderColor.ui[2] ||
        msamp->BorderColor.ui[3]) {
+      struct st_texture_object *stobj = st_texture_object(texobj);
       struct gl_texture_image *teximg;
       GLboolean is_integer = GL_FALSE;
+      union pipe_color_union border_color;
 
       teximg = texobj->Image[0][texobj->BaseLevel];
 
@@ -181,9 +185,26 @@ convert_sampler(struct st_context *st,
          is_integer = _mesa_is_enum_format_integer(teximg->InternalFormat);
       }
 
-      st_translate_color(&msamp->BorderColor,
-                         &sampler->border_color,
-                         teximg ? teximg->_BaseFormat : GL_RGBA, is_integer);
+      if (st->apply_texture_swizzle_to_border_color && stobj->sampler_view) {
+         const unsigned char swz[4] =
+         {
+            stobj->sampler_view->swizzle_r,
+            stobj->sampler_view->swizzle_g,
+            stobj->sampler_view->swizzle_b,
+            stobj->sampler_view->swizzle_a,
+         };
+
+         st_translate_color(&msamp->BorderColor,
+                            &border_color,
+                            teximg ? teximg->_BaseFormat : GL_RGBA, is_integer);
+
+         util_format_apply_color_swizzle(&sampler->border_color,
+                                         &border_color, swz, is_integer);
+      } else {
+         st_translate_color(&msamp->BorderColor,
+                            &sampler->border_color,
+                            teximg ? teximg->_BaseFormat : GL_RGBA, is_integer);
+      }
    }
 
    sampler->max_anisotropy = (msamp->MaxAnisotropy == 1.0 ?
index 2042be36bd3e5432e2f40791542f3ace23e8de72..ed1bf26a26068db81637f2c5baf34758df44c211 100644 (file)
@@ -188,6 +188,10 @@ st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe,
 
    st->needs_texcoord_semantic =
       screen->get_param(screen, PIPE_CAP_TGSI_TEXCOORD);
+   st->apply_texture_swizzle_to_border_color =
+      !!(screen->get_param(screen, PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK) &
+         (PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50 |
+          PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_R600));
 
    /* GL limits and extensions */
    st_init_limits(st);
index 8786a036ff4b8705a73d410bb0e220df5bea7423..807453e997498809ab692459a5533d7f0083c873 100644 (file)
@@ -87,6 +87,7 @@ struct st_context
    boolean prefer_blit_based_texture_transfer;
 
    boolean needs_texcoord_semantic;
+   boolean apply_texture_swizzle_to_border_color;
 
    /* On old libGL's for linux we need to invalidate the drawables
     * on glViewpport calls, this is set via a option.