diff options
Diffstat (limited to 'src/gallium/drivers/softpipe/sp_state_sampler.c')
-rw-r--r-- | src/gallium/drivers/softpipe/sp_state_sampler.c | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/src/gallium/drivers/softpipe/sp_state_sampler.c b/src/gallium/drivers/softpipe/sp_state_sampler.c index e51241892e1..e56fb5b1485 100644 --- a/src/gallium/drivers/softpipe/sp_state_sampler.c +++ b/src/gallium/drivers/softpipe/sp_state_sampler.c @@ -31,6 +31,7 @@ #include "util/u_memory.h" #include "util/u_inlines.h" +#include "util/u_format.h" #include "draw/draw_context.h" @@ -39,6 +40,8 @@ #include "sp_texture.h" #include "sp_tex_sample.h" #include "sp_tex_tile_cache.h" +#include "sp_screen.h" +#include "state_tracker/sw_winsys.h" /** @@ -159,6 +162,159 @@ softpipe_delete_sampler_state(struct pipe_context *pipe, } +static void +prepare_shader_sampling( + struct softpipe_context *sp, + unsigned num, + struct pipe_sampler_view **views, + unsigned shader_type, + struct pipe_resource *mapped_tex[PIPE_MAX_SHADER_SAMPLER_VIEWS]) +{ + + unsigned i; + uint32_t row_stride[PIPE_MAX_TEXTURE_LEVELS]; + uint32_t img_stride[PIPE_MAX_TEXTURE_LEVELS]; + uint32_t mip_offsets[PIPE_MAX_TEXTURE_LEVELS]; + const void *addr; + + assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS); + if (!num) + return; + + for (i = 0; i < PIPE_MAX_SHADER_SAMPLER_VIEWS; i++) { + struct pipe_sampler_view *view = i < num ? views[i] : NULL; + + if (view) { + struct pipe_resource *tex = view->texture; + struct softpipe_resource *sp_tex = softpipe_resource(tex); + unsigned width0 = tex->width0; + unsigned num_layers = tex->depth0; + unsigned first_level = 0; + unsigned last_level = 0; + + /* We're referencing the texture's internal data, so save a + * reference to it. + */ + pipe_resource_reference(&mapped_tex[i], tex); + + if (!sp_tex->dt) { + /* regular texture - setup array of mipmap level offsets */ + struct pipe_resource *res = view->texture; + int j; + + if (res->target != PIPE_BUFFER) { + first_level = view->u.tex.first_level; + last_level = view->u.tex.last_level; + assert(first_level <= last_level); + assert(last_level <= res->last_level); + addr = sp_tex->data; + + for (j = first_level; j <= last_level; j++) { + mip_offsets[j] = sp_tex->level_offset[j]; + row_stride[j] = sp_tex->stride[j]; + img_stride[j] = sp_tex->img_stride[j]; + } + if (res->target == PIPE_TEXTURE_1D_ARRAY || + res->target == PIPE_TEXTURE_2D_ARRAY || + res->target == PIPE_TEXTURE_CUBE_ARRAY) { + num_layers = view->u.tex.last_layer - view->u.tex.first_layer + 1; + for (j = first_level; j <= last_level; j++) { + mip_offsets[j] += view->u.tex.first_layer * + sp_tex->img_stride[j]; + } + if (res->target == PIPE_TEXTURE_CUBE_ARRAY) { + assert(num_layers % 6 == 0); + } + assert(view->u.tex.first_layer <= view->u.tex.last_layer); + assert(view->u.tex.last_layer < res->array_size); + } + } + else { + unsigned view_blocksize = util_format_get_blocksize(view->format); + addr = sp_tex->data; + /* probably don't really need to fill that out */ + mip_offsets[0] = 0; + row_stride[0] = 0; + img_stride[0] = 0; + + /* everything specified in number of elements here. */ + width0 = view->u.buf.last_element - view->u.buf.first_element + 1; + addr = (uint8_t *)addr + view->u.buf.first_element * + view_blocksize; + assert(view->u.buf.first_element <= view->u.buf.last_element); + assert(view->u.buf.last_element * view_blocksize < res->width0); + } + } + else { + /* display target texture/surface */ + /* + * XXX: Where should this be unmapped? + */ + struct softpipe_screen *screen = softpipe_screen(tex->screen); + struct sw_winsys *winsys = screen->winsys; + addr = winsys->displaytarget_map(winsys, sp_tex->dt, + PIPE_TRANSFER_READ); + row_stride[0] = sp_tex->stride[0]; + img_stride[0] = sp_tex->img_stride[0]; + mip_offsets[0] = 0; + assert(addr); + } + draw_set_mapped_texture(sp->draw, + shader_type, + i, + width0, tex->height0, num_layers, + first_level, last_level, + addr, + row_stride, img_stride, mip_offsets); + } + } +} + + +/** + * Called during state validation when SP_NEW_TEXTURE is set. + */ +void +softpipe_prepare_vertex_sampling(struct softpipe_context *sp, + unsigned num, + struct pipe_sampler_view **views) +{ + prepare_shader_sampling(sp, num, views, PIPE_SHADER_VERTEX, + sp->mapped_vs_tex); +} + +void +softpipe_cleanup_vertex_sampling(struct softpipe_context *ctx) +{ + unsigned i; + for (i = 0; i < Elements(ctx->mapped_vs_tex); i++) { + pipe_resource_reference(&ctx->mapped_vs_tex[i], NULL); + } +} + + +/** + * Called during state validation when SP_NEW_TEXTURE is set. + */ +void +softpipe_prepare_geometry_sampling(struct softpipe_context *sp, + unsigned num, + struct pipe_sampler_view **views) +{ + prepare_shader_sampling(sp, num, views, PIPE_SHADER_GEOMETRY, + sp->mapped_gs_tex); +} + +void +softpipe_cleanup_geometry_sampling(struct softpipe_context *ctx) +{ + unsigned i; + for (i = 0; i < Elements(ctx->mapped_gs_tex); i++) { + pipe_resource_reference(&ctx->mapped_gs_tex[i], NULL); + } +} + + void softpipe_init_sampler_funcs(struct pipe_context *pipe) { |