<div dir="ltr"><div>PIPE_CAP_TEXTURE_SWIZZLE_AFFECTS_BORDER_COLOR would be a better name (note the meaning is inverted). Other than that, this looks good.<br><br></div>Marek<br></div><div class="gmail_extra"><br><br><div class="gmail_quote">

On Sat, Apr 13, 2013 at 4:31 PM, Christoph Bumiller <span dir="ltr"><<a href="mailto:e0425955@student.tuwien.ac.at" target="_blank">e0425955@student.tuwien.ac.at</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

From: Christoph Bumiller <<a href="mailto:christoph.bumiller@speed.at">christoph.bumiller@speed.at</a>><br>
<br>
This is the only sane solution for nv50 and nvc0 (really, trust me),<br>
but since on other hardware the border colour is tightly coupled with<br>
texture state they'd have to undo the swizzle, so I've added a cap.<br>
<br>
The name of the cap could be changed to be more descriptive, like<br>
PIPE_CAP_TEXTURE_SWIZZLE_AFFECTS_BORDER_COLOR.<br>
<br>
The dependency of update_sampler on the texture updates was<br>
introduced to avoid doing the apply_depthmode to the swizzle twice.<br>
<br>
More detailed explanation of driver situation:<br>
<br>
No, really, don't suggest doing this in the driver. The driver has<br>
elegantly separated texture view and sampler states (which are each<br>
a structure in a table in VRAM and should not be updated to avoid<br>
performance loss), and table are bound to the independent (!) texture<br>
and sampler slots in shaders which must be separately indexable<br>
indirectly).<br>
So, if I was to do this in the driver, I'd have to add separate sampler<br>
state object instances for each texture view with appropriately swizzled<br>
border color, and there's only 16 slots, so I'd be limited to 4 texture<br>
units.<br>
Not to mention the sheer insanity, ugliness and emotional pain incurred<br>
when writing that code when it COULD be so easy and simple in the state<br>
tracker where you know that textures and samplers are tightly coupled,<br>
while in gallium I cannot assume that to be the case.<br>
---<br>
 src/gallium/docs/source/cso/sampler.rst          |    7 ++-<br>
 src/gallium/docs/source/screen.rst               |    2 +<br>
 src/gallium/drivers/freedreno/freedreno_screen.c |    1 +<br>
 src/gallium/drivers/i915/i915_screen.c           |    1 +<br>
 src/gallium/drivers/llvmpipe/lp_screen.c         |    2 +<br>
 src/gallium/drivers/nv30/nv30_screen.c           |    1 +<br>
 src/gallium/drivers/nv50/nv50_screen.c           |    1 +<br>
 src/gallium/drivers/nvc0/nvc0_screen.c           |    1 +<br>
 src/gallium/drivers/r300/r300_screen.c           |    1 +<br>
 src/gallium/drivers/r600/r600_pipe.c             |    1 +<br>
 src/gallium/drivers/radeonsi/radeonsi_pipe.c     |    1 +<br>
 src/gallium/drivers/softpipe/sp_screen.c         |    2 +<br>
 src/gallium/drivers/svga/svga_screen.c           |    2 +<br>
 src/gallium/include/pipe/p_defines.h             |    3 +-<br>
 src/mesa/state_tracker/st_atom.c                 |    2 +-<br>
 src/mesa/state_tracker/st_atom_sampler.c         |   65 +++++++++++++++++++++-<br>
 src/mesa/state_tracker/st_context.c              |    2 +<br>
 src/mesa/state_tracker/st_context.h              |    1 +<br>
 18 files changed, 89 insertions(+), 7 deletions(-)<br>
<br>
diff --git a/src/gallium/docs/source/cso/sampler.rst b/src/gallium/docs/source/cso/sampler.rst<br>
index 26ffc18..1911cea 100644<br>
--- a/src/gallium/docs/source/cso/sampler.rst<br>
+++ b/src/gallium/docs/source/cso/sampler.rst<br>
@@ -101,7 +101,10 @@ max_lod<br>
 border_color<br>
     Color union used for texel coordinates that are outside the [0,width-1],<br>
     [0, height-1] or [0, depth-1] ranges. Interpreted according to sampler<br>
