* Keith Whitwell <keith@tungstengraphics.com>
*/
+#include "util/u_math.h"
+#include "util/u_format.h"
#include "brw_context.h"
#include "brw_state.h"
#include "brw_defines.h"
+#include "brw_resource.h"
/* Samplers aren't strictly wm state from the hardware's perspective,
-/* 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 )
-{
- switch( wrap ) {
- case GL_REPEAT:
- return BRW_TEXCOORDMODE_WRAP;
- case GL_CLAMP:
- return BRW_TEXCOORDMODE_CLAMP;
- case GL_CLAMP_TO_EDGE:
- return BRW_TEXCOORDMODE_CLAMP; /* conform likes it this way */
- case GL_CLAMP_TO_BORDER:
- return BRW_TEXCOORDMODE_CLAMP_BORDER;
- case GL_MIRRORED_REPEAT:
- return BRW_TEXCOORDMODE_MIRROR;
- default:
- return BRW_TEXCOORDMODE_WRAP;
- }
-}
-
-
-static GLuint U_FIXED(GLfloat value, GLuint frac_bits)
-{
- value *= (1<<frac_bits);
- return value < 0 ? 0 : value;
-}
-
-static GLint S_FIXED(GLfloat value, GLuint frac_bits)
-{
- return value * (1<<frac_bits);
-}
-
-
-static struct brw_winsys_buffer *upload_default_color( struct brw_context *brw,
- const GLfloat *color )
+static enum pipe_error
+upload_default_color( struct brw_context *brw,
+ const GLfloat *color,
+ struct brw_winsys_buffer **bo_out )
{
struct brw_sampler_default_color sdc;
+ enum pipe_error ret;
COPY_4V(sdc.color, color);
- return brw_cache_data( &brw->cache, BRW_SAMPLER_DEFAULT_COLOR, &sdc,
- NULL, 0 );
+ ret = brw_cache_data( &brw->cache, BRW_SAMPLER_DEFAULT_COLOR, &sdc,
+ NULL, 0, bo_out );
+ if (ret)
+ return ret;
+
+ return PIPE_OK;
}
struct wm_sampler_key {
int sampler_count;
-
- 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;
- struct brw_winsys_buffer *sdc_bo;
-
- /** If target is cubemap, take context setting.
- */
- GLboolean seamless_cube_map;
- } sampler[BRW_MAX_TEX_UNIT];
+ struct brw_sampler_state sampler[BRW_MAX_TEX_UNIT];
};
-/**
- * Sets the sampler state for a single unit based off of the sampler key
- * entry.
- */
-static void brw_update_sampler_state(struct wm_sampler_entry *key,
- struct brw_winsys_buffer *sdc_bo,
- struct brw_sampler_state *sampler)
-{
- _mesa_memset(sampler, 0, sizeof(*sampler));
-
- switch (key->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 (key->max_aniso > 1.0) {
- sampler->ss0.min_filter = BRW_MAPFILTER_ANISOTROPIC;
- sampler->ss0.mag_filter = BRW_MAPFILTER_ANISOTROPIC;
+/** 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)
+{
+ int i;
- if (key->max_aniso > 2.0) {
- sampler->ss3.max_aniso = MIN2((key->max_aniso - 2) / 2,
- BRW_ANISORATIO_16);
- }
- }
- else {
- switch (key->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;
- }
- }
+ memset(key, 0, sizeof(*key));
- 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);
+ key->sampler_count = MIN2(brw->curr.num_fragment_sampler_views,
+ brw->curr.num_samplers);
- /* 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)) {
- sampler->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CUBE;
- sampler->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CUBE;
- sampler->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CUBE;
- } else {
- sampler->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
- sampler->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
- sampler->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
- }
- } else if (key->tex_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->ss1.t_wrap_mode = BRW_TEXCOORDMODE_WRAP;
- }
+ for (i = 0; i < key->sampler_count; i++) {
+ const struct brw_texture *tex = brw_texture(brw->curr.fragment_sampler_views[i]->texture);
+ const struct brw_sampler *sampler = brw->curr.sampler[i];
+ struct brw_sampler_state *entry = &key->sampler[i];
+ entry->ss0 = sampler->ss0;
+ entry->ss1 = sampler->ss1;
+ entry->ss2.default_color_pointer = 0; /* reloc */
+ entry->ss3 = sampler->ss3;
- /* Set shadow function:
- */
- if (key->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.
+ /* Cube-maps on 965 and later must use the same wrap mode for all 3
+ * coordinate dimensions. Futher, only CUBE and CLAMP are valid.
*/
- sampler->ss0.shadow_function =
- intel_translate_shadow_compare_func(key->comparefunc);
+ if (tex->b.b.target == PIPE_TEXTURE_CUBE) {
+ if (FALSE &&
+ (sampler->ss0.min_filter != BRW_MAPFILTER_NEAREST ||
+ sampler->ss0.mag_filter != BRW_MAPFILTER_NEAREST)) {
+ entry->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CUBE;
+ entry->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CUBE;
+ entry->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CUBE;
+ } else {
+ entry->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
+ entry->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
+ entry->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
+ }
+ } else if (tex->b.b.target == PIPE_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.
+ */
+ entry->ss1.t_wrap_mode = BRW_TEXCOORDMODE_WRAP;
+ }
}
-
- /* Set LOD bias:
- */
- sampler->ss0.lod_bias = S_FIXED(CLAMP(key->lod_bias, -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(MIN2(MAX2(key->maxlod, 0), 13), 6);
- sampler->ss1.min_lod = U_FIXED(MIN2(MAX2(key->minlod, 0), 13), 6);
-
- sampler->ss2.default_color_pointer = sdc_bo->offset >> 5; /* reloc */
}
-/** 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)
+static enum pipe_error
+brw_wm_sampler_update_default_colors(struct brw_context *brw)
{
- int unit;
-
- memset(key, 0, sizeof(*key));
+ enum pipe_error ret;
+ int nr = MIN2(brw->curr.num_fragment_sampler_views,
+ brw->curr.num_samplers);
+ int i;
- 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];
-
- 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;
-
- brw->sws->bo_unreference(brw->wm.sdc_bo[unit]);
- if (firstImage->_BaseFormat == GL_DEPTH_COMPONENT) {
- float bordercolor[4] = {
- texObj->BorderColor[0],
- texObj->BorderColor[0],
- texObj->BorderColor[0],
- texObj->BorderColor[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);
- }
- key->sampler_count = unit + 1;
+ for (i = 0; i < nr; i++) {
+ const struct brw_texture *tex = brw_texture(brw->curr.fragment_sampler_views[i]->texture);
+ const struct brw_sampler *sampler = brw->curr.sampler[i];
+ const float *bc;
+ float bordercolor[4] = {
+ sampler->border_color[0],
+ sampler->border_color[0],
+ sampler->border_color[0],
+ sampler->border_color[0]
+ };
+
+ if (util_format_is_depth_or_stencil(tex->b.b.format)) {
+ bc = bordercolor;
}
+ else {
+ bc = sampler->border_color;
+ }
+
+ /* 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.
+ */
+ ret = upload_default_color(brw,
+ bc,
+ &brw->wm.sdc_bo[i]);
+ if (ret)
+ return ret;
}
+
+ return PIPE_OK;
}
-/* 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.
+
+
+/* All samplers must be uploaded in a single contiguous array.
*/
-static void upload_wm_samplers( struct brw_context *brw )
+static int upload_wm_samplers( struct brw_context *brw )
{
struct wm_sampler_key key;
+ struct brw_winsys_reloc reloc[BRW_MAX_TEX_UNIT];
+ enum pipe_error ret;
int i;
+ brw_wm_sampler_update_default_colors(brw);
brw_wm_sampler_populate_key(brw, &key);
if (brw->wm.sampler_count != key.sampler_count) {
brw->state.dirty.cache |= CACHE_NEW_SAMPLER;
}
- brw->sws->bo_unreference(brw->wm.sampler_bo);
- brw->wm.sampler_bo = NULL;
- if (brw->wm.sampler_count == 0)
- return;
+ if (brw->wm.sampler_count == 0) {
+ bo_reference(&brw->wm.sampler_bo, NULL);
+ return PIPE_OK;
+ }
+
+ /* Emit SDC relocations */
+ for (i = 0; i < key.sampler_count; i++) {
+ make_reloc( &reloc[i],
+ BRW_USAGE_SAMPLER,
+ 0,
+ i * sizeof(struct brw_sampler_state) +
+ offsetof(struct brw_sampler_state, ss2),
+ brw->wm.sdc_bo[i]);
+ }
+
- brw->wm.sampler_bo = brw_search_cache(&brw->cache, BRW_SAMPLER,
- &key, sizeof(key),
- brw->wm.sdc_bo, key.sampler_count,
- NULL);
+ if (brw_search_cache(&brw->cache, BRW_SAMPLER,
+ &key, sizeof(key),
+ reloc, key.sampler_count,
+ NULL,
+ &brw->wm.sampler_bo))
+ return PIPE_OK;
/* 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];
+ ret = brw_upload_cache(&brw->cache, BRW_SAMPLER,
+ &key, sizeof(key),
+ reloc, key.sampler_count,
+ &key.sampler, sizeof(key.sampler),
+ NULL, NULL,
+ &brw->wm.sampler_bo);
+ if (ret)
+ return ret;
- 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(&key.sampler[i], brw->wm.sdc_bo[i],
- &sampler[i]);
- }
-
- brw->wm.sampler_bo = brw_upload_cache(&brw->cache, BRW_SAMPLER,
- &key, sizeof(key),
- brw->wm.sdc_bo, key.sampler_count,
- &sampler, sizeof(sampler),
- NULL, NULL);
-
- /* Emit SDC relocations */
- for (i = 0; i < BRW_MAX_TEX_UNIT; i++) {
- if (!ctx->Texture.Unit[i]._ReallyEnabled)
- continue;
-
- dri_bo_emit_reloc(brw->wm.sampler_bo,
- I915_GEM_DOMAIN_SAMPLER, 0,
- 0,
- i * sizeof(struct brw_sampler_state) +
- offsetof(struct brw_sampler_state, ss2),
- brw->wm.sdc_bo[i]);
- }
- }
+ return 0;
}
const struct brw_tracked_state brw_wm_samplers = {
.dirty = {
- .mesa = _NEW_TEXTURE,
+ .mesa = PIPE_NEW_BOUND_TEXTURES | PIPE_NEW_SAMPLERS,
.brw = 0,
.cache = 0
},