[PATCH v2 17/17] etnaviv: GC7000: Factor out state based texture functionality

Wladimir J. van der Laan laanwj at gmail.com
Sat Nov 18 09:44:40 UTC 2017


Prepare for two texture handling paths, the descriptor-based
path will be added in a future commit. These are structured
so that the texture implementation handles its own state
emission.

Signed-off-by: Wladimir J. van der Laan <laanwj at gmail.com>
Reviewed-by: Christian Gmeiner <christian.gmeiner at gmail.com>
---
 src/gallium/drivers/etnaviv/Makefile.sources       |   2 +
 src/gallium/drivers/etnaviv/etnaviv_context.h      |   6 +
 src/gallium/drivers/etnaviv/etnaviv_emit.c         | 107 +------
 src/gallium/drivers/etnaviv/etnaviv_texture.c      | 194 ++----------
 src/gallium/drivers/etnaviv/etnaviv_texture.h      |  40 +--
 .../drivers/etnaviv/etnaviv_texture_state.c        | 329 +++++++++++++++++++++
 .../drivers/etnaviv/etnaviv_texture_state.h        |  82 +++++
 src/gallium/drivers/etnaviv/meson.build            |   2 +
 8 files changed, 454 insertions(+), 308 deletions(-)
 create mode 100644 src/gallium/drivers/etnaviv/etnaviv_texture_state.c
 create mode 100644 src/gallium/drivers/etnaviv/etnaviv_texture_state.h

- Renamed from _plain to _state.
- Remove unnecessary #include in header.
- Needed update for ASTC.
- Needed update for sampler TS: add context method ts_for_sampler_view to get
  the associated sampler TS configuration for a sampler view. This factors out
  the sampler TS unit configuration which is more or less the same,
  and also first step in handling sampler TS to sampler mapping dynamically
  which is possible on HALTI5.
- Update both meson and makefile.

diff --git a/src/gallium/drivers/etnaviv/Makefile.sources b/src/gallium/drivers/etnaviv/Makefile.sources
index 78029ad..587d369 100644
--- a/src/gallium/drivers/etnaviv/Makefile.sources
+++ b/src/gallium/drivers/etnaviv/Makefile.sources
@@ -51,6 +51,8 @@ C_SOURCES :=  \
 	etnaviv_surface.h \
 	etnaviv_texture.c \
 	etnaviv_texture.h \
+	etnaviv_texture_state.c \
+	etnaviv_texture_state.h \
 	etnaviv_tiling.c \
 	etnaviv_tiling.h \
 	etnaviv_transfer.c \
diff --git a/src/gallium/drivers/etnaviv/etnaviv_context.h b/src/gallium/drivers/etnaviv/etnaviv_context.h
index 1ed38ce..584caa7 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_context.h
+++ b/src/gallium/drivers/etnaviv/etnaviv_context.h
@@ -42,6 +42,7 @@
 
 struct pipe_screen;
 struct etna_shader_variant;
