Merge commit 'origin/gallium-master-merge'
[mesa.git] / src / mesa / main / state.c
index a962f1cb41da5b00f512095deb101bc3f268a58a..0a39279bff326bffa116e60bfcfad99273ff33f5 100644 (file)
 #include "texstate.h"
 
 
+static void
+update_separate_specular(GLcontext *ctx)
+{
+   if (NEED_SECONDARY_COLOR(ctx))
+      ctx->_TriangleCaps |= DD_SEPARATE_SPECULAR;
+   else
+      ctx->_TriangleCaps &= ~DD_SEPARATE_SPECULAR;
+}
+
+
 /**
  * Update state dependent on vertex arrays.
  */
@@ -163,25 +173,47 @@ update_arrays( GLcontext *ctx )
 }
 
 
+/**
+ * Update the following fields:
+ *   ctx->VertexProgram._Enabled
+ *   ctx->FragmentProgram._Enabled
+ *   ctx->ATIFragmentShader._Enabled
+ * This needs to be done before texture state validation.
+ */
 static void
-update_program(GLcontext *ctx)
+update_program_enables(GLcontext *ctx)
 {
-   const struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
-   const struct gl_vertex_program *prevVP = ctx->VertexProgram._Current;
-   const struct gl_fragment_program *prevFP = ctx->FragmentProgram._Current;
-
    /* These _Enabled flags indicate if the program is enabled AND valid. */
    ctx->VertexProgram._Enabled = ctx->VertexProgram.Enabled
       && ctx->VertexProgram.Current->Base.Instructions;
    ctx->FragmentProgram._Enabled = ctx->FragmentProgram.Enabled
       && ctx->FragmentProgram.Current->Base.Instructions;
    ctx->ATIFragmentShader._Enabled = ctx->ATIFragmentShader.Enabled
-      && ctx->ATIFragmentShader.Current->Instructions;
+      && ctx->ATIFragmentShader.Current->Instructions[0];
+}
+
+
+/**
+ * Update vertex/fragment program state.  In particular, update these fields:
+ *   ctx->VertexProgram._Current
+ *   ctx->VertexProgram._TnlProgram,
+ * These point to the highest priority enabled vertex/fragment program or are
+ * NULL if fixed-function processing is to be done.
+ *
+ * This function needs to be called after texture state validation in case
+ * we're generating a fragment program from fixed-function texture state.
+ */
+static void
+update_program(GLcontext *ctx)
+{
+   const struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
+   const struct gl_vertex_program *prevVP = ctx->VertexProgram._Current;
+   const struct gl_fragment_program *prevFP = ctx->FragmentProgram._Current;
 
    /*
     * Set the ctx->VertexProgram._Current and ctx->FragmentProgram._Current
-    * pointers to the programs that should be enabled/used.  These will only
-    * be NULL if we need to use the fixed-function code.
+    * pointers to the programs that should be used for rendering.  If either
+    * is NULL, use fixed-function code paths.
     *
     * These programs may come from several sources.  The priority is as
     * follows:
@@ -194,56 +226,37 @@ update_program(GLcontext *ctx)
     * come up, or matter.
     */
 
-   /**
-    ** Fragment program
-    **/
-#if 1
-   /* XXX get rid of this someday? */
-   ctx->FragmentProgram._Active = GL_FALSE;
-#endif
    if (shProg && shProg->LinkStatus && shProg->FragmentProgram) {
-      /* user-defined fragment shader */
+      /* Use shader programs */
       _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current,
                                shProg->FragmentProgram);
    }
    else if (ctx->FragmentProgram._Enabled) {
-      /* use user-defined fragment program */
+      /* use user-defined vertex program */
       _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current,
                                ctx->FragmentProgram.Current);
    }
    else if (ctx->FragmentProgram._MaintainTexEnvProgram) {
-      /* fragment program generated from fixed-function state */
+      /* Use fragment program generated from fixed-function state.
+       */
       _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current,
                                _mesa_get_fixed_func_fragment_program(ctx));
       _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram,
                                ctx->FragmentProgram._Current);
