summaryrefslogtreecommitdiffstats
path: root/src/gallium
diff options
context:
space:
mode:
authorBrian Paul <[email protected]>2011-07-25 16:06:45 -0600
committerBrian Paul <[email protected]>2011-09-23 07:58:48 -0600
commit9bd15aef865352b9234fedae76617fc51c71e6d5 (patch)
tree52e9f15ec416b54b18c021be42abeaa0e99bd20e /src/gallium
parent49a6f5e68eeb6b23bb040cfc1f93befc2f1eb35a (diff)
svga: implement texture swizzling
This exposes the GL_EXT_texture_swizzle extension and allows the various depth texture modes to be implemented properly. This, plus a follow-on texture/shadow change fixes quite a few piglit GLSL shadow sampler test failures.
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/drivers/svga/svga_screen.c2
-rw-r--r--src/gallium/drivers/svga/svga_state_fs.c5
-rw-r--r--src/gallium/drivers/svga/svga_tgsi.h4
-rw-r--r--src/gallium/drivers/svga/svga_tgsi_insn.c126
4 files changed, 128 insertions, 9 deletions
diff --git a/src/gallium/drivers/svga/svga_screen.c b/src/gallium/drivers/svga/svga_screen.c
index 3a1ac9e1d93..87b48dea173 100644
--- a/src/gallium/drivers/svga/svga_screen.c
+++ b/src/gallium/drivers/svga/svga_screen.c
@@ -148,6 +148,8 @@ svga_get_paramf(struct pipe_screen *screen, enum pipe_cap param)
return 0;
case PIPE_CAP_TEXTURE_SHADOW_MAP:
return 1;
+ case PIPE_CAP_TEXTURE_SWIZZLE:
+ return 1;
case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
{
diff --git a/src/gallium/drivers/svga/svga_state_fs.c b/src/gallium/drivers/svga/svga_state_fs.c
index 5b96750bbf1..349aa275f18 100644
--- a/src/gallium/drivers/svga/svga_state_fs.c
+++ b/src/gallium/drivers/svga/svga_state_fs.c
@@ -167,6 +167,11 @@ static int make_fs_key( const struct svga_context *svga,
key->tex[i].unnormalized = TRUE;
++key->num_unnormalized_coords;
}
+
+ key->tex[i].swizzle_r = svga->curr.sampler_views[i]->swizzle_r;
+ key->tex[i].swizzle_g = svga->curr.sampler_views[i]->swizzle_g;
+ key->tex[i].swizzle_b = svga->curr.sampler_views[i]->swizzle_b;
+ key->tex[i].swizzle_a = svga->curr.sampler_views[i]->swizzle_a;
}
}
key->num_textures = svga->curr.num_sampler_views;
diff --git a/src/gallium/drivers/svga/svga_tgsi.h b/src/gallium/drivers/svga/svga_tgsi.h
index bd63bf5c264..214e113aaaa 100644
--- a/src/gallium/drivers/svga/svga_tgsi.h
+++ b/src/gallium/drivers/svga/svga_tgsi.h
@@ -60,6 +60,10 @@ struct svga_fs_compile_key
unsigned width_height_idx:7;
unsigned texture_target:8;
unsigned sprite_texgen:1;
+ unsigned swizzle_r:3;
+ unsigned swizzle_g:3;
+ unsigned swizzle_b:3;
+ unsigned swizzle_a:3;
} tex[PIPE_MAX_SAMPLERS];
};
diff --git a/src/gallium/drivers/svga/svga_tgsi_insn.c b/src/gallium/drivers/svga/svga_tgsi_insn.c
index 05531a15eb5..b93c0cbab90 100644
--- a/src/gallium/drivers/svga/svga_tgsi_insn.c
+++ b/src/gallium/drivers/svga/svga_tgsi_insn.c
@@ -25,6 +25,7 @@
#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_dump.h"
#include "tgsi/tgsi_parse.h"
#include "util/u_memory.h"
#include "util/u_math.h"
@@ -1524,6 +1525,73 @@ static boolean emit_tex4(struct svga_shader_emitter *emit,
}
+/**
+ * Emit texture swizzle code.
+ */
+static boolean emit_tex_swizzle( struct svga_shader_emitter *emit,
+ SVGA3dShaderDestToken dst,
+ struct src_register src,
+ unsigned swizzle_x,
+ unsigned swizzle_y,
+ unsigned swizzle_z,
+ unsigned swizzle_w)
+{
+ const unsigned swizzleIn[4] = {swizzle_x, swizzle_y, swizzle_z, swizzle_w};
+ unsigned srcSwizzle[4];
+ unsigned srcWritemask = 0x0, zeroWritemask = 0x0, oneWritemask = 0x0;
+ int i;
+
+ /* build writemasks and srcSwizzle terms */
+ for (i = 0; i < 4; i++) {
+ if (swizzleIn[i] == PIPE_SWIZZLE_ZERO) {
+ srcSwizzle[i] = TGSI_SWIZZLE_X + i;
+ zeroWritemask |= (1 << i);
+ }
+ else if (swizzleIn[i] == PIPE_SWIZZLE_ONE) {
+ srcSwizzle[i] = TGSI_SWIZZLE_X + i;
+ oneWritemask |= (1 << i);
+ }
+ else {
+ srcSwizzle[i] = swizzleIn[i];
+ srcWritemask |= (1 << i);
+ }
+ }
+
+ /* write x/y/z/w comps */
+ if (dst.mask & srcWritemask) {
+ if (!submit_op1(emit,
+ inst_token(SVGA3DOP_MOV),
+ writemask(dst, srcWritemask),
+ swizzle(src,
+ srcSwizzle[0],
+ srcSwizzle[1],
+ srcSwizzle[2],
+ srcSwizzle[3])))
+ return FALSE;
+ }
+
+ /* write 0 comps */
+ if (dst.mask & zeroWritemask) {
+ if (!submit_op1(emit,
+ inst_token(SVGA3DOP_MOV),
+ writemask(dst, zeroWritemask),
+ scalar(get_zero_immediate(emit), TGSI_SWIZZLE_X)))
+ return FALSE;
+ }
+
+ /* write 1 comps */
+ if (dst.mask & oneWritemask) {
+ if (!submit_op1(emit,
+ inst_token(SVGA3DOP_MOV),
+ writemask(dst, oneWritemask),
+ scalar(get_zero_immediate(emit), TGSI_SWIZZLE_W)))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
static boolean emit_tex(struct svga_shader_emitter *emit,
const struct tgsi_full_instruction *insn )
{
@@ -1535,16 +1603,23 @@ static boolean emit_tex(struct svga_shader_emitter *emit,
translate_src_register( emit, &insn->Src[1] );
SVGA3dShaderDestToken tex_result;
+ const unsigned unit = src1.base.num;
/* check for shadow samplers */
- boolean compare = (emit->key.fkey.tex[src1.base.num].compare_mode ==
+ boolean compare = (emit->key.fkey.tex[unit].compare_mode ==
PIPE_TEX_COMPARE_R_TO_TEXTURE);
+ /* texture swizzle */
+ boolean swizzle = (emit->key.fkey.tex[unit].swizzle_r != PIPE_SWIZZLE_RED ||
+ emit->key.fkey.tex[unit].swizzle_g != PIPE_SWIZZLE_GREEN ||
+ emit->key.fkey.tex[unit].swizzle_b != PIPE_SWIZZLE_BLUE ||
+ emit->key.fkey.tex[unit].swizzle_a != PIPE_SWIZZLE_ALPHA);
- /* If doing compare processing, need to put this value into a
- * temporary so it can be used as a source later on.
+ /* If doing compare processing or tex swizzle, need to put fetched color into
+ * a temporary so it can be used as a source later on.
*/
if (compare ||
+ swizzle ||
(!emit->use_sm30 && dst.mask != TGSI_WRITEMASK_XYZW) ) {
tex_result = get_temp( emit );
}
@@ -1570,8 +1645,18 @@ static boolean emit_tex(struct svga_shader_emitter *emit,
if (compare) {
+ SVGA3dShaderDestToken dst2;
+
+ if (swizzle)
+ dst2 = tex_result;
+ else
+ dst2 = dst;
+
if (dst.mask & TGSI_WRITEMASK_XYZ) {
SVGA3dShaderDestToken src0_zdivw = get_temp( emit );
+ /* When sampling a depth texture, the result of the comparison is in
+ * the Y component.
+ */
struct src_register tex_src_x = scalar(src(tex_result), TGSI_SWIZZLE_Y);
/* Divide texcoord R by Q */
@@ -1588,8 +1673,8 @@ static boolean emit_tex(struct svga_shader_emitter *emit,
if (!emit_select(
emit,
- emit->key.fkey.tex[src1.base.num].compare_func,
- writemask( dst, TGSI_WRITEMASK_XYZ ),
+ emit->key.fkey.tex[unit].compare_func,
+ writemask( dst2, TGSI_WRITEMASK_XYZ ),
scalar(src(src0_zdivw), TGSI_SWIZZLE_X),
tex_src_x))
return FALSE;
@@ -1600,15 +1685,29 @@ static boolean emit_tex(struct svga_shader_emitter *emit,
scalar( get_zero_immediate( emit ), TGSI_SWIZZLE_W );
if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ),
- writemask( dst, TGSI_WRITEMASK_W ),
+ writemask( dst2, TGSI_WRITEMASK_W ),
one ))
return FALSE;
}
+ }
- return TRUE;
+ if (swizzle) {
+ /* swizzle from tex_result to dst */
+ emit_tex_swizzle(emit,
+ dst, src(tex_result),
+ emit->key.fkey.tex[unit].swizzle_r,
+ emit->key.fkey.tex[unit].swizzle_g,
+ emit->key.fkey.tex[unit].swizzle_b,
+ emit->key.fkey.tex[unit].swizzle_a);
}
- else if (!emit->use_sm30 && dst.mask != TGSI_WRITEMASK_XYZW)
- {
+
+ if (!emit->use_sm30 &&
+ dst.mask != TGSI_WRITEMASK_XYZW &&
+ !compare &&
+ !swizzle) {
+ /* pre SM3.0 a TEX instruction can't have a writemask. Do it as a
+ * separate step here.
+ */
if (!emit_op1( emit, inst_token( SVGA3DOP_MOV ), dst, src(tex_result) ))
return FALSE;
}
@@ -2934,6 +3033,15 @@ needs_to_create_zero( struct svga_shader_emitter *emit )
if (emit->inverted_texcoords)
return TRUE;
+
+ /* look for any PIPE_SWIZZLE_ZERO/ONE terms */
+ for (i = 0; i < emit->key.fkey.num_textures; i++) {
+ if (emit->key.fkey.tex[i].swizzle_r > PIPE_SWIZZLE_ALPHA ||
+ emit->key.fkey.tex[i].swizzle_g > PIPE_SWIZZLE_ALPHA ||
+ emit->key.fkey.tex[i].swizzle_b > PIPE_SWIZZLE_ALPHA ||
+ emit->key.fkey.tex[i].swizzle_a > PIPE_SWIZZLE_ALPHA)
+ return TRUE;
+ }
}
if (emit->unit == PIPE_SHADER_VERTEX) {