etnaviv: enable texture upload memory throttling
[mesa.git] / src / gallium / drivers / etnaviv / etnaviv_texture_state.c
index ef2a7bd581ca682732fa3fc370f433b6730a09fe..84d0e00be004f78b5db328ca08776e2536a3bfbb 100644 (file)
 #include "util/u_inlines.h"
 #include "util/u_memory.h"
 
-#include <drm_fourcc.h>
+#include "drm-uapi/drm_fourcc.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;
+   uint32_t TE_SAMPLER_3D_CONFIG;
+   uint32_t NTE_SAMPLER_BASELOD;
+   unsigned min_lod, max_lod, max_lod_min;
+};
+
+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_3D_CONFIG;
+   uint32_t TE_SAMPLER_SIZE;
+   uint32_t TE_SAMPLER_LOG_SIZE;
+   uint32_t TE_SAMPLER_ASTC0;
+   uint32_t TE_SAMPLER_LINEAR_STRIDE[VIVS_TE_SAMPLER_LINEAR_STRIDE__LEN];
+   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;
+}
 
 static void *
 etna_create_sampler_state_state(struct pipe_context *pipe,
@@ -53,14 +95,24 @@ etna_create_sampler_state_state(struct pipe_context *pipe,
       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 */
+      VIVS_TE_SAMPLER_CONFIG0_MAG(translate_texture_filter(ss->mag_img_filter));
+
+   /* ROUND_UV improves precision - but not compatible with NEAREST filter */
+   if (ss->min_img_filter != PIPE_TEX_FILTER_NEAREST &&
+       ss->mag_img_filter != PIPE_TEX_FILTER_NEAREST) {
+      cs->TE_SAMPLER_CONFIG0 |= VIVS_TE_SAMPLER_CONFIG0_ROUND_UV;
+   }
+
+   cs->TE_SAMPLER_CONFIG1 =
+      COND(ss->seamless_cube_map, VIVS_TE_SAMPLER_CONFIG1_SEAMLESS_CUBE_MAP);
+
    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));
 
+   cs->TE_SAMPLER_3D_CONFIG =
+      VIVS_TE_SAMPLER_3D_CONFIG_WRAP(translate_texture_wrapmode(ss->wrap_r));
+
    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);
@@ -70,6 +122,16 @@ etna_create_sampler_state_state(struct pipe_context *pipe,
       cs->min_lod = cs->max_lod = etna_float_to_fixp55(ss->min_lod);
    }
 
+   /* if max_lod is 0, MIN filter will never be used (GC3000)
+    * when min filter is different from mag filter, we need HW to compute LOD
+    * the workaround is to set max_lod to at least 1
+    */
+   cs->max_lod_min = (ss->min_img_filter != ss->mag_img_filter) ? 1 : 0;
+
+   cs->NTE_SAMPLER_BASELOD =
+      COND(ss->compare_mode, VIVS_NTE_SAMPLER_BASELOD_COMPARE_ENABLE) |
+      VIVS_NTE_SAMPLER_BASELOD_COMPARE_FUNC(translate_texture_compare(ss->compare_func));
+
    return cs;
 }
 
@@ -88,6 +150,7 @@ etna_create_sampler_view_state(struct pipe_context *pctx, struct pipe_resource *
    const uint32_t format = translate_texture_format(so->format);
    const bool ext = !!(format & EXT_FORMAT);
    const bool astc = !!(format & ASTC_FORMAT);
+   const bool srgb = util_format_is_srgb(so->format);
    const uint32_t swiz = get_texture_swiz(so->format, so->swizzle_r,
                                           so->swizzle_g, so->swizzle_b,
                                           so->swizzle_a);
@@ -108,30 +171,39 @@ etna_create_sampler_view_state(struct pipe_context *pctx, struct pipe_resource *
    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 =
+      VIVS_TE_SAMPLER_CONFIG0_TYPE(translate_texture_target(sv->base.target)) |
+      COND(!ext && !astc, VIVS_TE_SAMPLER_CONFIG0_FORMAT(format));
    sv->TE_SAMPLER_CONFIG0_MASK = 0xffffffff;
 
+   uint32_t base_height = res->base.height0;
+   uint32_t base_depth = res->base.depth0;
+   bool is_array = false;
+
    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 */
+      /* use 2D texture with T wrap to repeat for 1D texture
+       * TODO: check if old HW supports 1D texture
+       */
       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);
+      sv->TE_SAMPLER_CONFIG0 &= ~VIVS_TE_SAMPLER_CONFIG0_TYPE__MASK;
+      sv->TE_SAMPLER_CONFIG0 |=
+         VIVS_TE_SAMPLER_CONFIG0_TYPE(TEXTURE_TYPE_2D) |
+         VIVS_TE_SAMPLER_CONFIG0_VWRAP(TEXTURE_WRAPMODE_REPEAT);
       break;
-   case PIPE_TEXTURE_CUBE:
-      sv->TE_SAMPLER_CONFIG0 |= VIVS_TE_SAMPLER_CONFIG0_TYPE(TEXTURE_TYPE_CUBE_MAP);
+   case PIPE_TEXTURE_1D_ARRAY:
+      is_array = true;
+      base_height = res->base.array_size;
+      break;
+   case PIPE_TEXTURE_2D_ARRAY:
+      is_array = true;
+      base_depth = res->base.array_size;
       break;
    default:
-      BUG("Unhandled texture target");
-      free(sv);
-      return NULL;
+      break;
    }
 
