st/xorg: s/free/FREE for matching MALLOC/CALLOC
[mesa.git] / src / gallium / state_trackers / xorg / xorg_exa_tgsi.c
index cfee10c3b30ed79ed9853dbe57b9f64395f56661..fe1aab3ab981675341bc24a68b35b92fe909da16 100644 (file)
@@ -6,11 +6,9 @@
 #include "pipe/p_format.h"
 #include "pipe/p_context.h"
 #include "pipe/p_state.h"
-#include "pipe/p_inlines.h"
 #include "pipe/p_shader_tokens.h"
 
 #include "util/u_memory.h"
-#include "util/u_simple_shaders.h"
 
 #include "tgsi/tgsi_ureg.h"
 
  * OUT[0] = color
  */
 
+static void
+print_fs_traits(int fs_traits)
+{
+   const char *strings[] = {
+      "FS_COMPOSITE",       /* = 1 << 0, */
+      "FS_MASK",            /* = 1 << 1, */
+      "FS_SOLID_FILL",      /* = 1 << 2, */
+      "FS_LINGRAD_FILL",    /* = 1 << 3, */
+      "FS_RADGRAD_FILL",    /* = 1 << 4, */
+      "FS_CA_FULL",         /* = 1 << 5, */ /* src.rgba * mask.rgba */
+      "FS_CA_SRCALPHA",     /* = 1 << 6, */ /* src.aaaa * mask.rgba */
+      "FS_YUV",             /* = 1 << 7, */
+      "FS_SRC_REPEAT_NONE", /* = 1 << 8, */
+      "FS_MASK_REPEAT_NONE",/* = 1 << 9, */
+      "FS_SRC_SWIZZLE_RGB", /* = 1 << 10, */
+      "FS_MASK_SWIZZLE_RGB",/* = 1 << 11, */
+      "FS_SRC_SET_ALPHA",   /* = 1 << 12, */
+      "FS_MASK_SET_ALPHA",  /* = 1 << 13, */
+      "FS_SRC_LUMINANCE",   /* = 1 << 14, */
+      "FS_MASK_LUMINANCE",  /* = 1 << 15, */
+   };
+   int i, k;
+   debug_printf("%s: ", __func__);
+
+   for (i = 0, k = 1; k < (1 << 16); i++, k <<= 1) {
+      if (fs_traits & k)
+         debug_printf("%s, ", strings[i]);
+   }
+
+   debug_printf("\n");
+}
+
 struct xorg_shaders {
-   struct exa_context *exa;
+   struct xorg_renderer *r;
 
    struct cso_hash *vs_hash;
    struct cso_hash *fs_hash;
 };
 
-static const char over_op[] =
-   "SUB TEMP[3], CONST[0].wwww, TEMP[1].wwww\n"
-   "MUL TEMP[3], TEMP[0], TEMP[3]\n"
-   "ADD TEMP[0], TEMP[3], TEMP[0]\n";
-
-
-static INLINE void
-create_preamble(struct ureg_program *ureg)
-{
-}
-
-
 static INLINE void
 src_in_mask(struct ureg_program *ureg,
             struct ureg_dst dst,
             struct ureg_src src,
-            struct ureg_src mask)
+            struct ureg_src mask,
+            unsigned component_alpha,
+            unsigned mask_luminance)
 {
-   /* MUL dst, src, mask.wwww */
-   ureg_MUL(ureg, dst, src,
-            ureg_scalar(mask, TGSI_SWIZZLE_W));
+   if (component_alpha == FS_CA_FULL) {
+      ureg_MUL(ureg, dst, src, mask);
+   } else if (component_alpha == FS_CA_SRCALPHA) {
+      ureg_MUL(ureg, dst,
+               ureg_scalar(src, TGSI_SWIZZLE_W), mask);
+   }
+   else {
+      if (mask_luminance)
+         ureg_MUL(ureg, dst, src,
+                  ureg_scalar(mask, TGSI_SWIZZLE_X));
+      else
+         ureg_MUL(ureg, dst, src,
+                  ureg_scalar(mask, TGSI_SWIZZLE_W));
+   }
 }
 
 static struct ureg_src
