st/egl: Remove.
[mesa.git] / src / gallium / state_trackers / vega / shaders_cache.c
index fd0831fab1f70ee27b598b975f4c03ee9d342c46..c1082ca3673c5469020627ea32b3dc748a4c97b3 100644 (file)
@@ -30,8 +30,6 @@
 
 #include "pipe/p_context.h"
 #include "pipe/p_defines.h"
-#include "pipe/p_inlines.h"
-#include "pipe/p_screen.h"
 #include "pipe/p_shader_tokens.h"
 
 #include "tgsi/tgsi_build.h"
 
 /* Essentially we construct an ubber-shader based on the state
  * of the pipeline. The stages are:
- * 1) Fill (mandatory, solid color/gradient/pattern/image draw)
- * 2) Image composition (image mode multiply and stencil)
- * 3) Mask
- * 4) Extended blend (multiply/screen/darken/lighten)
- * 5) Premultiply/Unpremultiply
- * 6) Color transform (to black and white)
+ * 1) Paint generation (color/gradient/pattern)
+ * 2) Image composition (normal/multiply/stencil)
+ * 3) Color transform
+ * 4) Per-channel alpha generation
+ * 5) Extended blend (multiply/screen/darken/lighten)
+ * 6) Mask
+ * 7) Premultiply/Unpremultiply
+ * 8) Color transform (to black and white)
  */
-#define SHADER_STAGES 6
+#define SHADER_STAGES 8
 
 struct cached_shader {
    void *driver_shader;
@@ -88,16 +88,9 @@ static INLINE struct tgsi_token *tokens_from_assembly(const char *txt, int num_t
    return tokens;
 }
 
-#define ALL_FILLS (VEGA_SOLID_FILL_SHADER | \
-   VEGA_LINEAR_GRADIENT_SHADER | \
-   VEGA_RADIAL_GRADIENT_SHADER | \
-   VEGA_PATTERN_SHADER         | \
-   VEGA_IMAGE_NORMAL_SHADER)
-
-
 /*
 static const char max_shader_preamble[] =
-   "FRAG1.1\n"
+   "FRAG\n"
    "DCL IN[0], POSITION, LINEAR\n"
    "DCL IN[1], GENERIC[0], PERSPECTIVE\n"
    "DCL OUT[0], COLOR, CONSTANT\n"
@@ -123,17 +116,23 @@ static INLINE VGint range_max(VGint max, VGint current)
    return MAX2(max, current);
 }
 
-static void
-create_preamble(char *txt,
-                const struct shader_asm_info *shaders[SHADER_STAGES],
-                int num_shaders)
+static void *
+combine_shaders(const struct shader_asm_info *shaders[SHADER_STAGES], int num_shaders,
+                struct pipe_context *pipe,
+                struct pipe_shader_state *shader)
 {
    VGboolean declare_input = VG_FALSE;
    VGint start_const   = -1, end_const   = 0;
    VGint start_temp    = -1, end_temp    = 0;
    VGint start_sampler = -1, end_sampler = 0;
-   VGint i;
+   VGint i, current_shader = 0;
    VGint num_consts, num_temps, num_samplers;
+   struct ureg_program *ureg;
+   struct ureg_src in[2];
+   struct ureg_src *sampler = NULL;
+   struct ureg_src *constant = NULL;
+   struct ureg_dst out, *temp = NULL;
+   void *p = NULL;
 
    for (i = 0; i < num_shaders; ++i) {
       if (shaders[i]->num_consts)
@@ -158,99 +157,94 @@ create_preamble(char *txt,
    if (start_temp < 0)
       start_temp = 0;
    if (start_sampler < 0)
-      start_sampler = 0;
+       start_sampler = 0;
 
    num_consts   = end_const   - start_const;
    num_temps    = end_temp    - start_temp;
    num_samplers = end_sampler - start_sampler;
-   /* end exclusive */
-   --end_const;
-   --end_temp;
-   --end_sampler;
 
