summaryrefslogtreecommitdiff
path: root/src/gallium
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_arit.c56
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_arit.h12
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_logic.c5
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_sample.c9
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_sample.h1
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c634
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c1
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_type.c20
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_type.h4
-rw-r--r--src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c4
-rw-r--r--src/gallium/drivers/r300/r300_render.c7
-rw-r--r--src/gallium/drivers/softpipe/sp_tex_sample.c14
-rw-r--r--src/gallium/state_trackers/egl/common/egl_g3d.c37
-rw-r--r--src/gallium/state_trackers/egl/common/egl_g3d.h14
-rw-r--r--src/gallium/state_trackers/egl/common/egl_g3d_image.c136
-rw-r--r--src/gallium/state_trackers/egl/common/egl_g3d_image.h41
-rw-r--r--src/gallium/state_trackers/egl/common/native.h88
-rw-r--r--src/gallium/state_trackers/egl/common/native_modeset.h87
-rw-r--r--src/gallium/state_trackers/egl/kms/native_kms.c29
-rw-r--r--src/gallium/state_trackers/egl/kms/native_kms.h2
-rw-r--r--src/gallium/state_trackers/egl/x11/native_dri2.c40
-rw-r--r--src/gallium/state_trackers/egl/x11/native_x11.c7
-rw-r--r--src/gallium/state_trackers/egl/x11/native_x11.h8
-rw-r--r--src/gallium/state_trackers/egl/x11/native_ximage.c40
24 files changed, 1150 insertions, 146 deletions
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_arit.c b/src/gallium/auxiliary/gallivm/lp_bld_arit.c
index bbce31f9eb..32f9e5201c 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_arit.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_arit.c
@@ -669,6 +669,14 @@ lp_build_abs(struct lp_build_context *bld,
LLVMValueRef
+lp_build_negate(struct lp_build_context *bld,
+ LLVMValueRef a)
+{
+ return LLVMBuildNeg(bld->builder, a, "");
+}
+
+
+LLVMValueRef
lp_build_sgn(struct lp_build_context *bld,
LLVMValueRef a)
{
@@ -710,6 +718,41 @@ lp_build_sgn(struct lp_build_context *bld,
/**
+ * Set the sign of float vector 'a' according to 'sign'.
+ * If sign==0, return abs(a).
+ * If sign==1, return -abs(a);
+ * Other values for sign produce undefined results.
+ */
+LLVMValueRef
+lp_build_set_sign(struct lp_build_context *bld,
+ LLVMValueRef a, LLVMValueRef sign)
+{
+ const struct lp_type type = bld->type;
+ LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);
+ LLVMTypeRef vec_type = lp_build_vec_type(type);
+ LLVMValueRef shift = lp_build_int_const_scalar(type, type.width - 1);
+ LLVMValueRef mask = lp_build_int_const_scalar(type,
+ ~((unsigned long long) 1 << (type.width - 1)));
+ LLVMValueRef val, res;
+
+ assert(type.floating);
+
+ /* val = reinterpret_cast<int>(a) */
+ val = LLVMBuildBitCast(bld->builder, a, int_vec_type, "");
+ /* val = val & mask */
+ val = LLVMBuildAnd(bld->builder, val, mask, "");
+ /* sign = sign << shift */
+ sign = LLVMBuildShl(bld->builder, sign, shift, "");
+ /* res = val | sign */
+ res = LLVMBuildOr(bld->builder, val, sign, "");
+ /* res = reinterpret_cast<float>(res) */
+ res = LLVMBuildBitCast(bld->builder, res, vec_type, "");
+
+ return res;
+}
+
+
+/**
* Convert vector of int to vector of float.
*/
LLVMValueRef
@@ -857,6 +900,19 @@ lp_build_ceil(struct lp_build_context *bld,
/**
+ * Return fractional part of 'a' computed as a - floor(f)
+ * Typically used in texture coord arithmetic.
+ */
+LLVMValueRef
+lp_build_fract(struct lp_build_context *bld,
+ LLVMValueRef a)
+{
+ assert(bld->type.floating);
+ return lp_build_sub(bld, a, lp_build_floor(bld, a));
+}
+
+
+/**
* Convert to integer, through whichever rounding method that's fastest,
* typically truncating toward zero.
*/
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_arit.h b/src/gallium/auxiliary/gallivm/lp_bld_arit.h
index da84b7ca02..55385e3a66 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_arit.h
+++ b/src/gallium/auxiliary/gallivm/lp_bld_arit.h
@@ -117,10 +117,18 @@ lp_build_abs(struct lp_build_context *bld,
LLVMValueRef a);
LLVMValueRef
+lp_build_negate(struct lp_build_context *bld,
+ LLVMValueRef a);
+
+LLVMValueRef
lp_build_sgn(struct lp_build_context *bld,
LLVMValueRef a);
LLVMValueRef
+lp_build_set_sign(struct lp_build_context *bld,
+ LLVMValueRef a, LLVMValueRef sign);
+
+LLVMValueRef
lp_build_int_to_float(struct lp_build_context *bld,
LLVMValueRef a);
@@ -141,6 +149,10 @@ lp_build_trunc(struct lp_build_context *bld,
LLVMValueRef a);
LLVMValueRef
+lp_build_fract(struct lp_build_context *bld,
+ LLVMValueRef a);
+
+LLVMValueRef
lp_build_ifloor(struct lp_build_context *bld,
LLVMValueRef a);
LLVMValueRef
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_logic.c b/src/gallium/auxiliary/gallivm/lp_bld_logic.c
index 41ac81b744..2726747eae 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_logic.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_logic.c
@@ -45,6 +45,7 @@
/**
* Build code to compare two values 'a' and 'b' of 'type' using the given func.
* \param func one of PIPE_FUNC_x
+ * The result values will be 0 for false or ~0 for true.
*/
LLVMValueRef
lp_build_compare(LLVMBuilderRef builder,
@@ -311,6 +312,7 @@ lp_build_compare(LLVMBuilderRef builder,
/**
* Build code to compare two values 'a' and 'b' using the given func.
* \param func one of PIPE_FUNC_x
+ * The result values will be 0 for false or ~0 for true.
*/
LLVMValueRef
lp_build_cmp(struct lp_build_context *bld,
@@ -322,6 +324,9 @@ lp_build_cmp(struct lp_build_context *bld,
}
+/**
+ * Return mask ? a : b;
+ */
LLVMValueRef
lp_build_select(struct lp_build_context *bld,
LLVMValueRef mask,
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.c b/src/gallium/auxiliary/gallivm/lp_bld_sample.c
index a133b56ac5..55ac2e9436 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_sample.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.c
@@ -44,6 +44,11 @@
#include "lp_bld_sample.h"
+/**
+ * Initialize lp_sampler_static_state object with the gallium sampler
+ * and texture state.
+ * The former is considered to be static and the later dynamic.
+ */
void
lp_sampler_static_state(struct lp_sampler_static_state *state,
const struct pipe_texture *texture,
@@ -70,6 +75,10 @@ lp_sampler_static_state(struct lp_sampler_static_state *state,
state->min_mip_filter = sampler->min_mip_filter;
state->mag_img_filter = sampler->mag_img_filter;
state->compare_mode = sampler->compare_mode;
+ state->border_color[0] = sampler->border_color[0];
+ state->border_color[1] = sampler->border_color[1];
+ state->border_color[2] = sampler->border_color[2];
+ state->border_color[3] = sampler->border_color[3];
if(sampler->compare_mode != PIPE_TEX_COMPARE_NONE) {
state->compare_func = sampler->compare_func;
}
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.h b/src/gallium/auxiliary/gallivm/lp_bld_sample.h
index 39edcf13d1..a791d88612 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_sample.h
+++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.h
@@ -70,6 +70,7 @@ struct lp_sampler_static_state
unsigned compare_mode:1;
unsigned compare_func:3;
unsigned normalized_coords:1;
+ float border_color[4];
};
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
index e268862282..fe41d5ee49 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
@@ -69,7 +69,11 @@ struct lp_build_sample_context
struct lp_type coord_type;
struct lp_build_context coord_bld;
- /** Integer coordinates */
+ /** Unsigned integer coordinates */
+ struct lp_type uint_coord_type;
+ struct lp_build_context uint_coord_bld;
+
+ /** Signed integer coordinates */
struct lp_type int_coord_type;
struct lp_build_context int_coord_bld;
@@ -79,18 +83,93 @@ struct lp_build_sample_context
};
+/**
+ * Does the given texture wrap mode allow sampling the texture border color?
+ * XXX maybe move this into gallium util code.
+ */
+static boolean
+wrap_mode_uses_border_color(unsigned mode)
+{
+ switch (mode) {
+ case PIPE_TEX_WRAP_REPEAT:
+ case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+ case PIPE_TEX_WRAP_MIRROR_REPEAT:
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
+ return FALSE;
+ case PIPE_TEX_WRAP_CLAMP:
+ case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+ case PIPE_TEX_WRAP_MIRROR_CLAMP:
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
+ return TRUE;
+ default:
+ assert(0 && "unexpected wrap mode");
+ return FALSE;
+ }
+}
+
+
+
+/**
+ * Gen code to fetch a texel from a texture at int coords (x, y).
+ * The result, texel, will be:
+ * texel[0] = red values
+ * texel[1] = green values
+ * texel[2] = blue values
+ * texel[3] = alpha values
+ */
static void
lp_build_sample_texel_soa(struct lp_build_sample_context *bld,
+ LLVMValueRef width,
+ LLVMValueRef height,
LLVMValueRef x,
LLVMValueRef y,
LLVMValueRef y_stride,
LLVMValueRef data_ptr,
LLVMValueRef *texel)
{
+ struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
LLVMValueRef offset;
LLVMValueRef packed;
+ LLVMValueRef use_border = NULL;
+
+ /* use_border = x < 0 || x >= width || y < 0 || y >= height */
+ if (wrap_mode_uses_border_color(bld->static_state->wrap_s)) {
+ LLVMValueRef b1, b2;
+ b1 = lp_build_cmp(int_coord_bld, PIPE_FUNC_LESS, x, int_coord_bld->zero);
+ b2 = lp_build_cmp(int_coord_bld, PIPE_FUNC_GEQUAL, x, width);
+ use_border = LLVMBuildOr(bld->builder, b1, b2, "b1_or_b2");
+ }
- offset = lp_build_sample_offset(&bld->int_coord_bld,
+ if (wrap_mode_uses_border_color(bld->static_state->wrap_t)) {
+ LLVMValueRef b1, b2;
+ b1 = lp_build_cmp(int_coord_bld, PIPE_FUNC_LESS, y, int_coord_bld->zero);
+ b2 = lp_build_cmp(int_coord_bld, PIPE_FUNC_GEQUAL, y, height);
+ if (use_border) {
+ use_border = LLVMBuildOr(bld->builder, use_border, b1, "ub_or_b1");
+ use_border = LLVMBuildOr(bld->builder, use_border, b2, "ub_or_b2");
+ }
+ else {
+ use_border = LLVMBuildOr(bld->builder, b1, b2, "b1_or_b2");
+ }
+ }
+
+ /*
+ * Note: if we find an app which frequently samples the texture border
+ * we might want to implement a true conditional here to avoid sampling
+ * the texture whenever possible (since that's quite a bit of code).
+ * Ex:
+ * if (use_border) {
+ * texel = border_color;
+ * }
+ * else {
+ * texel = sample_texture(coord);
+ * }
+ * As it is now, we always sample the texture, then selectively replace
+ * the texel color results with the border color.
+ */
+
+ /* convert x,y coords to linear offset from start of texture, in bytes */
+ offset = lp_build_sample_offset(&bld->uint_coord_bld,
bld->format_desc,
x, y, y_stride,
data_ptr);
@@ -99,16 +178,30 @@ lp_build_sample_texel_soa(struct lp_build_sample_context *bld,
assert(bld->format_desc->block.height == 1);
assert(bld->format_desc->block.bits <= bld->texel_type.width);
+ /* gather the texels from the texture */
packed = lp_build_gather(bld->builder,
bld->texel_type.length,
bld->format_desc->block.bits,
bld->texel_type.width,
data_ptr, offset);
+ /* convert texels to float rgba */
lp_build_unpack_rgba_soa(bld->builder,
bld->format_desc,
bld->texel_type,
packed, texel);
+
+ if (use_border) {
+ /* select texel color or border color depending on use_border */
+ int chan;
+ for (chan = 0; chan < 4; chan++) {
+ LLVMValueRef border_chan =
+ lp_build_const_scalar(bld->texel_type,
+ bld->static_state->border_color[chan]);
+ texel[chan] = lp_build_select(&bld->texel_bld, use_border,
+ border_chan, texel[chan]);
+ }
+ }
}
@@ -121,7 +214,7 @@ lp_build_sample_packed(struct lp_build_sample_context *bld,
{
LLVMValueRef offset;
- offset = lp_build_sample_offset(&bld->int_coord_bld,
+ offset = lp_build_sample_offset(&bld->uint_coord_bld,
bld->format_desc,
x, y, y_stride,
data_ptr);
@@ -138,17 +231,77 @@ lp_build_sample_packed(struct lp_build_sample_context *bld,
}
+/**
+ * Helper to compute the mirror function for the PIPE_WRAP_MIRROR modes.
+ */
+static LLVMValueRef
+lp_build_coord_mirror(struct lp_build_sample_context *bld,
+ LLVMValueRef coord)
+{
+ struct lp_build_context *coord_bld = &bld->coord_bld;
+ struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
+ LLVMValueRef fract, flr, isOdd;
+
+ /* fract = coord - floor(coord) */
+ fract = lp_build_sub(coord_bld, coord, lp_build_floor(coord_bld, coord));
+
+ /* flr = ifloor(coord); */
+ flr = lp_build_ifloor(coord_bld, coord);
+
+ /* isOdd = flr & 1 */
+ isOdd = LLVMBuildAnd(bld->builder, flr, int_coord_bld->one, "");
+
+ /* make coord positive or negative depending on isOdd */
+ coord = lp_build_set_sign(coord_bld, fract, isOdd);
+
+ /* convert isOdd to float */
+ isOdd = lp_build_int_to_float(coord_bld, isOdd);
+
+ /* add isOdd to coord */
+ coord = lp_build_add(coord_bld, coord, isOdd);
+
+ return coord;
+}
+
+
+/**
+ * We only support a few wrap modes in lp_build_sample_wrap_int() at this time.
+ * Return whether the given mode is supported by that function.
+ */
+static boolean
+is_simple_wrap_mode(unsigned mode)
+{
+ switch (mode) {
+ case PIPE_TEX_WRAP_REPEAT:
+ case PIPE_TEX_WRAP_CLAMP:
+ case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+ return TRUE;
+ case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+ default:
+ return FALSE;
+ }
+}
+
+
+/**
+ * Build LLVM code for texture wrap mode, for scaled integer texcoords.
+ * \param coord the incoming texcoord (s,t,r or q) scaled to the texture size
+ * \param length the texture size along one dimension
+ * \param is_pot if TRUE, length is a power of two
+ * \param wrap_mode one of PIPE_TEX_WRAP_x
+ */
static LLVMValueRef
-lp_build_sample_wrap(struct lp_build_sample_context *bld,
- LLVMValueRef coord,
- LLVMValueRef length,
- boolean is_pot,
- unsigned wrap_mode)
+lp_build_sample_wrap_int(struct lp_build_sample_context *bld,
+ LLVMValueRef coord,
+ LLVMValueRef length,
+ boolean is_pot,
+ unsigned wrap_mode)
{
+ struct lp_build_context *uint_coord_bld = &bld->uint_coord_bld;
struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
LLVMValueRef length_minus_one;
- length_minus_one = lp_build_sub(int_coord_bld, length, int_coord_bld->one);
+ length_minus_one = lp_build_sub(uint_coord_bld, length, uint_coord_bld->one);
switch(wrap_mode) {
case PIPE_TEX_WRAP_REPEAT:
@@ -161,12 +314,12 @@ lp_build_sample_wrap(struct lp_build_sample_context *bld,
break;
case PIPE_TEX_WRAP_CLAMP:
+ case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+ case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
coord = lp_build_max(int_coord_bld, coord, int_coord_bld->zero);
coord = lp_build_min(int_coord_bld, coord, length_minus_one);
break;
- case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
- case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
case PIPE_TEX_WRAP_MIRROR_REPEAT:
case PIPE_TEX_WRAP_MIRROR_CLAMP:
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
@@ -174,8 +327,8 @@ lp_build_sample_wrap(struct lp_build_sample_context *bld,
/* FIXME */
_debug_printf("llvmpipe: failed to translate texture wrap mode %s\n",
util_dump_tex_wrap(wrap_mode, TRUE));
- coord = lp_build_max(int_coord_bld, coord, int_coord_bld->zero);
- coord = lp_build_min(int_coord_bld, coord, length_minus_one);
+ coord = lp_build_max(uint_coord_bld, coord, uint_coord_bld->zero);
+ coord = lp_build_min(uint_coord_bld, coord, length_minus_one);
break;
default:
@@ -186,6 +339,344 @@ lp_build_sample_wrap(struct lp_build_sample_context *bld,
}
+/**
+ * Build LLVM code for texture wrap mode for linear filtering.
+ * \param x0_out returns first integer texcoord
+ * \param x1_out returns second integer texcoord
+ * \param weight_out returns linear interpolation weight
+ */
+static void
+lp_build_sample_wrap_linear(struct lp_build_sample_context *bld,
+ LLVMValueRef coord,
+ LLVMValueRef length,
+ boolean is_pot,
+ unsigned wrap_mode,
+ LLVMValueRef *x0_out,
+ LLVMValueRef *x1_out,
+ LLVMValueRef *weight_out)
+{
+ struct lp_build_context *coord_bld = &bld->coord_bld;
+ struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
+ struct lp_build_context *uint_coord_bld = &bld->uint_coord_bld;
+ LLVMValueRef two = lp_build_const_scalar(coord_bld->type, 2.0);
+ LLVMValueRef half = lp_build_const_scalar(coord_bld->type, 0.5);
+ LLVMValueRef length_f = lp_build_int_to_float(coord_bld, length);
+ LLVMValueRef length_minus_one;
+ LLVMValueRef length_f_minus_one;
+ LLVMValueRef coord0, coord1, weight;
+
+ /* XXX check for normalized vs. unnormalized coords */
+
+ length_minus_one = lp_build_sub(uint_coord_bld, length, uint_coord_bld->one);
+ length_f_minus_one = lp_build_sub(coord_bld, length_f, coord_bld->one);
+
+ switch(wrap_mode) {
+ case PIPE_TEX_WRAP_REPEAT:
+ /* mul by size and subtract 0.5 */
+ coord = lp_build_mul(coord_bld, coord, length_f);
+ coord = lp_build_sub(coord_bld, coord, half);
+ /* convert to int */
+ coord0 = lp_build_ifloor(coord_bld, coord);
+ coord1 = lp_build_add(uint_coord_bld, coord0, uint_coord_bld->one);
+ /* compute lerp weight */
+ weight = lp_build_fract(coord_bld, coord);
+ /* repeat wrap */
+ if (is_pot) {
+ coord0 = LLVMBuildAnd(bld->builder, coord0, length_minus_one, "");
+ coord1 = LLVMBuildAnd(bld->builder, coord1, length_minus_one, "");
+ }
+ else {
+ /* Signed remainder won't give the right results for negative
+ * dividends but unsigned remainder does.*/
+ coord0 = LLVMBuildURem(bld->builder, coord0, length, "");
+ coord1 = LLVMBuildURem(bld->builder, coord1, length, "");
+ }
+ break;
+
+ case PIPE_TEX_WRAP_CLAMP:
+ coord = lp_build_mul(coord_bld, coord, length_f);
+ weight = lp_build_fract(coord_bld, coord);
+ coord0 = lp_build_clamp(coord_bld, coord, coord_bld->zero,
+ length_f_minus_one);
+ coord1 = lp_build_add(coord_bld, coord, coord_bld->one);
+ coord1 = lp_build_clamp(coord_bld, coord1, coord_bld->zero,
+ length_f_minus_one);
+ coord0 = lp_build_ifloor(coord_bld, coord0);
+ coord1 = lp_build_ifloor(coord_bld, coord1);
+ break;
+
+ case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+ /* clamp to [0,1] */
+ coord = lp_build_clamp(coord_bld, coord, coord_bld->zero, coord_bld->one);
+ /* mul by tex size and subtract 0.5 */
+ coord = lp_build_mul(coord_bld, coord, length_f);
+ coord = lp_build_sub(coord_bld, coord, half);
+ /* compute lerp weight */
+ weight = lp_build_fract(coord_bld, coord);
+ /* coord0 = floor(coord); */
+ coord0 = lp_build_ifloor(coord_bld, coord);
+ coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one);
+ /* coord0 = max(coord0, 0) */
+ coord0 = lp_build_max(int_coord_bld, coord0, int_coord_bld->zero);
+ /* coord1 = min(coord1, length-1) */
+ coord1 = lp_build_min(int_coord_bld, coord1, length_minus_one);
+ break;
+
+ case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+ {
+ LLVMValueRef min, max;
+ /* min = -1.0 / (2 * length) */
+ min = lp_build_rcp(coord_bld, lp_build_mul(coord_bld, two, length_f));
+ min = lp_build_negate(coord_bld, min);
+ /* max = 1.0 - min */
+ max = lp_build_sub(coord_bld, coord_bld->one, min);
+ /* coord = clamp(coord, min, max) */
+ coord = lp_build_clamp(coord_bld, coord, min, max);
+ /* scale coord to length (and sub 0.5?) */
+ coord = lp_build_mul(coord_bld, coord, length_f);
+ coord = lp_build_sub(coord_bld, coord, half);
+ /* compute lerp weight */
+ weight = lp_build_fract(coord_bld, coord);
+ /* convert to int */
+ coord0 = lp_build_ifloor(coord_bld, coord);
+ coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one);
+ }
+ break;
+
+ case PIPE_TEX_WRAP_MIRROR_REPEAT:
+ /* compute mirror function */
+ coord = lp_build_coord_mirror(bld, coord);
+
+ /* scale coord to length */
+ coord = lp_build_mul(coord_bld, coord, length_f);
+ coord = lp_build_sub(coord_bld, coord, half);
+
+ /* compute lerp weight */
+ weight = lp_build_fract(coord_bld, coord);
+
+ /* convert to int coords */
+ coord0 = lp_build_ifloor(coord_bld, coord);
+ coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one);
+
+ /* coord0 = max(coord0, 0) */
+ coord0 = lp_build_max(int_coord_bld, coord0, int_coord_bld->zero);
+ /* coord1 = min(coord1, length-1) */
+ coord1 = lp_build_min(int_coord_bld, coord1, length_minus_one);
+ break;
+
+ case PIPE_TEX_WRAP_MIRROR_CLAMP:
+ {
+ LLVMValueRef min, max;
+ /* min = 1.0 / (2 * length) */
+ min = lp_build_rcp(coord_bld, lp_build_mul(coord_bld, two, length_f));
+ /* max = 1.0 - min */
+ max = lp_build_sub(coord_bld, coord_bld->one, min);
+
+ coord = lp_build_abs(coord_bld, coord);
+ coord = lp_build_clamp(coord_bld, coord, min, max);
+ coord = lp_build_mul(coord_bld, coord, length_f);
+ if(0)coord = lp_build_sub(coord_bld, coord, half);
+ weight = lp_build_fract(coord_bld, coord);
+ coord0 = lp_build_ifloor(coord_bld, coord);
+ coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one);
+ }
+ break;
+
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
+ {
+ LLVMValueRef min, max;
+ /* min = 1.0 / (2 * length) */
+ min = lp_build_rcp(coord_bld, lp_build_mul(coord_bld, two, length_f));
+ /* max = 1.0 - min */
+ max = lp_build_sub(coord_bld, coord_bld->one, min);
+
+ coord = lp_build_abs(coord_bld, coord);
+ coord = lp_build_clamp(coord_bld, coord, min, max);
+ coord = lp_build_mul(coord_bld, coord, length_f);
+ coord = lp_build_sub(coord_bld, coord, half);
+ weight = lp_build_fract(coord_bld, coord);
+ coord0 = lp_build_ifloor(coord_bld, coord);
+ coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one);
+ }
+ break;
+
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
+ {
+ LLVMValueRef min, max;
+ /* min = -1.0 / (2 * length) */
+ min = lp_build_rcp(coord_bld, lp_build_mul(coord_bld, two, length_f));
+ min = lp_build_negate(coord_bld, min);
+ /* max = 1.0 - min */
+ max = lp_build_sub(coord_bld, coord_bld->one, min);
+
+ coord = lp_build_abs(coord_bld, coord);
+ coord = lp_build_clamp(coord_bld, coord, min, max);
+ coord = lp_build_mul(coord_bld, coord, length_f);
+ coord = lp_build_sub(coord_bld, coord, half);
+ weight = lp_build_fract(coord_bld, coord);
+ coord0 = lp_build_ifloor(coord_bld, coord);
+ coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one);
+ }
+ break;
+
+ default:
+ assert(0);
+ }
+
+ *x0_out = coord0;
+ *x1_out = coord1;
+ *weight_out = weight;
+}
+
+
+/**
+ * Build LLVM code for texture wrap mode for nearest filtering.
+ * \param coord the incoming texcoord (nominally in [0,1])
+ * \param length the texture size along one dimension, as int
+ * \param is_pot if TRUE, length is a power of two
+ * \param wrap_mode one of PIPE_TEX_WRAP_x
+ */
+static LLVMValueRef
+lp_build_sample_wrap_nearest(struct lp_build_sample_context *bld,
+ LLVMValueRef coord,
+ LLVMValueRef length,
+ boolean is_pot,
+ unsigned wrap_mode)
+{
+ struct lp_build_context *coord_bld = &bld->coord_bld;
+ struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
+ struct lp_build_context *uint_coord_bld = &bld->uint_coord_bld;
+ LLVMValueRef two = lp_build_const_scalar(coord_bld->type, 2.0);
+ LLVMValueRef length_f = lp_build_int_to_float(coord_bld, length);
+ LLVMValueRef length_minus_one = lp_build_sub(uint_coord_bld, length, uint_coord_bld->one);
+ LLVMValueRef length_f_minus_one = lp_build_sub(coord_bld, length_f, coord_bld->one);
+ LLVMValueRef icoord;
+
+ /* XXX check for normalized vs. unnormalized coords */
+
+ switch(wrap_mode) {
+ case PIPE_TEX_WRAP_REPEAT:
+ coord = lp_build_mul(coord_bld, coord, length_f);
+ icoord = lp_build_ifloor(coord_bld, coord);
+ if (is_pot)
+ icoord = LLVMBuildAnd(bld->builder, icoord, length_minus_one, "");
+ else
+ /* Signed remainder won't give the right results for negative
+ * dividends but unsigned remainder does.*/
+ icoord = LLVMBuildURem(bld->builder, icoord, length, "");
+ break;
+
+ case PIPE_TEX_WRAP_CLAMP:
+ /* mul by size */
+ coord = lp_build_mul(coord_bld, coord, length_f);
+ /* floor */
+ icoord = lp_build_ifloor(coord_bld, coord);
+ /* clamp to [0, size-1]. Note: int coord builder type */
+ icoord = lp_build_clamp(int_coord_bld, icoord, int_coord_bld->zero,
+ length_minus_one);
+ break;
+
+ case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+ {
+ LLVMValueRef min, max;
+ /* min = 1.0 / (2 * length) */
+ min = lp_build_rcp(coord_bld, lp_build_mul(coord_bld, two, length_f));
+ /* max = length - min */
+ max = lp_build_sub(coord_bld, length_f, min);
+ /* scale coord to length */
+ coord = lp_build_mul(coord_bld, coord, length_f);
+ /* coord = clamp(coord, min, max) */
+ coord = lp_build_clamp(coord_bld, coord, min, max);
+ icoord = lp_build_ifloor(coord_bld, coord);
+ }
+ break;
+
+ case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+ /* Note: this is the same as CLAMP_TO_EDGE, except min = -min */
+ {
+ LLVMValueRef min, max;
+ /* min = -1.0 / (2 * length) */
+ min = lp_build_rcp(coord_bld, lp_build_mul(coord_bld, two, length_f));
+ min = lp_build_negate(coord_bld, min);
+ /* max = length - min */
+ max = lp_build_sub(coord_bld, length_f, min);
+ /* scale coord to length */
+ coord = lp_build_mul(coord_bld, coord, length_f);
+ /* coord = clamp(coord, min, max) */
+ coord = lp_build_clamp(coord_bld, coord, min, max);
+ icoord = lp_build_ifloor(coord_bld, coord);
+ }
+ break;
+
+ case PIPE_TEX_WRAP_MIRROR_REPEAT:
+ {
+ LLVMValueRef min, max;
+ /* min = 1.0 / (2 * length) */
+ min = lp_build_rcp(coord_bld, lp_build_mul(coord_bld, two, length_f));
+ /* max = length - min */
+ max = lp_build_sub(coord_bld, length_f, min);
+
+ /* compute mirror function */
+ coord = lp_build_coord_mirror(bld, coord);
+
+ /* scale coord to length */
+ coord = lp_build_mul(coord_bld, coord, length_f);
+
+ /* coord = clamp(coord, min, max) */
+ coord = lp_build_clamp(coord_bld, coord, min, max);
+ icoord = lp_build_ifloor(coord_bld, coord);
+ }
+ break;
+
+ case PIPE_TEX_WRAP_MIRROR_CLAMP:
+ coord = lp_build_abs(coord_bld, coord);
+ coord = lp_build_mul(coord_bld, coord, length_f);
+ coord = lp_build_clamp(coord_bld, coord, coord_bld->zero, length_f_minus_one);
+ icoord = lp_build_ifloor(coord_bld, coord);
+ break;
+
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
+ {
+ LLVMValueRef min, max;
+ /* min = 1.0 / (2 * length) */
+ min = lp_build_rcp(coord_bld, lp_build_mul(coord_bld, two, length_f));
+ /* max = length - min */
+ max = lp_build_sub(coord_bld, length_f, min);
+
+ coord = lp_build_abs(coord_bld, coord);
+ coord = lp_build_mul(coord_bld, coord, length_f);
+ coord = lp_build_clamp(coord_bld, coord, min, max);
+ icoord = lp_build_ifloor(coord_bld, coord);
+ }
+ break;
+
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
+ {
+ LLVMValueRef min, max;
+ /* min = 1.0 / (2 * length) */
+ min = lp_build_rcp(coord_bld, lp_build_mul(coord_bld, two, length_f));
+ min = lp_build_negate(coord_bld, min);
+ /* max = length - min */
+ max = lp_build_sub(coord_bld, length_f, min);
+
+ coord = lp_build_abs(coord_bld, coord);
+ coord = lp_build_mul(coord_bld, coord, length_f);
+ coord = lp_build_clamp(coord_bld, coord, min, max);
+ icoord = lp_build_ifloor(coord_bld, coord);
+ }
+ break;
+
+ default:
+ assert(0);
+ }
+
+ return icoord;
+}
+
+
+/**
+ * Sample 2D texture with nearest filtering.
+ */
static void
lp_build_sample_2d_nearest_soa(struct lp_build_sample_context *bld,
LLVMValueRef s,
@@ -196,23 +687,25 @@ lp_build_sample_2d_nearest_soa(struct lp_build_sample_context *bld,
LLVMValueRef data_ptr,
LLVMValueRef *texel)
{
- LLVMValueRef x;
- LLVMValueRef y;
+ LLVMValueRef x, y;
- x = lp_build_ifloor(&bld->coord_bld, s);
- y = lp_build_ifloor(&bld->coord_bld, t);
- lp_build_name(x, "tex.x.floor");
- lp_build_name(y, "tex.y.floor");
+ x = lp_build_sample_wrap_nearest(bld, s, width,
+ bld->static_state->pot_width,
+ bld->static_state->wrap_s);
+ y = lp_build_sample_wrap_nearest(bld, t, height,
+ bld->static_state->pot_height,
+ bld->static_state->wrap_t);
- x = lp_build_sample_wrap(bld, x, width, bld->static_state->pot_width, bld->static_state->wrap_s);
- y = lp_build_sample_wrap(bld, y, height, bld->static_state->pot_height, bld->static_state->wrap_t);
lp_build_name(x, "tex.x.wrapped");
lp_build_name(y, "tex.y.wrapped");
- lp_build_sample_texel_soa(bld, x, y, stride, data_ptr, texel);
+ lp_build_sample_texel_soa(bld, width, height, x, y, stride, data_ptr, texel);
}
+/**
+ * Sample 2D texture with bilinear filtering.
+ */
static void
lp_build_sample_2d_linear_soa(struct lp_build_sample_context *bld,
LLVMValueRef s,
@@ -223,9 +716,6 @@ lp_build_sample_2d_linear_soa(struct lp_build_sample_context *bld,
LLVMValueRef data_ptr,
LLVMValueRef *texel)
{
- LLVMValueRef half;
- LLVMValueRef s_ipart;
- LLVMValueRef t_ipart;
LLVMValueRef s_fpart;
LLVMValueRef t_fpart;
LLVMValueRef x0, x1;
@@ -233,32 +723,15 @@ lp_build_sample_2d_linear_soa(struct lp_build_sample_context *bld,
LLVMValueRef neighbors[2][2][4];
unsigned chan;
- half = lp_build_const_scalar(bld->coord_type, 0.5);
- s = lp_build_sub(&bld->coord_bld, s, half);
- t = lp_build_sub(&bld->coord_bld, t, half);
-
- s_ipart = lp_build_floor(&bld->coord_bld, s);
- t_ipart = lp_build_floor(&bld->coord_bld, t);
-
- s_fpart = lp_build_sub(&bld->coord_bld, s, s_ipart);
- t_fpart = lp_build_sub(&bld->coord_bld, t, t_ipart);
+ lp_build_sample_wrap_linear(bld, s, width, bld->static_state->pot_width,
+ bld->static_state->wrap_s, &x0, &x1, &s_fpart);
+ lp_build_sample_wrap_linear(bld, t, height, bld->static_state->pot_height,
+ bld->static_state->wrap_t, &y0, &y1, &t_fpart);
- x0 = lp_build_itrunc(&bld->coord_bld, s_ipart);
- y0 = lp_build_itrunc(&bld->coord_bld, t_ipart);
-
- x0 = lp_build_sample_wrap(bld, x0, width, bld->static_state->pot_width, bld->static_state->wrap_s);
- y0 = lp_build_sample_wrap(bld, y0, height, bld->static_state->pot_height, bld->static_state->wrap_t);
-
- x1 = lp_build_add(&bld->int_coord_bld, x0, bld->int_coord_bld.one);
- y1 = lp_build_add(&bld->int_coord_bld, y0, bld->int_coord_bld.one);
-
- x1 = lp_build_sample_wrap(bld, x1, width, bld->static_state->pot_width, bld->static_state->wrap_s);
- y1 = lp_build_sample_wrap(bld, y1, height, bld->static_state->pot_height, bld->static_state->wrap_t);
-
- lp_build_sample_texel_soa(bld, x0, y0, stride, data_ptr, neighbors[0][0]);
- lp_build_sample_texel_soa(bld, x1, y0, stride, data_ptr, neighbors[0][1]);
- lp_build_sample_texel_soa(bld, x0, y1, stride, data_ptr, neighbors[1][0]);
- lp_build_sample_texel_soa(bld, x1, y1, stride, data_ptr, neighbors[1][1]);
+ lp_build_sample_texel_soa(bld, width, height, x0, y0, stride, data_ptr, neighbors[0][0]);
+ lp_build_sample_texel_soa(bld, width, height, x1, y0, stride, data_ptr, neighbors[0][1]);
+ lp_build_sample_texel_soa(bld, width, height, x0, y1, stride, data_ptr, neighbors[1][0]);
+ lp_build_sample_texel_soa(bld, width, height, x1, y1, stride, data_ptr, neighbors[1][1]);
/* TODO: Don't interpolate missing channels */
for(chan = 0; chan < 4; ++chan) {
@@ -334,20 +807,33 @@ lp_build_sample_2d_linear_aos(struct lp_build_sample_context *bld,
h16_vec_type = lp_build_vec_type(h16.type);
u8n_vec_type = lp_build_vec_type(u8n.type);
+ if (bld->static_state->normalized_coords) {
+ LLVMTypeRef coord_vec_type = lp_build_vec_type(bld->coord_type);
+ LLVMValueRef fp_width = LLVMBuildSIToFP(bld->builder, width, coord_vec_type, "");
+ LLVMValueRef fp_height = LLVMBuildSIToFP(bld->builder, height, coord_vec_type, "");
+ s = lp_build_mul(&bld->coord_bld, s, fp_width);
+ t = lp_build_mul(&bld->coord_bld, t, fp_height);
+ }
+
+ /* scale coords by 256 (8 fractional bits) */
s = lp_build_mul_imm(&bld->coord_bld, s, 256);
t = lp_build_mul_imm(&bld->coord_bld, t, 256);
+ /* convert float to int */
s = LLVMBuildFPToSI(builder, s, i32_vec_type, "");
t = LLVMBuildFPToSI(builder, t, i32_vec_type, "");
+ /* subtract 0.5 (add -128) */
i32_c128 = lp_build_int_const_scalar(i32.type, -128);
s = LLVMBuildAdd(builder, s, i32_c128, "");
t = LLVMBuildAdd(builder, t, i32_c128, "");
+ /* compute floor (shift right 8) */
i32_c8 = lp_build_int_const_scalar(i32.type, 8);
s_ipart = LLVMBuildAShr(builder, s, i32_c8, "");
t_ipart = LLVMBuildAShr(builder, t, i32_c8, "");
+ /* compute fractional part (AND with 0xff) */
i32_c255 = lp_build_int_const_scalar(i32.type, 255);
s_fpart = LLVMBuildAnd(builder, s, i32_c255, "");
t_fpart = LLVMBuildAnd(builder, t, i32_c255, "");
@@ -355,14 +841,18 @@ lp_build_sample_2d_linear_aos(struct lp_build_sample_context *bld,
x0 = s_ipart;
y0 = t_ipart;
- x0 = lp_build_sample_wrap(bld, x0, width, bld->static_state->pot_width, bld->static_state->wrap_s);
- y0 = lp_build_sample_wrap(bld, y0, height, bld->static_state->pot_height, bld->static_state->wrap_t);
-
x1 = lp_build_add(&bld->int_coord_bld, x0, bld->int_coord_bld.one);
y1 = lp_build_add(&bld->int_coord_bld, y0, bld->int_coord_bld.one);
- x1 = lp_build_sample_wrap(bld, x1, width, bld->static_state->pot_width, bld->static_state->wrap_s);
- y1 = lp_build_sample_wrap(bld, y1, height, bld->static_state->pot_height, bld->static_state->wrap_t);
+ x0 = lp_build_sample_wrap_int(bld, x0, width, bld->static_state->pot_width,
+ bld->static_state->wrap_s);
+ y0 = lp_build_sample_wrap_int(bld, y0, height, bld->static_state->pot_height,
+ bld->static_state->wrap_t);
+
+ x1 = lp_build_sample_wrap_int(bld, x1, width, bld->static_state->pot_width,
+ bld->static_state->wrap_s);
+ y1 = lp_build_sample_wrap_int(bld, y1, height, bld->static_state->pot_height,
+ bld->static_state->wrap_t);
/*
* Transform 4 x i32 in
@@ -518,6 +1008,11 @@ lp_build_sample_compare(struct lp_build_sample_context *bld,
}
+/**
+ * Build texture sampling code.
+ * 'texel' will return a vector of four LLVMValueRefs corresponding to
+ * R, G, B, A.
+ */
void
lp_build_sample_soa(LLVMBuilderRef builder,
const struct lp_sampler_static_state *static_state,
@@ -545,9 +1040,11 @@ lp_build_sample_soa(LLVMBuilderRef builder,
bld.dynamic_state = dynamic_state;
bld.format_desc = util_format_description(static_state->format);
bld.coord_type = type;
+ bld.uint_coord_type = lp_uint_type(type);
bld.int_coord_type = lp_int_type(type);
bld.texel_type = type;
lp_build_context_init(&bld.coord_bld, builder, bld.coord_type);
+ lp_build_context_init(&bld.uint_coord_bld, builder, bld.uint_coord_type);
lp_build_context_init(&bld.int_coord_bld, builder, bld.int_coord_type);
lp_build_context_init(&bld.texel_bld, builder, bld.texel_type);
@@ -561,30 +1058,27 @@ lp_build_sample_soa(LLVMBuilderRef builder,
t = coords[1];
p = coords[2];
- width = lp_build_broadcast_scalar(&bld.int_coord_bld, width);
- height = lp_build_broadcast_scalar(&bld.int_coord_bld, height);
- stride = lp_build_broadcast_scalar(&bld.int_coord_bld, stride);
+ width = lp_build_broadcast_scalar(&bld.uint_coord_bld, width);
+ height = lp_build_broadcast_scalar(&bld.uint_coord_bld, height);
+ stride = lp_build_broadcast_scalar(&bld.uint_coord_bld, stride);
if(static_state->target == PIPE_TEXTURE_1D)
t = bld.coord_bld.zero;
- if(static_state->normalized_coords) {
- LLVMTypeRef coord_vec_type = lp_build_vec_type(bld.coord_type);
- LLVMValueRef fp_width = LLVMBuildSIToFP(builder, width, coord_vec_type, "");
- LLVMValueRef fp_height = LLVMBuildSIToFP(builder, height, coord_vec_type, "");
- s = lp_build_mul(&bld.coord_bld, s, fp_width);
- t = lp_build_mul(&bld.coord_bld, t, fp_height);
- }
-
switch (static_state->min_img_filter) {
case PIPE_TEX_FILTER_NEAREST:
- lp_build_sample_2d_nearest_soa(&bld, s, t, width, height, stride, data_ptr, texel);
+ lp_build_sample_2d_nearest_soa(&bld, s, t, width, height,
+ stride, data_ptr, texel);
break;
case PIPE_TEX_FILTER_LINEAR:
- if(lp_format_is_rgba8(bld.format_desc))
- lp_build_sample_2d_linear_aos(&bld, s, t, width, height, stride, data_ptr, texel);
+ if(lp_format_is_rgba8(bld.format_desc) &&
+ is_simple_wrap_mode(static_state->wrap_s) &&
+ is_simple_wrap_mode(static_state->wrap_t))
+ lp_build_sample_2d_linear_aos(&bld, s, t, width, height,
+ stride, data_ptr, texel);
else
- lp_build_sample_2d_linear_soa(&bld, s, t, width, height, stride, data_ptr, texel);
+ lp_build_sample_2d_linear_soa(&bld, s, t, width, height,
+ stride, data_ptr, texel);
break;
default:
assert(0);
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
index ae866243a9..5f2c2a54ee 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
@@ -1126,6 +1126,7 @@ emit_instruction(
break;
case TGSI_OPCODE_TEX:
+ /* XXX what about dst0 writemask? */
emit_tex( bld, inst, FALSE, FALSE, dst0 );
break;
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_type.c b/src/gallium/auxiliary/gallivm/lp_bld_type.c
index 8270cd057f..c327ba045a 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_type.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_type.c
@@ -178,6 +178,25 @@ lp_build_int32_vec4_type(void)
}
+/**
+ * Create unsigned integer type variation of given type.
+ */
+struct lp_type
+lp_uint_type(struct lp_type type)
+{
+ struct lp_type res_type;
+
+ memset(&res_type, 0, sizeof res_type);
+ res_type.width = type.width;
+ res_type.length = type.length;
+
+ return res_type;
+}
+
+
+/**
+ * Create signed integer type variation of given type.
+ */
struct lp_type
lp_int_type(struct lp_type type)
{
@@ -186,6 +205,7 @@ lp_int_type(struct lp_type type)
memset(&res_type, 0, sizeof res_type);
res_type.width = type.width;
res_type.length = type.length;
+ res_type.sign = 1;
return res_type;
}
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_type.h b/src/gallium/auxiliary/gallivm/lp_bld_type.h
index 62ee05be4d..16946cc28a 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_type.h
+++ b/src/gallium/auxiliary/gallivm/lp_bld_type.h
@@ -257,6 +257,10 @@ lp_build_int32_vec4_type(void);
struct lp_type
+lp_uint_type(struct lp_type type);
+
+
+struct lp_type
lp_int_type(struct lp_type type);
diff --git a/src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c b/src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c
index 2533275dc1..515c9089dd 100644
--- a/src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c
+++ b/src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c
@@ -145,6 +145,10 @@ lp_llvm_sampler_soa_destroy(struct lp_build_sampler_soa *sampler)
}
+/**
+ * Fetch filtered values from texture.
+ * The 'texel' parameter returns four vectors corresponding to R, G, B, A.
+ */
static void
lp_llvm_sampler_soa_emit_fetch_texel(struct lp_build_sampler_soa *base,
LLVMBuilderRef builder,
diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c
index 770a92be74..6c891029a5 100644
--- a/src/gallium/drivers/r300/r300_render.c
+++ b/src/gallium/drivers/r300/r300_render.c
@@ -273,9 +273,14 @@ static void r300_emit_draw_elements(struct r300_context *r300,
CS_LOCALS(r300);
assert((start * indexSize) % 4 == 0);
+ assert(count < (1 << 24));
+
+ DBG(r300, DBG_DRAW, "r300: Indexbuf of %u indices, min %u max %u\n",
+ count, minIndex, maxIndex);
+
+ maxIndex = MIN2(maxIndex, ((1 << 24) - 1));
if (alt_num_verts) {
- assert(count < (1 << 24));
BEGIN_CS(16);
OUT_CS_REG(R500_VAP_ALT_NUM_VERTICES, count);
} else {
diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.c b/src/gallium/drivers/softpipe/sp_tex_sample.c
index ecd6b39863..b3a79732b4 100644
--- a/src/gallium/drivers/softpipe/sp_tex_sample.c
+++ b/src/gallium/drivers/softpipe/sp_tex_sample.c
@@ -55,7 +55,7 @@
static INLINE float
frac(float f)
{
- return f - util_ifloor(f);
+ return f - floorf(f);
}
@@ -201,11 +201,9 @@ wrap_nearest_mirror_repeat(const float s[4], unsigned size, int icoord[4])
const float max = 1.0F - min;
for (ch = 0; ch < 4; ch++) {
const int flr = util_ifloor(s[ch]);
- float u;
+ float u = frac(s[ch]);
if (flr & 1)
- u = 1.0F - (s[ch] - (float) flr);
- else
- u = s[ch] - (float) flr;
+ u = 1.0F - u;
if (u < min)
icoord[ch] = 0;
else if (u > max)
@@ -358,11 +356,9 @@ wrap_linear_mirror_repeat(const float s[4], unsigned size,
uint ch;
for (ch = 0; ch < 4; ch++) {
const int flr = util_ifloor(s[ch]);
- float u;
+ float u = frac(s[ch]);
if (flr & 1)
- u = 1.0F - (s[ch] - (float) flr);
- else
- u = s[ch] - (float) flr;
+ u = 1.0F - u;
u = u * size - 0.5F;
icoord0[ch] = util_ifloor(u);
icoord1[ch] = icoord0[ch] + 1;
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.c b/src/gallium/state_trackers/egl/common/egl_g3d.c
index 04268c71c5..50774b03f3 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d.c
+++ b/src/gallium/state_trackers/egl/common/egl_g3d.c
@@ -36,6 +36,7 @@
#include "native.h"
#include "egl_g3d.h"
+#include "egl_g3d_image.h"
#include "egl_st.h"
/**
@@ -531,6 +532,24 @@ egl_g3d_update_buffer(struct pipe_screen *screen, void *context_private)
egl_g3d_validate_context(gctx->base.Resource.Display, &gctx->base);
}
+static void
+egl_g3d_invalid_surface(struct native_display *ndpy,
+ struct native_surface *nsurf,
+ unsigned int seq_num)
+{
+ /* XXX not thread safe? */
+ struct egl_g3d_surface *gsurf = egl_g3d_surface(nsurf->user_data);
+ struct egl_g3d_context *gctx = egl_g3d_context(gsurf->base.CurrentContext);
+
+ /* set force_validate to skip an unnecessary check */
+ if (gctx)
+ gctx->force_validate = TRUE;
+}
+
+static struct native_event_handler egl_g3d_native_event_handler = {
+ .invalid_surface = egl_g3d_invalid_surface
+};
+
static EGLBoolean
egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy)
{
@@ -575,12 +594,14 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy,
}
dpy->DriverData = gdpy;
- gdpy->native = native_create_display(dpy->NativeDisplay);
+ gdpy->native = native_create_display(dpy->NativeDisplay,
+ &egl_g3d_native_event_handler);
if (!gdpy->native) {
_eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)");
goto fail;
}
+ gdpy->native->user_data = (void *) dpy;
gdpy->native->screen->flush_frontbuffer = egl_g3d_flush_frontbuffer;
gdpy->native->screen->update_buffer = egl_g3d_update_buffer;
@@ -595,6 +616,10 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy,
}
#endif
+ dpy->Extensions.KHR_image_base = EGL_TRUE;
+ if (gdpy->native->get_param(gdpy->native, NATIVE_PARAM_USE_NATIVE_BUFFER))
+ dpy->Extensions.KHR_image_pixmap = EGL_TRUE;
+
if (egl_g3d_add_configs(drv, dpy, 1) == 1) {
_eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)");
goto fail;
@@ -776,6 +801,7 @@ egl_g3d_create_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
return NULL;
}
+ nsurf->user_data = &gsurf->base;
gsurf->native = nsurf;
gsurf->render_att = (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER) ?
@@ -937,8 +963,8 @@ egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
/**
* Find a config that supports the pixmap.
*/
-static _EGLConfig *
-find_pixmap_config(_EGLDisplay *dpy, EGLNativePixmapType pix)
+_EGLConfig *
+egl_g3d_find_pixmap_config(_EGLDisplay *dpy, EGLNativePixmapType pix)
{
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
struct egl_g3d_config *gconf;
@@ -990,7 +1016,7 @@ egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
if (!gsurf->render_surface)
return EGL_TRUE;
- gconf = egl_g3d_config(find_pixmap_config(dpy, target));
+ gconf = egl_g3d_config(egl_g3d_find_pixmap_config(dpy, target));
if (!gconf)
return _eglError(EGL_BAD_NATIVE_PIXMAP, "eglCopyBuffers");
@@ -1301,6 +1327,9 @@ _eglMain(const char *args)
gdrv->base.API.BindTexImage = egl_g3d_bind_tex_image;
gdrv->base.API.ReleaseTexImage = egl_g3d_release_tex_image;
+ gdrv->base.API.CreateImageKHR = egl_g3d_create_image;
+ gdrv->base.API.DestroyImageKHR = egl_g3d_destroy_image;
+
#ifdef EGL_MESA_screen_surface
gdrv->base.API.CreateScreenSurfaceMESA = egl_g3d_create_screen_surface;
gdrv->base.API.ShowScreenSurfaceMESA = egl_g3d_show_screen_surface;
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.h b/src/gallium/state_trackers/egl/common/egl_g3d.h
index 5d2d9c481a..e3e55e46d3 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d.h
+++ b/src/gallium/state_trackers/egl/common/egl_g3d.h
@@ -34,6 +34,7 @@
#include "eglcontext.h"
#include "eglsurface.h"
#include "eglconfig.h"
+#include "eglimage.h"
#include "eglscreen.h"
#include "eglmode.h"
@@ -81,6 +82,14 @@ struct egl_g3d_config {
const struct native_config *native;
};
+struct egl_g3d_image {
+ _EGLImage base;
+ struct pipe_texture *texture;
+ unsigned face;
+ unsigned level;
+ unsigned zslice;
+};
+
struct egl_g3d_screen {
_EGLScreen base;
const struct native_connector *native;
@@ -90,5 +99,10 @@ struct egl_g3d_screen {
/* standard typecasts */
_EGL_DRIVER_STANDARD_TYPECASTS(egl_g3d)
_EGL_DRIVER_TYPECAST(egl_g3d_screen, _EGLScreen, obj)
+_EGL_DRIVER_TYPECAST(egl_g3d_image, _EGLImage, obj)
+
+
+_EGLConfig *
+egl_g3d_find_pixmap_config(_EGLDisplay *dpy, EGLNativePixmapType pix);
#endif /* _EGL_G3D_H_ */
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_image.c b/src/gallium/state_trackers/egl/common/egl_g3d_image.c
new file mode 100644
index 0000000000..d701f9c9a8
--- /dev/null
+++ b/src/gallium/state_trackers/egl/common/egl_g3d_image.c
@@ -0,0 +1,136 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2010 LunarG Inc.
+ *
+ * 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, sublicense,
+ * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL 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.
+ *
+ * Authors:
+ * Chia-I Wu <olv@lunarg.com>
+ */
+
+#include <assert.h>
+#include "pipe/p_screen.h"
+#include "util/u_memory.h"
+#include "util/u_rect.h"
+#include "util/u_inlines.h"
+#include "eglcurrent.h"
+#include "egllog.h"
+
+#include "native.h"
+#include "egl_g3d.h"
+#include "egl_g3d_image.h"
+
+/**
+ * Reference and return the front left buffer of the native pixmap.
+ */
+static struct pipe_texture *
+egl_g3d_reference_native_pixmap(_EGLDisplay *dpy, EGLNativePixmapType pix)
+{
+ struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
+ struct egl_g3d_config *gconf;
+ struct native_surface *nsurf;
+ struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS];
+ enum native_attachment natt;
+
+ gconf = egl_g3d_config(egl_g3d_find_pixmap_config(dpy, pix));
+ if (!gconf)
+ return NULL;
+
+ nsurf = gdpy->native->create_pixmap_surface(gdpy->native,
+ pix, gconf->native);
+ if (!nsurf)
+ return NULL;
+
+ natt = NATIVE_ATTACHMENT_FRONT_LEFT;
+ if (!nsurf->validate(nsurf, 1 << natt, NULL, textures, NULL, NULL))
+ textures[natt] = NULL;
+
+ nsurf->destroy(nsurf);
+
+ return textures[natt];
+}
+
+_EGLImage *
+egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
+ EGLenum target, EGLClientBuffer buffer,
+ const EGLint *attribs)
+{
+ struct pipe_texture *ptex;
+ struct egl_g3d_image *gimg;
+ unsigned face = 0, level = 0, zslice = 0;
+
+ gimg = CALLOC_STRUCT(egl_g3d_image);
+ if (!gimg) {
+ _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface");
+ return NULL;
+ }
+
+ if (!_eglInitImage(&gimg->base, dpy, attribs)) {
+ free(gimg);
+ return NULL;
+ }
+
+ switch (target) {
+ case EGL_NATIVE_PIXMAP_KHR:
+ ptex = egl_g3d_reference_native_pixmap(dpy,
+ (EGLNativePixmapType) buffer);
+ break;
+ default:
+ ptex = NULL;
+ break;
+ }
+
+ if (!ptex) {
+ free(gimg);
+ return NULL;
+ }
+
+ if (level > ptex->last_level) {
+ _eglError(EGL_BAD_MATCH, "eglCreateEGLImageKHR");
+ pipe_texture_reference(&gimg->texture, NULL);
+ free(gimg);
+ return NULL;
+ }
+ if (zslice > ptex->depth0) {
+ _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
+ pipe_texture_reference(&gimg->texture, NULL);
+ free(gimg);
+ return NULL;
+ }
+
+ /* transfer the ownership to the image */
+ gimg->texture = ptex;
+ gimg->face = face;
+ gimg->level = level;
+ gimg->zslice = zslice;
+
+ return &gimg->base;
+}
+
+EGLBoolean
+egl_g3d_destroy_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img)
+{
+ struct egl_g3d_image *gimg = egl_g3d_image(img);
+
+ pipe_texture_reference(&gimg->texture, NULL);
+ free(gimg);
+
+ return EGL_TRUE;
+}
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_image.h b/src/gallium/state_trackers/egl/common/egl_g3d_image.h
new file mode 100644
index 0000000000..c199c46645
--- /dev/null
+++ b/src/gallium/state_trackers/egl/common/egl_g3d_image.h
@@ -0,0 +1,41 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2010 LunarG Inc.
+ *
+ * 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, sublicense,
+ * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL 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.
+ *
+ * Authors:
+ * Chia-I Wu <olv@lunarg.com>
+ */
+
+#ifndef _EGL_G3D_IMAGE_H_
+#define _EGL_G3D_IMAGE_H_
+
+#include "egl_g3d.h"
+
+_EGLImage *
+egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
+ EGLenum target, EGLClientBuffer buffer,
+ const EGLint *attribs);
+
+EGLBoolean
+egl_g3d_destroy_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *image);
+
+#endif /* _EGL_G3D_IMAGE_H_ */
diff --git a/src/gallium/state_trackers/egl/common/native.h b/src/gallium/state_trackers/egl/common/native.h
index 4f9758545a..9c22ff3e43 100644
--- a/src/gallium/state_trackers/egl/common/native.h
+++ b/src/gallium/state_trackers/egl/common/native.h
@@ -34,6 +34,8 @@
#include "pipe/p_context.h"
#include "pipe/p_state.h"
+#include "native_modeset.h"
+
/**
* Only color buffers are listed. The others are allocated privately through,
* for example, st_renderbuffer_alloc_storage().
@@ -47,6 +49,14 @@ enum native_attachment {
NUM_NATIVE_ATTACHMENTS
};
+enum native_param_type {
+ /*
+ * Return TRUE if window/pixmap surfaces use the buffers of the native
+ * types.
+ */
+ NATIVE_PARAM_USE_NATIVE_BUFFER
+};
+
/**
* Enumerations for probe results.
*/
@@ -69,6 +79,11 @@ struct native_probe {
};
struct native_surface {
+ /**
+ * Available for caller's use.
+ */
+ void *user_data;
+
void (*destroy)(struct native_surface *nsurf);
/**
@@ -117,18 +132,6 @@ struct native_config {
boolean scanout_bit;
};
-struct native_connector {
- int dummy;
-};
-
-struct native_mode {
- const char *desc;
- int width, height;
- int refresh_rate;
-};
-
-struct native_display_modeset;
-
/**
* A pipe winsys abstracts the OS. A pipe screen abstracts the graphcis
* hardware. A native display consists of a pipe winsys, a pipe screen, and
@@ -143,9 +146,22 @@ struct native_display {
*/
struct pipe_screen *screen;
+ /**
+ * Available for caller's use.
+ */
+ void *user_data;
+
void (*destroy)(struct native_display *ndpy);
/**
+ * Query the parameters of the native display.
+ *
+ * The return value is defined by the parameter.
+ */
+ int (*get_param)(struct native_display *ndpy,
+ enum native_param_type param);
+
+ /**
* Get the supported configs. The configs are owned by the display, but
* the returned array should be free()ed.
*
@@ -196,46 +212,17 @@ struct native_display {
};
/**
- * Mode setting interface of the native display. It exposes the mode setting
- * capabilities of the underlying graphics hardware.
+ * The handler for events that a native display may generate. The events are
+ * generated asynchronously and the handler may be called by any thread at any
+ * time.
*/
-struct native_display_modeset {
- /**
- * Get the available physical connectors and the number of CRTCs.
- */
- const struct native_connector **(*get_connectors)(struct native_display *ndpy,
- int *num_connectors,
- int *num_crtcs);
-
+struct native_event_handler {
/**
- * Get the current supported modes of a connector. The returned modes may
- * change every time this function is called and those from previous calls
- * might become invalid.
- */
- const struct native_mode **(*get_modes)(struct native_display *ndpy,
- const struct native_connector *nconn,
- int *num_modes);
-
- /**
- * Create a scan-out surface. Required unless no config has
- * GLX_SCREEN_BIT_MESA set.
- */
- struct native_surface *(*create_scanout_surface)(struct native_display *ndpy,
- const struct native_config *nconf,
- uint width, uint height);
-
- /**
- * Program the CRTC to output the surface to the given connectors with the
- * given mode. When surface is not given, the CRTC is disabled.
- *
- * This interface does not export a way to query capabilities of the CRTCs.
- * The native display usually needs to dynamically map the index to a CRTC
- * that supports the given connectors.
+ * This function is called when a surface needs to be validated.
*/
- boolean (*program)(struct native_display *ndpy, int crtc_idx,
- struct native_surface *nsurf, uint x, uint y,
- const struct native_connector **nconns, int num_nconns,
- const struct native_mode *nmode);
+ void (*invalid_surface)(struct native_display *ndpy,
+ struct native_surface *nsurf,
+ unsigned int seq_num);
};
/**
@@ -267,6 +254,7 @@ const char *
native_get_name(void);
struct native_display *
-native_create_display(EGLNativeDisplayType dpy);
+native_create_display(EGLNativeDisplayType dpy,
+ struct native_event_handler *handler);
#endif /* _NATIVE_H_ */
diff --git a/src/gallium/state_trackers/egl/common/native_modeset.h b/src/gallium/state_trackers/egl/common/native_modeset.h
new file mode 100644
index 0000000000..71dc3ec860
--- /dev/null
+++ b/src/gallium/state_trackers/egl/common/native_modeset.h
@@ -0,0 +1,87 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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, sublicense,
+ * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL 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 _NATIVE_MODESET_H_
+#define _NATIVE_MODESET_H_
+
+#include "pipe/p_compiler.h"
+
+struct native_display;
+struct native_surface;
+struct native_config;
+
+struct native_connector {
+ int dummy;
+};
+
+struct native_mode {
+ const char *desc;
+ int width, height;
+ int refresh_rate;
+};
+
+/**
+ * Mode setting interface of the native display. It exposes the mode setting
+ * capabilities of the underlying graphics hardware.
+ */
+struct native_display_modeset {
+ /**
+ * Get the available physical connectors and the number of CRTCs.
+ */
+ const struct native_connector **(*get_connectors)(struct native_display *ndpy,
+ int *num_connectors,
+ int *num_crtcs);
+
+ /**
+ * Get the current supported modes of a connector. The returned modes may
+ * change every time this function is called and those from previous calls
+ * might become invalid.
+ */
+ const struct native_mode **(*get_modes)(struct native_display *ndpy,
+ const struct native_connector *nconn,
+ int *num_modes);
+
+ /**
+ * Create a scan-out surface. Required unless no config has
+ * GLX_SCREEN_BIT_MESA set.
+ */
+ struct native_surface *(*create_scanout_surface)(struct native_display *ndpy,
+ const struct native_config *nconf,
+ uint width, uint height);
+
+ /**
+ * Program the CRTC to output the surface to the given connectors with the
+ * given mode. When surface is not given, the CRTC is disabled.
+ *
+ * This interface does not export a way to query capabilities of the CRTCs.
+ * The native display usually needs to dynamically map the index to a CRTC
+ * that supports the given connectors.
+ */
+ boolean (*program)(struct native_display *ndpy, int crtc_idx,
+ struct native_surface *nsurf, uint x, uint y,
+ const struct native_connector **nconns, int num_nconns,
+ const struct native_mode *nmode);
+};
+
+#endif /* _NATIVE_MODESET_H_ */
diff --git a/src/gallium/state_trackers/egl/kms/native_kms.c b/src/gallium/state_trackers/egl/kms/native_kms.c
index aedf3d430c..94588bfa74 100644
--- a/src/gallium/state_trackers/egl/kms/native_kms.c
+++ b/src/gallium/state_trackers/egl/kms/native_kms.c
@@ -201,6 +201,8 @@ kms_surface_swap_buffers(struct native_surface *nsurf)
/* the front/back textures are swapped */
ksurf->sequence_number++;
+ kdpy->event_handler->invalid_surface(&kdpy->base,
+ &ksurf->base, ksurf->sequence_number);
return TRUE;
}
@@ -663,6 +665,21 @@ kms_display_get_configs(struct native_display *ndpy, int *num_configs)
return configs;
}
+static int
+kms_display_get_param(struct native_display *ndpy,
+ enum native_param_type param)
+{
+ int val;
+
+ switch (param) {
+ default:
+ val = 0;
+ break;
+ }
+
+ return val;
+}
+
static void
kms_display_destroy(struct native_display *ndpy)
{
@@ -762,7 +779,9 @@ static struct native_display_modeset kms_display_modeset = {
};
static struct native_display *
-kms_create_display(EGLNativeDisplayType dpy, struct drm_api *api)
+kms_create_display(EGLNativeDisplayType dpy,
+ struct native_event_handler *event_handler,
+ struct drm_api *api)
{
struct kms_display *kdpy;
@@ -770,6 +789,8 @@ kms_create_display(EGLNativeDisplayType dpy, struct drm_api *api)
if (!kdpy)
return NULL;
+ kdpy->event_handler = event_handler;
+
kdpy->api = api;
if (!kdpy->api) {
_eglLog(_EGL_WARNING, "failed to create DRM API");
@@ -805,6 +826,7 @@ kms_create_display(EGLNativeDisplayType dpy, struct drm_api *api)
}
kdpy->base.destroy = kms_display_destroy;
+ kdpy->base.get_param = kms_display_get_param;
kdpy->base.get_configs = kms_display_get_configs;
kdpy->base.create_pbuffer_surface = kms_display_create_pbuffer_surface;
@@ -845,7 +867,8 @@ native_get_name(void)
}
struct native_display *
-native_create_display(EGLNativeDisplayType dpy)
+native_create_display(EGLNativeDisplayType dpy,
+ struct native_event_handler *event_handler)
{
struct native_display *ndpy = NULL;
@@ -853,7 +876,7 @@ native_create_display(EGLNativeDisplayType dpy)
drm_api = drm_api_create();
if (drm_api)
- ndpy = kms_create_display(dpy, drm_api);
+ ndpy = kms_create_display(dpy, event_handler, drm_api);
return ndpy;
}
diff --git a/src/gallium/state_trackers/egl/kms/native_kms.h b/src/gallium/state_trackers/egl/kms/native_kms.h
index 095186e3cf..f9cbcb158b 100644
--- a/src/gallium/state_trackers/egl/kms/native_kms.h
+++ b/src/gallium/state_trackers/egl/kms/native_kms.h
@@ -53,6 +53,8 @@ struct kms_crtc {
struct kms_display {
struct native_display base;
+ struct native_event_handler *event_handler;
+
int fd;
struct drm_api *api;
drmModeResPtr resources;
diff --git a/src/gallium/state_trackers/egl/x11/native_dri2.c b/src/gallium/state_trackers/egl/x11/native_dri2.c
index 74d3d104b9..8d2a8b1dff 100644
--- a/src/gallium/state_trackers/egl/x11/native_dri2.c
+++ b/src/gallium/state_trackers/egl/x11/native_dri2.c
@@ -48,6 +48,8 @@ struct dri2_display {
Display *dpy;
boolean own_dpy;
+ struct native_event_handler *event_handler;
+
struct drm_api *api;
struct x11_screen *xscr;
int xscr_number;
@@ -324,8 +326,11 @@ dri2_surface_flush_frontbuffer(struct native_surface *nsurf)
DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
/* force buffers to be updated in next validation call */
- if (!dri2_surface_receive_events(&dri2surf->base))
+ if (!dri2_surface_receive_events(&dri2surf->base)) {
dri2surf->server_stamp++;
+ dri2dpy->event_handler->invalid_surface(&dri2dpy->base,
+ &dri2surf->base, dri2surf->server_stamp);
+ }
return TRUE;
}
@@ -353,8 +358,11 @@ dri2_surface_swap_buffers(struct native_surface *nsurf)
DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
/* force buffers to be updated in next validation call */
- if (!dri2_surface_receive_events(&dri2surf->base))
+ if (!dri2_surface_receive_events(&dri2surf->base)) {
dri2surf->server_stamp++;
+ dri2dpy->event_handler->invalid_surface(&dri2dpy->base,
+ &dri2surf->base, dri2surf->server_stamp);
+ }
return TRUE;
}
@@ -699,6 +707,25 @@ dri2_display_is_pixmap_supported(struct native_display *ndpy,
return (depth == nconf_depth || (depth == 24 && depth + 8 == nconf_depth));
}
+static int
+dri2_display_get_param(struct native_display *ndpy,
+ enum native_param_type param)
+{
+ int val;
+
+ switch (param) {
+ case NATIVE_PARAM_USE_NATIVE_BUFFER:
+ /* DRI2GetBuffers use the native buffers */
+ val = TRUE;
+ break;
+ default:
+ val = 0;
+ break;
+ }
+
+ return val;
+}
+
static void
dri2_display_destroy(struct native_display *ndpy)
{
@@ -737,7 +764,10 @@ dri2_display_invalidate_buffers(struct x11_screen *xscr, Drawable drawable,
return;
dri2surf = dri2_surface(nsurf);
+
dri2surf->server_stamp++;
+ dri2dpy->event_handler->invalid_surface(&dri2dpy->base,
+ &dri2surf->base, dri2surf->server_stamp);
}
/**
@@ -796,7 +826,9 @@ dri2_display_hash_table_compare(void *key1, void *key2)
}
struct native_display *
-x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api)
+x11_create_dri2_display(EGLNativeDisplayType dpy,
+ struct native_event_handler *event_handler,
+ struct drm_api *api)
{
struct dri2_display *dri2dpy;
@@ -804,6 +836,7 @@ x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api)
if (!dri2dpy)
return NULL;
+ dri2dpy->event_handler = event_handler;
dri2dpy->api = api;
dri2dpy->dpy = dpy;
@@ -836,6 +869,7 @@ x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api)
}
dri2dpy->base.destroy = dri2_display_destroy;
+ dri2dpy->base.get_param = dri2_display_get_param;
dri2dpy->base.get_configs = dri2_display_get_configs;
dri2dpy->base.is_pixmap_supported = dri2_display_is_pixmap_supported;
dri2dpy->base.create_window_surface = dri2_display_create_window_surface;
diff --git a/src/gallium/state_trackers/egl/x11/native_x11.c b/src/gallium/state_trackers/egl/x11/native_x11.c
index 3add95d0ac..7b4fe63fa0 100644
--- a/src/gallium/state_trackers/egl/x11/native_x11.c
+++ b/src/gallium/state_trackers/egl/x11/native_x11.c
@@ -126,7 +126,8 @@ native_get_name(void)
}
struct native_display *
-native_create_display(EGLNativeDisplayType dpy)
+native_create_display(EGLNativeDisplayType dpy,
+ struct native_event_handler *event_handler)
{
struct native_display *ndpy = NULL;
boolean force_sw;
@@ -136,7 +137,7 @@ native_create_display(EGLNativeDisplayType dpy)
force_sw = debug_get_bool_option("EGL_SOFTWARE", FALSE);
if (api && !force_sw) {
- ndpy = x11_create_dri2_display(dpy, api);
+ ndpy = x11_create_dri2_display(dpy, event_handler, api);
}
if (!ndpy) {
@@ -150,7 +151,7 @@ native_create_display(EGLNativeDisplayType dpy)
*/
use_shm = FALSE;
_eglLog(level, "use software%s fallback", (use_shm) ? " (SHM)" : "");
- ndpy = x11_create_ximage_display(dpy, use_shm);
+ ndpy = x11_create_ximage_display(dpy, event_handler, use_shm);
}
return ndpy;
diff --git a/src/gallium/state_trackers/egl/x11/native_x11.h b/src/gallium/state_trackers/egl/x11/native_x11.h
index 622ddac5df..8c6a7d9349 100644
--- a/src/gallium/state_trackers/egl/x11/native_x11.h
+++ b/src/gallium/state_trackers/egl/x11/native_x11.h
@@ -29,9 +29,13 @@
#include "common/native.h"
struct native_display *
-x11_create_ximage_display(EGLNativeDisplayType dpy, boolean use_xshm);
+x11_create_ximage_display(EGLNativeDisplayType dpy,
+ struct native_event_handler *event_handler,
+ boolean use_xshm);
struct native_display *
-x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api);
+x11_create_dri2_display(EGLNativeDisplayType dpy,
+ struct native_event_handler *event_handler,
+ struct drm_api *api);
#endif /* _NATIVE_X11_H_ */
diff --git a/src/gallium/state_trackers/egl/x11/native_ximage.c b/src/gallium/state_trackers/egl/x11/native_ximage.c
index a8633b1501..3421c1951a 100644
--- a/src/gallium/state_trackers/egl/x11/native_ximage.c
+++ b/src/gallium/state_trackers/egl/x11/native_ximage.c
@@ -56,6 +56,8 @@ struct ximage_display {
struct x11_screen *xscr;
int xscr_number;
+ struct native_event_handler *event_handler;
+
boolean use_xshm;
struct pipe_winsys *winsys;
@@ -228,6 +230,16 @@ ximage_surface_update_geometry(struct native_surface *nsurf)
return updated;
}
+static void
+ximage_surface_notify_invalid(struct native_surface *nsurf)
+{
+ struct ximage_surface *xsurf = ximage_surface(nsurf);
+ struct ximage_display *xdpy = xsurf->xdpy;
+
+ xdpy->event_handler->invalid_surface(&xdpy->base,
+ &xsurf->base, xsurf->server_stamp);
+}
+
/**
* Update the buffers of the surface. It is a slow function due to the
* round-trip to the server.
@@ -339,6 +351,7 @@ ximage_surface_flush_frontbuffer(struct native_surface *nsurf)
NATIVE_ATTACHMENT_FRONT_LEFT);
/* force buffers to be updated in next validation call */
xsurf->server_stamp++;
+ ximage_surface_notify_invalid(&xsurf->base);
return ret;
}
@@ -354,6 +367,7 @@ ximage_surface_swap_buffers(struct native_surface *nsurf)
ret = ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_BACK_LEFT);
/* force buffers to be updated in next validation call */
xsurf->server_stamp++;
+ ximage_surface_notify_invalid(&xsurf->base);
xfront = &xsurf->buffers[NATIVE_ATTACHMENT_FRONT_LEFT];
xback = &xsurf->buffers[NATIVE_ATTACHMENT_BACK_LEFT];
@@ -685,6 +699,25 @@ ximage_display_is_pixmap_supported(struct native_display *ndpy,
return (fmt == nconf->color_format);
}
+static int
+ximage_display_get_param(struct native_display *ndpy,
+ enum native_param_type param)
+{
+ int val;
+
+ switch (param) {
+ case NATIVE_PARAM_USE_NATIVE_BUFFER:
+ /* private buffers are allocated */
+ val = FALSE;
+ break;
+ default:
+ val = 0;
+ break;
+ }
+
+ return val;
+}
+
static void
ximage_display_destroy(struct native_display *ndpy)
{
@@ -703,7 +736,9 @@ ximage_display_destroy(struct native_display *ndpy)
}
struct native_display *
-x11_create_ximage_display(EGLNativeDisplayType dpy, boolean use_xshm)
+x11_create_ximage_display(EGLNativeDisplayType dpy,
+ struct native_event_handler *event_handler,
+ boolean use_xshm)
{
struct ximage_display *xdpy;
@@ -728,6 +763,8 @@ x11_create_ximage_display(EGLNativeDisplayType dpy, boolean use_xshm)
return NULL;
}
+ xdpy->event_handler = event_handler;
+
xdpy->use_xshm =
(use_xshm && x11_screen_support(xdpy->xscr, X11_SCREEN_EXTENSION_XSHM));
@@ -735,6 +772,7 @@ x11_create_ximage_display(EGLNativeDisplayType dpy, boolean use_xshm)
xdpy->base.screen = softpipe_create_screen(xdpy->winsys);
xdpy->base.destroy = ximage_display_destroy;
+ xdpy->base.get_param = ximage_display_get_param;
xdpy->base.get_configs = ximage_display_get_configs;
xdpy->base.is_pixmap_supported = ximage_display_is_pixmap_supported;