#include "util/u_memory.h" #include "util/u_math.h" #include "pipe/p_context.h" #include "pipe/p_state.h" #include "util/u_inlines.h" #include "brw_context.h" #include "brw_defines.h" /* 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( unsigned wrap ) { switch( wrap ) { case PIPE_TEX_WRAP_REPEAT: return BRW_TEXCOORDMODE_WRAP; case PIPE_TEX_WRAP_CLAMP: case PIPE_TEX_WRAP_CLAMP_TO_EDGE: return BRW_TEXCOORDMODE_CLAMP; case PIPE_TEX_WRAP_CLAMP_TO_BORDER: return BRW_TEXCOORDMODE_CLAMP_BORDER; case PIPE_TEX_WRAP_MIRROR_REPEAT: return BRW_TEXCOORDMODE_MIRROR; case PIPE_TEX_WRAP_MIRROR_CLAMP: case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: return BRW_TEXCOORDMODE_MIRROR_ONCE; default: return BRW_TEXCOORDMODE_WRAP; } } static GLuint translate_img_filter( unsigned filter ) { switch (filter) { case PIPE_TEX_FILTER_NEAREST: return BRW_MAPFILTER_NEAREST; case PIPE_TEX_FILTER_LINEAR: return BRW_MAPFILTER_LINEAR; default: assert(0); return BRW_MAPFILTER_NEAREST; } } static GLuint translate_mip_filter( unsigned filter ) { switch (filter) { case PIPE_TEX_MIPFILTER_NONE: return BRW_MIPFILTER_NONE; case PIPE_TEX_MIPFILTER_NEAREST: return BRW_MIPFILTER_NEAREST; case PIPE_TEX_MIPFILTER_LINEAR: return BRW_MIPFILTER_LINEAR; default: assert(0); return BRW_MIPFILTER_NONE; } } /* XXX: not sure why there are special translations for the shadow tex * compare functions. In particular ALWAYS is translated to NEVER. * Is this a hardware issue? Does i965 really suffer from this? */ static GLuint translate_shadow_compare_func( unsigned func ) { switch (func) { case PIPE_FUNC_NEVER: return BRW_COMPAREFUNCTION_ALWAYS; case PIPE_FUNC_LESS: return BRW_COMPAREFUNCTION_LEQUAL; case PIPE_FUNC_LEQUAL: return BRW_COMPAREFUNCTION_LESS; case PIPE_FUNC_GREATER: return BRW_COMPAREFUNCTION_GEQUAL; case PIPE_FUNC_GEQUAL: return BRW_COMPAREFUNCTION_GREATER; case PIPE_FUNC_NOTEQUAL: return BRW_COMPAREFUNCTION_EQUAL; case PIPE_FUNC_EQUAL: return BRW_COMPAREFUNCTION_NOTEQUAL; case PIPE_FUNC_ALWAYS: return BRW_COMPAREFUNCTION_NEVER; default: assert(0); return BRW_COMPAREFUNCTION_NEVER; } } static void * brw_create_sampler_state( struct pipe_context *pipe, const struct pipe_sampler_state *template ) { struct brw_sampler *sampler = CALLOC_STRUCT(brw_sampler); sampler->ss0.min_filter = translate_img_filter( template->min_img_filter ); sampler->ss0.mag_filter = translate_img_filter( template->mag_img_filter ); sampler->ss0.mip_filter = translate_mip_filter( template->min_mip_filter ); /* XXX: anisotropy logic slightly changed: */ if (template->max_anisotropy > 1) { sampler->ss0.min_filter = BRW_MAPFILTER_ANISOTROPIC; sampler->ss0.mag_filter = BRW_MAPFILTER_ANISOTROPIC; sampler->ss3.max_aniso = MIN2((template->max_anisotropy - 2) / 2, BRW_ANISORATIO_16); } sampler->ss1.r_wrap_mode = translate_wrap_mode(template->wrap_r); sampler->ss1.s_wrap_mode = translate_wrap_mode(template->wrap_s); sampler->ss1.t_wrap_mode = translate_wrap_mode(template->wrap_t); /* Set LOD bias: */ sampler->ss0.lod_bias = util_signed_fixed(CLAMP(template->lod_bias, -16, 15), 6); sampler->ss0.lod_preclamp = 1; /* OpenGL mode */ sampler->ss0.default_color_mode = 0; /* OpenGL/DX10 mode */ /* Set shadow function: */ if (template->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { /* 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 = translate_shadow_compare_func(template->compare_func); } /* Set BaseMipLevel, MaxLOD, MinLOD: */ sampler->ss0.base_level = util_unsigned_fixed(0, 1); sampler->ss1.max_lod = util_unsigned_fixed(CLAMP(template->max_lod, 0, 13), 6); sampler->ss1.min_lod = util_unsigned_fixed(CLAMP(template->min_lod, 0, 13), 6); return (void *)sampler; } static void brw_bind_sampler_state(struct pipe_context *pipe, unsigned num, void **sampler) { struct brw_context *brw = brw_context(pipe); int i; for (i = 0; i < num; i++) brw->curr.sampler[i] = sampler[i]; for (i = num; i < brw->curr.num_samplers; i++) brw->curr.sampler[i] = NULL; brw->curr.num_samplers = num; brw->state.dirty.mesa |= PIPE_NEW_SAMPLERS; } static void brw_delete_sampler_state(struct pipe_context *pipe, void *cso) { FREE(cso); } static void brw_set_fragment_sampler_views(struct pipe_context *pipe, unsigned num, struct pipe_sampler_view **views) { struct brw_context *brw = brw_context(pipe); int i; for (i = 0; i < num; i++) pipe_sampler_view_reference(&brw->curr.fragment_sampler_views[i], views[i]); for (i = num; i < brw->curr.num_fragment_sampler_views; i++) pipe_sampler_view_reference(&brw->curr.fragment_sampler_views[i], NULL); brw->curr.num_fragment_sampler_views = num; brw->state.dirty.mesa |= PIPE_NEW_BOUND_TEXTURES; } static void brw_set_vertex_sampler_views(struct pipe_context *pipe, unsigned num, struct pipe_sampler_view **views) { } static void brw_bind_vertex_sampler_state(struct pipe_context *pipe, unsigned num, void **sampler) { } static struct pipe_sampler_view * brw_create_sampler_view(struct pipe_context *pipe, struct pipe_resource *texture, const struct pipe_sampler_view *templ) { struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view); if (view) { *view = *templ; view->reference.count = 1; view->texture = NULL; pipe_resource_reference(&view->texture, texture); view->context = pipe; } return view; } static void brw_sampler_view_destroy(struct pipe_context *pipe, struct pipe_sampler_view *view) { pipe_resource_reference(&view->texture, NULL); FREE(view); } void brw_pipe_sampler_init( struct brw_context *brw ) { brw->base.create_sampler_state = brw_create_sampler_state; brw->base.delete_sampler_state = brw_delete_sampler_state; brw->base.set_fragment_sampler_views = brw_set_fragment_sampler_views; brw->base.bind_fragment_sampler_states = brw_bind_sampler_state; brw->base.set_vertex_sampler_views = brw_set_vertex_sampler_views; brw->base.bind_vertex_sampler_states = brw_bind_vertex_sampler_state; brw->base.create_sampler_view = brw_create_sampler_view; brw->base.sampler_view_destroy = brw_sampler_view_destroy; } void brw_pipe_sampler_cleanup( struct brw_context *brw ) { }