@@ -79,8 +110,7 @@ vs_normalize_coords(struct ureg_program *ureg, struct ureg_src coords,
 {
    struct ureg_dst tmp = ureg_DECL_temporary(ureg);
    struct ureg_src ret;
-   ureg_MUL(ureg, tmp, coords, const0);
-   ureg_ADD(ureg, tmp, ureg_src(tmp), const1);
+   ureg_MAD(ureg, tmp, coords, const0, const1);
    ret = ureg_src(tmp);
    ureg_release_temporary(ureg, tmp);
    return ret;
@@ -238,45 +268,49 @@ create_vs(struct pipe_context *pipe,
    struct ureg_src src;
    struct ureg_dst dst;
    struct ureg_src const0, const1;
-   boolean is_fill = vs_traits & VS_FILL;
-   boolean is_composite = vs_traits & VS_COMPOSITE;
-   boolean has_mask = vs_traits & VS_MASK;
+   boolean is_fill = (vs_traits & VS_FILL) != 0;
+   boolean is_composite = (vs_traits & VS_COMPOSITE) != 0;
+   boolean has_mask = (vs_traits & VS_MASK) != 0;
+   boolean is_yuv = (vs_traits & VS_YUV) != 0;
+   unsigned input_slot = 0;
 
    ureg = ureg_create(TGSI_PROCESSOR_VERTEX);
    if (ureg == NULL)
       return 0;
 
-   const0 = ureg_DECL_constant(ureg);
-   const1 = ureg_DECL_constant(ureg);
+   const0 = ureg_DECL_constant(ureg, 0);
+   const1 = ureg_DECL_constant(ureg, 1);
 
    /* it has to be either a fill or a composite op */
-   debug_assert(is_fill ^ is_composite);
+   debug_assert((is_fill ^ is_composite) ^ is_yuv);
 
-   src = ureg_DECL_vs_input(ureg,
-                            TGSI_SEMANTIC_POSITION, 0);
+   src = ureg_DECL_vs_input(ureg, input_slot++);
    dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
    src = vs_normalize_coords(ureg, src,
                              const0, const1);
    ureg_MOV(ureg, dst, src);
 
+   if (is_yuv) {
+      src = ureg_DECL_vs_input(ureg, input_slot++);
+      dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0);
+      ureg_MOV(ureg, dst, src);
+   }
 
    if (is_composite) {
-      src = ureg_DECL_vs_input(ureg,
-                               TGSI_SEMANTIC_GENERIC, 1);
-      dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 1);
+      src = ureg_DECL_vs_input(ureg, input_slot++);
+      dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0);
       ureg_MOV(ureg, dst, src);
    }
+
    if (is_fill) {
-      src = ureg_DECL_vs_input(ureg,
-                               TGSI_SEMANTIC_COLOR, 1);
-      dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 1);
+      src = ureg_DECL_vs_input(ureg, input_slot++);
+      dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
       ureg_MOV(ureg, dst, src);
    }
 
    if (has_mask) {
-      src = ureg_DECL_vs_input(ureg,
-                               TGSI_SEMANTIC_GENERIC, 2);
-      dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 2);
+      src = ureg_DECL_vs_input(ureg, input_slot++);
+      dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 1);
       ureg_MOV(ureg, dst, src);
    }
 
@@ -285,6 +319,138 @@ create_vs(struct pipe_context *pipe,
    return ureg_create_shader_and_destroy(ureg, pipe);
 }
 