+struct etna_sampler_ts;
 
 struct etna_index_buffer {
    struct etna_reloc FE_INDEX_STREAM_BASE_ADDR;
@@ -100,6 +101,11 @@ struct etna_shader_uniform_info {
 struct etna_context {
    struct pipe_context base;
 
+   /* GPU-specific implementation to emit texture state */
+   void (*emit_texture_state)(struct etna_context *pctx);
+   /* Get sampler TS pointer for sampler view */
+   struct etna_sampler_ts *(*ts_for_sampler_view)(struct pipe_sampler_view *pview);
+
    struct etna_specs specs;
    struct etna_screen *screen;
    struct etna_cmd_stream *stream;
diff --git a/src/gallium/drivers/etnaviv/etnaviv_emit.c b/src/gallium/drivers/etnaviv/etnaviv_emit.c
index 339ecd2..85a4819 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_emit.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_emit.c
@@ -214,7 +214,6 @@ void
 etna_emit_state(struct etna_context *ctx)
 {
    struct etna_cmd_stream *stream = ctx->stream;
-   uint32_t active_samplers = active_samplers_bits(ctx);
 
    /* Pre-reserve the command buffer space which we are likely to need.
     * This must cover all the state emitted below, and the following
@@ -555,113 +554,9 @@ etna_emit_state(struct etna_context *ctx)
       /*01668*/ EMIT_STATE_RELOC(TS_DEPTH_SURFACE_BASE, &ctx->framebuffer.TS_DEPTH_SURFACE_BASE);
       /*0166C*/ EMIT_STATE(TS_DEPTH_CLEAR_VALUE, ctx->framebuffer.TS_DEPTH_CLEAR_VALUE);
    }
-   if (unlikely(dirty & ETNA_DIRTY_SAMPLER_VIEWS)) {
-      for (int x = 0; x < VIVS_TS_SAMPLER__LEN; ++x) {
-         if ((1 << x) & active_samplers) {
-            struct etna_sampler_view *sv = etna_sampler_view(ctx->sampler_view[x]);
-            /*01720*/ EMIT_STATE(TS_SAMPLER_CONFIG(x), sv->TS_SAMPLER_CONFIG);
-         }
-      }
-      for (int x = 0; x < VIVS_TS_SAMPLER__LEN; ++x) {
-         if ((1 << x) & active_samplers) {
-            struct etna_sampler_view *sv = etna_sampler_view(ctx->sampler_view[x]);
-            /*01740*/ EMIT_STATE_RELOC(TS_SAMPLER_STATUS_BASE(x), &sv->TS_SAMPLER_STATUS_BASE);
-         }
-      }
-      for (int x = 0; x < VIVS_TS_SAMPLER__LEN; ++x) {
-         if ((1 << x) & active_samplers) {
-            struct etna_sampler_view *sv = etna_sampler_view(ctx->sampler_view[x]);
-            /*01760*/ EMIT_STATE(TS_SAMPLER_CLEAR_VALUE(x), sv->TS_SAMPLER_CLEAR_VALUE);
-         }
-      }
-      for (int x = 0; x < VIVS_TS_SAMPLER__LEN; ++x) {
-         if ((1 << x) & active_samplers) {
-            struct etna_sampler_view *sv = etna_sampler_view(ctx->sampler_view[x]);
-            /*01780*/ EMIT_STATE(TS_SAMPLER_CLEAR_VALUE2(x), sv->TS_SAMPLER_CLEAR_VALUE2);
-         }
-      }
-   }
-   if (unlikely(dirty & (ETNA_DIRTY_SAMPLER_VIEWS | ETNA_DIRTY_SAMPLERS))) {
-      for (int x = 0; x < VIVS_TE_SAMPLER__LEN; ++x) {
-         uint32_t val = 0; /* 0 == sampler inactive */
-
-         /* set active samplers to their configuration value (determined by both
-          * the sampler state and sampler view) */
-         if ((1 << x) & active_samplers) {
-            struct etna_sampler_state *ss = etna_sampler_state(ctx->sampler[x]);
-            struct etna_sampler_view *sv = etna_sampler_view(ctx->sampler_view[x]);
-
-            val = (ss->TE_SAMPLER_CONFIG0 & sv->TE_SAMPLER_CONFIG0_MASK) |
-                  sv->TE_SAMPLER_CONFIG0;
-         }
-
-         /*02000*/ EMIT_STATE(TE_SAMPLER_CONFIG0(x), val);
-      }
-   }
-   if (unlikely(dirty & (ETNA_DIRTY_SAMPLER_VIEWS))) {
-      struct etna_sampler_view *sv;
-
-      for (int x = 0; x < VIVS_TE_SAMPLER__LEN; ++x) {
-         if ((1 << x) & active_samplers) {
-            sv = etna_sampler_view(ctx->sampler_view[x]);
-            /*02040*/ EMIT_STATE(TE_SAMPLER_SIZE(x), sv->TE_SAMPLER_SIZE);
-         }
-      }
-      for (int x = 0; x < VIVS_TE_SAMPLER__LEN; ++x) {
-         if ((1 << x) & active_samplers) {
-            sv = etna_sampler_view(ctx->sampler_view[x]);
-            /*02080*/ EMIT_STATE(TE_SAMPLER_LOG_SIZE(x), sv->TE_SAMPLER_LOG_SIZE);
-         }
-      }
-   }
-   if (unlikely(dirty & (ETNA_DIRTY_SAMPLER_VIEWS | ETNA_DIRTY_SAMPLERS))) {
-      struct etna_sampler_state *ss;
-      struct etna_sampler_view *sv;
-
-      for (int x = 0; x < VIVS_TE_SAMPLER__LEN; ++x) {
-         if ((1 << x) & active_samplers) {
-            ss = etna_sampler_state(ctx->sampler[x]);
-            sv = etna_sampler_view(ctx->sampler_view[x]);
-
-            /* min and max lod is determined both by the sampler and the view */
-            /*020C0*/ EMIT_STATE(TE_SAMPLER_LOD_CONFIG(x),
-                                 ss->TE_SAMPLER_LOD_CONFIG |
-                                 VIVS_TE_SAMPLER_LOD_CONFIG_MAX(MIN2(ss->max_lod, sv->max_lod)) |
-                                 VIVS_TE_SAMPLER_LOD_CONFIG_MIN(MAX2(ss->min_lod, sv->min_lod)));
-         }
-      }
-      for (int x = 0; x < VIVS_TE_SAMPLER__LEN; ++x) {
-         if ((1 << x) & active_samplers) {
-            ss = etna_sampler_state(ctx->sampler[x]);
-            sv = etna_sampler_view(ctx->sampler_view[x]);
-
-            /*021C0*/ EMIT_STATE(TE_SAMPLER_CONFIG1(x), ss->TE_SAMPLER_CONFIG1 |
-                                                        sv->TE_SAMPLER_CONFIG1);
-         }
-      }
-   }
-   if (unlikely(dirty & (ETNA_DIRTY_SAMPLER_VIEWS))) {
-      for (int y = 0; y < VIVS_TE_SAMPLER_LOD_ADDR__LEN; ++y) {
-         for (int x = 0; x < VIVS_TE_SAMPLER__LEN; ++x) {
-            if ((1 << x) & active_samplers) {
-               struct etna_sampler_view *sv = etna_sampler_view(ctx->sampler_view[x]);
-               /*02400*/ EMIT_STATE_RELOC(TE_SAMPLER_LOD_ADDR(x, y),&sv->TE_SAMPLER_LOD_ADDR[y]);
-            }
-         }
-      }
-   }
-
    if (unlikely(dirty & (ETNA_DIRTY_SHADER))) {
       /*0381C*/ EMIT_STATE(GL_VARYING_TOTAL_COMPONENTS, ctx->shader_state.GL_VARYING_TOTAL_COMPONENTS);
    }
-   if (unlikely(ctx->specs.tex_astc && (dirty & (ETNA_DIRTY_SAMPLER_VIEWS)))) {
-      for (int x = 0; x < VIVS_TE_SAMPLER__LEN; ++x) {
-         if ((1 << x) & active_samplers) {
-            struct etna_sampler_view *sv = etna_sampler_view(ctx->sampler_view[x]);
-            /*10500*/ EMIT_STATE(NTE_SAMPLER_ASTC0(x), sv->TE_SAMPLER_ASTC0);
-         }
-      }
-   }
    etna_coalesce_end(stream, &coalesce);
    /* end only EMIT_STATE */
 
@@ -671,6 +566,8 @@ etna_emit_state(struct etna_context *ctx)
    else
       emit_pre_halti5_state(ctx);
 
+   ctx->emit_texture_state(ctx);
+
    /* Insert a FE/PE stall as changing the shader instructions (and maybe
     * the uniforms) can corrupt the previous in-progress draw operation.
     * Observed with amoeba on GC2000 during the right-to-left rendering
diff --git a/src/gallium/drivers/etnaviv/etnaviv_texture.c b/src/gallium/drivers/etnaviv/etnaviv_texture.c
index 55b92f6..72ef00b 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_texture.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_texture.c
@@ -32,46 +32,13 @@
 #include "etnaviv_context.h"
 #include "etnaviv_emit.h"
 #include "etnaviv_format.h"
+#include "etnaviv_texture_state.h"
 #include "etnaviv_translate.h"
 #include "util/u_inlines.h"
 #include "util/u_memory.h"
 
 #include <drm_fourcc.h>
 
-static void *
-etna_create_sampler_state(struct pipe_context *pipe,
-                          const struct pipe_sampler_state *ss)
-{
-   struct etna_sampler_state *cs = CALLOC_STRUCT(etna_sampler_state);
-
-   if (!cs)
-      return NULL;
-
-   cs->TE_SAMPLER_CONFIG0 =
-      VIVS_TE_SAMPLER_CONFIG0_UWRAP(translate_texture_wrapmode(ss->wrap_s)) |
-      VIVS_TE_SAMPLER_CONFIG0_VWRAP(translate_texture_wrapmode(ss->wrap_t)) |
-      VIVS_TE_SAMPLER_CONFIG0_MIN(translate_texture_filter(ss->min_img_filter)) |
-      VIVS_TE_SAMPLER_CONFIG0_MIP(translate_texture_mipfilter(ss->min_mip_filter)) |
-      VIVS_TE_SAMPLER_CONFIG0_MAG(translate_texture_filter(ss->mag_img_filter)) |
-      COND(ss->normalized_coords, VIVS_TE_SAMPLER_CONFIG0_ROUND_UV);
-   cs->TE_SAMPLER_CONFIG1 = 0; /* VIVS_TE_SAMPLER_CONFIG1 (swizzle, extended
-                                  format) fully determined by sampler view */
-   cs->TE_SAMPLER_LOD_CONFIG =
-      COND(ss->lod_bias != 0.0, VIVS_TE_SAMPLER_LOD_CONFIG_BIAS_ENABLE) |
-      VIVS_TE_SAMPLER_LOD_CONFIG_BIAS(etna_float_to_fixp55(ss->lod_bias));
-
-   if (ss->min_mip_filter != PIPE_TEX_MIPFILTER_NONE) {
-      cs->min_lod = etna_float_to_fixp55(ss->min_lod);
-      cs->max_lod = etna_float_to_fixp55(ss->max_lod);
-   } else {
-      /* when not mipmapping, we need to set max/min lod so that always
-       * lowest LOD is selected */
-      cs->min_lod = cs->max_lod = etna_float_to_fixp55(ss->min_lod);
-   }
-
-   return cs;
-}
-
 static void
 etna_bind_sampler_states(struct pipe_context *pctx, enum pipe_shader_type shader,
                          unsigned start_slot, unsigned num_samplers,
@@ -107,9 +74,28 @@ etna_bind_sampler_states(struct pipe_context *pctx, enum pipe_shader_type shader
 }
 
 static void
-etna_delete_sampler_state(struct pipe_context *pctx, void *ss)
+etna_configure_sampler_ts(struct etna_sampler_ts *sts, struct pipe_sampler_view *pview, bool enable)
 {
-   FREE(ss);
+   assert(sts);
+   sts->enable = enable;
+   if (enable) {
+      struct etna_resource *rsc = etna_resource(pview->texture);
+      struct etna_resource_level *lev = &rsc->levels[0];
+      assert(rsc->ts_bo && lev->ts_valid);
+
+      sts->TS_SAMPLER_CONFIG =
+         VIVS_TS_SAMPLER_CONFIG_ENABLE(1) |
+         VIVS_TS_SAMPLER_CONFIG_FORMAT(translate_ts_sampler_format(rsc->base.format));
+      sts->TS_SAMPLER_CLEAR_VALUE = lev->clear_value;
+      sts->TS_SAMPLER_CLEAR_VALUE2 = lev->clear_value; /* To handle 64-bit formats this needs a different value */
+      sts->TS_SAMPLER_STATUS_BASE.bo = rsc->ts_bo;
+      sts->TS_SAMPLER_STATUS_BASE.offset = lev->ts_offset;
+      sts->TS_SAMPLER_STATUS_BASE.flags = ETNA_RELOC_READ;
+   } else {
+      sts->TS_SAMPLER_CONFIG = 0;
+      sts->TS_SAMPLER_STATUS_BASE.bo = NULL;
+   }
+   /* n.b.: relies on caller to mark ETNA_DIRTY_SAMPLER_VIEWS */
 }
 
 /* Return true if the GPU can use sampler TS with this sampler view.
@@ -142,36 +128,11 @@ etna_can_use_sampler_ts(struct pipe_sampler_view *view, int num)
 }
 
 static void
-etna_configure_sampler_ts(struct pipe_sampler_view *pview, bool enable)
-{
-   struct etna_sampler_view *view = etna_sampler_view(pview);
-   if (enable) {
-      struct etna_resource *rsc = etna_resource(view->base.texture);
-      struct etna_resource_level *lev = &rsc->levels[0];
-      assert(rsc->ts_bo && lev->ts_valid);
-
-      view->TE_SAMPLER_CONFIG1 |= VIVS_TE_SAMPLER_CONFIG1_USE_TS;
-      view->TS_SAMPLER_CONFIG =
-         VIVS_TS_SAMPLER_CONFIG_ENABLE(1) |
-         VIVS_TS_SAMPLER_CONFIG_FORMAT(translate_ts_sampler_format(rsc->base.format));
-      view->TS_SAMPLER_CLEAR_VALUE = lev->clear_value;
-      view->TS_SAMPLER_CLEAR_VALUE2 = lev->clear_value; /* To handle 64-bit formats this needs a different value */
-      view->TS_SAMPLER_STATUS_BASE.bo = rsc->ts_bo;
-      view->TS_SAMPLER_STATUS_BASE.offset = lev->ts_offset;
-      view->TS_SAMPLER_STATUS_BASE.flags = ETNA_RELOC_READ;
-   } else {
-      view->TE_SAMPLER_CONFIG1 &= ~VIVS_TE_SAMPLER_CONFIG1_USE_TS;
-      view->TS_SAMPLER_CONFIG = 0;
-      view->TS_SAMPLER_STATUS_BASE.bo = NULL;
-   }
-   /* n.b.: relies on caller to mark ETNA_DIRTY_SAMPLER_VIEWS */
-}
-
-static void
 etna_update_sampler_source(struct pipe_sampler_view *view, int num)
 {
    struct etna_resource *base = etna_resource(view->texture);
    struct etna_resource *to = base, *from = base;
+   struct etna_context *ctx = etna_context(view->context);
    bool enable_sampler_ts = false;
 
    if (base->external && etna_resource_newer(etna_resource(base->external), base))
@@ -185,7 +146,7 @@ etna_update_sampler_source(struct pipe_sampler_view *view, int num)
                          view->texture->last_level);
       to->seqno = from->seqno;
    } else if ((to == from) && etna_resource_needs_flush(to)) {
-      if (etna_can_use_sampler_ts(view, num)) {
+      if (ctx->ts_for_sampler_view && etna_can_use_sampler_ts(view, num)) {
          enable_sampler_ts = true;
          /* Do not set flush_seqno because the resolve-to-self was bypassed */
       } else {
@@ -195,7 +156,9 @@ etna_update_sampler_source(struct pipe_sampler_view *view, int num)
          to->flush_seqno = from->seqno;
       }
    }
-   etna_configure_sampler_ts(view, enable_sampler_ts);
+   if (ctx->ts_for_sampler_view) {
+      etna_configure_sampler_ts(ctx->ts_for_sampler_view(view), view, enable_sampler_ts);
+   }
 }
 
 static bool
