i965/vs: Fix NULL pointer dereference in pre-Gen6 push constant loading.
[mesa.git] / src / mesa / drivers / dri / r300 / r300_vertprog.c
index 129004fee7850d97d0cea5572a9e6de699ee3699..1daa305e3c4657e72f0097a0d852255c9718fcae 100644 (file)
@@ -31,12 +31,12 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "main/glheader.h"
 #include "main/macros.h"
 #include "main/enums.h"
-#include "shader/program.h"
-#include "shader/programopt.h"
-#include "shader/prog_instruction.h"
-#include "shader/prog_parameter.h"
-#include "shader/prog_print.h"
-#include "shader/prog_statevars.h"
+#include "program/program.h"
+#include "program/programopt.h"
+#include "program/prog_instruction.h"
+#include "program/prog_parameter.h"
+#include "program/prog_print.h"
+#include "program/prog_statevars.h"
 #include "tnl/tnl.h"
 
 #include "compiler/radeon_compiler.h"
@@ -49,7 +49,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
  * Write parameter array for the given vertex program into dst.
  * Return the total number of components written.
  */
-static int r300VertexProgUpdateParams(GLcontext * ctx, struct r300_vertex_program *vp, float *dst)
+static int r300VertexProgUpdateParams(struct gl_context * ctx, struct r300_vertex_program *vp, float *dst)
 {
        int i;
 
@@ -227,7 +227,7 @@ static void initialize_NV_registers(struct radeon_compiler * compiler)
        inst->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_0000;
 }
 
-static struct r300_vertex_program *build_program(GLcontext *ctx,
+static struct r300_vertex_program *build_program(struct gl_context *ctx,
                                                 struct r300_vertex_program_key *wanted_key,
                                                 const struct gl_vertex_program *mesa_vp)
 {
@@ -238,12 +238,19 @@ static struct r300_vertex_program *build_program(GLcontext *ctx,
        vp->Base = _mesa_clone_vertex_program(ctx, mesa_vp);
        memcpy(&vp->key, wanted_key, sizeof(vp->key));
 
+        memset(&compiler, 0, sizeof(compiler));
        rc_init(&compiler.Base);
        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);
        compiler.SetHwInputOutput = &t_inputs_outputs;
+       compiler.Base.is_r500 = R300_CONTEXT(ctx)->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515;
+       compiler.Base.disable_optimizations = 0;
+       compiler.Base.has_half_swizzles = 0;
+       compiler.Base.max_temp_regs = 32;
+       compiler.Base.max_constants = 256;
+       compiler.Base.max_alu_insts = compiler.Base.is_r500 ? 1024 : 256;
 
        if (compiler.Base.Debug) {
                fprintf(stderr, "Initial vertex program:\n");
@@ -263,15 +270,25 @@ static struct r300_vertex_program *build_program(GLcontext *ctx,
        rc_move_output(&compiler.Base, VERT_RESULT_PSIZ, VERT_RESULT_PSIZ, WRITEMASK_X);
 
        if (vp->key.WPosAttr != FRAG_ATTRIB_MAX) {
-               rc_copy_output(&compiler.Base,
-                       VERT_RESULT_HPOS,
-                       vp->key.WPosAttr - FRAG_ATTRIB_TEX0 + VERT_RESULT_TEX0);
+               unsigned int vp_wpos_attr = vp->key.WPosAttr - FRAG_ATTRIB_TEX0 + VERT_RESULT_TEX0;
+
+               /* Set empty writemask for instructions writing to vp_wpos_attr
+                * before moving the wpos attr there.
+                * Such instructions will be removed by DCE.
+                */
+               rc_move_output(&compiler.Base, vp_wpos_attr, vp->key.WPosAttr, 0);
+               rc_copy_output(&compiler.Base, VERT_RESULT_HPOS, vp_wpos_attr);
        }
 
        if (vp->key.FogAttr != FRAG_ATTRIB_MAX) {
-               rc_move_output(&compiler.Base,
-                       VERT_RESULT_FOGC,
-                       vp->key.FogAttr - FRAG_ATTRIB_TEX0 + VERT_RESULT_TEX0, WRITEMASK_X);
+               unsigned int vp_fog_attr = vp->key.FogAttr - FRAG_ATTRIB_TEX0 + VERT_RESULT_TEX0;
+
+               /* Set empty writemask for instructions writing to vp_fog_attr
+                * before moving the fog attr there.
+                * Such instructions will be removed by DCE.
+                */
+               rc_move_output(&compiler.Base, vp_fog_attr, vp->key.FogAttr, 0);
+               rc_move_output(&compiler.Base, VERT_RESULT_FOGC, vp_fog_attr, WRITEMASK_X);
        }
 
        r3xx_compile_vertex_program(&compiler);
@@ -290,7 +307,7 @@ static struct r300_vertex_program *build_program(GLcontext *ctx,
        return vp;
 }
 
-struct r300_vertex_program * r300SelectAndTranslateVertexShader(GLcontext *ctx)
+struct r300_vertex_program * r300SelectAndTranslateVertexShader(struct gl_context *ctx)
 {
        r300ContextPtr r300 = R300_CONTEXT(ctx);
        struct r300_vertex_program_key wanted_key = { 0 };
@@ -369,7 +386,7 @@ static void r300EmitVertexProgram(r300ContextPtr r300, int dest, struct r300_ver
 
 void r300SetupVertexProgram(r300ContextPtr rmesa)
 {
-       GLcontext *ctx = rmesa->radeon.glCtx;
+       struct gl_context *ctx = rmesa->radeon.glCtx;
        struct r300_vertex_program *prog = rmesa->selected_vp;
        int inst_count = 0;
        int param_count = 0;
@@ -382,7 +399,11 @@ void r300SetupVertexProgram(r300ContextPtr rmesa)
        R300_STATECHANGE(rmesa, vap_cntl);
        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);
+       if (!rmesa->radeon.radeonScreen->kernel_mm && param_count > 255 * 4) {
+               WARN_ONCE("Too many VP params, expect rendering errors\n");
+       }
+       /* Prevent the overflow (vpu.count is u8) */
+       bump_vpu_count(rmesa->hw.vpp.cmd, MIN2(255 * 4, param_count));
        param_count /= 4;
 
        r300EmitVertexProgram(rmesa, R300_PVS_CODE_START, &(prog->code));
@@ -395,6 +416,6 @@ void r300SetupVertexProgram(r300ContextPtr rmesa)
        rmesa->hw.pvs.cmd[R300_PVS_CNTL_1] = (0 << R300_PVS_FIRST_INST_SHIFT) | (inst_count << R300_PVS_XYZW_VALID_INST_SHIFT) |
                                (inst_count << R300_PVS_LAST_INST_SHIFT);
 
-       rmesa->hw.pvs.cmd[R300_PVS_CNTL_2] = (0 << R300_PVS_CONST_BASE_OFFSET_SHIFT) | (param_count << R300_PVS_MAX_CONST_ADDR_SHIFT);
+       rmesa->hw.pvs.cmd[R300_PVS_CNTL_2] = (0 << R300_PVS_CONST_BASE_OFFSET_SHIFT) | ((param_count - 1) << R300_PVS_MAX_CONST_ADDR_SHIFT);
        rmesa->hw.pvs.cmd[R300_PVS_CNTL_3] = (inst_count << R300_PVS_LAST_VTX_SRC_INST_SHIFT);
 }