+static void *
+create_yuv_shader(struct pipe_context *pipe, struct ureg_program *ureg)
+{
+   struct ureg_src y_sampler, u_sampler, v_sampler;
+   struct ureg_src pos;
+   struct ureg_src matrow0, matrow1, matrow2;
+   struct ureg_dst y, u, v, rgb;
+   struct ureg_dst out = ureg_DECL_output(ureg,
+                                          TGSI_SEMANTIC_COLOR,
+                                          0);
+
+   pos = ureg_DECL_fs_input(ureg,
+                            TGSI_SEMANTIC_GENERIC,
+                            0,
+                            TGSI_INTERPOLATE_PERSPECTIVE);
+
+   rgb = ureg_DECL_temporary(ureg);
+   y = ureg_DECL_temporary(ureg);
+   u = ureg_DECL_temporary(ureg);
+   v = ureg_DECL_temporary(ureg);
+
+   y_sampler = ureg_DECL_sampler(ureg, 0);
+   u_sampler = ureg_DECL_sampler(ureg, 1);
+   v_sampler = ureg_DECL_sampler(ureg, 2);
+
+   matrow0 = ureg_DECL_constant(ureg, 0);
+   matrow1 = ureg_DECL_constant(ureg, 1);
+   matrow2 = ureg_DECL_constant(ureg, 2);
+
+   ureg_TEX(ureg, y,
+            TGSI_TEXTURE_2D, pos, y_sampler);
+   ureg_TEX(ureg, u,
+            TGSI_TEXTURE_2D, pos, u_sampler);
+   ureg_TEX(ureg, v,
+            TGSI_TEXTURE_2D, pos, v_sampler);
+
+   ureg_SUB(ureg, u, ureg_src(u),
+            ureg_scalar(matrow0, TGSI_SWIZZLE_W));
+   ureg_SUB(ureg, v, ureg_src(v),
+            ureg_scalar(matrow0, TGSI_SWIZZLE_W));
+
+   ureg_MUL(ureg, rgb,
+            ureg_scalar(ureg_src(y), TGSI_SWIZZLE_X),
+            matrow0);
+   ureg_MAD(ureg, rgb,
+            ureg_scalar(ureg_src(u), TGSI_SWIZZLE_X),
+            matrow1,
+            ureg_src(rgb));
+   ureg_MAD(ureg, rgb,
+            ureg_scalar(ureg_src(v), TGSI_SWIZZLE_X),
+            matrow2,
+            ureg_src(rgb));
+
+   /* rgb.a = 1; */
+   ureg_MOV(ureg, ureg_writemask(rgb, TGSI_WRITEMASK_W),
+            ureg_scalar(matrow0, TGSI_SWIZZLE_X));
+
+   ureg_MOV(ureg, out, ureg_src(rgb));
+
+   ureg_release_temporary(ureg, rgb);
+   ureg_release_temporary(ureg, y);
+   ureg_release_temporary(ureg, u);
+   ureg_release_temporary(ureg, v);
+
+   ureg_END(ureg);
+
+   return ureg_create_shader_and_destroy(ureg, pipe);
+}
+
+
+static INLINE void
+xrender_tex(struct ureg_program *ureg,
+            struct ureg_dst dst,
+            struct ureg_src coords,
+            struct ureg_src sampler,
+            struct ureg_src imm0,
+            boolean repeat_none,
+            boolean swizzle,
+            boolean set_alpha)
+{
+   if (repeat_none) {
+      struct ureg_dst tmp0 = ureg_DECL_temporary(ureg);
+      struct ureg_dst tmp1 = ureg_DECL_temporary(ureg);
+      ureg_SGT(ureg, tmp1, ureg_swizzle(coords,
+                                        TGSI_SWIZZLE_X,
+                                        TGSI_SWIZZLE_Y,
+                                        TGSI_SWIZZLE_X,
+                                        TGSI_SWIZZLE_Y),
+               ureg_scalar(imm0, TGSI_SWIZZLE_X));
+      ureg_SLT(ureg, tmp0, ureg_swizzle(coords,
+                                        TGSI_SWIZZLE_X,
+                                        TGSI_SWIZZLE_Y,
+                                        TGSI_SWIZZLE_X,
+                                        TGSI_SWIZZLE_Y),
+               ureg_scalar(imm0, TGSI_SWIZZLE_W));
+      ureg_MIN(ureg, tmp0, ureg_src(tmp0), ureg_src(tmp1));
+      ureg_MIN(ureg, tmp0, ureg_scalar(ureg_src(tmp0), TGSI_SWIZZLE_X),
+               ureg_scalar(ureg_src(tmp0), TGSI_SWIZZLE_Y));
+      ureg_TEX(ureg, tmp1, TGSI_TEXTURE_2D, coords, sampler);
+      if (swizzle)
+         ureg_MOV(ureg, tmp1, ureg_swizzle(ureg_src(tmp1),
+                                           TGSI_SWIZZLE_Z,
+                                           TGSI_SWIZZLE_Y,
+                                           TGSI_SWIZZLE_X,
+                                           TGSI_SWIZZLE_W));
+      if (set_alpha)
+         ureg_MOV(ureg,
+                  ureg_writemask(tmp1, TGSI_WRITEMASK_W),
+                  ureg_scalar(imm0, TGSI_SWIZZLE_W));
+      ureg_MUL(ureg, dst, ureg_src(tmp1), ureg_src(tmp0));
+      ureg_release_temporary(ureg, tmp0);
+      ureg_release_temporary(ureg, tmp1);
+   } else {
+      if (swizzle) {
+         struct ureg_dst tmp = ureg_DECL_temporary(ureg);
+         ureg_TEX(ureg, tmp, TGSI_TEXTURE_2D, coords, sampler);
+         ureg_MOV(ureg, dst, ureg_swizzle(ureg_src(tmp),
+                                          TGSI_SWIZZLE_Z,
+                                          TGSI_SWIZZLE_Y,
+                                          TGSI_SWIZZLE_X,
+                                          TGSI_SWIZZLE_W));
+         ureg_release_temporary(ureg, tmp);
+      } else {
+         ureg_TEX(ureg, dst, TGSI_TEXTURE_2D, coords, sampler);
+      }
+      if (set_alpha)
+         ureg_MOV(ureg,
+                  ureg_writemask(dst, TGSI_WRITEMASK_W),
+                  ureg_scalar(imm0, TGSI_SWIZZLE_W));
+   }
+}
+
 static void *
 create_fs(struct pipe_context *pipe,
           unsigned fs_traits)
