i915: Add support for GL_EXT_texture_sRGB and GL_EXT_texture_sRGB_decode.
[mesa.git] / src / mesa / drivers / dri / i915 / i915_program.c
index e87700f8e0aaa71159dfa8a5ddae613a8c46d249..4437167722758803aeac95200ab248d6456c2dcf 100644 (file)
@@ -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,6 +187,11 @@ 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));
@@ -239,7 +245,7 @@ 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.
        */
@@ -270,6 +276,11 @@ GLuint i915_emit_texld( struct i915_fragment_program *p,
          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 | 
                     T0_DEST( dest ) |
                     T0_SAMPLER( sampler ));
@@ -424,12 +435,23 @@ i915_emit_param4fv(struct i915_fragment_program * p, const GLfloat * values)
    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;
 }
 
@@ -437,7 +459,7 @@ 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;
@@ -474,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;
@@ -511,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:
     */