Merge branch 'master' of git+ssh://keithw@git.freedesktop.org/git/mesa/mesa into...
[mesa.git] / src / mesa / drivers / dri / nouveau / nv30_state.c
index 7b50cbc4611b41c761f1aa2a9e383b1db3d0d7a5..4d79bb6127ca5ed8de0f999002ce5937e54ff079 100644 (file)
@@ -79,6 +79,22 @@ static void nv30BlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB, GLenum dfac
        OUT_RING_CACHE((dfactorA<<16) | dfactorRGB);
 }
 
+static void nv30Clear(GLcontext *ctx, GLbitfield mask)
+{
+       nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+       GLuint hw_bufs = 0;
+
+       if (mask & (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT))
+               hw_bufs |= 0xf0;
+       if (mask & (BUFFER_BIT_DEPTH))
+               hw_bufs |= 0x03;
+
+       if (hw_bufs) {
+               BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CLEAR_WHICH_BUFFERS, 1);
+               OUT_RING(hw_bufs);
+       }
+}
+
 static void nv30ClearColor(GLcontext *ctx, const GLfloat color[4])
 {
        nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
@@ -277,8 +293,10 @@ static void nv30Enable(GLcontext *ctx, GLenum cap, GLboolean state)
 //             case GL_MAP2_VERTEX_4:
 //             case GL_MINMAX:
                case GL_NORMALIZE:
-                       BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_NORMALIZE_ENABLE, 1);
-                       OUT_RING_CACHE(state);
+                       if (nmesa->screen->card->type != NV_44) {
+                               BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_NORMALIZE_ENABLE, 1);
+                               OUT_RING_CACHE(state);
+                       }
                        break;
 //             case GL_POINT_SMOOTH:
                case GL_POLYGON_OFFSET_POINT:
@@ -304,10 +322,16 @@ static void nv30Enable(GLcontext *ctx, GLenum cap, GLboolean state)
 //             case GL_POST_COLOR_MATRIX_COLOR_TABLE:
 //             case GL_POST_CONVOLUTION_COLOR_TABLE:
 //             case GL_RESCALE_NORMAL:
-//             case GL_SCISSOR_TEST:
+               case GL_SCISSOR_TEST:
+                       /* No enable bit, nv30Scissor will adjust to max range */
+                       ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
+                                                ctx->Scissor.Width, ctx->Scissor.Height);
+                       break;
 //             case GL_SEPARABLE_2D:
                case GL_STENCIL_TEST:
                        // TODO BACK and FRONT ?
+                       BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_ENABLE, 1);
+                       OUT_RING_CACHE(state);
                        BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_ENABLE, 1);
                        OUT_RING_CACHE(state);
                        break;
@@ -324,17 +348,71 @@ static void nv30Enable(GLcontext *ctx, GLenum cap, GLboolean state)
 static void nv30Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *params)
 {
     nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+    if (NOUVEAU_CARD_USING_SHADERS)
+        return;
+
     switch(pname)
     {
-        case GL_FOG_MODE:
-            BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FOG_MODE, 1);
-            //OUT_RING_CACHE (params);
+    case GL_FOG_MODE:
+    {
+        int mode = 0;
+        /* The modes are different in GL and the card.  */
+        switch(ctx->Fog.Mode)
+        {
+        case GL_LINEAR:
+            mode = 0x804;
+            break;
+        case GL_EXP:
+            mode = 0x802;
             break;
-            /* TODO: unsure about the rest.*/
-        default:
+        case GL_EXP2:
+            mode = 0x803;
             break;
+        }
+       BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FOG_MODE, 1);
+       OUT_RING_CACHE (mode);
+       break;
+    }
+    case GL_FOG_COLOR:
+    {
+       GLubyte c[4];
+       UNCLAMPED_FLOAT_TO_RGBA_CHAN(c,params);
+        BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FOG_COLOR, 1);
+        /* nvidia ignores the alpha channel */
+       OUT_RING_CACHE(PACK_COLOR_8888_REV(c[0],c[1],c[2],c[3]));
+        break;
+    }
+    case GL_FOG_DENSITY:
+    case GL_FOG_START:
+    case GL_FOG_END:
+    {
+        GLfloat f=0., c=0.;
+        switch(ctx->Fog.Mode)
+        {
+        case GL_LINEAR:
+            f = -1.0/(ctx->Fog.End - ctx->Fog.Start);
+            c = ctx->Fog.Start/(ctx->Fog.End - ctx->Fog.Start) + 2.001953;
+            break;
+        case GL_EXP:
+            f = -0.090168*ctx->Fog.Density;
+            c = 1.5;
+        case GL_EXP2:
+            f = -0.212330*ctx->Fog.Density;
+            c = 1.5;
+        }
+        BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FOG_EQUATION_LINEAR, 1);
+        OUT_RING_CACHE(f);
+        BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FOG_EQUATION_CONSTANT, 1);
+        OUT_RING_CACHE(c);
+        BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FOG_EQUATION_QUADRATIC, 1);
+        OUT_RING_CACHE(0); /* Is this always the same? */
+        break;
+    }
+//    case GL_FOG_COORD_SRC:
+    default:
+        break;
     }