-
-      /* XXX get rid of this confusing stuff someday? */
-      ctx->FragmentProgram._Active = ctx->FragmentProgram._Enabled;
-      if (ctx->FragmentProgram._UseTexEnvProgram)
-         ctx->FragmentProgram._Active = GL_TRUE;
    }
    else {
       /* no fragment program */
       _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL);
    }
 
-   if (ctx->FragmentProgram._Current != prevFP && ctx->Driver.BindProgram) {
-      ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB,
-                         (struct gl_program *) ctx->FragmentProgram._Current);
-   }
-
-   /**
-    ** Vertex program
-    **/
-#if 1
-   /* XXX get rid of this someday? */
-   _mesa_reference_vertprog(ctx, &ctx->VertexProgram._TnlProgram, NULL);
-#endif
+   /* Examine vertex program after fragment program as
+    * _mesa_get_fixed_func_vertex_program() needs to know active
+    * fragprog inputs.
+    */
    if (shProg && shProg->LinkStatus && shProg->VertexProgram) {
-      /* user-defined vertex shader */
+      /* Use shader programs */
       _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current,
-                               shProg->VertexProgram);
+                            shProg->VertexProgram);
    }
    else if (ctx->VertexProgram._Enabled) {
       /* use user-defined vertex program */
@@ -251,20 +264,28 @@ update_program(GLcontext *ctx)
                                ctx->VertexProgram.Current);
    }
    else if (ctx->VertexProgram._MaintainTnlProgram) {
-      /* vertex program generated from fixed-function state */
+      /* Use vertex program generated from fixed-function state.
+       */
       _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current,
                                _mesa_get_fixed_func_vertex_program(ctx));
       _mesa_reference_vertprog(ctx, &ctx->VertexProgram._TnlProgram,
                                ctx->VertexProgram._Current);
    }
    else {
-      /* no vertex program / used fixed-function code */
+      /* no vertex program */
       _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, NULL);
    }
 
+   /* Let the driver know what's happening:
+    */
+   if (ctx->FragmentProgram._Current != prevFP && ctx->Driver.BindProgram) {
+      ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB,
+                              (struct gl_program *) ctx->FragmentProgram._Current);
+   }
+   
    if (ctx->VertexProgram._Current != prevVP && ctx->Driver.BindProgram) {
       ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
-                           (struct gl_program *) ctx->VertexProgram._Current);
+                              (struct gl_program *) ctx->VertexProgram._Current);
    }
 }
 
@@ -315,6 +336,24 @@ update_color(GLcontext *ctx)
 }
 
 
+/*
+ * Check polygon state and set DD_TRI_CULL_FRONT_BACK and/or DD_TRI_OFFSET
+ * in ctx->_TriangleCaps if needed.
+ */
+static void
+update_polygon(GLcontext *ctx)
+{
+   ctx->_TriangleCaps &= ~(DD_TRI_CULL_FRONT_BACK | DD_TRI_OFFSET);
+
+   if (ctx->Polygon.CullFlag && ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK)
+      ctx->_TriangleCaps |= DD_TRI_CULL_FRONT_BACK;
+
+   if (   ctx->Polygon.OffsetPoint
+       || ctx->Polygon.OffsetLine
+       || ctx->Polygon.OffsetFill)
+      ctx->_TriangleCaps |= DD_TRI_OFFSET;
+}
+
 
 /**
  * Update the ctx->_TriangleCaps bitfield.
@@ -322,6 +361,7 @@ update_color(GLcontext *ctx)
  * This function must be called after other update_*() functions since
  * there are dependencies on some other derived values.
  */
+#if 0
 static void
 update_tricaps(GLcontext *ctx, GLbitfield new_state)
 {
@@ -387,6 +427,7 @@ update_tricaps(GLcontext *ctx, GLbitfield new_state)
    if (ctx->Stencil._TestTwoSide)
       ctx->_TriangleCaps |= DD_TRI_TWOSTENCIL;
 }
