X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fdri%2Fi965%2Fbrw_wm_sampler_state.c;h=8938561bf8ff2432ad3bfaff9ca618827fd6bcf2;hb=76669381c0de6a49a1edd0b88fa1ae6b86f10b30;hp=fea96d353818e67361274e931a770beb771c7201;hpb=4926c5748028d33da4808f8a5473aa7b2f2bdc62;p=mesa.git diff --git a/src/mesa/drivers/dri/i965/brw_wm_sampler_state.c b/src/mesa/drivers/dri/i965/brw_wm_sampler_state.c index fea96d35381..8938561bf8f 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_sampler_state.c +++ b/src/mesa/drivers/dri/i965/brw_wm_sampler_state.c @@ -35,7 +35,7 @@ #include "brw_defines.h" #include "main/macros.h" - +#include "main/samplerobj.h" /* Samplers aren't strictly wm state from the hardware's perspective, @@ -44,19 +44,28 @@ -/* The brw (and related graphics cores) do not support GL_CLAMP. The - * Intel drivers for "other operating systems" implement GL_CLAMP as - * GL_CLAMP_TO_EDGE, so the same is done here. - */ -static GLuint translate_wrap_mode( GLenum wrap ) +uint32_t +translate_wrap_mode(GLenum wrap, bool using_nearest) { switch( wrap ) { case GL_REPEAT: return BRW_TEXCOORDMODE_WRAP; - case GL_CLAMP: - return BRW_TEXCOORDMODE_CLAMP; + case GL_CLAMP: + /* GL_CLAMP is the weird mode where coordinates are clamped to + * [0.0, 1.0], so linear filtering of coordinates outside of + * [0.0, 1.0] give you half edge texel value and half border + * color. The fragment shader will clamp the coordinates, and + * we set clamp_border here, which gets the result desired. We + * just use clamp(_to_edge) for nearest, because for nearest + * clamping to 1.0 gives border color instead of the desired + * edge texels. + */ + if (using_nearest) + return BRW_TEXCOORDMODE_CLAMP; + else + return BRW_TEXCOORDMODE_CLAMP_BORDER; case GL_CLAMP_TO_EDGE: - return BRW_TEXCOORDMODE_CLAMP; /* conform likes it this way */ + return BRW_TEXCOORDMODE_CLAMP; case GL_CLAMP_TO_BORDER: return BRW_TEXCOORDMODE_CLAMP_BORDER; case GL_MIRRORED_REPEAT: @@ -66,53 +75,103 @@ static GLuint translate_wrap_mode( GLenum wrap ) } } -static drm_intel_bo *upload_default_color( struct brw_context *brw, - const GLfloat *color ) +/** + * Upload SAMPLER_BORDER_COLOR_STATE. + */ +void +upload_default_color(struct brw_context *brw, struct gl_sampler_object *sampler, + int unit) { - struct brw_sampler_default_color sdc; + 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_texture_image *firstImage = texObj->Image[0][texObj->BaseLevel]; + float color[4]; + + if (firstImage->_BaseFormat == GL_DEPTH_COMPONENT) { + /* GL specs that border color for depth textures is taken from the + * R channel, while the hardware uses A. Spam R into all the + * channels for safety. + */ + color[0] = sampler->BorderColor.f[0]; + color[1] = sampler->BorderColor.f[0]; + color[2] = sampler->BorderColor.f[0]; + color[3] = sampler->BorderColor.f[0]; + } else { + color[0] = sampler->BorderColor.f[0]; + color[1] = sampler->BorderColor.f[1]; + color[2] = sampler->BorderColor.f[2]; + color[3] = sampler->BorderColor.f[3]; + } - COPY_4V(sdc.color, color); - - return brw_cache_data(&brw->cache, BRW_SAMPLER_DEFAULT_COLOR, - &sdc, sizeof(sdc)); -} + if (intel->gen == 5 || intel->gen == 6) { + struct gen5_sampler_default_color *sdc; + sdc = brw_state_batch(brw, AUB_TRACE_SAMPLER_DEFAULT_COLOR, + sizeof(*sdc), 32, &brw->wm.sdc_offset[unit]); -struct wm_sampler_key { - int sampler_count; + memset(sdc, 0, sizeof(*sdc)); - struct wm_sampler_entry { - GLenum tex_target; - GLenum wrap_r, wrap_s, wrap_t; - float maxlod, minlod; - float lod_bias; - float max_aniso; - GLenum minfilter, magfilter; - GLenum comparemode, comparefunc; + UNCLAMPED_FLOAT_TO_UBYTE(sdc->ub[0], color[0]); + UNCLAMPED_FLOAT_TO_UBYTE(sdc->ub[1], color[1]); + UNCLAMPED_FLOAT_TO_UBYTE(sdc->ub[2], color[2]); + UNCLAMPED_FLOAT_TO_UBYTE(sdc->ub[3], color[3]); - /** If target is cubemap, take context setting. - */ - GLboolean seamless_cube_map; - } sampler[BRW_MAX_TEX_UNIT]; -}; + UNCLAMPED_FLOAT_TO_USHORT(sdc->us[0], color[0]); + UNCLAMPED_FLOAT_TO_USHORT(sdc->us[1], color[1]); + UNCLAMPED_FLOAT_TO_USHORT(sdc->us[2], color[2]); + UNCLAMPED_FLOAT_TO_USHORT(sdc->us[3], color[3]); + + UNCLAMPED_FLOAT_TO_SHORT(sdc->s[0], color[0]); + UNCLAMPED_FLOAT_TO_SHORT(sdc->s[1], color[1]); + UNCLAMPED_FLOAT_TO_SHORT(sdc->s[2], color[2]); + UNCLAMPED_FLOAT_TO_SHORT(sdc->s[3], color[3]); + + sdc->hf[0] = _mesa_float_to_half(color[0]); + sdc->hf[1] = _mesa_float_to_half(color[1]); + sdc->hf[2] = _mesa_float_to_half(color[2]); + sdc->hf[3] = _mesa_float_to_half(color[3]); + + sdc->b[0] = sdc->s[0] >> 8; + sdc->b[1] = sdc->s[1] >> 8; + sdc->b[2] = sdc->s[2] >> 8; + sdc->b[3] = sdc->s[3] >> 8; + + sdc->f[0] = color[0]; + sdc->f[1] = color[1]; + sdc->f[2] = color[2]; + sdc->f[3] = color[3]; + } else { + struct brw_sampler_default_color *sdc; + + sdc = brw_state_batch(brw, AUB_TRACE_SAMPLER_DEFAULT_COLOR, + sizeof(*sdc), 32, &brw->wm.sdc_offset[unit]); + + COPY_4V(sdc->color, color); + } +} /** * Sets the sampler state for a single unit based off of the sampler key * entry. */ static void brw_update_sampler_state(struct brw_context *brw, - struct wm_sampler_entry *key, - drm_intel_bo *sdc_bo, + int unit, struct brw_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); + bool using_nearest = false; - memset(sampler, 0, sizeof(*sampler)); - - switch (key->minfilter) { + switch (gl_sampler->MinFilter) { case GL_NEAREST: sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST; sampler->ss0.mip_filter = BRW_MIPFILTER_NONE; + using_nearest = true; break; case GL_LINEAR: sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR; @@ -140,19 +199,20 @@ static void brw_update_sampler_state(struct brw_context *brw, /* Set Anisotropy: */ - if (key->max_aniso > 1.0) { + if (gl_sampler->MaxAnisotropy > 1.0) { sampler->ss0.min_filter = BRW_MAPFILTER_ANISOTROPIC; sampler->ss0.mag_filter = BRW_MAPFILTER_ANISOTROPIC; - if (key->max_aniso > 2.0) { - sampler->ss3.max_aniso = MIN2((key->max_aniso - 2) / 2, + if (gl_sampler->MaxAnisotropy > 2.0) { + sampler->ss3.max_aniso = MIN2((gl_sampler->MaxAnisotropy - 2) / 2, BRW_ANISORATIO_16); } } else { - switch (key->magfilter) { + switch (gl_sampler->MagFilter) { case GL_NEAREST: sampler->ss0.mag_filter = BRW_MAPFILTER_NEAREST; + using_nearest = true; break; case GL_LINEAR: sampler->ss0.mag_filter = BRW_MAPFILTER_LINEAR; @@ -162,9 +222,12 @@ static void brw_update_sampler_state(struct brw_context *brw, } } - sampler->ss1.r_wrap_mode = translate_wrap_mode(key->wrap_r); - sampler->ss1.s_wrap_mode = translate_wrap_mode(key->wrap_s); - sampler->ss1.t_wrap_mode = translate_wrap_mode(key->wrap_t); + sampler->ss1.r_wrap_mode = translate_wrap_mode(gl_sampler->WrapR, + using_nearest); + sampler->ss1.s_wrap_mode = translate_wrap_mode(gl_sampler->WrapS, + using_nearest); + sampler->ss1.t_wrap_mode = translate_wrap_mode(gl_sampler->WrapT, + using_nearest); if (intel->gen >= 6 && sampler->ss0.min_filter != sampler->ss0.mag_filter) @@ -173,9 +236,10 @@ static void brw_update_sampler_state(struct brw_context *brw, /* 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 (key->tex_target == GL_TEXTURE_CUBE_MAP) { - if (key->seamless_cube_map && - (key->minfilter != GL_NEAREST || key->magfilter != GL_NEAREST)) { + if (texObj->Target == GL_TEXTURE_CUBE_MAP) { + if (ctx->Texture.CubeMapSeamless && + (gl_sampler->MinFilter != GL_NEAREST || + gl_sampler->MagFilter != GL_NEAREST)) { sampler->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CUBE; sampler->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CUBE; sampler->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CUBE; @@ -184,7 +248,7 @@ static void brw_update_sampler_state(struct brw_context *brw, sampler->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP; sampler->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP; } - } else if (key->tex_target == GL_TEXTURE_1D) { + } 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 @@ -196,18 +260,19 @@ static void brw_update_sampler_state(struct brw_context *brw, /* Set shadow function: */ - if (key->comparemode == GL_COMPARE_R_TO_TEXTURE_ARB) { + 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->ss0.shadow_function = - intel_translate_shadow_compare_func(key->comparefunc); + intel_translate_shadow_compare_func(gl_sampler->CompareFunc); } /* Set LOD bias: */ - sampler->ss0.lod_bias = S_FIXED(CLAMP(key->lod_bias, -16, 15), 6); + 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 */ @@ -221,151 +286,84 @@ static void brw_update_sampler_state(struct brw_context *brw, */ sampler->ss0.base_level = U_FIXED(0, 1); - sampler->ss1.max_lod = U_FIXED(CLAMP(key->maxlod, 0, 13), 6); - sampler->ss1.min_lod = U_FIXED(CLAMP(key->minlod, 0, 13), 6); - - sampler->ss2.default_color_pointer = sdc_bo->offset >> 5; /* reloc */ -} + 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); + /* On Gen6+, the sampler can handle non-normalized texture + * rectangle coordinates natively + */ + if (intel->gen >= 6 && texObj->Target == GL_TEXTURE_RECTANGLE) { + sampler->ss3.non_normalized_coord = 1; + } -/** Sets up the cache key for sampler state for all texture units */ -static void -brw_wm_sampler_populate_key(struct brw_context *brw, - struct wm_sampler_key *key) -{ - struct gl_context *ctx = &brw->intel.ctx; - int unit; - char *last_entry_end = ((char*)&key->sampler_count) + - sizeof(key->sampler_count); - - key->sampler_count = 0; - - for (unit = 0; unit < BRW_MAX_TEX_UNIT; unit++) { - if (ctx->Texture.Unit[unit]._ReallyEnabled) { - struct wm_sampler_entry *entry = &key->sampler[unit]; - struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; - struct gl_texture_object *texObj = texUnit->_Current; - struct intel_texture_object *intelObj = intel_texture_object(texObj); - struct gl_texture_image *firstImage = - texObj->Image[0][intelObj->firstLevel]; - - memset(last_entry_end, 0, - (char*)entry - last_entry_end + sizeof(*entry)); - last_entry_end = ((char*)entry) + sizeof(*entry); - - entry->tex_target = texObj->Target; - - entry->seamless_cube_map = (texObj->Target == GL_TEXTURE_CUBE_MAP) - ? ctx->Texture.CubeMapSeamless : GL_FALSE; - - entry->wrap_r = texObj->WrapR; - entry->wrap_s = texObj->WrapS; - entry->wrap_t = texObj->WrapT; - - entry->maxlod = texObj->MaxLod; - entry->minlod = texObj->MinLod; - entry->lod_bias = texUnit->LodBias + texObj->LodBias; - entry->max_aniso = texObj->MaxAnisotropy; - entry->minfilter = texObj->MinFilter; - entry->magfilter = texObj->MagFilter; - entry->comparemode = texObj->CompareMode; - entry->comparefunc = texObj->CompareFunc; - - drm_intel_bo_unreference(brw->wm.sdc_bo[unit]); - if (firstImage->_BaseFormat == GL_DEPTH_COMPONENT) { - float bordercolor[4] = { - texObj->BorderColor.f[0], - texObj->BorderColor.f[0], - texObj->BorderColor.f[0], - texObj->BorderColor.f[0] - }; - /* GL specs that border color for depth textures is taken from the - * R channel, while the hardware uses A. Spam R into all the - * channels for safety. - */ - brw->wm.sdc_bo[unit] = upload_default_color(brw, bordercolor); - } else { - brw->wm.sdc_bo[unit] = upload_default_color(brw, - texObj->BorderColor.f); - } - key->sampler_count = unit + 1; - } + upload_default_color(brw, gl_sampler, unit); + + if (intel->gen >= 6) { + sampler->ss2.default_color_pointer = brw->wm.sdc_offset[unit] >> 5; + } else { + /* reloc */ + sampler->ss2.default_color_pointer = (intel->batch.bo->offset + + brw->wm.sdc_offset[unit]) >> 5; + + drm_intel_bo_emit_reloc(intel->batch.bo, + brw->wm.sampler_offset + + unit * sizeof(struct brw_sampler_state) + + offsetof(struct brw_sampler_state, ss2), + intel->batch.bo, brw->wm.sdc_offset[unit], + I915_GEM_DOMAIN_SAMPLER, 0); } - struct wm_sampler_entry *entry = &key->sampler[key->sampler_count]; - memset(last_entry_end, 0, (char*)entry - last_entry_end); + + if (sampler->ss0.min_filter != BRW_MAPFILTER_NEAREST) + sampler->ss3.address_round |= BRW_ADDRESS_ROUNDING_ENABLE_U_MIN | + BRW_ADDRESS_ROUNDING_ENABLE_V_MIN | + BRW_ADDRESS_ROUNDING_ENABLE_R_MIN; + if (sampler->ss0.mag_filter != BRW_MAPFILTER_NEAREST) + sampler->ss3.address_round |= BRW_ADDRESS_ROUNDING_ENABLE_U_MAG | + BRW_ADDRESS_ROUNDING_ENABLE_V_MAG | + BRW_ADDRESS_ROUNDING_ENABLE_R_MAG; } + /* 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 upload_wm_samplers( struct brw_context *brw ) +static void +prepare_wm_samplers(struct brw_context *brw) { struct gl_context *ctx = &brw->intel.ctx; - struct wm_sampler_key key; - int i, sampler_key_size; - - brw_wm_sampler_populate_key(brw, &key); + struct brw_sampler_state *samplers; + int i; - if (brw->wm.sampler_count != key.sampler_count) { - brw->wm.sampler_count = key.sampler_count; - brw->state.dirty.cache |= CACHE_NEW_SAMPLER; + 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; } - drm_intel_bo_unreference(brw->wm.sampler_bo); - brw->wm.sampler_bo = NULL; if (brw->wm.sampler_count == 0) return; - /* Only include the populated portion of the key in the search. */ - sampler_key_size = offsetof(struct wm_sampler_key, - sampler[key.sampler_count]); - brw->wm.sampler_bo = brw_search_cache(&brw->cache, BRW_SAMPLER, - &key, sampler_key_size, - brw->wm.sdc_bo, key.sampler_count, - NULL); - - /* If we didnt find it in the cache, compute the state and put it in the - * cache. - */ - if (brw->wm.sampler_bo == NULL) { - struct brw_sampler_state sampler[BRW_MAX_TEX_UNIT]; - - memset(sampler, 0, sizeof(sampler)); - for (i = 0; i < key.sampler_count; i++) { - if (brw->wm.sdc_bo[i] == NULL) - continue; - - brw_update_sampler_state(brw, &key.sampler[i], brw->wm.sdc_bo[i], - &sampler[i]); - } + samplers = brw_state_batch(brw, AUB_TRACE_SAMPLER_STATE, + brw->wm.sampler_count * sizeof(*samplers), + 32, &brw->wm.sampler_offset); + memset(samplers, 0, brw->wm.sampler_count * sizeof(*samplers)); - brw->wm.sampler_bo = brw_upload_cache(&brw->cache, BRW_SAMPLER, - &key, sampler_key_size, - brw->wm.sdc_bo, key.sampler_count, - &sampler, sizeof(sampler)); - - /* Emit SDC relocations */ - for (i = 0; i < BRW_MAX_TEX_UNIT; i++) { - if (!ctx->Texture.Unit[i]._ReallyEnabled) - continue; - - drm_intel_bo_emit_reloc(brw->wm.sampler_bo, - i * sizeof(struct brw_sampler_state) + - offsetof(struct brw_sampler_state, ss2), - brw->wm.sdc_bo[i], 0, - I915_GEM_DOMAIN_SAMPLER, 0); - } + for (i = 0; i < brw->wm.sampler_count; i++) { + if (ctx->Texture.Unit[i]._ReallyEnabled) + brw_update_sampler_state(brw, i, &samplers[i]); } + + brw->state.dirty.cache |= CACHE_NEW_SAMPLER; } const struct brw_tracked_state brw_wm_samplers = { .dirty = { .mesa = _NEW_TEXTURE, - .brw = 0, + .brw = BRW_NEW_BATCH, .cache = 0 }, - .prepare = upload_wm_samplers, + .prepare = prepare_wm_samplers, };