@@ -251,104 +214,6 @@ etna_texture_handle_incompatible(struct pipe_context *pctx, struct pipe_resource
    return res;
 }
 
-static struct pipe_sampler_view *
-etna_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc,
-                         const struct pipe_sampler_view *so)
-{
-   struct etna_sampler_view *sv = CALLOC_STRUCT(etna_sampler_view);
-   struct etna_context *ctx = etna_context(pctx);
-   const uint32_t format = translate_texture_format(so->format);
-   const bool ext = !!(format & EXT_FORMAT);
-   const bool astc = !!(format & ASTC_FORMAT);
-   const uint32_t swiz = get_texture_swiz(so->format, so->swizzle_r,
-                                          so->swizzle_g, so->swizzle_b,
-                                          so->swizzle_a);
-
-   if (!sv)
-      return NULL;
-
-   struct etna_resource *res = etna_texture_handle_incompatible(pctx, prsc);
-   if (!res) {
-      free(sv);
-      return NULL;
-   }
-
-   sv->base = *so;
-   pipe_reference_init(&sv->base.reference, 1);
-   sv->base.texture = NULL;
-   pipe_resource_reference(&sv->base.texture, prsc);
-   sv->base.context = pctx;
-
-   /* merged with sampler state */
-   sv->TE_SAMPLER_CONFIG0 = COND(!ext && !astc, VIVS_TE_SAMPLER_CONFIG0_FORMAT(format));
-   sv->TE_SAMPLER_CONFIG0_MASK = 0xffffffff;
-
-   switch (sv->base.target) {
-   case PIPE_TEXTURE_1D:
-      /* For 1D textures, we will have a height of 1, so we can use 2D
-       * but set T wrap to repeat */
-      sv->TE_SAMPLER_CONFIG0_MASK = ~VIVS_TE_SAMPLER_CONFIG0_VWRAP__MASK;
-      sv->TE_SAMPLER_CONFIG0 |= VIVS_TE_SAMPLER_CONFIG0_VWRAP(TEXTURE_WRAPMODE_REPEAT);
-      /* fallthrough */
-   case PIPE_TEXTURE_2D:
-   case PIPE_TEXTURE_RECT:
-      sv->TE_SAMPLER_CONFIG0 |= VIVS_TE_SAMPLER_CONFIG0_TYPE(TEXTURE_TYPE_2D);
-      break;
-   case PIPE_TEXTURE_CUBE:
-      sv->TE_SAMPLER_CONFIG0 |= VIVS_TE_SAMPLER_CONFIG0_TYPE(TEXTURE_TYPE_CUBE_MAP);
-      break;
-   default:
-      BUG("Unhandled texture target");
-      free(sv);
-      return NULL;
-   }
-
-   sv->TE_SAMPLER_CONFIG1 = COND(ext, VIVS_TE_SAMPLER_CONFIG1_FORMAT_EXT(format)) |
-                            COND(astc, VIVS_TE_SAMPLER_CONFIG1_FORMAT_EXT(TEXTURE_FORMAT_EXT_ASTC)) |
-                            VIVS_TE_SAMPLER_CONFIG1_HALIGN(res->halign) | swiz;
-   sv->TE_SAMPLER_ASTC0 = COND(astc, VIVS_NTE_SAMPLER_ASTC0_ASTC_FORMAT(format)) |
-                          VIVS_NTE_SAMPLER_ASTC0_UNK8(0xc) |
-                          VIVS_NTE_SAMPLER_ASTC0_UNK16(0xc) |
-                          VIVS_NTE_SAMPLER_ASTC0_UNK24(0xc);
-   sv->TE_SAMPLER_SIZE = VIVS_TE_SAMPLER_SIZE_WIDTH(res->base.width0) |
-                         VIVS_TE_SAMPLER_SIZE_HEIGHT(res->base.height0);
-   sv->TE_SAMPLER_LOG_SIZE =
-      VIVS_TE_SAMPLER_LOG_SIZE_WIDTH(etna_log2_fixp55(res->base.width0)) |
-      VIVS_TE_SAMPLER_LOG_SIZE_HEIGHT(etna_log2_fixp55(res->base.height0)) |
-      COND(util_format_is_srgb(so->format) && !astc, VIVS_TE_SAMPLER_LOG_SIZE_SRGB) |
-      COND(astc, VIVS_TE_SAMPLER_LOG_SIZE_ASTC);
-
-   /* Set up levels-of-detail */
-   for (int lod = 0; lod <= res->base.last_level; ++lod) {
-      sv->TE_SAMPLER_LOD_ADDR[lod].bo = res->bo;
-      sv->TE_SAMPLER_LOD_ADDR[lod].offset = res->levels[lod].offset;
-      sv->TE_SAMPLER_LOD_ADDR[lod].flags = ETNA_RELOC_READ;
-   }
-   sv->min_lod = sv->base.u.tex.first_level << 5;
-   sv->max_lod = MIN2(sv->base.u.tex.last_level, res->base.last_level) << 5;
-
-   /* Workaround for npot textures -- it appears that only CLAMP_TO_EDGE is
-    * supported when the appropriate capability is not set. */
-   if (!ctx->specs.npot_tex_any_wrap &&
-       (!util_is_power_of_two(res->base.width0) || !util_is_power_of_two(res->base.height0))) {
-      sv->TE_SAMPLER_CONFIG0_MASK = ~(VIVS_TE_SAMPLER_CONFIG0_UWRAP__MASK |
-                                      VIVS_TE_SAMPLER_CONFIG0_VWRAP__MASK);
-      sv->TE_SAMPLER_CONFIG0 |=
-         VIVS_TE_SAMPLER_CONFIG0_UWRAP(TEXTURE_WRAPMODE_CLAMP_TO_EDGE) |
-         VIVS_TE_SAMPLER_CONFIG0_VWRAP(TEXTURE_WRAPMODE_CLAMP_TO_EDGE);
-   }
-
-   return &sv->base;
-}
-
-static void
-etna_sampler_view_destroy(struct pipe_context *pctx,
-                          struct pipe_sampler_view *view)
-{
-   pipe_resource_reference(&view->texture, NULL);
-   FREE(view);
-}
-
 static void
 set_sampler_views(struct etna_context *ctx, unsigned start, unsigned end,
                   unsigned nr, struct pipe_sampler_view **views)