-    view format.<br>
+    view format, unless the driver reports<br>
+    PIPE_CAP_BORDER_COLOR_QUIRK, in which case this value is substituted for<br>
+    the texture color exactly as specified, the sampler view format and swizzle<br>
+    have no effect on it.<br>
 max_anisotropy<br>
     Maximum anistropy ratio to use when sampling from textures.  For example,<br>
     if max_anistropy=4, a region of up to 1 by 4 texels will be sampled.<br>
@@ -111,4 +114,4 @@ max_anisotropy<br>
 seamless_cube_map<br>
     If set, the bilinear filter of a cube map may take samples from adjacent<br>
     cube map faces when sampled near a texture border to produce a seamless<br>
-    look.<br>
\ No newline at end of file<br>
+    look.<br>
diff --git a/src/gallium/docs/source/screen.rst b/src/gallium/docs/source/screen.rst<br>
index 4b01d77..495398b 100644<br>
--- a/src/gallium/docs/source/screen.rst<br>
+++ b/src/gallium/docs/source/screen.rst<br>
@@ -151,6 +151,8 @@ The integer capabilities:<br>
   dedicated memory should return 1 and all software rasterizers should return 0.<br>
 * ``PIPE_CAP_QUERY_PIPELINE_STATISTICS``: Whether PIPE_QUERY_PIPELINE_STATISTICS<br>
   is supported.<br>
+* ``PIPE_CAP_BORDER_COLOR_QUIRK``: Whether the sampler view's format and swizzle<br>
+  affect the border color.<br>
<br>
<br>
 .. _pipe_capf:<br>
diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c<br>
index 283d07f..5b60401 100644<br>
--- a/src/gallium/drivers/freedreno/freedreno_screen.c<br>
+++ b/src/gallium/drivers/freedreno/freedreno_screen.c<br>
@@ -200,6 +200,7 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)<br>
        case PIPE_CAP_USER_VERTEX_BUFFERS:<br>
        case PIPE_CAP_USER_INDEX_BUFFERS:<br>
        case PIPE_CAP_QUERY_PIPELINE_STATISTICS:<br>
+       case PIPE_CAP_BORDER_COLOR_QUIRK:<br>
                return 0;<br>
<br>
        /* Stream output. */<br>
diff --git a/src/gallium/drivers/i915/i915_screen.c b/src/gallium/drivers/i915/i915_screen.c<br>
index 54b2154..4c3d52f 100644<br>
--- a/src/gallium/drivers/i915/i915_screen.c<br>
+++ b/src/gallium/drivers/i915/i915_screen.c<br>
@@ -213,6 +213,7 @@ i915_get_param(struct pipe_screen *screen, enum pipe_cap cap)<br>
    case PIPE_CAP_QUERY_PIPELINE_STATISTICS:<br>
    case PIPE_CAP_TEXTURE_MULTISAMPLE:<br>
    case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT:<br>
+   case PIPE_CAP_BORDER_COLOR_QUIRK:<br>
       return 0;<br>
<br>
    case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:<br>
diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c<br>
index ebcf680..9506162 100644<br>
--- a/src/gallium/drivers/llvmpipe/lp_screen.c<br>
+++ b/src/gallium/drivers/llvmpipe/lp_screen.c<br>
@@ -138,6 +138,8 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)<br>
       return 1;<br>
    case PIPE_CAP_TEXTURE_SWIZZLE:<br>
       return 1;<br>
+   case PIPE_CAP_BORDER_COLOR_QUIRK:<br>
+      return 0;<br>
    case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:<br>
       return LP_MAX_TEXTURE_2D_LEVELS;<br>
    case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:<br>
diff --git a/src/gallium/drivers/nv30/nv30_screen.c b/src/gallium/drivers/nv30/nv30_screen.c<br>
index e33710e..52a3ec9 100644<br>
--- a/src/gallium/drivers/nv30/nv30_screen.c<br>
+++ b/src/gallium/drivers/nv30/nv30_screen.c<br>
@@ -123,6 +123,7 @@ nv30_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)<br>
    case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:<br>
    case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:<br>
    case PIPE_CAP_QUERY_PIPELINE_STATISTICS:<br>
+   case PIPE_CAP_BORDER_COLOR_QUIRK: /* TODO: check */<br>
       return 0;<br>
    case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY:<br>
    case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:<br>
diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c<br>
index 55081be..39e0e63 100644<br>
--- a/src/gallium/drivers/nv50/nv50_screen.c<br>
+++ b/src/gallium/drivers/nv50/nv50_screen.c<br>
@@ -161,6 +161,7 @@ nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)<br>
    case PIPE_CAP_CONDITIONAL_RENDER:<br>
    case PIPE_CAP_TEXTURE_BARRIER:<br>
    case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION:<br>
+   case PIPE_CAP_BORDER_COLOR_QUIRK:<br>
    case PIPE_CAP_START_INSTANCE:<br>
       return 1;<br>
    case PIPE_CAP_TGSI_CAN_COMPACT_VARYINGS:<br>
diff --git a/src/gallium/drivers/nvc0/nvc0_screen.c b/src/gallium/drivers/nvc0/nvc0_screen.c<br>
index ccdf2cd..4768e9d 100644<br>
--- a/src/gallium/drivers/nvc0/nvc0_screen.c<br>
+++ b/src/gallium/drivers/nvc0/nvc0_screen.c<br>
@@ -153,6 +153,7 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)<br>
    case PIPE_CAP_CONDITIONAL_RENDER:<br>
    case PIPE_CAP_TEXTURE_BARRIER:<br>
    case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION:<br>
+   case PIPE_CAP_BORDER_COLOR_QUIRK:<br>
    case PIPE_CAP_START_INSTANCE:<br>
       return 1;<br>
    case PIPE_CAP_TGSI_CAN_COMPACT_VARYINGS:<br>
diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c<br>
index 3175b3b..f8bd5ce 100644<br>
--- a/src/gallium/drivers/r300/r300_screen.c<br>
+++ b/src/gallium/drivers/r300/r300_screen.c<br>
@@ -162,6 +162,7 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param)<br>
         case PIPE_CAP_CUBE_MAP_ARRAY:<br>
         case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:<br>
         case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:<br>
+        case PIPE_CAP_BORDER_COLOR_QUIRK:<br>
             return 0;<br>
<br>
         /* SWTCL-only features. */<br>
diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c<br>
index 3f36e63..ec05732 100644<br>
--- a/src/gallium/drivers/r600/r600_pipe.c<br>
+++ b/src/gallium/drivers/r600/r600_pipe.c<br>
@@ -611,6 +611,7 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param)<br>
        case PIPE_CAP_VERTEX_COLOR_CLAMPED:<br>
        case PIPE_CAP_USER_VERTEX_BUFFERS:<br>
        case PIPE_CAP_QUERY_PIPELINE_STATISTICS:<br>
+       case PIPE_CAP_BORDER_COLOR_QUIRK:<br>
                return 0;<br>
<br>
        /* Stream output. */<br>
diff --git a/src/gallium/drivers/radeonsi/radeonsi_pipe.c b/src/gallium/drivers/radeonsi/radeonsi_pipe.c<br>
index 5c25b2f..b1f50bf 100644<br>
--- a/src/gallium/drivers/radeonsi/radeonsi_pipe.c<br>
+++ b/src/gallium/drivers/radeonsi/radeonsi_pipe.c<br>
@@ -380,6 +380,7 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param)<br>
        case PIPE_CAP_CUBE_MAP_ARRAY:<br>
        case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:<br>
        case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:<br>
+       case PIPE_CAP_BORDER_COLOR_QUIRK:<br>
                return 0;<br>
<br>
        /* Stream output. */<br>
diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c<br>
index 6915f91..fb602ba 100644<br>
--- a/src/gallium/drivers/softpipe/sp_screen.c<br>
+++ b/src/gallium/drivers/softpipe/sp_screen.c<br>
@@ -94,6 +94,8 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)<br>
       return 1;<br>
    case PIPE_CAP_TEXTURE_SWIZZLE:<br>
       return 1;<br>
+   case PIPE_CAP_BORDER_COLOR_QUIRK:<br>
+      return 0;<br>
    case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:<br>
       return SP_MAX_TEXTURE_2D_LEVELS;<br>
    case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:<br>
