r300: Writing to result.depth in fragment programs (R3xx; only stub for R5xx)
authorNicolai Haehnle <nhaehnle@gmail.com>
Sun, 1 Jun 2008 17:53:52 +0000 (19:53 +0200)
committerNicolai Haehnle <nhaehnle@gmail.com>
Sun, 1 Jun 2008 17:59:42 +0000 (19:59 +0200)
Setup fg_depth_src for depth writing programs and change early Z (ztop)
semantics.

Piglit's version of glean/fragprog test passes now (unlike Glean, its
dependency on EXT_fog_coord, which we don't support, is optional).

R3xx only at the moment, but should be straightforward to adapt to R5xx
(I don't own an R5xx, and I don't want to break anything.)

src/mesa/drivers/dri/r300/r300_context.h
src/mesa/drivers/dri/r300/r300_fragprog.c
src/mesa/drivers/dri/r300/r300_state.c

index 53e5d181a4c04fdd19ee96df271937f353bb14d7..817f783dffbfae8b3e49e6928467aa8f19e4593b 100644 (file)
@@ -794,6 +794,7 @@ struct r300_fragment_program {
 
        int max_temp_idx;
 
+       GLboolean WritesDepth;
        GLuint optimization;
 };
 
@@ -869,7 +870,7 @@ struct r300_state {
  */
 struct r300_swtcl_info {
    GLuint RenderIndex;
-   
+
    /**
     * Size of a hardware vertex.  This is calculated when \c ::vertex_attrs is
     * installed in the Mesa state vector.
index ac45da440494150189d18fd688c1e749e7461ae1..54b80d20a1661fbc9f1d5c2afebf34c6ce709d6f 100644 (file)
@@ -862,6 +862,7 @@ static int t_hw_dst(struct r300_fragment_program *fp,
                            R300_RGBA_OUT;
                        break;
                case FRAG_RESULT_DEPR:
+                       fp->WritesDepth = GL_TRUE;
                        fp->node[fp->cur_node].flags |=
                            R300_W_OUT;
                        break;
@@ -2105,6 +2106,7 @@ static void init_program(r300ContextPtr r300, struct r300_fragment_program *fp)
        fp->translated = GL_FALSE;
        fp->error = GL_FALSE;
        fp->cs = cs = &(R300_CONTEXT(fp->ctx)->state.pfs_compile);
+       fp->WritesDepth = GL_FALSE;
        fp->tex.length = 0;
        fp->cur_node = 0;
        fp->first_node_has_tex = 0;
index df4573d6b2200928fc5f4c37a391c5076741863e..f0a5176949d80d4fd164ba426b5cac7b9310113c 100644 (file)
@@ -402,42 +402,37 @@ static void r300SetPolygonOffsetState(GLcontext * ctx, GLboolean state)
        }
 }
 
-static void r300SetEarlyZState(GLcontext * ctx)
+static GLboolean current_fragment_program_writes_depth(GLcontext* ctx)
 {
-       /* updates register R300_RB3D_EARLY_Z (0x4F14)
-          if depth test is not enabled it should be R300_EARLY_Z_DISABLE
-          if depth is enabled and alpha not it should be R300_EARLY_Z_ENABLE
-          if depth and alpha is enabled it should be R300_EARLY_Z_DISABLE
-        */
        r300ContextPtr r300 = R300_CONTEXT(ctx);
 
-       R300_STATECHANGE(r300, zstencil_format);
-       switch (ctx->Visual.depthBits) {
-       case 16:
-               r300->hw.zstencil_format.cmd[1] = R300_DEPTHFORMAT_16BIT_INT_Z;
-               break;
-       case 24:
-               r300->hw.zstencil_format.cmd[1] = R300_DEPTHFORMAT_24BIT_INT_Z_8BIT_STENCIL;
-               break;
-       default:
-               fprintf(stderr, "Error: Unsupported depth %d... exiting\n", ctx->Visual.depthBits);
-               _mesa_exit(-1);
+       if (r300->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV515) {
+               struct r300_fragment_program *fp = (struct r300_fragment_program *)
+                       (char *)ctx->FragmentProgram._Current;
+               return (fp && fp->WritesDepth);
+       } else {
+               return GL_FALSE; /* TODO: Verify depth writing works on R5xx */
        }
+}
+
+static void r300SetEarlyZState(GLcontext * ctx)
+{
+       r300ContextPtr r300 = R300_CONTEXT(ctx);
+       GLuint topZ = R300_ZTOP_ENABLE;
 
        if (ctx->Color.AlphaEnabled && ctx->Color.AlphaFunc != GL_ALWAYS)
-               /* disable early Z */
-               r300->hw.zstencil_format.cmd[2] = R300_ZTOP_DISABLE;
-       else {
-               if (ctx->Depth.Test && ctx->Depth.Func != GL_NEVER)
-                       /* enable early Z */
-                       r300->hw.zstencil_format.cmd[2] = R300_ZTOP_ENABLE;
-               else
-                       /* disable early Z */
-                       r300->hw.zstencil_format.cmd[2] = R300_ZTOP_DISABLE;
+               topZ = R300_ZTOP_DISABLE;
+       if (current_fragment_program_writes_depth(ctx))
+               topZ = R300_ZTOP_DISABLE;
+
+       if (topZ != r300->hw.zstencil_format.cmd[2]) {
+               /* Note: This completely reemits the stencil format.
+                * I have not tested whether this is strictly necessary,
+                * or if emitting a write to ZB_ZTOP is enough.
+                */
+               R300_STATECHANGE(r300, zstencil_format);
+               r300->hw.zstencil_format.cmd[2] = topZ;
        }
-
-       r300->hw.zstencil_format.cmd[3] = 0x00000003;
-       r300->hw.zstencil_format.cmd[4] = 0x00000000;
 }
 
 static void r300SetAlphaState(GLcontext * ctx)
@@ -2346,6 +2341,23 @@ static void r300ResetHwState(r300ContextPtr r300)
 
        r300->hw.zb_depthclearvalue.cmd[1] = 0;
 
+       switch (ctx->Visual.depthBits) {
+       case 16:
+               r300->hw.zstencil_format.cmd[1] = R300_DEPTHFORMAT_16BIT_INT_Z;
+               break;
+       case 24:
+               r300->hw.zstencil_format.cmd[1] = R300_DEPTHFORMAT_24BIT_INT_Z_8BIT_STENCIL;
+               break;
+       default:
+               fprintf(stderr, "Error: Unsupported depth %d... exiting\n", ctx->Visual.depthBits);
+               _mesa_exit(-1);
+       }
+
+       r300->hw.zstencil_format.cmd[2] = R300_ZTOP_DISABLE;
+       r300->hw.zstencil_format.cmd[3] = 0x00000003;
+       r300->hw.zstencil_format.cmd[4] = 0x00000000;
+       r300SetEarlyZState(ctx);
+
        r300->hw.unk4F30.cmd[1] = 0;
        r300->hw.unk4F30.cmd[2] = 0;
 
@@ -2559,6 +2571,15 @@ void r300UpdateShaderStates(r300ContextPtr rmesa)
        ctx = rmesa->radeon.glCtx;
 
        r300UpdateTextureState(ctx);
+       r300SetEarlyZState(ctx);
+
+       GLuint fgdepthsrc = R300_FG_DEPTH_SRC_SCAN;
+       if (current_fragment_program_writes_depth(ctx))
+               fgdepthsrc = R300_FG_DEPTH_SRC_SHADER;
+       if (fgdepthsrc != rmesa->hw.fg_depth_src.cmd[1]) {
+               R300_STATECHANGE(rmesa, fg_depth_src);
+               rmesa->hw.fg_depth_src.cmd[1] = fgdepthsrc;
+       }
 
        if (rmesa->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515)
                r500SetupPixelShader(rmesa);