r300g: fix regression in texdepth.
[mesa.git] / src / gallium / drivers / r300 / r300_fs.c
index 4969c1472b05de4fc3fca5af2958886a8c2ec177..dab57fdcc77e73d2a489b81b2785f0d00646f8b3 100644 (file)
@@ -31,6 +31,7 @@
 #include "r300_context.h"
 #include "r300_screen.h"
 #include "r300_fs.h"
+#include "r300_reg.h"
 #include "r300_tgsi_to_rc.h"
 
 #include "radeon_code.h"
@@ -130,20 +131,21 @@ static void allocate_hardware_inputs(
     }
 }
 
-static void get_compare_state(
+static void get_external_state(
     struct r300_context* r300,
-    struct r300_fragment_program_external_state* state,
-    unsigned shadow_samplers)
+    struct r300_fragment_program_external_state* state)
 {
-    struct r300_textures_state *texstate =
-        (struct r300_textures_state*)r300->textures_state.state;
-
-    memset(state, 0, sizeof(*state));
+    struct r300_textures_state *texstate = r300->textures_state.state;
+    unsigned i;
 
-    for (int i = 0; i < texstate->sampler_state_count; i++) {
+    for (i = 0; i < texstate->sampler_state_count; i++) {
         struct r300_sampler_state* s = texstate->sampler_states[i];
 
-        if (s && s->state.compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
+        if (!s) {
+            continue;
+        }
+
+        if (s->state.compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
             /* XXX Gallium doesn't provide us with any information regarding
              * this mode, so we are screwed. I'm setting 0 = LUMINANCE. */
             state->unit[i].depth_texture_mode = 0;
@@ -151,6 +153,35 @@ static void get_compare_state(
             /* Fortunately, no need to translate this. */
             state->unit[i].texture_compare_func = s->state.compare_func;
         }
+
+        if (texstate->sampler_views[i]) {
+            struct r300_texture *t;
+            t = (struct r300_texture*)texstate->sampler_views[i]->base.texture;
+
+            state->unit[i].fake_npot = t->uses_pitch;
+        }
+        state->unit[i].non_normalized_coords = !s->state.normalized_coords;
+
+        /* XXX this should probably take into account STR, not just S. */
+        switch (s->state.wrap_s) {
+            case PIPE_TEX_WRAP_REPEAT:
+                state->unit[i].wrap_mode = RC_WRAP_REPEAT;
+                break;
+            case PIPE_TEX_WRAP_CLAMP:
+            case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+            case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+                state->unit[i].wrap_mode = RC_WRAP_CLAMP;
+                break;
+            case PIPE_TEX_WRAP_MIRROR_REPEAT:
+            case PIPE_TEX_WRAP_MIRROR_CLAMP:
+            case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
+            case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
+                state->unit[i].wrap_mode = RC_WRAP_MIRROR;
+                break;
+            default:
+                state->unit[i].wrap_mode = RC_WRAP_NONE;
+                break;
+        }
     }
 }
 
@@ -225,8 +256,6 @@ static void r300_translate_fragment_shader(
 
     r300_tgsi_to_rc(&ttr, tokens);
 
-    shader->shadow_samplers = compiler.Base.Program.ShadowSamplers;
-
     /**
      * Transform the program to support WPOS.
      *
@@ -251,7 +280,10 @@ static void r300_translate_fragment_shader(
                     "Giving up...\n");
             abort();
         }
+
+        rc_destroy(&compiler.Base);
         r300_dummy_fragment_shader(r300, shader);
+        return;
     }
 
     /* Initialize numbers of constants for each type. */
@@ -272,31 +304,37 @@ static void r300_translate_fragment_shader(
         }
     }
 
+    /* Setup shader depth output. */
+    if (shader->code.writes_depth) {
+        shader->fg_depth_src = R300_FG_DEPTH_SRC_SHADER;
+        shader->us_out_w = R300_W_FMT_W24 | R300_W_SRC_US;
+    } else {
+        shader->fg_depth_src = R300_FG_DEPTH_SRC_SCAN;
+        shader->us_out_w = R300_W_FMT_W0 | R300_W_SRC_US;
+    }
+
     /* And, finally... */
     rc_destroy(&compiler.Base);
 }
 
 boolean r300_pick_fragment_shader(struct r300_context* r300)
 {
-    struct r300_fragment_shader* fs = r300->fs;
-    struct r300_fragment_program_external_state state;
+    struct r300_fragment_shader* fs = r300_fs(r300);
+    struct r300_fragment_program_external_state state = {{{ 0 }}};
     struct r300_fragment_shader_code* ptr;
 
+    get_external_state(r300, &state);
+
     if (!fs->first) {
         /* Build the fragment shader for the first time. */
         fs->first = fs->shader = CALLOC_STRUCT(r300_fragment_shader_code);
 
-        /* BTW shadow samplers will be known after the first translation,
-         * therefore we set ~0, which means it should look at all sampler
-         * states. This choice doesn't have any impact on the correctness. */
-        get_compare_state(r300, &fs->shader->compare_state, ~0);
+        memcpy(&fs->shader->compare_state, &state,
+            sizeof(struct r300_fragment_program_external_state));
         r300_translate_fragment_shader(r300, fs->shader, fs->state.tokens);
-        fs->shadow_samplers = fs->shader->shadow_samplers;
         return TRUE;
 
-    } else if (fs->shadow_samplers) {
-        get_compare_state(r300, &state, fs->shadow_samplers);
-
+    } else {
         /* Check if the currently-bound shader has been compiled
          * with the texture-compare state we need. */
         if (memcmp(&fs->shader->compare_state, &state, sizeof(state)) != 0) {