* befast, suitable for calling every draw to avoid wacky dirty
* tracking paths. If the cache hits, boom, done. */
-static struct panfrost_blend_shader *
+struct panfrost_blend_shader *
panfrost_get_blend_shader(
struct panfrost_context *ctx,
struct panfrost_blend_state *blend,
so->base = *blend;
/* TODO: The following features are not yet implemented */
- assert(!blend->logicop_enable);
- assert(!blend->alpha_to_coverage);
assert(!blend->alpha_to_one);
for (unsigned c = 0; c < PIPE_MAX_COLOR_BUFS; ++c) {
/* Without indep blending, the first RT settings replicate */
- unsigned g =
- blend->independent_blend_enable ? c : 0;
+ if (!blend->logicop_enable) {
+ unsigned g =
+ blend->independent_blend_enable ? c : 0;
- rt->has_fixed_function =
- panfrost_make_fixed_blend_mode(
- &blend->rt[g],
- &rt->equation,
- &rt->constant_mask,
- blend->rt[g].colormask);
+ rt->has_fixed_function =
+ panfrost_make_fixed_blend_mode(
+ &blend->rt[g],
+ &rt->equation,
+ &rt->constant_mask,
+ blend->rt[g].colormask);
+ }
/* Regardless if that works, we also need to initialize
* the blend shaders */
void *cso)
{
struct panfrost_context *ctx = pan_context(pipe);
- struct panfrost_screen *screen = pan_screen(ctx->base.screen);
struct pipe_blend_state *blend = (struct pipe_blend_state *) cso;
struct panfrost_blend_state *pblend = (struct panfrost_blend_state *) cso;
ctx->blend = pblend;
if (!blend)
return;
-
- if (screen->quirks & MIDGARD_SFBD) {
- SET_BIT(ctx->fragment_shader_core.unknown2_4, MALI_NO_DITHER, !blend->dither);
- }
}
static void
{
struct panfrost_blend_state *blend = (struct panfrost_blend_state *) cso;
- for (unsigned c = 0; c < 4; ++c) {
+ for (unsigned c = 0; c < PIPE_MAX_COLOR_BUFS; ++c) {
struct panfrost_blend_rt *rt = &blend->rt[c];
_mesa_hash_table_u64_clear(rt->shaders, panfrost_delete_blend_shader);
}
static bool
panfrost_blend_constant(float *out, float *in, unsigned mask)
{
- /* If there is no components used, it automatically works. Do set a
- * dummy constant just to avoid reading uninitialized memory. */
+ /* If there is no components used, it automatically works */
- if (!mask) {
- *out = 0.0;
+ if (!mask)
return true;
- }
/* Find some starter mask */
unsigned first = ffs(mask) - 1;
while (mask) {
unsigned i = u_bit_scan(&mask);
- if (in[i] != cons) {
- *out = 0.0;
+ if (in[i] != cons)
return false;
- }
}
/* Otherwise, we're good to go */
/* Create a final blend given the context */
struct panfrost_blend_final
-panfrost_get_blend_for_context(struct panfrost_context *ctx, unsigned rti, struct panfrost_bo **bo, unsigned *shader_offset)
+panfrost_get_blend_for_context(struct panfrost_context *ctx, unsigned rti)
{
struct panfrost_batch *batch = panfrost_get_batch_for_fbo(ctx);
-
- /* Grab the format, falling back gracefully if called invalidly (which
- * has to happen for no-color-attachment FBOs, for instance) */
struct pipe_framebuffer_state *fb = &ctx->pipe_framebuffer;
- enum pipe_format fmt = PIPE_FORMAT_R8G8B8A8_UNORM;
-
- if ((fb->nr_cbufs > rti) && fb->cbufs[rti])
- fmt = fb->cbufs[rti]->format;
+ enum pipe_format fmt = fb->cbufs[rti]->format;
/* Grab the blend state */
struct panfrost_blend_state *blend = ctx->blend;
- assert(blend);
-
struct panfrost_blend_rt *rt = &blend->rt[rti];
- struct panfrost_blend_final final;
-
- /* First, we'll try a fixed function path */
+ /* First, we'll try fixed function, matching equationn and constant */
if (rt->has_fixed_function && panfrost_can_fixed_blend(fmt)) {
+ float constant = 0.0;
+
if (panfrost_blend_constant(
- &final.equation.constant,
+ &constant,
ctx->blend_color.color,
rt->constant_mask)) {
- /* There's an equation and suitable constant, so we're good to go */
- final.is_shader = false;
- final.equation.equation = &rt->equation;
-
- final.no_blending =
+ bool no_blending =
(rt->equation.rgb_mode == 0x122) &&
(rt->equation.alpha_mode == 0x122) &&
(rt->equation.color_mask == 0xf);
+ struct panfrost_blend_final final = {
+ .equation = {
+ .equation = &rt->equation,
+ .constant = constant
+ },
+ .no_blending = no_blending,
+ .no_colour = (rt->equation.color_mask == 0x0)
+ };
+
return final;
}
}
/* Otherwise, we need to grab a shader */
struct panfrost_blend_shader *shader = panfrost_get_blend_shader(ctx, blend, fmt, rti);
- final.is_shader = true;
- final.no_blending = false;
- final.shader.work_count = shader->work_count;
- final.shader.first_tag = shader->first_tag;
-
- /* Upload the shader, sharing a BO */
- if (!(*bo)) {
- *bo = panfrost_batch_create_bo(batch, 4096,
+
+ struct panfrost_bo *bo = panfrost_batch_create_bo(batch, shader->size,
PAN_BO_EXECUTE,
PAN_BO_ACCESS_PRIVATE |
PAN_BO_ACCESS_READ |
- PAN_BO_ACCESS_VERTEX_TILER |
PAN_BO_ACCESS_FRAGMENT);
- }
- /* Size check */
- assert((*shader_offset + shader->size) < 4096);
-
- memcpy((*bo)->cpu + *shader_offset, shader->buffer, shader->size);
- final.shader.gpu = (*bo)->gpu + *shader_offset;
+ memcpy(bo->cpu, shader->buffer, shader->size);
if (shader->patch_index) {
/* We have to specialize the blend shader to use constants, so
* patch in the current constants */
- float *patch = (float *) ((*bo)->cpu + *shader_offset + shader->patch_index);
+ float *patch = (float *) (bo->cpu + shader->patch_index);
memcpy(patch, ctx->blend_color.color, sizeof(float) * 4);
}
- *shader_offset += shader->size;
+ struct panfrost_blend_final final = {
+ .is_shader = true,
+ .shader = {
+ .work_count = shader->work_count,
+ .first_tag = shader->first_tag,
+ .gpu = bo->gpu,
+ }
+ };
return final;
}