Re: [Mesa-dev] [PATCH 6/8] etnaviv: use filter blit for 2D YUV import on old GC320

2019-04-26 Thread Christian Gmeiner
Am Fr., 12. Apr. 2019 um 19:38 Uhr schrieb Lucas Stach :
>
> The GC320 without the 2D tiling feature doesn't support regular blits
> with YUV input, as well as the tiled output. So on those cores we need
> need to do a filter blit for the YUV->RGB conversion to a temporary
> linear buffer and then do a tiling blit into the texture buffer using
> the RS engine on the 3D core.
>
> Not the most efficient path, but at least gives us the same level of
> functionality as on the newer GC320 cores and looks the same to the
> application.
>
> Signed-off-by: Lucas Stach 
> ---
>  src/gallium/drivers/etnaviv/etnaviv_2d.c | 198 ---
>  1 file changed, 180 insertions(+), 18 deletions(-)
>
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_2d.c 
> b/src/gallium/drivers/etnaviv/etnaviv_2d.c
> index 457fa4e0cbd0..31b6bf4313dd 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_2d.c
> +++ b/src/gallium/drivers/etnaviv/etnaviv_2d.c
> @@ -25,13 +25,16 @@
>  #include "etnaviv_context.h"
>  #include "etnaviv_emit.h"
>  #include "etnaviv_screen.h"
> +#include "etnaviv_rs.h"
>
>  #include "pipe/p_state.h"
>  #include "util/u_format.h"
>
>  #include "hw/state_2d.xml.h"
> +#include "hw/common.xml.h"
>

Sort includes in alphabetic order.