-
 }
    
 static void nv30Hint(GLcontext *ctx, GLenum target, GLenum mode)
@@ -344,9 +422,19 @@ static void nv30Hint(GLcontext *ctx, GLenum target, GLenum mode)
 
 // void (*IndexMask)(GLcontext *ctx, GLuint mask);
 
+enum {
+       SPOTLIGHT_NO_UPDATE,
+       SPOTLIGHT_UPDATE_EXPONENT,
+       SPOTLIGHT_UPDATE_DIRECTION,
+       SPOTLIGHT_UPDATE_ALL
+};
+
 static void nv30Lightfv(GLcontext *ctx, GLenum light, GLenum pname, const GLfloat *params )
 {
        nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+       GLint p = light - GL_LIGHT0;
+       struct gl_light *l = &ctx->Light.Light[p];
+       int spotlight_update = SPOTLIGHT_NO_UPDATE;
 
        if (NOUVEAU_CARD_USING_SHADERS)
           return;
@@ -355,63 +443,104 @@ static void nv30Lightfv(GLcontext *ctx, GLenum light, GLenum pname, const GLfloa
        switch(pname)
        {
                case GL_AMBIENT:
-                       BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_A(light), 3);
+                       BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_R(p), 3);
                        OUT_RING_CACHEf(params[0]);
                        OUT_RING_CACHEf(params[1]);
                        OUT_RING_CACHEf(params[2]);
                        break;
                case GL_DIFFUSE:
-                       BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_A(light), 3);
+                       BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_R(p), 3);
                        OUT_RING_CACHEf(params[0]);
                        OUT_RING_CACHEf(params[1]);
                        OUT_RING_CACHEf(params[2]);
                        break;
                case GL_SPECULAR:
-                       BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_A(light), 3);
-                       OUT_RING_CACHEf(params[0]);
-                       OUT_RING_CACHEf(params[1]);
-                       OUT_RING_CACHEf(params[2]);
-                       break;
-               case GL_SPOT_DIRECTION:
-                       BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_DIR_X(light), 3);
+                       BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_R(p), 3);
                        OUT_RING_CACHEf(params[0]);
                        OUT_RING_CACHEf(params[1]);
                        OUT_RING_CACHEf(params[2]);
                        break;
                case GL_POSITION:
-                       BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_POSITION_X(light), 3);
+                       BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_POSITION_X(p), 3);
                        OUT_RING_CACHEf(params[0]);
                        OUT_RING_CACHEf(params[1]);
                        OUT_RING_CACHEf(params[2]);
                        break;
+               case GL_SPOT_DIRECTION:
+                       spotlight_update = SPOTLIGHT_UPDATE_DIRECTION;
+                       break;
                case GL_SPOT_EXPONENT:
-                       BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_EXPONENT(light), 1);
-                       OUT_RING_CACHEf(*params);
+                       spotlight_update = SPOTLIGHT_UPDATE_EXPONENT;
                        break;
                case GL_SPOT_CUTOFF:
-                       /* you can't factor these */
-                       BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_A(light), 1);
-                       OUT_RING_CACHEf(params[0]);
-                       BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_B(light), 1);
-                       OUT_RING_CACHEf(params[1]);
-                       BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_C(light), 1);
-                       OUT_RING_CACHEf(params[2]);
+                       spotlight_update = SPOTLIGHT_UPDATE_ALL;
                        break;
                case GL_CONSTANT_ATTENUATION:
