+#endif
+}
+
+/* =============================================================
+ * Line state
+ */
+static void r300LineWidth(GLcontext *ctx, GLfloat widthf)
+{
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
+ /* IMHO mesa isnt clamping line widths according to ctx->Const.*LineWidth
+ before calling this from the dd function table.
+ Since r300ResetHwState calls these with clamped values,
+ they must be set properly. */
+
+ R300_STATECHANGE(r300, lcntl);
+ r300->hw.lcntl.cmd[1] = (int)(widthf * 6.0);
+ /* Doesnt look very good without this... */
+ r300->hw.lcntl.cmd[1] |= R300_LINE_CNT_UNK1;
+}
+
+/*
+
+glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); : 00000091 ( 1001 0001)
+glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); : 00000001 ( 1)
+
+glPolygonMode(GL_FRONT, GL_LINE); : 00000111 (1 0001 0001)
+glPolygonMode(GL_FRONT, GL_POINT); : 00000101 (1 0000 0001)
+
+glPolygonMode(GL_BACK, GL_LINE); : 000000a1 ( 1010 0001)
+glPolygonMode(GL_BACK, GL_POINT); : 00000021 ( 10 0001)
+
+*/
+
+/* exclusive */
+#define PM_NOT_BACK (1<<8)
+#define PM_NOT_FRONT (1<<5)
+
+#define PM_FRONT_LINE (1<<4)
+#define PM_BACK_LINE (1<<7)
+
+static void r300PolygonMode(GLcontext *ctx, GLenum face, GLenum mode)
+{
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
+ unsigned long hw_mode=0;
+
+ hw_mode=r300->hw.unk4288.cmd[1];
+ hw_mode |= 1; /* enables point mode by default */
+
+ switch (face) {
+ case GL_FRONT:
+ //fprintf(stderr, "front\n");
+ hw_mode &= ~PM_NOT_FRONT;
+ switch (mode) {
+ case GL_LINE:
+ hw_mode |= PM_FRONT_LINE;
+ break;
+ case GL_POINT:
+ hw_mode &= ~PM_FRONT_LINE;
+ break;
+ case GL_FILL: /* No idea */
+ hw_mode = 0;
+ break;
+ }
+ break;
+
+ case GL_BACK:
+ //fprintf(stderr, "back\n");
+ hw_mode &= ~PM_NOT_BACK;
+ switch (mode) {
+ case GL_LINE:
+ hw_mode |= PM_BACK_LINE;
+ break;
+ case GL_POINT:
+ hw_mode &= ~PM_BACK_LINE;
+ break;
+ case GL_FILL: /* No idea */
+ hw_mode = 0;
+ break;
+ }
+ break;
+
+ case GL_FRONT_AND_BACK:
+ //fprintf(stderr, "front and back\n");
+ hw_mode &= ~PM_NOT_FRONT;
+ hw_mode &= ~PM_NOT_BACK;
+ switch (mode) {
+ case GL_LINE:
+ hw_mode |= PM_FRONT_LINE;
+ hw_mode |= PM_BACK_LINE;
+ break;
+ case GL_POINT:
+ hw_mode &= ~PM_FRONT_LINE;
+ hw_mode &= ~PM_BACK_LINE;
+ break;
+ case GL_FILL:
+ hw_mode = 0;
+ break;
+ }
+ break;
+ }
+
+ //if( front and back fill) hw_mode=0;
+
+ if(r300->hw.unk4288.cmd[1] != hw_mode){
+ R300_STATECHANGE(r300, unk4288);
+ r300->hw.unk4288.cmd[1] = hw_mode;
+ }
+}
+
+/* =============================================================
+ * Stencil
+ */
+
+ static int translate_stencil_func(int func)
+ {
+ switch (func) {
+ case GL_NEVER:
+ return R300_ZS_NEVER;
+ break;
+ case GL_LESS:
+ return R300_ZS_LESS;
+ break;
+ case GL_EQUAL:
+ return R300_ZS_EQUAL;
+ break;
+ case GL_LEQUAL:
+ return R300_ZS_LEQUAL;
+ break;
+ case GL_GREATER:
+ return R300_ZS_GREATER;
+ break;
+ case GL_NOTEQUAL:
+ return R300_ZS_NOTEQUAL;
+ break;
+ case GL_GEQUAL:
+ return R300_ZS_GEQUAL;
+ break;
+ case GL_ALWAYS:
+ return R300_ZS_ALWAYS;
+ break;
+ }
+ return 0;
+ }
+
+ static int translate_stencil_op(int op)
+{
+ switch (op) {
+ case GL_KEEP:
+ return R300_ZS_KEEP;
+ case GL_ZERO:
+ return R300_ZS_ZERO;
+ case GL_REPLACE:
+ return R300_ZS_REPLACE;
+ case GL_INCR:
+ return R300_ZS_INCR;
+ case GL_DECR:
+ return R300_ZS_DECR;
+ case GL_INCR_WRAP_EXT:
+ return R300_ZS_INCR_WRAP;
+ case GL_DECR_WRAP_EXT:
+ return R300_ZS_DECR_WRAP;
+ case GL_INVERT:
+ return R300_ZS_INVERT;
+ default:
+ WARN_ONCE("Do not know how to translate stencil op");
+ return R300_ZS_KEEP;
+ }
+}
+
+static void r300StencilFunc(GLcontext * ctx, GLenum func,
+ GLint ref, GLuint mask)
+{
+ r300ContextPtr rmesa = R300_CONTEXT(ctx);
+ GLuint refmask = ((ctx->Stencil.Ref[0] << R300_RB3D_ZS2_STENCIL_REF_SHIFT) |
+ (ctx->Stencil.
+ ValueMask[0] << R300_RB3D_ZS2_STENCIL_MASK_SHIFT));
+ GLuint flag;
+
+ R300_STATECHANGE(rmesa, zs);
+
+ rmesa->hw.zs.cmd[R300_ZS_CNTL_1] &= ~(
+ (R300_ZS_MASK << R300_RB3D_ZS1_FRONT_FUNC_SHIFT)
+ | (R300_ZS_MASK << R300_RB3D_ZS1_BACK_FUNC_SHIFT));
+ rmesa->hw.zs.cmd[R300_ZS_CNTL_2] &= ~((R300_ZS_MASK << R300_RB3D_ZS2_STENCIL_REF_SHIFT) |
+ (R300_ZS_MASK << R300_RB3D_ZS2_STENCIL_MASK_SHIFT));
+
+ flag = translate_stencil_func(ctx->Stencil.Function[0]);
+
+ rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |= (flag << R300_RB3D_ZS1_FRONT_FUNC_SHIFT)
+ | (flag << R300_RB3D_ZS1_BACK_FUNC_SHIFT);
+ rmesa->hw.zs.cmd[R300_ZS_CNTL_2] |= refmask;
+}
+
+static void r300StencilMask(GLcontext * ctx, GLuint mask)
+{
+ r300ContextPtr rmesa = R300_CONTEXT(ctx);
+
+ R300_STATECHANGE(rmesa, zs);
+ rmesa->hw.zs.cmd[R300_ZS_CNTL_2] &= ~(R300_ZS_MASK << R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT);
+ rmesa->hw.zs.cmd[R300_ZS_CNTL_2] |= ctx->Stencil.WriteMask[0] << R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT;
+}
+
+
+static void r300StencilOp(GLcontext * ctx, GLenum fail,
+ GLenum zfail, GLenum zpass)
+{
+ r300ContextPtr rmesa = R300_CONTEXT(ctx);
+
+ R300_STATECHANGE(rmesa, zs);
+ /* It is easier to mask what's left.. */
+ rmesa->hw.zs.cmd[R300_ZS_CNTL_1] &= (R300_ZS_MASK << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT);
+
+ rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |=
+ (translate_stencil_op(ctx->Stencil.FailFunc[0]) << R300_RB3D_ZS1_FRONT_FAIL_OP_SHIFT)
+ |(translate_stencil_op(ctx->Stencil.ZFailFunc[0]) << R300_RB3D_ZS1_FRONT_ZFAIL_OP_SHIFT)
+ |(translate_stencil_op(ctx->Stencil.ZPassFunc[0]) << R300_RB3D_ZS1_FRONT_ZPASS_OP_SHIFT)
+ |(translate_stencil_op(ctx->Stencil.FailFunc[0]) << R300_RB3D_ZS1_BACK_FAIL_OP_SHIFT)
+ |(translate_stencil_op(ctx->Stencil.ZFailFunc[0]) << R300_RB3D_ZS1_BACK_ZFAIL_OP_SHIFT)
+ |(translate_stencil_op(ctx->Stencil.ZPassFunc[0]) << R300_RB3D_ZS1_BACK_ZPASS_OP_SHIFT);
+
+}
+
+static void r300ClearStencil(GLcontext * ctx, GLint s)
+{
+ r300ContextPtr rmesa = R300_CONTEXT(ctx);
+
+ /* Not sure whether this is correct.. */
+ R300_STATECHANGE(rmesa, zs);
+ rmesa->hw.zs.cmd[R300_ZS_CNTL_2] =
+ ((GLuint) ctx->Stencil.Clear |
+ (0xff << R200_STENCIL_MASK_SHIFT) |
+ (ctx->Stencil.WriteMask[0] << R200_STENCIL_WRITEMASK_SHIFT));