No visible changes, but commit the groundwork for further experiments:
authorNicolai Haehnle <prefect_@gmx.net>
Tue, 2 Nov 2004 13:06:45 +0000 (13:06 +0000)
committerNicolai Haehnle <prefect_@gmx.net>
Tue, 2 Nov 2004 13:06:45 +0000 (13:06 +0000)
- Install custom (though inactive) pipeline
- Track depth test and culling state in hardware registers

src/mesa/drivers/dri/r300/Makefile
src/mesa/drivers/dri/r300/r300_cmdbuf.c
src/mesa/drivers/dri/r300/r300_context.c
src/mesa/drivers/dri/r300/r300_context.h
src/mesa/drivers/dri/r300/r300_ioctl.c
src/mesa/drivers/dri/r300/r300_render.c [new file with mode: 0644]
src/mesa/drivers/dri/r300/r300_state.c

index 19e95c2..1306ded 100644 (file)
@@ -30,6 +30,7 @@ DRIVER_SOURCES = \
                 r300_ioctl.c \
                 r300_cmdbuf.c \
                 r300_state.c \
+                r300_render.c \
                 \
                 r200_context.c \
                 r200_ioctl.c \
index 7bf2df5..580c514 100644 (file)
@@ -50,6 +50,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "r300_cmdbuf.h"
 
 
+// Set this to 1 for extremely verbose debugging of command buffers
+#define DEBUG_CMDBUF           0
+
+
 /**
  * Send the current command buffer via ioctl to the hardware.
  */
@@ -69,7 +73,7 @@ int r300FlushCmdBuf(r300ContextPtr r300, const char* caller)
                fprintf(stderr, "%s from %s - %i cliprects\n",
                        __FUNCTION__, caller, r300->radeon.numClipRects);
 
-               if (RADEON_DEBUG & DEBUG_VERBOSE)
+               if (DEBUG_CMDBUF && RADEON_DEBUG & DEBUG_VERBOSE)
                        for (i = start; i < r300->cmdbuf.count_used; ++i)
                                fprintf(stderr, "%d: %08x\n", i,
                                        r300->cmdbuf.cmd_buf[i]);
@@ -140,7 +144,7 @@ static __inline__ void r300DoEmitState(r300ContextPtr r300, GLboolean dirty)
 
        dest = r300->cmdbuf.cmd_buf + r300->cmdbuf.count_used;
 
