summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/freedreno/freedreno_texture.c
diff options
context:
space:
mode:
authorRob Clark <[email protected]>2012-10-27 11:07:34 -0500
committerRob Clark <[email protected]>2013-03-11 21:53:24 -0400
commit6173cc19c45d92ef0b7bc6aa008aa89bb29abbda (patch)
tree50b2d2fca779e88ad8f143d08901dfb01fc36096 /src/gallium/drivers/freedreno/freedreno_texture.c
parent44a8e5135470fa51ae36b304f3c5286bf9cca259 (diff)
freedreno: gallium driver for adreno
Currently works on a220. Others in the a2xx family look pretty similar and should be pretty straightforward to support with the same driver. The a3xx has a new shader ISA, and while many registers appear similar, the register addresses have been completely shuffled around. I am not sure yet whether it is best to support with the same driver, but different compiler, or whether it should be split into a different driver. v1: original v2: build file updates from review comments, and remove GPL licensed header files from msm kernel v3: smarter temp/pred register assignment, fix clear and depth/stencil format issues, resource_transfer fixes, scissor fixes Signed-off-by: Rob Clark <[email protected]>
Diffstat (limited to 'src/gallium/drivers/freedreno/freedreno_texture.c')
-rw-r--r--src/gallium/drivers/freedreno/freedreno_texture.c286
1 files changed, 286 insertions, 0 deletions
diff --git a/src/gallium/drivers/freedreno/freedreno_texture.c b/src/gallium/drivers/freedreno/freedreno_texture.c
new file mode 100644
index 00000000000..07bfbd3ce36
--- /dev/null
+++ b/src/gallium/drivers/freedreno/freedreno_texture.c
@@ -0,0 +1,286 @@
+/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
+
+/*
+ * Copyright (C) 2012 Rob Clark <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Rob Clark <[email protected]>
+ */
+
+#include "pipe/p_state.h"
+#include "util/u_string.h"
+#include "util/u_memory.h"
+#include "util/u_inlines.h"
+
+#include "freedreno_texture.h"
+#include "freedreno_util.h"
+
+static enum sq_tex_clamp
+tex_clamp(unsigned wrap)
+{
+ switch (wrap) {
+ case PIPE_TEX_WRAP_REPEAT:
+ return SQ_TEX_WRAP;
+ case PIPE_TEX_WRAP_CLAMP:
+ return SQ_TEX_CLAMP_HALF_BORDER;
+ case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+ return SQ_TEX_CLAMP_LAST_TEXEL;
+ case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+ return SQ_TEX_CLAMP_BORDER;
+ case PIPE_TEX_WRAP_MIRROR_REPEAT:
+ return SQ_TEX_MIRROR;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP:
+ return SQ_TEX_MIRROR_ONCE_HALF_BORDER;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
+ return SQ_TEX_MIRROR_ONCE_LAST_TEXEL;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
+ return SQ_TEX_MIRROR_ONCE_BORDER;
+ default:
+ DBG("invalid wrap: %u", wrap);
+ return 0;
+ }
+}
+
+static enum sq_tex_filter
+tex_filter(unsigned filter)
+{
+ switch (filter) {
+ case PIPE_TEX_FILTER_NEAREST:
+ return SQ_TEX_FILTER_POINT;
+ case PIPE_TEX_FILTER_LINEAR:
+ return SQ_TEX_FILTER_BILINEAR;
+ default:
+ DBG("invalid filter: %u", filter);
+ return 0;
+ }
+}
+
+static void *
+fd_sampler_state_create(struct pipe_context *pctx,
+ const struct pipe_sampler_state *cso)
+{
+ struct fd_sampler_stateobj *so = CALLOC_STRUCT(fd_sampler_stateobj);
+
+ if (!so)
+ return NULL;
+
+ so->base = *cso;
+
+ /* SQ_TEX0_PITCH() must be OR'd in later when we know the bound texture: */
+ so->tex0 =
+ SQ_TEX0_CLAMP_X(tex_clamp(cso->wrap_s)) |
+ SQ_TEX0_CLAMP_Y(tex_clamp(cso->wrap_t)) |
+ SQ_TEX0_CLAMP_Z(tex_clamp(cso->wrap_r));
+
+ so->tex3 =
+ SQ_TEX3_XY_MAG_FILTER(tex_filter(cso->mag_img_filter)) |
+ SQ_TEX3_XY_MIN_FILTER(tex_filter(cso->min_img_filter));
+
+ so->tex4 = 0x00000000; /* ??? */
+ so->tex5 = 0x00000200; /* ??? */
+
+ return so;
+}
+
+static void
+fd_sampler_state_delete(struct pipe_context *pctx, void *hwcso)
+{
+ FREE(hwcso);
+}
+
+static struct pipe_sampler_view *
+fd_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc,
+ const struct pipe_sampler_view *cso)
+{
+ struct fd_pipe_sampler_view *so = CALLOC_STRUCT(fd_pipe_sampler_view);
+ struct fd_resource *rsc = fd_resource(prsc);
+
+ if (!so)
+ return NULL;
+
+ so->base = *cso;
+ pipe_reference(NULL, &prsc->reference);
+ so->base.texture = prsc;
+ so->base.reference.count = 1;
+ so->base.context = pctx;
+
+ so->tex_resource = rsc;
+ so->fmt = fd_pipe2surface(cso->format);
+
+ so->tex0 = SQ_TEX0_PITCH(rsc->pitch);
+ so->tex2 =
+ SQ_TEX2_HEIGHT(prsc->height0) |
+ SQ_TEX2_WIDTH(prsc->width0);
+ so->tex3 = fd_tex_swiz(cso->format, cso->swizzle_r, cso->swizzle_g,
+ cso->swizzle_b, cso->swizzle_a);
+
+ return &so->base;
+}
+
+static void
+fd_sampler_view_destroy(struct pipe_context *pctx,
+ struct pipe_sampler_view *view)
+{
+ pipe_resource_reference(&view->texture, NULL);
+ FREE(view);
+}
+
+static void bind_sampler_states(struct fd_texture_stateobj *prog,
+ unsigned nr, void **hwcso)
+{
+ unsigned i;
+
+ for (i = 0; i < nr; i++) {
+ prog->samplers[i] = hwcso[i];
+ prog->dirty_samplers |= (1 << i);
+ }
+
+ for (; i < prog->num_samplers; i++) {
+ prog->samplers[i] = NULL;
+ prog->dirty_samplers |= (1 << i);
+ }
+
+ prog->num_samplers = nr;
+}
+
+static void set_sampler_views(struct fd_texture_stateobj *prog,
+ unsigned nr, struct pipe_sampler_view **views)
+{
+ unsigned i;
+
+ for (i = 0; i < nr; i++) {
+ pipe_sampler_view_reference(&prog->textures[i], views[i]);
+ prog->dirty_samplers |= (1 << i);
+ }
+
+ for (; i < prog->num_textures; i++) {
+ pipe_sampler_view_reference(&prog->textures[i], NULL);
+ prog->dirty_samplers |= (1 << i);
+ }
+
+ prog->num_textures = nr;
+}
+
+static void
+fd_fragtex_sampler_states_bind(struct pipe_context *pctx,
+ unsigned nr, void **hwcso)
+{
+ struct fd_context *ctx = fd_context(pctx);
+ bind_sampler_states(&ctx->fragtex, nr, hwcso);
+ ctx->dirty |= FD_DIRTY_FRAGTEX;
+}
+
+
+static void
+fd_fragtex_set_sampler_views(struct pipe_context *pctx, unsigned nr,
+ struct pipe_sampler_view **views)
+{
+ struct fd_context *ctx = fd_context(pctx);
+ set_sampler_views(&ctx->fragtex, nr, views);
+ ctx->dirty |= FD_DIRTY_FRAGTEX;
+}
+
+static void
+fd_verttex_sampler_states_bind(struct pipe_context *pctx,
+ unsigned nr, void **hwcso)
+{
+ struct fd_context *ctx = fd_context(pctx);
+ bind_sampler_states(&ctx->verttex, nr, hwcso);
+ ctx->dirty |= FD_DIRTY_VERTTEX;
+}
+
+
+static void
+fd_verttex_set_sampler_views(struct pipe_context *pctx, unsigned nr,
+ struct pipe_sampler_view **views)
+{
+ struct fd_context *ctx = fd_context(pctx);
+ set_sampler_views(&ctx->verttex, nr, views);
+ ctx->dirty |= FD_DIRTY_VERTTEX;
+}
+
+static bool
+tex_cmp(struct fd_texture_stateobj *tex1, unsigned samp_id1,
+ struct fd_texture_stateobj *tex2, unsigned samp_id2)
+{
+ if ((samp_id1 >= tex1->num_samplers) ||
+ (samp_id2 >= tex2->num_samplers))
+ return false;
+
+ if ((tex1 == tex2) && (samp_id1 == samp_id2))
+ return true;
+
+ if (tex1->textures[samp_id1]->texture != tex2->textures[samp_id2]->texture)
+ return false;
+
+ if (memcmp(&tex1->samplers[samp_id1]->base, &tex2->samplers[samp_id2]->base,
+ sizeof(tex1->samplers[samp_id1]->base)))
+ return false;
+
+ return true;
+}
+
+/* map gallium sampler-id to hw const-idx.. adreno uses a flat address
+ * space of samplers (const-idx), so we need to map the gallium sampler-id
+ * which is per-shader to a global const-idx space.
+ */
+unsigned
+fd_get_const_idx(struct fd_context *ctx, struct fd_texture_stateobj *tex,
+ unsigned samp_id)
+{
+ unsigned i, const_idx = 0;
+
+ /* TODO maybe worth having some sort of cache, because we need to
+ * do this loop thru all the samplers both when patching shaders
+ * and also when emitting sampler state..
+ */
+
+ for (i = 0; i < ctx->verttex.num_samplers; i++) {
+ if (tex_cmp(&ctx->verttex, i, tex, samp_id))
+ return const_idx;
+ const_idx++;
+ }
+
+ for (i = 0; i < ctx->fragtex.num_samplers; i++) {
+ if (tex_cmp(&ctx->fragtex, i, tex, samp_id))
+ return const_idx;
+ const_idx++;
+ }
+
+ return const_idx;
+}
+
+void
+fd_texture_init(struct pipe_context *pctx)
+{
+ pctx->create_sampler_state = fd_sampler_state_create;
+ pctx->delete_sampler_state = fd_sampler_state_delete;
+
+ pctx->create_sampler_view = fd_sampler_view_create;
+ pctx->sampler_view_destroy = fd_sampler_view_destroy;
+
+ pctx->bind_fragment_sampler_states = fd_fragtex_sampler_states_bind;
+ pctx->set_fragment_sampler_views = fd_fragtex_set_sampler_views;
+
+ pctx->bind_vertex_sampler_states = fd_verttex_sampler_states_bind;
+ pctx->set_vertex_sampler_views = fd_verttex_set_sampler_views;
+}