X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fauxiliary%2Fcso_cache%2Fcso_context.c;h=9ec7a2a9676108fbf0c9254b059d3966761da4e9;hb=76eefcc70cc62db7d226591de3f918ff102f6de3;hp=6d0b42079866604460ae057d5530d506728a33f5;hpb=6fc532ae05352a5540c658580cde08b1e0e9f84c;p=mesa.git diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c index 6d0b4207986..9ec7a2a9676 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.c +++ b/src/gallium/auxiliary/cso_cache/cso_context.c @@ -36,6 +36,8 @@ */ #include "pipe/p_state.h" +#include "util/u_draw.h" +#include "util/u_framebuffer.h" #include "util/u_inlines.h" #include "util/u_math.h" #include "util/u_memory.h" @@ -46,41 +48,54 @@ #include "cso_cache/cso_hash.h" #include "cso_context.h" -struct cso_context { - struct pipe_context *pipe; - struct cso_cache *cache; +/** + * Info related to samplers and sampler views. + * We have one of these for fragment samplers and another for vertex samplers. + */ +struct sampler_info +{ struct { void *samplers[PIPE_MAX_SAMPLERS]; unsigned nr_samplers; - - void *vertex_samplers[PIPE_MAX_VERTEX_SAMPLERS]; - unsigned nr_vertex_samplers; } hw; void *samplers[PIPE_MAX_SAMPLERS]; unsigned nr_samplers; - void *vertex_samplers[PIPE_MAX_VERTEX_SAMPLERS]; - unsigned nr_vertex_samplers; - - unsigned nr_samplers_saved; void *samplers_saved[PIPE_MAX_SAMPLERS]; + unsigned nr_samplers_saved; + + struct pipe_sampler_view *views[PIPE_MAX_SAMPLERS]; + unsigned nr_views; + + struct pipe_sampler_view *views_saved[PIPE_MAX_SAMPLERS]; + unsigned nr_views_saved; +}; + + + +struct cso_context { + struct pipe_context *pipe; + struct cso_cache *cache; + + boolean has_geometry_shader; + boolean has_streamout; - unsigned nr_vertex_samplers_saved; - void *vertex_samplers_saved[PIPE_MAX_VERTEX_SAMPLERS]; + struct sampler_info fragment_samplers; + struct sampler_info vertex_samplers; - uint nr_fragment_sampler_views; - struct pipe_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS]; + uint nr_vertex_buffers; + struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS]; - uint nr_vertex_sampler_views; - struct pipe_sampler_view *vertex_sampler_views[PIPE_MAX_VERTEX_SAMPLERS]; + uint nr_vertex_buffers_saved; + struct pipe_vertex_buffer vertex_buffers_saved[PIPE_MAX_ATTRIBS]; - uint nr_fragment_sampler_views_saved; - struct pipe_sampler_view *fragment_sampler_views_saved[PIPE_MAX_SAMPLERS]; + unsigned nr_so_targets; + struct pipe_stream_output_target *so_targets[PIPE_MAX_SO_BUFFERS]; - uint nr_vertex_sampler_views_saved; - struct pipe_sampler_view *vertex_sampler_views_saved[PIPE_MAX_VERTEX_SAMPLERS]; + unsigned nr_so_targets_saved; + struct pipe_stream_output_target *so_targets_saved[PIPE_MAX_SO_BUFFERS]; /** Current and saved state. * The saved state is used as a 1-deep stack. @@ -98,14 +113,11 @@ struct cso_context { struct pipe_framebuffer_state fb, fb_saved; struct pipe_viewport_state vp, vp_saved; struct pipe_blend_color blend_color; + unsigned sample_mask; struct pipe_stencil_ref stencil_ref, stencil_ref_saved; }; -static void -free_framebuffer_state(struct pipe_framebuffer_state *fb); - - static boolean delete_blend_state(struct cso_context *ctx, void *state) { struct cso_blend *cso = (struct cso_blend *)state; @@ -154,28 +166,6 @@ static boolean delete_rasterizer_state(struct cso_context *ctx, void *state) return TRUE; } -static boolean delete_fs_state(struct cso_context *ctx, void *state) -{ - struct cso_fragment_shader *cso = (struct cso_fragment_shader *)state; - if (ctx->fragment_shader == cso->data) - return FALSE; - if (cso->delete_state) - cso->delete_state(cso->context, cso->data); - FREE(state); - return TRUE; -} - -static boolean delete_vs_state(struct cso_context *ctx, void *state) -{ - struct cso_vertex_shader *cso = (struct cso_vertex_shader *)state; - if (ctx->vertex_shader == cso->data) - return TRUE; - if (cso->delete_state) - cso->delete_state(cso->context, cso->data); - FREE(state); - return FALSE; -} - static boolean delete_vertex_elements(struct cso_context *ctx, void *state) { @@ -207,12 +197,6 @@ static INLINE boolean delete_cso(struct cso_context *ctx, case CSO_RASTERIZER: return delete_rasterizer_state(ctx, state); break; - case CSO_FRAGMENT_SHADER: - return delete_fs_state(ctx, state); - break; - case CSO_VERTEX_SHADER: - return delete_vs_state(ctx, state); - break; case CSO_VELEMENTS: return delete_vertex_elements(ctx, state); break; @@ -254,6 +238,8 @@ struct cso_context *cso_create_context( struct pipe_context *pipe ) if (ctx == NULL) goto out; + assert(PIPE_MAX_SAMPLERS == PIPE_MAX_VERTEX_SAMPLERS); + ctx->cache = cso_cache_create(); if (ctx->cache == NULL) goto out; @@ -266,6 +252,15 @@ struct cso_context *cso_create_context( struct pipe_context *pipe ) /* Enable for testing: */ if (0) cso_set_maximum_cache_size( ctx->cache, 4 ); + if (pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_GEOMETRY, + PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0) { + ctx->has_geometry_shader = TRUE; + } + if (pipe->screen->get_param(pipe->screen, + PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS) != 0) { + ctx->has_streamout = TRUE; + } + return ctx; out: @@ -280,7 +275,8 @@ out: void cso_release_all( struct cso_context *ctx ) { unsigned i; - + struct sampler_info *info; + if (ctx->pipe) { ctx->pipe->bind_blend_state( ctx->pipe, NULL ); ctx->pipe->bind_rasterizer_state( ctx->pipe, NULL ); @@ -291,20 +287,41 @@ void cso_release_all( struct cso_context *ctx ) ctx->pipe->bind_fs_state( ctx->pipe, NULL ); ctx->pipe->bind_vs_state( ctx->pipe, NULL ); ctx->pipe->bind_vertex_elements_state( ctx->pipe, NULL ); + ctx->pipe->set_fragment_sampler_views(ctx->pipe, 0, NULL); + if (ctx->pipe->set_vertex_sampler_views) + ctx->pipe->set_vertex_sampler_views(ctx->pipe, 0, NULL); + if (ctx->pipe->set_stream_output_targets) + ctx->pipe->set_stream_output_targets(ctx->pipe, 0, NULL, 0); } + /* free fragment samplers, views */ + info = &ctx->fragment_samplers; for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { - pipe_sampler_view_reference(&ctx->fragment_sampler_views[i], NULL); - pipe_sampler_view_reference(&ctx->fragment_sampler_views_saved[i], NULL); + pipe_sampler_view_reference(&info->views[i], NULL); + pipe_sampler_view_reference(&info->views_saved[i], NULL); } - for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) { - pipe_sampler_view_reference(&ctx->vertex_sampler_views[i], NULL); - pipe_sampler_view_reference(&ctx->vertex_sampler_views_saved[i], NULL); + /* free vertex samplers, views */ + info = &ctx->vertex_samplers; + for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { + pipe_sampler_view_reference(&info->views[i], NULL); + pipe_sampler_view_reference(&info->views_saved[i], NULL); } - free_framebuffer_state(&ctx->fb); - free_framebuffer_state(&ctx->fb_saved); + util_unreference_framebuffer_state(&ctx->fb); + util_unreference_framebuffer_state(&ctx->fb_saved); + + util_copy_vertex_buffers(ctx->vertex_buffers, + &ctx->nr_vertex_buffers, + NULL, 0); + util_copy_vertex_buffers(ctx->vertex_buffers_saved, + &ctx->nr_vertex_buffers_saved, + NULL, 0); + + for (i = 0; i < PIPE_MAX_SO_BUFFERS; i++) { + pipe_so_target_reference(&ctx->so_targets[i], NULL); + pipe_so_target_reference(&ctx->so_targets_saved[i], NULL); + } if (ctx->cache) { cso_cache_delete( ctx->cache ); @@ -313,10 +330,13 @@ void cso_release_all( struct cso_context *ctx ) } +/** + * Free the CSO context. NOTE: the state tracker should have previously called + * cso_release_all(). + */ void cso_destroy_context( struct cso_context *ctx ) { if (ctx) { - /*cso_release_all( ctx );*/ FREE( ctx ); } } @@ -391,233 +411,6 @@ void cso_restore_blend(struct cso_context *ctx) -enum pipe_error cso_single_sampler(struct cso_context *ctx, - unsigned idx, - const struct pipe_sampler_state *templ) -{ - void *handle = NULL; - - if (templ != NULL) { - unsigned key_size = sizeof(struct pipe_sampler_state); - unsigned hash_key = cso_construct_key((void*)templ, key_size); - struct cso_hash_iter iter = cso_find_state_template(ctx->cache, - hash_key, CSO_SAMPLER, - (void*)templ, key_size); - - if (cso_hash_iter_is_null(iter)) { - struct cso_sampler *cso = MALLOC(sizeof(struct cso_sampler)); - if (!cso) - return PIPE_ERROR_OUT_OF_MEMORY; - - memcpy(&cso->state, templ, sizeof(*templ)); - cso->data = ctx->pipe->create_sampler_state(ctx->pipe, &cso->state); - cso->delete_state = (cso_state_callback)ctx->pipe->delete_sampler_state; - cso->context = ctx->pipe; - - iter = cso_insert_state(ctx->cache, hash_key, CSO_SAMPLER, cso); - if (cso_hash_iter_is_null(iter)) { - FREE(cso); - return PIPE_ERROR_OUT_OF_MEMORY; - } - - handle = cso->data; - } - else { - handle = ((struct cso_sampler *)cso_hash_iter_data(iter))->data; - } - } - - ctx->samplers[idx] = handle; - return PIPE_OK; -} - -enum pipe_error -cso_single_vertex_sampler(struct cso_context *ctx, - unsigned idx, - const struct pipe_sampler_state *templ) -{ - void *handle = NULL; - - if (templ != NULL) { - unsigned key_size = sizeof(struct pipe_sampler_state); - unsigned hash_key = cso_construct_key((void*)templ, key_size); - struct cso_hash_iter iter = cso_find_state_template(ctx->cache, - hash_key, CSO_SAMPLER, - (void*)templ, key_size); - - if (cso_hash_iter_is_null(iter)) { - struct cso_sampler *cso = MALLOC(sizeof(struct cso_sampler)); - if (!cso) - return PIPE_ERROR_OUT_OF_MEMORY; - - memcpy(&cso->state, templ, sizeof(*templ)); - cso->data = ctx->pipe->create_sampler_state(ctx->pipe, &cso->state); - cso->delete_state = (cso_state_callback)ctx->pipe->delete_sampler_state; - cso->context = ctx->pipe; - - iter = cso_insert_state(ctx->cache, hash_key, CSO_SAMPLER, cso); - if (cso_hash_iter_is_null(iter)) { - FREE(cso); - return PIPE_ERROR_OUT_OF_MEMORY; - } - - handle = cso->data; - } - else { - handle = ((struct cso_sampler *)cso_hash_iter_data(iter))->data; - } - } - - ctx->vertex_samplers[idx] = handle; - return PIPE_OK; -} - -void cso_single_sampler_done( struct cso_context *ctx ) -{ - unsigned i; - - /* find highest non-null sampler */ - for (i = PIPE_MAX_SAMPLERS; i > 0; i--) { - if (ctx->samplers[i - 1] != NULL) - break; - } - - ctx->nr_samplers = i; - - if (ctx->hw.nr_samplers != ctx->nr_samplers || - memcmp(ctx->hw.samplers, - ctx->samplers, - ctx->nr_samplers * sizeof(void *)) != 0) - { - memcpy(ctx->hw.samplers, ctx->samplers, ctx->nr_samplers * sizeof(void *)); - ctx->hw.nr_samplers = ctx->nr_samplers; - - ctx->pipe->bind_fragment_sampler_states(ctx->pipe, ctx->nr_samplers, ctx->samplers); - } -} - -void -cso_single_vertex_sampler_done(struct cso_context *ctx) -{ - unsigned i; - - /* find highest non-null sampler */ - for (i = PIPE_MAX_VERTEX_SAMPLERS; i > 0; i--) { - if (ctx->vertex_samplers[i - 1] != NULL) - break; - } - - ctx->nr_vertex_samplers = i; - - if (ctx->hw.nr_vertex_samplers != ctx->nr_vertex_samplers || - memcmp(ctx->hw.vertex_samplers, - ctx->vertex_samplers, - ctx->nr_vertex_samplers * sizeof(void *)) != 0) - { - memcpy(ctx->hw.vertex_samplers, - ctx->vertex_samplers, - ctx->nr_vertex_samplers * sizeof(void *)); - ctx->hw.nr_vertex_samplers = ctx->nr_vertex_samplers; - - ctx->pipe->bind_vertex_sampler_states(ctx->pipe, - ctx->nr_vertex_samplers, - ctx->vertex_samplers); - } -} - -/* - * If the function encouters any errors it will return the - * last one. Done to always try to set as many samplers - * as possible. - */ -enum pipe_error cso_set_samplers( struct cso_context *ctx, - unsigned nr, - const struct pipe_sampler_state **templates ) -{ - unsigned i; - enum pipe_error temp, error = PIPE_OK; - - /* TODO: fastpath - */ - - for (i = 0; i < nr; i++) { - temp = cso_single_sampler( ctx, i, templates[i] ); - if (temp != PIPE_OK) - error = temp; - } - - for ( ; i < ctx->nr_samplers; i++) { - temp = cso_single_sampler( ctx, i, NULL ); - if (temp != PIPE_OK) - error = temp; - } - - cso_single_sampler_done( ctx ); - - return error; -} - -void cso_save_samplers(struct cso_context *ctx) -{ - ctx->nr_samplers_saved = ctx->nr_samplers; - memcpy(ctx->samplers_saved, ctx->samplers, sizeof(ctx->samplers)); -} - -void cso_restore_samplers(struct cso_context *ctx) -{ - ctx->nr_samplers = ctx->nr_samplers_saved; - memcpy(ctx->samplers, ctx->samplers_saved, sizeof(ctx->samplers)); - cso_single_sampler_done( ctx ); -} - -/* - * If the function encouters any errors it will return the - * last one. Done to always try to set as many samplers - * as possible. - */ -enum pipe_error cso_set_vertex_samplers(struct cso_context *ctx, - unsigned nr, - const struct pipe_sampler_state **templates) -{ - unsigned i; - enum pipe_error temp, error = PIPE_OK; - - /* TODO: fastpath - */ - - for (i = 0; i < nr; i++) { - temp = cso_single_vertex_sampler( ctx, i, templates[i] ); - if (temp != PIPE_OK) - error = temp; - } - - for ( ; i < ctx->nr_samplers; i++) { - temp = cso_single_vertex_sampler( ctx, i, NULL ); - if (temp != PIPE_OK) - error = temp; - } - - cso_single_vertex_sampler_done( ctx ); - - return error; -} - -void -cso_save_vertex_samplers(struct cso_context *ctx) -{ - ctx->nr_vertex_samplers_saved = ctx->nr_vertex_samplers; - memcpy(ctx->vertex_samplers_saved, ctx->vertex_samplers, sizeof(ctx->vertex_samplers)); -} - -void -cso_restore_vertex_samplers(struct cso_context *ctx) -{ - ctx->nr_vertex_samplers = ctx->nr_vertex_samplers_saved; - memcpy(ctx->vertex_samplers, ctx->vertex_samplers_saved, sizeof(ctx->vertex_samplers)); - cso_single_vertex_sampler_done(ctx); -} - - enum pipe_error cso_set_depth_stencil_alpha(struct cso_context *ctx, const struct pipe_depth_stencil_alpha_state *templ) { @@ -751,52 +544,6 @@ void cso_delete_fragment_shader(struct cso_context *ctx, void *handle ) ctx->pipe->delete_fs_state(ctx->pipe, handle); } -/* Not really working: - */ -#if 0 -enum pipe_error cso_set_fragment_shader(struct cso_context *ctx, - const struct pipe_shader_state *templ) -{ - const struct tgsi_token *tokens = templ->tokens; - unsigned num_tokens = tgsi_num_tokens(tokens); - size_t tokens_size = num_tokens*sizeof(struct tgsi_token); - unsigned hash_key = cso_construct_key((void*)tokens, tokens_size); - struct cso_hash_iter iter = cso_find_state_template(ctx->cache, - hash_key, - CSO_FRAGMENT_SHADER, - (void*)tokens, - sizeof(*templ)); /* XXX correct? tokens_size? */ - void *handle = NULL; - - if (cso_hash_iter_is_null(iter)) { - struct cso_fragment_shader *cso = MALLOC(sizeof(struct cso_fragment_shader) + tokens_size); - struct tgsi_token *cso_tokens = (struct tgsi_token *)((char *)cso + sizeof(*cso)); - - if (!cso) - return PIPE_ERROR_OUT_OF_MEMORY; - - memcpy(cso_tokens, tokens, tokens_size); - cso->state.tokens = cso_tokens; - cso->data = ctx->pipe->create_fs_state(ctx->pipe, &cso->state); - cso->delete_state = (cso_state_callback)ctx->pipe->delete_fs_state; - cso->context = ctx->pipe; - - iter = cso_insert_state(ctx->cache, hash_key, CSO_FRAGMENT_SHADER, cso); - if (cso_hash_iter_is_null(iter)) { - FREE(cso); - return PIPE_ERROR_OUT_OF_MEMORY; - } - - handle = cso->data; - } - else { - handle = ((struct cso_fragment_shader *)cso_hash_iter_data(iter))->data; - } - - return cso_set_fragment_shader_handle( ctx, handle ); -} -#endif - void cso_save_fragment_shader(struct cso_context *ctx) { assert(!ctx->fragment_shader_saved); @@ -833,102 +580,27 @@ void cso_delete_vertex_shader(struct cso_context *ctx, void *handle ) ctx->pipe->delete_vs_state(ctx->pipe, handle); } +void cso_save_vertex_shader(struct cso_context *ctx) +{ + assert(!ctx->vertex_shader_saved); + ctx->vertex_shader_saved = ctx->vertex_shader; +} -/* Not really working: - */ -#if 0 -enum pipe_error cso_set_vertex_shader(struct cso_context *ctx, - const struct pipe_shader_state *templ) +void cso_restore_vertex_shader(struct cso_context *ctx) { - unsigned hash_key = cso_construct_key((void*)templ, - sizeof(struct pipe_shader_state)); - struct cso_hash_iter iter = cso_find_state_template(ctx->cache, - hash_key, CSO_VERTEX_SHADER, - (void*)templ, - sizeof(*templ)); - void *handle = NULL; - - if (cso_hash_iter_is_null(iter)) { - struct cso_vertex_shader *cso = MALLOC(sizeof(struct cso_vertex_shader)); - - if (!cso) - return PIPE_ERROR_OUT_OF_MEMORY; - - memcpy(cso->state, templ, sizeof(*templ)); - cso->data = ctx->pipe->create_vs_state(ctx->pipe, &cso->state); - cso->delete_state = (cso_state_callback)ctx->pipe->delete_vs_state; - cso->context = ctx->pipe; - - iter = cso_insert_state(ctx->cache, hash_key, CSO_VERTEX_SHADER, cso); - if (cso_hash_iter_is_null(iter)) { - FREE(cso); - return PIPE_ERROR_OUT_OF_MEMORY; - } - - handle = cso->data; - } - else { - handle = ((struct cso_vertex_shader *)cso_hash_iter_data(iter))->data; - } - - return cso_set_vertex_shader_handle( ctx, handle ); -} -#endif - - - -void cso_save_vertex_shader(struct cso_context *ctx) -{ - assert(!ctx->vertex_shader_saved); - ctx->vertex_shader_saved = ctx->vertex_shader; -} - -void cso_restore_vertex_shader(struct cso_context *ctx) -{ - if (ctx->vertex_shader_saved != ctx->vertex_shader) { - ctx->pipe->bind_vs_state(ctx->pipe, ctx->vertex_shader_saved); - ctx->vertex_shader = ctx->vertex_shader_saved; - } - ctx->vertex_shader_saved = NULL; -} - - -/** - * Copy framebuffer state from src to dst with refcounting of surfaces. - */ -static void -copy_framebuffer_state(struct pipe_framebuffer_state *dst, - const struct pipe_framebuffer_state *src) -{ - uint i; - - dst->width = src->width; - dst->height = src->height; - dst->nr_cbufs = src->nr_cbufs; - for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { - pipe_surface_reference(&dst->cbufs[i], src->cbufs[i]); - } - pipe_surface_reference(&dst->zsbuf, src->zsbuf); -} - - -static void -free_framebuffer_state(struct pipe_framebuffer_state *fb) -{ - uint i; - - for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { - pipe_surface_reference(&fb->cbufs[i], NULL); - } - pipe_surface_reference(&fb->zsbuf, NULL); -} + if (ctx->vertex_shader_saved != ctx->vertex_shader) { + ctx->pipe->bind_vs_state(ctx->pipe, ctx->vertex_shader_saved); + ctx->vertex_shader = ctx->vertex_shader_saved; + } + ctx->vertex_shader_saved = NULL; +} enum pipe_error cso_set_framebuffer(struct cso_context *ctx, const struct pipe_framebuffer_state *fb) { if (memcmp(&ctx->fb, fb, sizeof(*fb)) != 0) { - copy_framebuffer_state(&ctx->fb, fb); + util_copy_framebuffer_state(&ctx->fb, fb); ctx->pipe->set_framebuffer_state(ctx->pipe, fb); } return PIPE_OK; @@ -936,15 +608,15 @@ enum pipe_error cso_set_framebuffer(struct cso_context *ctx, void cso_save_framebuffer(struct cso_context *ctx) { - copy_framebuffer_state(&ctx->fb_saved, &ctx->fb); + util_copy_framebuffer_state(&ctx->fb_saved, &ctx->fb); } void cso_restore_framebuffer(struct cso_context *ctx) { if (memcmp(&ctx->fb, &ctx->fb_saved, sizeof(ctx->fb))) { - copy_framebuffer_state(&ctx->fb, &ctx->fb_saved); + util_copy_framebuffer_state(&ctx->fb, &ctx->fb_saved); ctx->pipe->set_framebuffer_state(ctx->pipe, &ctx->fb); - free_framebuffer_state(&ctx->fb_saved); + util_unreference_framebuffer_state(&ctx->fb_saved); } } @@ -984,6 +656,16 @@ enum pipe_error cso_set_blend_color(struct cso_context *ctx, return PIPE_OK; } +enum pipe_error cso_set_sample_mask(struct cso_context *ctx, + unsigned sample_mask) +{ + if (ctx->sample_mask != sample_mask) { + ctx->sample_mask = sample_mask; + ctx->pipe->set_sample_mask(ctx->pipe, sample_mask); + } + return PIPE_OK; +} + enum pipe_error cso_set_stencil_ref(struct cso_context *ctx, const struct pipe_stencil_ref *sr) { @@ -1011,7 +693,9 @@ void cso_restore_stencil_ref(struct cso_context *ctx) enum pipe_error cso_set_geometry_shader_handle(struct cso_context *ctx, void *handle) { - if (ctx->geometry_shader != handle) { + assert(ctx->has_geometry_shader || !handle); + + if (ctx->has_geometry_shader && ctx->geometry_shader != handle) { ctx->geometry_shader = handle; ctx->pipe->bind_gs_state(ctx->pipe, handle); } @@ -1030,12 +714,20 @@ void cso_delete_geometry_shader(struct cso_context *ctx, void *handle) void cso_save_geometry_shader(struct cso_context *ctx) { + if (!ctx->has_geometry_shader) { + return; + } + assert(!ctx->geometry_shader_saved); ctx->geometry_shader_saved = ctx->geometry_shader; } void cso_restore_geometry_shader(struct cso_context *ctx) { + if (!ctx->has_geometry_shader) { + return; + } + if (ctx->geometry_shader_saved != ctx->geometry_shader) { ctx->pipe->bind_gs_state(ctx->pipe, ctx->geometry_shader_saved); ctx->geometry_shader = ctx->geometry_shader_saved; @@ -1049,23 +741,14 @@ static INLINE void clip_state_cpy(struct pipe_clip_state *dst, const struct pipe_clip_state *src) { - dst->nr = src->nr; - if (src->nr) { - memcpy(dst->ucp, src->ucp, src->nr * sizeof(src->ucp[0])); - } + memcpy(dst->ucp, src->ucp, sizeof(dst->ucp)); } static INLINE int clip_state_cmp(const struct pipe_clip_state *a, const struct pipe_clip_state *b) { - if (a->nr != b->nr) { - return 1; - } - if (a->nr) { - return memcmp(a->ucp, b->ucp, a->nr * sizeof(a->ucp[0])); - } - return 0; + return memcmp(a->ucp, b->ucp, sizeof(a->ucp)); } void @@ -1156,121 +839,489 @@ void cso_restore_vertex_elements(struct cso_context *ctx) ctx->velements_saved = NULL; } -/* fragment sampler view state */ +/* vertex buffers */ + +void cso_set_vertex_buffers(struct cso_context *ctx, + unsigned count, + const struct pipe_vertex_buffer *buffers) +{ + if (count != ctx->nr_vertex_buffers || + memcmp(buffers, ctx->vertex_buffers, + sizeof(struct pipe_vertex_buffer) * count) != 0) { + util_copy_vertex_buffers(ctx->vertex_buffers, &ctx->nr_vertex_buffers, + buffers, count); + ctx->pipe->set_vertex_buffers(ctx->pipe, count, buffers); + } +} + +void cso_save_vertex_buffers(struct cso_context *ctx) +{ + util_copy_vertex_buffers(ctx->vertex_buffers_saved, + &ctx->nr_vertex_buffers_saved, + ctx->vertex_buffers, + ctx->nr_vertex_buffers); +} + +void cso_restore_vertex_buffers(struct cso_context *ctx) +{ + unsigned i; + + util_copy_vertex_buffers(ctx->vertex_buffers, + &ctx->nr_vertex_buffers, + ctx->vertex_buffers_saved, + ctx->nr_vertex_buffers_saved); + + for (i = 0; i < ctx->nr_vertex_buffers_saved; i++) { + pipe_resource_reference(&ctx->vertex_buffers_saved[i].buffer, NULL); + } + ctx->nr_vertex_buffers_saved = 0; + + ctx->pipe->set_vertex_buffers(ctx->pipe, ctx->nr_vertex_buffers, + ctx->vertex_buffers); +} + + +/**************** fragment/vertex sampler view state *************************/ + +static enum pipe_error +single_sampler(struct cso_context *ctx, + struct sampler_info *info, + unsigned idx, + const struct pipe_sampler_state *templ) +{ + void *handle = NULL; + + if (templ != NULL) { + unsigned key_size = sizeof(struct pipe_sampler_state); + unsigned hash_key = cso_construct_key((void*)templ, key_size); + struct cso_hash_iter iter = + cso_find_state_template(ctx->cache, + hash_key, CSO_SAMPLER, + (void *) templ, key_size); + + if (cso_hash_iter_is_null(iter)) { + struct cso_sampler *cso = MALLOC(sizeof(struct cso_sampler)); + if (!cso) + return PIPE_ERROR_OUT_OF_MEMORY; + + memcpy(&cso->state, templ, sizeof(*templ)); + cso->data = ctx->pipe->create_sampler_state(ctx->pipe, &cso->state); + cso->delete_state = (cso_state_callback)ctx->pipe->delete_sampler_state; + cso->context = ctx->pipe; + + iter = cso_insert_state(ctx->cache, hash_key, CSO_SAMPLER, cso); + if (cso_hash_iter_is_null(iter)) { + FREE(cso); + return PIPE_ERROR_OUT_OF_MEMORY; + } + + handle = cso->data; + } + else { + handle = ((struct cso_sampler *)cso_hash_iter_data(iter))->data; + } + } + + info->samplers[idx] = handle; + + return PIPE_OK; +} + +enum pipe_error +cso_single_sampler(struct cso_context *ctx, + unsigned idx, + const struct pipe_sampler_state *templ) +{ + return single_sampler(ctx, &ctx->fragment_samplers, idx, templ); +} + +enum pipe_error +cso_single_vertex_sampler(struct cso_context *ctx, + unsigned idx, + const struct pipe_sampler_state *templ) +{ + return single_sampler(ctx, &ctx->vertex_samplers, idx, templ); +} + + + +static void +single_sampler_done(struct cso_context *ctx, + struct sampler_info *info) +{ + unsigned i; + + /* find highest non-null sampler */ + for (i = PIPE_MAX_SAMPLERS; i > 0; i--) { + if (info->samplers[i - 1] != NULL) + break; + } + + info->nr_samplers = i; + + if (info->hw.nr_samplers != info->nr_samplers || + memcmp(info->hw.samplers, + info->samplers, + info->nr_samplers * sizeof(void *)) != 0) + { + memcpy(info->hw.samplers, + info->samplers, + info->nr_samplers * sizeof(void *)); + info->hw.nr_samplers = info->nr_samplers; + + if (info == &ctx->fragment_samplers) { + ctx->pipe->bind_fragment_sampler_states(ctx->pipe, + info->nr_samplers, + info->samplers); + } + else if (info == &ctx->vertex_samplers) { + ctx->pipe->bind_vertex_sampler_states(ctx->pipe, + info->nr_samplers, + info->samplers); + } + else { + assert(0); + } + } +} + +void +cso_single_sampler_done( struct cso_context *ctx ) +{ + single_sampler_done(ctx, &ctx->fragment_samplers); +} void -cso_set_fragment_sampler_views(struct cso_context *cso, - uint count, - struct pipe_sampler_view **views) +cso_single_vertex_sampler_done(struct cso_context *ctx) +{ + single_sampler_done(ctx, &ctx->vertex_samplers); +} + + +/* + * If the function encouters any errors it will return the + * last one. Done to always try to set as many samplers + * as possible. + */ +static enum pipe_error +set_samplers(struct cso_context *ctx, + struct sampler_info *info, + unsigned nr, + const struct pipe_sampler_state **templates) +{ + unsigned i; + enum pipe_error temp, error = PIPE_OK; + + /* TODO: fastpath + */ + + for (i = 0; i < nr; i++) { + temp = single_sampler(ctx, info, i, templates[i]); + if (temp != PIPE_OK) + error = temp; + } + + for ( ; i < info->nr_samplers; i++) { + temp = single_sampler(ctx, info, i, NULL); + if (temp != PIPE_OK) + error = temp; + } + + single_sampler_done(ctx, info); + + return error; +} + +enum pipe_error +cso_set_samplers(struct cso_context *ctx, + unsigned nr, + const struct pipe_sampler_state **templates) +{ + return set_samplers(ctx, &ctx->fragment_samplers, nr, templates); +} + +enum pipe_error +cso_set_vertex_samplers(struct cso_context *ctx, + unsigned nr, + const struct pipe_sampler_state **templates) +{ + return set_samplers(ctx, &ctx->vertex_samplers, nr, templates); +} + + + +static void +save_samplers(struct cso_context *ctx, struct sampler_info *info) +{ + info->nr_samplers_saved = info->nr_samplers; + memcpy(info->samplers_saved, info->samplers, sizeof(info->samplers)); +} + +void +cso_save_samplers(struct cso_context *ctx) +{ + save_samplers(ctx, &ctx->fragment_samplers); +} + +void +cso_save_vertex_samplers(struct cso_context *ctx) +{ + save_samplers(ctx, &ctx->vertex_samplers); +} + + + +static void +restore_samplers(struct cso_context *ctx, struct sampler_info *info) +{ + info->nr_samplers = info->nr_samplers_saved; + memcpy(info->samplers, info->samplers_saved, sizeof(info->samplers)); + single_sampler_done(ctx, info); +} + +void +cso_restore_samplers(struct cso_context *ctx) +{ + restore_samplers(ctx, &ctx->fragment_samplers); +} + +void +cso_restore_vertex_samplers(struct cso_context *ctx) +{ + restore_samplers(ctx, &ctx->vertex_samplers); +} + + + +static void +set_sampler_views(struct cso_context *ctx, + struct sampler_info *info, + void (*set_views)(struct pipe_context *, + unsigned num_views, + struct pipe_sampler_view **), + uint count, + struct pipe_sampler_view **views) { uint i; + /* reference new views */ for (i = 0; i < count; i++) { - pipe_sampler_view_reference(&cso->fragment_sampler_views[i], views[i]); + pipe_sampler_view_reference(&info->views[i], views[i]); } - for (; i < cso->nr_fragment_sampler_views; i++) { - pipe_sampler_view_reference(&cso->fragment_sampler_views[i], NULL); + /* unref extra old views, if any */ + for (; i < info->nr_views; i++) { + pipe_sampler_view_reference(&info->views[i], NULL); } - cso->pipe->set_fragment_sampler_views(cso->pipe, - MAX2(count, cso->nr_fragment_sampler_views), - cso->fragment_sampler_views); + info->nr_views = count; - cso->nr_fragment_sampler_views = count; + /* bind the new sampler views */ + set_views(ctx->pipe, count, info->views); } void -cso_save_fragment_sampler_views(struct cso_context *cso) +cso_set_fragment_sampler_views(struct cso_context *ctx, + uint count, + struct pipe_sampler_view **views) { - uint i; + set_sampler_views(ctx, &ctx->fragment_samplers, + ctx->pipe->set_fragment_sampler_views, + count, views); +} + +void +cso_set_vertex_sampler_views(struct cso_context *ctx, + uint count, + struct pipe_sampler_view **views) +{ + set_sampler_views(ctx, &ctx->vertex_samplers, + ctx->pipe->set_vertex_sampler_views, + count, views); +} - cso->nr_fragment_sampler_views_saved = cso->nr_fragment_sampler_views; - for (i = 0; i < cso->nr_fragment_sampler_views; i++) { - assert(!cso->fragment_sampler_views_saved[i]); - pipe_sampler_view_reference(&cso->fragment_sampler_views_saved[i], - cso->fragment_sampler_views[i]); +static void +save_sampler_views(struct cso_context *ctx, + struct sampler_info *info) +{ + uint i; + + info->nr_views_saved = info->nr_views; + + for (i = 0; i < info->nr_views; i++) { + assert(!info->views_saved[i]); + pipe_sampler_view_reference(&info->views_saved[i], info->views[i]); } } void -cso_restore_fragment_sampler_views(struct cso_context *cso) +cso_save_fragment_sampler_views(struct cso_context *ctx) +{ + save_sampler_views(ctx, &ctx->fragment_samplers); +} + +void +cso_save_vertex_sampler_views(struct cso_context *ctx) +{ + save_sampler_views(ctx, &ctx->vertex_samplers); +} + + +static void +restore_sampler_views(struct cso_context *ctx, + struct sampler_info *info, + void (*set_views)(struct pipe_context *, + unsigned num_views, + struct pipe_sampler_view **)) { uint i; - for (i = 0; i < cso->nr_fragment_sampler_views_saved; i++) { - pipe_sampler_view_reference(&cso->fragment_sampler_views[i], cso->fragment_sampler_views_saved[i]); - pipe_sampler_view_reference(&cso->fragment_sampler_views_saved[i], NULL); + for (i = 0; i < info->nr_views_saved; i++) { + pipe_sampler_view_reference(&info->views[i], NULL); + /* move the reference from one pointer to another */ + info->views[i] = info->views_saved[i]; + info->views_saved[i] = NULL; } - for (; i < cso->nr_fragment_sampler_views; i++) { - pipe_sampler_view_reference(&cso->fragment_sampler_views[i], NULL); + for (; i < info->nr_views; i++) { + pipe_sampler_view_reference(&info->views[i], NULL); } - cso->pipe->set_fragment_sampler_views(cso->pipe, - MAX2(cso->nr_fragment_sampler_views, cso->nr_fragment_sampler_views_saved), - cso->fragment_sampler_views); + /* bind the old/saved sampler views */ + set_views(ctx->pipe, info->nr_views_saved, info->views); - cso->nr_fragment_sampler_views = cso->nr_fragment_sampler_views_saved; - cso->nr_fragment_sampler_views_saved = 0; + info->nr_views = info->nr_views_saved; + info->nr_views_saved = 0; } +void +cso_restore_fragment_sampler_views(struct cso_context *ctx) +{ + restore_sampler_views(ctx, &ctx->fragment_samplers, + ctx->pipe->set_fragment_sampler_views); +} + +void +cso_restore_vertex_sampler_views(struct cso_context *ctx) +{ + restore_sampler_views(ctx, &ctx->vertex_samplers, + ctx->pipe->set_vertex_sampler_views); +} -/* vertex sampler view state */ void -cso_set_vertex_sampler_views(struct cso_context *cso, - uint count, - struct pipe_sampler_view **views) +cso_set_stream_outputs(struct cso_context *ctx, + unsigned num_targets, + struct pipe_stream_output_target **targets, + unsigned append_bitmask) { + struct pipe_context *pipe = ctx->pipe; uint i; - for (i = 0; i < count; i++) { - pipe_sampler_view_reference(&cso->vertex_sampler_views[i], views[i]); + if (!ctx->has_streamout) { + assert(num_targets == 0); + return; } - for (; i < cso->nr_vertex_sampler_views; i++) { - pipe_sampler_view_reference(&cso->vertex_sampler_views[i], NULL); + + if (ctx->nr_so_targets == 0 && num_targets == 0) { + /* Nothing to do. */ + return; } - cso->pipe->set_vertex_sampler_views(cso->pipe, - MAX2(count, cso->nr_vertex_sampler_views), - cso->vertex_sampler_views); + /* reference new targets */ + for (i = 0; i < num_targets; i++) { + pipe_so_target_reference(&ctx->so_targets[i], targets[i]); + } + /* unref extra old targets, if any */ + for (; i < ctx->nr_so_targets; i++) { + pipe_so_target_reference(&ctx->so_targets[i], NULL); + } - cso->nr_vertex_sampler_views = count; + pipe->set_stream_output_targets(pipe, num_targets, targets, + append_bitmask); + ctx->nr_so_targets = num_targets; } void -cso_save_vertex_sampler_views(struct cso_context *cso) +cso_save_stream_outputs(struct cso_context *ctx) { uint i; - cso->nr_vertex_sampler_views_saved = cso->nr_vertex_sampler_views; + if (!ctx->has_streamout) { + return; + } - for (i = 0; i < cso->nr_vertex_sampler_views; i++) { - assert(!cso->vertex_sampler_views_saved[i]); + ctx->nr_so_targets_saved = ctx->nr_so_targets; - pipe_sampler_view_reference(&cso->vertex_sampler_views_saved[i], - cso->vertex_sampler_views[i]); + for (i = 0; i < ctx->nr_so_targets; i++) { + assert(!ctx->so_targets_saved[i]); + pipe_so_target_reference(&ctx->so_targets_saved[i], ctx->so_targets[i]); } } void -cso_restore_vertex_sampler_views(struct cso_context *cso) +cso_restore_stream_outputs(struct cso_context *ctx) { + struct pipe_context *pipe = ctx->pipe; uint i; - for (i = 0; i < cso->nr_vertex_sampler_views_saved; i++) { - pipe_sampler_view_reference(&cso->vertex_sampler_views[i], cso->vertex_sampler_views_saved[i]); - pipe_sampler_view_reference(&cso->vertex_sampler_views_saved[i], NULL); + if (!ctx->has_streamout) { + return; + } + + if (ctx->nr_so_targets == 0 && ctx->nr_so_targets_saved == 0) { + /* Nothing to do. */ + return; } - for (; i < cso->nr_vertex_sampler_views; i++) { - pipe_sampler_view_reference(&cso->vertex_sampler_views[i], NULL); + + for (i = 0; i < ctx->nr_so_targets_saved; i++) { + pipe_so_target_reference(&ctx->so_targets[i], NULL); + /* move the reference from one pointer to another */ + ctx->so_targets[i] = ctx->so_targets_saved[i]; + ctx->so_targets_saved[i] = NULL; } + for (; i < ctx->nr_so_targets; i++) { + pipe_so_target_reference(&ctx->so_targets[i], NULL); + } + + /* ~0 means append */ + pipe->set_stream_output_targets(pipe, ctx->nr_so_targets_saved, + ctx->so_targets, ~0); + + ctx->nr_so_targets = ctx->nr_so_targets_saved; + ctx->nr_so_targets_saved = 0; +} + +/* drawing */ + +void +cso_set_index_buffer(struct cso_context *cso, + const struct pipe_index_buffer *ib) +{ + struct pipe_context *pipe = cso->pipe; + pipe->set_index_buffer(pipe, ib); +} + +void +cso_draw_vbo(struct cso_context *cso, + const struct pipe_draw_info *info) +{ + struct pipe_context *pipe = cso->pipe; + pipe->draw_vbo(pipe, info); +} + +void +cso_draw_arrays(struct cso_context *cso, uint mode, uint start, uint count) +{ + struct pipe_draw_info info; + + util_draw_init_info(&info); - cso->pipe->set_vertex_sampler_views(cso->pipe, - MAX2(cso->nr_vertex_sampler_views, cso->nr_vertex_sampler_views_saved), - cso->vertex_sampler_views); + info.mode = mode; + info.start = start; + info.count = count; + info.min_index = start; + info.max_index = start + count - 1; - cso->nr_vertex_sampler_views = cso->nr_vertex_sampler_views_saved; - cso->nr_vertex_sampler_views_saved = 0; + cso_draw_vbo(cso, &info); }