X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fdri%2Fi915%2Fi915_program.c;h=64b0b4ddb03dab613afcb428ac9accadcc363b91;hb=3bcc780126ec3a479429a42befa27f141ebf8d48;hp=49193297a8c8776d7d9c74264013cce5c88f31f8;hpb=d7f1cb5b5a134b63227d5746a2dd1f05597c5c2f;p=mesa.git diff --git a/src/mesa/drivers/dri/i915/i915_program.c b/src/mesa/drivers/dri/i915/i915_program.c index 49193297a8c..64b0b4ddb03 100644 --- a/src/mesa/drivers/dri/i915/i915_program.c +++ b/src/mesa/drivers/dri/i915/i915_program.c @@ -1,6 +1,6 @@ /************************************************************************** * - * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2003 VMware, Inc. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -18,7 +18,7 @@ * 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 TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * IN NO EVENT SHALL VMWARE AND/OR ITS 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. @@ -130,6 +130,7 @@ i915_emit_decl(struct i915_fragment_program *p, *(p->decl++) = (D0_DCL | D0_DEST(reg) | d0_flags); *(p->decl++) = D1_MBZ; *(p->decl++) = D2_MBZ; + assert(p->decl <= p->declarations + ARRAY_SIZE(p->declarations)); p->nr_decl_insn++; return reg; @@ -186,10 +187,18 @@ i915_emit_arith(struct i915_fragment_program * p, p->utemp_flag = old_utemp_flag; /* restore */ } + if (p->csr >= p->program + ARRAY_SIZE(p->program)) { + i915_program_error(p, "Program contains too many instructions"); + return UREG_BAD; + } + *(p->csr++) = (op | A0_DEST(dest) | mask | saturate | A0_SRC0(src0)); *(p->csr++) = (A1_SRC0(src0) | A1_SRC1(src1)); *(p->csr++) = (A2_SRC1(src1) | A2_SRC2(src2)); + if (GET_UREG_TYPE(dest) == REG_TYPE_R) + p->register_phases[GET_UREG_NR(dest)] = p->nr_tex_indirect; + p->nr_alu_insn++; return dest; } @@ -236,10 +245,40 @@ GLuint i915_emit_texld( struct i915_fragment_program *p, } else { assert(GET_UREG_TYPE(dest) != REG_TYPE_CONST); - assert(dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest))); + assert(dest == UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest))); + /* Can't use unsaved temps for coords, as the phase boundary would result + * in the contents becoming undefined. + */ + assert(GET_UREG_TYPE(coord) != REG_TYPE_U); + + if ((GET_UREG_TYPE(coord) != REG_TYPE_R) && + (GET_UREG_TYPE(coord) != REG_TYPE_OC) && + (GET_UREG_TYPE(coord) != REG_TYPE_OD) && + (GET_UREG_TYPE(coord) != REG_TYPE_T)) { + GLuint tmpCoord = get_free_rreg(p, live_regs); + + if (tmpCoord == UREG_BAD) + return 0; + + i915_emit_arith(p, A0_MOV, tmpCoord, A0_DEST_CHANNEL_ALL, 0, coord, 0, 0); + coord = tmpCoord; + } - if (GET_UREG_TYPE(coord) != REG_TYPE_T) { + /* Output register being oC or oD defines a phase boundary */ + if (GET_UREG_TYPE(dest) == REG_TYPE_OC || + GET_UREG_TYPE(dest) == REG_TYPE_OD) p->nr_tex_indirect++; + + /* Reading from an r# register whose contents depend on output of the + * current phase defines a phase boundary. + */ + if (GET_UREG_TYPE(coord) == REG_TYPE_R && + p->register_phases[GET_UREG_NR(coord)] == p->nr_tex_indirect) + p->nr_tex_indirect++; + + if (p->csr >= p->program + ARRAY_SIZE(p->program)) { + i915_program_error(p, "Program contains too many instructions"); + return UREG_BAD; } *(p->csr++) = (op | @@ -249,6 +288,9 @@ GLuint i915_emit_texld( struct i915_fragment_program *p, *(p->csr++) = T1_ADDRESS_REG( coord ); *(p->csr++) = T2_MBZ; + if (GET_UREG_TYPE(dest) == REG_TYPE_R) + p->register_phases[GET_UREG_NR(dest)] = p->nr_tex_indirect; + p->nr_tex_insn++; return dest; } @@ -280,7 +322,7 @@ i915_emit_const1f(struct i915_fragment_program * p, GLfloat c0) } } - fprintf(stderr, "%s: out of constants\n", __FUNCTION__); + fprintf(stderr, "%s: out of constants\n", __func__); p->error = 1; return 0; } @@ -317,7 +359,7 @@ i915_emit_const2f(struct i915_fragment_program * p, GLfloat c0, GLfloat c1) } } - fprintf(stderr, "%s: out of constants\n", __FUNCTION__); + fprintf(stderr, "%s: out of constants\n", __func__); p->error = 1; return 0; } @@ -349,7 +391,7 @@ i915_emit_const4f(struct i915_fragment_program * p, } } - fprintf(stderr, "%s: out of constants\n", __FUNCTION__); + fprintf(stderr, "%s: out of constants\n", __func__); p->error = 1; return 0; } @@ -388,17 +430,28 @@ i915_emit_param4fv(struct i915_fragment_program * p, const GLfloat * values) } } - fprintf(stderr, "%s: out of constants\n", __FUNCTION__); + fprintf(stderr, "%s: out of constants\n", __func__); p->error = 1; return 0; } - - +/* Warning the user about program errors seems to be quite valuable, from + * our bug reports. It unfortunately means piglit reporting errors + * when we fall back to software due to an unsupportable program, though. + */ void -i915_program_error(struct i915_fragment_program *p, const char *msg) +i915_program_error(struct i915_fragment_program *p, const char *fmt, ...) { - _mesa_problem(NULL, "i915_program_error: %s", msg); + if (unlikely((INTEL_DEBUG & (DEBUG_WM | DEBUG_PERF)) != 0)) { + va_list args; + + fprintf(stderr, "i915_program_error: "); + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + + fprintf(stderr, "\n"); + } p->error = 1; } @@ -406,14 +459,15 @@ i915_program_error(struct i915_fragment_program *p, const char *msg) void i915_init_program(struct i915_context *i915, struct i915_fragment_program *p) { - GLcontext *ctx = &i915->intel.ctx; + struct gl_context *ctx = &i915->intel.ctx; p->translated = 0; p->params_uptodate = 0; p->on_hardware = 0; p->error = 0; - p->nr_tex_indirect = 1; /* correct? */ + memset(&p->register_phases, 0, sizeof(p->register_phases)); + p->nr_tex_indirect = 1; p->nr_tex_insn = 0; p->nr_alu_insn = 0; p->nr_decl_insn = 0; @@ -442,17 +496,25 @@ i915_fini_program(struct i915_fragment_program *p) GLuint program_size = p->csr - p->program; GLuint decl_size = p->decl - p->declarations; - if (p->nr_tex_indirect > I915_MAX_TEX_INDIRECT) - i915_program_error(p, "Exceeded max nr indirect texture lookups"); + if (p->nr_tex_indirect > I915_MAX_TEX_INDIRECT) { + i915_program_error(p, "Exceeded max nr indirect texture lookups " + "(%d out of %d)", + p->nr_tex_indirect, I915_MAX_TEX_INDIRECT); + } - if (p->nr_tex_insn > I915_MAX_TEX_INSN) - i915_program_error(p, "Exceeded max TEX instructions"); + if (p->nr_tex_insn > I915_MAX_TEX_INSN) { + i915_program_error(p, "Exceeded max TEX instructions (%d out of %d)", + p->nr_tex_insn, I915_MAX_TEX_INSN); + } if (p->nr_alu_insn > I915_MAX_ALU_INSN) - i915_program_error(p, "Exceeded max ALU instructions"); + i915_program_error(p, "Exceeded max ALU instructions (%d out of %d)", + p->nr_alu_insn, I915_MAX_ALU_INSN); - if (p->nr_decl_insn > I915_MAX_DECL_INSN) - i915_program_error(p, "Exceeded max DECL instructions"); + if (p->nr_decl_insn > I915_MAX_DECL_INSN) { + i915_program_error(p, "Exceeded max DECL instructions (%d out of %d)", + p->nr_decl_insn, I915_MAX_DECL_INSN); + } if (p->error) { p->FragProg.Base.NumNativeInstructions = 0; @@ -479,7 +541,8 @@ i915_upload_program(struct i915_context *i915, GLuint program_size = p->csr - p->program; GLuint decl_size = p->decl - p->declarations; - FALLBACK(&i915->intel, I915_FALLBACK_PROGRAM, p->error); + if (p->error) + return; /* Could just go straight to the batchbuffer from here: */