-   sprintf(txt, "FRAG1.1\n");
+   ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
+   if (!ureg)
+       return NULL;
 
    if (declare_input) {
-      sprintf(txt + strlen(txt), "DCL IN[0], POSITION, LINEAR\n");
-      sprintf(txt + strlen(txt), "DCL IN[1], GENERIC[0], PERSPECTIVE\n");
+      in[0] = ureg_DECL_fs_input(ureg,
+                                 TGSI_SEMANTIC_POSITION,
+                                 0,
+                                 TGSI_INTERPOLATE_LINEAR);
+      in[1] = ureg_DECL_fs_input(ureg,
+                                 TGSI_SEMANTIC_GENERIC,
+                                 0,
+                                 TGSI_INTERPOLATE_PERSPECTIVE);
    }
 
    /* we always have a color output */
-   sprintf(txt + strlen(txt), "DCL OUT[0], COLOR, CONSTANT\n");
-
-   if (num_consts > 1)
-      sprintf(txt + strlen(txt), "DCL CONST[%d..%d], CONSTANT\n", start_const, end_const);
-   else if (num_consts == 1)
-      sprintf(txt + strlen(txt), "DCL CONST[%d], CONSTANT\n", start_const);
-
-   if (num_temps > 1)
-      sprintf(txt + strlen(txt), "DCL TEMP[%d..%d], CONSTANT\n", start_temp, end_temp);
-   else if (num_temps > 1)
-      sprintf(txt + strlen(txt), "DCL TEMP[%d], CONSTANT\n", start_temp);
-
-   if (num_samplers > 1)
-      sprintf(txt + strlen(txt), "DCL SAMP[%d..%d], CONSTANT\n", start_sampler, end_sampler);
-   else if (num_samplers == 1)
-      sprintf(txt + strlen(txt), "DCL SAMP[%d], CONSTANT\n", start_sampler);
-}
+   out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
 