-   if (res->addressing_mode == ETNA_ADDRESSING_MODE_LINEAR) {
+   if (res->layout == ETNA_LAYOUT_LINEAR && !util_format_is_compressed(so->format)) {
       sv->TE_SAMPLER_CONFIG0 |= VIVS_TE_SAMPLER_CONFIG0_ADDRESSING_MODE(TEXTURE_ADDRESSING_MODE_LINEAR);
 
       for (int lod = 0; lod <= res->base.last_level; ++lod)
@@ -142,20 +214,26 @@ etna_create_sampler_view_state(struct pipe_context *pctx, struct pipe_resource *
       memset(&sv->TE_SAMPLER_LINEAR_STRIDE, 0, sizeof(sv->TE_SAMPLER_LINEAR_STRIDE));
    }
 
-   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_CONFIG1 |= COND(ext, VIVS_TE_SAMPLER_CONFIG1_FORMAT_EXT(format)) |
+                             COND(astc, VIVS_TE_SAMPLER_CONFIG1_FORMAT_EXT(TEXTURE_FORMAT_EXT_ASTC)) |
+                             COND(is_array, VIVS_TE_SAMPLER_CONFIG1_TEXTURE_ARRAY) |
+                             VIVS_TE_SAMPLER_CONFIG1_HALIGN(res->halign) | swiz;
    sv->TE_SAMPLER_ASTC0 = COND(astc, VIVS_NTE_SAMPLER_ASTC0_ASTC_FORMAT(format)) |
+                          COND(astc && srgb, VIVS_NTE_SAMPLER_ASTC0_ASTC_SRGB) |
                           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);
+                         VIVS_TE_SAMPLER_SIZE_HEIGHT(base_height);
    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)) |
+      VIVS_TE_SAMPLER_LOG_SIZE_HEIGHT(etna_log2_fixp55(base_height)) |
       COND(util_format_is_srgb(so->format) && !astc, VIVS_TE_SAMPLER_LOG_SIZE_SRGB) |
-      COND(astc, VIVS_TE_SAMPLER_LOG_SIZE_ASTC);
+      COND(astc, VIVS_TE_SAMPLER_LOG_SIZE_ASTC) |
+      COND(texture_use_int_filter(so, false), VIVS_TE_SAMPLER_LOG_SIZE_INT_FILTER);
+   sv->TE_SAMPLER_3D_CONFIG =
+      VIVS_TE_SAMPLER_3D_CONFIG_DEPTH(base_depth) |
+      VIVS_TE_SAMPLER_3D_CONFIG_LOG_DEPTH(etna_log2_fixp55(base_depth));
 
    /* Set up levels-of-detail */
    for (int lod = 0; lod <= res->base.last_level; ++lod) {
@@ -277,10 +355,12 @@ etna_emit_texture_state(struct etna_context *ctx)
             ss = etna_sampler_state(ctx->sampler[x]);
             sv = etna_sampler_view(ctx->sampler_view[x]);
 
+            unsigned max_lod = MAX2(MIN2(ss->max_lod, sv->max_lod), ss->max_lod_min);
+
             /* 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_MAX(max_lod) |
                                  VIVS_TE_SAMPLER_LOD_CONFIG_MIN(MAX2(ss->min_lod, sv->min_lod)));
          }
       }
@@ -289,6 +369,15 @@ etna_emit_texture_state(struct etna_context *ctx)
             ss = etna_sampler_state(ctx->sampler[x]);
             sv = etna_sampler_view(ctx->sampler_view[x]);
 
+            /*02180*/ EMIT_STATE(TE_SAMPLER_3D_CONFIG(x), ss->TE_SAMPLER_3D_CONFIG |
+                                                          sv->TE_SAMPLER_3D_CONFIG);
+         }
+      }
+      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));
@@ -323,6 +412,14 @@ etna_emit_texture_state(struct etna_context *ctx)
          }
       }
    }
+   if (unlikely(ctx->specs.halti >= 1 && (dirty & (ETNA_DIRTY_SAMPLER_VIEWS)))) {
+      for (int x = 0; x < VIVS_TE_SAMPLER__LEN; ++x) {
+         if ((1 << x) & active_samplers) {
+            struct etna_sampler_state *ss = etna_sampler_state(ctx->sampler[x]);
+            /*10700*/ EMIT_STATE(NTE_SAMPLER_BASELOD(x), ss->NTE_SAMPLER_BASELOD);
+         }
+      }
+   }
    etna_coalesce_end(stream, &coalesce);
 }