| @@ -43,6 +43,7 @@ struct cso_cache { | |||
| struct cso_hash *vs_hash; | |||
| struct cso_hash *rasterizer_hash; | |||
| struct cso_hash *sampler_hash; | |||
| struct cso_hash *velements_hash; | |||
| int max_size; | |||
| cso_sanitize_callback sanitize_cb; | |||
| @@ -108,6 +109,9 @@ static struct cso_hash *_cso_hash_for_type(struct cso_cache *sc, enum cso_cache_ | |||
| case CSO_VERTEX_SHADER: | |||
| hash = sc->vs_hash; | |||
| break; | |||
| case CSO_VELEMENTS: | |||
| hash = sc->velements_hash; | |||
| break; | |||
| } | |||
| return hash; | |||
| @@ -161,6 +165,13 @@ static void delete_vs_state(void *state, void *data) | |||
| FREE(state); | |||
| } | |||
| static void delete_velements(void *state, void *data) | |||
| { | |||
| struct cso_velements *cso = (struct cso_velements *)state; | |||
| if (cso->delete_state) | |||
| cso->delete_state(cso->context, cso->data); | |||
| FREE(state); | |||
| } | |||
| static INLINE void delete_cso(void *state, enum cso_cache_type type) | |||
| { | |||
| @@ -183,6 +194,9 @@ static INLINE void delete_cso(void *state, enum cso_cache_type type) | |||
| case CSO_VERTEX_SHADER: | |||
| delete_vs_state(state, 0); | |||
| break; | |||
| case CSO_VELEMENTS: | |||
| delete_velements(state, 0); | |||
| break; | |||
| default: | |||
| assert(0); | |||
| FREE(state); | |||
| @@ -294,6 +308,7 @@ struct cso_cache *cso_cache_create(void) | |||
| sc->rasterizer_hash = cso_hash_create(); | |||
| sc->fs_hash = cso_hash_create(); | |||
| sc->vs_hash = cso_hash_create(); | |||
| sc->velements_hash = cso_hash_create(); | |||
| sc->sanitize_cb = sanitize_cb; | |||
| sc->sanitize_data = 0; | |||
| @@ -325,6 +340,9 @@ void cso_for_each_state(struct cso_cache *sc, enum cso_cache_type type, | |||
| case CSO_VERTEX_SHADER: | |||
| hash = sc->vs_hash; | |||
| break; | |||
| case CSO_VELEMENTS: | |||
| hash = sc->velements_hash; | |||
| break; | |||
| } | |||
| iter = cso_hash_first_node(hash); | |||
| @@ -351,6 +369,7 @@ void cso_cache_delete(struct cso_cache *sc) | |||
| cso_for_each_state(sc, CSO_VERTEX_SHADER, delete_vs_state, 0); | |||
| cso_for_each_state(sc, CSO_RASTERIZER, delete_rasterizer_state, 0); | |||
| cso_for_each_state(sc, CSO_SAMPLER, delete_sampler_state, 0); | |||
| cso_for_each_state(sc, CSO_VELEMENTS, delete_velements, 0); | |||
| cso_hash_delete(sc->blend_hash); | |||
| cso_hash_delete(sc->sampler_hash); | |||
| @@ -358,6 +377,7 @@ void cso_cache_delete(struct cso_cache *sc) | |||
| cso_hash_delete(sc->rasterizer_hash); | |||
| cso_hash_delete(sc->fs_hash); | |||
| cso_hash_delete(sc->vs_hash); | |||
| cso_hash_delete(sc->velements_hash); | |||
| FREE(sc); | |||
| } | |||
| @@ -372,6 +392,7 @@ void cso_set_maximum_cache_size(struct cso_cache *sc, int number) | |||
| sanitize_hash(sc, sc->vs_hash, CSO_VERTEX_SHADER, sc->max_size); | |||
| sanitize_hash(sc, sc->rasterizer_hash, CSO_RASTERIZER, sc->max_size); | |||
| sanitize_hash(sc, sc->sampler_hash, CSO_SAMPLER, sc->max_size); | |||
| sanitize_hash(sc, sc->velements_hash, CSO_VELEMENTS, sc->max_size); | |||
| } | |||
| int cso_maximum_cache_size(const struct cso_cache *sc) | |||
| @@ -53,6 +53,7 @@ | |||
| * - rasterizer (old setup) | |||
| * - sampler | |||
| * - vertex shader | |||
| * - vertex elements | |||
| * | |||
| * Things that are not constant state objects include: | |||
| * - blend_color | |||
| @@ -90,7 +91,8 @@ enum cso_cache_type { | |||
| CSO_DEPTH_STENCIL_ALPHA, | |||
| CSO_RASTERIZER, | |||
| CSO_FRAGMENT_SHADER, | |||
| CSO_VERTEX_SHADER | |||
| CSO_VERTEX_SHADER, | |||
| CSO_VELEMENTS | |||
| }; | |||
| typedef void (*cso_state_callback)(void *ctx, void *obj); | |||
| @@ -144,6 +146,13 @@ struct cso_sampler { | |||
| struct pipe_context *context; | |||
| }; | |||
| struct cso_velements { | |||
| struct pipe_vertex_element state[PIPE_MAX_ATTRIBS]; | |||
| void *data; | |||
| cso_state_callback delete_state; | |||
| struct pipe_context *context; | |||
| }; | |||
| unsigned cso_construct_key(void *item, int item_size); | |||
| struct cso_cache *cso_cache_create(void); | |||
| @@ -89,6 +89,7 @@ struct cso_context { | |||
| void *rasterizer, *rasterizer_saved; | |||
| void *fragment_shader, *fragment_shader_saved, *geometry_shader; | |||
| void *vertex_shader, *vertex_shader_saved, *geometry_shader_saved; | |||
| void *velements, *velements_saved; | |||
| struct pipe_framebuffer_state fb, fb_saved; | |||
| struct pipe_viewport_state vp, vp_saved; | |||
| @@ -171,6 +172,20 @@ static boolean delete_vs_state(struct cso_context *ctx, void *state) | |||
| return FALSE; | |||
| } | |||
| static boolean delete_vertex_elements(struct cso_context *ctx, | |||
| void *state) | |||
| { | |||
| struct cso_velements *cso = (struct cso_velements *)state; | |||
| if (ctx->velements == cso->data) | |||
| return FALSE; | |||
| if (cso->delete_state) | |||
| cso->delete_state(cso->context, cso->data); | |||
| FREE(state); | |||
| return TRUE; | |||
| } | |||
| static INLINE boolean delete_cso(struct cso_context *ctx, | |||
| void *state, enum cso_cache_type type) | |||
| @@ -194,6 +209,9 @@ static INLINE boolean delete_cso(struct cso_context *ctx, | |||
| case CSO_VERTEX_SHADER: | |||
| return delete_vs_state(ctx, state); | |||
| break; | |||
| case CSO_VELEMENTS: | |||
| return delete_vertex_elements(ctx, state); | |||
| break; | |||
| default: | |||
| assert(0); | |||
| FREE(state); | |||
| @@ -1126,3 +1144,59 @@ void cso_restore_geometry_shader(struct cso_context *ctx) | |||
| } | |||
| ctx->geometry_shader_saved = NULL; | |||
| } | |||
| enum pipe_error cso_set_vertex_elements(struct cso_context *ctx, | |||
| unsigned count, | |||
| const struct pipe_vertex_element *states) | |||
| { | |||
| unsigned key_size, hash_key; | |||
| struct cso_hash_iter iter; | |||
| void *handle; | |||
| key_size = sizeof(struct pipe_vertex_element) * count; | |||
| hash_key = cso_construct_key((void*)states, key_size); | |||
| iter = cso_find_state_template(ctx->cache, hash_key, CSO_VELEMENTS, (void*)states, key_size); | |||
| if (cso_hash_iter_is_null(iter)) { | |||
| struct cso_velements *cso = MALLOC(sizeof(struct cso_velements)); | |||
| if (!cso) | |||
| return PIPE_ERROR_OUT_OF_MEMORY; | |||
| memcpy(&cso->state, states, key_size); | |||
| cso->data = ctx->pipe->create_vertex_elements_state(ctx->pipe, count, &cso->state[0]); | |||
| cso->delete_state = (cso_state_callback)ctx->pipe->delete_vertex_elements_state; | |||
| cso->context = ctx->pipe; | |||
| iter = cso_insert_state(ctx->cache, hash_key, CSO_VELEMENTS, cso); | |||
| if (cso_hash_iter_is_null(iter)) { | |||
| FREE(cso); | |||
| return PIPE_ERROR_OUT_OF_MEMORY; | |||
| } | |||
| handle = cso->data; | |||
| } | |||
| else { | |||
| handle = ((struct cso_velements *)cso_hash_iter_data(iter))->data; | |||
| } | |||
| if (ctx->velements != handle) { | |||
| ctx->velements = handle; | |||
| ctx->pipe->bind_vertex_elements_state(ctx->pipe, handle); | |||
| } | |||
| return PIPE_OK; | |||
| } | |||
| void cso_save_vertex_elements(struct cso_context *ctx) | |||
| { | |||
| assert(!ctx->velements); | |||
| ctx->velements_saved = ctx->velements; | |||
| } | |||
| void cso_restore_vertex_elements(struct cso_context *ctx) | |||
| { | |||
| if (ctx->velements != ctx->velements_saved) { | |||
| ctx->velements = ctx->velements_saved; | |||
| ctx->pipe->bind_vertex_elements_state(ctx->pipe, ctx->velements_saved); | |||
| } | |||
| ctx->velements_saved = NULL; | |||
| } | |||
| @@ -122,6 +122,12 @@ void | |||
| cso_restore_vertex_sampler_textures(struct cso_context *cso); | |||
| enum pipe_error cso_set_vertex_elements(struct cso_context *ctx, | |||
| unsigned count, | |||
| const struct pipe_vertex_element *states); | |||
| void cso_save_vertex_elements(struct cso_context *ctx); | |||
| void cso_restore_vertex_elements(struct cso_context *ctx); | |||
| /* These aren't really sensible -- most of the time the api provides | |||
| * object semantics for shaders anyway, and the cases where it doesn't | |||
| @@ -157,7 +163,6 @@ void cso_save_geometry_shader(struct cso_context *cso); | |||
| void cso_restore_geometry_shader(struct cso_context *cso); | |||
| enum pipe_error cso_set_framebuffer(struct cso_context *cso, | |||
| const struct pipe_framebuffer_state *fb); | |||
| void cso_save_framebuffer(struct cso_context *cso); | |||
| @@ -177,6 +177,12 @@ struct pipe_context { | |||
| void (*bind_gs_state)(struct pipe_context *, void *); | |||
| void (*delete_gs_state)(struct pipe_context *, void *); | |||
| void * (*create_vertex_elements_state)(struct pipe_context *, | |||
| unsigned num_elements, | |||
| const struct pipe_vertex_element *); | |||
| void (*bind_vertex_elements_state)(struct pipe_context *, void *); | |||
| void (*delete_vertex_elements_state)(struct pipe_context *, void *); | |||
| /*@}*/ | |||
| /** | |||
| @@ -220,9 +226,6 @@ struct pipe_context { | |||
| unsigned num_buffers, | |||
| const struct pipe_vertex_buffer * ); | |||
| void (*set_vertex_elements)( struct pipe_context *, | |||
| unsigned num_elements, | |||
| const struct pipe_vertex_element * ); | |||
| /*@}*/ | |||