diff options
Diffstat (limited to 'src/gallium')
-rw-r--r-- | src/gallium/drivers/softpipe/sp_tex_sample.c | 45 |
1 files changed, 31 insertions, 14 deletions
diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.c b/src/gallium/drivers/softpipe/sp_tex_sample.c index d54e02e40cd..83d9be8a024 100644 --- a/src/gallium/drivers/softpipe/sp_tex_sample.c +++ b/src/gallium/drivers/softpipe/sp_tex_sample.c @@ -799,7 +799,8 @@ get_texel_2d_array(const struct sp_sampler_variant *samp, const struct pipe_resource *texture = samp->view->texture; unsigned level = addr.bits.level; - assert(layer < texture->array_size); + assert(layer < (int) texture->array_size); + assert(layer >= 0); if (x < 0 || x >= (int) u_minify(texture->width0, level) || y < 0 || y >= (int) u_minify(texture->height0, level)) { @@ -2630,8 +2631,12 @@ sample_get_dims(struct tgsi_sampler *tgsi_sampler, int level, } } -/* this function is only used for unfiltered texel gets - via the TGSI TXF opcode. */ +/** + * This function is only used for getting unfiltered texels via the + * TXF opcode. The GL spec says that out-of-bounds texel fetches + * produce undefined results. Instead of crashing, lets just clamp + * coords to the texture image size. + */ static void sample_get_texels(struct tgsi_sampler *tgsi_sampler, const int v_i[TGSI_QUAD_SIZE], @@ -2650,15 +2655,22 @@ sample_get_texels(struct tgsi_sampler *tgsi_sampler, samp->key.bits.swizzle_g != PIPE_SWIZZLE_GREEN || samp->key.bits.swizzle_b != PIPE_SWIZZLE_BLUE || samp->key.bits.swizzle_a != PIPE_SWIZZLE_ALPHA); + int width, height, depth, layers; addr.value = 0; /* TODO write a better test for LOD */ addr.bits.level = lod[0]; + width = u_minify(texture->width0, addr.bits.level); + height = u_minify(texture->height0, addr.bits.level); + depth = u_minify(texture->depth0, addr.bits.level); + layers = texture->array_size; + switch(texture->target) { case PIPE_TEXTURE_1D: for (j = 0; j < TGSI_QUAD_SIZE; j++) { - tx = get_texel_2d(samp, addr, v_i[j] + offset[0], 0); + int x = CLAMP(v_i[j] + offset[0], 0, width - 1); + tx = get_texel_2d(samp, addr, x, 0); for (c = 0; c < 4; c++) { rgba[c][j] = tx[c]; } @@ -2666,8 +2678,9 @@ sample_get_texels(struct tgsi_sampler *tgsi_sampler, break; case PIPE_TEXTURE_1D_ARRAY: for (j = 0; j < TGSI_QUAD_SIZE; j++) { - tx = get_texel_1d_array(samp, addr, v_i[j] + offset[0], - v_j[j] + offset[1]); + int x = CLAMP(v_i[j] + offset[0], 0, width - 1); + int y = CLAMP(v_j[j] + offset[1], 0, layers - 1); + tx = get_texel_1d_array(samp, addr, x, y); for (c = 0; c < 4; c++) { rgba[c][j] = tx[c]; } @@ -2676,8 +2689,9 @@ sample_get_texels(struct tgsi_sampler *tgsi_sampler, case PIPE_TEXTURE_2D: case PIPE_TEXTURE_RECT: for (j = 0; j < TGSI_QUAD_SIZE; j++) { - tx = get_texel_2d(samp, addr, v_i[j] + offset[0], - v_j[j] + offset[1]); + int x = CLAMP(v_i[j] + offset[0], 0, width - 1); + int y = CLAMP(v_j[j] + offset[1], 0, height - 1); + tx = get_texel_2d(samp, addr, x, y); for (c = 0; c < 4; c++) { rgba[c][j] = tx[c]; } @@ -2685,9 +2699,10 @@ sample_get_texels(struct tgsi_sampler *tgsi_sampler, break; case PIPE_TEXTURE_2D_ARRAY: for (j = 0; j < TGSI_QUAD_SIZE; j++) { - tx = get_texel_2d_array(samp, addr, v_i[j] + offset[0], - v_j[j] + offset[1], - v_k[j] + offset[2]); + int x = CLAMP(v_i[j] + offset[0], 0, width - 1); + int y = CLAMP(v_j[j] + offset[1], 0, height - 1); + int layer = CLAMP(v_k[j] + offset[2], 0, layers - 1); + tx = get_texel_2d_array(samp, addr, x, y, layer); for (c = 0; c < 4; c++) { rgba[c][j] = tx[c]; } @@ -2695,9 +2710,11 @@ sample_get_texels(struct tgsi_sampler *tgsi_sampler, break; case PIPE_TEXTURE_3D: for (j = 0; j < TGSI_QUAD_SIZE; j++) { - tx = get_texel_3d(samp, addr, v_i[j] + offset[0], - v_j[j] + offset[1], - v_k[j] + offset[2]); + int x = CLAMP(v_i[j] + offset[0], 0, width - 1); + int y = CLAMP(v_j[j] + offset[1], 0, height - 1); + int z = CLAMP(v_k[j] + offset[2], 0, depth - 1); + + tx = get_texel_3d(samp, addr, x, y, z); for (c = 0; c < 4; c++) { rgba[c][j] = tx[c]; } |