const struct pipe_blend_state *blend)
{
struct panfrost_context *ctx = pan_context(pipe);
+ struct panfrost_device *dev = pan_device(pipe->screen);
struct panfrost_blend_state *so = rzalloc(ctx, struct panfrost_blend_state);
so->base = *blend;
for (unsigned c = 0; c < so->pan.rt_count; ++c) {
unsigned g = blend->independent_blend_enable ? c : 0;
- const struct pipe_rt_blend_state *pipe = &blend->rt[g];
- struct pan_blend_equation *equation = &so->pan.rts[c].equation;
-
- equation->color_mask = pipe->colormask;
- equation->blend_enable = pipe->blend_enable;
- if (!equation->blend_enable)
- continue;
-
- equation->rgb_func = util_blend_func_to_shader(pipe->rgb_func);
- equation->rgb_src_factor = util_blend_factor_to_shader(pipe->rgb_src_factor);
- equation->rgb_invert_src_factor = util_blend_factor_is_inverted(pipe->rgb_src_factor);
- equation->rgb_dst_factor = util_blend_factor_to_shader(pipe->rgb_dst_factor);
- equation->rgb_invert_dst_factor = util_blend_factor_is_inverted(pipe->rgb_dst_factor);
- equation->alpha_func = util_blend_func_to_shader(pipe->alpha_func);
- equation->alpha_src_factor = util_blend_factor_to_shader(pipe->alpha_src_factor);
- equation->alpha_invert_src_factor = util_blend_factor_is_inverted(pipe->alpha_src_factor);
- equation->alpha_dst_factor = util_blend_factor_to_shader(pipe->alpha_dst_factor);
- equation->alpha_invert_dst_factor = util_blend_factor_is_inverted(pipe->alpha_dst_factor);
+ const struct pipe_rt_blend_state pipe = blend->rt[g];
+ struct pan_blend_equation equation;
+
+ equation.color_mask = pipe.colormask;
+ equation.blend_enable = pipe.blend_enable;
+
+ if (pipe.blend_enable) {
+ equation.rgb_func = util_blend_func_to_shader(pipe.rgb_func);
+ equation.rgb_src_factor = util_blend_factor_to_shader(pipe.rgb_src_factor);
+ equation.rgb_invert_src_factor = util_blend_factor_is_inverted(pipe.rgb_src_factor);
+ equation.rgb_dst_factor = util_blend_factor_to_shader(pipe.rgb_dst_factor);
+ equation.rgb_invert_dst_factor = util_blend_factor_is_inverted(pipe.rgb_dst_factor);
+ equation.alpha_func = util_blend_func_to_shader(pipe.alpha_func);
+ equation.alpha_src_factor = util_blend_factor_to_shader(pipe.alpha_src_factor);
+ equation.alpha_invert_src_factor = util_blend_factor_is_inverted(pipe.alpha_src_factor);
+ equation.alpha_dst_factor = util_blend_factor_to_shader(pipe.alpha_dst_factor);
+ equation.alpha_invert_dst_factor = util_blend_factor_is_inverted(pipe.alpha_dst_factor);
+ }
+
+ /* Determine some common properties */
+ unsigned constant_mask = pan_blend_constant_mask(equation);
+ so->info[c] = (struct pan_blend_info) {
+ .no_colour = (equation.color_mask == 0),
+ .opaque = pan_blend_is_opaque(equation),
+ .constant_mask = constant_mask,
+
+ /* TODO: check the dest for the logicop */
+ .load_dest = blend->logicop_enable ||
+ pan_blend_reads_dest(equation),
+
+ /* Could this possibly be fixed-function? */
+ .fixed_function = !blend->logicop_enable &&
+ pan_blend_can_fixed_function(equation) &&
+ (!constant_mask ||
+ pan_blend_supports_constant(dev->arch, c))
+ };
+
+ so->pan.rts[c].equation = equation;
}
return so;
/* First, we'll try fixed function, matching equation and constant */
const struct pan_blend_equation eq = pan_blend.rts[rti].equation;
- unsigned constant_mask = pan_blend_constant_mask(eq);
+ bool ff = blend->info[rti].fixed_function;
- bool ff = pan_blend_can_fixed_function(eq);
- ff &= pan_blend_is_homogenous_constant(constant_mask, ctx->blend_color.color);
- ff &= (pan_blend_supports_constant(dev->arch, rti) || !constant_mask);
- ff &= !pan_blend.logicop_enable;
+ /* Not all formats are blendable, check if this one is */
ff &= panfrost_blendable_formats[fmt].internal;
+ /* There are hazards around constants, check that */
+ ff &= pan_blend_is_homogenous_constant(blend->info[rti].constant_mask,
+ ctx->blend_color.color);
+
if (ff) {
struct panfrost_blend_final final = {
- .load_dest = pan_blend_reads_dest(pan_blend.rts[rti].equation),
- .equation.constant = pan_blend_get_constant(constant_mask, ctx->blend_color.color),
- .opaque = pan_blend_is_opaque(pan_blend.rts[rti].equation),
- .no_colour = pan_blend.rts[rti].equation.color_mask == 0,
+ .equation.constant = pan_blend_get_constant(
+ blend->info[rti].constant_mask,
+ ctx->blend_color.color),
};
pan_blend_to_fixed_function_equation(eq, &final.equation.equation);
.first_tag = shader->first_tag,
.gpu = (*bo)->ptr.gpu + *shader_offset,
},
- .load_dest = pan_blend.logicop_enable ||
- pan_blend_reads_dest(pan_blend.rts[rti].equation),
};
*shader_offset += shader->binary.size;
static bool
panfrost_fs_required(
struct panfrost_shader_state *fs,
- struct panfrost_blend_final *blend,
+ struct panfrost_blend_state *blend,
struct pipe_framebuffer_state *state)
{
/* If we generally have side effects */
/* If colour is written we need to execute */
for (unsigned i = 0; i < state->nr_cbufs; ++i) {
- if (!blend[i].no_colour && state->cbufs[i])
+ if (state->cbufs[i] && !blend->info[i].no_colour)
return true;
}
void *rts)
{
unsigned rt_count = batch->key.nr_cbufs;
- const struct panfrost_device *dev = pan_device(batch->ctx->base.screen);
- struct panfrost_shader_state *fs = panfrost_get_shader_state(batch->ctx, PIPE_SHADER_FRAGMENT);
+ struct panfrost_context *ctx = batch->ctx;
+ const struct panfrost_blend_state *so = ctx->blend;
+ const struct panfrost_device *dev = pan_device(ctx->base.screen);
+ struct panfrost_shader_state *fs = panfrost_get_shader_state(ctx, PIPE_SHADER_FRAGMENT);
/* Always have at least one render target for depth-only passes */
for (unsigned i = 0; i < MAX2(rt_count, 1); ++i) {
}
pan_pack(rts + i * MALI_BLEND_LENGTH, BLEND, cfg) {
- if (blend[i].no_colour) {
+ struct pan_blend_info info = so->info[i];
+
+ if (info.no_colour) {
cfg.enable = false;
} else {
cfg.srgb = util_format_is_srgb(batch->key.cbufs[i]->format);
- cfg.load_destination = blend[i].load_dest;
+ cfg.load_destination = info.load_dest;
- cfg.round_to_fb_precision = !batch->ctx->blend->base.dither;
- cfg.alpha_to_one = batch->ctx->blend->base.alpha_to_one;
+ cfg.round_to_fb_precision = !ctx->blend->base.dither;
+ cfg.alpha_to_one = ctx->blend->base.alpha_to_one;
}
if (blend[i].is_shader) {
constant <<= 16 - chan_size;
cfg.bifrost.constant = constant;
- if (blend[i].opaque)
- cfg.bifrost.internal.mode = MALI_BIFROST_BLEND_MODE_OPAQUE;
- else
- cfg.bifrost.internal.mode = MALI_BIFROST_BLEND_MODE_FIXED_FUNCTION;
+ cfg.bifrost.internal.mode = info.opaque ?
+ MALI_BIFROST_BLEND_MODE_OPAQUE :
+ MALI_BIFROST_BLEND_MODE_FIXED_FUNCTION;
/* If we want the conversion to work properly,
* num_comps must be set to 4
void *rts)
{
unsigned rt_count = batch->key.nr_cbufs;
+ struct panfrost_context *ctx = batch->ctx;
+ const struct panfrost_blend_state *so = ctx->blend;
/* Always have at least one render target for depth-only passes */
for (unsigned i = 0; i < MAX2(rt_count, 1); ++i) {
}
pan_pack(rts + i * MALI_BLEND_LENGTH, BLEND, cfg) {
- if (blend[i].no_colour) {
+ struct pan_blend_info info = so->info[i];
+
+ if (info.no_colour) {
cfg.enable = false;
continue;
}
cfg.srgb = util_format_is_srgb(batch->key.cbufs[i]->format);
- cfg.load_destination = blend[i].load_dest;
- cfg.round_to_fb_precision = !batch->ctx->blend->base.dither;
- cfg.alpha_to_one = batch->ctx->blend->base.alpha_to_one;
+ cfg.load_destination = info.load_dest;
+ cfg.round_to_fb_precision = !ctx->blend->base.dither;
+ cfg.alpha_to_one = ctx->blend->base.alpha_to_one;
cfg.midgard.blend_shader = blend[i].is_shader;
if (blend[i].is_shader) {
cfg.midgard.shader_pc = blend[i].shader.gpu | blend[i].shader.first_tag;
struct panfrost_blend_final *blend)
{
const struct panfrost_device *dev = pan_device(batch->ctx->base.screen);
+ struct panfrost_blend_state *so = batch->ctx->blend;
if (pan_is_bifrost(dev))
panfrost_emit_bifrost_blend(batch, blend, rts);
panfrost_emit_midgard_blend(batch, blend, rts);
for (unsigned i = 0; i < batch->key.nr_cbufs; ++i) {
- if (!blend[i].no_colour && batch->key.cbufs[i]) {
+ if (!so->info[i].no_colour && batch->key.cbufs[i]) {
batch->draws |= (PIPE_CLEAR_COLOR0 << i);
batch->resolve |= (PIPE_CLEAR_COLOR0 << i);
}
{
const struct panfrost_device *dev = pan_device(ctx->base.screen);
struct panfrost_shader_state *fs = panfrost_get_shader_state(ctx, PIPE_SHADER_FRAGMENT);
- bool alpha_to_coverage = ctx->blend->base.alpha_to_coverage;
+ struct panfrost_blend_state *so = ctx->blend;
+ bool alpha_to_coverage = so->base.alpha_to_coverage;
- if (!panfrost_fs_required(fs, blend, &ctx->pipe_framebuffer)) {
+ if (!panfrost_fs_required(fs, so, &ctx->pipe_framebuffer)) {
state->properties.bifrost.shader_modifies_coverage = true;
state->properties.bifrost.allow_forward_pixel_to_kill = true;
state->properties.bifrost.allow_forward_pixel_to_be_killed = true;
for (unsigned i = 0; i < ctx->pipe_framebuffer.nr_cbufs; ++i) {
if (ctx->pipe_framebuffer.cbufs[i]) {
rt_mask |= (1 << i);
- blend_reads_dest |= blend[i].load_dest;
+ blend_reads_dest |= so->info[i].load_dest;
}
}
unsigned rt_count = ctx->pipe_framebuffer.nr_cbufs;
bool alpha_to_coverage = ctx->blend->base.alpha_to_coverage;
- if (!panfrost_fs_required(fs, blend, &ctx->pipe_framebuffer)) {
+ if (!panfrost_fs_required(fs, ctx->blend, &ctx->pipe_framebuffer)) {
state->shader.shader = 0x1;
state->properties.midgard.work_register_count = 1;
state->properties.depth_source = MALI_DEPTH_SOURCE_FIXED_FUNCTION;
}
if (dev->quirks & MIDGARD_SFBD && ctx->pipe_framebuffer.nr_cbufs > 0) {
- state->multisample_misc.sfbd_load_destination = blend[0].load_dest;
+ struct panfrost_blend_state *so = ctx->blend;
+ state->multisample_misc.sfbd_load_destination = so->info[0].load_dest;
state->multisample_misc.sfbd_blend_shader = blend[0].is_shader;
- state->stencil_mask_misc.sfbd_write_enable = !blend[0].no_colour;
+ state->stencil_mask_misc.sfbd_write_enable = !so->info[0].no_colour;
state->stencil_mask_misc.sfbd_srgb = util_format_is_srgb(ctx->pipe_framebuffer.cbufs[0]->format);
- state->stencil_mask_misc.sfbd_dither_disable = !ctx->blend->base.dither;
- state->stencil_mask_misc.sfbd_alpha_to_one = ctx->blend->base.alpha_to_one;
+ state->stencil_mask_misc.sfbd_dither_disable = !so->base.dither;
+ state->stencil_mask_misc.sfbd_alpha_to_one = so->base.alpha_to_one;
if (blend[0].is_shader) {
state->sfbd_blend_shader = blend[0].shader.gpu |