Merge branch 'llvm-cliptest-viewport'
[mesa.git] / src / mesa / drivers / dri / i915 / i915_state.c
index 814fb59fd3490291834529f76001558872eff099..9508fbaf9426e5f3e421981a4f4fc9991cc48c79 100644 (file)
 
 #define FILE_DEBUG_FLAG DEBUG_STATE
 
-static void
-i915StencilFuncSeparate(GLcontext * ctx, GLenum face, GLenum func, GLint ref,
-                        GLuint mask)
+void
+i915_update_stencil(struct gl_context * ctx)
 {
    struct i915_context *i915 = I915_CONTEXT(ctx);
-   int test = intel_translate_compare_func(func);
+   GLuint front_ref, front_writemask, front_mask;
+   GLenum front_func, front_fail, front_pass_z_fail, front_pass_z_pass;
+   GLuint back_ref, back_writemask, back_mask;
+   GLenum back_func, back_fail, back_pass_z_fail, back_pass_z_pass;
 
-   mask = mask & 0xff;
-
-   DBG("%s : func: %s, ref : 0x%x, mask: 0x%x\n", __FUNCTION__,
-       _mesa_lookup_enum_by_nr(func), ref, mask);
+   I915_STATECHANGE(i915, I915_UPLOAD_CTX);
 
+   /* The 915 considers CW to be "front" for two-sided stencil, so choose
+    * appropriately.
+    */
+   /* _NEW_POLYGON | _NEW_STENCIL */
+   if (ctx->Polygon.FrontFace == GL_CW) {
+      front_ref = ctx->Stencil.Ref[0];
+      front_mask = ctx->Stencil.ValueMask[0];
+      front_writemask = ctx->Stencil.WriteMask[0];
+      front_func = ctx->Stencil.Function[0];
+      front_fail = ctx->Stencil.FailFunc[0];
+      front_pass_z_fail = ctx->Stencil.ZFailFunc[0];
+      front_pass_z_pass = ctx->Stencil.ZPassFunc[0];
+      back_ref = ctx->Stencil.Ref[ctx->Stencil._BackFace];
+      back_mask = ctx->Stencil.ValueMask[ctx->Stencil._BackFace];
+      back_writemask = ctx->Stencil.WriteMask[ctx->Stencil._BackFace];
+      back_func = ctx->Stencil.Function[ctx->Stencil._BackFace];
+      back_fail = ctx->Stencil.FailFunc[ctx->Stencil._BackFace];
+      back_pass_z_fail = ctx->Stencil.ZFailFunc[ctx->Stencil._BackFace];
+      back_pass_z_pass = ctx->Stencil.ZPassFunc[ctx->Stencil._BackFace];
+   } else {
+      front_ref = ctx->Stencil.Ref[ctx->Stencil._BackFace];
+      front_mask = ctx->Stencil.ValueMask[ctx->Stencil._BackFace];
+      front_writemask = ctx->Stencil.WriteMask[ctx->Stencil._BackFace];
+      front_func = ctx->Stencil.Function[ctx->Stencil._BackFace];
+      front_fail = ctx->Stencil.FailFunc[ctx->Stencil._BackFace];
+      front_pass_z_fail = ctx->Stencil.ZFailFunc[ctx->Stencil._BackFace];
+      front_pass_z_pass = ctx->Stencil.ZPassFunc[ctx->Stencil._BackFace];
+      back_ref = ctx->Stencil.Ref[0];
+      back_mask = ctx->Stencil.ValueMask[0];
+      back_writemask = ctx->Stencil.WriteMask[0];
+      back_func = ctx->Stencil.Function[0];
+      back_fail = ctx->Stencil.FailFunc[0];
+      back_pass_z_fail = ctx->Stencil.ZFailFunc[0];
+      back_pass_z_pass = ctx->Stencil.ZPassFunc[0];
+   }
 
-   I915_STATECHANGE(i915, I915_UPLOAD_CTX);
-   i915->state.Ctx[I915_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_TEST_MASK;
+   /* Set front state. */
+   i915->state.Ctx[I915_CTXREG_STATE4] &= ~(MODE4_ENABLE_STENCIL_TEST_MASK |
+                                           MODE4_ENABLE_STENCIL_WRITE_MASK);
    i915->state.Ctx[I915_CTXREG_STATE4] |= (ENABLE_STENCIL_TEST_MASK |
-                                           STENCIL_TEST_MASK(mask));
+                                          ENABLE_STENCIL_WRITE_MASK |
+                                          STENCIL_TEST_MASK(front_mask) |
+                                          STENCIL_WRITE_MASK(front_writemask));
 
    i915->state.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_REF_MASK |
-                                          S5_STENCIL_TEST_FUNC_MASK);
-
-   i915->state.Ctx[I915_CTXREG_LIS5] |= ((ref << S5_STENCIL_REF_SHIFT) |
-                                         (test <<
-                                          S5_STENCIL_TEST_FUNC_SHIFT));
+                                         S5_STENCIL_TEST_FUNC_MASK |
+                                         S5_STENCIL_FAIL_MASK |
+                                         S5_STENCIL_PASS_Z_FAIL_MASK |
+                                         S5_STENCIL_PASS_Z_PASS_MASK);
+
+   i915->state.Ctx[I915_CTXREG_LIS5] |=
+      (front_ref << S5_STENCIL_REF_SHIFT) |
+      (intel_translate_compare_func(front_func) << S5_STENCIL_TEST_FUNC_SHIFT) |
+      (intel_translate_stencil_op(front_fail) << S5_STENCIL_FAIL_SHIFT) |
+      (intel_translate_stencil_op(front_pass_z_fail) <<
+       S5_STENCIL_PASS_Z_FAIL_SHIFT) |
+      (intel_translate_stencil_op(front_pass_z_pass) <<
+       S5_STENCIL_PASS_Z_PASS_SHIFT);
+
+   /* Set back state if different from front. */
+   if (ctx->Stencil._TestTwoSide) {
+      i915->state.Ctx[I915_CTXREG_BF_STENCIL_OPS] &=
+        ~(BFO_STENCIL_REF_MASK |
+          BFO_STENCIL_TEST_MASK |
+          BFO_STENCIL_FAIL_MASK |
+          BFO_STENCIL_PASS_Z_FAIL_MASK |
+          BFO_STENCIL_PASS_Z_PASS_MASK);
+      i915->state.Ctx[I915_CTXREG_BF_STENCIL_OPS] |= BFO_STENCIL_TWO_SIDE |
+        (back_ref << BFO_STENCIL_REF_SHIFT) |
+        (intel_translate_compare_func(back_func) << BFO_STENCIL_TEST_SHIFT) |
+        (intel_translate_stencil_op(back_fail) << BFO_STENCIL_FAIL_SHIFT) |
+        (intel_translate_stencil_op(back_pass_z_fail) <<
+         BFO_STENCIL_PASS_Z_FAIL_SHIFT) |
+        (intel_translate_stencil_op(back_pass_z_pass) <<
+         BFO_STENCIL_PASS_Z_PASS_SHIFT);
+
+      i915->state.Ctx[I915_CTXREG_BF_STENCIL_MASKS] &=
+        ~(BFM_STENCIL_TEST_MASK_MASK |
+          BFM_STENCIL_WRITE_MASK_MASK);
+      i915->state.Ctx[I915_CTXREG_BF_STENCIL_MASKS] |=
+        BFM_STENCIL_TEST_MASK(back_mask) |
+        BFM_STENCIL_WRITE_MASK(back_writemask);
+   } else {
+      i915->state.Ctx[I915_CTXREG_BF_STENCIL_OPS] &= ~BFO_STENCIL_TWO_SIDE;
+   }
 }
 
 static void
