diff options
Diffstat (limited to 'mesalib/src/gallium/auxiliary/util')
-rw-r--r-- | mesalib/src/gallium/auxiliary/util/u_atomic.h | 56 | ||||
-rw-r--r-- | mesalib/src/gallium/auxiliary/util/u_blit.c | 4 | ||||
-rw-r--r-- | mesalib/src/gallium/auxiliary/util/u_blitter.c | 7 | ||||
-rw-r--r-- | mesalib/src/gallium/auxiliary/util/u_box.h | 118 | ||||
-rw-r--r-- | mesalib/src/gallium/auxiliary/util/u_format_pack.py | 35 | ||||
-rw-r--r-- | mesalib/src/gallium/auxiliary/util/u_pstipple.c | 228 | ||||
-rw-r--r-- | mesalib/src/gallium/auxiliary/util/u_pstipple.h | 5 | ||||
-rw-r--r-- | mesalib/src/gallium/auxiliary/util/u_rect.h | 18 | ||||
-rw-r--r-- | mesalib/src/gallium/auxiliary/util/u_simple_shaders.c | 80 | ||||
-rw-r--r-- | mesalib/src/gallium/auxiliary/util/u_simple_shaders.h | 10 | ||||
-rw-r--r-- | mesalib/src/gallium/auxiliary/util/u_snprintf.c | 2 | ||||
-rw-r--r-- | mesalib/src/gallium/auxiliary/util/u_tests.c | 268 | ||||
-rw-r--r-- | mesalib/src/gallium/auxiliary/util/u_tests.h | 37 |
13 files changed, 696 insertions, 172 deletions
diff --git a/mesalib/src/gallium/auxiliary/util/u_atomic.h b/mesalib/src/gallium/auxiliary/util/u_atomic.h index 2f2b42b34..2500bc752 100644 --- a/mesalib/src/gallium/auxiliary/util/u_atomic.h +++ b/mesalib/src/gallium/auxiliary/util/u_atomic.h @@ -24,12 +24,12 @@ #define PIPE_ATOMIC_MSVC_INTRINSIC #elif (defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86)) #define PIPE_ATOMIC_ASM_MSVC_X86 +#elif defined(PIPE_CC_GCC) && (PIPE_CC_GCC_VERSION >= 401) +#define PIPE_ATOMIC_GCC_INTRINSIC #elif (defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86)) #define PIPE_ATOMIC_ASM_GCC_X86 #elif (defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86_64)) #define PIPE_ATOMIC_ASM_GCC_X86_64 -#elif defined(PIPE_CC_GCC) && (PIPE_CC_GCC_VERSION >= 401) -#define PIPE_ATOMIC_GCC_INTRINSIC #else #error "Unsupported platform" #endif @@ -69,6 +69,18 @@ p_atomic_dec(int32_t *v) } static INLINE int32_t +p_atomic_inc_return(int32_t *v) +{ + return __sync_add_and_fetch(v, 1); +} + +static INLINE int32_t +p_atomic_dec_return(int32_t *v) +{ + return __sync_sub_and_fetch(v, 1); +} + +static INLINE int32_t p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new) { return __sync_val_compare_and_swap(v, old, _new); @@ -116,6 +128,18 @@ p_atomic_dec(int32_t *v) } static INLINE int32_t +p_atomic_inc_return(int32_t *v) +{ + return __sync_add_and_fetch(v, 1); +} + +static INLINE int32_t +p_atomic_dec_return(int32_t *v) +{ + return __sync_sub_and_fetch(v, 1); +} + +static INLINE int32_t p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new) { return __sync_val_compare_and_swap(v, old, _new); @@ -161,6 +185,18 @@ p_atomic_dec(int32_t *v) } static INLINE int32_t +p_atomic_inc_return(int32_t *v) +{ + return __sync_add_and_fetch(v, 1); +} + +static INLINE int32_t +p_atomic_dec_return(int32_t *v) +{ + return __sync_sub_and_fetch(v, 1); +} + +static INLINE int32_t p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new) { return __sync_val_compare_and_swap(v, old, _new); @@ -186,6 +222,8 @@ p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new) #define p_atomic_dec_zero(_v) ((boolean) --(*(_v))) #define p_atomic_inc(_v) ((void) (*(_v))++) #define p_atomic_dec(_v) ((void) (*(_v))--) +#define p_atomic_inc_return(_v) ((*(_v))++) +#define p_atomic_dec_return(_v) ((*(_v))--) #define p_atomic_cmpxchg(_v, old, _new) (*(_v) == old ? *(_v) = (_new) : *(_v)) #endif @@ -288,6 +326,12 @@ p_atomic_inc(int32_t *v) _InterlockedIncrement((long *)v); } +static INLINE int32_t +p_atomic_inc_return(int32_t *v) +{ + return _InterlockedIncrement((long *)v); +} + static INLINE void p_atomic_dec(int32_t *v) { @@ -295,6 +339,12 @@ p_atomic_dec(int32_t *v) } static INLINE int32_t +p_atomic_dec_return(int32_t *v) +{ + return _InterlockedDecrement((long *)v); +} + +static INLINE int32_t p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new) { return _InterlockedCompareExchange((long *)v, _new, old); @@ -329,6 +379,8 @@ p_atomic_dec_zero(int32_t *v) #define p_atomic_inc(_v) atomic_inc_32((uint32_t *) _v) #define p_atomic_dec(_v) atomic_dec_32((uint32_t *) _v) +#define p_atomic_inc_return(_v) atomic_inc_32_nv((uint32_t *) _v) +#define p_atomic_dec_return(_v) atomic_dec_32_nv((uint32_t *) _v) #define p_atomic_cmpxchg(_v, _old, _new) \ atomic_cas_32( (uint32_t *) _v, (uint32_t) _old, (uint32_t) _new) diff --git a/mesalib/src/gallium/auxiliary/util/u_blit.c b/mesalib/src/gallium/auxiliary/util/u_blit.c index 2573bedf5..90408ffdc 100644 --- a/mesalib/src/gallium/auxiliary/util/u_blit.c +++ b/mesalib/src/gallium/auxiliary/util/u_blit.c @@ -188,7 +188,7 @@ set_vertex_shader(struct blit_state *ctx) const uint semantic_indexes[] = { 0, 0 }; ctx->vs = util_make_vertex_passthrough_shader(ctx->pipe, 2, semantic_names, - semantic_indexes); + semantic_indexes, FALSE); } cso_set_vertex_shader_handle(ctx->cso, ctx->vs); @@ -559,11 +559,9 @@ util_blit_pixels_tex(struct blit_state *ctx, ctx->viewport.scale[0] = 0.5f * dst->width; ctx->viewport.scale[1] = 0.5f * dst->height; ctx->viewport.scale[2] = 0.5f; - ctx->viewport.scale[3] = 1.0f; ctx->viewport.translate[0] = 0.5f * dst->width; ctx->viewport.translate[1] = 0.5f * dst->height; ctx->viewport.translate[2] = 0.5f; - ctx->viewport.translate[3] = 0.0f; cso_set_viewport(ctx->cso, &ctx->viewport); /* texture */ diff --git a/mesalib/src/gallium/auxiliary/util/u_blitter.c b/mesalib/src/gallium/auxiliary/util/u_blitter.c index e59fa0481..9d087fe8a 100644 --- a/mesalib/src/gallium/auxiliary/util/u_blitter.c +++ b/mesalib/src/gallium/auxiliary/util/u_blitter.c @@ -319,7 +319,8 @@ static void bind_vs_pos_only(struct blitter_context_priv *ctx) ctx->vs_pos_only = util_make_vertex_passthrough_shader_with_so(pipe, 1, semantic_names, - semantic_indices, &so); + semantic_indices, FALSE, + &so); } pipe->bind_vs_state(pipe, ctx->vs_pos_only); @@ -335,7 +336,7 @@ static void bind_vs_passthrough(struct blitter_context_priv *ctx) const uint semantic_indices[] = { 0, 0 }; ctx->vs = util_make_vertex_passthrough_shader(pipe, 2, semantic_names, - semantic_indices); + semantic_indices, FALSE); } pipe->bind_vs_state(pipe, ctx->vs); @@ -682,11 +683,9 @@ static void blitter_set_rectangle(struct blitter_context_priv *ctx, ctx->viewport.scale[0] = 0.5f * ctx->dst_width; ctx->viewport.scale[1] = 0.5f * ctx->dst_height; ctx->viewport.scale[2] = 1.0f; - ctx->viewport.scale[3] = 1.0f; ctx->viewport.translate[0] = 0.5f * ctx->dst_width; ctx->viewport.translate[1] = 0.5f * ctx->dst_height; ctx->viewport.translate[2] = 0.0f; - ctx->viewport.translate[3] = 0.0f; ctx->base.pipe->set_viewport_states(ctx->base.pipe, 0, 1, &ctx->viewport); } diff --git a/mesalib/src/gallium/auxiliary/util/u_box.h b/mesalib/src/gallium/auxiliary/util/u_box.h index 0b28d0f12..520a3d596 100644 --- a/mesalib/src/gallium/auxiliary/util/u_box.h +++ b/mesalib/src/gallium/auxiliary/util/u_box.h @@ -2,6 +2,7 @@ #define UTIL_BOX_INLINES_H #include "pipe/p_state.h" +#include "util/u_math.h" static INLINE void u_box_1d( unsigned x, @@ -77,4 +78,121 @@ void u_box_3d( unsigned x, box->depth = d; } +/* Clips @dst to width @w and height @h. + * Returns -1 if the resulting box would be empty (then @dst is left unchanged). + * 0 if nothing has been reduced. + * 1 if width has been reduced. + * 2 if height has been reduced. + * 3 if both width and height have been reduced. + * Aliasing permitted. + */ +static INLINE int +u_box_clip_2d(struct pipe_box *dst, + const struct pipe_box *box, int w, int h) +{ + unsigned i; + int a[2], b[2], dim[2]; + int *start, *end; + int res = 0; + + if (!box->width || !box->height) + return -1; + dim[0] = w; + dim[1] = h; + a[0] = box->x; + a[1] = box->y; + b[0] = box->x + box->width; + b[1] = box->y + box->height; + + for (i = 0; i < 2; ++i) { + start = (a[i] <= b[i]) ? &a[i] : &b[i]; + end = (a[i] <= b[i]) ? &b[i] : &a[i]; + + if (*end < 0 || *start >= dim[i]) + return -1; + if (*start < 0) { + *start = 0; + res |= (1 << i); + } + if (*end > dim[i]) { + *end = dim[i]; + res |= (1 << i); + } + } + + if (res) { + dst->x = a[0]; + dst->y = a[1]; + dst->width = b[0] - a[0]; + dst->height = b[1] - a[1]; + } + return res; +} + +static INLINE int64_t +u_box_volume_3d(const struct pipe_box *box) +{ + return (int64_t)box->width * box->height * box->depth; +} + +/* Aliasing of @dst permitted. */ +static INLINE void +u_box_union_2d(struct pipe_box *dst, + const struct pipe_box *a, const struct pipe_box *b) +{ + dst->x = MIN2(a->x, b->x); + dst->y = MIN2(a->y, b->y); + + dst->width = MAX2(a->x + a->width, b->x + b->width) - dst->x; + dst->height = MAX2(a->y + a->height, b->y + b->height) - dst->y; +} + +/* Aliasing of @dst permitted. */ +static INLINE void +u_box_union_3d(struct pipe_box *dst, + const struct pipe_box *a, const struct pipe_box *b) +{ + dst->x = MIN2(a->x, b->x); + dst->y = MIN2(a->y, b->y); + dst->z = MIN2(a->z, b->z); + + dst->width = MAX2(a->x + a->width, b->x + b->width) - dst->x; + dst->height = MAX2(a->y + a->height, b->y + b->height) - dst->y; + dst->depth = MAX2(a->z + a->depth, b->z + b->depth) - dst->z; +} + +static INLINE boolean +u_box_test_intersection_2d(const struct pipe_box *a, + const struct pipe_box *b) +{ + unsigned i; + int a_l[2], a_r[2], b_l[2], b_r[2]; + + a_l[0] = MIN2(a->x, a->x + a->width); + a_r[0] = MAX2(a->x, a->x + a->width); + a_l[1] = MIN2(a->y, a->y + a->height); + a_r[1] = MAX2(a->y, a->y + a->height); + + b_l[0] = MIN2(b->x, b->x + b->width); + b_r[0] = MAX2(b->x, b->x + b->width); + b_l[1] = MIN2(b->y, b->y + b->height); + b_r[1] = MAX2(b->y, b->y + b->height); + + for (i = 0; i < 2; ++i) { + if (a_l[i] > b_r[i] || a_r[i] < b_l[i]) + return FALSE; + } + return TRUE; +} + +static INLINE void +u_box_minify_2d(struct pipe_box *dst, + const struct pipe_box *src, unsigned l) +{ + dst->x = src->x >> l; + dst->y = src->y >> l; + dst->width = MAX2(src->width >> l, 1); + dst->height = MAX2(src->height >> l, 1); +} + #endif diff --git a/mesalib/src/gallium/auxiliary/util/u_format_pack.py b/mesalib/src/gallium/auxiliary/util/u_format_pack.py index 6ccf04c29..d5138cc05 100644 --- a/mesalib/src/gallium/auxiliary/util/u_format_pack.py +++ b/mesalib/src/gallium/auxiliary/util/u_format_pack.py @@ -207,9 +207,36 @@ def get_one_shift(type): assert False +def truncate_mantissa(x, bits): + '''Truncate an integer so it can be represented exactly with a floating + point mantissa''' + + assert isinstance(x, (int, long)) + + s = 1 + if x < 0: + s = -1 + x = -x + + # We can represent integers up to mantissa + 1 bits exactly + mask = (1 << (bits + 1)) - 1 + + # Slide the mask until the MSB matches + shift = 0 + while (x >> shift) & ~mask: + shift += 1 + + x &= mask << shift + x *= s + return x + + def value_to_native(type, value): '''Get the value of unity for this type.''' if type.type == FLOAT: + if type.size <= 32 \ + and isinstance(value, (int, long)): + return truncate_mantissa(value, 23) return value if type.type == FIXED: return int(value * (1 << (type.size/2))) @@ -226,9 +253,9 @@ def native_to_constant(type, value): '''Get the value of unity for this type.''' if type.type == FLOAT: if type.size <= 32: - return "%ff" % value + return "%.1ff" % float(value) else: - return "%ff" % value + return "%.1f" % float(value) else: return str(int(value)) @@ -251,8 +278,8 @@ def clamp_expr(src_channel, dst_channel, dst_native_type, value): dst_max = dst_channel.max() # Translate the destination range to the src native value - dst_min_native = value_to_native(src_channel, dst_min) - dst_max_native = value_to_native(src_channel, dst_max) + dst_min_native = native_to_constant(src_channel, value_to_native(src_channel, dst_min)) + dst_max_native = native_to_constant(src_channel, value_to_native(src_channel, dst_max)) if src_min < dst_min and src_max > dst_max: return 'CLAMP(%s, %s, %s)' % (value, dst_min_native, dst_max_native) diff --git a/mesalib/src/gallium/auxiliary/util/u_pstipple.c b/mesalib/src/gallium/auxiliary/util/u_pstipple.c index 509f815c5..1e1ec4a98 100644 --- a/mesalib/src/gallium/auxiliary/util/u_pstipple.c +++ b/mesalib/src/gallium/auxiliary/util/u_pstipple.c @@ -180,9 +180,7 @@ struct pstip_transform_context { int maxInput; uint samplersUsed; /**< bitfield of samplers used */ int freeSampler; /** an available sampler for the pstipple */ - int texTemp; /**< temp registers */ int numImmed; - boolean firstInstruction; uint coordOrigin; }; @@ -243,7 +241,7 @@ free_bit(uint bitfield) /** - * TGSI instruction transform callback. + * TGSI transform prolog * Before the first instruction, insert our new code to sample the * stipple texture (using the fragment coord register) then kill the * fragment if the stipple texture bit is off. @@ -256,165 +254,95 @@ free_bit(uint bitfield) * [...original code...] */ static void -pstip_transform_inst(struct tgsi_transform_context *ctx, - struct tgsi_full_instruction *inst) +pstip_transform_prolog(struct tgsi_transform_context *ctx) { struct pstip_transform_context *pctx = (struct pstip_transform_context *) ctx; + int wincoordInput; + int texTemp; + + /* find free texture sampler */ + pctx->freeSampler = free_bit(pctx->samplersUsed); + if (pctx->freeSampler >= PIPE_MAX_SAMPLERS) + pctx->freeSampler = PIPE_MAX_SAMPLERS - 1; + + if (pctx->wincoordInput < 0) + wincoordInput = pctx->maxInput + 1; + else + wincoordInput = pctx->wincoordInput; + + if (pctx->wincoordInput < 0) { + /* declare new position input reg */ + tgsi_transform_input_decl(ctx, wincoordInput, + TGSI_SEMANTIC_POSITION, 1, + TGSI_INTERPOLATE_LINEAR); + } - if (pctx->firstInstruction) { - /* emit our new declarations before the first instruction */ - - struct tgsi_full_declaration decl; - struct tgsi_full_instruction newInst; - uint i; - int wincoordInput; - - /* find free texture sampler */ - pctx->freeSampler = free_bit(pctx->samplersUsed); - if (pctx->freeSampler >= PIPE_MAX_SAMPLERS) - pctx->freeSampler = PIPE_MAX_SAMPLERS - 1; - - if (pctx->wincoordInput < 0) - wincoordInput = pctx->maxInput + 1; - else - wincoordInput = pctx->wincoordInput; - - /* find one free temp register */ - for (i = 0; i < 32; i++) { - if ((pctx->tempsUsed & (1 << i)) == 0) { - /* found a free temp */ - if (pctx->texTemp < 0) - pctx->texTemp = i; - else - break; - } - } - assert(pctx->texTemp >= 0); - - if (pctx->wincoordInput < 0) { - /* declare new position input reg */ - decl = tgsi_default_full_declaration(); - decl.Declaration.File = TGSI_FILE_INPUT; - decl.Declaration.Interpolate = 1; - decl.Declaration.Semantic = 1; - decl.Semantic.Name = TGSI_SEMANTIC_POSITION; - decl.Semantic.Index = 0; - decl.Range.First = - decl.Range.Last = wincoordInput; - decl.Interp.Interpolate = TGSI_INTERPOLATE_LINEAR; - ctx->emit_declaration(ctx, &decl); - } + /* declare new sampler */ + tgsi_transform_sampler_decl(ctx, pctx->freeSampler); - /* declare new sampler */ - decl = tgsi_default_full_declaration(); - decl.Declaration.File = TGSI_FILE_SAMPLER; - decl.Range.First = - decl.Range.Last = pctx->freeSampler; - ctx->emit_declaration(ctx, &decl); - - /* declare new temp regs */ - decl = tgsi_default_full_declaration(); - decl.Declaration.File = TGSI_FILE_TEMPORARY; - decl.Range.First = - decl.Range.Last = pctx->texTemp; - ctx->emit_declaration(ctx, &decl); - - /* emit immediate = {1/32, 1/32, 1, 1} - * The index/position of this immediate will be pctx->numImmed - */ - { - static const float value[4] = { 1.0/32, 1.0/32, 1.0, 1.0 }; - struct tgsi_full_immediate immed; - uint size = 4; - immed = tgsi_default_full_immediate(); - immed.Immediate.NrTokens = 1 + size; /* one for the token itself */ - immed.u[0].Float = value[0]; - immed.u[1].Float = value[1]; - immed.u[2].Float = value[2]; - immed.u[3].Float = value[3]; - ctx->emit_immediate(ctx, &immed); - } - - pctx->firstInstruction = FALSE; - - - /* - * Insert new MUL/TEX/KILL_IF instructions at start of program - * Take gl_FragCoord, divide by 32 (stipple size), sample the - * texture and kill fragment if needed. - * - * We'd like to use non-normalized texcoords to index into a RECT - * texture, but we can only use REPEAT wrap mode with normalized - * texcoords. Darn. - */ - - /* XXX invert wincoord if origin isn't lower-left... */ - - /* MUL texTemp, INPUT[wincoord], 1/32; */ - newInst = tgsi_default_full_instruction(); - newInst.Instruction.Opcode = TGSI_OPCODE_MUL; - newInst.Instruction.NumDstRegs = 1; - newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; - newInst.Dst[0].Register.Index = pctx->texTemp; - newInst.Instruction.NumSrcRegs = 2; - newInst.Src[0].Register.File = TGSI_FILE_INPUT; - newInst.Src[0].Register.Index = wincoordInput; - newInst.Src[1].Register.File = TGSI_FILE_IMMEDIATE; - newInst.Src[1].Register.Index = pctx->numImmed; - ctx->emit_instruction(ctx, &newInst); - - /* TEX texTemp, texTemp, sampler; */ - newInst = tgsi_default_full_instruction(); - newInst.Instruction.Opcode = TGSI_OPCODE_TEX; - newInst.Instruction.NumDstRegs = 1; - newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; - newInst.Dst[0].Register.Index = pctx->texTemp; - newInst.Instruction.NumSrcRegs = 2; - newInst.Instruction.Texture = TRUE; - newInst.Texture.Texture = TGSI_TEXTURE_2D; - newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY; - newInst.Src[0].Register.Index = pctx->texTemp; - newInst.Src[1].Register.File = TGSI_FILE_SAMPLER; - newInst.Src[1].Register.Index = pctx->freeSampler; - ctx->emit_instruction(ctx, &newInst); - - /* KILL_IF -texTemp; # if -texTemp < 0, kill fragment */ - newInst = tgsi_default_full_instruction(); - newInst.Instruction.Opcode = TGSI_OPCODE_KILL_IF; - newInst.Instruction.NumDstRegs = 0; - newInst.Instruction.NumSrcRegs = 1; - newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY; - newInst.Src[0].Register.Index = pctx->texTemp; - newInst.Src[0].Register.Negate = 1; - ctx->emit_instruction(ctx, &newInst); + /* Declare temp[0] reg if not already declared. + * We can always use temp[0] since this code is before + * the rest of the shader. + */ + texTemp = 0; + if ((pctx->tempsUsed & (1 << texTemp)) == 0) { + tgsi_transform_temp_decl(ctx, texTemp); } - /* emit this instruction */ - ctx->emit_instruction(ctx, inst); + /* emit immediate = {1/32, 1/32, 1, 1} + * The index/position of this immediate will be pctx->numImmed + */ + tgsi_transform_immediate_decl(ctx, 1.0/32.0, 1.0/32.0, 1.0, 1.0); + + /* + * Insert new MUL/TEX/KILL_IF instructions at start of program + * Take gl_FragCoord, divide by 32 (stipple size), sample the + * texture and kill fragment if needed. + * + * We'd like to use non-normalized texcoords to index into a RECT + * texture, but we can only use REPEAT wrap mode with normalized + * texcoords. Darn. + */ + + /* XXX invert wincoord if origin isn't lower-left... */ + + /* MUL texTemp, INPUT[wincoord], 1/32; */ + tgsi_transform_op2_inst(ctx, TGSI_OPCODE_MUL, + TGSI_FILE_TEMPORARY, texTemp, + TGSI_WRITEMASK_XYZW, + TGSI_FILE_INPUT, wincoordInput, + TGSI_FILE_IMMEDIATE, pctx->numImmed); + + /* TEX texTemp, texTemp, sampler; */ + tgsi_transform_tex_2d_inst(ctx, + TGSI_FILE_TEMPORARY, texTemp, + TGSI_FILE_TEMPORARY, texTemp, + pctx->freeSampler); + + /* KILL_IF -texTemp; # if -texTemp < 0, kill fragment */ + tgsi_transform_kill_inst(ctx, + TGSI_FILE_TEMPORARY, texTemp, + TGSI_SWIZZLE_W); } /** * Given a fragment shader, return a new fragment shader which * samples a stipple texture and executes KILL. + * \param samplerUnitOut returns the index of the sampler unit which + * will be used to sample the stipple texture */ -struct pipe_shader_state * -util_pstipple_create_fragment_shader(struct pipe_context *pipe, - struct pipe_shader_state *fs, +struct tgsi_token * +util_pstipple_create_fragment_shader(const struct tgsi_token *tokens, unsigned *samplerUnitOut) { - struct pipe_shader_state *new_fs; struct pstip_transform_context transform; - const uint newLen = tgsi_num_tokens(fs->tokens) + NUM_NEW_TOKENS; - - new_fs = MALLOC(sizeof(*new_fs)); - if (!new_fs) - return NULL; + const uint newLen = tgsi_num_tokens(tokens) + NUM_NEW_TOKENS; + struct tgsi_token *new_tokens; - new_fs->tokens = tgsi_alloc_tokens(newLen); - if (!new_fs->tokens) { - FREE(new_fs); + new_tokens = tgsi_alloc_tokens(newLen); + if (!new_tokens) { return NULL; } @@ -423,21 +351,17 @@ util_pstipple_create_fragment_shader(struct pipe_context *pipe, memset(&transform, 0, sizeof(transform)); transform.wincoordInput = -1; transform.maxInput = -1; - transform.texTemp = -1; - transform.firstInstruction = TRUE; transform.coordOrigin = TGSI_FS_COORD_ORIGIN_UPPER_LEFT; - transform.base.transform_instruction = pstip_transform_inst; + transform.base.prolog = pstip_transform_prolog; transform.base.transform_declaration = pstip_transform_decl; transform.base.transform_immediate = pstip_transform_immed; - tgsi_scan_shader(fs->tokens, &transform.info); + tgsi_scan_shader(tokens, &transform.info); transform.coordOrigin = transform.info.properties[TGSI_PROPERTY_FS_COORD_ORIGIN]; - tgsi_transform_shader(fs->tokens, - (struct tgsi_token *) new_fs->tokens, - newLen, &transform.base); + tgsi_transform_shader(tokens, new_tokens, newLen, &transform.base); #if 0 /* DEBUG */ tgsi_dump(fs->tokens, 0); @@ -447,6 +371,6 @@ util_pstipple_create_fragment_shader(struct pipe_context *pipe, assert(transform.freeSampler < PIPE_MAX_SAMPLERS); *samplerUnitOut = transform.freeSampler; - return new_fs; + return new_tokens; } diff --git a/mesalib/src/gallium/auxiliary/util/u_pstipple.h b/mesalib/src/gallium/auxiliary/util/u_pstipple.h index 6fbed80cc..13155e7f5 100644 --- a/mesalib/src/gallium/auxiliary/util/u_pstipple.h +++ b/mesalib/src/gallium/auxiliary/util/u_pstipple.h @@ -47,9 +47,8 @@ util_pstipple_create_sampler_view(struct pipe_context *pipe, extern void * util_pstipple_create_sampler(struct pipe_context *pipe); -extern struct pipe_shader_state * -util_pstipple_create_fragment_shader(struct pipe_context *pipe, - struct pipe_shader_state *fs, +struct tgsi_token * +util_pstipple_create_fragment_shader(const struct tgsi_token *tokens, unsigned *samplerUnitOut); diff --git a/mesalib/src/gallium/auxiliary/util/u_rect.h b/mesalib/src/gallium/auxiliary/util/u_rect.h index dd87f81f3..cf29dff0d 100644 --- a/mesalib/src/gallium/auxiliary/util/u_rect.h +++ b/mesalib/src/gallium/auxiliary/util/u_rect.h @@ -30,6 +30,7 @@ #define U_RECT_H #include "pipe/p_compiler.h" +#include "util/u_math.h" #ifdef __cplusplus extern "C" { @@ -67,6 +68,12 @@ u_rect_find_intersection(const struct u_rect *a, } +static INLINE int +u_rect_area(const struct u_rect *r) +{ + return (r->x1 - r->x0) * (r->y1 - r->y0); +} + static INLINE void u_rect_possible_intersection(const struct u_rect *a, struct u_rect *b) @@ -79,6 +86,17 @@ u_rect_possible_intersection(const struct u_rect *a, } } +/* Set @d to a rectangle that covers both @a and @b. + */ +static INLINE void +u_rect_union(struct u_rect *d, const struct u_rect *a, const struct u_rect *b) +{ + d->x0 = MIN2(a->x0, b->x0); + d->y0 = MIN2(a->y0, b->y0); + d->x1 = MAX2(a->x1, b->x1); + d->y1 = MAX2(a->y1, b->y1); +} + #ifdef __cplusplus } #endif diff --git a/mesalib/src/gallium/auxiliary/util/u_simple_shaders.c b/mesalib/src/gallium/auxiliary/util/u_simple_shaders.c index adf4887d5..edb30379b 100644 --- a/mesalib/src/gallium/auxiliary/util/u_simple_shaders.c +++ b/mesalib/src/gallium/auxiliary/util/u_simple_shaders.c @@ -59,11 +59,13 @@ void * util_make_vertex_passthrough_shader(struct pipe_context *pipe, uint num_attribs, const uint *semantic_names, - const uint *semantic_indexes) + const uint *semantic_indexes, + bool window_space) { return util_make_vertex_passthrough_shader_with_so(pipe, num_attribs, semantic_names, - semantic_indexes, NULL); + semantic_indexes, + window_space, NULL); } void * @@ -71,6 +73,7 @@ util_make_vertex_passthrough_shader_with_so(struct pipe_context *pipe, uint num_attribs, const uint *semantic_names, const uint *semantic_indexes, + bool window_space, const struct pipe_stream_output_info *so) { struct ureg_program *ureg; @@ -80,6 +83,9 @@ util_make_vertex_passthrough_shader_with_so(struct pipe_context *pipe, if (ureg == NULL) return NULL; + if (window_space) + ureg_property(ureg, TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION, TRUE); + for (i = 0; i < num_attribs; i++) { struct ureg_src src; struct ureg_dst dst; @@ -124,6 +130,76 @@ void *util_make_layered_clear_vertex_shader(struct pipe_context *pipe) return pipe->create_vs_state(pipe, &state); } +/** + * Takes position and color, and outputs position, color, and instance id. + */ +void *util_make_layered_clear_helper_vertex_shader(struct pipe_context *pipe) +{ + static const char text[] = + "VERT\n" + "DCL IN[0]\n" + "DCL IN[1]\n" + "DCL SV[0], INSTANCEID\n" + "DCL OUT[0], POSITION\n" + "DCL OUT[1], GENERIC[0]\n" + "DCL OUT[2], GENERIC[1]\n" + + "MOV OUT[0], IN[0]\n" + "MOV OUT[1], IN[1]\n" + "MOV OUT[2].x, SV[0].xxxx\n" + "END\n"; + struct tgsi_token tokens[1000]; + struct pipe_shader_state state = {tokens}; + + if (!tgsi_text_translate(text, tokens, Elements(tokens))) { + assert(0); + return NULL; + } + return pipe->create_vs_state(pipe, &state); +} + +/** + * Takes position, color, and target layer, and emits vertices on that target + * layer, with the specified color. + */ +void *util_make_layered_clear_geometry_shader(struct pipe_context *pipe) +{ + static const char text[] = + "GEOM\n" + "PROPERTY GS_INPUT_PRIMITIVE TRIANGLES\n" + "PROPERTY GS_OUTPUT_PRIMITIVE TRIANGLE_STRIP\n" + "PROPERTY GS_MAX_OUTPUT_VERTICES 3\n" + "PROPERTY GS_INVOCATIONS 1\n" + "DCL IN[][0], POSITION\n" /* position */ + "DCL IN[][1], GENERIC[0]\n" /* color */ + "DCL IN[][2], GENERIC[1]\n" /* vs invocation */ + "DCL OUT[0], POSITION\n" + "DCL OUT[1], GENERIC[0]\n" + "DCL OUT[2], LAYER\n" + "IMM[0] INT32 {0, 0, 0, 0}\n" + + "MOV OUT[0], IN[0][0]\n" + "MOV OUT[1], IN[0][1]\n" + "MOV OUT[2].x, IN[0][2].xxxx\n" + "EMIT IMM[0].xxxx\n" + "MOV OUT[0], IN[1][0]\n" + "MOV OUT[1], IN[1][1]\n" + "MOV OUT[2].x, IN[1][2].xxxx\n" + "EMIT IMM[0].xxxx\n" + "MOV OUT[0], IN[2][0]\n" + "MOV OUT[1], IN[2][1]\n" + "MOV OUT[2].x, IN[2][2].xxxx\n" + "EMIT IMM[0].xxxx\n" + "END\n"; + struct tgsi_token tokens[1000]; + struct pipe_shader_state state = {tokens}; + + if (!tgsi_text_translate(text, tokens, Elements(tokens))) { + assert(0); + return NULL; + } + return pipe->create_gs_state(pipe, &state); +} /** * Make simple fragment texture shader: diff --git a/mesalib/src/gallium/auxiliary/util/u_simple_shaders.h b/mesalib/src/gallium/auxiliary/util/u_simple_shaders.h index c1d14aa3b..dd282e02a 100644 --- a/mesalib/src/gallium/auxiliary/util/u_simple_shaders.h +++ b/mesalib/src/gallium/auxiliary/util/u_simple_shaders.h @@ -47,19 +47,27 @@ extern void * util_make_vertex_passthrough_shader(struct pipe_context *pipe, uint num_attribs, const uint *semantic_names, - const uint *semantic_indexes); + const uint *semantic_indexes, + bool window_space); extern void * util_make_vertex_passthrough_shader_with_so(struct pipe_context *pipe, uint num_attribs, const uint *semantic_names, const uint *semantic_indexes, + bool window_space, const struct pipe_stream_output_info *so); extern void * util_make_layered_clear_vertex_shader(struct pipe_context *pipe); extern void * +util_make_layered_clear_helper_vertex_shader(struct pipe_context *pipe); + +extern void * +util_make_layered_clear_geometry_shader(struct pipe_context *pipe); + +extern void * util_make_fragment_tex_shader_writemask(struct pipe_context *pipe, unsigned tex_target, unsigned interp_mode, diff --git a/mesalib/src/gallium/auxiliary/util/u_snprintf.c b/mesalib/src/gallium/auxiliary/util/u_snprintf.c index 7a2bf2a6f..39e9b70d0 100644 --- a/mesalib/src/gallium/auxiliary/util/u_snprintf.c +++ b/mesalib/src/gallium/auxiliary/util/u_snprintf.c @@ -176,7 +176,7 @@ #define HAVE_ASPRINTF 1 /* not needed */ #define HAVE_STDARG_H 1 #define HAVE_STDDEF_H 1 -#define HAVE_STDINT_H 0 +#define HAVE_STDINT_H 1 #define HAVE_STDLIB_H 1 #define HAVE_INTTYPES_H 0 #define HAVE_LOCALE_H 0 diff --git a/mesalib/src/gallium/auxiliary/util/u_tests.c b/mesalib/src/gallium/auxiliary/util/u_tests.c new file mode 100644 index 000000000..c0f6327b6 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_tests.c @@ -0,0 +1,268 @@ +/************************************************************************** + * + * Copyright 2014 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "util/u_tests.h" + +#include "util/u_draw_quad.h" +#include "util/u_format.h" +#include "util/u_inlines.h" +#include "util/u_simple_shaders.h" +#include "util/u_surface.h" +#include "util/u_tile.h" +#include "cso_cache/cso_context.h" +#include <stdio.h> + +#define TOLERANCE 0.01 + +static struct pipe_resource * +util_create_texture2d(struct pipe_screen *screen, unsigned width, + unsigned height, enum pipe_format format) +{ + struct pipe_resource templ = {{0}}; + + templ.target = PIPE_TEXTURE_2D; + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; + templ.array_size = 1; + templ.format = format; + templ.usage = PIPE_USAGE_DEFAULT; + templ.bind = PIPE_BIND_SAMPLER_VIEW | + (util_format_is_depth_or_stencil(format) ? + PIPE_BIND_DEPTH_STENCIL : PIPE_BIND_RENDER_TARGET); + + return screen->resource_create(screen, &templ); +} + +static void +util_set_framebuffer_cb0(struct cso_context *cso, struct pipe_context *ctx, + struct pipe_resource *tex) +{ + struct pipe_surface templ = {{0}}, *surf; + struct pipe_framebuffer_state fb = {0}; + + templ.format = tex->format; + surf = ctx->create_surface(ctx, tex, &templ); + + fb.width = tex->width0; + fb.height = tex->height0; + fb.cbufs[0] = surf; + fb.nr_cbufs = 1; + + cso_set_framebuffer(cso, &fb); + pipe_surface_reference(&surf, NULL); +} + +static void +util_set_blend_normal(struct cso_context *cso) +{ + struct pipe_blend_state blend = {0}; + + blend.rt[0].colormask = PIPE_MASK_RGBA; + cso_set_blend(cso, &blend); +} + +static void +util_set_dsa_disable(struct cso_context *cso) +{ + struct pipe_depth_stencil_alpha_state dsa = {{0}}; + + cso_set_depth_stencil_alpha(cso, &dsa); +} + +static void +util_set_rasterizer_normal(struct cso_context *cso) +{ + struct pipe_rasterizer_state rs = {0}; + + rs.half_pixel_center = 1; + rs.bottom_edge_rule = 1; + rs.depth_clip = 1; + + cso_set_rasterizer(cso, &rs); +} + +static void +util_set_max_viewport(struct cso_context *cso, struct pipe_resource *tex) +{ + struct pipe_viewport_state viewport; + + viewport.scale[0] = 0.5f * tex->width0; + viewport.scale[1] = 0.5f * tex->height0; + viewport.scale[2] = 1.0f; + viewport.translate[0] = 0.5f * tex->width0; + viewport.translate[1] = 0.5f * tex->height0; + viewport.translate[2] = 0.0f; + + cso_set_viewport(cso, &viewport); +} + +static void +util_set_interleaved_vertex_elements(struct cso_context *cso, + unsigned num_elements) +{ + int i; + struct pipe_vertex_element *velem = + calloc(1, num_elements * sizeof(struct pipe_vertex_element)); + + for (i = 0; i < num_elements; i++) { + velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + velem[i].src_offset = i * 16; + } + + cso_set_vertex_elements(cso, num_elements, velem); + free(velem); +} + +static bool +util_probe_rect_rgba(struct pipe_context *ctx, struct pipe_resource *tex, + unsigned offx, unsigned offy, unsigned w, unsigned h, + const float *expected) +{ + struct pipe_transfer *transfer; + void *map; + float *pixels = malloc(w * h * 4 * sizeof(float)); + int x,y,c; + bool pass = true; + + map = pipe_transfer_map(ctx, tex, 0, 0, PIPE_TRANSFER_READ, + offx, offy, w, h, &transfer); + pipe_get_tile_rgba(transfer, map, 0, 0, w, h, pixels); + pipe_transfer_unmap(ctx, transfer); + + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + float *probe = &pixels[(y*w + x)*4]; + + for (c = 0; c < 4; c++) + if (fabs(probe[c] - expected[c]) >= TOLERANCE) { + printf("Probe color at (%i,%i), ", offx+x, offy+y); + printf("Expected: %.3f, %.3f, %.3f, %.3f, ", + expected[0], expected[1], expected[2], expected[3]); + printf("Got: %.3f, %.3f, %.3f, %.3f\n", + probe[0], probe[1], probe[2], probe[2]); + pass = false; + goto done; + } + } + } +done: + + free(pixels); + return pass; +} + +/** + * Test TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION. + * + * The viewport state is set as usual, but it should have no effect. + * Clipping should also be disabled. + * + * POSITION.xyz should already be multiplied by 1/w and POSITION.w should + * contain 1/w. By setting w=0, we can test that POSITION.xyz isn't + * multiplied by 1/w (otherwise nothing would be rendered). + * + * TODO: Whether the value of POSITION.w is correctly interpreted as 1/w + * during perspective interpolation is not tested. + */ +static void +tgsi_vs_window_space_position(struct pipe_context *ctx) +{ + struct cso_context *cso; + struct pipe_resource *cb; + void *fs, *vs; + bool pass = true; + + static uint vs_attribs[] = { + TGSI_SEMANTIC_POSITION, + TGSI_SEMANTIC_GENERIC + }; + static uint vs_indices[] = {0, 0}; + static float vertices[] = { + 0, 0, 0, 0, 1, 0, 0, 1, + 0, 256, 0, 0, 1, 0, 0, 1, + 256, 256, 0, 0, 1, 0, 0, 1, + 256, 0, 0, 0, 1, 0, 0, 1, + }; + static float red[] = {1, 0, 0, 1}; + static float clear_color[] = {0.1, 0.1, 0.1, 0.1}; + + if (!ctx->screen->get_param(ctx->screen, + PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION)) { + printf("Test(%s) = skip\n", __func__); + return; + } + + cso = cso_create_context(ctx); + cb = util_create_texture2d(ctx->screen, 256, 256, + PIPE_FORMAT_R8G8B8A8_UNORM); + + /* Set states. */ + util_set_framebuffer_cb0(cso, ctx, cb); + util_set_blend_normal(cso); + util_set_dsa_disable(cso); + util_set_rasterizer_normal(cso); + util_set_max_viewport(cso, cb); + util_set_interleaved_vertex_elements(cso, 2); + + /* Fragment shader. */ + fs = util_make_fragment_passthrough_shader(ctx, TGSI_SEMANTIC_GENERIC, + TGSI_INTERPOLATE_LINEAR, TRUE); + cso_set_fragment_shader_handle(cso, fs); + + /* Vertex shader. */ + vs = util_make_vertex_passthrough_shader(ctx, 2, vs_attribs, vs_indices, + TRUE); + cso_set_vertex_shader_handle(cso, vs); + + /* Clear and draw. */ + ctx->clear(ctx, PIPE_CLEAR_COLOR0, (void*)clear_color, 0, 0); + util_draw_user_vertex_buffer(cso, vertices, PIPE_PRIM_QUADS, 4, 2); + + /* Probe pixels. */ + pass = pass && util_probe_rect_rgba(ctx, cb, 0, 0, + cb->width0, cb->height0, red); + + /* Cleanup. */ + cso_release_all(cso); + cso_destroy_context(cso); + ctx->delete_vs_state(ctx, vs); + ctx->delete_fs_state(ctx, fs); + pipe_resource_reference(&cb, NULL); + + printf("Test(%s) = %s\n", __func__, pass ? "pass" : "fail"); +} + +/** + * Run all tests. This should be run with a clean context after + * context_create. + */ +void +util_run_tests(struct pipe_context *ctx) +{ + tgsi_vs_window_space_position(ctx); +} diff --git a/mesalib/src/gallium/auxiliary/util/u_tests.h b/mesalib/src/gallium/auxiliary/util/u_tests.h new file mode 100644 index 000000000..a1439347d --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_tests.h @@ -0,0 +1,37 @@ +/************************************************************************** + * + * Copyright 2014 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef U_TESTS_H +#define U_TESTS_H + +#include "pipe/p_compiler.h" + +struct pipe_context; + +void util_run_tests(struct pipe_context *ctx); + +#endif |