summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/softpipe
diff options
context:
space:
mode:
authorBrian Paul <brianp@vmware.com>2011-01-25 20:27:10 -0700
committerBrian Paul <brianp@vmware.com>2011-01-25 20:27:10 -0700
commit779e9cb658dba4ef44fae7e8aa62409f7227f46c (patch)
tree2ef0ef43f345ea86f00fda5762b2b43f0c1c65f4 /src/gallium/drivers/softpipe
parent9b56a2cb626b254bcb7b7202e6babd1b5570208f (diff)
softpipe: support for 1D/2D texture arrays
Diffstat (limited to 'src/gallium/drivers/softpipe')
-rw-r--r--src/gallium/drivers/softpipe/sp_screen.c4
-rw-r--r--src/gallium/drivers/softpipe/sp_tex_sample.c201
-rw-r--r--src/gallium/drivers/softpipe/sp_texture.c6
3 files changed, 210 insertions, 1 deletions
diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c
index e19f2e6fc7..6d47fb9628 100644
--- a/src/gallium/drivers/softpipe/sp_screen.c
+++ b/src/gallium/drivers/softpipe/sp_screen.c
@@ -125,6 +125,8 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
return 1;
case PIPE_CAP_INSTANCED_DRAWING:
return 1;
+ case PIPE_CAP_ARRAY_TEXTURES:
+ return 1;
default:
return 0;
}
@@ -185,7 +187,9 @@ softpipe_is_format_supported( struct pipe_screen *screen,
assert(target == PIPE_BUFFER ||
target == PIPE_TEXTURE_1D ||
+ target == PIPE_TEXTURE_1D_ARRAY ||
target == PIPE_TEXTURE_2D ||
+ target == PIPE_TEXTURE_2D_ARRAY ||
target == PIPE_TEXTURE_RECT ||
target == PIPE_TEXTURE_3D ||
target == PIPE_TEXTURE_CUBE);
diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.c b/src/gallium/drivers/softpipe/sp_tex_sample.c
index 242c27c7eb..15f7eb2b94 100644
--- a/src/gallium/drivers/softpipe/sp_tex_sample.c
+++ b/src/gallium/drivers/softpipe/sp_tex_sample.c
@@ -539,6 +539,19 @@ wrap_linear_unorm_clamp_to_edge(const float s[4], unsigned size,
}
+/**
+ * Do coordinate to array index conversion. For array textures.
+ */
+static INLINE void
+wrap_array_layer(const float coord[4], unsigned size, int layer[4])
+{
+ uint ch;
+ for (ch = 0; ch < 4; ch++) {
+ int c = util_ifloor(coord[ch] + 0.5F);
+ layer[ch] = CLAMP(c, 0, size - 1);
+ }
+}
+
/**
* Examine the quad's texture coordinates to compute the partial
@@ -990,6 +1003,47 @@ img_filter_1d_nearest(struct tgsi_sampler *tgsi_sampler,
static void
+img_filter_1d_array_nearest(struct tgsi_sampler *tgsi_sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ const float c0[QUAD_SIZE],
+ enum tgsi_sampler_control control,
+ float rgba[NUM_CHANNELS][QUAD_SIZE])
+{
+ const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler);
+ const struct pipe_resource *texture = samp->view->texture;
+ unsigned level0, j;
+ int width;
+ int x[4], layer[4];
+ union tex_tile_address addr;
+
+ level0 = samp->level;
+ width = u_minify(texture->width0, level0);
+
+ assert(width > 0);
+
+ addr.value = 0;
+ addr.bits.level = samp->level;
+
+ samp->nearest_texcoord_s(s, width, x);
+ wrap_array_layer(t, texture->height0, layer);
+
+ for (j = 0; j < QUAD_SIZE; j++) {
+ const float *out = get_texel_2d(samp, addr, x[j], layer[j]);
+ int c;
+ for (c = 0; c < 4; c++) {
+ rgba[c][j] = out[c];
+ }
+ }
+
+ if (DEBUG_TEX) {
+ print_sample(__FUNCTION__, rgba);
+ }
+}
+
+
+static void
img_filter_2d_nearest(struct tgsi_sampler *tgsi_sampler,
const float s[QUAD_SIZE],
const float t[QUAD_SIZE],
@@ -1033,6 +1087,50 @@ img_filter_2d_nearest(struct tgsi_sampler *tgsi_sampler,
}
+static void
+img_filter_2d_array_nearest(struct tgsi_sampler *tgsi_sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ const float c0[QUAD_SIZE],
+ enum tgsi_sampler_control control,
+ float rgba[NUM_CHANNELS][QUAD_SIZE])
+{
+ const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler);
+ const struct pipe_resource *texture = samp->view->texture;
+ unsigned level0, j;
+ int width, height;
+ int x[4], y[4], layer[4];
+ union tex_tile_address addr;
+
+ level0 = samp->level;
+ width = u_minify(texture->width0, level0);
+ height = u_minify(texture->height0, level0);
+
+ assert(width > 0);
+ assert(height > 0);
+
+ addr.value = 0;
+ addr.bits.level = samp->level;
+
+ samp->nearest_texcoord_s(s, width, x);
+ samp->nearest_texcoord_t(t, height, y);
+ wrap_array_layer(p, texture->depth0, layer);
+
+ for (j = 0; j < QUAD_SIZE; j++) {
+ const float *out = get_texel_3d(samp, addr, x[j], y[j], layer[j]);
+ int c;
+ for (c = 0; c < 4; c++) {
+ rgba[c][j] = out[c];
+ }
+ }
+
+ if (DEBUG_TEX) {
+ print_sample(__FUNCTION__, rgba);
+ }
+}
+
+
static INLINE union tex_tile_address
face(union tex_tile_address addr, unsigned face )
{
@@ -1168,6 +1266,47 @@ img_filter_1d_linear(struct tgsi_sampler *tgsi_sampler,
static void
+img_filter_1d_array_linear(struct tgsi_sampler *tgsi_sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ const float c0[QUAD_SIZE],
+ enum tgsi_sampler_control control,
+ float rgba[NUM_CHANNELS][QUAD_SIZE])
+{
+ const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler);
+ const struct pipe_resource *texture = samp->view->texture;
+ unsigned level0, j;
+ int width;
+ int x0[4], x1[4], layer[4];
+ float xw[4]; /* weights */
+ union tex_tile_address addr;
+
+ level0 = samp->level;
+ width = u_minify(texture->width0, level0);
+
+ assert(width > 0);
+
+ addr.value = 0;
+ addr.bits.level = samp->level;
+
+ samp->linear_texcoord_s(s, width, x0, x1, xw);
+ wrap_array_layer(t, texture->height0, layer);
+
+ for (j = 0; j < QUAD_SIZE; j++) {
+ const float *tx0 = get_texel_2d(samp, addr, x0[j], layer[j]);
+ const float *tx1 = get_texel_2d(samp, addr, x1[j], layer[j]);
+ int c;
+
+ /* interpolate R, G, B, A */
+ for (c = 0; c < 4; c++) {
+ rgba[c][j] = lerp(xw[j], tx0[c], tx1[c]);
+ }
+ }
+}
+
+
+static void
img_filter_2d_linear(struct tgsi_sampler *tgsi_sampler,
const float s[QUAD_SIZE],
const float t[QUAD_SIZE],
@@ -1215,6 +1354,54 @@ img_filter_2d_linear(struct tgsi_sampler *tgsi_sampler,
static void
+img_filter_2d_array_linear(struct tgsi_sampler *tgsi_sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ const float c0[QUAD_SIZE],
+ enum tgsi_sampler_control control,
+ float rgba[NUM_CHANNELS][QUAD_SIZE])
+{
+ const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler);
+ const struct pipe_resource *texture = samp->view->texture;
+ unsigned level0, j;
+ int width, height;
+ int x0[4], y0[4], x1[4], y1[4], layer[4];
+ float xw[4], yw[4]; /* weights */
+ union tex_tile_address addr;
+
+ level0 = samp->level;
+ width = u_minify(texture->width0, level0);
+ height = u_minify(texture->height0, level0);
+
+ assert(width > 0);
+ assert(height > 0);
+
+ addr.value = 0;
+ addr.bits.level = samp->level;
+
+ samp->linear_texcoord_s(s, width, x0, x1, xw);
+ samp->linear_texcoord_t(t, height, y0, y1, yw);
+ wrap_array_layer(p, texture->depth0, layer);
+
+ for (j = 0; j < QUAD_SIZE; j++) {
+ const float *tx0 = get_texel_3d(samp, addr, x0[j], y0[j], layer[j]);
+ const float *tx1 = get_texel_3d(samp, addr, x1[j], y0[j], layer[j]);
+ const float *tx2 = get_texel_3d(samp, addr, x0[j], y1[j], layer[j]);
+ const float *tx3 = get_texel_3d(samp, addr, x1[j], y1[j], layer[j]);
+ int c;
+
+ /* interpolate R, G, B, A */
+ for (c = 0; c < 4; c++) {
+ rgba[c][j] = lerp_2d(xw[j], yw[j],
+ tx0[c], tx1[c],
+ tx2[c], tx3[c]);
+ }
+ }
+}
+
+
+static void
img_filter_cube_linear(struct tgsi_sampler *tgsi_sampler,
const float s[QUAD_SIZE],
const float t[QUAD_SIZE],
@@ -1906,8 +2093,10 @@ get_lambda_func(const union sp_sampler_key key)
switch (key.bits.target) {
case PIPE_TEXTURE_1D:
+ case PIPE_TEXTURE_1D_ARRAY:
return compute_lambda_1d;
case PIPE_TEXTURE_2D:
+ case PIPE_TEXTURE_2D_ARRAY:
case PIPE_TEXTURE_RECT:
case PIPE_TEXTURE_CUBE:
return compute_lambda_2d;
@@ -1932,6 +2121,12 @@ get_img_filter(const union sp_sampler_key key,
else
return img_filter_1d_linear;
break;
+ case PIPE_TEXTURE_1D_ARRAY:
+ if (filter == PIPE_TEX_FILTER_NEAREST)
+ return img_filter_1d_array_nearest;
+ else
+ return img_filter_1d_array_linear;
+ break;
case PIPE_TEXTURE_2D:
case PIPE_TEXTURE_RECT:
/* Try for fast path:
@@ -1967,6 +2162,12 @@ get_img_filter(const union sp_sampler_key key,
else
return img_filter_2d_linear;
break;
+ case PIPE_TEXTURE_2D_ARRAY:
+ if (filter == PIPE_TEX_FILTER_NEAREST)
+ return img_filter_2d_array_nearest;
+ else
+ return img_filter_2d_array_linear;
+ break;
case PIPE_TEXTURE_CUBE:
if (filter == PIPE_TEX_FILTER_NEAREST)
return img_filter_cube_nearest;
diff --git a/src/gallium/drivers/softpipe/sp_texture.c b/src/gallium/drivers/softpipe/sp_texture.c
index 509d9982b1..2daed2022e 100644
--- a/src/gallium/drivers/softpipe/sp_texture.c
+++ b/src/gallium/drivers/softpipe/sp_texture.c
@@ -227,9 +227,13 @@ sp_get_tex_image_offset(const struct softpipe_resource *spr,
unsigned offset = spr->level_offset[level];
if (spr->base.target == PIPE_TEXTURE_CUBE ||
- spr->base.target == PIPE_TEXTURE_3D) {
+ spr->base.target == PIPE_TEXTURE_3D ||
+ spr->base.target == PIPE_TEXTURE_2D_ARRAY) {
offset += layer * nblocksy * spr->stride[level];
}
+ else if (spr->base.target == PIPE_TEXTURE_1D_ARRAY) {
+ offset += layer * spr->stride[level];
+ }
else {
assert(layer == 0);
}