*/
#include "pipe/p_state.h"
+#include "util/u_inlines.h"
#include "util/u_memory.h"
#include "tgsi/tgsi_parse.h"
#include "cso_cache/cso_context.h"
#include "cso_cache/cso_cache.h"
#include "cso_cache/cso_hash.h"
+#include "cso_context.h"
struct cso_context {
struct pipe_context *pipe;
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_vertex_samplers_saved;
+ void *vertex_samplers_saved[PIPE_MAX_VERTEX_SAMPLERS];
+
struct pipe_texture *textures[PIPE_MAX_SAMPLERS];
uint nr_textures;
+ struct pipe_texture *vertex_textures[PIPE_MAX_VERTEX_SAMPLERS];
+ uint nr_vertex_textures;
+
uint nr_textures_saved;
struct pipe_texture *textures_saved[PIPE_MAX_SAMPLERS];
+ uint nr_vertex_textures_saved;
+ struct pipe_texture *vertex_textures_saved[PIPE_MAX_SAMPLERS];
+
/** Current and saved state.
* The saved state is used as a 1-deep stack.
*/
void *blend, *blend_saved;
void *depth_stencil, *depth_stencil_saved;
void *rasterizer, *rasterizer_saved;
- void *fragment_shader, *fragment_shader_saved;
- void *vertex_shader, *vertex_shader_saved;
+ void *fragment_shader, *fragment_shader_saved, *geometry_shader;
+ void *vertex_shader, *vertex_shader_saved, *geometry_shader_saved;
struct pipe_framebuffer_state fb, fb_saved;
struct pipe_viewport_state vp, vp_saved;
struct pipe_blend_color blend_color;
+ struct pipe_stencil_ref stencil_ref;
};
if (ctx->pipe) {
ctx->pipe->bind_blend_state( ctx->pipe, NULL );
ctx->pipe->bind_rasterizer_state( ctx->pipe, NULL );
- ctx->pipe->bind_sampler_states( ctx->pipe, 0, NULL );
+ ctx->pipe->bind_fragment_sampler_states( ctx->pipe, 0, NULL );
+ if (ctx->pipe->bind_vertex_sampler_states)
+ ctx->pipe->bind_vertex_sampler_states(ctx->pipe, 0, NULL);
ctx->pipe->bind_depth_stencil_alpha_state( ctx->pipe, NULL );
ctx->pipe->bind_fs_state( ctx->pipe, NULL );
ctx->pipe->bind_vs_state( ctx->pipe, NULL );
pipe_texture_reference(&ctx->textures_saved[i], NULL);
}
+ for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) {
+ pipe_texture_reference(&ctx->vertex_textures[i], NULL);
+ pipe_texture_reference(&ctx->vertex_textures_saved[i], NULL);
+ }
+
free_framebuffer_state(&ctx->fb);
free_framebuffer_state(&ctx->fb_saved);
void cso_destroy_context( struct cso_context *ctx )
{
if (ctx) {
- //cso_release_all( ctx );
+ /*cso_release_all( ctx );*/
FREE( ctx );
}
}
enum pipe_error cso_set_blend(struct cso_context *ctx,
const struct pipe_blend_state *templ)
{
- unsigned hash_key = cso_construct_key((void*)templ, sizeof(struct pipe_blend_state));
- struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
- hash_key, CSO_BLEND,
- (void*)templ);
+ unsigned key_size, hash_key;
+ struct cso_hash_iter iter;
void *handle;
+ key_size = templ->independent_blend_enable ? sizeof(struct pipe_blend_state) :
+ (char *)&(templ->rt[1]) - (char *)templ;
+ hash_key = cso_construct_key((void*)templ, key_size);
+ iter = cso_find_state_template(ctx->cache, hash_key, CSO_BLEND, (void*)templ, key_size);
+
if (cso_hash_iter_is_null(iter)) {
struct cso_blend *cso = MALLOC(sizeof(struct cso_blend));
if (!cso)
return PIPE_ERROR_OUT_OF_MEMORY;
- memcpy(&cso->state, templ, sizeof(*templ));
+ memcpy(&cso->state, templ, key_size);
cso->data = ctx->pipe->create_blend_state(ctx->pipe, &cso->state);
cso->delete_state = (cso_state_callback)ctx->pipe->delete_blend_state;
cso->context = ctx->pipe;
void *handle = NULL;
if (templ != NULL) {
- unsigned hash_key = cso_construct_key((void*)templ, sizeof(struct pipe_sampler_state));
+ 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);
+ (void*)templ, key_size);
if (cso_hash_iter_is_null(iter)) {
struct cso_sampler *cso = MALLOC(sizeof(struct cso_sampler));
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;
memcpy(ctx->hw.samplers, ctx->samplers, ctx->nr_samplers * sizeof(void *));
ctx->hw.nr_samplers = ctx->nr_samplers;
- ctx->pipe->bind_sampler_states(ctx->pipe, ctx->nr_samplers, ctx->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);
}
}
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_sampler_textures( struct cso_context *ctx,
uint count,
for ( ; i < PIPE_MAX_SAMPLERS; i++)
pipe_texture_reference(&ctx->textures[i], NULL);
- ctx->pipe->set_sampler_textures(ctx->pipe, count, textures);
+ ctx->pipe->set_fragment_sampler_textures(ctx->pipe, count, textures);
return PIPE_OK;
}
for ( ; i < PIPE_MAX_SAMPLERS; i++)
pipe_texture_reference(&ctx->textures[i], NULL);
- ctx->pipe->set_sampler_textures(ctx->pipe, ctx->nr_textures, ctx->textures);
+ ctx->pipe->set_fragment_sampler_textures(ctx->pipe, ctx->nr_textures, ctx->textures);
ctx->nr_textures_saved = 0;
}
+enum pipe_error
+cso_set_vertex_sampler_textures(struct cso_context *ctx,
+ uint count,
+ struct pipe_texture **textures)
+{
+ uint i;
+
+ ctx->nr_vertex_textures = count;
+
+ for (i = 0; i < count; i++) {
+ pipe_texture_reference(&ctx->vertex_textures[i], textures[i]);
+ }
+ for ( ; i < PIPE_MAX_VERTEX_SAMPLERS; i++) {
+ pipe_texture_reference(&ctx->vertex_textures[i], NULL);
+ }
+
+ ctx->pipe->set_vertex_sampler_textures(ctx->pipe, count, textures);
+
+ return PIPE_OK;
+}
+
+void
+cso_save_vertex_sampler_textures(struct cso_context *ctx)
+{
+ uint i;
+
+ ctx->nr_vertex_textures_saved = ctx->nr_vertex_textures;
+ for (i = 0; i < ctx->nr_vertex_textures; i++) {
+ assert(!ctx->vertex_textures_saved[i]);
+ pipe_texture_reference(&ctx->vertex_textures_saved[i], ctx->vertex_textures[i]);
+ }
+}
+
+void
+cso_restore_vertex_sampler_textures(struct cso_context *ctx)
+{
+ uint i;
+
+ ctx->nr_vertex_textures = ctx->nr_vertex_textures_saved;
+
+ for (i = 0; i < ctx->nr_vertex_textures; i++) {
+ pipe_texture_reference(&ctx->vertex_textures[i], NULL);
+ ctx->vertex_textures[i] = ctx->vertex_textures_saved[i];
+ ctx->vertex_textures_saved[i] = NULL;
+ }
+ for ( ; i < PIPE_MAX_VERTEX_SAMPLERS; i++) {
+ pipe_texture_reference(&ctx->vertex_textures[i], NULL);
+ }
+
+ ctx->pipe->set_vertex_sampler_textures(ctx->pipe,
+ ctx->nr_vertex_textures,
+ ctx->vertex_textures);
+
+ ctx->nr_vertex_textures_saved = 0;
+}
+
+
+
enum pipe_error cso_set_depth_stencil_alpha(struct cso_context *ctx,
const struct pipe_depth_stencil_alpha_state *templ)
{
- unsigned hash_key = cso_construct_key((void*)templ,
- sizeof(struct pipe_depth_stencil_alpha_state));
+ unsigned key_size = sizeof(struct pipe_depth_stencil_alpha_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_DEPTH_STENCIL_ALPHA,
- (void*)templ);
+ CSO_DEPTH_STENCIL_ALPHA,
+ (void*)templ, key_size);
void *handle;
if (cso_hash_iter_is_null(iter)) {
enum pipe_error cso_set_rasterizer(struct cso_context *ctx,
const struct pipe_rasterizer_state *templ)
{
- unsigned hash_key = cso_construct_key((void*)templ,
- sizeof(struct pipe_rasterizer_state));
+ unsigned key_size = sizeof(struct pipe_rasterizer_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_RASTERIZER,
- (void*)templ);
+ (void*)templ, key_size);
void *handle = NULL;
if (cso_hash_iter_is_null(iter)) {
struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
hash_key,
CSO_FRAGMENT_SHADER,
- (void*)tokens);
+ (void*)tokens,
+ sizeof(*templ)); /* XXX correct? tokens_size? */
void *handle = NULL;
if (cso_hash_iter_is_null(iter)) {
sizeof(struct pipe_shader_state));
struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
hash_key, CSO_VERTEX_SHADER,
- (void*)templ);
+ (void*)templ,
+ sizeof(*templ));
void *handle = NULL;
if (cso_hash_iter_is_null(iter)) {
}
return PIPE_OK;
}
+
+enum pipe_error cso_set_stencil_ref(struct cso_context *ctx,
+ const struct pipe_stencil_ref *sr)
+{
+ if (memcmp(&ctx->stencil_ref, sr, sizeof(ctx->stencil_ref))) {
+ ctx->stencil_ref = *sr;
+ ctx->pipe->set_stencil_ref(ctx->pipe, sr);
+ }
+ return PIPE_OK;
+}
+
+enum pipe_error cso_set_geometry_shader_handle(struct cso_context *ctx,
+ void *handle)
+{
+ if (ctx->geometry_shader != handle) {
+ ctx->geometry_shader = handle;
+ ctx->pipe->bind_gs_state(ctx->pipe, handle);
+ }
+ return PIPE_OK;
+}
+
+void cso_delete_geometry_shader(struct cso_context *ctx, void *handle)
+{
+ if (handle == ctx->geometry_shader) {
+ /* unbind before deleting */
+ ctx->pipe->bind_gs_state(ctx->pipe, NULL);
+ ctx->geometry_shader = NULL;
+ }
+ ctx->pipe->delete_gs_state(ctx->pipe, handle);
+}
+
+void cso_save_geometry_shader(struct cso_context *ctx)
+{
+ assert(!ctx->geometry_shader_saved);
+ ctx->geometry_shader_saved = ctx->geometry_shader;
+}
+
+void cso_restore_geometry_shader(struct cso_context *ctx)
+{
+ 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;
+ }
+ ctx->geometry_shader_saved = NULL;
+}