-       if (RADEON_DEBUG & DEBUG_STATE) {
+       if (DEBUG_CMDBUF && RADEON_DEBUG & DEBUG_STATE) {
                foreach(atom, &r300->hw.atomlist) {
                        if ((atom->dirty || r300->hw.all_dirty) == dirty) {
                                int dwords = (*atom->check)(r300, atom);
@@ -324,8 +328,10 @@ void r300InitCmdBuf(r300ContextPtr r300)
                r300->hw.unk4288.cmd[0] = cmducs(0x4288, 5);
        ALLOC_STATE( unk42A0, always, 2, "unk42A0", 0 );
                r300->hw.unk42A0.cmd[0] = cmducs(0x42A0, 1);
-       ALLOC_STATE( unk42B4, always, 3, "unk42B4", 0 );
-               r300->hw.unk42B4.cmd[0] = cmducs(0x42B4, 2);
+       ALLOC_STATE( unk42B4, always, 2, "unk42B4", 0 );
+               r300->hw.unk42B4.cmd[0] = cmducs(0x42B4, 1);
+       ALLOC_STATE( cul, always, R300_CUL_CMDSIZE, "cul", 0 );
+               r300->hw.cul.cmd[R300_CUL_CMD_0] = cmducs(R300_RE_CULL_CNTL, 1);
        ALLOC_STATE( unk42C0, always, 3, "unk42C0", 0 );
                r300->hw.unk42C0.cmd[0] = cmducs(0x42C0, 2);
        ALLOC_STATE( rc, always, R300_RC_CMDSIZE, "rc", 0 );
@@ -428,6 +434,7 @@ void r300InitCmdBuf(r300ContextPtr r300)
        insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4288);
        insert_at_tail(&r300->hw.atomlist, &r300->hw.unk42A0);
        insert_at_tail(&r300->hw.atomlist, &r300->hw.unk42B4);
+       insert_at_tail(&r300->hw.atomlist, &r300->hw.cul);
        insert_at_tail(&r300->hw.atomlist, &r300->hw.unk42C0);
        insert_at_tail(&r300->hw.atomlist, &r300->hw.rc);
        insert_at_tail(&r300->hw.atomlist, &r300->hw.ri);
index 6e98bd1..9831dc6 100644 (file)
@@ -100,15 +100,13 @@ static const char *const card_extensions[] = {
        NULL
 };
 
-#if 0
-extern const struct tnl_pipeline_stage _r300_render_stage;
-extern const struct tnl_pipeline_stage _r300_tcl_stage;
+extern struct tnl_pipeline_stage _r300_render_stage;
 
 static const struct tnl_pipeline_stage *r300_pipeline[] = {
 
        /* Try and go straight to t&l
         */
-       &_r300_tcl_stage,
+//     &_r300_tcl_stage,
 
        /* Catch any t&l fallbacks
         */
@@ -136,7 +134,7 @@ static const struct tnl_pipeline_stage *r300_pipeline[] = {
        &_tnl_render_stage,     /* FALLBACK  */
        0,
 };
-#endif
+
 
 /* Create the device specific rendering context.
  */
@@ -217,13 +215,10 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual,
        _swsetup_CreateContext(ctx);
        _ae_create_context(ctx);
 
-#if 0
        /* Install the customized pipeline:
         */
        _tnl_destroy_pipeline(ctx);
-       _tnl_install_pipeline(ctx, r200_pipeline);
-       ctx->Driver.FlushVertices = r200FlushVertices;
-#endif
+       _tnl_install_pipeline(ctx, r300_pipeline);
 
        /* Try and keep materials and vertices separate:
         */
@@ -245,7 +240,6 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual,
        /* plug in a few more device driver functions */
        /* XXX these should really go right after _mesa_init_driver_functions() */
        r200InitPixelFuncs(ctx);
-       r200InitTnlFuncs(ctx);
        r200InitSwtcl(ctx);
 #endif
        TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline;
index ada6e4a..d80bcc6 100644 (file)
@@ -126,6 +126,10 @@ struct r300_state_atom {
 #define R300_PS_POINTSIZE      1
 #define R300_PS_CMDSIZE                2
 
+#define R300_CUL_CMD_0         0
+#define R300_CUL_CULL          1
+#define R300_CUL_CMDSIZE       2
+
 #define R300_RC_CMD_0          0
 #define R300_RC_CNTL_0         1
 #define R300_RC_CNTL_1         2
@@ -247,6 +251,7 @@ struct r300_hw_state {
        struct r300_state_atom unk4288; /* (4288) */
        struct r300_state_atom unk42A0; /* (42A0) */
        struct r300_state_atom unk42B4; /* (42B4) */
+       struct r300_state_atom cul;     /* cull cntl (42B8) */
        struct r300_state_atom unk42C0; /* (42C0) */
        struct r300_state_atom rc;      /* rs control (4300) */
        struct r300_state_atom ri;      /* rs interpolators (4310) */
index f6a3d81..63a7d54 100644 (file)
@@ -171,7 +171,7 @@ static void r300ClearBuffer(r300ContextPtr r300, int flags, int buffer)
        R300_STATECHANGE(r300, zc);
        if (flags & CLEARBUFFER_DEPTH) {
                r300->hw.zc.cmd[R300_ZC_CNTL_0] = 0x6; // test and write
-               r300->hw.zc.cmd[R300_ZC_CNTL_1] = R300_RB3D_Z_TEST_ALWAYS;
+               r300->hw.zc.cmd[R300_ZC_CNTL_1] = R300_Z_TEST_ALWAYS;
 /*
                R300_STATECHANGE(r300, zb);
                r300->hw.zb.cmd[R300_ZB_OFFSET] =
diff --git a/src/mesa/drivers/dri/r300/r300_render.c b/src/mesa/drivers/dri/r300/r300_render.c
new file mode 100644 (file)
index 0000000..3f9a63f
--- /dev/null
@@ -0,0 +1,189 @@
+/**************************************************************************
+
+Copyright (C) 2004 Nicolai Haehnle.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Nicolai Haehnle <prefect_@gmx.net>
+ */
+
+#include "glheader.h"
+#include "state.h"
+#include "imports.h"
+#include "enums.h"
+#include "macros.h"
+#include "context.h"
+#include "dd.h"
+#include "simple_list.h"
+
+#include "api_arrayelt.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "array_cache/acache.h"
+#include "tnl/tnl.h"
+
+#include "radeon_ioctl.h"
+#include "radeon_state.h"
+#include "r300_context.h"
+#include "r300_ioctl.h"
+#include "r300_state.h"
+#include "r300_reg.h"
+#include "r300_program.h"
+
+
+/**********************************************************************
+*                     Hardware rasterization
+*
+* When we fell back to software TCL, we still try to use the
+* rasterization hardware for rendering.
+**********************************************************************/
+
+
+/**
+ * Called by the pipeline manager to render a batch of primitives.
+ * We can return true to pass on to the next stage (i.e. software
+ * rasterization) or false to indicate that the pipeline has finished
+ * after we render something.
+ */
+static GLboolean r300_run_render(GLcontext *ctx,
+                                struct tnl_pipeline_stage *stage)
+{
+       if (RADEON_DEBUG == DEBUG_PRIMS)
+               fprintf(stderr, "%s\n", __FUNCTION__);
+
+       return GL_TRUE;
+
+#if 0
+   mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   struct vertex_buffer *VB = &tnl->vb;
+   GLuint i;
+
+   /* Don't handle clipping or indexed vertices or vertex manipulations.
+    */
+   if (mmesa->RenderIndex != 0 ||
+       !mga_validate_render( ctx, VB )) {
+      return GL_TRUE;
+   }
+
+   tnl->Driver.Render.Start( ctx );
+   mmesa->SetupNewInputs = ~0;
+
+   for (i = 0 ; i < VB->PrimitiveCount ; i++)
+   {
+      GLuint prim = VB->Primitive[i].mode;
+      GLuint start = VB->Primitive[i].start;
+      GLuint length = VB->Primitive[i].count;
+
+      if (!length)
+        continue;
+
+      mga_render_tab_verts[prim & PRIM_MODE_MASK]( ctx, start, start + length,
+                                                  prim);
+   }
+
+   tnl->Driver.Render.Finish( ctx );
+
+   return GL_FALSE;            /* finished the pipe */
+#endif
+}
+
+
+/**
+ * Called by the pipeline manager once before rendering.
+ * We check the GL state here to
+ *  a) decide whether we can do the current state in hardware and
+ *  b) update hardware registers
+ */
+#define FALLBACK_IF(expr) \
+do {                                                                           \
+       if (expr) {                                                             \
+               if (RADEON_DEBUG & DEBUG_FALLBACKS)                             \
+                       fprintf(stderr, "%s: fallback:%s\n",                    \
+                               __FUNCTION__, #expr);                           \
+               stage->active = GL_FALSE;                                       \
+               return;                                                         \
+       }                                                                       \
+} while(0)
+
+static void r300_check_render(GLcontext *ctx, struct tnl_pipeline_stage *stage)
+{
+       r300ContextPtr r300 = R300_CONTEXT(ctx);
+       int i;
+
+       if (RADEON_DEBUG & DEBUG_STATE)
+               fprintf(stderr, "%s\n", __FUNCTION__);
+
+       /* We only support rendering in hardware for now */
+       if (ctx->RenderMode != GL_RENDER) {
+               stage->active = GL_FALSE;
+               return;
+       }
+
+       // I failed to figure out how dither works in hardware,
+       // let's just ignore it for now
+       //FALLBACK_IF(ctx->Color.DitherFlag);
+
+       /* I'm almost certain I forgot something here */
+       FALLBACK_IF(ctx->Color.AlphaEnabled); // GL_ALPHA_TEST
+       FALLBACK_IF(ctx->Color.BlendEnabled); // GL_BLEND
+       FALLBACK_IF(ctx->Fog.Enabled); // GL_FOG
+       FALLBACK_IF(ctx->Line.SmoothFlag); // GL_LINE_SMOOTH
+       FALLBACK_IF(ctx->Line.StippleFlag); // GL_LINE_STIPPLE
+       FALLBACK_IF(ctx->Point.SmoothFlag); // GL_POINT_SMOOTH
+       if (ctx->Extensions.NV_point_sprite || ctx->Extensions.ARB_point_sprite)
+               FALLBACK_IF(ctx->Point.PointSprite); // GL_POINT_SPRITE_NV
+       FALLBACK_IF(ctx->Polygon.OffsetPoint); // GL_POLYGON_OFFSET_POINT
+       FALLBACK_IF(ctx->Polygon.OffsetLine); // GL_POLYGON_OFFSET_LINE
+       FALLBACK_IF(ctx->Polygon.OffsetFill); // GL_POLYGON_OFFSET_FILL
+       FALLBACK_IF(ctx->Polygon.SmoothFlag); // GL_POLYGON_SMOOTH
+       FALLBACK_IF(ctx->Polygon.StippleFlag); // GL_POLYGON_STIPPLE
+       FALLBACK_IF(ctx->Stencil.Enabled); // GL_STENCIL_TEST
+       FALLBACK_IF(ctx->Multisample.Enabled); // GL_MULTISAMPLE_ARB
+
+       for (i = 0; i < ctx->Const.MaxTextureUnits; i++)
+               FALLBACK_IF(ctx->Texture.Unit[i].Enabled);
+
+       stage->active = GL_FALSE;
+}
+
+
+static void dtr(struct tnl_pipeline_stage *stage)
+{
+       (void)stage;
+}
+
+const struct tnl_pipeline_stage _r300_render_stage = {
+       "r300 hw rasterize",
+       _NEW_ALL,               /* re-check (always re-check for now) */
+       0,                      /* re-run (always runs) */
+       GL_TRUE,                /* active */
+       0, 0,                   /* inputs (set in check_render), outputs */
+       0, 0,                   /* changed_inputs, private */
+       dtr,                    /* destructor */
+       r300_check_render,      /* check */
+       r300_run_render         /* run */
+};
index df71995..48f0164 100644 (file)
@@ -59,16 +59,66 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 
 /**
+ * Update our tracked culling state based on Mesa's state.
+ */
+static void r300UpdateCulling(GLcontext* ctx)
+{
+       r300ContextPtr r300 = R300_CONTEXT(ctx);
+       uint32_t val = 0;
+
+       R300_STATECHANGE(r300, cul);
+       if (ctx->Polygon.CullFlag) {
+               if (ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK)
+                       val = R300_CULL_FRONT|R300_CULL_BACK;
+               else if (ctx->Polygon.CullFaceMode == GL_FRONT)
+                       val = R300_CULL_FRONT;
+               else
+                       val = R300_CULL_BACK;
+
+               if (ctx->Polygon.FrontFace == GL_CW)
+                       val |= R300_FRONT_FACE_CW;
+               else
+                       val |= R300_FRONT_FACE_CCW;
+       }
+
+       r300->hw.cul.cmd[R300_CUL_CULL] = val;
+}
+
+
+/**
  * Handle glEnable()/glDisable().
+ *
+ * \note Mesa already filters redundant calls to glEnable/glDisable.
  */
 static void r300Enable(GLcontext* ctx, GLenum cap, GLboolean state)
 {
+       r300ContextPtr r300 = R300_CONTEXT(ctx);
+       uint32_t newval;
+
        if (RADEON_DEBUG & DEBUG_STATE)
                fprintf(stderr, "%s( %s = %s )\n", __FUNCTION__,
                        _mesa_lookup_enum_by_nr(cap),
                        state ? "GL_TRUE" : "GL_FALSE");
 
        switch (cap) {
+       case GL_DEPTH_TEST:
+               R300_STATECHANGE(r300, zc);
+
+               if (state) {
+                       if (ctx->Depth.Mask)
+                               newval = R300_RB3D_Z_TEST_AND_WRITE;
+                       else
+                               newval = R300_RB3D_Z_TEST;
+               } else
+                       newval = 0;
+
+               r300->hw.zc.cmd[R300_ZC_CNTL_0] = newval;
+               break;
+
+       case GL_CULL_FACE:
+               r300UpdateCulling(ctx);
+               break;
+
        default:
                radeonEnable(ctx, cap, state);
                return;
@@ -77,6 +127,90 @@ static void r300Enable(GLcontext* ctx, GLenum cap, GLboolean state)
 
 
 /**
+ * Change the culling mode.
+ *
+ * \note Mesa already filters redundant calls to this function.
+ */
+static void r300CullFace(GLcontext* ctx, GLenum mode)
+{
+       (void)mode;
+
+       r300UpdateCulling(ctx);
+}
+
+
+/**
+ * Change the polygon orientation.
+ *
+ * \note Mesa already filters redundant calls to this function.
+ */
+static void r300FrontFace(GLcontext* ctx, GLenum mode)
+{
+       (void)mode;
+
+       r300UpdateCulling(ctx);
+}
+
+
+/**
+ * Change the depth testing function.
+ *
+ * \note Mesa already filters redundant calls to this function.
+ */
+static void r300DepthFunc(GLcontext* ctx, GLenum func)
+{
+       r300ContextPtr r300 = R300_CONTEXT(ctx);
+
+       R300_STATECHANGE(r300, zc);
+
+       switch(func) {
+       case GL_NEVER:
+               r300->hw.zc.cmd[R300_ZC_CNTL_1] = R300_Z_TEST_NEVER;
+               break;
+       case GL_LESS:
+               r300->hw.zc.cmd[R300_ZC_CNTL_1] = R300_Z_TEST_LESS;
+               break;
+       case GL_EQUAL:
+               r300->hw.zc.cmd[R300_ZC_CNTL_1] = R300_Z_TEST_EQUAL;
+               break;
+       case GL_LEQUAL:
+               r300->hw.zc.cmd[R300_ZC_CNTL_1] = R300_Z_TEST_LEQUAL;
+               break;
+       case GL_GREATER:
+               r300->hw.zc.cmd[R300_ZC_CNTL_1] = R300_Z_TEST_GREATER;
+               break;
+       case GL_NOTEQUAL:
+               r300->hw.zc.cmd[R300_ZC_CNTL_1] = R300_Z_TEST_NEQUAL;
+               break;
+       case GL_GEQUAL:
+               r300->hw.zc.cmd[R300_ZC_CNTL_1] = R300_Z_TEST_GEQUAL;
+               break;
+       case GL_ALWAYS:
+               r300->hw.zc.cmd[R300_ZC_CNTL_1] = R300_Z_TEST_ALWAYS;
+               break;
+       }
+}
+
+
+/**
+ * Enable/Disable depth writing.
+ *
+ * \note Mesa already filters redundant calls to this function.
+ */
+static void r300DepthMask(GLcontext* ctx, GLboolean mask)
+{
+       r300ContextPtr r300 = R300_CONTEXT(ctx);
+
+       if (!ctx->Depth.Test)
+               return;
+
+       R300_STATECHANGE(r300, zc);
+       r300->hw.zc.cmd[R300_ZC_CNTL_0] = mask
+               ? R300_RB3D_Z_TEST_AND_WRITE : R300_RB3D_Z_TEST;
+}
+
+
+/**
  * Handle glColorMask()
  */
 static void r300ColorMask(GLcontext* ctx,
@@ -141,11 +275,17 @@ void r300ResetHwState(r300ContextPtr r300)
                        r300PackFloat32(v[MAT_TZ]);
        }
 
-       r300->hw.cmk.cmd[R300_CMK_COLORMASK] =
-               (ctx->Color.ColorMask[BCOMP] ? R300_COLORMASK0_B : 0) |
-               (ctx->Color.ColorMask[GCOMP] ? R300_COLORMASK0_G : 0) |
-               (ctx->Color.ColorMask[RCOMP] ? R300_COLORMASK0_R : 0) |
-               (ctx->Color.ColorMask[ACOMP] ? R300_COLORMASK0_A : 0);
+       r300ColorMask(ctx,
+               ctx->Color.ColorMask[RCOMP],
+               ctx->Color.ColorMask[GCOMP],
+               ctx->Color.ColorMask[BCOMP],
+               ctx->Color.ColorMask[ACOMP]);
+
+       r300Enable(ctx, GL_DEPTH_TEST, ctx->Depth.Test);
+       r300DepthMask(ctx, ctx->Depth.Mask);
+       r300DepthFunc(ctx, ctx->Depth.Func);
+
+       r300UpdateCulling(ctx);
 
 //BEGIN: TODO
        r300->hw.unk2080.cmd[1] = 0x0030045A;
@@ -233,7 +373,6 @@ void r300ResetHwState(r300ContextPtr r300)
        r300->hw.unk42A0.cmd[1] = 0x00000000;
 
        r300->hw.unk42B4.cmd[1] = 0x00000000;
-       r300->hw.unk42B4.cmd[2] = 0x00000000;
 
        r300->hw.unk42C0.cmd[1] = 0x4B7FFFFF;
        r300->hw.unk42C0.cmd[2] = 0x00000000;
@@ -312,9 +451,6 @@ void r300ResetHwState(r300ContextPtr r300)
 
        r300->hw.unk4E88.cmd[1] = 0;
 
-       r300->hw.zc.cmd[R300_ZC_CNTL_0] = 0;
-       r300->hw.zc.cmd[R300_ZC_CNTL_1] = 0;
-
        r300->hw.unk4F08.cmd[1] = 0x00FFFF00;
 
        r300->hw.unk4F10.cmd[1] = 0x00000002; // depthbuffer format?
@@ -383,5 +519,9 @@ void r300InitStateFuncs(struct dd_function_table* functions)
        functions->UpdateState = r300InvalidateState;
        functions->Enable = r300Enable;
        functions->ColorMask = r300ColorMask;
+       functions->DepthFunc = r300DepthFunc;
+       functions->DepthMask = r300DepthMask;
+       functions->CullFace = r300CullFace;
+       functions->FrontFace = r300FrontFace;
 }