X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fsvga%2Fsvga_state_tss.c;h=0ab571c05881992422a59d5733784bb63e88e0dd;hb=13862812dc910a4ef57cb72cb9fe777ce3c14515;hp=b3137945202add4bccbae2270365d8675ba4d8ff;hpb=b57abd3bea29e95e5dee2524c3f1be4b26017c0f;p=mesa.git diff --git a/src/gallium/drivers/svga/svga_state_tss.c b/src/gallium/drivers/svga/svga_state_tss.c index b3137945202..0ab571c0588 100644 --- a/src/gallium/drivers/svga/svga_state_tss.c +++ b/src/gallium/drivers/svga/svga_state_tss.c @@ -23,101 +23,113 @@ * **********************************************************/ -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" +#include "util/u_memory.h" #include "pipe/p_defines.h" #include "util/u_math.h" -#include "svga_screen_texture.h" +#include "svga_sampler_view.h" #include "svga_winsys.h" #include "svga_context.h" #include "svga_state.h" #include "svga_cmd.h" -#include "svga_hw_reg.h" - void svga_cleanup_tss_binding(struct svga_context *svga) { - int i; - unsigned count = MAX2( svga->curr.num_textures, + unsigned i; + unsigned count = MAX2( svga->curr.num_sampler_views, svga->state.hw_draw.num_views ); for (i = 0; i < count; i++) { struct svga_hw_view_state *view = &svga->state.hw_draw.views[i]; svga_sampler_view_reference(&view->v, NULL); - pipe_texture_reference( &svga->curr.texture[i], NULL ); - pipe_texture_reference( &view->texture, NULL ); + pipe_sampler_view_release(&svga->pipe, &svga->curr.sampler_views[i]); + pipe_resource_reference( &view->texture, NULL ); view->dirty = 1; } } -static int +struct bind_queue { + struct { + unsigned unit; + struct svga_hw_view_state *view; + } bind[PIPE_MAX_SAMPLERS]; + + unsigned bind_count; +}; + + +static enum pipe_error update_tss_binding(struct svga_context *svga, unsigned dirty ) { + boolean reemit = svga->rebind.texture_samplers; unsigned i; - unsigned count = MAX2( svga->curr.num_textures, + unsigned count = MAX2( svga->curr.num_sampler_views, svga->state.hw_draw.num_views ); unsigned min_lod; unsigned max_lod; - - struct { - struct { - unsigned unit; - struct svga_hw_view_state *view; - } bind[PIPE_MAX_SAMPLERS]; - - unsigned bind_count; - } queue; + struct bind_queue queue; queue.bind_count = 0; for (i = 0; i < count; i++) { const struct svga_sampler_state *s = svga->curr.sampler[i]; struct svga_hw_view_state *view = &svga->state.hw_draw.views[i]; + struct pipe_resource *texture = NULL; + struct pipe_sampler_view *sv = svga->curr.sampler_views[i]; /* get min max lod */ - if (svga->curr.texture[i]) { - min_lod = MAX2(s->view_min_lod, 0); - max_lod = MIN2(s->view_max_lod, svga->curr.texture[i]->last_level); + if (sv && s) { + min_lod = MAX2(0, (s->view_min_lod + sv->u.tex.first_level)); + max_lod = MIN2(s->view_max_lod + sv->u.tex.first_level, + sv->texture->last_level); + texture = sv->texture; } else { min_lod = 0; max_lod = 0; } - if (view->texture != svga->curr.texture[i] || + if (view->texture != texture || view->min_lod != min_lod || view->max_lod != max_lod) { svga_sampler_view_reference(&view->v, NULL); - pipe_texture_reference( &view->texture, svga->curr.texture[i] ); + pipe_resource_reference( &view->texture, texture ); view->dirty = TRUE; view->min_lod = min_lod; view->max_lod = max_lod; - if (svga->curr.texture[i]) + if (texture) view->v = svga_get_tex_sampler_view(&svga->pipe, - svga->curr.texture[i], + texture, min_lod, max_lod); } - if (view->dirty) { + /* + * We need to reemit non-null texture bindings, even when they are not + * dirty, to ensure that the resources are paged in. + */ + + if (view->dirty || + (reemit && view->v)) { queue.bind[queue.bind_count].unit = i; queue.bind[queue.bind_count].view = view; queue.bind_count++; } - else if (view->v) { + if (!view->dirty && view->v) { svga_validate_sampler_view(svga, view->v); } } - svga->state.hw_draw.num_views = svga->curr.num_textures; + svga->state.hw_draw.num_views = svga->curr.num_sampler_views; if (queue.bind_count) { SVGA3dTextureState *ts; @@ -128,18 +140,22 @@ update_tss_binding(struct svga_context *svga, goto fail; for (i = 0; i < queue.bind_count; i++) { + struct svga_winsys_surface *handle; + ts[i].stage = queue.bind[i].unit; ts[i].name = SVGA3D_TS_BIND_TEXTURE; if (queue.bind[i].view->v) { - svga->swc->surface_relocation(svga->swc, - &ts[i].value, - queue.bind[i].view->v->handle, - PIPE_BUFFER_USAGE_GPU_READ); + handle = queue.bind[i].view->v->handle; } else { - ts[i].value = SVGA3D_INVALID_ID; + handle = NULL; } + svga->swc->surface_relocation(svga->swc, + &ts[i].value, + NULL, + handle, + SVGA_RELOC_READ); queue.bind[i].view->dirty = FALSE; } @@ -147,13 +163,78 @@ update_tss_binding(struct svga_context *svga, SVGA_FIFOCommitAll( svga->swc ); } - return 0; + svga->rebind.texture_samplers = FALSE; + + return PIPE_OK; fail: return PIPE_ERROR_OUT_OF_MEMORY; } +/* + * Rebind textures. + * + * Similar to update_tss_binding, but without any state checking/update. + * + * Called at the beginning of every new command buffer to ensure that + * non-dirty textures are properly paged-in. + */ +enum pipe_error +svga_reemit_tss_bindings(struct svga_context *svga) +{ + unsigned i; + enum pipe_error ret; + struct bind_queue queue; + + assert(svga->rebind.texture_samplers); + + queue.bind_count = 0; + + for (i = 0; i < svga->state.hw_draw.num_views; i++) { + struct svga_hw_view_state *view = &svga->state.hw_draw.views[i]; + + if (view->v) { + queue.bind[queue.bind_count].unit = i; + queue.bind[queue.bind_count].view = view; + queue.bind_count++; + } + } + + if (queue.bind_count) { + SVGA3dTextureState *ts; + + ret = SVGA3D_BeginSetTextureState(svga->swc, + &ts, + queue.bind_count); + if (ret != PIPE_OK) { + return ret; + } + + for (i = 0; i < queue.bind_count; i++) { + struct svga_winsys_surface *handle; + + ts[i].stage = queue.bind[i].unit; + ts[i].name = SVGA3D_TS_BIND_TEXTURE; + + assert(queue.bind[i].view->v); + handle = queue.bind[i].view->v->handle; + svga->swc->surface_relocation(svga->swc, + &ts[i].value, + NULL, + handle, + SVGA_RELOC_READ); + } + + SVGA_FIFOCommitAll(svga->swc); + } + + svga->rebind.texture_samplers = FALSE; + + return PIPE_OK; +} + + struct svga_tracked_state svga_hw_tss_binding = { "texture binding emit", SVGA_NEW_TEXTURE_BINDING | @@ -173,6 +254,8 @@ struct ts_queue { #define EMIT_TS(svga, unit, val, token, fail) \ do { \ + assert(unit < Elements(svga->state.hw_draw.ts)); \ + assert(SVGA3D_TS_##token < Elements(svga->state.hw_draw.ts[unit])); \ if (svga->state.hw_draw.ts[unit][SVGA3D_TS_##token] != val) { \ svga_queue_tss( &queue, unit, SVGA3D_TS_##token, val ); \ svga->state.hw_draw.ts[unit][SVGA3D_TS_##token] = val; \ @@ -182,6 +265,8 @@ do { \ #define EMIT_TS_FLOAT(svga, unit, fvalue, token, fail) \ do { \ unsigned val = fui(fvalue); \ + assert(unit < Elements(svga->state.hw_draw.ts)); \ + assert(SVGA3D_TS_##token < Elements(svga->state.hw_draw.ts[unit])); \ if (svga->state.hw_draw.ts[unit][SVGA3D_TS_##token] != val) { \ svga_queue_tss( &queue, unit, SVGA3D_TS_##token, val ); \ svga->state.hw_draw.ts[unit][SVGA3D_TS_##token] = val; \ @@ -203,7 +288,7 @@ svga_queue_tss( struct ts_queue *q, } -static int +static enum pipe_error update_tss(struct svga_context *svga, unsigned dirty ) { @@ -227,7 +312,6 @@ update_tss(struct svga_context *svga, // TEXCOORDINDEX -- hopefully not needed if (svga->curr.tex_flags.flag_1d & (1 << i)) { - debug_printf("wrap 1d tex %d\n", i); EMIT_TS(svga, i, SVGA3D_TEX_ADDRESS_WRAP, ADDRESSV, fail); } else @@ -256,7 +340,7 @@ update_tss(struct svga_context *svga, SVGA_FIFOCommitAll( svga->swc ); } - return 0; + return PIPE_OK; fail: /* XXX: need to poison cached hardware state on failure to ensure