-                       BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_CONSTANT_ATTENUATION(light), 1);
+                       BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_CONSTANT_ATTENUATION(p), 1);
                        OUT_RING_CACHEf(*params);
                        break;
                case GL_LINEAR_ATTENUATION:
-                       BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_LINEAR_ATTENUATION(light), 1);
+                       BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_LINEAR_ATTENUATION(p), 1);
                        OUT_RING_CACHEf(*params);
                        break;
                case GL_QUADRATIC_ATTENUATION:
-                       BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_QUADRATIC_ATTENUATION(light), 1);
+                       BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_QUADRATIC_ATTENUATION(p), 1);
                        OUT_RING_CACHEf(*params);
                        break;
                default:
                        break;
        }
+
+       switch(spotlight_update) {
+               case SPOTLIGHT_UPDATE_DIRECTION:
+                       {
+                               GLfloat x,y,z;
+                               GLfloat spot_light_coef_a = 1.0 / (l->_CosCutoff - 1.0);
+                               x = spot_light_coef_a * l->_NormDirection[0];
+                               y = spot_light_coef_a * l->_NormDirection[1];
+                               z = spot_light_coef_a * l->_NormDirection[2];
+                               BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_DIR_X(p), 3);
+                               OUT_RING_CACHEf(x);
+                               OUT_RING_CACHEf(y);
+                               OUT_RING_CACHEf(z);
+                       }
+                       break;
+               case SPOTLIGHT_UPDATE_EXPONENT:
+                       {
+                               GLfloat cc,lc,qc;
+                               cc = 1.0;       /* FIXME: These need to be correctly computed */
+                               lc = 0.0;
+                               qc = 2.0;
+                               BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_A(p), 3);
+                               OUT_RING_CACHEf(cc);
+                               OUT_RING_CACHEf(lc);
+                               OUT_RING_CACHEf(qc);
+                       }
+                       break;
+               case SPOTLIGHT_UPDATE_ALL:
+                       {
+                               GLfloat cc,lc,qc, x,y,z, c;
+                               GLfloat spot_light_coef_a = 1.0 / (l->_CosCutoff - 1.0);
+                               cc = 1.0;       /* FIXME: These need to be correctly computed */
+                               lc = 0.0;
+                               qc = 2.0;
+                               x = spot_light_coef_a * l->_NormDirection[0];
+                               y = spot_light_coef_a * l->_NormDirection[1];
+                               z = spot_light_coef_a * l->_NormDirection[2];
+                               c = spot_light_coef_a + 1.0;
+                               BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_A(p), 7);
+                               OUT_RING_CACHEf(cc);
+                               OUT_RING_CACHEf(lc);
+                               OUT_RING_CACHEf(qc);
+                               OUT_RING_CACHEf(x);
+                               OUT_RING_CACHEf(y);
+                               OUT_RING_CACHEf(z);
+                               OUT_RING_CACHEf(c);
+                       }
+                       break;
+               default:
+                       break;
+       }
 }
 
 /** Set the lighting model parameters */
@@ -477,19 +606,19 @@ static void nv30PolygonMode(GLcontext *ctx, GLenum face, GLenum mode)
 static void nv30PolygonOffset(GLcontext *ctx, GLfloat factor, GLfloat units)
 {
         nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
-        BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FACTOR, 2);
-        OUT_RINGf(factor);
+        BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FACTOR, 2);
+        OUT_RING_CACHEf(factor);
 
         /* Looks like we always multiply units by 2.0... according to the dumps.*/
-        OUT_RINGf(units * 2.0);
+        OUT_RING_CACHEf(units * 2.0);
 }
 
 /** Set the polygon stippling pattern */
 static void nv30PolygonStipple(GLcontext *ctx, const GLubyte *mask )
 {
         nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
-        BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_STIPPLE_PATTERN(0), 32);
-        OUT_RINGp(mask, 32);
+        BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_STIPPLE_PATTERN(0), 32);
+        OUT_RING_CACHEp(mask, 32);
 }
 
 /* Specifies the current buffer for reading */
