diff options
Diffstat (limited to 'src/gallium/drivers/ilo/ilo_state.c')
-rw-r--r-- | src/gallium/drivers/ilo/ilo_state.c | 328 |
1 files changed, 322 insertions, 6 deletions
diff --git a/src/gallium/drivers/ilo/ilo_state.c b/src/gallium/drivers/ilo/ilo_state.c index 048152158eb..0a568bfbdc2 100644 --- a/src/gallium/drivers/ilo/ilo_state.c +++ b/src/gallium/drivers/ilo/ilo_state.c @@ -28,6 +28,7 @@ #include "core/ilo_builder_3d.h" /* for gen6_3d_translate_pipe_prim() */ #include "core/ilo_format.h" #include "core/ilo_state_3d.h" +#include "util/u_dual_blend.h" #include "util/u_dynarray.h" #include "util/u_helpers.h" #include "util/u_resource.h" @@ -160,6 +161,112 @@ ilo_translate_half_pixel_center(bool half_pixel_center) return (half_pixel_center) ? GEN6_PIXLOC_CENTER : GEN6_PIXLOC_UL_CORNER; } +static enum gen_compare_function +ilo_translate_compare_func(unsigned func) +{ + switch (func) { + case PIPE_FUNC_NEVER: return GEN6_COMPAREFUNCTION_NEVER; + case PIPE_FUNC_LESS: return GEN6_COMPAREFUNCTION_LESS; + case PIPE_FUNC_EQUAL: return GEN6_COMPAREFUNCTION_EQUAL; + case PIPE_FUNC_LEQUAL: return GEN6_COMPAREFUNCTION_LEQUAL; + case PIPE_FUNC_GREATER: return GEN6_COMPAREFUNCTION_GREATER; + case PIPE_FUNC_NOTEQUAL: return GEN6_COMPAREFUNCTION_NOTEQUAL; + case PIPE_FUNC_GEQUAL: return GEN6_COMPAREFUNCTION_GEQUAL; + case PIPE_FUNC_ALWAYS: return GEN6_COMPAREFUNCTION_ALWAYS; + default: + assert(!"unknown compare function"); + return GEN6_COMPAREFUNCTION_NEVER; + } +} + +static enum gen_stencil_op +ilo_translate_stencil_op(unsigned stencil_op) +{ + switch (stencil_op) { + case PIPE_STENCIL_OP_KEEP: return GEN6_STENCILOP_KEEP; + case PIPE_STENCIL_OP_ZERO: return GEN6_STENCILOP_ZERO; + case PIPE_STENCIL_OP_REPLACE: return GEN6_STENCILOP_REPLACE; + case PIPE_STENCIL_OP_INCR: return GEN6_STENCILOP_INCRSAT; + case PIPE_STENCIL_OP_DECR: return GEN6_STENCILOP_DECRSAT; + case PIPE_STENCIL_OP_INCR_WRAP: return GEN6_STENCILOP_INCR; + case PIPE_STENCIL_OP_DECR_WRAP: return GEN6_STENCILOP_DECR; + case PIPE_STENCIL_OP_INVERT: return GEN6_STENCILOP_INVERT; + default: + assert(!"unknown stencil op"); + return GEN6_STENCILOP_KEEP; + } +} + +static enum gen_logic_op +ilo_translate_logicop(unsigned logicop) +{ + switch (logicop) { + case PIPE_LOGICOP_CLEAR: return GEN6_LOGICOP_CLEAR; + case PIPE_LOGICOP_NOR: return GEN6_LOGICOP_NOR; + case PIPE_LOGICOP_AND_INVERTED: return GEN6_LOGICOP_AND_INVERTED; + case PIPE_LOGICOP_COPY_INVERTED: return GEN6_LOGICOP_COPY_INVERTED; + case PIPE_LOGICOP_AND_REVERSE: return GEN6_LOGICOP_AND_REVERSE; + case PIPE_LOGICOP_INVERT: return GEN6_LOGICOP_INVERT; + case PIPE_LOGICOP_XOR: return GEN6_LOGICOP_XOR; + case PIPE_LOGICOP_NAND: return GEN6_LOGICOP_NAND; + case PIPE_LOGICOP_AND: return GEN6_LOGICOP_AND; + case PIPE_LOGICOP_EQUIV: return GEN6_LOGICOP_EQUIV; + case PIPE_LOGICOP_NOOP: return GEN6_LOGICOP_NOOP; + case PIPE_LOGICOP_OR_INVERTED: return GEN6_LOGICOP_OR_INVERTED; + case PIPE_LOGICOP_COPY: return GEN6_LOGICOP_COPY; + case PIPE_LOGICOP_OR_REVERSE: return GEN6_LOGICOP_OR_REVERSE; + case PIPE_LOGICOP_OR: return GEN6_LOGICOP_OR; + case PIPE_LOGICOP_SET: return GEN6_LOGICOP_SET; + default: + assert(!"unknown logicop function"); + return GEN6_LOGICOP_CLEAR; + } +} + +static int +ilo_translate_blend_func(unsigned blend) +{ + switch (blend) { + case PIPE_BLEND_ADD: return GEN6_BLENDFUNCTION_ADD; + case PIPE_BLEND_SUBTRACT: return GEN6_BLENDFUNCTION_SUBTRACT; + case PIPE_BLEND_REVERSE_SUBTRACT: return GEN6_BLENDFUNCTION_REVERSE_SUBTRACT; + case PIPE_BLEND_MIN: return GEN6_BLENDFUNCTION_MIN; + case PIPE_BLEND_MAX: return GEN6_BLENDFUNCTION_MAX; + default: + assert(!"unknown blend function"); + return GEN6_BLENDFUNCTION_ADD; + } +} + +static int +ilo_translate_blend_factor(unsigned factor) +{ + switch (factor) { + case PIPE_BLENDFACTOR_ONE: return GEN6_BLENDFACTOR_ONE; + case PIPE_BLENDFACTOR_SRC_COLOR: return GEN6_BLENDFACTOR_SRC_COLOR; + case PIPE_BLENDFACTOR_SRC_ALPHA: return GEN6_BLENDFACTOR_SRC_ALPHA; + case PIPE_BLENDFACTOR_DST_ALPHA: return GEN6_BLENDFACTOR_DST_ALPHA; + case PIPE_BLENDFACTOR_DST_COLOR: return GEN6_BLENDFACTOR_DST_COLOR; + case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: return GEN6_BLENDFACTOR_SRC_ALPHA_SATURATE; + case PIPE_BLENDFACTOR_CONST_COLOR: return GEN6_BLENDFACTOR_CONST_COLOR; + case PIPE_BLENDFACTOR_CONST_ALPHA: return GEN6_BLENDFACTOR_CONST_ALPHA; + case PIPE_BLENDFACTOR_SRC1_COLOR: return GEN6_BLENDFACTOR_SRC1_COLOR; + case PIPE_BLENDFACTOR_SRC1_ALPHA: return GEN6_BLENDFACTOR_SRC1_ALPHA; + case PIPE_BLENDFACTOR_ZERO: return GEN6_BLENDFACTOR_ZERO; + case PIPE_BLENDFACTOR_INV_SRC_COLOR: return GEN6_BLENDFACTOR_INV_SRC_COLOR; + case PIPE_BLENDFACTOR_INV_SRC_ALPHA: return GEN6_BLENDFACTOR_INV_SRC_ALPHA; + case PIPE_BLENDFACTOR_INV_DST_ALPHA: return GEN6_BLENDFACTOR_INV_DST_ALPHA; + case PIPE_BLENDFACTOR_INV_DST_COLOR: return GEN6_BLENDFACTOR_INV_DST_COLOR; + case PIPE_BLENDFACTOR_INV_CONST_COLOR: return GEN6_BLENDFACTOR_INV_CONST_COLOR; + case PIPE_BLENDFACTOR_INV_CONST_ALPHA: return GEN6_BLENDFACTOR_INV_CONST_ALPHA; + case PIPE_BLENDFACTOR_INV_SRC1_COLOR: return GEN6_BLENDFACTOR_INV_SRC1_COLOR; + case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: return GEN6_BLENDFACTOR_INV_SRC1_ALPHA; + default: + assert(!"unknown blend factor"); + return GEN6_BLENDFACTOR_ONE; + } +} + static void finalize_shader_states(struct ilo_state_vector *vec) { @@ -466,6 +573,98 @@ finalize_rasterizer(struct ilo_context *ilo) } } +static bool +finalize_blend_rt(struct ilo_context *ilo) +{ + struct ilo_state_vector *vec = &ilo->state_vector; + const struct ilo_fb_state *fb = &vec->fb; + struct ilo_blend_state *blend = vec->blend; + struct ilo_state_cc_blend_info *info = &vec->blend->info.blend; + bool changed = false; + unsigned i; + + if (!(vec->dirty & (ILO_DIRTY_FB | ILO_DIRTY_BLEND))) + return false; + + /* set up one for dummy RT writes */ + if (!fb->state.nr_cbufs) { + if (info->rt != &blend->dummy_rt) { + info->rt = &blend->dummy_rt; + info->rt_count = 1; + changed = true; + } + + return changed; + } + + if (info->rt != blend->effective_rt || + info->rt_count != fb->state.nr_cbufs) { + info->rt = blend->effective_rt; + info->rt_count = fb->state.nr_cbufs; + changed = true; + } + + for (i = 0; i < fb->state.nr_cbufs; i++) { + const struct ilo_fb_blend_caps *caps = &fb->blend_caps[i]; + struct ilo_state_cc_blend_rt_info *rt = &blend->effective_rt[i]; + /* ignore logicop when not UNORM */ + const bool logicop_enable = + (blend->rt[i].logicop_enable && caps->is_unorm); + + if (rt->cv_is_unorm != caps->is_unorm || + rt->cv_is_integer != caps->is_integer || + rt->logicop_enable != logicop_enable || + rt->force_dst_alpha_one != caps->force_dst_alpha_one) { + rt->cv_is_unorm = caps->is_unorm; + rt->cv_is_integer = caps->is_integer; + rt->logicop_enable = logicop_enable; + rt->force_dst_alpha_one = caps->force_dst_alpha_one; + + changed = true; + } + } + + return changed; +} + +static void +finalize_blend(struct ilo_context *ilo) +{ + const struct ilo_dev *dev = ilo->dev; + struct ilo_state_vector *vec = &ilo->state_vector; + struct ilo_blend_state *blend = vec->blend; + struct ilo_state_cc_info *info = &blend->info; + const bool sample_count_one = (vec->fb.num_samples <= 1); + const bool float_source0_alpha = + (!vec->fb.state.nr_cbufs || !vec->fb.state.cbufs[0] || + !util_format_is_pure_integer(vec->fb.state.cbufs[0]->format)); + + /* check for non-orthogonal states */ + if (finalize_blend_rt(ilo) || + info->alpha.cv_sample_count_one != sample_count_one || + info->alpha.cv_float_source0_alpha != float_source0_alpha || + info->alpha.test_enable != vec->dsa->alpha_test || + info->alpha.test_func != vec->dsa->alpha_func || + memcmp(&info->stencil, &vec->dsa->stencil, sizeof(info->stencil)) || + memcmp(&info->depth, &vec->dsa->depth, sizeof(info->depth)) || + memcmp(&info->params, &vec->cc_params, sizeof(info->params))) { + info->alpha.cv_sample_count_one = sample_count_one; + info->alpha.cv_float_source0_alpha = float_source0_alpha; + info->alpha.test_enable = vec->dsa->alpha_test; + info->alpha.test_func = vec->dsa->alpha_func; + info->stencil = vec->dsa->stencil; + info->depth = vec->dsa->depth; + info->params = vec->cc_params; + + ilo_state_cc_set_info(&blend->cc, dev, info); + + blend->alpha_may_kill = (info->alpha.alpha_to_coverage || + info->alpha.test_enable); + + vec->dirty |= ILO_DIRTY_BLEND; + } +} + /** * Finalize states. Some states depend on other states and are * incomplete/invalid until finalized. @@ -483,6 +682,7 @@ ilo_finalize_3d_states(struct ilo_context *ilo, finalize_rasterizer(ilo); finalize_viewport(ilo); + finalize_blend(ilo); u_upload_unmap(ilo->uploader); } @@ -526,12 +726,79 @@ ilo_create_blend_state(struct pipe_context *pipe, const struct pipe_blend_state *state) { const struct ilo_dev *dev = ilo_context(pipe)->dev; + struct ilo_state_cc_info *info; struct ilo_blend_state *blend; + int i; - blend = MALLOC_STRUCT(ilo_blend_state); + blend = CALLOC_STRUCT(ilo_blend_state); assert(blend); - ilo_gpe_init_blend(dev, state, blend); + info = &blend->info; + + info->alpha.cv_float_source0_alpha = true; + info->alpha.cv_sample_count_one = true; + info->alpha.alpha_to_one = state->alpha_to_one; + info->alpha.alpha_to_coverage = state->alpha_to_coverage; + info->alpha.test_enable = false; + info->alpha.test_func = GEN6_COMPAREFUNCTION_ALWAYS; + + info->stencil.cv_has_buffer = true; + info->depth.cv_has_buffer= true; + + info->blend.rt = blend->effective_rt; + info->blend.rt_count = 1; + info->blend.dither_enable = state->dither; + + for (i = 0; i < ARRAY_SIZE(blend->rt); i++) { + const struct pipe_rt_blend_state *rt = &state->rt[i]; + struct ilo_state_cc_blend_rt_info *rt_info = &blend->rt[i]; + + rt_info->cv_has_buffer = true; + rt_info->cv_is_unorm = true; + rt_info->cv_is_integer = false; + + /* logic op takes precedence over blending */ + if (state->logicop_enable) { + rt_info->logicop_enable = true; + rt_info->logicop_func = ilo_translate_logicop(state->logicop_func); + } else if (rt->blend_enable) { + rt_info->blend_enable = true; + + rt_info->rgb_src = ilo_translate_blend_factor(rt->rgb_src_factor); + rt_info->rgb_dst = ilo_translate_blend_factor(rt->rgb_dst_factor); + rt_info->rgb_func = ilo_translate_blend_func(rt->rgb_func); + + rt_info->a_src = ilo_translate_blend_factor(rt->alpha_src_factor); + rt_info->a_dst = ilo_translate_blend_factor(rt->alpha_dst_factor); + rt_info->a_func = ilo_translate_blend_func(rt->alpha_func); + } + + if (!(rt->colormask & PIPE_MASK_A)) + rt_info->argb_write_disables |= (1 << 3); + if (!(rt->colormask & PIPE_MASK_R)) + rt_info->argb_write_disables |= (1 << 2); + if (!(rt->colormask & PIPE_MASK_G)) + rt_info->argb_write_disables |= (1 << 1); + if (!(rt->colormask & PIPE_MASK_B)) + rt_info->argb_write_disables |= (1 << 0); + + if (!state->independent_blend_enable) { + for (i = 1; i < ARRAY_SIZE(blend->rt); i++) + blend->rt[i] = *rt_info; + break; + } + } + + memcpy(blend->effective_rt, blend->rt, sizeof(blend->rt)); + + blend->dummy_rt.argb_write_disables = 0xf; + + if (!ilo_state_cc_init(&blend->cc, dev, &blend->info)) { + FREE(blend); + return NULL; + } + + blend->dual_blend = util_blend_state_is_dual(state, 0); return blend; } @@ -814,13 +1081,48 @@ static void * ilo_create_depth_stencil_alpha_state(struct pipe_context *pipe, const struct pipe_depth_stencil_alpha_state *state) { - const struct ilo_dev *dev = ilo_context(pipe)->dev; struct ilo_dsa_state *dsa; + int i; - dsa = MALLOC_STRUCT(ilo_dsa_state); + dsa = CALLOC_STRUCT(ilo_dsa_state); assert(dsa); - ilo_gpe_init_dsa(dev, state, dsa); + dsa->depth.cv_has_buffer = true; + dsa->depth.test_enable = state->depth.enabled; + dsa->depth.write_enable = state->depth.writemask; + dsa->depth.test_func = ilo_translate_compare_func(state->depth.func); + + dsa->stencil.cv_has_buffer = true; + for (i = 0; i < ARRAY_SIZE(state->stencil); i++) { + const struct pipe_stencil_state *stencil = &state->stencil[i]; + struct ilo_state_cc_stencil_op_info *op; + + if (!stencil->enabled) + break; + + if (i == 0) { + dsa->stencil.test_enable = true; + dsa->stencil_front.test_mask = stencil->valuemask; + dsa->stencil_front.write_mask = stencil->writemask; + + op = &dsa->stencil.front; + } else { + dsa->stencil.twosided_enable = true; + dsa->stencil_back.test_mask = stencil->valuemask; + dsa->stencil_back.write_mask = stencil->writemask; + + op = &dsa->stencil.back; + } + + op->test_func = ilo_translate_compare_func(stencil->func); + op->fail_op = ilo_translate_stencil_op(stencil->fail_op); + op->zfail_op = ilo_translate_stencil_op(stencil->zfail_op); + op->zpass_op = ilo_translate_stencil_op(stencil->zpass_op); + } + + dsa->alpha_test = state->alpha.enabled; + dsa->alpha_ref = state->alpha.ref_value; + dsa->alpha_func = ilo_translate_compare_func(state->alpha.func); return dsa; } @@ -831,6 +1133,17 @@ ilo_bind_depth_stencil_alpha_state(struct pipe_context *pipe, void *state) struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector; vec->dsa = state; + if (vec->dsa) { + vec->cc_params.alpha_ref = vec->dsa->alpha_ref; + vec->cc_params.stencil_front.test_mask = + vec->dsa->stencil_front.test_mask; + vec->cc_params.stencil_front.write_mask = + vec->dsa->stencil_front.write_mask; + vec->cc_params.stencil_back.test_mask = + vec->dsa->stencil_back.test_mask; + vec->cc_params.stencil_back.write_mask = + vec->dsa->stencil_back.write_mask; + } vec->dirty |= ILO_DIRTY_DSA; } @@ -990,7 +1303,7 @@ ilo_set_blend_color(struct pipe_context *pipe, { struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector; - vec->blend_color = *state; + memcpy(vec->cc_params.blend_rgba, state->color, sizeof(state->color)); vec->dirty |= ILO_DIRTY_BLEND_COLOR; } @@ -1007,6 +1320,9 @@ ilo_set_stencil_ref(struct pipe_context *pipe, vec->stencil_ref = *state; + vec->cc_params.stencil_front.test_ref = state->ref_value[0]; + vec->cc_params.stencil_back.test_ref = state->ref_value[1]; + vec->dirty |= ILO_DIRTY_STENCIL_REF; } |