summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/softpipe/sp_state_sampler.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/softpipe/sp_state_sampler.c')
-rw-r--r--src/gallium/drivers/softpipe/sp_state_sampler.c127
1 files changed, 122 insertions, 5 deletions
diff --git a/src/gallium/drivers/softpipe/sp_state_sampler.c b/src/gallium/drivers/softpipe/sp_state_sampler.c
index cb517b02e4..db0b8ab76b 100644
--- a/src/gallium/drivers/softpipe/sp_state_sampler.c
+++ b/src/gallium/drivers/softpipe/sp_state_sampler.c
@@ -32,21 +32,37 @@
#include "util/u_memory.h"
#include "draw/draw_context.h"
+#include "draw/draw_context.h"
#include "sp_context.h"
-#include "sp_context.h"
#include "sp_state.h"
#include "sp_texture.h"
-#include "sp_tile_cache.h"
-#include "draw/draw_context.h"
+#include "sp_tex_sample.h"
+#include "sp_tex_tile_cache.h"
+struct sp_sampler {
+ struct pipe_sampler_state base;
+ struct sp_sampler_varient *varients;
+ struct sp_sampler_varient *current;
+};
+
+static struct sp_sampler *sp_sampler( struct pipe_sampler_state *sampler )
+{
+ return (struct sp_sampler *)sampler;
+}
+
void *
softpipe_create_sampler_state(struct pipe_context *pipe,
const struct pipe_sampler_state *sampler)
{
- return mem_dup(sampler, sizeof(*sampler));
+ struct sp_sampler *sp_sampler = CALLOC_STRUCT(sp_sampler);
+
+ sp_sampler->base = *sampler;
+ sp_sampler->varients = NULL;
+
+ return (void *)sp_sampler;
}
@@ -97,7 +113,7 @@ softpipe_set_sampler_textures(struct pipe_context *pipe,
struct pipe_texture *tex = i < num ? texture[i] : NULL;
pipe_texture_reference(&softpipe->texture[i], tex);
- sp_tile_cache_set_texture(pipe, softpipe->tex_cache[i], tex);
+ sp_tex_tile_cache_set_texture(softpipe->tex_cache[i], tex);
}
softpipe->num_textures = num;
@@ -106,10 +122,111 @@ softpipe_set_sampler_textures(struct pipe_context *pipe,
}
+/**
+ * Find/create an sp_sampler_varient object for sampling the given texture,
+ * sampler and tex unit.
+ *
+ * Note that the tex unit is significant. We can't re-use a sampler
+ * varient for multiple texture units because the sampler varient contains
+ * the texture object pointer. If the texture object pointer were stored
+ * somewhere outside the sampler varient, we could re-use samplers for
+ * multiple texture units.
+ */
+static struct sp_sampler_varient *
+get_sampler_varient( unsigned unit,
+ struct sp_sampler *sampler,
+ struct pipe_texture *texture,
+ unsigned processor )
+{
+ struct softpipe_texture *sp_texture = softpipe_texture(texture);
+ struct sp_sampler_varient *v = NULL;
+ union sp_sampler_key key;
+
+ /* if this fails, widen the key.unit field and update this assertion */
+ assert(PIPE_MAX_SAMPLERS <= 16);
+
+ key.bits.target = sp_texture->base.target;
+ key.bits.is_pot = sp_texture->pot;
+ key.bits.processor = processor;
+ key.bits.unit = unit;
+ key.bits.pad = 0;
+
+ if (sampler->current &&
+ key.value == sampler->current->key.value) {
+ v = sampler->current;
+ }
+
+ if (v == NULL) {
+ for (v = sampler->varients; v; v = v->next)
+ if (v->key.value == key.value)
+ break;
+
+ if (v == NULL) {
+ v = sp_create_sampler_varient( &sampler->base, key );
+ v->next = sampler->varients;
+ sampler->varients = v;
+ }
+ }
+
+ sampler->current = v;
+ return v;
+}
+
+
+
+
+void
+softpipe_reset_sampler_varients(struct softpipe_context *softpipe)
+{
+ int i;
+
+ /* It's a bit hard to build these samplers ahead of time -- don't
+ * really know which samplers are going to be used for vertex and
+ * fragment programs.
+ */
+ for (i = 0; i <= softpipe->vs->max_sampler; i++) {
+ if (softpipe->sampler[i]) {
+ softpipe->tgsi.vert_samplers_list[i] =
+ get_sampler_varient( i,
+ sp_sampler(softpipe->sampler[i]),
+ softpipe->texture[i],
+ TGSI_PROCESSOR_VERTEX );
+
+ sp_sampler_varient_bind_texture( softpipe->tgsi.vert_samplers_list[i],
+ softpipe->tex_cache[i],
+ softpipe->texture[i] );
+ }
+ }
+
+ for (i = 0; i <= softpipe->fs->info.file_max[TGSI_FILE_SAMPLER]; i++) {
+ if (softpipe->sampler[i]) {
+ softpipe->tgsi.frag_samplers_list[i] =
+ get_sampler_varient( i,
+ sp_sampler(softpipe->sampler[i]),
+ softpipe->texture[i],
+ TGSI_PROCESSOR_FRAGMENT );
+
+ sp_sampler_varient_bind_texture( softpipe->tgsi.frag_samplers_list[i],
+ softpipe->tex_cache[i],
+ softpipe->texture[i] );
+ }
+ }
+}
+
+
+
void
softpipe_delete_sampler_state(struct pipe_context *pipe,
void *sampler)
{
+ struct sp_sampler *sp_sampler = (struct sp_sampler *)sampler;
+ struct sp_sampler_varient *v, *tmp;
+
+ for (v = sp_sampler->varients; v; v = tmp) {
+ tmp = v->next;
+ sp_sampler_varient_destroy(v);
+ }
+
FREE( sampler );
}