+#endif
 
 
 /**
@@ -413,6 +454,24 @@ _mesa_update_state_locked( GLcontext *ctx )
    if (MESA_VERBOSE & VERBOSE_STATE)
       _mesa_print_state("_mesa_update_state", new_state);
 
+   /* Determine which state flags effect vertex/fragment program state */
+   if (ctx->FragmentProgram._MaintainTexEnvProgram) {
+      prog_flags |= (_NEW_TEXTURE | _NEW_FOG | _DD_NEW_SEPARATE_SPECULAR);
+   }
+   if (ctx->VertexProgram._MaintainTnlProgram) {
+      prog_flags |= (_NEW_ARRAY | _NEW_TEXTURE | _NEW_TEXTURE_MATRIX |
+                     _NEW_TRANSFORM | _NEW_POINT |
+                     _NEW_FOG | _NEW_LIGHT |
+                     _MESA_NEW_NEED_EYE_COORDS);
+   }
+
+   /*
+    * Now update derived state info
+    */
+
+   if (new_state & prog_flags)
+      update_program_enables( ctx );
+
    if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
       _mesa_update_modelview_project( ctx, new_state );
 
@@ -425,6 +484,9 @@ _mesa_update_state_locked( GLcontext *ctx )
    if (new_state & (_NEW_SCISSOR | _NEW_BUFFERS | _NEW_VIEWPORT))
       _mesa_update_draw_buffer_bounds( ctx );
 
+   if (new_state & _NEW_POLYGON)
+      update_polygon( ctx );
+
    if (new_state & _NEW_LIGHT)
       _mesa_update_lighting( ctx );
 
@@ -432,10 +494,13 @@ _mesa_update_state_locked( GLcontext *ctx )
       _mesa_update_stencil( ctx );
 
 #if FEATURE_pixel_transfer
-   if (new_state & _IMAGE_NEW_TRANSFER_STATE)
+   if (new_state & _MESA_NEW_TRANSFER_STATE)
       _mesa_update_pixel( ctx, new_state );
 #endif
 
+   if (new_state & _DD_NEW_SEPARATE_SPECULAR)
+      update_separate_specular( ctx );
+
    if (new_state & (_NEW_ARRAY | _NEW_PROGRAM))
       update_arrays( ctx );
 
@@ -448,9 +513,11 @@ _mesa_update_state_locked( GLcontext *ctx )
    if (new_state & _NEW_COLOR)
       update_color( ctx );
 
+#if 0
    if (new_state & (_NEW_POINT | _NEW_LINE | _NEW_POLYGON | _NEW_LIGHT
                     | _NEW_STENCIL | _DD_NEW_SEPARATE_SPECULAR))
       update_tricaps( ctx, new_state );
+#endif
 
    /* ctx->_NeedEyeCoords is now up to date.
     *
@@ -464,23 +531,9 @@ _mesa_update_state_locked( GLcontext *ctx )
    if (new_state & _MESA_NEW_NEED_EYE_COORDS) 
       _mesa_update_tnl_spaces( ctx, new_state );
 
-   if (ctx->FragmentProgram._MaintainTexEnvProgram) {
-      prog_flags |= (_NEW_ARRAY | _NEW_TEXTURE_MATRIX | _NEW_LIGHT |
-                     _NEW_RENDERMODE |
-                     _NEW_TEXTURE | _NEW_FOG | _DD_NEW_SEPARATE_SPECULAR);
-   }
-   if (ctx->VertexProgram._MaintainTnlProgram) {
-      prog_flags |= (_NEW_ARRAY | _NEW_TEXTURE | _NEW_TEXTURE_MATRIX |
-                     _NEW_RENDERMODE |
-                     _NEW_TRANSFORM | _NEW_POINT |
-                     _NEW_FOG | _NEW_LIGHT |
-                     _MESA_NEW_NEED_EYE_COORDS);
-   }
    if (new_state & prog_flags)
       update_program( ctx );
 
-
-
    /*
     * Give the driver a chance to act upon the new_state flags.
     * The driver might plug in different span functions, for example.