radeon/r600: use new libdrm_radeon api
[mesa.git] / src / mesa / drivers / dri / r300 / r300_vertprog.c
index c5edbd0052b51e2790cd603c98c16f7bc1f7f18b..ed8b7881081863f6bdd98f1117497e59d0e213ae 100644 (file)
@@ -43,6 +43,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "compiler/radeon_compiler.h"
 #include "compiler/radeon_nqssadce.h"
 #include "r300_context.h"
+#include "r300_fragprog_common.h"
 #include "r300_state.h"
 
 /**
@@ -61,12 +62,6 @@ static int r300VertexProgUpdateParams(GLcontext * ctx, struct r300_vertex_progra
                }
        }
 
-       if (vp->code.constants.Count * 4 > VSF_MAX_FRAGMENT_LENGTH) {
-               /* Should have checked this earlier... */
-               fprintf(stderr, "%s:Params exhausted\n", __FUNCTION__);
-               _mesa_exit(-1);
-       }
-
        for(i = 0; i < vp->code.constants.Count; ++i) {
                const float * src = 0;
                const struct rc_constant * constant = &vp->code.constants.Constants[i];
@@ -203,6 +198,34 @@ static void t_inputs_outputs(struct r300_vertex_program_compiler * c)
        }
 }
 
+/**
+ * The NV_vertex_program spec mandates that all registers be
+ * initialized to zero. We do this here unconditionally.
+ *
+ * \note We rely on dead-code elimination in the compiler.
+ */
+static void initialize_NV_registers(struct radeon_compiler * compiler)
+{
+       unsigned int reg;
+       struct rc_instruction * inst;
+
+       for(reg = 0; reg < 12; ++reg) {
+               inst = rc_insert_new_instruction(compiler, &compiler->Program.Instructions);
+               inst->I.Opcode = OPCODE_MOV;
+               inst->I.DstReg.File = PROGRAM_TEMPORARY;
+               inst->I.DstReg.Index = reg;
+               inst->I.SrcReg[0].File = PROGRAM_BUILTIN;
+               inst->I.SrcReg[0].Swizzle = SWIZZLE_0000;
+       }
+
+       inst = rc_insert_new_instruction(compiler, &compiler->Program.Instructions);
+       inst->I.Opcode = OPCODE_ARL;
+       inst->I.DstReg.File = PROGRAM_ADDRESS;
+       inst->I.DstReg.Index = 0;
+       inst->I.DstReg.WriteMask = WRITEMASK_X;
+       inst->I.SrcReg[0].File = PROGRAM_BUILTIN;
+       inst->I.SrcReg[0].Swizzle = SWIZZLE_0000;
+}
 
 static struct r300_vertex_program *build_program(GLcontext *ctx,
                                                 struct r300_vertex_program_key *wanted_key,
@@ -216,7 +239,7 @@ static struct r300_vertex_program *build_program(GLcontext *ctx,
        _mesa_memcpy(&vp->key, wanted_key, sizeof(vp->key));
 
        rc_init(&compiler.Base);
-       compiler.Base.Debug = (RADEON_DEBUG & DEBUG_VERTS) ? GL_TRUE : GL_FALSE;
+       compiler.Base.Debug = (RADEON_DEBUG & RADEON_VERTS) ? GL_TRUE : GL_FALSE;
 
        compiler.code = &vp->code;
        compiler.RequiredOutputs = compute_required_outputs(vp->Base, vp->key.FpReads);
@@ -225,7 +248,7 @@ static struct r300_vertex_program *build_program(GLcontext *ctx,
        if (compiler.Base.Debug) {
                fprintf(stderr, "Initial vertex program:\n");
                _mesa_print_program(&vp->Base->Base);
-               fflush(stdout);
+               fflush(stderr);
        }
 
        if (mesa_vp->IsPositionInvariant) {
@@ -234,6 +257,9 @@ static struct r300_vertex_program *build_program(GLcontext *ctx,
 
        rc_mesa_to_rc_program(&compiler.Base, &vp->Base->Base);
 
+       if (mesa_vp->IsNVProgram)
+               initialize_NV_registers(&compiler.Base);
+
        rc_move_output(&compiler.Base, VERT_RESULT_PSIZ, VERT_RESULT_PSIZ, WRITEMASK_X);
 
        if (vp->key.WPosAttr != FRAG_ATTRIB_MAX) {
@@ -249,6 +275,11 @@ static struct r300_vertex_program *build_program(GLcontext *ctx,
        }
 
        r3xx_compile_vertex_program(&compiler);
+
+       if (vp->code.constants.Count > ctx->Const.VertexProgram.MaxParameters) {
+               rc_error(&compiler.Base, "Program exceeds constant buffer size limit\n");
+       }
+
        vp->error = compiler.Base.Error;
 
        vp->Base->Base.InputsRead = vp->code.InputsRead;
@@ -267,6 +298,20 @@ struct r300_vertex_program * r300SelectAndTranslateVertexShader(GLcontext *ctx)
        struct r300_vertex_program *vp;
 
        vpc = (struct r300_vertex_program_cont *)ctx->VertexProgram._Current;
+
+       if (!r300->selected_fp) {
+               /* This can happen when GetProgramiv is called to check
+                * whether the program runs natively.
+                *
+                * To be honest, this is not a very good solution,
+                * but solving the problem of reporting good values
+                * for those queries is tough anyway considering that
+                * we recompile vertex programs based on the precise
+                * fragment program that is in use.
+                */
+               r300SelectAndTranslateFragmentShader(ctx);
+       }
+
        wanted_key.FpReads = r300->selected_fp->InputsRead;
        wanted_key.FogAttr = r300->selected_fp->fog_attr;
        wanted_key.WPosAttr = r300->selected_fp->wpos_attr;
@@ -288,7 +333,6 @@ struct r300_vertex_program * r300SelectAndTranslateVertexShader(GLcontext *ctx)
 #define bump_vpu_count(ptr, new_count)   do { \
                drm_r300_cmd_header_t* _p=((drm_r300_cmd_header_t*)(ptr)); \
                int _nc=(new_count)/4; \
-               assert(_nc < 256); \
                if(_nc>_p->vpu.count)_p->vpu.count=_nc; \
        } while(0)
 
@@ -298,6 +342,8 @@ static void r300EmitVertexProgram(r300ContextPtr r300, int dest, struct r300_ver
 
        assert((code->length > 0) && (code->length % 4 == 0));
 
+       R300_STATECHANGE( r300, vap_flush );
+
        switch ((dest >> 8) & 0xf) {
                case 0:
                        R300_STATECHANGE(r300, vpi);
@@ -335,6 +381,7 @@ void r300SetupVertexProgram(r300ContextPtr rmesa)
        ((drm_r300_cmd_header_t *) rmesa->hw.vpi.cmd)->vpu.count = 0;
        ((drm_r300_cmd_header_t *) rmesa->hw.vps.cmd)->vpu.count = 0;
 
+       R300_STATECHANGE(rmesa, vap_flush);
        R300_STATECHANGE(rmesa, vpp);
        param_count = r300VertexProgUpdateParams(ctx, prog, (float *)&rmesa->hw.vpp.cmd[R300_VPP_PARAM_0]);
        bump_vpu_count(rmesa->hw.vpp.cmd, param_count);