diff options
Diffstat (limited to 'src/mesa/pipe/tgsi/util/tgsi_util.c')
-rw-r--r-- | src/mesa/pipe/tgsi/util/tgsi_util.c | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/src/mesa/pipe/tgsi/util/tgsi_util.c b/src/mesa/pipe/tgsi/util/tgsi_util.c new file mode 100644 index 0000000000..1e76b0f133 --- /dev/null +++ b/src/mesa/pipe/tgsi/util/tgsi_util.c @@ -0,0 +1,273 @@ +#include "pipe/p_util.h" +#include "pipe/p_shader_tokens.h" +#include "tgsi_parse.h" +#include "tgsi_build.h" +#include "tgsi_util.h" + +union pointer_hack +{ + void *pointer; + unsigned long long uint64; +}; + +void * +tgsi_align_128bit( + void *unaligned ) +{ + union pointer_hack ph; + + ph.uint64 = 0; + ph.pointer = unaligned; + ph.uint64 = (ph.uint64 + 15) & ~15; + return ph.pointer; +} + +unsigned +tgsi_util_get_src_register_swizzle( + const struct tgsi_src_register *reg, + unsigned component ) +{ + switch( component ) { + case 0: + return reg->SwizzleX; + case 1: + return reg->SwizzleY; + case 2: + return reg->SwizzleZ; + case 3: + return reg->SwizzleW; + default: + assert( 0 ); + } + return 0; +} + +unsigned +tgsi_util_get_src_register_extswizzle( + const struct tgsi_src_register_ext_swz *reg, + unsigned component ) +{ + switch( component ) { + case 0: + return reg->ExtSwizzleX; + case 1: + return reg->ExtSwizzleY; + case 2: + return reg->ExtSwizzleZ; + case 3: + return reg->ExtSwizzleW; + default: + assert( 0 ); + } + return 0; +} + +unsigned +tgsi_util_get_full_src_register_extswizzle( + const struct tgsi_full_src_register *reg, + unsigned component ) +{ + unsigned swizzle; + + /* + * First, calculate the extended swizzle for a given channel. This will give + * us either a channel index into the simple swizzle or a constant 1 or 0. + */ + swizzle = tgsi_util_get_src_register_extswizzle( + ®->SrcRegisterExtSwz, + component ); + + assert (TGSI_SWIZZLE_X == TGSI_EXTSWIZZLE_X); + assert (TGSI_SWIZZLE_Y == TGSI_EXTSWIZZLE_Y); + assert (TGSI_SWIZZLE_Z == TGSI_EXTSWIZZLE_Z); + assert (TGSI_SWIZZLE_W == TGSI_EXTSWIZZLE_W); + assert (TGSI_EXTSWIZZLE_ZERO > TGSI_SWIZZLE_W); + assert (TGSI_EXTSWIZZLE_ONE > TGSI_SWIZZLE_W); + + /* + * Second, calculate the simple swizzle for the unswizzled channel index. + * Leave the constants intact, they are not affected by the simple swizzle. + */ + if( swizzle <= TGSI_SWIZZLE_W ) { + swizzle = tgsi_util_get_src_register_swizzle( + ®->SrcRegister, + component ); + } + + return swizzle; +} + +void +tgsi_util_set_src_register_swizzle( + struct tgsi_src_register *reg, + unsigned swizzle, + unsigned component ) +{ + switch( component ) { + case 0: + reg->SwizzleX = swizzle; + break; + case 1: + reg->SwizzleY = swizzle; + break; + case 2: + reg->SwizzleZ = swizzle; + break; + case 3: + reg->SwizzleW = swizzle; + break; + default: + assert( 0 ); + } +} + +void +tgsi_util_set_src_register_extswizzle( + struct tgsi_src_register_ext_swz *reg, + unsigned swizzle, + unsigned component ) +{ + switch( component ) { + case 0: + reg->ExtSwizzleX = swizzle; + break; + case 1: + reg->ExtSwizzleY = swizzle; + break; + case 2: + reg->ExtSwizzleZ = swizzle; + break; + case 3: + reg->ExtSwizzleW = swizzle; + break; + default: + assert( 0 ); + } +} + +unsigned +tgsi_util_get_src_register_extnegate( + const struct tgsi_src_register_ext_swz *reg, + unsigned component ) +{ + switch( component ) { + case 0: + return reg->NegateX; + case 1: + return reg->NegateY; + case 2: + return reg->NegateZ; + case 3: + return reg->NegateW; + default: + assert( 0 ); + } + return 0; +} + +void +tgsi_util_set_src_register_extnegate( + struct tgsi_src_register_ext_swz *reg, + unsigned negate, + unsigned component ) +{ + switch( component ) { + case 0: + reg->NegateX = negate; + break; + case 1: + reg->NegateY = negate; + break; + case 2: + reg->NegateZ = negate; + break; + case 3: + reg->NegateW = negate; + break; + default: + assert( 0 ); + } +} + +unsigned +tgsi_util_get_full_src_register_sign_mode( + const struct tgsi_full_src_register *reg, + unsigned component ) +{ + unsigned sign_mode; + + if( reg->SrcRegisterExtMod.Absolute ) { + /* Consider only the post-abs negation. */ + + if( reg->SrcRegisterExtMod.Negate ) { + sign_mode = TGSI_UTIL_SIGN_SET; + } + else { + sign_mode = TGSI_UTIL_SIGN_CLEAR; + } + } + else { + /* Accumulate the three negations. */ + + unsigned negate; + + negate = reg->SrcRegister.Negate; + if( tgsi_util_get_src_register_extnegate( ®->SrcRegisterExtSwz, component ) ) { + negate = !negate; + } + if( reg->SrcRegisterExtMod.Negate ) { + negate = !negate; + } + + if( negate ) { + sign_mode = TGSI_UTIL_SIGN_TOGGLE; + } + else { + sign_mode = TGSI_UTIL_SIGN_KEEP; + } + } + + return sign_mode; +} + +void +tgsi_util_set_full_src_register_sign_mode( + struct tgsi_full_src_register *reg, + unsigned sign_mode ) +{ + reg->SrcRegisterExtSwz.NegateX = 0; + reg->SrcRegisterExtSwz.NegateY = 0; + reg->SrcRegisterExtSwz.NegateZ = 0; + reg->SrcRegisterExtSwz.NegateW = 0; + + switch (sign_mode) + { + case TGSI_UTIL_SIGN_CLEAR: + reg->SrcRegister.Negate = 0; + reg->SrcRegisterExtMod.Absolute = 1; + reg->SrcRegisterExtMod.Negate = 0; + break; + + case TGSI_UTIL_SIGN_SET: + reg->SrcRegister.Negate = 0; + reg->SrcRegisterExtMod.Absolute = 1; + reg->SrcRegisterExtMod.Negate = 1; + break; + + case TGSI_UTIL_SIGN_TOGGLE: + reg->SrcRegister.Negate = 1; + reg->SrcRegisterExtMod.Absolute = 0; + reg->SrcRegisterExtMod.Negate = 0; + break; + + case TGSI_UTIL_SIGN_KEEP: + reg->SrcRegister.Negate = 0; + reg->SrcRegisterExtMod.Absolute = 0; + reg->SrcRegisterExtMod.Negate = 0; + break; + + default: + assert( 0 ); + } +} + |