i965/fs: Implement texelFetch() on Gen4.
[mesa.git] / src / mesa / drivers / dri / i965 / brw_wm.c
index 61b2262cfa62d5e193052abfd14a82ec93ce39c6..f746b31f66c6266431e0d6d63b0494191a6da154 100644 (file)
@@ -34,8 +34,9 @@
 #include "brw_state.h"
 #include "main/formats.h"
 #include "main/samplerobj.h"
+#include "program/prog_parameter.h"
 
-#include "../glsl/ralloc.h"
+#include "glsl/ralloc.h"
 
 /** Return number of src args for given instruction */
 GLuint brw_wm_nr_args( GLuint opcode )
@@ -115,7 +116,7 @@ brw_wm_non_glsl_emit(struct brw_context *brw, struct brw_wm_compile *c)
    brw_wm_pass2(c);
 
    /* how many general-purpose registers are used */
-   c->prog_data.total_grf = c->max_wm_grf;
+   c->prog_data.reg_blocks = brw_register_blocks(c->max_wm_grf);
 
    /* Emit GEN4 code.
     */
@@ -184,9 +185,10 @@ brw_wm_payload_setup(struct brw_context *brw,
  * Depending on the instructions used (i.e. flow control instructions)
  * we'll use one of two code generators.
  */
-static void do_wm_prog( struct brw_context *brw,
-                       struct brw_fragment_program *fp, 
-                       struct brw_wm_prog_key *key)
+bool do_wm_prog(struct brw_context *brw,
+               struct gl_shader_program *prog,
+               struct brw_fragment_program *fp,
+               struct brw_wm_prog_key *key)
 {
    struct intel_context *intel = &brw->intel;
    struct brw_wm_compile *c;
@@ -202,12 +204,8 @@ static void do_wm_prog( struct brw_context *brw,
           * without triggering a segfault, no way to signal,
           * so just return.
           */
-         return;
+         return false;
       }
-      c->instruction = rzalloc_array(c, struct brw_wm_instruction, BRW_WM_MAX_INSN);
-      c->prog_instructions = rzalloc_array(c, struct prog_instruction, BRW_WM_MAX_INSN);
-      c->vreg = rzalloc_array(c, struct brw_wm_value, BRW_WM_MAX_VREG);
-      c->refs = rzalloc_array(c, struct brw_wm_ref, BRW_WM_MAX_REF);
    } else {
       void *instruction = c->instruction;
       void *prog_instructions = c->prog_instructions;
@@ -226,7 +224,17 @@ static void do_wm_prog( struct brw_context *brw,
 
    brw_init_compile(brw, &c->func, c);
 
-   if (!brw_wm_fs_emit(brw, c)) {
+   if (prog && prog->FragmentProgram) {
+      if (!brw_wm_fs_emit(brw, c, prog))
+        return false;
+   } else {
+      if (!c->instruction) {
+        c->instruction = rzalloc_array(c, struct brw_wm_instruction, BRW_WM_MAX_INSN);
+        c->prog_instructions = rzalloc_array(c, struct prog_instruction, BRW_WM_MAX_INSN);
+        c->vreg = rzalloc_array(c, struct brw_wm_value, BRW_WM_MAX_VREG);
+        c->refs = rzalloc_array(c, struct brw_wm_ref, BRW_WM_MAX_REF);
+      }
+
       /* Fallback for fixed function and ARB_fp shaders. */
       c->dispatch_width = 16;
       brw_wm_payload_setup(brw, c);
@@ -236,29 +244,10 @@ static void do_wm_prog( struct brw_context *brw,
 
    /* Scratch space is used for register spilling */
    if (c->last_scratch) {
-      uint32_t total_scratch;
+      c->prog_data.total_scratch = brw_get_scratch_size(c->last_scratch);
 
-      /* Per-thread scratch space is power-of-two sized. */
-      for (c->prog_data.total_scratch = 1024;
-          c->prog_data.total_scratch <= c->last_scratch;
-          c->prog_data.total_scratch *= 2) {
-        /* empty */
-      }
-      total_scratch = c->prog_data.total_scratch * brw->wm_max_threads;
-
-      if (brw->wm.scratch_bo && total_scratch > brw->wm.scratch_bo->size) {
-        drm_intel_bo_unreference(brw->wm.scratch_bo);
-        brw->wm.scratch_bo = NULL;
-      }
-      if (brw->wm.scratch_bo == NULL) {
-        brw->wm.scratch_bo = drm_intel_bo_alloc(intel->bufmgr,
-                                                "wm scratch",
-                                                total_scratch,
-                                                4096);
-      }
-   }
-   else {
-      c->prog_data.total_scratch = 0;
+      brw_get_scratch_bo(intel, &brw->wm.scratch_bo,
+                        c->prog_data.total_scratch * brw->wm_max_threads);
    }
 
    if (unlikely(INTEL_DEBUG & DEBUG_WM))
@@ -268,12 +257,13 @@ static void do_wm_prog( struct brw_context *brw,
     */
    program = brw_get_program(&c->func, &program_size);
 
-   drm_intel_bo_unreference(brw->wm.prog_bo);
-   brw->wm.prog_bo = brw_upload_cache(&brw->cache, BRW_WM_PROG,
-                                     &c->key, sizeof(c->key),
-                                     program, program_size,
-                                     &c->prog_data, sizeof(c->prog_data),
-                                     &brw->wm.prog_data);
+   brw_upload_cache(&brw->cache, BRW_WM_PROG,
+                   &c->key, sizeof(c->key),
+                   program, program_size,
+                   &c->prog_data, sizeof(c->prog_data),
+                   &brw->wm.prog_offset, &brw->wm.prog_data);
+
+   return true;
 }
 
 
@@ -382,6 +372,8 @@ static void brw_wm_populate_key( struct brw_context *brw,
          * all 4 channels.
          */
         if (sampler->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) {
+           key->compare_funcs[i] = sampler->CompareFunc;
+
            if (sampler->DepthMode == GL_ALPHA) {
               swizzles[0] = SWIZZLE_ZERO;
               swizzles[1] = SWIZZLE_ZERO;
@@ -423,9 +415,6 @@ static void brw_wm_populate_key( struct brw_context *brw,
       }
    }
 
-   /* Shadow */
-   key->shadowtex_mask = fp->program.Base.ShadowSamplers;
-
    /* _NEW_BUFFERS */
    /*
     * Include the draw buffer origin and height so that we can calculate
@@ -465,20 +454,21 @@ static void brw_wm_populate_key( struct brw_context *brw,
 
 static void brw_prepare_wm_prog(struct brw_context *brw)
 {
+   struct intel_context *intel = &brw->intel;
+   struct gl_context *ctx = &intel->ctx;
    struct brw_wm_prog_key key;
    struct brw_fragment_program *fp = (struct brw_fragment_program *)
       brw->fragment_program;
 
    brw_wm_populate_key(brw, &key);
 
-   /* Make an early check for the key.
-    */
-   drm_intel_bo_unreference(brw->wm.prog_bo);
-   brw->wm.prog_bo = brw_search_cache(&brw->cache, BRW_WM_PROG,
-                                     &key, sizeof(key),
-                                     &brw->wm.prog_data);
-   if (brw->wm.prog_bo == NULL)
-      do_wm_prog(brw, fp, &key);
+   if (!brw_search_cache(&brw->cache, BRW_WM_PROG,
+                        &key, sizeof(key),
+                        &brw->wm.prog_offset, &brw->wm.prog_data)) {
+      bool success = do_wm_prog(brw, ctx->Shader.CurrentFragmentProgram, fp,
+                               &key);
+      assert(success);
+   }
 }