-static void *
-combine_shaders(const struct shader_asm_info *shaders[SHADER_STAGES], int num_shaders,
-                struct pipe_context *pipe,
-                struct pipe_shader_state *shader)
-{
-   char *combined_txt;
-   int combined_len = MAX_PREAMBLE;
-   int combined_tokens = 0;
-   int i = 0;
-   int current_shader = 0;
-   int current_len;
+   if (num_consts >= 1) {
+      constant = malloc(sizeof(struct ureg_src) * end_const);
+      for (i = start_const; i < end_const; i++) {
+         constant[i] = ureg_DECL_constant(ureg, i);
+      }
 
-   for (i = 0; i < num_shaders; ++i) {
-      combined_len += strlen(shaders[i]->txt);
-      combined_tokens += shaders[i]->num_tokens;
    }
-   /* add for the %s->TEMP[0] substitutions */
-   combined_len += num_shaders * 7 /*TEMP[0]*/ + 4 /*"END\n"*/;
 
-   combined_txt = (char*)malloc(combined_len);
-   combined_txt[0] = '\0';
+   if (num_temps >= 1) {
+      temp = malloc(sizeof(struct ureg_dst) * end_temp);
+      for (i = start_temp; i < end_temp; i++) {
+         temp[i] = ureg_DECL_temporary(ureg);
+      }
+   }
 
-   create_preamble(combined_txt, shaders, num_shaders);
+   if (num_samplers >= 1) {
+      sampler = malloc(sizeof(struct ureg_src) * end_sampler);
+      for (i = start_sampler; i < end_sampler; i++) {
+         sampler[i] = ureg_DECL_sampler(ureg, i);
+      }
+   }
 
    while (current_shader < num_shaders) {
-      const char temp[] = "TEMP[0]";
-      const char out[] = "OUT[0]";
-      const char *subst = temp;
-
-      current_len = strlen(combined_txt);
+      if ((current_shader + 1) == num_shaders) {
+         shaders[current_shader]->func(ureg,
+                                       &out,
+                                       in,
+                                       sampler,
+                                       temp,
+                                       constant);
+      } else {
+         shaders[current_shader]->func(ureg,
+                                      &temp[0],
+                                      in,
+                                      sampler,
+                                      temp,
+                                      constant);
+      }
+      current_shader++;
+   }
 
-      /* if the last shader then output */
-      if (current_shader + 1 == num_shaders)
-         subst = out;
+   ureg_END(ureg);
 
-      snprintf(combined_txt + current_len,
-               combined_len - current_len,
-               shaders[current_shader]->txt,
-               subst);
-      ++current_shader;
+   shader->tokens = ureg_finalize(ureg);
+   if (!shader->tokens) {
+      ureg_destroy(ureg);
+      return NULL;
    }
 
+   p = pipe->create_fs_state(pipe, shader);
 
-   current_len = strlen(combined_txt);
-   snprintf(combined_txt + current_len,
-            combined_len - current_len,
-            "END\n");
-
-   debug_printf("Combined shader is : \n%s\n",
-                 combined_txt);
+   if (num_temps >= 1) {
+      for (i = start_temp; i < end_temp; i++) {
+         ureg_release_temporary(ureg, temp[i]);
+      }
+   }
 
-   shader->tokens = tokens_from_assembly(
-            combined_txt, combined_tokens);
+   ureg_destroy(ureg);
 
-   free(combined_txt);
+   free(temp);
+   free(constant);
+   free(sampler);
 
-   return pipe->create_fs_state(pipe, shader);
+   return p;
 }
 
 static void *
@@ -258,98 +252,126 @@ create_shader(struct pipe_context *pipe,
               int id,
               struct pipe_shader_state *shader)
 {
-   int idx = 0;
+   int idx = 0, sh;
    const struct shader_asm_info * shaders[SHADER_STAGES];
 
-   /* the shader has to have a fill */
-   debug_assert(id & ALL_FILLS);
-
    /* first stage */
-   if (id & VEGA_SOLID_FILL_SHADER) {
-      debug_assert(idx == 0);
-      shaders[idx] = &shaders_asm[0];
-      debug_assert(shaders_asm[0].id == VEGA_SOLID_FILL_SHADER);
-      ++idx;
-   }
-   if ((id & VEGA_LINEAR_GRADIENT_SHADER)) {
-      debug_assert(idx == 0);
-      shaders[idx] = &shaders_asm[1];
-      debug_assert(shaders_asm[1].id == VEGA_LINEAR_GRADIENT_SHADER);
-      ++idx;
-   }
-   if ((id & VEGA_RADIAL_GRADIENT_SHADER)) {
-      debug_assert(idx == 0);
-      shaders[idx] = &shaders_asm[2];
-      debug_assert(shaders_asm[2].id == VEGA_RADIAL_GRADIENT_SHADER);
-      ++idx;
-   }
-   if ((id & VEGA_PATTERN_SHADER)) {
-      debug_assert(idx == 0);
-      debug_assert(shaders_asm[3].id == VEGA_PATTERN_SHADER);
-      shaders[idx] = &shaders_asm[3];
-      ++idx;
-   }
-   if ((id & VEGA_IMAGE_NORMAL_SHADER)) {
-      debug_assert(idx == 0);
-      debug_assert(shaders_asm[4].id == VEGA_IMAGE_NORMAL_SHADER);
-      shaders[idx] = &shaders_asm[4];
-      ++idx;
+   sh = SHADERS_GET_PAINT_SHADER(id);
+   switch (sh << SHADERS_PAINT_SHIFT) {
+   case VEGA_SOLID_FILL_SHADER:
+   case VEGA_LINEAR_GRADIENT_SHADER:
+   case VEGA_RADIAL_GRADIENT_SHADER:
+   case VEGA_PATTERN_SHADER:
+   case VEGA_PAINT_DEGENERATE_SHADER:
+      shaders[idx] = &shaders_paint_asm[(sh >> SHADERS_PAINT_SHIFT) - 1];
+      assert(shaders[idx]->id == sh);
+      idx++;
+      break;
+   default:
+      break;
    }
 
    /* second stage */
-   if ((id & VEGA_IMAGE_MULTIPLY_SHADER)) {
-      debug_assert(shaders_asm[5].id == VEGA_IMAGE_MULTIPLY_SHADER);
-      shaders[idx] = &shaders_asm[5];
-      ++idx;
-   } else if ((id & VEGA_IMAGE_STENCIL_SHADER)) {
-      debug_assert(shaders_asm[6].id == VEGA_IMAGE_STENCIL_SHADER);
-      shaders[idx] = &shaders_asm[6];
-      ++idx;
+   sh = SHADERS_GET_IMAGE_SHADER(id);
+   switch (sh) {
+   case VEGA_IMAGE_NORMAL_SHADER:
+   case VEGA_IMAGE_MULTIPLY_SHADER:
+   case VEGA_IMAGE_STENCIL_SHADER:
+      shaders[idx] = &shaders_image_asm[(sh >> SHADERS_IMAGE_SHIFT) - 1];
+      assert(shaders[idx]->id == sh);
+      idx++;
+      break;
+   default:
+      break;
    }
 
+   /* sanity check */
+   assert(idx == ((!sh || sh == VEGA_IMAGE_NORMAL_SHADER) ? 1 : 2));
+
    /* third stage */
-   if ((id & VEGA_MASK_SHADER)) {
-      debug_assert(idx == 1);
-      debug_assert(shaders_asm[7].id == VEGA_MASK_SHADER);
-      shaders[idx] = &shaders_asm[7];
-      ++idx;
+   sh = SHADERS_GET_COLOR_TRANSFORM_SHADER(id);
+   switch (sh) {
+   case VEGA_COLOR_TRANSFORM_SHADER:
+      shaders[idx] = &shaders_color_transform_asm[
+         (sh >> SHADERS_COLOR_TRANSFORM_SHIFT) - 1];
+      assert(shaders[idx]->id == sh);
+      idx++;
+      break;
+   default:
+      break;
    }
 
    /* fourth stage */
-   if ((id & VEGA_BLEND_MULTIPLY_SHADER)) {
-      debug_assert(shaders_asm[8].id == VEGA_BLEND_MULTIPLY_SHADER);
-      shaders[idx] = &shaders_asm[8];
-      ++idx;
-   } else if ((id & VEGA_BLEND_SCREEN_SHADER)) {
-      debug_assert(shaders_asm[9].id == VEGA_BLEND_SCREEN_SHADER);
-      shaders[idx] = &shaders_asm[9];
-      ++idx;
-   } else if ((id & VEGA_BLEND_DARKEN_SHADER)) {
-      debug_assert(shaders_asm[10].id == VEGA_BLEND_DARKEN_SHADER);
-      shaders[idx] = &shaders_asm[10];
-      ++idx;
-   } else if ((id & VEGA_BLEND_LIGHTEN_SHADER)) {
-      debug_assert(shaders_asm[11].id == VEGA_BLEND_LIGHTEN_SHADER);
-      shaders[idx] = &shaders_asm[11];
-      ++idx;
+   sh = SHADERS_GET_ALPHA_SHADER(id);
+   switch (sh) {
+   case VEGA_ALPHA_NORMAL_SHADER:
+   case VEGA_ALPHA_PER_CHANNEL_SHADER:
+      shaders[idx] = &shaders_alpha_asm[
+         (sh >> SHADERS_ALPHA_SHIFT) - 1];
+      assert(shaders[idx]->id == sh);
+      idx++;
+      break;
+   default:
+      break;
    }
 
    /* fifth stage */
-   if ((id & VEGA_PREMULTIPLY_SHADER)) {
-      debug_assert(shaders_asm[12].id == VEGA_PREMULTIPLY_SHADER);
-      shaders[idx] = &shaders_asm[12];
-      ++idx;
-   } else if ((id & VEGA_UNPREMULTIPLY_SHADER)) {
-      debug_assert(shaders_asm[13].id == VEGA_UNPREMULTIPLY_SHADER);
-      shaders[idx] = &shaders_asm[13];
-      ++idx;
+   sh = SHADERS_GET_BLEND_SHADER(id);
+   switch (sh) {
+   case VEGA_BLEND_SRC_SHADER:
+   case VEGA_BLEND_SRC_OVER_SHADER:
+   case VEGA_BLEND_DST_OVER_SHADER:
+   case VEGA_BLEND_SRC_IN_SHADER:
+   case VEGA_BLEND_DST_IN_SHADER:
+   case VEGA_BLEND_MULTIPLY_SHADER:
+   case VEGA_BLEND_SCREEN_SHADER:
+   case VEGA_BLEND_DARKEN_SHADER:
+   case VEGA_BLEND_LIGHTEN_SHADER:
+   case VEGA_BLEND_ADDITIVE_SHADER:
+      shaders[idx] = &shaders_blend_asm[(sh >> SHADERS_BLEND_SHIFT) - 1];
+      assert(shaders[idx]->id == sh);
+      idx++;
+      break;
+   default:
+      break;
    }
 
    /* sixth stage */
-   if ((id & VEGA_BW_SHADER)) {
-      debug_assert(shaders_asm[14].id == VEGA_BW_SHADER);
-      shaders[idx] = &shaders_asm[14];
-      ++idx;
+   sh = SHADERS_GET_MASK_SHADER(id);
+   switch (sh) {
+   case VEGA_MASK_SHADER:
+      shaders[idx] = &shaders_mask_asm[(sh >> SHADERS_MASK_SHIFT) - 1];
+      assert(shaders[idx]->id == sh);
+      idx++;
+      break;
+   default:
+      break;
+   }
+
+   /* seventh stage */
+   sh = SHADERS_GET_PREMULTIPLY_SHADER(id);
+   switch (sh) {
+   case VEGA_PREMULTIPLY_SHADER:
+   case VEGA_UNPREMULTIPLY_SHADER:
+      shaders[idx] = &shaders_premultiply_asm[
+         (sh >> SHADERS_PREMULTIPLY_SHIFT) - 1];
+      assert(shaders[idx]->id == sh);
+      idx++;
+      break;
+   default:
+      break;
+   }
+
+   /* eighth stage */
+   sh = SHADERS_GET_BW_SHADER(id);
+   switch (sh) {
+   case VEGA_BW_SHADER:
+      shaders[idx] = &shaders_bw_asm[(sh >> SHADERS_BW_SHIFT) - 1];
+      assert(shaders[idx]->id == sh);
+      idx++;
+      break;
+   default:
+      break;
    }
 
    return combine_shaders(shaders, idx, pipe, shader);
@@ -380,7 +402,7 @@ void shaders_cache_destroy(struct shaders_cache *sc)
    }
 
    cso_hash_delete(sc->hash);
-   free(sc);
+   FREE(sc);
 }
 
 void * shaders_cache_fill(struct shaders_cache *sc,
@@ -409,7 +431,7 @@ struct vg_shader * shader_create_from_text(struct pipe_context *pipe,
                                            const char *txt, int num_tokens,
                                            int type)
 {
-   struct vg_shader *shader = (struct vg_shader *)malloc(
+   struct vg_shader *shader = (struct vg_shader *)MALLOC(
       sizeof(struct vg_shader));
    struct tgsi_token *tokens = tokens_from_assembly(txt, num_tokens);
    struct pipe_shader_state state;
@@ -418,6 +440,7 @@ struct vg_shader * shader_create_from_text(struct pipe_context *pipe,
                 type == PIPE_SHADER_FRAGMENT);
 
    state.tokens = tokens;
+   memset(&state.stream_output, 0, sizeof(state.stream_output));
    shader->type = type;
    shader->tokens = tokens;
 
@@ -434,6 +457,6 @@ void vg_shader_destroy(struct vg_context *ctx, struct vg_shader *shader)
       cso_delete_fragment_shader(ctx->cso_context, shader->driver);
    else
       cso_delete_vertex_shader(ctx->cso_context, shader->driver);
-   free(shader->tokens);
-   free(shader);
+   FREE(shader->tokens);
+   FREE(shader);
 }