>  #include 
> +#include 
>
>  #define EMIT_STATE(state_name, src_value) \
> etna_coalsence_emit(stream, , VIVS_##state_name, src_value)
> @@ -39,15 +42,85 @@
>  #define EMIT_STATE_RELOC(state_name, src_value) \
> etna_coalsence_emit_reloc(stream, , VIVS_##state_name, src_value)
>
> +/* stolen from xf86-video-armada */
> +#define KERNEL_ROWS 17
> +#define KERNEL_INDICES  9
> +#define KERNEL_SIZE (KERNEL_ROWS * KERNEL_INDICES)
> +#define KERNEL_STATE_SZ ((KERNEL_SIZE + 1) / 2)
> +
> +static bool filter_kernel_initialized;
> +static uint32_t filter_kernel[KERNEL_STATE_SZ];
> +
> +static inline float
> +sinc (float x)
> +{
> +  return x != 0.0 ? sinf (x) / x : 1.0;
> +}
> +
> +static void
> +etnaviv_init_filter_kernel(void)
> +{
> +   unsigned row, idx, i;
> +   int16_t kernel_val[KERNEL_STATE_SZ * 2];
> +   float row_ofs = 0.5;
> +   float radius = 4.0;
> +
> +   /* Compute lanczos filter kernel */
> +   for (row = i = 0; row < KERNEL_ROWS; row++) {
> +  float kernel[KERNEL_INDICES] = { 0.0 };
> +  float sum = 0.0;
> +
> +  for (idx = 0; idx < KERNEL_INDICES; idx++) {
> + float x = idx - 4.0 + row_ofs;
> +
> + if (fabs (x) <= radius)
> +kernel[idx] = sinc (M_PI * x) * sinc (M_PI * x / radius);
> +
> + sum += kernel[idx];
> +   }
> +
> +   /* normalise the row */
> +   if (sum)
> +  for (idx = 0; idx < KERNEL_INDICES; idx++)
> + kernel[idx] /= sum;
> +
> +   /* convert to 1.14 format */
> +   for (idx = 0; idx < KERNEL_INDICES; idx++) {
> +  int val = kernel[idx] * (float) (1 << 14);
> +
> +  if (val < -0x8000)
> + val = -0x8000;
> +  else if (val > 0x7fff)
> + val = 0x7fff;
> +
> +  kernel_val[i++] = val;
> +   }
> +
> +   row_ofs -= 1.0 / ((KERNEL_ROWS - 1) * 2);
> +   }
> +
> +   kernel_val[KERNEL_SIZE] = 0;
> +
> +   /* Now convert the kernel values into state values */
> +   for (i = 0; i < KERNEL_STATE_SZ * 2; i += 2)
> +  filter_kernel[i / 2] =
> + VIVS_DE_FILTER_KERNEL_COEFFICIENT0 (kernel_val[i]) |
> + VIVS_DE_FILTER_KERNEL_COEFFICIENT1 (kernel_val[i + 1]);
> +}
> +
>  bool etna_try_2d_blit(struct pipe_context *pctx,
>const struct pipe_blit_info *blit_info)
>  {
> struct etna_context *ctx = etna_context(pctx);
> +   struct etna_screen *screen = ctx->screen;
> struct etna_cmd_stream *stream = ctx->stream2d;
> struct etna_coalesce coalesce;
> struct etna_reloc ry, ru, rv, rdst;
> struct pipe_resource *res_y, *res_u, *res_v, *res_dst;
> +   struct etna_bo *temp_bo = NULL;
> uint32_t src_format;
> +   bool ext_blt = VIV_2D_FEATURE(screen, chipMinorFeatures2, 2D_TILING);
> +   uint32_t dst_config;
>
> assert(util_format_is_yuv(blit_info->src.format));
> assert(blit_info->dst.format == PIPE_FORMAT_R8G8B8A8_UNORM);
> @@ -55,6 +128,11 @@ bool etna_try_2d_blit(struct pipe_context *pctx,
> if (!stream)
>return FALSE;
>
> +  if (unlikely(!ext_blt && !filter_kernel_initialized)) {
> +  etnaviv_init_filter_kernel();
> +  filter_kernel_initialized = true;
> +  }
> +
> switch (blit_info->src.format) {
> case PIPE_FORMAT_NV12:
>src_format = DE_FORMAT_NV12;
> @@ -66,6 +144,18 @@ bool etna_try_2d_blit(struct pipe_context *pctx,
>return FALSE;
  retutn false;
> }
>
> +   res_dst = blit_info->dst.resource;
> +
> +   if (!ext_blt && etna_resource(res_dst)->layout != ETNA_LAYOUT_LINEAR) {
> +  struct etna_resource *dst = etna_resource(blit_info->dst.resource);
> +  unsigned int bo_size = dst->levels[blit_info->dst.level].stride *
> + 

Re: [Mesa-dev] [PATCH 6/8] etnaviv: use filter blit for 2D YUV import on old GC320

2019-04-15 Thread Philipp Zabel
On Fri, 2019-04-12 at 19:38 +0200, Lucas Stach wrote:
> The GC320 without the 2D tiling feature doesn't support regular blits
> with YUV input, as well as the tiled output. So on those cores we need
> need to do a filter blit for the YUV->RGB conversion to a temporary
> linear buffer and then do a tiling blit into the texture buffer using
> the RS engine on the 3D core.
> 
> Not the most efficient path, but at least gives us the same level of
> functionality as on the newer GC320 cores and looks the same to the
> application.
> 
> Signed-off-by: Lucas Stach 
> ---
>  src/gallium/drivers/etnaviv/etnaviv_2d.c | 198 ---
>  1 file changed, 180 insertions(+), 18 deletions(-)
> 
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_2d.c 
> b/src/gallium/drivers/etnaviv/etnaviv_2d.c
> index 457fa4e0cbd0..31b6bf4313dd 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_2d.c
> +++ b/src/gallium/drivers/etnaviv/etnaviv_2d.c
> @@ -25,13 +25,16 @@
>  #include "etnaviv_context.h"
>  #include "etnaviv_emit.h"
>  #include "etnaviv_screen.h"
> +#include "etnaviv_rs.h"
>  
>  #include "pipe/p_state.h"
>  #include "util/u_format.h"
>  
>  #include "hw/state_2d.xml.h"
> +#include "hw/common.xml.h"
>  
>  #include 
> +#include 
>  
>  #define EMIT_STATE(state_name, src_value) \
> etna_coalsence_emit(stream, , VIVS_##state_name, src_value)
> @@ -39,15 +42,85 @@
>  #define EMIT_STATE_RELOC(state_name, src_value) \
> etna_coalsence_emit_reloc(stream, , VIVS_##state_name, src_value)
>  
> +/* stolen from xf86-video-armada */
> +#define KERNEL_ROWS 17
> +#define KERNEL_INDICES  9
> +#define KERNEL_SIZE (KERNEL_ROWS * KERNEL_INDICES)
> +#define KERNEL_STATE_SZ ((KERNEL_SIZE + 1) / 2)
> +
> +static bool filter_kernel_initialized;
> +static uint32_t filter_kernel[KERNEL_STATE_SZ];
> +
> +static inline float
> +sinc (float x)
   ^
> +{
> +  return x != 0.0 ? sinf (x) / x : 1.0;
   ^
> +}
> +
> +static void
> +etnaviv_init_filter_kernel(void)
> +{
> +   unsigned row, idx, i;
> +   int16_t kernel_val[KERNEL_STATE_SZ * 2];
> +   float row_ofs = 0.5;
> +   float radius = 4.0;
> +
> +   /* Compute lanczos filter kernel */
> +   for (row = i = 0; row < KERNEL_ROWS; row++) {
> +  float kernel[KERNEL_INDICES] = { 0.0 };
> +  float sum = 0.0;
> +
> +  for (idx = 0; idx < KERNEL_INDICES; idx++) {
> + float x = idx - 4.0 + row_ofs;
> +
> + if (fabs (x) <= radius)
> +kernel[idx] = sinc (M_PI * x) * sinc (M_PI * x / radius);
 ^ ^

Why the whitespace?

> +
> + sum += kernel[idx];
> +   }
> +
> +   /* normalise the row */
> +   if (sum)
> +  for (idx = 0; idx < KERNEL_INDICES; idx++)
> + kernel[idx] /= sum;
> +
> +   /* convert to 1.14 format */
> +   for (idx = 0; idx < KERNEL_INDICES; idx++) {
> +  int val = kernel[idx] * (float) (1 << 14);
> +
> +  if (val < -0x8000)
> + val = -0x8000;
> +  else if (val > 0x7fff)
> + val = 0x7fff;
> +
> +  kernel_val[i++] = val;
> +   }
> +
> +   row_ofs -= 1.0 / ((KERNEL_ROWS - 1) * 2);
> +   }
> +
> +   kernel_val[KERNEL_SIZE] = 0;
> +
> +   /* Now convert the kernel values into state values */
> +   for (i = 0; i < KERNEL_STATE_SZ * 2; i += 2)
> +  filter_kernel[i / 2] =
> + VIVS_DE_FILTER_KERNEL_COEFFICIENT0 (kernel_val[i]) |
> + VIVS_DE_FILTER_KERNEL_COEFFICIENT1 (kernel_val[i + 1]);
> +}
> +
>  bool etna_try_2d_blit(struct pipe_context *pctx,
>const struct pipe_blit_info *blit_info)
>  {
> struct etna_context *ctx = etna_context(pctx);
> +   struct etna_screen *screen = ctx->screen;
> struct etna_cmd_stream *stream = ctx->stream2d;
> struct etna_coalesce coalesce;
> struct etna_reloc ry, ru, rv, rdst;
> struct pipe_resource *res_y, *res_u, *res_v, *res_dst;
> +   struct etna_bo *temp_bo = NULL;
> uint32_t src_format;
> +   bool ext_blt = VIV_2D_FEATURE(screen, chipMinorFeatures2, 2D_TILING);
> +   uint32_t dst_config;
>  
> assert(util_format_is_yuv(blit_info->src.format));
> assert(blit_info->dst.format == PIPE_FORMAT_R8G8B8A8_UNORM);
> @@ -55,6 +128,11 @@ bool etna_try_2d_blit(struct pipe_context *pctx,
> if (!stream)
>return FALSE;
>  
> +  if (unlikely(!ext_blt && !filter_kernel_initialized)) {
> +  etnaviv_init_filter_kernel();
> +  filter_kernel_initialized = true;
> +  }
> +
> switch (blit_info->src.format) {
> case PIPE_FORMAT_NV12:
>src_format = DE_FORMAT_NV12;
> @@ -66,6 +144,18 @@ bool etna_try_2d_blit(struct pipe_context *pctx,
>return FALSE;
> }
>  
> +   res_dst = blit_info->dst.resource;
> +
> +   if (!ext_blt && etna_resource(res_dst)->layout != ETNA_LAYOUT_LINEAR) {
> +  struct etna_resource *dst = etna_resource(blit_info->dst.resource);
> +  unsigned int bo_size = dst->levels[blit_info->dst.level].stride 

[Mesa-dev] [PATCH 6/8] etnaviv: use filter blit for 2D YUV import on old GC320

2019-04-12 Thread Lucas Stach
The GC320 without the 2D tiling feature doesn't support regular blits
with YUV input, as well as the tiled output. So on those cores we need
need to do a filter blit for the YUV->RGB conversion to a temporary
linear buffer and then do a tiling blit into the texture buffer using
the RS engine on the 3D core.

Not the most efficient path, but at least gives us the same level of
functionality as on the newer GC320 cores and looks the same to the
application.

Signed-off-by: Lucas Stach 
---
 src/gallium/drivers/etnaviv/etnaviv_2d.c | 198 ---
 1 file changed, 180 insertions(+), 18 deletions(-)

diff --git a/src/gallium/drivers/etnaviv/etnaviv_2d.c 
b/src/gallium/drivers/etnaviv/etnaviv_2d.c
index 457fa4e0cbd0..31b6bf4313dd 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_2d.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_2d.c
@@ -25,13 +25,16 @@
 #include "etnaviv_context.h"
 #include "etnaviv_emit.h"
 #include "etnaviv_screen.h"
+#include "etnaviv_rs.h"
 
 #include "pipe/p_state.h"
 #include "util/u_format.h"
 
 #include "hw/state_2d.xml.h"
+#include "hw/common.xml.h"
 
 #include 
+#include 
 
 #define EMIT_STATE(state_name, src_value) \
etna_coalsence_emit(stream, , VIVS_##state_name, src_value)
@@ -39,15 +42,85 @@
 #define EMIT_STATE_RELOC(state_name, src_value) \
etna_coalsence_emit_reloc(stream, , VIVS_##state_name, src_value)
 
+/* stolen from xf86-video-armada */
+#define KERNEL_ROWS 17
+#define KERNEL_INDICES  9
+#define KERNEL_SIZE (KERNEL_ROWS * KERNEL_INDICES)
+#define KERNEL_STATE_SZ ((KERNEL_SIZE + 1) / 2)
+
+static bool filter_kernel_initialized;
+static uint32_t filter_kernel[KERNEL_STATE_SZ];
+
+static inline float
+sinc (float x)
+{
+  return x != 0.0 ? sinf (x) / x : 1.0;
+}
+
+static void
+etnaviv_init_filter_kernel(void)
+{
+   unsigned row, idx, i;
+   int16_t kernel_val[KERNEL_STATE_SZ * 2];
+   float row_ofs = 0.5;
+   float radius = 4.0;
+
+   /* Compute lanczos filter kernel */
+   for (row = i = 0; row < KERNEL_ROWS; row++) {
+  float kernel[KERNEL_INDICES] = { 0.0 };
+  float sum = 0.0;
+
+  for (idx = 0; idx < KERNEL_INDICES; idx++) {
+ float x = idx - 4.0 + row_ofs;
+
+ if (fabs (x) <= radius)
+kernel[idx] = sinc (M_PI * x) * sinc (M_PI * x / radius);
+
+ sum += kernel[idx];
+   }
+
+   /* normalise the row */
+   if (sum)
+  for (idx = 0; idx < KERNEL_INDICES; idx++)
+ kernel[idx] /= sum;
+
+   /* convert to 1.14 format */
+   for (idx = 0; idx < KERNEL_INDICES; idx++) {
+  int val = kernel[idx] * (float) (1 << 14);
+
+  if (val < -0x8000)
+ val = -0x8000;
+  else if (val > 0x7fff)
+ val = 0x7fff;
+
+  kernel_val[i++] = val;
+   }
+
+   row_ofs -= 1.0 / ((KERNEL_ROWS - 1) * 2);
+   }
+
+   kernel_val[KERNEL_SIZE] = 0;
+
+   /* Now convert the kernel values into state values */
+   for (i = 0; i < KERNEL_STATE_SZ * 2; i += 2)
+  filter_kernel[i / 2] =
+ VIVS_DE_FILTER_KERNEL_COEFFICIENT0 (kernel_val[i]) |
+ VIVS_DE_FILTER_KERNEL_COEFFICIENT1 (kernel_val[i + 1]);
+}
+
 bool etna_try_2d_blit(struct pipe_context *pctx,
   const struct pipe_blit_info *blit_info)
 {
struct etna_context *ctx = etna_context(pctx);
+   struct etna_screen *screen = ctx->screen;
struct etna_cmd_stream *stream = ctx->stream2d;
struct etna_coalesce coalesce;
struct etna_reloc ry, ru, rv, rdst;
struct pipe_resource *res_y, *res_u, *res_v, *res_dst;
+   struct etna_bo *temp_bo = NULL;
uint32_t src_format;
+   bool ext_blt = VIV_2D_FEATURE(screen, chipMinorFeatures2, 2D_TILING);
+   uint32_t dst_config;
 
assert(util_format_is_yuv(blit_info->src.format));
assert(blit_info->dst.format == PIPE_FORMAT_R8G8B8A8_UNORM);
@@ -55,6 +128,11 @@ bool etna_try_2d_blit(struct pipe_context *pctx,
if (!stream)
   return FALSE;
 
+  if (unlikely(!ext_blt && !filter_kernel_initialized)) {
+  etnaviv_init_filter_kernel();
+  filter_kernel_initialized = true;
+  }
+
switch (blit_info->src.format) {
case PIPE_FORMAT_NV12:
   src_format = DE_FORMAT_NV12;
@@ -66,6 +144,18 @@ bool etna_try_2d_blit(struct pipe_context *pctx,
   return FALSE;
}
 
+   res_dst = blit_info->dst.resource;
+
+   if (!ext_blt && etna_resource(res_dst)->layout != ETNA_LAYOUT_LINEAR) {
+  struct etna_resource *dst = etna_resource(blit_info->dst.resource);
+  unsigned int bo_size = dst->levels[blit_info->dst.level].stride *
+ dst->levels[blit_info->dst.level].padded_height;
+
+  temp_bo = etna_bo_new(screen->dev, bo_size, DRM_ETNA_GEM_CACHE_WC);
+  if (!temp_bo)
+ return FALSE;
+   }
+
res_y = blit_info->src.resource;
res_u = res_y->next ? res_y->next : res_y;
res_v = res_u->next ? res_u->next : res_u;
@@ -79,8 +169,7 @@ bool etna_try_2d_blit(struct pipe_context *pctx,
 
ry.flags = ru.flags = rv.flags =