freedreno/a3xx: add support for dual-source blending
authorIlia Mirkin <imirkin@alum.mit.edu>
Sun, 13 Sep 2015 23:50:45 +0000 (19:50 -0400)
committerIlia Mirkin <imirkin@alum.mit.edu>
Wed, 16 Sep 2015 19:42:54 +0000 (15:42 -0400)
Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
docs/relnotes/11.1.0.html
src/gallium/drivers/freedreno/a3xx/fd3_blend.c
src/gallium/drivers/freedreno/a3xx/fd3_blend.h
src/gallium/drivers/freedreno/a3xx/fd3_emit.c
src/gallium/drivers/freedreno/freedreno_context.h
src/gallium/drivers/freedreno/freedreno_screen.c
src/gallium/drivers/freedreno/freedreno_state.c
src/gallium/drivers/freedreno/freedreno_util.c

index 6abdf7ad8552de8ceddd1e17b64aed44a49e5649..24fdf2e96830478cd4dff91d2d8963ff138f9590 100644 (file)
@@ -44,6 +44,7 @@ Note: some of the new features are only available with certain drivers.
 </p>
 
 <ul>
+<li>GL_ARB_blend_func_extended on freedreno (a3xx)</li>
 <li>GL_ARB_shader_texture_image_samples on i965, nv50, nvc0, r600</li>
 <li>GL_ARB_texture_query_lod on softpipe</li>
 <li>GL_ARB_gpu_shader_fp64 on r600 for Cypress/Cayman/Aruba chips</li>
index 6f5de9d47f71d617f5709ed060edb92b9c78d7eb..35360f33822f25868b20c580d9e4101eec4ead82 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "pipe/p_state.h"
 #include "util/u_blend.h"
+#include "util/u_dual_blend.h"
 #include "util/u_string.h"
 #include "util/u_memory.h"
 
@@ -131,5 +132,8 @@ fd3_blend_state_create(struct pipe_context *pctx,
                        so->rb_mrt[i].control |= A3XX_RB_MRT_CONTROL_DITHER_MODE(DITHER_ALWAYS);
        }
 
+       if (cso->rt[0].blend_enable && util_blend_state_is_dual(cso, 0))
+               so->rb_render_control = A3XX_RB_RENDER_CONTROL_DUAL_COLOR_IN_ENABLE;
+
        return so;
 }
index 142df7c300f54c30be0ad03f1983c4fa1c9cc329..59e0010372d4037e4822526e2185bcc7912f49b1 100644 (file)
@@ -36,6 +36,7 @@
 
 struct fd3_blend_stateobj {
        struct pipe_blend_state base;
+       uint32_t rb_render_control;
        struct {
                /* Blend control bits for color if there is an alpha channel */
                uint32_t blend_control_rgb;
index b81bc5a90a49cd5556dcbc699636a86f255d01fe..40301971d90d1a6f2956ac48279c1f42f4bc884a 100644 (file)
@@ -443,8 +443,10 @@ fd3_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring,
                                A3XX_RB_MSAA_CONTROL_SAMPLE_MASK(ctx->sample_mask));
        }
 