diff --git a/src/gallium/drivers/svga/svga_screen.c b/src/gallium/drivers/svga/svga_screen.c<br>
index 6213535..a8235b8 100644<br>
--- a/src/gallium/drivers/svga/svga_screen.c<br>
+++ b/src/gallium/drivers/svga/svga_screen.c<br>
@@ -166,6 +166,8 @@ svga_get_param(struct pipe_screen *screen, enum pipe_cap param)<br>
       return 1;<br>
    case PIPE_CAP_TEXTURE_SWIZZLE:<br>
       return 1;<br>
+   case PIPE_CAP_BORDER_COLOR_QUIRK:<br>
+      return 0;<br>
    case PIPE_CAP_USER_VERTEX_BUFFERS:<br>
    case PIPE_CAP_USER_INDEX_BUFFERS:<br>
       return 0;<br>
diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h<br>
index c790660..35d2707 100644<br>
--- a/src/gallium/include/pipe/p_defines.h<br>
+++ b/src/gallium/include/pipe/p_defines.h<br>
@@ -505,7 +505,8 @@ enum pipe_cap {<br>
    PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT = 78,<br>
    PIPE_CAP_TGSI_TEXCOORD = 79,<br>
    PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER = 80,<br>
-   PIPE_CAP_QUERY_PIPELINE_STATISTICS = 81<br>
+   PIPE_CAP_QUERY_PIPELINE_STATISTICS = 81,<br>
+   PIPE_CAP_BORDER_COLOR_QUIRK = 82<br>
 };<br>
<br>
 /**<br>
diff --git a/src/mesa/state_tracker/st_atom.c b/src/mesa/state_tracker/st_atom.c<br>
index 32bcc26..7d38392 100644<br>
--- a/src/mesa/state_tracker/st_atom.c<br>
+++ b/src/mesa/state_tracker/st_atom.c<br>
@@ -55,10 +55,10 @@ static const struct st_tracked_state *atoms[] =<br>
    &st_update_viewport,<br>
    &st_update_scissor,<br>
    &st_update_blend,<br>
-   &st_update_sampler,<br>
    &st_update_vertex_texture,<br>
    &st_update_fragment_texture,<br>
    &st_update_geometry_texture,<br>
+   &st_update_sampler, /* depends on update_*_texture for swizzle */<br>
    &st_update_framebuffer,<br>
    &st_update_msaa,<br>
    &st_update_vs_constants,<br>
diff --git a/src/mesa/state_tracker/st_atom_sampler.c b/src/mesa/state_tracker/st_atom_sampler.c<br>
index 3eba5b1..1a78144 100644<br>
--- a/src/mesa/state_tracker/st_atom_sampler.c<br>
+++ b/src/mesa/state_tracker/st_atom_sampler.c<br>
@@ -123,6 +123,54 @@ gl_filter_to_img_filter(GLenum filter)<br>
 }<br>