@@ -501,9 +630,21 @@ void (*RenderMode)(GLcontext *ctx, GLenum mode );
 static void nv30Scissor(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
 {
         nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
-        BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SCISSOR_WIDTH_XPOS, 2);
-        OUT_RING((w << 16) | x);
-        OUT_RING((y << 16) | y);
+
+       /* There's no scissor enable bit, so adjust the scissor to cover the
+        * maximum draw buffer bounds
+        */
+       if (!ctx->Scissor.Enabled) {
+          x = y = 0;
+          w = h = 4095;
+       } else {
+          x += nmesa->drawX;
+          y += nmesa->drawY;
+       }
+
+        BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SCISSOR_WIDTH_XPOS, 2);
+        OUT_RING_CACHE(((w) << 16) | x);
+        OUT_RING_CACHE(((h) << 16) | y);
 }
 
 /** Select flat or smooth shading */
@@ -584,27 +725,133 @@ void (*TexParameter)(GLcontext *ctx, GLenum target,
 static void nv30TextureMatrix(GLcontext *ctx, GLuint unit, const GLmatrix *mat)
 {
         nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
-        BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_TX_MATRIX(unit, 0), 16);
+        BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_TX_MATRIX(unit, 0), 16);
         /*XXX: This SHOULD work.*/
-        OUT_RINGp(mat->m, 16);
+        OUT_RING_CACHEp(mat->m, 16);
 }
 
-/** Set the viewport */
-static void nv30Viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
+static void nv30WindowMoved(nouveauContextPtr nmesa)
 {
-        /* TODO: Where do the VIEWPORT_XFRM_* regs come in? */
-        nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+       GLcontext *ctx = nmesa->glCtx;
+       GLfloat *v = nmesa->viewport.m;
+       GLuint w = ctx->Viewport.Width;
+       GLuint h = ctx->Viewport.Height;
+       GLuint x = ctx->Viewport.X + nmesa->drawX;
+       GLuint y = ctx->Viewport.Y + nmesa->drawY;
+
         BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VIEWPORT_DIMS_0, 2);
         OUT_RING_CACHE((w << 16) | x);
         OUT_RING_CACHE((h << 16) | y);
