i965: Fix SAMPLER_STATE on Ivybridge.
authorKenneth Graunke <kenneth@whitecape.org>
Fri, 29 Apr 2011 05:46:15 +0000 (22:46 -0700)
committerKenneth Graunke <kenneth@whitecape.org>
Wed, 18 May 2011 06:33:01 +0000 (23:33 -0700)
Most of this code copied from brw_wm_sampler_state.c.

Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Eric Anholt <eric@anholt.net>
src/mesa/drivers/dri/i965/Makefile
src/mesa/drivers/dri/i965/brw_state.h
src/mesa/drivers/dri/i965/brw_state_upload.c
src/mesa/drivers/dri/i965/brw_structs.h
src/mesa/drivers/dri/i965/gen7_sampler_state.c [new file with mode: 0644]

index 651f09e5e0c087081baf105cc125213daac24c45..b96f42bfe883c9335c3e02e3758721ce2a6cf01e 100644 (file)
@@ -101,6 +101,7 @@ DRIVER_SOURCES = \
        gen7_clip_state.c \
        gen7_disable.c \
        gen7_misc_state.c \
+       gen7_sampler_state.c \
        gen7_sf_state.c \
        gen7_urb.c \
        gen7_viewport_state.c \
index e58840f67879f5dcafa3c1b462870a6798eebf2c..11a873205424771bca8a6134dcde1b54621ee370 100644 (file)
@@ -119,7 +119,7 @@ extern const struct brw_tracked_state gen7_clip_state;
 extern const struct brw_tracked_state gen7_depth_stencil_state_pointer;
 extern const struct brw_tracked_state gen7_disable_stages;
 extern const struct brw_tracked_state gen7_ps_state;
-extern const struct brw_tracked_state gen7_sampler_state;
+extern const struct brw_tracked_state gen7_samplers;
 extern const struct brw_tracked_state gen7_sbe_state;
 extern const struct brw_tracked_state gen7_sf_clip_viewport;
 extern const struct brw_tracked_state gen7_sf_clip_viewport_state_pointer;
index 2ea2a0531f35f405612da45d64980b29f1dee2fc..f4a7048f525d43aa2fc59c9c3b127b6ca9ebdf8a 100644 (file)
@@ -207,7 +207,7 @@ const struct brw_tracked_state *gen7_atoms[] =
    &gen7_wm_surfaces,          /* must do before samplers and unit */
    &brw_wm_binding_table,
 
-   &brw_wm_samplers,
+   &gen7_samplers,
 
    &gen7_disable_stages,
    &gen7_vs_state,
index 730e7e22fc964c30f1e7ba85b5ceeca70b217b1d..bcc5ad4b1e67c99f64a789d0d52601dc5d381981 100644 (file)
@@ -1111,6 +1111,54 @@ struct brw_sampler_state
    } ss3;
 };
 
