svga: check for and skip null vertex buffer pointers
[mesa.git] / src / mesa / drivers / dri / i965 / brw_vs_constval.c
index 734a926e968d8458fac92326d03c1ddaed995eba..5b26c7a6db46bd9eb86d313fa322d2e7344ce60d 100644 (file)
@@ -30,7 +30,7 @@
   */
             
 
-#include "macros.h"
+#include "main/macros.h"
 #include "brw_context.h"
 #include "brw_vs.h"
 
@@ -38,9 +38,9 @@
  * are promoted to [0,0,0,1] for the purposes of this analysis.
  */
 struct tracker {
-   GLboolean twoside;
-   GLubyte active[PROGRAM_OUTPUT+1][128];
-   GLuint size_masks[4];
+   bool twoside;
+   GLubyte active[PROGRAM_OUTPUT+1][MAX_PROGRAM_TEMPS];
+   GLbitfield size_masks[4];  /**< one bit per fragment program input attrib */
 };
 
 
@@ -53,8 +53,10 @@ static void set_active_component( struct tracker *t,
    case PROGRAM_TEMPORARY:
    case PROGRAM_INPUT:
    case PROGRAM_OUTPUT:
+      assert(file < PROGRAM_OUTPUT + 1);
+      assert(index < Elements(t->active[0]));
       t->active[file][index] |= active;
-
+      break;
    default:
       break;
    }
@@ -96,7 +98,7 @@ static GLubyte get_active( struct tracker *t,
                           struct prog_src_register src )
 {
    GLuint i;
-   GLubyte active = src.NegateBase; /* NOTE! */
+   GLubyte active = src.Negate; /* NOTE! */
 
    if (src.RelAddr)
       return 0xf;
@@ -108,10 +110,15 @@ static GLubyte get_active( struct tracker *t,
    return active;
 }
 
+/**
+ * Return the size (1,2,3 or 4) of the output/result for VERT_RESULT_idx.
+ */
 static GLubyte get_output_size( struct tracker *t,
                                GLuint idx )
 {
-   GLubyte active = t->active[PROGRAM_OUTPUT][idx];
+   GLubyte active;
+   assert(idx < VERT_RESULT_MAX);
+   active = t->active[PROGRAM_OUTPUT][idx];
    if (active & (1<<3)) return 4;
    if (active & (1<<2)) return 3;
    if (active & (1<<1)) return 2;
@@ -123,7 +130,7 @@ static GLubyte get_output_size( struct tracker *t,
  */
 static void calc_sizes( struct tracker *t )
 {
-   GLuint i;
+   GLint vertRes;
 
    if (t->twoside) {
       t->active[PROGRAM_OUTPUT][VERT_RESULT_COL0] |= 
@@ -133,12 +140,23 @@ static void calc_sizes( struct tracker *t )
         t->active[PROGRAM_OUTPUT][VERT_RESULT_BFC1];
    }
 
-   for (i = 0; i < FRAG_ATTRIB_MAX; i++) {
-      switch (get_output_size(t, i)) {
-      case 4: t->size_masks[4-1] |= 1<<i;
-      case 3: t->size_masks[3-1] |= 1<<i;
-      case 2: t->size_masks[2-1] |= 1<<i;
-      case 1: t->size_masks[1-1] |= 1<<i;
+   /* Examine vertex program output sizes to set the size_masks[] info
+    * which describes the fragment program input sizes.
+    */
+   for (vertRes = VERT_RESULT_TEX0; vertRes < VERT_RESULT_MAX; vertRes++) {
+
+      /* map vertex program output index to fragment program input index */
+      GLint fragAttrib = _mesa_vert_result_to_frag_attrib(vertRes);
+      if (fragAttrib < 0)
+         continue;
+      assert(fragAttrib >= FRAG_ATTRIB_TEX0);
+      assert(fragAttrib <= FRAG_ATTRIB_MAX);
+
+      switch (get_output_size(t, vertRes)) {
+      case 4: t->size_masks[4-1] |= 1 << fragAttrib;
+      case 3: t->size_masks[3-1] |= 1 << fragAttrib;
+      case 2: t->size_masks[2-1] |= 1 << fragAttrib;
+      case 1: t->size_masks[1-1] |= 1 << fragAttrib;
         break;
       }
    }
@@ -168,22 +186,38 @@ static GLuint get_input_size(struct brw_context *brw,
  */
 static void calc_wm_input_sizes( struct brw_context *brw )
 {
+   struct gl_context *ctx = &brw->intel.ctx;
    /* BRW_NEW_VERTEX_PROGRAM */
-   struct brw_vertex_program *vp = 
-      (struct brw_vertex_program *)brw->vertex_program;
+   const struct brw_vertex_program *vp =
+      brw_vertex_program_const(brw->vertex_program);
    /* BRW_NEW_INPUT_DIMENSIONS */
    struct tracker t;
    GLuint insn;
    GLuint i;
 
+   /* Mesa IR is not generated for GLSL vertex shaders.  If there's no Mesa
+    * IR, the code below cannot determine which output components are
+    * written.  So, skip it and assume everything is written.  This
+    * circumvents some optimizations in the fragment shader, but it guarantees
+    * that correct code is generated.
+    */
+   if (vp->program.Base.NumInstructions == 0) {
+      brw->wm.input_size_masks[0] = ~0;
+      brw->wm.input_size_masks[1] = ~0;
+      brw->wm.input_size_masks[2] = ~0;
+      brw->wm.input_size_masks[3] = ~0;
+      return;
+   }
+
+
    memset(&t, 0, sizeof(t));
 
-   /* _NEW_LIGHT */
-   if (brw->attribs.Light->Model.TwoSide)
+   /* _NEW_LIGHT | _NEW_PROGRAM */
+   if (ctx->VertexProgram._TwoSideEnabled)
       t.twoside = 1;
 
    for (i = 0; i < VERT_ATTRIB_MAX; i++) 
-      if (vp->program.Base.InputsRead & (1<<i))
+      if (vp->program.Base.InputsRead & BITFIELD64_BIT(i))
         set_active_component(&t, PROGRAM_INPUT, i, 
                              szflag[get_input_size(brw, i)]);
       
@@ -214,10 +248,10 @@ static void calc_wm_input_sizes( struct brw_context *brw )
 
 const struct brw_tracked_state brw_wm_input_sizes = {
    .dirty = {
-      .mesa  = _NEW_LIGHT,
+      .mesa  = _NEW_LIGHT | _NEW_PROGRAM,
       .brw   = BRW_NEW_VERTEX_PROGRAM | BRW_NEW_INPUT_DIMENSIONS,
       .cache = 0
    },
-   .prepare = calc_wm_input_sizes
+   .emit = calc_wm_input_sizes
 };