aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/gallium/auxiliary/util
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/gallium/auxiliary/util')
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_atomic.h56
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_blit.c4
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_blitter.c7
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_box.h118
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_format_pack.py35
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_pstipple.c228
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_pstipple.h5
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_rect.h18
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_simple_shaders.c80
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_simple_shaders.h10
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_snprintf.c2
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_tests.c268
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_tests.h37
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