st: rearrange some code to be a little more clear
[mesa.git] / src / mesa / state_tracker / st_atom_shader.c
index 919691850938a553b9623a187f9ffa35c1bb345d..fc1ff5be04a59cc6d43b8c0885ea8512cdbddef1 100644 (file)
 
 #include "main/imports.h"
 #include "main/mtypes.h"
+#include "main/macros.h"
+#include "shader/program.h"
 
 #include "pipe/p_context.h"
 #include "pipe/p_shader_tokens.h"
 
-#include "pipe/cso_cache/cso_cache.h"
+#include "util/u_simple_shaders.h"
+
+#include "cso_cache/cso_context.h"
 
 #include "st_context.h"
-#include "st_cache.h"
 #include "st_atom.h"
 #include "st_program.h"
 #include "st_atom_shader.h"
@@ -69,9 +72,8 @@ struct translated_vertex_program
 
    /** Maps VERT_RESULT_x to slot */
    GLuint output_to_slot[VERT_RESULT_MAX];
-
-   /** The program in TGSI format */
-   struct tgsi_token tokens[ST_MAX_SHADER_TOKENS];
+   ubyte output_to_semantic_name[VERT_RESULT_MAX];
+   ubyte output_to_semantic_index[VERT_RESULT_MAX];
 
    /** Pointer to the translated vertex program */
    struct st_vertex_program *vp;
@@ -81,34 +83,6 @@ struct translated_vertex_program
 
 
 
-/**
- * Free data hanging off the st vert prog.
- */
-void
-st_remove_vertex_program(struct st_context *st, struct st_vertex_program *stvp)
-{
-   /* no-op, for now? */
-}
-
-
-/**
- * Free data hanging off the st frag prog.
- */
-void
-st_remove_fragment_program(struct st_context *st,
-                          struct st_fragment_program *stfp)
-{
-   struct translated_vertex_program *xvp, *next;
-
-   for (xvp = stfp->vertex_programs; xvp; xvp = next) {
-      next = xvp->next;
-      /* XXX free xvp->vs */
-      free(xvp);
-   }
-}
-
-
-
 /**
  * Given a vertex program output attribute, return the corresponding
  * fragment program input attribute.
@@ -158,7 +132,7 @@ find_translated_vp(struct st_context *st,
    /*
     * Translate fragment program if needed.
     */