@@ -294,32 +460,54 @@ create_fs(struct pipe_context *pipe,
    struct ureg_src /*dst_pos,*/ src_input, mask_pos;
    struct ureg_dst src, mask;
    struct ureg_dst out;
-   boolean has_mask = fs_traits & FS_MASK;
-   boolean is_fill = fs_traits & FS_FILL;
-   boolean is_composite = fs_traits & FS_COMPOSITE;
-   boolean is_solid   = fs_traits & FS_SOLID_FILL;
-   boolean is_lingrad = fs_traits & FS_LINGRAD_FILL;
-   boolean is_radgrad = fs_traits & FS_RADGRAD_FILL;
+   struct ureg_src imm0 = { 0 };
+   unsigned has_mask = (fs_traits & FS_MASK) != 0;
+   unsigned is_fill = (fs_traits & FS_FILL) != 0;
+   unsigned is_composite = (fs_traits & FS_COMPOSITE) != 0;
+   unsigned is_solid   = (fs_traits & FS_SOLID_FILL) != 0;
+   unsigned is_lingrad = (fs_traits & FS_LINGRAD_FILL) != 0;
+   unsigned is_radgrad = (fs_traits & FS_RADGRAD_FILL) != 0;
+   unsigned comp_alpha_mask = fs_traits & FS_COMPONENT_ALPHA;
+   unsigned is_yuv = (fs_traits & FS_YUV) != 0;
+   unsigned src_repeat_none = (fs_traits & FS_SRC_REPEAT_NONE) != 0;
+   unsigned mask_repeat_none = (fs_traits & FS_MASK_REPEAT_NONE) != 0;
+   unsigned src_swizzle = (fs_traits & FS_SRC_SWIZZLE_RGB) != 0;
+   unsigned mask_swizzle = (fs_traits & FS_MASK_SWIZZLE_RGB) != 0;
+   unsigned src_set_alpha = (fs_traits & FS_SRC_SET_ALPHA) != 0;
+   unsigned mask_set_alpha = (fs_traits & FS_MASK_SET_ALPHA) != 0;
+   unsigned src_luminance = (fs_traits & FS_SRC_LUMINANCE) != 0;
+   unsigned mask_luminance = (fs_traits & FS_MASK_LUMINANCE) != 0;
+
+#if 0
+   print_fs_traits(fs_traits);
+#else
+   (void)print_fs_traits;
+#endif
 
    ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
    if (ureg == NULL)
       return 0;
 
-   /* it has to be either a fill or a composite op */
-   debug_assert(is_fill ^ is_composite);
+   /* it has to be either a fill, a composite op or a yuv conversion */
+   debug_assert((is_fill ^ is_composite) ^ is_yuv);
+   (void) is_yuv;
 
    out = ureg_DECL_output(ureg,
                           TGSI_SEMANTIC_COLOR,
                           0);
 
+   if (src_repeat_none || mask_repeat_none ||
+       src_set_alpha || mask_set_alpha ||
+       src_luminance) {
+      imm0 = ureg_imm4f(ureg, 0, 0, 0, 1);
+   }
    if (is_composite) {
       src_sampler = ureg_DECL_sampler(ureg, 0);
       src_input = ureg_DECL_fs_input(ureg,
-                                     TGSI_SEMANTIC_POSITION,
+                                     TGSI_SEMANTIC_GENERIC,
                                      0,
                                      TGSI_INTERPOLATE_PERSPECTIVE);
-   }
-   if (is_fill) {
+   } else if (is_fill) {
       if (is_solid)
          src_input = ureg_DECL_fs_input(ureg,
                                         TGSI_SEMANTIC_COLOR,
@@ -330,12 +518,15 @@ create_fs(struct pipe_context *pipe,
                                         TGSI_SEMANTIC_POSITION,
                                         0,
                                         TGSI_INTERPOLATE_PERSPECTIVE);
+   } else {
+      debug_assert(is_yuv);
+      return create_yuv_shader(pipe, ureg);
    }
 
    if (has_mask) {
       mask_sampler = ureg_DECL_sampler(ureg, 1);
       mask_pos = ureg_DECL_fs_input(ureg,
-                                    TGSI_SEMANTIC_POSITION,
+                                    TGSI_SEMANTIC_GENERIC,
                                     1,
                                     TGSI_INTERPOLATE_PERSPECTIVE);
    }
@@ -348,16 +539,17 @@ create_fs(struct pipe_context *pipe,
                                 TGSI_INTERPOLATE_PERSPECTIVE);
 #endif
 
+
    if (is_composite) {
-      if (has_mask)
+      if (has_mask || src_luminance)
          src = ureg_DECL_temporary(ureg);
       else
          src = out;
-      ureg_TEX(ureg, src,
-               TGSI_TEXTURE_2D, src_input, src_sampler);
+      xrender_tex(ureg, src, src_input, src_sampler, imm0,
+                  src_repeat_none, src_swizzle, src_set_alpha);
    } else if (is_fill) {
       if (is_solid) {
-         if (has_mask)
+         if (has_mask || src_luminance)
             src = ureg_dst(src_input);
          else
             ureg_MOV(ureg, out, src_input);
@@ -365,16 +557,16 @@ create_fs(struct pipe_context *pipe,
          struct ureg_src coords, const0124,
             matrow0, matrow1, matrow2;
 
-         if (has_mask)
+         if (has_mask || src_luminance)
             src = ureg_DECL_temporary(ureg);
          else
             src = out;
 
-         coords = ureg_DECL_constant(ureg);
-         const0124 = ureg_DECL_constant(ureg);
-         matrow0 = ureg_DECL_constant(ureg);
-         matrow1 = ureg_DECL_constant(ureg);
-         matrow2 = ureg_DECL_constant(ureg);
+         coords = ureg_DECL_constant(ureg, 0);
+         const0124 = ureg_DECL_constant(ureg, 1);
+         matrow0 = ureg_DECL_constant(ureg, 2);
+         matrow1 = ureg_DECL_constant(ureg, 3);
+         matrow2 = ureg_DECL_constant(ureg, 4);
 
          if (is_lingrad) {
             linear_gradient(ureg, src,
@@ -390,13 +582,22 @@ create_fs(struct pipe_context *pipe,
       } else
          debug_assert(!"Unknown fill type!");
    }
+   if (src_luminance) {
+      ureg_MOV(ureg, src,
+               ureg_scalar(ureg_src(src), TGSI_SWIZZLE_X));
+      ureg_MOV(ureg, ureg_writemask(src, TGSI_WRITEMASK_XYZ),
+               ureg_scalar(imm0, TGSI_SWIZZLE_X));
+      if (!has_mask)
+         ureg_MOV(ureg, out, ureg_src(src));
+   }
 
    if (has_mask) {
       mask = ureg_DECL_temporary(ureg);
-      ureg_TEX(ureg, mask,
-               TGSI_TEXTURE_2D, mask_pos, mask_sampler);
+      xrender_tex(ureg, mask, mask_pos, mask_sampler, imm0,
+                  mask_repeat_none, mask_swizzle, mask_set_alpha);
       /* src IN mask */
-      src_in_mask(ureg, out, ureg_src(src), ureg_src(mask));
+      src_in_mask(ureg, out, ureg_src(src), ureg_src(mask),
+                  comp_alpha_mask, mask_luminance);
       ureg_release_temporary(ureg, mask);
    }
 
@@ -405,11 +606,11 @@ create_fs(struct pipe_context *pipe,
    return ureg_create_shader_and_destroy(ureg, pipe);
 }
 
-struct xorg_shaders * xorg_shaders_create(struct exa_context *exa)
+struct xorg_shaders * xorg_shaders_create(struct xorg_renderer *r)
 {
    struct xorg_shaders *sc = CALLOC_STRUCT(xorg_shaders);
 
-   sc->exa = exa;
+   sc->r = r;
    sc->vs_hash = cso_hash_create();
    sc->fs_hash = cso_hash_create();
 
@@ -436,12 +637,12 @@ cache_destroy(struct cso_context *cso,
 
 void xorg_shaders_destroy(struct xorg_shaders *sc)
 {
-   cache_destroy(sc->exa->cso, sc->vs_hash,
+   cache_destroy(sc->r->cso, sc->vs_hash,
                  PIPE_SHADER_VERTEX);
-   cache_destroy(sc->exa->cso, sc->fs_hash,
+   cache_destroy(sc->r->cso, sc->fs_hash,
                  PIPE_SHADER_FRAGMENT);
 
-   free(sc);
+   FREE(sc);
 }
 
 static INLINE void *
@@ -470,12 +671,12 @@ struct xorg_shader xorg_shaders_get(struct xorg_shaders *sc,
                                     unsigned vs_traits,
                                     unsigned fs_traits)
 {
-   struct xorg_shader shader = {0};
+   struct xorg_shader shader = { NULL, NULL };
    void *vs, *fs;
 
-   vs = shader_from_cache(sc->exa->ctx, PIPE_SHADER_VERTEX,
+   vs = shader_from_cache(sc->r->pipe, PIPE_SHADER_VERTEX,
                           sc->vs_hash, vs_traits);
-   fs = shader_from_cache(sc->exa->ctx, PIPE_SHADER_FRAGMENT,
+   fs = shader_from_cache(sc->r->pipe, PIPE_SHADER_FRAGMENT,
                           sc->fs_hash, fs_traits);
 
    debug_assert(vs && fs);