-       if ((dirty & (FD_DIRTY_ZSA | FD_DIRTY_PROG)) && !emit->key.binning_pass) {
-               uint32_t val = fd3_zsa_stateobj(ctx->zsa)->rb_render_control;
+       if ((dirty & (FD_DIRTY_ZSA | FD_DIRTY_PROG | FD_DIRTY_BLEND_DUAL)) &&
+               !emit->key.binning_pass) {
+               uint32_t val = fd3_zsa_stateobj(ctx->zsa)->rb_render_control |
+                       fd3_blend_stateobj(ctx->blend)->rb_render_control;
 
                val |= COND(fp->frag_face, A3XX_RB_RENDER_CONTROL_FACENESS);
                val |= COND(fp->frag_coord, A3XX_RB_RENDER_CONTROL_XCOORD |
@@ -590,9 +592,13 @@ fd3_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring,
                OUT_RING(ring, A3XX_GRAS_CL_VPORT_ZSCALE(ctx->viewport.scale[2]));
        }
 
-       if (dirty & (FD_DIRTY_PROG | FD_DIRTY_FRAMEBUFFER)) {
+       if (dirty & (FD_DIRTY_PROG | FD_DIRTY_FRAMEBUFFER | FD_DIRTY_BLEND_DUAL)) {
                struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
-               fd3_program_emit(ring, emit, pfb->nr_cbufs, pfb->cbufs);
+               int nr_cbufs = pfb->nr_cbufs;
+               if (fd3_blend_stateobj(ctx->blend)->rb_render_control &
+                       A3XX_RB_RENDER_CONTROL_DUAL_COLOR_IN_ENABLE)
+                       nr_cbufs++;
+               fd3_program_emit(ring, emit, nr_cbufs, pfb->cbufs);
        }
 
        /* TODO we should not need this or fd_wfi() before emit_constants():
index 3486c2fd1b7bdb4c508010bdfa00a2a4781e4e2f..61c4c6d6e240b615479f2d5f29818ac13cb4aa36 100644 (file)
@@ -335,6 +335,7 @@ struct fd_context {
                FD_DIRTY_SCISSOR     = (1 << 17),
                FD_DIRTY_STREAMOUT   = (1 << 18),
                FD_DIRTY_UCP         = (1 << 19),
+               FD_DIRTY_BLEND_DUAL  = (1 << 20),
        } dirty;
 
        struct pipe_blend_state *blend;
index a3dede2500e20ae260a18438a324915813feb3dc..9a684d4ffbb71a48c7c0e683b1ccf219ede05966 100644 (file)
@@ -163,7 +163,6 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
        case PIPE_CAP_TEXTURE_MULTISAMPLE:
        case PIPE_CAP_TEXTURE_BARRIER:
        case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
-       case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:
        case PIPE_CAP_START_INSTANCE:
        case PIPE_CAP_COMPUTE:
                return 0;
@@ -278,6 +277,8 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
        /* Render targets. */
        case PIPE_CAP_MAX_RENDER_TARGETS:
                return screen->max_rts;
+       case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:
+               return is_a3xx(screen) ? 1 : 0;
 
        /* Queries. */
        case PIPE_CAP_QUERY_TIME_ELAPSED:
index e75865a9387f0d7694b70df469fa94a8e0f133ff..685d3a756598b192750bbdd5605e6b3d536417ab 100644 (file)
@@ -27,6 +27,7 @@
  */
 
 #include "pipe/p_state.h"
+#include "util/u_dual_blend.h"
 #include "util/u_string.h"
 #include "util/u_memory.h"
 #include "util/u_helpers.h"
@@ -225,8 +226,17 @@ static void
 fd_blend_state_bind(struct pipe_context *pctx, void *hwcso)
 {
        struct fd_context *ctx = fd_context(pctx);
+       struct pipe_blend_state *cso = hwcso;
+       bool old_is_dual = ctx->blend ?
+               ctx->blend->rt[0].blend_enable && util_blend_state_is_dual(ctx->blend, 0) :
+               false;
+       bool new_is_dual = cso ?
+               cso->rt[0].blend_enable && util_blend_state_is_dual(cso, 0) :
+               false;
        ctx->blend = hwcso;
        ctx->dirty |= FD_DIRTY_BLEND;
+       if (old_is_dual != new_is_dual)
+               ctx->dirty |= FD_DIRTY_BLEND_DUAL;
 }
 
 static void
index 2acce06d1482ce1d9ba19d1b9333f3a474f46fca..c8f2127c9100203df7d06fd03f7b11d887b0ba44 100644 (file)
@@ -104,10 +104,13 @@ fd_blend_factor(unsigned factor)
        case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
                return FACTOR_ONE_MINUS_CONSTANT_ALPHA;
        case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
+               return FACTOR_ONE_MINUS_SRC1_COLOR;
        case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
+               return FACTOR_ONE_MINUS_SRC1_ALPHA;
        case PIPE_BLENDFACTOR_SRC1_COLOR:
+               return FACTOR_SRC1_COLOR;
        case PIPE_BLENDFACTOR_SRC1_ALPHA:
-               /* I don't think these are supported */
+               return FACTOR_SRC1_ALPHA;
        default:
                DBG("invalid blend factor: %x", factor);
                return 0;