<br>
<br>
+static INLINE unsigned<br>
+get_sampler_view_swz(const struct pipe_sampler_view *view, unsigned component)<br>
+{<br>
+   switch (component) {<br>
+   case 1: return view->swizzle_g;<br>
+   case 2: return view->swizzle_b;<br>
+   case 3: return view->swizzle_a;<br>
+   default:<br>
+      assert(component == 0);<br>
+      return view->swizzle_r;<br>
+   }<br>
+}<br>
+<br>
+static void<br>
+apply_swizzle(union pipe_color_union *dst, const union pipe_color_union *src,<br>
+              const struct pipe_sampler_view *view, boolean is_integer)<br>
+{<br>
+   unsigned c;<br>
+<br>
+   if (is_integer) {<br>
+      for (c = 0; c < 4; ++c) {<br>
+         unsigned swz = get_sampler_view_swz(view, c);<br>
+         switch (swz) {<br>
+         case PIPE_SWIZZLE_RED:   dst->ui[c] = src->ui[0]; break;<br>
+         case PIPE_SWIZZLE_GREEN: dst->ui[c] = src->ui[1]; break;<br>
+         case PIPE_SWIZZLE_BLUE:  dst->ui[c] = src->ui[2]; break;<br>
+         case PIPE_SWIZZLE_ALPHA: dst->ui[c] = src->ui[3]; break;<br>
+         default:<br>
+            dst->ui[c] = (swz == PIPE_SWIZZLE_ONE) ? 1 : 0;<br>
+            break;<br>
+         }<br>
+      }<br>
+   } else {<br>
+      for (c = 0; c < 4; ++c) {<br>
+         unsigned swz = get_sampler_view_swz(view, c);<br>
+         switch (swz) {<br>
+         case PIPE_SWIZZLE_RED:   dst->f[c] = src->f[0]; break;<br>
+         case PIPE_SWIZZLE_GREEN: dst->f[c] = src->f[1]; break;<br>
+         case PIPE_SWIZZLE_BLUE:  dst->f[c] = src->f[2]; break;<br>
+         case PIPE_SWIZZLE_ALPHA: dst->f[c] = src->f[3]; break;<br>
+         default:<br>
+            dst->f[c] = (swz == PIPE_SWIZZLE_ONE) ? 1.0f : 0.0f;<br>
+            break;<br>
+         }<br>
+      }<br>
+   }<br>
+}<br>
+<br>
 static void<br>
 convert_sampler(struct st_context *st,<br>
                 struct pipe_sampler_state *sampler,<br>
@@ -172,8 +220,10 @@ convert_sampler(struct st_context *st,<br>
        msamp->BorderColor.ui[1] ||<br>
        msamp->BorderColor.ui[2] ||<br>
        msamp->BorderColor.ui[3]) {<br>
+      struct st_texture_object *stobj = st_texture_object(texobj);<br>
       struct gl_texture_image *teximg;<br>
       GLboolean is_integer = GL_FALSE;<br>
+      union pipe_color_union border_color;<br>
<br>
       teximg = texobj->Image[0][texobj->BaseLevel];<br>
<br>
@@ -181,9 +231,18 @@ convert_sampler(struct st_context *st,<br>
          is_integer = _mesa_is_enum_format_integer(teximg->InternalFormat);<br>
       }<br>
<br>
-      st_translate_color(&msamp->BorderColor,<br>
-                         &sampler->border_color,<br>
-                         teximg ? teximg->_BaseFormat : GL_RGBA, is_integer);<br>
+      if (st->apply_texture_swizzle_to_border_color && stobj->sampler_view) {<br>
+         st_translate_color(&msamp->BorderColor,<br>
+                            &border_color,<br>
+                            teximg ? teximg->_BaseFormat : GL_RGBA, is_integer);<br>
+<br>
+         apply_swizzle(&sampler->border_color, &border_color,<br>
+                       stobj->sampler_view, is_integer);<br>
+      } else {<br>
+         st_translate_color(&msamp->BorderColor,<br>
+                            &sampler->border_color,<br>
+                            teximg ? teximg->_BaseFormat : GL_RGBA, is_integer);<br>
+      }<br>
    }<br>
<br>
    sampler->max_anisotropy = (msamp->MaxAnisotropy == 1.0 ?<br>
diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c<br>
index 2042be3..a6aee69 100644<br>
--- a/src/mesa/state_tracker/st_context.c<br>
+++ b/src/mesa/state_tracker/st_context.c<br>
@@ -188,6 +188,8 @@ st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe,<br>
<br>
    st->needs_texcoord_semantic =<br>
       screen->get_param(screen, PIPE_CAP_TGSI_TEXCOORD);<br>
+   st->apply_texture_swizzle_to_border_color =<br>
+      screen->get_param(screen, PIPE_CAP_BORDER_COLOR_QUIRK);<br>
<br>
    /* GL limits and extensions */<br>
    st_init_limits(st);<br>
diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h<br>
index 8786a03..807453e 100644<br>
--- a/src/mesa/state_tracker/st_context.h<br>
+++ b/src/mesa/state_tracker/st_context.h<br>
@@ -87,6 +87,7 @@ struct st_context<br>
    boolean prefer_blit_based_texture_transfer;<br>
<br>
    boolean needs_texcoord_semantic;<br>
+   boolean apply_texture_swizzle_to_border_color;<br>
<br>
    /* On old libGL's for linux we need to invalidate the drawables<br>
     * on glViewpport calls, this is set via a option.<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.7.3.4<br>
<br>
_______________________________________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/mesa-dev" target="_blank">http://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
</font></span></blockquote></div><br></div>