diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c index 111de3f0e24..2684c75e1ce 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.c +++ b/src/gallium/auxiliary/cso_cache/cso_context.c @@ -68,6 +68,7 @@ struct cso_context { struct u_vbuf *vbuf; struct u_vbuf *vbuf_current; bool always_use_vbuf; + bool sampler_format; boolean has_geometry_shader; boolean has_tessellation; @@ -285,6 +286,10 @@ cso_create_context(struct pipe_context *pipe, unsigned flags) ctx->has_streamout = TRUE; } + if (pipe->screen->get_param(pipe->screen, PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK) & + PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_FREEDRENO) + ctx->sampler_format = true; + ctx->max_fs_samplerviews = pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_FRAGMENT, PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS); @@ -1208,11 +1213,10 @@ cso_set_vertex_buffers_and_elements(struct cso_context *ctx, cso_set_vertex_elements_direct(ctx, velems); } -static bool -cso_set_sampler(struct cso_context *ctx, enum pipe_shader_type shader_stage, - unsigned idx, const struct pipe_sampler_state *templ) +ALWAYS_INLINE static struct cso_sampler * +set_sampler(struct cso_context *ctx, enum pipe_shader_type shader_stage, + unsigned idx, const struct pipe_sampler_state *templ, size_t key_size) { - unsigned key_size = sizeof(struct pipe_sampler_state); unsigned hash_key = cso_construct_key((void*)templ, key_size); struct cso_sampler *cso; struct cso_hash_iter iter = @@ -1237,7 +1241,14 @@ cso_set_sampler(struct cso_context *ctx, enum pipe_shader_type shader_stage, } else { cso = cso_hash_iter_data(iter); } + return cso; +} +ALWAYS_INLINE static bool +cso_set_sampler(struct cso_context *ctx, enum pipe_shader_type shader_stage, + unsigned idx, const struct pipe_sampler_state *templ, size_t size) +{ + struct cso_sampler *cso = set_sampler(ctx, shader_stage, idx, templ, size); ctx->samplers[shader_stage].cso_samplers[idx] = cso; ctx->samplers[shader_stage].samplers[idx] = cso->data; return true; @@ -1247,7 +1258,9 @@ void cso_single_sampler(struct cso_context *ctx, enum pipe_shader_type shader_stage, unsigned idx, const struct pipe_sampler_state *templ) { - if (cso_set_sampler(ctx, shader_stage, idx, templ)) + size_t size = ctx->sampler_format ? sizeof(struct pipe_sampler_state) : + offsetof(struct pipe_sampler_state, border_color_format); + if (cso_set_sampler(ctx, shader_stage, idx, templ, size)) ctx->max_sampler_seen = MAX2(ctx->max_sampler_seen, (int)idx); } @@ -1269,20 +1282,14 @@ cso_single_sampler_done(struct cso_context *ctx, ctx->max_sampler_seen = -1; } - -/* - * If the function encouters any errors it will return the - * last one. Done to always try to set as many samplers - * as possible. - */ -void -cso_set_samplers(struct cso_context *ctx, - enum pipe_shader_type shader_stage, - unsigned nr, - const struct pipe_sampler_state **templates) +ALWAYS_INLINE static int +set_samplers(struct cso_context *ctx, + enum pipe_shader_type shader_stage, + unsigned nr, + const struct pipe_sampler_state **templates, + size_t key_size) { int last = -1; - for (unsigned i = 0; i < nr; i++) { if (!templates[i]) continue; @@ -1302,18 +1309,38 @@ cso_set_samplers(struct cso_context *ctx, */ if (last >= 0 && !memcmp(templates[i], templates[last], - sizeof(struct pipe_sampler_state))) { + key_size)) { ctx->samplers[shader_stage].cso_samplers[i] = ctx->samplers[shader_stage].cso_samplers[last]; ctx->samplers[shader_stage].samplers[i] = ctx->samplers[shader_stage].samplers[last]; } else { /* Look up the sampler state CSO. */ - cso_set_sampler(ctx, shader_stage, i, templates[i]); + cso_set_sampler(ctx, shader_stage, i, templates[i], key_size); } last = i; } + return last; +} + +/* + * If the function encouters any errors it will return the + * last one. Done to always try to set as many samplers + * as possible. + */ +void +cso_set_samplers(struct cso_context *ctx, + enum pipe_shader_type shader_stage, + unsigned nr, + const struct pipe_sampler_state **templates) +{ + int last = -1; + + /* ensure sampler size is a constant for memcmp */ + size_t size = ctx->sampler_format ? sizeof(struct pipe_sampler_state) : + offsetof(struct pipe_sampler_state, border_color_format); + last = set_samplers(ctx, shader_stage, nr, templates, size); ctx->max_sampler_seen = MAX2(ctx->max_sampler_seen, last); cso_single_sampler_done(ctx, shader_stage); diff --git a/src/gallium/auxiliary/driver_trace/tr_dump_state.c b/src/gallium/auxiliary/driver_trace/tr_dump_state.c index 6933f989db2..45a02a0bd15 100644 --- a/src/gallium/auxiliary/driver_trace/tr_dump_state.c +++ b/src/gallium/auxiliary/driver_trace/tr_dump_state.c @@ -549,6 +549,7 @@ void trace_dump_sampler_state(const struct pipe_sampler_state *state) trace_dump_member(float, state, min_lod); trace_dump_member(float, state, max_lod); trace_dump_member_array(float, state, border_color.f); + trace_dump_member(format, state, border_color_format); trace_dump_struct_end(); } diff --git a/src/gallium/frontends/nine/nine_pipe.c b/src/gallium/frontends/nine/nine_pipe.c index eaa91101a24..d35211ac221 100644 --- a/src/gallium/frontends/nine/nine_pipe.c +++ b/src/gallium/frontends/nine/nine_pipe.c @@ -251,6 +251,7 @@ nine_convert_sampler_state(struct cso_context *ctx, int idx, const DWORD *ss) samp.border_color_is_integer = 0; samp.reduction_mode = 0; samp.pad = 0; + samp.border_color_format = PIPE_FORMAT_NONE; d3dcolor_to_pipe_color_union(&samp.border_color, ss[D3DSAMP_BORDERCOLOR]); /* see nine_state.h */ diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h index e57693958b4..3a10ee0c847 100644 --- a/src/gallium/include/pipe/p_defines.h +++ b/src/gallium/include/pipe/p_defines.h @@ -1036,6 +1036,7 @@ enum pipe_texture_transfer_mode { #define PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50 (1 << 0) #define PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_R600 (1 << 1) +#define PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_FREEDRENO (1 << 2) enum pipe_endian { diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h index 46613808fd7..282a57a1028 100644 --- a/src/gallium/include/pipe/p_state.h +++ b/src/gallium/include/pipe/p_state.h @@ -426,6 +426,7 @@ struct pipe_sampler_state float lod_bias; /**< LOD/lambda bias */ float min_lod, max_lod; /**< LOD clamp range, after bias */ union pipe_color_union border_color; + enum pipe_format border_color_format; /**< only with PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_FREEDRENO, must be last */ }; union pipe_surface_desc { diff --git a/src/mesa/state_tracker/st_atom_sampler.c b/src/mesa/state_tracker/st_atom_sampler.c index 7aaaa22590b..bf6122cddea 100644 --- a/src/mesa/state_tracker/st_atom_sampler.c +++ b/src/mesa/state_tracker/st_atom_sampler.c @@ -128,6 +128,9 @@ st_convert_sampler(const struct st_context *st, } else { st_translate_color(&sampler->border_color, texBaseFormat, is_integer); + if (st->use_format_with_border_color) + sampler->border_color_format = st_get_sampler_view_format(st, texobj, + msamp->Attrib.sRGBDecode == GL_SKIP_DECODE_EXT); } sampler->border_color_is_integer = is_integer; } diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index b9c69e52409..d3fc9774b76 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -595,6 +595,9 @@ st_create_context_priv(struct gl_context *ctx, struct pipe_context *pipe, !!(screen->get_param(screen, PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK) & (PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50 | PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_R600)); + st->use_format_with_border_color = + !!(screen->get_param(screen, PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK) & + PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_FREEDRENO); st->emulate_gl_clamp = !screen->get_param(screen, PIPE_CAP_GL_CLAMP); st->texture_buffer_sampler = diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index 2f1f2f84f45..e90c170dcfb 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -185,6 +185,7 @@ struct st_context boolean needs_texcoord_semantic; boolean apply_texture_swizzle_to_border_color; + boolean use_format_with_border_color; boolean emulate_gl_clamp; boolean texture_buffer_sampler;