nouveau: NV40 glClipPlane support.
authorBen Skeggs <darktama@iinet.net.au>
Tue, 30 Jan 2007 05:00:20 +0000 (16:00 +1100)
committerBen Skeggs <darktama@iinet.net.au>
Tue, 30 Jan 2007 05:41:55 +0000 (16:41 +1100)
src/mesa/drivers/dri/nouveau/nouveau_shader.h
src/mesa/drivers/dri/nouveau/nouveau_shader_0.c
src/mesa/drivers/dri/nouveau/nv30_state.c
src/mesa/drivers/dri/nouveau/nv30_vertprog.c
src/mesa/drivers/dri/nouveau/nv40_vertprog.c

index 68007dd..b2df354 100644 (file)
@@ -32,6 +32,7 @@ typedef union {
        struct {
                uint32_t vp_in_reg;
                uint32_t vp_out_reg;
+               uint32_t clip_enables;
        } NV30VP;
 } nvsCardPriv;
 
index fb6e0b0..73c1f7c 100644 (file)
@@ -811,12 +811,65 @@ pass0_build_attrib_map(nouveauShader *nvs, struct gl_vertex_program *vp)
 }
 
 static void
-pass0_prealloc_mesa_consts(nouveauShader *nvs)
+pass0_vp_insert_ff_clip_planes(GLcontext *ctx, nouveauShader *nvs)
+{
+       struct gl_program *prog = &nvs->mesa.vp.Base;
+       nvsFragmentHeader *parent = nvs->program_tree;
+       nvsInstruction *nvsinst;
+       GLuint fpos = 0;
+       nvsRegister opos, epos, eqn, mv[4];
+       GLint tokens[6] = { STATE_MATRIX, STATE_MODELVIEW, 0, 0, 0, 0 };
+       GLint id;
+       int i;
+
+       /* modelview transform */
+       pass0_make_reg(nvs, &opos, NVS_FILE_ATTRIB, NVS_FR_POSITION);
+       pass0_make_reg(nvs, &epos, NVS_FILE_TEMP  , -1);
+       for (i=0; i<4; i++) {
+               tokens[3] = tokens[4] = i;
+               id = _mesa_add_state_reference(prog->Parameters, tokens);
+               pass0_make_reg(nvs, &mv[i], NVS_FILE_CONST, id);
+       }
+       ARITHu(NVS_OP_DP4, epos, SMASK_X, 0, opos, mv[0], nvr_unused);
+       ARITHu(NVS_OP_DP4, epos, SMASK_Y, 0, opos, mv[1], nvr_unused);
+       ARITHu(NVS_OP_DP4, epos, SMASK_Z, 0, opos, mv[2], nvr_unused);
+       ARITHu(NVS_OP_DP4, epos, SMASK_W, 0, opos, mv[3], nvr_unused);
+
+       /* Emit code to emulate fixed-function glClipPlane */
+       for (i=0; i<6; i++) {
+               GLuint clipmask = SMASK_X;
+               nvsRegister clip;
+
+               if (!(ctx->Transform.ClipPlanesEnabled & (1<<i)))
+                       continue;
+
+               /* Point a const at a user clipping plane */
+               tokens[0] = STATE_CLIPPLANE;
+               tokens[1] = i;
+               id = _mesa_add_state_reference(prog->Parameters, tokens);
+               pass0_make_reg(nvs, &eqn , NVS_FILE_CONST , id);
+               pass0_make_reg(nvs, &clip, NVS_FILE_RESULT, NVS_FR_CLIP0 + i);
+
+               /*XXX: something else needs to take care of modifying the
+                *     instructions to write to the correct hw clip register.
+                */
+               switch (i) {
+               case 0: case 3: clipmask = SMASK_Y; break;
+               case 1: case 4: clipmask = SMASK_Z; break;
+               case 2: case 5: clipmask = SMASK_W; break;
+               }
+
+               /* Emit transform */
+               ARITHu(NVS_OP_DP4, clip, clipmask, 0, epos, eqn, nvr_unused);
+       }
+}
+
+static void
+pass0_rebase_mesa_consts(nouveauShader *nvs)
 {
        struct pass0_rec *rec = nvs->pass_rec;
        struct gl_program *prog = &nvs->mesa.vp.Base;
        struct prog_instruction *inst = prog->Instructions;
-       struct gl_program_parameter_list *plist = prog->Parameters;
        int i;
 
        /*XXX: not a good idea, params->hw_index is malloc'd */
@@ -848,10 +901,23 @@ pass0_prealloc_mesa_consts(nouveauShader *nvs)
 
                inst++;
        }
