<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>