diff options
Diffstat (limited to 'src/gallium/drivers')
-rw-r--r-- | src/gallium/drivers/vc4/vc4_program.c | 62 |
1 files changed, 60 insertions, 2 deletions
diff --git a/src/gallium/drivers/vc4/vc4_program.c b/src/gallium/drivers/vc4/vc4_program.c index d21522fdcd6..cea2a490eca 100644 --- a/src/gallium/drivers/vc4/vc4_program.c +++ b/src/gallium/drivers/vc4/vc4_program.c @@ -69,6 +69,7 @@ struct vc4_fs_key { bool point_coord_upper_left; bool light_twoside; uint8_t alpha_test_func; + uint8_t logicop_func; uint32_t point_sprite_mask; struct pipe_rt_blend_state blend; @@ -1629,6 +1630,46 @@ alpha_test_discard(struct vc4_compile *c) } } +static struct qreg +vc4_logicop(struct vc4_compile *c, struct qreg src, struct qreg dst) +{ + switch (c->fs_key->logicop_func) { + case PIPE_LOGICOP_CLEAR: + return qir_uniform_f(c, 0.0); + case PIPE_LOGICOP_NOR: + return qir_NOT(c, qir_OR(c, src, dst)); + case PIPE_LOGICOP_AND_INVERTED: + return qir_AND(c, qir_NOT(c, src), dst); + case PIPE_LOGICOP_COPY_INVERTED: + return qir_NOT(c, src); + case PIPE_LOGICOP_AND_REVERSE: + return qir_AND(c, src, qir_NOT(c, dst)); + case PIPE_LOGICOP_INVERT: + return qir_NOT(c, dst); + case PIPE_LOGICOP_XOR: + return qir_XOR(c, src, dst); + case PIPE_LOGICOP_NAND: + return qir_NOT(c, qir_AND(c, src, dst)); + case PIPE_LOGICOP_AND: + return qir_AND(c, src, dst); + case PIPE_LOGICOP_EQUIV: + return qir_NOT(c, qir_XOR(c, src, dst)); + case PIPE_LOGICOP_NOOP: + return dst; + case PIPE_LOGICOP_OR_INVERTED: + return qir_OR(c, qir_NOT(c, src), dst); + case PIPE_LOGICOP_OR_REVERSE: + return qir_OR(c, src, qir_NOT(c, dst)); + case PIPE_LOGICOP_OR: + return qir_OR(c, src, dst); + case PIPE_LOGICOP_SET: + return qir_uniform_ui(c, ~0); + case PIPE_LOGICOP_COPY: + default: + return src; + } +} + static void emit_frag_end(struct vc4_compile *c) { @@ -1640,8 +1681,11 @@ emit_frag_end(struct vc4_compile *c) struct qreg tlb_read_color[4] = { c->undef, c->undef, c->undef, c->undef }; struct qreg dst_color[4] = { c->undef, c->undef, c->undef, c->undef }; struct qreg linear_dst_color[4] = { c->undef, c->undef, c->undef, c->undef }; + struct qreg packed_dst_color = c->undef; + if (c->fs_key->blend.blend_enable || - c->fs_key->blend.colormask != 0xf) { + c->fs_key->blend.colormask != 0xf || + c->fs_key->logicop_func != PIPE_LOGICOP_COPY) { struct qreg r4 = qir_TLB_COLOR_READ(c); for (int i = 0; i < 4; i++) tlb_read_color[i] = qir_R4_UNPACK(c, r4, i); @@ -1656,6 +1700,11 @@ emit_frag_end(struct vc4_compile *c) linear_dst_color[i] = dst_color[i]; } } + + /* Save the packed value for logic ops. Can't reuse r4 + * becuase other things might smash it (like sRGB) + */ + packed_dst_color = qir_MOV(c, r4); } struct qreg blend_color[4]; @@ -1748,6 +1797,11 @@ emit_frag_end(struct vc4_compile *c) packed_color = qir_uniform_ui(c, 0); } + + if (c->fs_key->logicop_func != PIPE_LOGICOP_COPY) { + packed_color = vc4_logicop(c, packed_color, packed_dst_color); + } + qir_emit(c, qir_inst(QOP_TLB_COLOR_WRITE, c->undef, packed_color, c->undef)); } @@ -2254,7 +2308,11 @@ vc4_update_compiled_fs(struct vc4_context *vc4, uint8_t prim_mode) key->is_lines = (prim_mode >= PIPE_PRIM_LINES && prim_mode <= PIPE_PRIM_LINE_STRIP); key->blend = vc4->blend->rt[0]; - + if (vc4->blend->logicop_enable) { + key->logicop_func = vc4->blend->logicop_func; + } else { + key->logicop_func = PIPE_LOGICOP_COPY; + } if (vc4->framebuffer.cbufs[0]) key->color_format = vc4->framebuffer.cbufs[0]->format; |