freedreno/a3xx: add support for dual-source blending
Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
This commit is contained in:
@@ -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>
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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():
|
||||
|
@@ -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;
|
||||
|
@@ -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:
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user