-   if (!stfp->fs) {
+   if (!stfp->state.tokens) {
       GLuint inAttr, numIn = 0;
 
       for (inAttr = 0; inAttr < FRAG_ATTRIB_MAX; inAttr++) {
@@ -175,11 +149,7 @@ find_translated_vp(struct st_context *st,
 
       assert(stfp->Base.Base.NumInstructions > 1);
 
-      (void) st_translate_fragment_program(st, stfp,
-                                           stfp->input_to_slot,
-                                           stfp->tokens,
-                                           ST_MAX_SHADER_TOKENS);
-      assert(stfp->fs);
+      st_translate_fragment_program(st, stfp, stfp->input_to_slot);
    }
 
 
@@ -195,7 +165,7 @@ find_translated_vp(struct st_context *st,
 
    /* No?  Allocate translated vp object now */
    if (!xvp) {
-      xvp = CALLOC_STRUCT(translated_vertex_program);
+      xvp = ST_CALLOC_STRUCT(translated_vertex_program);
       xvp->frag_inputs = fragInputsRead;
       xvp->master = stvp;
 
@@ -208,17 +178,23 @@ find_translated_vp(struct st_context *st,
       GLuint outAttr, dummySlot;
       const GLbitfield outputsWritten = stvp->Base.Base.OutputsWritten;
       GLuint numVpOuts = 0;
+      GLboolean emitPntSize = GL_FALSE, emitBFC0 = GL_FALSE, emitBFC1 = GL_FALSE;
+      GLint maxGeneric;
 
       /* Compute mapping of vertex program outputs to slots, which depends
        * on the fragment program's input->slot mapping.
        */
       for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
-         /* set default: */
+         /* set defaults: */
          xvp->output_to_slot[outAttr] = UNUSED;
+         xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_COUNT;
+         xvp->output_to_semantic_index[outAttr] = 99;
 
          if (outAttr == VERT_RESULT_HPOS) {
             /* always put xformed position into slot zero */
             xvp->output_to_slot[VERT_RESULT_HPOS] = 0;
+            xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_POSITION;
+            xvp->output_to_semantic_index[outAttr] = 0;
             numVpOuts++;
          }
          else if (outputsWritten & (1 << outAttr)) {
@@ -227,22 +203,42 @@ find_translated_vp(struct st_context *st,
             if (fpInAttrib >= 0) {
                GLuint fpInSlot = stfp->input_to_slot[fpInAttrib];
                if (fpInSlot != ~0) {
-                  GLuint vpOutSlot = stfp->fs->state.input_map[fpInSlot];
+                  /* match this vp output to the fp input */
+                  GLuint vpOutSlot = stfp->input_map[fpInSlot];
                   xvp->output_to_slot[outAttr] = vpOutSlot;
+                  xvp->output_to_semantic_name[outAttr] = stfp->input_semantic_name[fpInSlot];
+                  xvp->output_to_semantic_index[outAttr] = stfp->input_semantic_index[fpInSlot];
                   numVpOuts++;
                }
             }
-            else if (outAttr == VERT_RESULT_PSIZ ||
-                     outAttr == VERT_RESULT_BFC0 ||
-                     outAttr == VERT_RESULT_BFC1) {
-               /* backface colors go into last slots */
-               xvp->output_to_slot[outAttr] = numVpOuts++;
-            }
+            else if (outAttr == VERT_RESULT_PSIZ)
+               emitPntSize = GL_TRUE;
+            else if (outAttr == VERT_RESULT_BFC0)
+               emitBFC0 = GL_TRUE;
+            else if (outAttr == VERT_RESULT_BFC1)
+               emitBFC1 = GL_TRUE;
          }
-         /*
-         printf("output_to_slot[%d] = %d\n", outAttr, 
+#if 0 /*debug*/
+         printf("assign vp output_to_slot[%d] = %d\n", outAttr, 
                 xvp->output_to_slot[outAttr]);
-         */
+#endif
+      }
+
+      /* must do these last */
+      if (emitPntSize) {
+         xvp->output_to_slot[VERT_RESULT_PSIZ] = numVpOuts++;
+         xvp->output_to_semantic_name[VERT_RESULT_PSIZ] = TGSI_SEMANTIC_PSIZE;
+         xvp->output_to_semantic_index[VERT_RESULT_PSIZ] = 0;
+      }
+      if (emitBFC0) {
+         xvp->output_to_slot[VERT_RESULT_BFC0] = numVpOuts++;
+         xvp->output_to_semantic_name[VERT_RESULT_BFC0] = TGSI_SEMANTIC_COLOR;
+         xvp->output_to_semantic_index[VERT_RESULT_BFC0] = 0;
+      }
+      if (emitBFC1) {
+         xvp->output_to_slot[VERT_RESULT_BFC1] = numVpOuts++;
+         xvp->output_to_semantic_name[VERT_RESULT_BFC0] = TGSI_SEMANTIC_COLOR;
+         xvp->output_to_semantic_index[VERT_RESULT_BFC0] = 1;
       }
 
       /* Unneeded vertex program outputs will go to this slot.
@@ -251,22 +247,39 @@ find_translated_vp(struct st_context *st,
        */
       dummySlot = numVpOuts;
 
-      /* Map vert program outputs that aren't used to the dummy slot */
+      /* find max GENERIC slot index */
+      maxGeneric = -1;
+      for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
+         if (xvp->output_to_semantic_name[outAttr] == TGSI_SEMANTIC_GENERIC) {
+            maxGeneric = MAX2(maxGeneric,
+                              xvp->output_to_semantic_index[outAttr]);
+         }
+      }
+
+      /* Map vert program outputs that aren't used to the dummy slot
+       * (and an unused generic attribute slot).
+       */
       for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
          if (outputsWritten & (1 << outAttr)) {
-            if (xvp->output_to_slot[outAttr] == UNUSED)
+            if (xvp->output_to_slot[outAttr] == UNUSED) {
                xvp->output_to_slot[outAttr] = dummySlot;
+               xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_GENERIC;
+               xvp->output_to_semantic_index[outAttr] = maxGeneric + 1;
+            }
          }
+
+#if 0 /*debug*/
+         printf("vp output_to_slot[%d] = %d\n", outAttr, 
+                xvp->output_to_slot[outAttr]);
+#endif
       }
 
       assert(stvp->Base.Base.NumInstructions > 1);
 
-      st_translate_vertex_program(st, stvp,
-                                  xvp->output_to_slot,
-                                  xvp->tokens,
-                                  ST_MAX_SHADER_TOKENS);
+      st_translate_vertex_program(st, stvp, xvp->output_to_slot,
+                                  xvp->output_to_semantic_name,
+                                  xvp->output_to_semantic_index);
 
-      assert(stvp->cso);
       xvp->vp = stvp;
 
       /* translated VP is up to date now */
@@ -277,6 +290,32 @@ find_translated_vp(struct st_context *st,
 }
 
 
+void
+st_free_translated_vertex_programs(struct st_context *st,
+                                   struct translated_vertex_program *xvp)
+{
+   struct translated_vertex_program *next;
+
+   while (xvp) {
+      next = xvp->next;
+      _mesa_free(xvp);
+      xvp = next;
+   }
+}
+
+
+static void *
+get_passthrough_fs(struct st_context *st)
+{
+   if (!st->passthrough_fs) {
+      st->passthrough_fs =
+         util_make_fragment_passthrough_shader(st->pipe);
+   }
+
+   return st->passthrough_fs;
+}
+
+
 static void
 update_linkage( struct st_context *st )
 {
@@ -289,29 +328,37 @@ update_linkage( struct st_context *st )
     */
    assert(st->ctx->VertexProgram._Current);
    stvp = st_vertex_program(st->ctx->VertexProgram._Current);
+   assert(stvp->Base.Base.Target == GL_VERTEX_PROGRAM_ARB);
 
    assert(st->ctx->FragmentProgram._Current);
    stfp = st_fragment_program(st->ctx->FragmentProgram._Current);
+   assert(stfp->Base.Base.Target == GL_FRAGMENT_PROGRAM_ARB);
 
    xvp = find_translated_vp(st, stvp, stfp);
 
-   st->vp = stvp;
-   st->state.vs = xvp->vp;
-   st->pipe->bind_vs_state(st->pipe, st->state.vs->cso->data);
+   st_reference_vertprog(st, &st->vp, stvp);
+   st_reference_fragprog(st, &st->fp, stfp);
 
-   st->fp = stfp;
-   st->state.fs = stfp->fs;
-   st->pipe->bind_fs_state(st->pipe, st->state.fs->data);
+   cso_set_vertex_shader_handle(st->cso_context, stvp->driver_shader);
+
+   if (st->missing_textures) {
+      /* use a pass-through frag shader that uses no textures */
+      void *fs = get_passthrough_fs(st);
+      cso_set_fragment_shader_handle(st->cso_context, fs);
+   }
+   else {
+      cso_set_fragment_shader_handle(st->cso_context, stfp->driver_shader);
+   }
 
    st->vertex_result_to_slot = xvp->output_to_slot;
 }
 
 
 const struct st_tracked_state st_update_shader = {
-   .name = "st_update_shader",
-   .dirty = {
-      .mesa  = 0,
-      .st   = ST_NEW_VERTEX_PROGRAM | ST_NEW_FRAGMENT_PROGRAM
+   "st_update_shader",                                 /* name */
+   {                                                   /* dirty */
+      0,                                               /* mesa */
+      ST_NEW_VERTEX_PROGRAM | ST_NEW_FRAGMENT_PROGRAM  /* st */
    },
-   .update = update_linkage
+   update_linkage                                      /* update */
 };