@@ -441,11 +306,8 @@ active_samplers_bits(struct etna_context *ctx)
 void
 etna_texture_init(struct pipe_context *pctx)
 {
-   pctx->create_sampler_state = etna_create_sampler_state;
    pctx->bind_sampler_states = etna_bind_sampler_states;
-   pctx->delete_sampler_state = etna_delete_sampler_state;
    pctx->set_sampler_views = etna_set_sampler_views;
-   pctx->create_sampler_view = etna_create_sampler_view;
-   pctx->sampler_view_destroy = etna_sampler_view_destroy;
    pctx->texture_barrier = etna_texture_barrier;
+   etna_texture_state_init(pctx);
 }
diff --git a/src/gallium/drivers/etnaviv/etnaviv_texture.h b/src/gallium/drivers/etnaviv/etnaviv_texture.h
index 373e10c..b3e099b 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_texture.h
+++ b/src/gallium/drivers/etnaviv/etnaviv_texture.h
@@ -32,51 +32,17 @@
 #include "pipe/p_context.h"
 #include "pipe/p_state.h"
 
-#include "hw/state_3d.xml.h"
-
 struct etna_context;
 
-struct etna_sampler_state {
-   struct pipe_sampler_state base;
-
-   /* sampler offset +4*sampler, interleave when committing state */
-   uint32_t TE_SAMPLER_CONFIG0;
-   uint32_t TE_SAMPLER_CONFIG1;
-   uint32_t TE_SAMPLER_LOD_CONFIG;
-   unsigned min_lod, max_lod;
-};
-
-static inline struct etna_sampler_state *
-etna_sampler_state(struct pipe_sampler_state *samp)
-{
-   return (struct etna_sampler_state *)samp;
-}
-
-struct etna_sampler_view {
-   struct pipe_sampler_view base;
-
-   /* sampler offset +4*sampler, interleave when committing state */
-   uint32_t TE_SAMPLER_CONFIG0;
-   uint32_t TE_SAMPLER_CONFIG0_MASK;
-   uint32_t TE_SAMPLER_CONFIG1;
-   uint32_t TE_SAMPLER_SIZE;
-   uint32_t TE_SAMPLER_LOG_SIZE;
-   uint32_t TE_SAMPLER_ASTC0;
-   struct etna_reloc TE_SAMPLER_LOD_ADDR[VIVS_TE_SAMPLER_LOD_ADDR__LEN];
-   unsigned min_lod, max_lod; /* 5.5 fixp */
-
+struct etna_sampler_ts {
+   unsigned enable:1;
    uint32_t TS_SAMPLER_CONFIG;
    struct etna_reloc TS_SAMPLER_STATUS_BASE;
    uint32_t TS_SAMPLER_CLEAR_VALUE;
    uint32_t TS_SAMPLER_CLEAR_VALUE2;
 };
 
-static inline struct etna_sampler_view *
-etna_sampler_view(struct pipe_sampler_view *view)
-{
-   return (struct etna_sampler_view *)view;
-}
-
+/* Initialize texture methods for context. */
 void
 etna_texture_init(struct pipe_context *pctx);
 
diff --git a/src/gallium/drivers/etnaviv/etnaviv_texture_state.c b/src/gallium/drivers/etnaviv/etnaviv_texture_state.c
new file mode 100644
index 0000000..0b00ad4
--- /dev/null
+++ b/src/gallium/drivers/etnaviv/etnaviv_texture_state.c
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2012-2015 Etnaviv Project
+ *
+ * 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, sub license,
+ * 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 NON-INFRINGEMENT. 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:
+ *    Wladimir J. van der Laan <laanwj at gmail.com>
+ */
+
+#include "etnaviv_texture_state.h"
+
+#include "hw/common.xml.h"
+
+#include "etnaviv_clear_blit.h"
+#include "etnaviv_context.h"
+#include "etnaviv_emit.h"
+#include "etnaviv_format.h"
+#include "etnaviv_texture.h"
+#include "etnaviv_translate.h"
+#include "util/u_inlines.h"
+#include "util/u_memory.h"
+
+#include <drm_fourcc.h>
+
+static void *
+etna_create_sampler_state_state(struct pipe_context *pipe,
+                          const struct pipe_sampler_state *ss)
+{
+   struct etna_sampler_state *cs = CALLOC_STRUCT(etna_sampler_state);
+
+   if (!cs)
+      return NULL;
+
+   cs->TE_SAMPLER_CONFIG0 =
+      VIVS_TE_SAMPLER_CONFIG0_UWRAP(translate_texture_wrapmode(ss->wrap_s)) |
+      VIVS_TE_SAMPLER_CONFIG0_VWRAP(translate_texture_wrapmode(ss->wrap_t)) |
+      VIVS_TE_SAMPLER_CONFIG0_MIN(translate_texture_filter(ss->min_img_filter)) |
+      VIVS_TE_SAMPLER_CONFIG0_MIP(translate_texture_mipfilter(ss->min_mip_filter)) |
+      VIVS_TE_SAMPLER_CONFIG0_MAG(translate_texture_filter(ss->mag_img_filter)) |
+      COND(ss->normalized_coords, VIVS_TE_SAMPLER_CONFIG0_ROUND_UV);
+   cs->TE_SAMPLER_CONFIG1 = 0; /* VIVS_TE_SAMPLER_CONFIG1 (swizzle, extended
+                                  format) fully determined by sampler view */
+   cs->TE_SAMPLER_LOD_CONFIG =
+      COND(ss->lod_bias != 0.0, VIVS_TE_SAMPLER_LOD_CONFIG_BIAS_ENABLE) |
+      VIVS_TE_SAMPLER_LOD_CONFIG_BIAS(etna_float_to_fixp55(ss->lod_bias));
+
+   if (ss->min_mip_filter != PIPE_TEX_MIPFILTER_NONE) {
+      cs->min_lod = etna_float_to_fixp55(ss->min_lod);
+      cs->max_lod = etna_float_to_fixp55(ss->max_lod);
+   } else {
+      /* when not mipmapping, we need to set max/min lod so that always
+       * lowest LOD is selected */
+      cs->min_lod = cs->max_lod = etna_float_to_fixp55(ss->min_lod);
+   }
+
+   return cs;
+}
+
+static void
+etna_delete_sampler_state_state(struct pipe_context *pctx, void *ss)
+{
+   FREE(ss);
+}
+
+static struct pipe_sampler_view *
+etna_create_sampler_view_state(struct pipe_context *pctx, struct pipe_resource *prsc,
+                         const struct pipe_sampler_view *so)
+{
+   struct etna_sampler_view *sv = CALLOC_STRUCT(etna_sampler_view);
+   struct etna_context *ctx = etna_context(pctx);
+   const uint32_t format = translate_texture_format(so->format);
+   const bool ext = !!(format & EXT_FORMAT);
+   const bool astc = !!(format & ASTC_FORMAT);
+   const uint32_t swiz = get_texture_swiz(so->format, so->swizzle_r,
+                                          so->swizzle_g, so->swizzle_b,
+                                          so->swizzle_a);
+
+   if (!sv)
+      return NULL;
+
+   struct etna_resource *res = etna_texture_handle_incompatible(pctx, prsc);
+   if (!res) {
+      free(sv);
+      return NULL;
+   }
+
+   sv->base = *so;
+   pipe_reference_init(&sv->base.reference, 1);
+   sv->base.texture = NULL;
+   pipe_resource_reference(&sv->base.texture, prsc);
+   sv->base.context = pctx;
+
+   /* merged with sampler state */
+   sv->TE_SAMPLER_CONFIG0 = COND(!ext && !astc, VIVS_TE_SAMPLER_CONFIG0_FORMAT(format));
+   sv->TE_SAMPLER_CONFIG0_MASK = 0xffffffff;
+
+   switch (sv->base.target) {
+   case PIPE_TEXTURE_1D:
+      /* For 1D textures, we will have a height of 1, so we can use 2D
+       * but set T wrap to repeat */
+      sv->TE_SAMPLER_CONFIG0_MASK = ~VIVS_TE_SAMPLER_CONFIG0_VWRAP__MASK;
+      sv->TE_SAMPLER_CONFIG0 |= VIVS_TE_SAMPLER_CONFIG0_VWRAP(TEXTURE_WRAPMODE_REPEAT);
+      /* fallthrough */
+   case PIPE_TEXTURE_2D:
+   case PIPE_TEXTURE_RECT:
+      sv->TE_SAMPLER_CONFIG0 |= VIVS_TE_SAMPLER_CONFIG0_TYPE(TEXTURE_TYPE_2D);
+      break;
+   case PIPE_TEXTURE_CUBE:
+      sv->TE_SAMPLER_CONFIG0 |= VIVS_TE_SAMPLER_CONFIG0_TYPE(TEXTURE_TYPE_CUBE_MAP);
+      break;
+   default:
+      BUG("Unhandled texture target");
+      free(sv);
+      return NULL;
+   }
+
+   sv->TE_SAMPLER_CONFIG1 = COND(ext, VIVS_TE_SAMPLER_CONFIG1_FORMAT_EXT(format)) |
+                            COND(astc, VIVS_TE_SAMPLER_CONFIG1_FORMAT_EXT(TEXTURE_FORMAT_EXT_ASTC)) |
+                            VIVS_TE_SAMPLER_CONFIG1_HALIGN(res->halign) | swiz;
+   sv->TE_SAMPLER_ASTC0 = COND(astc, VIVS_NTE_SAMPLER_ASTC0_ASTC_FORMAT(format)) |
+                          VIVS_NTE_SAMPLER_ASTC0_UNK8(0xc) |
+                          VIVS_NTE_SAMPLER_ASTC0_UNK16(0xc) |
+                          VIVS_NTE_SAMPLER_ASTC0_UNK24(0xc);
+   sv->TE_SAMPLER_SIZE = VIVS_TE_SAMPLER_SIZE_WIDTH(res->base.width0) |
+                         VIVS_TE_SAMPLER_SIZE_HEIGHT(res->base.height0);
+   sv->TE_SAMPLER_LOG_SIZE =
+      VIVS_TE_SAMPLER_LOG_SIZE_WIDTH(etna_log2_fixp55(res->base.width0)) |
+      VIVS_TE_SAMPLER_LOG_SIZE_HEIGHT(etna_log2_fixp55(res->base.height0)) |
+      COND(util_format_is_srgb(so->format) && !astc, VIVS_TE_SAMPLER_LOG_SIZE_SRGB) |
+      COND(astc, VIVS_TE_SAMPLER_LOG_SIZE_ASTC);
+
+   /* Set up levels-of-detail */
+   for (int lod = 0; lod <= res->base.last_level; ++lod) {
+      sv->TE_SAMPLER_LOD_ADDR[lod].bo = res->bo;
+      sv->TE_SAMPLER_LOD_ADDR[lod].offset = res->levels[lod].offset;
+      sv->TE_SAMPLER_LOD_ADDR[lod].flags = ETNA_RELOC_READ;
+   }
+   sv->min_lod = sv->base.u.tex.first_level << 5;
+   sv->max_lod = MIN2(sv->base.u.tex.last_level, res->base.last_level) << 5;
+
+   /* Workaround for npot textures -- it appears that only CLAMP_TO_EDGE is
+    * supported when the appropriate capability is not set. */
+   if (!ctx->specs.npot_tex_any_wrap &&
+       (!util_is_power_of_two(res->base.width0) || !util_is_power_of_two(res->base.height0))) {
+      sv->TE_SAMPLER_CONFIG0_MASK = ~(VIVS_TE_SAMPLER_CONFIG0_UWRAP__MASK |
+                                      VIVS_TE_SAMPLER_CONFIG0_VWRAP__MASK);
+      sv->TE_SAMPLER_CONFIG0 |=
+         VIVS_TE_SAMPLER_CONFIG0_UWRAP(TEXTURE_WRAPMODE_CLAMP_TO_EDGE) |
+         VIVS_TE_SAMPLER_CONFIG0_VWRAP(TEXTURE_WRAPMODE_CLAMP_TO_EDGE);
+   }
+
+   return &sv->base;
+}
+
+static void
+etna_sampler_view_state_destroy(struct pipe_context *pctx,
+                          struct pipe_sampler_view *view)
+{
+   pipe_resource_reference(&view->texture, NULL);
+   FREE(view);
+}
+
+#define EMIT_STATE(state_name, src_value) \
+   etna_coalsence_emit(stream, &coalesce, VIVS_##state_name, src_value)
+
+#define EMIT_STATE_FIXP(state_name, src_value) \
+   etna_coalsence_emit_fixp(stream, &coalesce, VIVS_##state_name, src_value)
+
+#define EMIT_STATE_RELOC(state_name, src_value) \
+   etna_coalsence_emit_reloc(stream, &coalesce, VIVS_##state_name, src_value)
+
+/* Emit plain (non-descriptor) texture state */
+static void
+etna_emit_texture_state(struct etna_context *ctx)
+{
+   struct etna_cmd_stream *stream = ctx->stream;
+   uint32_t active_samplers = active_samplers_bits(ctx);
+   uint32_t dirty = ctx->dirty;
+   struct etna_coalesce coalesce;
+
+   etna_coalesce_start(stream, &coalesce);
+
+   if (unlikely(dirty & ETNA_DIRTY_SAMPLER_VIEWS)) {
+      for (int x = 0; x < VIVS_TS_SAMPLER__LEN; ++x) {
+         if ((1 << x) & active_samplers) {
+            struct etna_sampler_view *sv = etna_sampler_view(ctx->sampler_view[x]);
+            /*01720*/ EMIT_STATE(TS_SAMPLER_CONFIG(x), sv->ts.TS_SAMPLER_CONFIG);
+         }
+      }
+      for (int x = 0; x < VIVS_TS_SAMPLER__LEN; ++x) {
+         if ((1 << x) & active_samplers) {
+            struct etna_sampler_view *sv = etna_sampler_view(ctx->sampler_view[x]);
+            /*01740*/ EMIT_STATE_RELOC(TS_SAMPLER_STATUS_BASE(x), &sv->ts.TS_SAMPLER_STATUS_BASE);
+         }
+      }
+      for (int x = 0; x < VIVS_TS_SAMPLER__LEN; ++x) {
+         if ((1 << x) & active_samplers) {
+            struct etna_sampler_view *sv = etna_sampler_view(ctx->sampler_view[x]);
+            /*01760*/ EMIT_STATE(TS_SAMPLER_CLEAR_VALUE(x), sv->ts.TS_SAMPLER_CLEAR_VALUE);
+         }
+      }
+      for (int x = 0; x < VIVS_TS_SAMPLER__LEN; ++x) {
+         if ((1 << x) & active_samplers) {
+            struct etna_sampler_view *sv = etna_sampler_view(ctx->sampler_view[x]);
+            /*01780*/ EMIT_STATE(TS_SAMPLER_CLEAR_VALUE2(x), sv->ts.TS_SAMPLER_CLEAR_VALUE2);
+         }
+      }
+   }
+   if (unlikely(dirty & (ETNA_DIRTY_SAMPLER_VIEWS | ETNA_DIRTY_SAMPLERS))) {
+      for (int x = 0; x < VIVS_TE_SAMPLER__LEN; ++x) {
+         uint32_t val = 0; /* 0 == sampler inactive */
+
+         /* set active samplers to their configuration value (determined by both
+          * the sampler state and sampler view) */
+         if ((1 << x) & active_samplers) {
+            struct etna_sampler_state *ss = etna_sampler_state(ctx->sampler[x]);
+            struct etna_sampler_view *sv = etna_sampler_view(ctx->sampler_view[x]);
+
+            val = (ss->TE_SAMPLER_CONFIG0 & sv->TE_SAMPLER_CONFIG0_MASK) |
+                  sv->TE_SAMPLER_CONFIG0;
+         }
+
+         /*02000*/ EMIT_STATE(TE_SAMPLER_CONFIG0(x), val);
+      }
+   }
+   if (unlikely(dirty & (ETNA_DIRTY_SAMPLER_VIEWS))) {
+      struct etna_sampler_view *sv;
+
+      for (int x = 0; x < VIVS_TE_SAMPLER__LEN; ++x) {
+         if ((1 << x) & active_samplers) {
+            sv = etna_sampler_view(ctx->sampler_view[x]);
+            /*02040*/ EMIT_STATE(TE_SAMPLER_SIZE(x), sv->TE_SAMPLER_SIZE);
+         }
+      }
+      for (int x = 0; x < VIVS_TE_SAMPLER__LEN; ++x) {
+         if ((1 << x) & active_samplers) {
+            sv = etna_sampler_view(ctx->sampler_view[x]);
+            /*02080*/ EMIT_STATE(TE_SAMPLER_LOG_SIZE(x), sv->TE_SAMPLER_LOG_SIZE);
+         }
+      }
+   }
+   if (unlikely(dirty & (ETNA_DIRTY_SAMPLER_VIEWS | ETNA_DIRTY_SAMPLERS))) {
+      struct etna_sampler_state *ss;
+      struct etna_sampler_view *sv;
+
+      for (int x = 0; x < VIVS_TE_SAMPLER__LEN; ++x) {
+         if ((1 << x) & active_samplers) {
+            ss = etna_sampler_state(ctx->sampler[x]);
+            sv = etna_sampler_view(ctx->sampler_view[x]);
+
+            /* min and max lod is determined both by the sampler and the view */
+            /*020C0*/ EMIT_STATE(TE_SAMPLER_LOD_CONFIG(x),
+                                 ss->TE_SAMPLER_LOD_CONFIG |
+                                 VIVS_TE_SAMPLER_LOD_CONFIG_MAX(MIN2(ss->max_lod, sv->max_lod)) |
+                                 VIVS_TE_SAMPLER_LOD_CONFIG_MIN(MAX2(ss->min_lod, sv->min_lod)));
+         }
+      }
+      for (int x = 0; x < VIVS_TE_SAMPLER__LEN; ++x) {
+         if ((1 << x) & active_samplers) {
+            ss = etna_sampler_state(ctx->sampler[x]);
+            sv = etna_sampler_view(ctx->sampler_view[x]);
+
+            /*021C0*/ EMIT_STATE(TE_SAMPLER_CONFIG1(x), ss->TE_SAMPLER_CONFIG1 |
+                                                        sv->TE_SAMPLER_CONFIG1 |
+                                                        COND(sv->ts.enable, VIVS_TE_SAMPLER_CONFIG1_USE_TS));
+         }
+      }
+   }
+   if (unlikely(dirty & (ETNA_DIRTY_SAMPLER_VIEWS))) {
+      for (int y = 0; y < VIVS_TE_SAMPLER_LOD_ADDR__LEN; ++y) {
+         for (int x = 0; x < VIVS_TE_SAMPLER__LEN; ++x) {
+            if ((1 << x) & active_samplers) {
+               struct etna_sampler_view *sv = etna_sampler_view(ctx->sampler_view[x]);
+               /*02400*/ EMIT_STATE_RELOC(TE_SAMPLER_LOD_ADDR(x, y),&sv->TE_SAMPLER_LOD_ADDR[y]);
+            }
+         }
+      }
+   }
+   if (unlikely(ctx->specs.tex_astc && (dirty & (ETNA_DIRTY_SAMPLER_VIEWS)))) {
+      for (int x = 0; x < VIVS_TE_SAMPLER__LEN; ++x) {
+         if ((1 << x) & active_samplers) {
+            struct etna_sampler_view *sv = etna_sampler_view(ctx->sampler_view[x]);
+            /*10500*/ EMIT_STATE(NTE_SAMPLER_ASTC0(x), sv->TE_SAMPLER_ASTC0);
+         }
+      }
+   }
+   etna_coalesce_end(stream, &coalesce);
+}
+
+#undef EMIT_STATE
+#undef EMIT_STATE_FIXP
+#undef EMIT_STATE_RELOC
+
+static struct etna_sampler_ts*
+etna_ts_for_sampler_view_state(struct pipe_sampler_view *pview)
+{
+   struct etna_sampler_view *sv = etna_sampler_view(pview);
+   return &sv->ts;
+}
+
+void
+etna_texture_state_init(struct pipe_context *pctx)
+{
+   struct etna_context *ctx = etna_context(pctx);
+   DBG("etnaviv: Using state-based texturing\n");
+   ctx->base.create_sampler_state = etna_create_sampler_state_state;
+   ctx->base.delete_sampler_state = etna_delete_sampler_state_state;
+   ctx->base.create_sampler_view = etna_create_sampler_view_state;
+   ctx->base.sampler_view_destroy = etna_sampler_view_state_destroy;
+   ctx->emit_texture_state = etna_emit_texture_state;
+   ctx->ts_for_sampler_view = etna_ts_for_sampler_view_state;
+}
diff --git a/src/gallium/drivers/etnaviv/etnaviv_texture_state.h b/src/gallium/drivers/etnaviv/etnaviv_texture_state.h
new file mode 100644
index 0000000..86bbcb3
--- /dev/null
+++ b/src/gallium/drivers/etnaviv/etnaviv_texture_state.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2012-2015 Etnaviv Project
+ *
+ * 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, sub license,
+ * 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 NON-INFRINGEMENT. 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:
+ *    Wladimir J. van der Laan <laanwj at gmail.com>
+ */
+
+#ifndef H_ETNAVIV_TEXTURE_PLAIN
+#define H_ETNAVIV_TEXTURE_PLAIN
+
+#include <etnaviv_drmif.h>
+
+#include "etnaviv_texture.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+
+#include "hw/state_3d.xml.h"
+
+struct etna_sampler_state {
+   struct pipe_sampler_state base;
+
+   /* sampler offset +4*sampler, interleave when committing state */
+   uint32_t TE_SAMPLER_CONFIG0;
+   uint32_t TE_SAMPLER_CONFIG1;
+   uint32_t TE_SAMPLER_LOD_CONFIG;
+   unsigned min_lod, max_lod;
+};
+
+static inline struct etna_sampler_state *
+etna_sampler_state(struct pipe_sampler_state *samp)
+{
+   return (struct etna_sampler_state *)samp;
+}
+
+struct etna_sampler_view {
+   struct pipe_sampler_view base;
+
+   /* sampler offset +4*sampler, interleave when committing state */
+   uint32_t TE_SAMPLER_CONFIG0;
+   uint32_t TE_SAMPLER_CONFIG0_MASK;
+   uint32_t TE_SAMPLER_CONFIG1;
+   uint32_t TE_SAMPLER_SIZE;
+   uint32_t TE_SAMPLER_LOG_SIZE;
+   uint32_t TE_SAMPLER_ASTC0;
+   struct etna_reloc TE_SAMPLER_LOD_ADDR[VIVS_TE_SAMPLER_LOD_ADDR__LEN];
+   unsigned min_lod, max_lod; /* 5.5 fixp */
+
+   struct etna_sampler_ts ts;
+};
+
+static inline struct etna_sampler_view *
+etna_sampler_view(struct pipe_sampler_view *view)
+{
+   return (struct etna_sampler_view *)view;
+}
+
+/* Initialize context for "plain" (non-descriptor, state-based) texture views
+ * and descriptors */
+void
+etna_texture_state_init(struct pipe_context *pctx);
+
+#endif
diff --git a/src/gallium/drivers/etnaviv/meson.build b/src/gallium/drivers/etnaviv/meson.build
index f9128ae..ac0231e 100644
--- a/src/gallium/drivers/etnaviv/meson.build
+++ b/src/gallium/drivers/etnaviv/meson.build
@@ -70,6 +70,8 @@ files_etnaviv = files(
   'etnaviv_surface.h',
   'etnaviv_texture.c',
   'etnaviv_texture.h',
+  'etnaviv_texture_state.c',
+  'etnaviv_texture_state.h',
   'etnaviv_tiling.c',
   'etnaviv_tiling.h',
   'etnaviv_transfer.c',
-- 
2.7.4



More information about the etnaviv mailing list