-       
+}
+
+static void
+pass0_resolve_mesa_consts(nouveauShader *nvs)
+{
+       struct pass0_rec *rec = nvs->pass_rec;
+       struct gl_program *prog = &nvs->mesa.vp.Base;
+       struct gl_program_parameter_list *plist = prog->Parameters;
+       int i;
+
        /* Init all const tracking/alloc info from the parameter list, rather
-        * than doing it as we translate the program.  Otherwise we can't get
-        * at the correct constant info when relative addressing is being used.
+        * than doing it as we translate the program.  Otherwise:
+        *   1) we can't get at the correct constant info when relative
+        *      addressing is being used due to src->Index not pointing
+        *      at the exact const;
+        *   2) as we add extra consts to the program, mesa will call realloc()
+        *      and we get invalid pointers to the const data.
         */
        rec->mesa_const_last = plist->NumParameters + rec->mesa_const_base;
        nvs->param_high = rec->mesa_const_last;
@@ -907,12 +973,10 @@ nouveau_shader_pass0(GLcontext *ctx, nouveauShader *nvs)
 
                if (vp->IsPositionInvariant)
                        _mesa_insert_mvp_code(ctx, vp);
-               pass0_prealloc_mesa_consts(nvs);
+               pass0_rebase_mesa_consts(nvs);
 
-#if 0
-               if (IS_FIXEDFUNCTION_PROG && CLIP_PLANES_USED)
-                       pass0_insert_ff_clip_planes();
-#endif
+               if (!prog->String && ctx->Transform.ClipPlanesEnabled)
+                       pass0_vp_insert_ff_clip_planes(ctx, nvs);
 
                pass0_build_attrib_map(nvs, vp);
                break;
@@ -921,7 +985,7 @@ nouveau_shader_pass0(GLcontext *ctx, nouveauShader *nvs)
 
                if (fp->FogOption != GL_NONE)
                        _mesa_append_fog_code(ctx, fp);
-               pass0_prealloc_mesa_consts(nvs);
+               pass0_rebase_mesa_consts(nvs);
                break;
        default:
                fprintf(stderr, "Unknown program type %d", prog->Target);
@@ -932,6 +996,8 @@ nouveau_shader_pass0(GLcontext *ctx, nouveauShader *nvs)
        nvs->func->card_priv = &nvs->card_priv;
 
        ret = pass0_translate_instructions(nvs, 0, 0, nvs->program_tree);
+       if (ret)
+               pass0_resolve_mesa_consts(nvs);
        /*XXX: if (!ret) DESTROY TREE!!! */
 
        FREE(rec);
index 55b6463..db13ec7 100644 (file)
@@ -127,6 +127,11 @@ static void nv30ClearStencil(GLcontext *ctx, GLint s)
 static void nv30ClipPlane(GLcontext *ctx, GLenum plane, const GLfloat *equation)
 {
        nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+       if (NOUVEAU_CARD_USING_SHADERS)
+               return;
+
+       plane -= GL_CLIP_PLANE0;
        BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CLIP_PLANE_A(plane), 4);
        OUT_RING_CACHEf(equation[0]);
        OUT_RING_CACHEf(equation[1]);
@@ -208,8 +213,14 @@ static void nv30Enable(GLcontext *ctx, GLenum cap, GLboolean state)
                case GL_CLIP_PLANE3:
                case GL_CLIP_PLANE4:
                case GL_CLIP_PLANE5:
-                       BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CLIP_PLANE_ENABLE(cap-GL_CLIP_PLANE0), 1);
-                       OUT_RING_CACHE(state);
+                       if (NOUVEAU_CARD_USING_SHADERS) {
+                               nouveauShader *nvs = (nouveauShader *)ctx->VertexProgram._Current;
+                               if (nvs)
+                                       nvs->translated = GL_FALSE;
+                       } else {
+                               BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CLIP_PLANE_ENABLE(cap-GL_CLIP_PLANE0), 1);
+                               OUT_RING_CACHE(state);
+                       }
                        break;
                case GL_COLOR_LOGIC_OP:
                        BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_ENABLE, 1);
index afcacf3..d023e84 100644 (file)
@@ -33,6 +33,9 @@ NV30VPUploadToHW(GLcontext *ctx, nouveauShader *nvs)
    BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VP_IN_REG, 2);
    OUT_RING(nvs->card_priv.NV30VP.vp_in_reg);
    OUT_RING(nvs->card_priv.NV30VP.vp_out_reg);
+
+   BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_CLIPPING_PLANES, 1);
+   OUT_RING_CACHE  (nvs->card_priv.NV30VP.clip_enables);
 }
 
 static void
index 6cb7e1c..d054140 100644 (file)
@@ -86,6 +86,7 @@ NV40VPTranslateResultReg(nvsFunc *shader, nvsFixedReg result,
                                          unsigned int *mask_ret)
 {
        unsigned int *out_reg = &shader->card_priv->NV30VP.vp_out_reg;
+       unsigned int *clip_en = &shader->card_priv->NV30VP.clip_enables;
 
        *mask_ret = 0xf;
 
@@ -111,14 +112,17 @@ NV40VPTranslateResultReg(nvsFunc *shader, nvsFixedReg result,
                return NV40_VP_INST_DEST_FOGC;
        case NVS_FR_CLIP0:
                (*out_reg) |= NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_CLP0;
+               (*clip_en) |= 0x00000002;
                *mask_ret = 0x4;
                return NV40_VP_INST_DEST_FOGC;
        case NVS_FR_CLIP1:
                (*out_reg) |= NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_CLP1;
+               (*clip_en) |= 0x00000020;
                *mask_ret = 0x2;
                return NV40_VP_INST_DEST_FOGC;
        case NVS_FR_CLIP2:
                (*out_reg) |= NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_CLP2;
+               (*clip_en) |= 0x00000200;
                *mask_ret = 0x1;
                return NV40_VP_INST_DEST_FOGC;
        case NVS_FR_POINTSZ:
@@ -127,13 +131,16 @@ NV40VPTranslateResultReg(nvsFunc *shader, nvsFixedReg result,
                return NV40_VP_INST_DEST_PSZ;
        case NVS_FR_CLIP3:
                (*out_reg) |= NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_CLP3;
+               (*clip_en) |= 0x00002000;
                *mask_ret = 0x4;
                return NV40_VP_INST_DEST_PSZ;
        case NVS_FR_CLIP4:
+               (*clip_en) |= 0x00020000;
                (*out_reg) |= NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_CLP4;
                *mask_ret = 0x2;
                return NV40_VP_INST_DEST_PSZ;
        case NVS_FR_CLIP5:
+               (*clip_en) |= 0x00200000;
                (*out_reg) |= NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_CLP5;
                *mask_ret = 0x1;
                return NV40_VP_INST_DEST_PSZ;