summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_sample.c24
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_sample.h4
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c642
3 files changed, 420 insertions, 250 deletions
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.c b/src/gallium/auxiliary/gallivm/lp_bld_sample.c
index 311c9f1b9e..543fd5fea3 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_sample.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.c
@@ -155,14 +155,16 @@ lp_build_gather(LLVMBuilderRef builder,
/**
* Compute the offset of a pixel.
*
- * x, y, y_stride are vectors
+ * x, y, z, y_stride, z_stride are vectors
*/
LLVMValueRef
lp_build_sample_offset(struct lp_build_context *bld,
const struct util_format_description *format_desc,
LLVMValueRef x,
LLVMValueRef y,
- LLVMValueRef y_stride)
+ LLVMValueRef z,
+ LLVMValueRef y_stride,
+ LLVMValueRef z_stride)
{
LLVMValueRef x_stride;
LLVMValueRef offset;
@@ -178,6 +180,10 @@ lp_build_sample_offset(struct lp_build_context *bld,
LLVMValueRef y_offset_lo, y_offset_hi;
LLVMValueRef offset_lo, offset_hi;
+ /* XXX 1D & 3D addressing not done yet */
+ assert(!z);
+ assert(!z_stride);
+
x_lo = LLVMBuildAnd(bld->builder, x, bld->one, "");
y_lo = LLVMBuildAnd(bld->builder, y, bld->one, "");
@@ -201,13 +207,17 @@ lp_build_sample_offset(struct lp_build_context *bld,
offset = lp_build_add(bld, offset_hi, offset_lo);
}
else {
- LLVMValueRef x_offset;
- LLVMValueRef y_offset;
+ offset = lp_build_mul(bld, x, x_stride);
- x_offset = lp_build_mul(bld, x, x_stride);
- y_offset = lp_build_mul(bld, y, y_stride);
+ if (y && y_stride) {
+ LLVMValueRef y_offset = lp_build_mul(bld, y, y_stride);
+ offset = lp_build_add(bld, offset, y_offset);
+ }
- offset = lp_build_add(bld, x_offset, y_offset);
+ if (z && z_stride) {
+ LLVMValueRef z_offset = lp_build_mul(bld, z, z_stride);
+ offset = lp_build_add(bld, offset, z_offset);
+ }
}
return offset;
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.h b/src/gallium/auxiliary/gallivm/lp_bld_sample.h
index 68db91d6fd..5b8da5dbf2 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_sample.h
+++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.h
@@ -148,7 +148,9 @@ lp_build_sample_offset(struct lp_build_context *bld,
const struct util_format_description *format_desc,
LLVMValueRef x,
LLVMValueRef y,
- LLVMValueRef y_stride);
+ LLVMValueRef z,
+ LLVMValueRef y_stride,
+ LLVMValueRef z_stride);
void
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
index 2e6865a67b..dadae61115 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
@@ -138,8 +138,28 @@ lp_build_get_const_mipmap_level(struct lp_build_sample_context *bld,
}
+static int
+texture_dims(enum pipe_texture_target tex)
+{
+ switch (tex) {
+ case PIPE_TEXTURE_1D:
+ return 1;
+ case PIPE_TEXTURE_2D:
+ case PIPE_TEXTURE_CUBE:
+ return 2;
+ case PIPE_TEXTURE_3D:
+ return 3;
+ default:
+ assert(0 && "bad texture target in texture_dims()");
+ return 2;
+ }
+}
+
+
+
/**
- * Gen code to fetch a texel from a texture at int coords (x, y).
+ * Generate code to fetch a texel from a texture at int coords (x, y, z).
+ * The computation depends on whether the texture is 1D, 2D or 3D.
* The result, texel, will be:
* texel[0] = red values
* texel[1] = green values
@@ -150,12 +170,16 @@ static void
lp_build_sample_texel_soa(struct lp_build_sample_context *bld,
LLVMValueRef width,
LLVMValueRef height,
+ LLVMValueRef depth,
LLVMValueRef x,
LLVMValueRef y,
+ LLVMValueRef z,
LLVMValueRef y_stride,
+ LLVMValueRef z_stride,
LLVMValueRef data_ptr,
LLVMValueRef *texel)
{
+ const int dims = texture_dims(bld->static_state->target);
struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
LLVMValueRef offset;
LLVMValueRef packed;
@@ -169,7 +193,7 @@ lp_build_sample_texel_soa(struct lp_build_sample_context *bld,
use_border = LLVMBuildOr(bld->builder, b1, b2, "b1_or_b2");
}
- if (wrap_mode_uses_border_color(bld->static_state->wrap_t)) {
+ if (dims >= 2 && 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);
@@ -182,6 +206,19 @@ lp_build_sample_texel_soa(struct lp_build_sample_context *bld,
}
}
+ if (dims == 3 && wrap_mode_uses_border_color(bld->static_state->wrap_r)) {
+ LLVMValueRef b1, b2;
+ b1 = lp_build_cmp(int_coord_bld, PIPE_FUNC_LESS, z, int_coord_bld->zero);
+ b2 = lp_build_cmp(int_coord_bld, PIPE_FUNC_GEQUAL, z, depth);
+ 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
@@ -197,10 +234,10 @@ lp_build_sample_texel_soa(struct lp_build_sample_context *bld,
* the texel color results with the border color.
*/
- /* convert x,y coords to linear offset from start of texture, in bytes */
+ /* convert x,y,z 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);
+ x, y, z, y_stride, z_stride);
assert(bld->format_desc->block.width == 1);
assert(bld->format_desc->block.height == 1);
@@ -213,6 +250,8 @@ lp_build_sample_texel_soa(struct lp_build_sample_context *bld,
bld->texel_type.width,
data_ptr, offset);
+ texel[0] = texel[1] = texel[2] = texel[3] = NULL;
+
/* convert texels to float rgba */
lp_build_unpack_rgba_soa(bld->builder,
bld->format_desc,
@@ -245,7 +284,7 @@ lp_build_sample_packed(struct lp_build_sample_context *bld,
offset = lp_build_sample_offset(&bld->uint_coord_bld,
bld->format_desc,
- x, y, y_stride);
+ x, y, NULL, y_stride, NULL);
assert(bld->format_desc->block.width == 1);
assert(bld->format_desc->block.height == 1);
@@ -756,24 +795,6 @@ lp_build_minify(struct lp_build_sample_context *bld,
}
-static int
-texture_dims(enum pipe_texture_target tex)
-{
- switch (tex) {
- case PIPE_TEXTURE_1D:
- return 1;
- case PIPE_TEXTURE_2D:
- case PIPE_TEXTURE_CUBE:
- return 2;
- case PIPE_TEXTURE_3D:
- return 3;
- default:
- assert(0 && "bad texture target in texture_dims()");
- return 2;
- }
-}
-
-
/**
* Generate code to compute texture level of detail (lambda).
* \param s vector of texcoord s values
@@ -920,229 +941,406 @@ lp_build_linear_mip_levels(struct lp_build_sample_context *bld,
LLVMValueRef *level1_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 *float_bld = &bld->float_bld;
+ struct lp_build_context *int_bld = &bld->int_bld;
LLVMValueRef last_level, level;
last_level = bld->dynamic_state->last_level(bld->dynamic_state,
bld->builder, unit);
/* convert float lod to integer */
- level = lp_build_ifloor(coord_bld, lod);
+ level = lp_build_ifloor(float_bld, lod);
/* compute level 0 and clamp to legal range of levels */
- *level0_out = lp_build_clamp(int_coord_bld, level,
- int_coord_bld->zero,
+ *level0_out = lp_build_clamp(int_bld, level,
+ int_bld->zero,
last_level);
/* compute level 1 and clamp to legal range of levels */
- *level1_out = lp_build_add(int_coord_bld, *level0_out, int_coord_bld->one);
- *level1_out = lp_build_min(int_coord_bld, *level1_out, int_coord_bld->zero);
+ *level1_out = lp_build_add(int_bld, *level0_out, int_bld->one);
+ *level1_out = lp_build_min(int_bld, *level1_out, int_bld->zero);
- *weight_out = lp_build_fract(coord_bld, lod);
+ *weight_out = lp_build_fract(float_bld, lod);
}
-
/**
- * Sample 2D texture with nearest filtering, no mipmapping.
+ * Generate code to sample a mipmap level with nearest filtering.
*/
static void
-lp_build_sample_2d_nearest_soa(struct lp_build_sample_context *bld,
- LLVMValueRef s,
- LLVMValueRef t,
- LLVMValueRef width,
- LLVMValueRef height,
- LLVMValueRef stride,
- LLVMValueRef data_array,
- LLVMValueRef *texel)
+lp_build_sample_image_nearest(struct lp_build_sample_context *bld,
+ LLVMValueRef width_vec,
+ LLVMValueRef height_vec,
+ LLVMValueRef depth_vec,
+ LLVMValueRef row_stride_vec,
+ LLVMValueRef img_stride_vec,
+ LLVMValueRef data_ptr,
+ LLVMValueRef s,
+ LLVMValueRef t,
+ LLVMValueRef r,
+ LLVMValueRef colors_out[4])
{
- LLVMValueRef x, y;
- LLVMValueRef data_ptr;
+ const int dims = texture_dims(bld->static_state->target);
+ LLVMValueRef x, y, z;
- x = lp_build_sample_wrap_nearest(bld, s, width,
+ /*
+ * Compute integer texcoords.
+ */
+ x = lp_build_sample_wrap_nearest(bld, s, width_vec,
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);
-
lp_build_name(x, "tex.x.wrapped");
- lp_build_name(y, "tex.y.wrapped");
- /* get pointer to mipmap level 0 data */
- data_ptr = lp_build_get_const_mipmap_level(bld, data_array, 0);
+ if (dims >= 2) {
+ y = lp_build_sample_wrap_nearest(bld, t, height_vec,
+ bld->static_state->pot_height,
+ bld->static_state->wrap_t);
+ lp_build_name(y, "tex.y.wrapped");
+
+ if (dims == 3) {
+ z = lp_build_sample_wrap_nearest(bld, r, depth_vec,
+ bld->static_state->pot_height,
+ bld->static_state->wrap_r);
+ lp_build_name(z, "tex.z.wrapped");
+ }
+ else {
+ z = NULL;
+ }
+ }
+ else {
+ y = NULL;
+ }
- lp_build_sample_texel_soa(bld, width, height, x, y, stride, data_ptr, texel);
+ /*
+ * Get texture colors.
+ */
+ lp_build_sample_texel_soa(bld, width_vec, height_vec, depth_vec,
+ x, y, z,
+ row_stride_vec, img_stride_vec,
+ data_ptr, colors_out);
}
/**
- * Sample 2D texture with nearest filtering, nearest mipmap.
+ * Generate code to sample a mipmap level with linear filtering.
+ * 1D, 2D and 3D images are suppored.
*/
static void
-lp_build_sample_2d_nearest_mip_nearest_soa(struct lp_build_sample_context *bld,
- unsigned unit,
- LLVMValueRef s,
- LLVMValueRef t,
- LLVMValueRef width,
- LLVMValueRef height,
- LLVMValueRef width_vec,
- LLVMValueRef height_vec,
- LLVMValueRef stride,
- LLVMValueRef data_array,
- LLVMValueRef *texel)
+lp_build_sample_image_linear(struct lp_build_sample_context *bld,
+ LLVMValueRef width_vec,
+ LLVMValueRef height_vec,
+ LLVMValueRef depth_vec,
+ LLVMValueRef row_stride_vec,
+ LLVMValueRef img_stride_vec,
+ LLVMValueRef data_ptr,
+ LLVMValueRef s,
+ LLVMValueRef t,
+ LLVMValueRef r,
+ LLVMValueRef colors_out[4])
{
- LLVMValueRef x, y;
- LLVMValueRef lod, ilevel, ilevel_vec;
- LLVMValueRef data_ptr;
-
- /* compute float LOD */
- lod = lp_build_lod_selector(bld, s, t, NULL, width, height, NULL);
-
- /* convert LOD to int */
- lp_build_nearest_mip_level(bld, unit, lod, &ilevel);
-
- ilevel_vec = lp_build_broadcast_scalar(&bld->int_coord_bld, ilevel);
+ const int dims = texture_dims(bld->static_state->target);
+ LLVMValueRef x0, y0, z0, x1, y1, z1;
+ LLVMValueRef s_fpart, t_fpart, r_fpart;
+ LLVMValueRef neighbors[2][2][4];
+ int chan;
- /* compute width_vec, height at mipmap level 'ilevel' */
- width_vec = lp_build_minify(bld, width_vec, ilevel_vec);
- height_vec = lp_build_minify(bld, height_vec, ilevel_vec);
- stride = lp_build_minify(bld, stride, ilevel_vec);
+ /*
+ * Compute integer texcoords.
+ */
+ lp_build_sample_wrap_linear(bld, s, width_vec,
+ bld->static_state->pot_width,
+ bld->static_state->wrap_s,
+ &x0, &x1, &s_fpart);
+ lp_build_name(x0, "tex.x0.wrapped");
+ lp_build_name(x1, "tex.x1.wrapped");
- x = lp_build_sample_wrap_nearest(bld, s, width_vec,
- bld->static_state->pot_width,
- bld->static_state->wrap_s);
- y = lp_build_sample_wrap_nearest(bld, t, height_vec,
- bld->static_state->pot_height,
- bld->static_state->wrap_t);
+ if (dims >= 2) {
+ lp_build_sample_wrap_linear(bld, t, height_vec,
+ bld->static_state->pot_height,
+ bld->static_state->wrap_t,
+ &y0, &y1, &t_fpart);
+ lp_build_name(y0, "tex.y0.wrapped");
+ lp_build_name(y1, "tex.y1.wrapped");
+
+ if (dims == 3) {
+ lp_build_sample_wrap_linear(bld, r, depth_vec,
+ bld->static_state->pot_depth,
+ bld->static_state->wrap_r,
+ &z0, &z1, &r_fpart);
+ lp_build_name(z0, "tex.z0.wrapped");
+ lp_build_name(z1, "tex.z1.wrapped");
+ }
+ else {
+ z0 = z1 = r_fpart = NULL;
+ }
+ }
+ else {
+ y0 = y1 = t_fpart = NULL;
+ }
- lp_build_name(x, "tex.x.wrapped");
- lp_build_name(y, "tex.y.wrapped");
+ /*
+ * Get texture colors.
+ */
+ /* get x0/x1 texels */
+ lp_build_sample_texel_soa(bld, width_vec, height_vec, depth_vec,
+ x0, y0, z0,
+ row_stride_vec, img_stride_vec,
+ data_ptr, neighbors[0][0]);
+ lp_build_sample_texel_soa(bld, width_vec, height_vec, depth_vec,
+ x1, y0, z0,
+ row_stride_vec, img_stride_vec,
+ data_ptr, neighbors[0][1]);
+
+ if (dims == 1) {
+ /* Interpolate two samples from 1D image to produce one color */
+ colors_out[chan] = lp_build_lerp(&bld->texel_bld, s_fpart,
+ neighbors[0][0][chan],
+ neighbors[0][1][chan]);
+ }
+ else {
+ /* 2D/3D texture */
+ LLVMValueRef colors0[4];
+
+ /* get x0/x1 texels at y1 */
+ lp_build_sample_texel_soa(bld, width_vec, height_vec, depth_vec,
+ x0, y1, z0,
+ row_stride_vec, img_stride_vec,
+ data_ptr, neighbors[1][0]);
+ lp_build_sample_texel_soa(bld, width_vec, height_vec, depth_vec,
+ x1, y1, z0,
+ row_stride_vec, img_stride_vec,
+ data_ptr, neighbors[1][1]);
+
+ /* Bilinear interpolate the four samples from the 2D image / 3D slice */
+ for (chan = 0; chan < 4; chan++) {
+ colors0[chan] = lp_build_lerp_2d(&bld->texel_bld,
+ s_fpart, t_fpart,
+ neighbors[0][0][chan],
+ neighbors[0][1][chan],
+ neighbors[1][0][chan],
+ neighbors[1][1][chan]);
+ }
- /* get pointer to mipmap level [ilevel] data */
- data_ptr = lp_build_get_mipmap_level(bld, data_array, ilevel);
+ if (dims == 3) {
+ LLVMValueRef neighbors1[2][2][4];
+ LLVMValueRef colors1[4];
+
+ /* get x0/x1/y0/y1 texels at z1 */
+ lp_build_sample_texel_soa(bld, width_vec, height_vec, depth_vec,
+ x0, y0, z1,
+ row_stride_vec, img_stride_vec,
+ data_ptr, neighbors1[0][0]);
+ lp_build_sample_texel_soa(bld, width_vec, height_vec, depth_vec,
+ x1, y0, z1,
+ row_stride_vec, img_stride_vec,
+ data_ptr, neighbors1[0][1]);
+ lp_build_sample_texel_soa(bld, width_vec, height_vec, depth_vec,
+ x0, y1, z1,
+ row_stride_vec, img_stride_vec,
+ data_ptr, neighbors1[1][0]);
+ lp_build_sample_texel_soa(bld, width_vec, height_vec, depth_vec,
+ x1, y1, z1,
+ row_stride_vec, img_stride_vec,
+ data_ptr, neighbors1[1][1]);
+
+ /* Bilinear interpolate the four samples from the second Z slice */
+ for (chan = 0; chan < 4; chan++) {
+ colors1[chan] = lp_build_lerp_2d(&bld->texel_bld,
+ s_fpart, t_fpart,
+ neighbors1[0][0][chan],
+ neighbors1[0][1][chan],
+ neighbors1[1][0][chan],
+ neighbors1[1][1][chan]);
+ }
- lp_build_sample_texel_soa(bld, width_vec, height_vec, x, y,
- stride, data_ptr, texel);
+ /* Linearly interpolate the two samples from the two 3D slices */
+ for (chan = 0; chan < 4; chan++) {
+ colors_out[chan] = lp_build_lerp(&bld->texel_bld,
+ r_fpart,
+ colors0[chan], colors1[chan]);
+ }
+ }
+ else {
+ /* 2D tex */
+ for (chan = 0; chan < 4; chan++) {
+ colors_out[chan] = colors0[chan];
+ }
+ }
+ }
}
+
/**
- * Sample 2D texture with linear filtering, nearest mipmap.
+ * General texture sampling codegen.
+ * This function handles texture sampling for all texture targets (1D,
+ * 2D, 3D, cube) and all filtering modes.
*/
static void
-lp_build_sample_2d_linear_mip_nearest_soa(struct lp_build_sample_context *bld,
- unsigned unit,
- LLVMValueRef s,
- LLVMValueRef t,
- LLVMValueRef width,
- LLVMValueRef height,
- LLVMValueRef width_vec,
- LLVMValueRef height_vec,
- LLVMValueRef stride,
- LLVMValueRef data_array,
- LLVMValueRef *texel)
+lp_build_sample_general(struct lp_build_sample_context *bld,
+ unsigned unit,
+ LLVMValueRef s,
+ LLVMValueRef t,
+ LLVMValueRef r,
+ LLVMValueRef width,
+ LLVMValueRef height,
+ LLVMValueRef depth,
+ LLVMValueRef width_vec,
+ LLVMValueRef height_vec,
+ LLVMValueRef depth_vec,
+ LLVMValueRef row_stride_vec,
+ LLVMValueRef img_stride_vec,
+ LLVMValueRef data_array,
+ LLVMValueRef *colors_out)
{
- LLVMValueRef x0, y0, x1, y1, s_fpart, t_fpart;
- LLVMValueRef lod, ilevel, ilevel_vec;
- LLVMValueRef neighbors[2][2][4];
- LLVMValueRef data_ptr;
+ const unsigned mip_filter = bld->static_state->min_mip_filter;
+ const unsigned min_filter = bld->static_state->min_img_filter;
+ const unsigned mag_filter = bld->static_state->mag_img_filter;
+ const int dims = texture_dims(bld->static_state->target);
+ LLVMValueRef lod, lod_fpart;
+ LLVMValueRef ilevel0, ilevel1, ilevel0_vec, ilevel1_vec;
+ LLVMValueRef width0_vec, height0_vec, depth0_vec;
+ LLVMValueRef width1_vec, height1_vec, depth1_vec;
+ LLVMValueRef row_stride0_vec, row_stride1_vec;
+ LLVMValueRef img_stride0_vec, img_stride1_vec;
+ LLVMValueRef data_ptr0, data_ptr1;
int chan;
- /* compute float LOD */
- lod = lp_build_lod_selector(bld, s, t, NULL, width, height, NULL);
-
- /* convert LOD to int */
- lp_build_nearest_mip_level(bld, unit, lod, &ilevel);
-
- ilevel_vec = lp_build_broadcast_scalar(&bld->int_coord_bld, ilevel);
+ /*
+ printf("%s mip %d min %d mag %d\n", __FUNCTION__,
+ mip_filter, min_filter, mag_filter);
+ */
- /* compute width_vec, height at mipmap level 'ilevel' */
- width_vec = lp_build_minify(bld, width_vec, ilevel_vec);
- height_vec = lp_build_minify(bld, height_vec, ilevel_vec);
- stride = lp_build_minify(bld, stride, ilevel_vec);
+ /*
+ * Compute the level of detail (mipmap level index(es)).
+ */
+ if (mip_filter == PIPE_TEX_MIPFILTER_NONE) {
+ /* always use mip level 0 */
+ ilevel0 = LLVMConstInt(LLVMInt32Type(), 0, 0);
+ }
+ else {
+ /* compute float LOD */
+ lod = lp_build_lod_selector(bld, s, t, r, width, height, depth);
- lp_build_sample_wrap_linear(bld, s, width_vec,
- bld->static_state->pot_width,
- bld->static_state->wrap_s, &x0, &x1, &s_fpart);
- lp_build_sample_wrap_linear(bld, t, height_vec,
- bld->static_state->pot_height,
- bld->static_state->wrap_t, &y0, &y1, &t_fpart);
+ if (mip_filter == PIPE_TEX_MIPFILTER_NEAREST) {
+ lp_build_nearest_mip_level(bld, unit, lod, &ilevel0);
+ }
+ else {
+ assert(mip_filter == PIPE_TEX_MIPFILTER_LINEAR);
+ lp_build_linear_mip_levels(bld, unit, lod, &ilevel0, &ilevel1,
+ &lod_fpart);
+ lod_fpart = lp_build_broadcast_scalar(&bld->coord_bld, lod_fpart);
+ }
+ }
- lp_build_name(x0, "tex.x0.wrapped");
- lp_build_name(y0, "tex.y0.wrapped");
- lp_build_name(x1, "tex.x1.wrapped");
- lp_build_name(y1, "tex.y1.wrapped");
+ /*
+ * Convert scalar integer mipmap levels into vectors.
+ */
+ ilevel0_vec = lp_build_broadcast_scalar(&bld->int_coord_bld, ilevel0);
+ if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR)
+ ilevel1_vec = lp_build_broadcast_scalar(&bld->int_coord_bld, ilevel1);
- /* get pointer to mipmap level [ilevel] data */
- data_ptr = lp_build_get_mipmap_level(bld, data_array, ilevel);
+ /*
+ * Compute width, height at mipmap level 'ilevel0'
+ */
+ width0_vec = lp_build_minify(bld, width_vec, ilevel0_vec);
+ if (dims >= 2) {
+ height0_vec = lp_build_minify(bld, height_vec, ilevel0_vec);
+ row_stride0_vec = lp_build_minify(bld, row_stride_vec, ilevel0_vec);
+ if (dims == 3) {
+ depth0_vec = lp_build_minify(bld, depth_vec, ilevel0_vec);
+ }
+ }
+ if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) {
+ /* compute width, height, depth for second mipmap level at ilevel1 */
+ width1_vec = lp_build_minify(bld, width_vec, ilevel1_vec);
+ if (dims >= 2) {
+ height1_vec = lp_build_minify(bld, height_vec, ilevel1_vec);
+ row_stride1_vec = lp_build_minify(bld, row_stride_vec, ilevel1_vec);
+ if (dims == 3) {
+ depth1_vec = lp_build_minify(bld, depth_vec, ilevel1_vec);
+ }
+ }
+ }
- lp_build_sample_texel_soa(bld, width_vec, height_vec, x0, y0,
- stride, data_ptr, neighbors[0][0]);
- lp_build_sample_texel_soa(bld, width_vec, height_vec, x1, y0,
- stride, data_ptr, neighbors[0][1]);
- lp_build_sample_texel_soa(bld, width_vec, height_vec, x0, y1,
- stride, data_ptr, neighbors[1][0]);
- lp_build_sample_texel_soa(bld, width_vec, height_vec, x1, y1,
- stride, data_ptr, neighbors[1][1]);
+ /*
+ * Choose cube face, recompute texcoords.
+ */
+ if (bld->static_state->target == PIPE_TEXTURE_CUBE) {
- for(chan = 0; chan < 4; ++chan) {
- texel[chan] = lp_build_lerp_2d(&bld->texel_bld,
- s_fpart, t_fpart,
- neighbors[0][0][chan],
- neighbors[0][1][chan],
- neighbors[1][0][chan],
- neighbors[1][1][chan]);
}
-}
+ /*
+ * Get pointer(s) to image data for mipmap level(s).
+ */
+ data_ptr0 = lp_build_get_mipmap_level(bld, data_array, ilevel0);
+ if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) {
+ data_ptr1 = lp_build_get_mipmap_level(bld, data_array, ilevel1);
+ }
-/**
- * Sample 2D texture with bilinear filtering.
- */
-static void
-lp_build_sample_2d_linear_soa(struct lp_build_sample_context *bld,
- LLVMValueRef s,
- LLVMValueRef t,
- LLVMValueRef width,
- LLVMValueRef height,
- LLVMValueRef stride,
- LLVMValueRef data_array,
- LLVMValueRef *texel)
-{
- LLVMValueRef s_fpart;
- LLVMValueRef t_fpart;
- LLVMValueRef x0, x1;
- LLVMValueRef y0, y1;
- LLVMValueRef neighbors[2][2][4];
- LLVMValueRef data_ptr;
- unsigned chan;
+ /*
+ * Get/interpolate texture colors.
+ */
+ /* XXX temporarily force this path: */
+ if (1 /*min_filter == mag_filter*/) {
+ /* same filter for minification or magnification */
+ LLVMValueRef colors0[4], colors1[4];
+
+ if (min_filter == PIPE_TEX_FILTER_NEAREST) {
+ lp_build_sample_image_nearest(bld,
+ width0_vec, height0_vec, depth0_vec,
+ row_stride0_vec, img_stride0_vec,
+ data_ptr0, s, t, r, colors0);
+
+ if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) {
+ /* sample the second mipmap level, and interp */
+ lp_build_sample_image_nearest(bld,
+ width1_vec, height1_vec, depth1_vec,
+ row_stride1_vec, img_stride1_vec,
+ data_ptr1, s, t, r, colors1);
+ }
+ }
+ else {
+ assert(min_filter == PIPE_TEX_FILTER_LINEAR);
- 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);
+ lp_build_sample_image_linear(bld,
+ width0_vec, height0_vec, depth0_vec,
+ row_stride0_vec, img_stride0_vec,
+ data_ptr0, s, t, r, colors0);
- /* get pointer to mipmap level 0 data */
- data_ptr = lp_build_get_const_mipmap_level(bld, data_array, 0);
- 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]);
+ if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) {
+ /* sample the second mipmap level, and interp */
+ lp_build_sample_image_linear(bld,
+ width1_vec, height1_vec, depth1_vec,
+ row_stride1_vec, img_stride1_vec,
+ data_ptr1, s, t, r, colors1);
+ }
+ }
- /* TODO: Don't interpolate missing channels */
- for(chan = 0; chan < 4; ++chan) {
- texel[chan] = lp_build_lerp_2d(&bld->texel_bld,
- s_fpart, t_fpart,
- neighbors[0][0][chan],
- neighbors[0][1][chan],
- neighbors[1][0][chan],
- neighbors[1][1][chan]);
+ if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) {
+ /* interpolate samples from the two mipmap levels */
+ for (chan = 0; chan < 4; chan++) {
+ colors_out[chan] = lp_build_lerp(&bld->texel_bld, lod_fpart,
+ colors0[chan], colors1[chan]);
+ }
+ }
+ else {
+ /* use first/only level's colors */
+ for (chan = 0; chan < 4; chan++) {
+ colors_out[chan] = colors0[chan];
+ }
+ }
+ }
+ else {
+ /* emit conditional to choose min image filter or mag image filter
+ * depending on the lod being >0 or <= 0, respectively.
+ */
+ abort();
}
}
+
static void
lp_build_rgba8_to_f32_soa(LLVMBuilderRef builder,
struct lp_type dst_type,
@@ -1426,12 +1624,12 @@ lp_build_sample_soa(LLVMBuilderRef builder,
struct lp_build_sample_context bld;
LLVMValueRef width, width_vec;
LLVMValueRef height, height_vec;
+ LLVMValueRef depth, depth_vec;
LLVMValueRef stride, stride_vec;
LLVMValueRef data_array;
LLVMValueRef s;
LLVMValueRef t;
LLVMValueRef r;
- boolean done = FALSE;
(void) lp_build_lod_selector; /* temporary to silence warning */
(void) lp_build_nearest_mip_level;
@@ -1462,6 +1660,7 @@ lp_build_sample_soa(LLVMBuilderRef builder,
/* Get the dynamic state */
width = dynamic_state->width(dynamic_state, builder, unit);
height = dynamic_state->height(dynamic_state, builder, unit);
+ depth = dynamic_state->depth(dynamic_state, builder, unit);
stride = dynamic_state->stride(dynamic_state, builder, unit);
data_array = dynamic_state->data_ptr(dynamic_state, builder, unit);
/* Note that data_array is an array[level] of pointers to texture images */
@@ -1472,67 +1671,26 @@ lp_build_sample_soa(LLVMBuilderRef builder,
width_vec = lp_build_broadcast_scalar(&bld.uint_coord_bld, width);
height_vec = lp_build_broadcast_scalar(&bld.uint_coord_bld, height);
+ depth_vec = lp_build_broadcast_scalar(&bld.uint_coord_bld, depth);
stride_vec = lp_build_broadcast_scalar(&bld.uint_coord_bld, stride);
- if(static_state->target == PIPE_TEXTURE_1D)
- t = bld.coord_bld.zero;
-
- switch (static_state->min_mip_filter) {
- case PIPE_TEX_MIPFILTER_NONE:
- break;
- case PIPE_TEX_MIPFILTER_NEAREST:
-
- switch (static_state->min_img_filter) {
- case PIPE_TEX_FILTER_LINEAR:
- lp_build_sample_2d_linear_mip_nearest_soa(&bld, unit,
- s, t,
- width, height,
- width_vec, height_vec,
- stride_vec,
- data_array, texel);
- done = TRUE;
- break;
- case PIPE_TEX_FILTER_NEAREST:
- lp_build_sample_2d_nearest_mip_nearest_soa(&bld, unit,
- s, t,
- width, height,
- width_vec, height_vec,
- stride_vec,
- data_array, texel);
- done = TRUE;
- break;
- }
-
- break;
- case PIPE_TEX_MIPFILTER_LINEAR:
- break;
- default:
- assert(0 && "invalid mip filter");
+ if (lp_format_is_rgba8(bld.format_desc) &&
+ static_state->min_img_filter == PIPE_TEX_FILTER_LINEAR &&
+ static_state->mag_img_filter == PIPE_TEX_FILTER_LINEAR &&
+ static_state->min_mip_filter == PIPE_TEX_MIPFILTER_NONE &&
+ is_simple_wrap_mode(static_state->wrap_s) &&
+ is_simple_wrap_mode(static_state->wrap_t)) {
+ /* special case */
+ lp_build_sample_2d_linear_aos(&bld, s, t, width_vec, height_vec,
+ stride_vec, data_array, texel);
}
-
- if (!done) {
- switch (static_state->min_img_filter) {
- case PIPE_TEX_FILTER_NEAREST:
- lp_build_sample_2d_nearest_soa(&bld, s, t, width_vec, height_vec,
- stride_vec, data_array, texel);
- break;
- case PIPE_TEX_FILTER_LINEAR:
- 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_vec, height_vec,
- stride_vec, data_array, texel);
- else
- lp_build_sample_2d_linear_soa(&bld, s, t, width_vec, height_vec,
- stride_vec, data_array, texel);
- break;
- default:
- assert(0);
- }
+ else {
+ lp_build_sample_general(&bld, unit, s, t, r,
+ width, height, depth,
+ width_vec, height_vec, depth_vec,
+ stride_vec, NULL, data_array,
+ texel);
}
- /* FIXME: respect static_state->min_mip_filter */;
- /* FIXME: respect static_state->mag_img_filter */;
-
lp_build_sample_compare(&bld, r, texel);
}