From 3f44043da37bcd0c481ceddf4f878ddb3419b763 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Thu, 28 Apr 2011 22:46:15 -0700 Subject: [PATCH] i965: Fix SAMPLER_STATE on Ivybridge. Most of this code copied from brw_wm_sampler_state.c. Signed-off-by: Kenneth Graunke Reviewed-by: Eric Anholt --- src/mesa/drivers/dri/i965/Makefile | 1 + src/mesa/drivers/dri/i965/brw_state.h | 2 +- src/mesa/drivers/dri/i965/brw_state_upload.c | 2 +- src/mesa/drivers/dri/i965/brw_structs.h | 48 ++++++ src/mesa/drivers/dri/i965/gen7_sampler_state.c | 199 +++++++++++++++++++++++++ 5 files changed, 250 insertions(+), 2 deletions(-) create mode 100644 src/mesa/drivers/dri/i965/gen7_sampler_state.c diff --git a/src/mesa/drivers/dri/i965/Makefile b/src/mesa/drivers/dri/i965/Makefile index 651f09e..b96f42b 100644 --- a/src/mesa/drivers/dri/i965/Makefile +++ b/src/mesa/drivers/dri/i965/Makefile @@ -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 \ diff --git a/src/mesa/drivers/dri/i965/brw_state.h b/src/mesa/drivers/dri/i965/brw_state.h index e58840f..11a8732 100644 --- a/src/mesa/drivers/dri/i965/brw_state.h +++ b/src/mesa/drivers/dri/i965/brw_state.h @@ -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; diff --git a/src/mesa/drivers/dri/i965/brw_state_upload.c b/src/mesa/drivers/dri/i965/brw_state_upload.c index 2ea2a05..f4a7048 100644 --- a/src/mesa/drivers/dri/i965/brw_state_upload.c +++ b/src/mesa/drivers/dri/i965/brw_state_upload.c @@ -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, diff --git a/src/mesa/drivers/dri/i965/brw_structs.h b/src/mesa/drivers/dri/i965/brw_structs.h index 730e7e2..bcc5ad4 100644 --- a/src/mesa/drivers/dri/i965/brw_structs.h +++ b/src/mesa/drivers/dri/i965/brw_structs.h @@ -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 index 0000000..75d898e --- /dev/null +++ b/src/mesa/drivers/dri/i965/gen7_sampler_state.c @@ -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, +}; -- 2.7.4