-}
-
-void nv30InitStateFuncs(struct dd_function_table *func)
+       /* something to do with clears, possibly doesn't belong here */
+       BEGIN_RING_CACHE(NvSub3D,
+             NV30_TCL_PRIMITIVE_3D_VIEWPORT_COLOR_BUFFER_OFS0, 2);
+        OUT_RING_CACHE(((w+x) << 16) | x);
+        OUT_RING_CACHE(((h+y) << 16) | y);
+       /* viewport transform */
+       BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VIEWPORT_XFRM_OX, 8);
+       OUT_RING_CACHEf (v[MAT_TX]);
+       OUT_RING_CACHEf (v[MAT_TY]);
+       OUT_RING_CACHEf (v[MAT_TZ]);
+       OUT_RING_CACHEf (0.0);
+       OUT_RING_CACHEf (v[MAT_SX]);
+       OUT_RING_CACHEf (v[MAT_SY]);
+       OUT_RING_CACHEf (v[MAT_SZ]);
+       OUT_RING_CACHEf (0.0);
+
+       ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
+                           ctx->Scissor.Width, ctx->Scissor.Height);
+}
+
+static GLboolean nv30InitCard(nouveauContextPtr nmesa)
+{
+       /* Need some love.. */
+       return GL_FALSE;
+}
+
+static GLboolean nv40InitCard(nouveauContextPtr nmesa)
+{
+       nouveauObjectOnSubchannel(nmesa, NvSub3D, Nv3D);
+
+       BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT1, 2);
+       OUT_RING(NvDmaFB);
+       OUT_RING(NvDmaFB);
+       BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT8, 1);
+       OUT_RING(NvDmaFB);
+       BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT4, 2);
+       OUT_RING(NvDmaFB);
+       OUT_RING(NvDmaFB);
+       BEGIN_RING_SIZE(NvSub3D, 0x0220, 1);
+       OUT_RING(1);
+
+       BEGIN_RING_SIZE(NvSub3D, 0x1ea4, 3);
+       OUT_RING(0x00000010);
+       OUT_RING(0x01000100);
+       OUT_RING(0xff800006);
+       BEGIN_RING_SIZE(NvSub3D, 0x1fc4, 1);
+       OUT_RING(0x06144321);
+       BEGIN_RING_SIZE(NvSub3D, 0x1fc8, 2);
+       OUT_RING(0xedcba987);
+       OUT_RING(0x00000021);
+       BEGIN_RING_SIZE(NvSub3D, 0x1fd0, 1);
+       OUT_RING(0x00171615);
+       BEGIN_RING_SIZE(NvSub3D, 0x1fd4, 1);
+       OUT_RING(0x001b1a19);
+
+       BEGIN_RING_SIZE(NvSub3D, 0x1ef8, 1);
+       OUT_RING(0x0020ffff);
+       BEGIN_RING_SIZE(NvSub3D, 0x1d64, 1);
+       OUT_RING(0x00d30000);
+       BEGIN_RING_SIZE(NvSub3D, 0x1e94, 1);
+       OUT_RING(0x00000001);
+
+       BEGIN_RING_SIZE(NvSub3D, 0x1d60, 1);
+       OUT_RING(0x03008000);
+
+       return GL_TRUE;
+}
+
+static GLboolean nv30BindBuffers(nouveauContextPtr nmesa, int num_color,
+                                nouveau_renderbuffer **color,
+                                nouveau_renderbuffer *depth)
+{
+   GLuint x, y, w, h;
+
+   w = color[0]->mesa.Width;
+   h = color[0]->mesa.Height;
+   x = nmesa->drawX;
+   y = nmesa->drawY;
+
+   if (num_color != 1)
+      return GL_FALSE;
+   BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VIEWPORT_COLOR_BUFFER_DIM0, 5);
+   OUT_RING        (((w+x)<<16)|x);
+   OUT_RING        (((h+y)<<16)|y);
+   if (color[0]->mesa._ActualFormat == GL_RGBA8)
+      OUT_RING        (0x148);
+   else
+      OUT_RING        (0x143);
+   OUT_RING        (color[0]->pitch);
+   OUT_RING        (color[0]->offset);
+
+   if (depth) {
+      BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_DEPTH_OFFSET, 1);
+      OUT_RING        (depth->offset);
+      BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LMA_DEPTH_BUFFER_PITCH, 1);
+      OUT_RING        (depth->pitch);
+   }
+
+   return GL_TRUE;
+}
+
+void nv30InitStateFuncs(GLcontext *ctx, struct dd_function_table *func)
 {
+       nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
        func->AlphaFunc                 = nv30AlphaFunc;
        func->BlendColor                = nv30BlendColor;
        func->BlendEquationSeparate     = nv30BlendEquationSeparate;
        func->BlendFuncSeparate         = nv30BlendFuncSeparate;
+       func->Clear                     = nv30Clear;
        func->ClearColor                = nv30ClearColor;
        func->ClearDepth                = nv30ClearDepth;
        func->ClearStencil              = nv30ClearStencil;
@@ -615,7 +862,6 @@ void nv30InitStateFuncs(struct dd_function_table *func)
        func->FrontFace                 = nv30FrontFace;
        func->DepthFunc                 = nv30DepthFunc;
        func->DepthMask                 = nv30DepthMask;
-       func->DepthRange                = nv30DepthRange;
        func->Enable                    = nv30Enable;
        func->Fogfv                     = nv30Fogfv;
        func->Hint                      = nv30Hint;
@@ -643,6 +889,13 @@ void nv30InitStateFuncs(struct dd_function_table *func)
        func->TexParameter              = nv30TexParameter;
 #endif
        func->TextureMatrix             = nv30TextureMatrix;
-       func->Viewport                  = nv30Viewport;
+
+
+       if (nmesa->screen->card->type >= NV_40)
+          nmesa->hw_func.InitCard      = nv40InitCard;
+       else 
+          nmesa->hw_func.InitCard      = nv30InitCard;
+       nmesa->hw_func.BindBuffers      = nv30BindBuffers;
+       nmesa->hw_func.WindowMoved      = nv30WindowMoved;
 }