-i915StencilMaskSeparate(GLcontext * ctx, GLenum face, GLuint mask)
+i915StencilFuncSeparate(struct gl_context * ctx, GLenum face, GLenum func, GLint ref,
+                        GLuint mask)
 {
-   struct i915_context *i915 = I915_CONTEXT(ctx);
-
-   DBG("%s : mask 0x%x\n", __FUNCTION__, mask);
-   
-   mask = mask & 0xff;
-
-   I915_STATECHANGE(i915, I915_UPLOAD_CTX);
-   i915->state.Ctx[I915_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK;
-   i915->state.Ctx[I915_CTXREG_STATE4] |= (ENABLE_STENCIL_WRITE_MASK |
-                                           STENCIL_WRITE_MASK(mask));
 }
 
+static void
+i915StencilMaskSeparate(struct gl_context * ctx, GLenum face, GLuint mask)
+{
+}
 
 static void
-i915StencilOpSeparate(GLcontext * ctx, GLenum face, GLenum fail, GLenum zfail,
+i915StencilOpSeparate(struct gl_context * ctx, GLenum face, GLenum fail, GLenum zfail,
                       GLenum zpass)
 {
-   struct i915_context *i915 = I915_CONTEXT(ctx);
-   int fop = intel_translate_stencil_op(fail);
-   int dfop = intel_translate_stencil_op(zfail);
-   int dpop = intel_translate_stencil_op(zpass);
-
-
-   DBG("%s: fail : %s, zfail: %s, zpass : %s\n", __FUNCTION__,
-       _mesa_lookup_enum_by_nr(fail),
-       _mesa_lookup_enum_by_nr(zfail), _mesa_lookup_enum_by_nr(zpass));
-
-   I915_STATECHANGE(i915, I915_UPLOAD_CTX);
-
-   i915->state.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_FAIL_MASK |
-                                          S5_STENCIL_PASS_Z_FAIL_MASK |
-                                          S5_STENCIL_PASS_Z_PASS_MASK);
-
-   i915->state.Ctx[I915_CTXREG_LIS5] |= ((fop << S5_STENCIL_FAIL_SHIFT) |
-                                         (dfop <<
-                                          S5_STENCIL_PASS_Z_FAIL_SHIFT) |
-                                         (dpop <<
-                                          S5_STENCIL_PASS_Z_PASS_SHIFT));
 }
 
 static void
-i915AlphaFunc(GLcontext * ctx, GLenum func, GLfloat ref)
+i915AlphaFunc(struct gl_context * ctx, GLenum func, GLfloat ref)
 {
    struct i915_context *i915 = I915_CONTEXT(ctx);
    int test = intel_translate_compare_func(func);
@@ -141,7 +187,7 @@ i915AlphaFunc(GLcontext * ctx, GLenum func, GLfloat ref)
  * calls to glEnable.
  */
 static void
-i915EvalLogicOpBlendState(GLcontext * ctx)
+i915EvalLogicOpBlendState(struct gl_context * ctx)
 {
    struct i915_context *i915 = I915_CONTEXT(ctx);
 
@@ -164,7 +210,7 @@ i915EvalLogicOpBlendState(GLcontext * ctx)
 }
 
 static void
-i915BlendColor(GLcontext * ctx, const GLfloat color[4])
+i915BlendColor(struct gl_context * ctx, const GLfloat color[4])
 {
    struct i915_context *i915 = I915_CONTEXT(ctx);
    GLubyte r, g, b, a;
@@ -209,7 +255,7 @@ translate_blend_equation(GLenum mode)
 }
 
 static void
-i915UpdateBlendState(GLcontext * ctx)
+i915UpdateBlendState(struct gl_context * ctx)
 {
    struct i915_context *i915 = I915_CONTEXT(ctx);
    GLuint iab = (i915->state.Ctx[I915_CTXREG_IAB] &
@@ -260,7 +306,7 @@ i915UpdateBlendState(GLcontext * ctx)
 
 
 static void
-i915BlendFuncSeparate(GLcontext * ctx, GLenum srcRGB,
+i915BlendFuncSeparate(struct gl_context * ctx, GLenum srcRGB,
                       GLenum dstRGB, GLenum srcA, GLenum dstA)
 {
    i915UpdateBlendState(ctx);
@@ -268,14 +314,14 @@ i915BlendFuncSeparate(GLcontext * ctx, GLenum srcRGB,
 
 
 static void
-i915BlendEquationSeparate(GLcontext * ctx, GLenum eqRGB, GLenum eqA)
+i915BlendEquationSeparate(struct gl_context * ctx, GLenum eqRGB, GLenum eqA)
 {
    i915UpdateBlendState(ctx);
 }
 
 
 static void
-i915DepthFunc(GLcontext * ctx, GLenum func)
+i915DepthFunc(struct gl_context * ctx, GLenum func)
 {
    struct i915_context *i915 = I915_CONTEXT(ctx);
    int test = intel_translate_compare_func(func);
@@ -288,7 +334,7 @@ i915DepthFunc(GLcontext * ctx, GLenum func)
 }
 
 static void
-i915DepthMask(GLcontext * ctx, GLboolean flag)
+i915DepthMask(struct gl_context * ctx, GLboolean flag)
 {
    struct i915_context *i915 = I915_CONTEXT(ctx);
 
@@ -311,7 +357,7 @@ i915DepthMask(GLcontext * ctx, GLboolean flag)
  *  - window pos/size or FBO size
  */
 void
-intelCalcViewport(GLcontext * ctx)
+intelCalcViewport(struct gl_context * ctx)
 {
    struct intel_context *intel = intel_context(ctx);
    const GLfloat *v = ctx->Viewport._WindowMap.m;
@@ -328,7 +374,7 @@ intelCalcViewport(GLcontext * ctx)
    else {
       /* window buffer, y=0=top */
       yScale = -1.0;
-      yBias = (intel->driDrawable) ? intel->driDrawable->h : 0.0F;
+      yBias = ctx->DrawBuffer->Height;
    }
 
    m[MAT_SX] = v[MAT_SX];
@@ -344,18 +390,16 @@ intelCalcViewport(GLcontext * ctx)
 
 /** Called from ctx->Driver.Viewport() */
 static void
-i915Viewport(GLcontext * ctx,
+i915Viewport(struct gl_context * ctx,
               GLint x, GLint y, GLsizei width, GLsizei height)
 {
    intelCalcViewport(ctx);
-
-   intel_viewport(ctx, x, y, width, height);
 }
 
 
 /** Called from ctx->Driver.DepthRange() */
 static void
-i915DepthRange(GLcontext * ctx, GLclampd nearval, GLclampd farval)
+i915DepthRange(struct gl_context * ctx, GLclampd nearval, GLclampd farval)
 {
    intelCalcViewport(ctx);
 }
@@ -368,7 +412,7 @@ i915DepthRange(GLcontext * ctx, GLclampd nearval, GLclampd farval)
  * Fortunately stipple is usually a repeating pattern.
  */
 static void
-i915PolygonStipple(GLcontext * ctx, const GLubyte * mask)
+i915PolygonStipple(struct gl_context * ctx, const GLubyte * mask)
 {
    struct i915_context *i915 = I915_CONTEXT(ctx);
    const GLubyte *m;
@@ -430,7 +474,7 @@ i915PolygonStipple(GLcontext * ctx, const GLubyte * mask)
  * Hardware clipping
  */
 static void
-i915Scissor(GLcontext * ctx, GLint x, GLint y, GLsizei w, GLsizei h)
+i915Scissor(struct gl_context * ctx, GLint x, GLint y, GLsizei w, GLsizei h)
 {
    struct i915_context *i915 = I915_CONTEXT(ctx);
    int x1, y1, x2, y2;
@@ -470,7 +514,7 @@ i915Scissor(GLcontext * ctx, GLint x, GLint y, GLsizei w, GLsizei h)
 }
 
 static void
-i915LogicOp(GLcontext * ctx, GLenum opcode)
+i915LogicOp(struct gl_context * ctx, GLenum opcode)
 {
    struct i915_context *i915 = I915_CONTEXT(ctx);
    int tmp = intel_translate_logic_op(opcode);
@@ -485,7 +529,7 @@ i915LogicOp(GLcontext * ctx, GLenum opcode)
 
 
 static void
-i915CullFaceFrontFace(GLcontext * ctx, GLenum unused)
+i915CullFaceFrontFace(struct gl_context * ctx, GLenum unused)
 {
    struct i915_context *i915 = I915_CONTEXT(ctx);
    GLuint mode;
@@ -516,7 +560,7 @@ i915CullFaceFrontFace(GLcontext * ctx, GLenum unused)
 }
 
 static void
-i915LineWidth(GLcontext * ctx, GLfloat widthf)
+i915LineWidth(struct gl_context * ctx, GLfloat widthf)
 {
    struct i915_context *i915 = I915_CONTEXT(ctx);
    int lis4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_LINE_WIDTH_MASK;
@@ -525,7 +569,7 @@ i915LineWidth(GLcontext * ctx, GLfloat widthf)
    DBG("%s\n", __FUNCTION__);
    
    width = (int) (widthf * 2);
-   CLAMP_SELF(width, 1, 0xf);
+   width = CLAMP(width, 1, 0xf);
    lis4 |= width << S4_LINE_WIDTH_SHIFT;
 
    if (lis4 != i915->state.Ctx[I915_CTXREG_LIS4]) {
@@ -535,15 +579,15 @@ i915LineWidth(GLcontext * ctx, GLfloat widthf)
 }
 
 static void
-i915PointSize(GLcontext * ctx, GLfloat size)
+i915PointSize(struct gl_context * ctx, GLfloat size)
 {
    struct i915_context *i915 = I915_CONTEXT(ctx);
    int lis4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_POINT_WIDTH_MASK;
-   GLint point_size = (int) size;
+   GLint point_size = (int) round(size);
 
    DBG("%s\n", __FUNCTION__);
    
-   CLAMP_SELF(point_size, 1, 255);
+   point_size = CLAMP(point_size, 1, 255);
    lis4 |= point_size << S4_POINT_WIDTH_SHIFT;
 
    if (lis4 != i915->state.Ctx[I915_CTXREG_LIS4]) {
@@ -553,12 +597,30 @@ i915PointSize(GLcontext * ctx, GLfloat size)
 }
 
 
+static void
+i915PointParameterfv(struct gl_context * ctx, GLenum pname, const GLfloat *params)
+{
+   struct i915_context *i915 = I915_CONTEXT(ctx);
+
+   switch (pname) {
+   case GL_POINT_SPRITE_COORD_ORIGIN:
+      /* This could be supported, but it would require modifying the fragment
+       * program to invert the y component of the texture coordinate by
+       * inserting a 'SUB tc.y, {1.0}.xxxx, tc' instruction.
+       */
+      FALLBACK(&i915->intel, I915_FALLBACK_POINT_SPRITE_COORD_ORIGIN,
+              (params[0] != GL_UPPER_LEFT));
+      break;
+   }
+}
+
+
 /* =============================================================
  * Color masks
  */
 
 static void
-i915ColorMask(GLcontext * ctx,
+i915ColorMask(struct gl_context * ctx,
               GLboolean r, GLboolean g, GLboolean b, GLboolean a)
 {
    struct i915_context *i915 = I915_CONTEXT(ctx);
@@ -583,7 +645,7 @@ i915ColorMask(GLcontext * ctx,
 }
 
 static void
-update_specular(GLcontext * ctx)
+update_specular(struct gl_context * ctx)
 {
    /* A hack to trigger the rebuild of the fragment program.
     */
@@ -591,7 +653,7 @@ update_specular(GLcontext * ctx)
 }
 
 static void
-i915LightModelfv(GLcontext * ctx, GLenum pname, const GLfloat * param)
+i915LightModelfv(struct gl_context * ctx, GLenum pname, const GLfloat * param)
 {
    DBG("%s\n", __FUNCTION__);
    
@@ -601,7 +663,7 @@ i915LightModelfv(GLcontext * ctx, GLenum pname, const GLfloat * param)
 }
 
 static void
-i915ShadeModel(GLcontext * ctx, GLenum mode)
+i915ShadeModel(struct gl_context * ctx, GLenum mode)
 {
    struct i915_context *i915 = I915_CONTEXT(ctx);
    I915_STATECHANGE(i915, I915_UPLOAD_CTX);
@@ -622,7 +684,7 @@ i915ShadeModel(GLcontext * ctx, GLenum mode)
  * Fog
  */
 void
-i915_update_fog(GLcontext * ctx)
+i915_update_fog(struct gl_context * ctx)
 {
    struct i915_context *i915 = I915_CONTEXT(ctx);
    GLenum mode;
@@ -718,7 +780,7 @@ i915_update_fog(GLcontext * ctx)
 }
 
 static void
-i915Fogfv(GLcontext * ctx, GLenum pname, const GLfloat * param)
+i915Fogfv(struct gl_context * ctx, GLenum pname, const GLfloat * param)
 {
    struct i915_context *i915 = I915_CONTEXT(ctx);
 
@@ -758,7 +820,7 @@ i915Fogfv(GLcontext * ctx, GLenum pname, const GLfloat * param)
 }
 
 static void
-i915Hint(GLcontext * ctx, GLenum target, GLenum state)
+i915Hint(struct gl_context * ctx, GLenum target, GLenum state)
 {
    switch (target) {
    case GL_FOG_HINT:
@@ -772,7 +834,7 @@ i915Hint(GLcontext * ctx, GLenum target, GLenum state)
  */
 
 static void
-i915Enable(GLcontext * ctx, GLenum cap, GLboolean state)
+i915Enable(struct gl_context * ctx, GLenum cap, GLboolean state)
 {
    struct i915_context *i915 = I915_CONTEXT(ctx);
 
@@ -893,6 +955,17 @@ i915Enable(GLcontext * ctx, GLenum cap, GLboolean state)
    case GL_POLYGON_SMOOTH:
       break;
 
+   case GL_POINT_SPRITE:
+      /* This state change is handled in i915_reduced_primitive_state because
+       * the hardware bit should only be set when rendering points.
+       */
+      I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+      if (state)
+        i915->state.Ctx[I915_CTXREG_LIS4] |= S4_SPRITE_POINT_ENABLE;
+      else
+        i915->state.Ctx[I915_CTXREG_LIS4] &= ~S4_SPRITE_POINT_ENABLE;
+      break;
+
    case GL_POINT_SMOOTH:
       break;
 
@@ -945,6 +1018,17 @@ i915_init_packets(struct i915_context *i915)
          _3DSTATE_CONST_BLEND_COLOR_CMD;
       i915->state.Ctx[I915_CTXREG_BLENDCOLOR1] = 0;
 
+      i915->state.Ctx[I915_CTXREG_BF_STENCIL_MASKS] =
+        _3DSTATE_BACKFACE_STENCIL_MASKS |
+        BFM_ENABLE_STENCIL_TEST_MASK |
+        BFM_ENABLE_STENCIL_WRITE_MASK |
+        (0xff << BFM_STENCIL_WRITE_MASK_SHIFT) |
+        (0xff << BFM_STENCIL_TEST_MASK_SHIFT);
+      i915->state.Ctx[I915_CTXREG_BF_STENCIL_OPS] =
+        _3DSTATE_BACKFACE_STENCIL_OPS |
+        BFO_ENABLE_STENCIL_REF |
+        BFO_ENABLE_STENCIL_FUNCS |
+        BFO_ENABLE_STENCIL_TWO_SIDE;
    }
 
    {
@@ -976,6 +1060,13 @@ i915_init_packets(struct i915_context *i915)
       i915->state.Buffer[I915_DESTREG_SR2] = 0;
    }
 
+   i915->state.RasterRules[I915_RASTER_RULES] = _3DSTATE_RASTER_RULES_CMD |
+      ENABLE_POINT_RASTER_RULE |
+      OGL_POINT_RASTER_RULE |
+      ENABLE_LINE_STRIP_PROVOKE_VRTX |
+      ENABLE_TRI_FAN_PROVOKE_VRTX |
+      LINE_STRIP_PROVOKE_VRTX(1) |
+      TRI_FAN_PROVOKE_VRTX(2) | ENABLE_TEXKILL_3D_4D | TEXKILL_4D;
 
 #if 0
    {
@@ -996,7 +1087,33 @@ i915_init_packets(struct i915_context *i915)
    i915->state.active = (I915_UPLOAD_PROGRAM |
                          I915_UPLOAD_STIPPLE |
                          I915_UPLOAD_CTX |
-                         I915_UPLOAD_BUFFERS | I915_UPLOAD_INVARIENT);
+                         I915_UPLOAD_BUFFERS |
+                        I915_UPLOAD_INVARIENT |
+                        I915_UPLOAD_RASTER_RULES);
+}
+
+void
+i915_update_provoking_vertex(struct gl_context * ctx)
+{
+   struct i915_context *i915 = I915_CONTEXT(ctx);
+
+   I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+   i915->state.Ctx[I915_CTXREG_LIS6] &= ~(S6_TRISTRIP_PV_MASK);
+
+   I915_STATECHANGE(i915, I915_UPLOAD_RASTER_RULES);
+   i915->state.RasterRules[I915_RASTER_RULES] &= ~(LINE_STRIP_PROVOKE_VRTX_MASK |
+                                                  TRI_FAN_PROVOKE_VRTX_MASK);
+
+   /* _NEW_LIGHT */
+   if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION) {
+      i915->state.RasterRules[I915_RASTER_RULES] |= (LINE_STRIP_PROVOKE_VRTX(1) |
+                                                    TRI_FAN_PROVOKE_VRTX(2));
+      i915->state.Ctx[I915_CTXREG_LIS6] |= (2 << S6_TRISTRIP_PV_SHIFT);
+   } else {
+      i915->state.RasterRules[I915_RASTER_RULES] |= (LINE_STRIP_PROVOKE_VRTX(0) |
+                                                    TRI_FAN_PROVOKE_VRTX(1));
+      i915->state.Ctx[I915_CTXREG_LIS6] |= (0 << S6_TRISTRIP_PV_SHIFT);
+    }
 }
 
 void
@@ -1018,6 +1135,7 @@ i915InitStateFunctions(struct dd_function_table *functions)
    functions->LineWidth = i915LineWidth;
    functions->LogicOpcode = i915LogicOp;
    functions->PointSize = i915PointSize;
+   functions->PointParameterfv = i915PointParameterfv;
    functions->PolygonStipple = i915PolygonStipple;
    functions->Scissor = i915Scissor;
    functions->ShadeModel = i915ShadeModel;
@@ -1032,12 +1150,9 @@ i915InitStateFunctions(struct dd_function_table *functions)
 void
 i915InitState(struct i915_context *i915)
 {
-   GLcontext *ctx = &i915->intel.ctx;
+   struct gl_context *ctx = &i915->intel.ctx;
 
    i915_init_packets(i915);
 
    _mesa_init_driver_state(ctx);
-
-   memcpy(&i915->initial, &i915->state, sizeof(i915->state));
-   i915->current = &i915->state;
 }