+struct gen7_sampler_state
+{
+   struct
+   {
+      GLuint aniso_algorithm:1;
+      GLuint lod_bias:13;
+      GLuint min_filter:3;
+      GLuint mag_filter:3;
+      GLuint mip_filter:2;
+      GLuint base_level:5;
+      GLuint pad1:1;
+      GLuint lod_preclamp:1;
+      GLuint default_color_mode:1;
+      GLuint pad0:1;
+      GLuint disable:1;
+   } ss0;
+
+   struct
+   {
+      GLuint cube_control_mode:1;
+      GLuint shadow_function:3;
+      GLuint pad:4;
+      GLuint max_lod:12;
+      GLuint min_lod:12;
+   } ss1;
+
+   struct
+   {
+      GLuint pad:5;
+      GLuint default_color_pointer:27;
+   } ss2;
+
+   struct
+   {
+      GLuint r_wrap_mode:3;
+      GLuint t_wrap_mode:3;
+      GLuint s_wrap_mode:3;
+      GLuint pad:1;
+      GLuint non_normalized_coord:1;
+      GLuint trilinear_quality:2;
+      GLuint address_round:6;
+      GLuint max_aniso:3;
+      GLuint chroma_key_mode:1;
+      GLuint chroma_key_index:2;
+      GLuint chroma_key_enable:1;
+      GLuint pad0:6;
+   } ss3;
+};
 
 struct brw_clipper_viewport
 {
diff --git a/src/mesa/drivers/dri/i965/gen7_sampler_state.c b/src/mesa/drivers/dri/i965/gen7_sampler_state.c
new file mode 100644 (file)
index 0000000..75d898e
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#include "brw_context.h"
+#include "brw_state.h"
+#include "brw_defines.h"
+#include "intel_batchbuffer.h"
+
+#include "main/macros.h"
+#include "main/samplerobj.h"
+
+/**
+ * Sets the sampler state for a single unit.
+ */
+static void
+gen7_update_sampler_state(struct brw_context *brw, int unit,
+                         struct gen7_sampler_state *sampler)
+{
+   struct intel_context *intel = &brw->intel;
+   struct gl_context *ctx = &intel->ctx;
+   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+   struct gl_texture_object *texObj = texUnit->_Current;
+   struct gl_sampler_object *gl_sampler = _mesa_get_samplerobj(ctx, unit);
+
+   switch (gl_sampler->MinFilter) {
+   case GL_NEAREST:
+      sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST;
+      sampler->ss0.mip_filter = BRW_MIPFILTER_NONE;
+      break;
+   case GL_LINEAR:
+      sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR;
+      sampler->ss0.mip_filter = BRW_MIPFILTER_NONE;
+      break;
+   case GL_NEAREST_MIPMAP_NEAREST:
+      sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST;
+      sampler->ss0.mip_filter = BRW_MIPFILTER_NEAREST;
+      break;
+   case GL_LINEAR_MIPMAP_NEAREST:
+      sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR;
+      sampler->ss0.mip_filter = BRW_MIPFILTER_NEAREST;
+      break;
+   case GL_NEAREST_MIPMAP_LINEAR:
+      sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST;
+      sampler->ss0.mip_filter = BRW_MIPFILTER_LINEAR;
+      break;
+   case GL_LINEAR_MIPMAP_LINEAR:
+      sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR;
+      sampler->ss0.mip_filter = BRW_MIPFILTER_LINEAR;
+      break;
+   default:
+      break;
+   }
+
+   /* Set Anisotropy: */
+   if (gl_sampler->MaxAnisotropy > 1.0) {
+      sampler->ss0.min_filter = BRW_MAPFILTER_ANISOTROPIC;
+      sampler->ss0.mag_filter = BRW_MAPFILTER_ANISOTROPIC;
+
+      if (gl_sampler->MaxAnisotropy > 2.0) {
+        sampler->ss3.max_aniso = MIN2((gl_sampler->MaxAnisotropy - 2) / 2,
+                                      BRW_ANISORATIO_16);
+      }
+   }
+   else {
+      switch (gl_sampler->MagFilter) {
+      case GL_NEAREST:
+        sampler->ss0.mag_filter = BRW_MAPFILTER_NEAREST;
+        break;
+      case GL_LINEAR:
+        sampler->ss0.mag_filter = BRW_MAPFILTER_LINEAR;
+        break;
+      default:
+        break;
+      }
+   }
+
+   sampler->ss3.r_wrap_mode = translate_wrap_mode(gl_sampler->WrapR);
+   sampler->ss3.s_wrap_mode = translate_wrap_mode(gl_sampler->WrapS);
+   sampler->ss3.t_wrap_mode = translate_wrap_mode(gl_sampler->WrapT);
+
+   /* Cube-maps on 965 and later must use the same wrap mode for all 3
+    * coordinate dimensions.  Futher, only CUBE and CLAMP are valid.
+    */
+   if (texObj->Target == GL_TEXTURE_CUBE_MAP) {
+      if (ctx->Texture.CubeMapSeamless &&
+         (gl_sampler->MinFilter != GL_NEAREST ||
+          gl_sampler->MagFilter != GL_NEAREST)) {
+        sampler->ss3.r_wrap_mode = BRW_TEXCOORDMODE_CUBE;
+        sampler->ss3.s_wrap_mode = BRW_TEXCOORDMODE_CUBE;
+        sampler->ss3.t_wrap_mode = BRW_TEXCOORDMODE_CUBE;
+      } else {
+        sampler->ss3.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
+        sampler->ss3.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
+        sampler->ss3.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
+      }
+   } else if (texObj->Target == GL_TEXTURE_1D) {
+      /* There's a bug in 1D texture sampling - it actually pays
+       * attention to the wrap_t value, though it should not.
+       * Override the wrap_t value here to GL_REPEAT to keep
+       * any nonexistent border pixels from floating in.
+       */
+      sampler->ss3.t_wrap_mode = BRW_TEXCOORDMODE_WRAP;
+   }
+
+   /* Set shadow function: */
+   if (gl_sampler->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) {
+      /* Shadowing is "enabled" by emitting a particular sampler
+       * message (sample_c).  So need to recompile WM program when
+       * shadow comparison is enabled on each/any texture unit.
+       */
+      sampler->ss1.shadow_function =
+        intel_translate_shadow_compare_func(gl_sampler->CompareFunc);
+   }
+
+   /* Set LOD bias: */
+   sampler->ss0.lod_bias = S_FIXED(CLAMP(texUnit->LodBias +
+                                        gl_sampler->LodBias, -16, 15), 6);
+
+   sampler->ss0.lod_preclamp = 1; /* OpenGL mode */
+   sampler->ss0.default_color_mode = 0; /* OpenGL/DX10 mode */
+
+   /* Set BaseMipLevel, MaxLOD, MinLOD:
+    *
+    * XXX: I don't think that using firstLevel, lastLevel works,
+    * because we always setup the surface state as if firstLevel ==
+    * level zero.  Probably have to subtract firstLevel from each of
+    * these:
+    */
+   sampler->ss0.base_level = U_FIXED(0, 1);
+
+   sampler->ss1.max_lod = U_FIXED(CLAMP(gl_sampler->MaxLod, 0, 13), 6);
+   sampler->ss1.min_lod = U_FIXED(CLAMP(gl_sampler->MinLod, 0, 13), 6);
+
+   upload_default_color(brw, gl_sampler, unit);
+
+   sampler->ss2.default_color_pointer = brw->wm.sdc_offset[unit] >> 5;
+}
+
+
+/* All samplers must be uploaded in a single contiguous array, which
+ * complicates various things.  However, this is still too confusing -
+ * FIXME: simplify all the different new texture state flags.
+ */
+static void
+gen7_prepare_samplers(struct brw_context *brw)
+{
+   struct gl_context *ctx = &brw->intel.ctx;
+   struct gen7_sampler_state *samplers;
+   int i;
+
+   brw->wm.sampler_count = 0;
+   for (i = 0; i < BRW_MAX_TEX_UNIT; i++) {
+      if (ctx->Texture.Unit[i]._ReallyEnabled)
+        brw->wm.sampler_count = i + 1;
+   }
+
+   if (brw->wm.sampler_count == 0)
+      return;
+
+   samplers = brw_state_batch(brw, brw->wm.sampler_count * sizeof(*samplers),
+                             32, &brw->wm.sampler_offset);
+   memset(samplers, 0, brw->wm.sampler_count * sizeof(*samplers));
+
+   for (i = 0; i < brw->wm.sampler_count; i++) {
+      if (ctx->Texture.Unit[i]._ReallyEnabled)
+        gen7_update_sampler_state(brw, i, &samplers[i]);
+   }
+
+   brw->state.dirty.cache |= CACHE_NEW_SAMPLER;
+}
+
+const struct brw_tracked_state gen7_samplers = {
+   .dirty = {
+      .mesa = _NEW_TEXTURE,
+      .brw = BRW_NEW_BATCH,
+      .cache = 0
+   },
+   .prepare = gen7_prepare_samplers,
+};