Path: blob/21.2-virgl/src/gallium/drivers/freedreno/a6xx/fd6_blend.c
4574 views
/*1* Copyright (C) 2016 Rob Clark <[email protected]>2* Copyright © 2018 Google, Inc.3*4* Permission is hereby granted, free of charge, to any person obtaining a5* copy of this software and associated documentation files (the "Software"),6* to deal in the Software without restriction, including without limitation7* the rights to use, copy, modify, merge, publish, distribute, sublicense,8* and/or sell copies of the Software, and to permit persons to whom the9* Software is furnished to do so, subject to the following conditions:10*11* The above copyright notice and this permission notice (including the next12* paragraph) shall be included in all copies or substantial portions of the13* Software.14*15* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR16* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL18* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER19* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,20* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE21* SOFTWARE.22*23* Authors:24* Rob Clark <[email protected]>25*/2627#include "pipe/p_state.h"28#include "util/u_blend.h"29#include "util/u_dual_blend.h"30#include "util/u_memory.h"31#include "util/u_string.h"3233#include "fd6_blend.h"34#include "fd6_context.h"35#include "fd6_format.h"36#include "fd6_pack.h"3738// XXX move somewhere common.. same across a3xx/a4xx/a5xx..39static enum a3xx_rb_blend_opcode40blend_func(unsigned func)41{42switch (func) {43case PIPE_BLEND_ADD:44return BLEND_DST_PLUS_SRC;45case PIPE_BLEND_MIN:46return BLEND_MIN_DST_SRC;47case PIPE_BLEND_MAX:48return BLEND_MAX_DST_SRC;49case PIPE_BLEND_SUBTRACT:50return BLEND_SRC_MINUS_DST;51case PIPE_BLEND_REVERSE_SUBTRACT:52return BLEND_DST_MINUS_SRC;53default:54DBG("invalid blend func: %x", func);55return 0;56}57}5859struct fd6_blend_variant *60__fd6_setup_blend_variant(struct fd6_blend_stateobj *blend,61unsigned sample_mask)62{63const struct pipe_blend_state *cso = &blend->base;64struct fd6_blend_variant *so;65enum a3xx_rop_code rop = ROP_COPY;66bool reads_dest = false;67unsigned mrt_blend = 0;6869if (cso->logicop_enable) {70rop = cso->logicop_func; /* maps 1:1 */71reads_dest = util_logicop_reads_dest(cso->logicop_func);72}7374so = rzalloc_size(blend, sizeof(*so));75if (!so)76return NULL;7778struct fd_ringbuffer *ring = fd_ringbuffer_new_object(79blend->ctx->pipe, ((A6XX_MAX_RENDER_TARGETS * 4) + 6) * 4);80so->stateobj = ring;8182for (unsigned i = 0; i <= cso->max_rt; i++) {83const struct pipe_rt_blend_state *rt;8485if (cso->independent_blend_enable)86rt = &cso->rt[i];87else88rt = &cso->rt[0];8990OUT_REG(ring,91A6XX_RB_MRT_BLEND_CONTROL(92i, .rgb_src_factor = fd_blend_factor(rt->rgb_src_factor),93.rgb_blend_opcode = blend_func(rt->rgb_func),94.rgb_dest_factor = fd_blend_factor(rt->rgb_dst_factor),95.alpha_src_factor = fd_blend_factor(rt->alpha_src_factor),96.alpha_blend_opcode = blend_func(rt->alpha_func),97.alpha_dest_factor = fd_blend_factor(rt->alpha_dst_factor), ));9899OUT_REG(ring, A6XX_RB_MRT_CONTROL(i, .rop_code = rop,100.rop_enable = cso->logicop_enable,101.component_enable = rt->colormask,102.blend = rt->blend_enable,103.blend2 = rt->blend_enable, ));104105if (rt->blend_enable) {106mrt_blend |= (1 << i);107}108109if (reads_dest) {110mrt_blend |= (1 << i);111}112}113114OUT_REG(115ring,116A6XX_RB_DITHER_CNTL(117.dither_mode_mrt0 = cso->dither ? DITHER_ALWAYS : DITHER_DISABLE,118.dither_mode_mrt1 = cso->dither ? DITHER_ALWAYS : DITHER_DISABLE,119.dither_mode_mrt2 = cso->dither ? DITHER_ALWAYS : DITHER_DISABLE,120.dither_mode_mrt3 = cso->dither ? DITHER_ALWAYS : DITHER_DISABLE,121.dither_mode_mrt4 = cso->dither ? DITHER_ALWAYS : DITHER_DISABLE,122.dither_mode_mrt5 = cso->dither ? DITHER_ALWAYS : DITHER_DISABLE,123.dither_mode_mrt6 = cso->dither ? DITHER_ALWAYS : DITHER_DISABLE,124.dither_mode_mrt7 =125cso->dither ? DITHER_ALWAYS : DITHER_DISABLE, ));126127OUT_REG(ring, A6XX_SP_BLEND_CNTL(.enable_blend = mrt_blend,128.unk8 = true,129.alpha_to_coverage = cso->alpha_to_coverage,130.dual_color_in_enable =131blend->use_dual_src_blend, ));132133OUT_REG(ring,134A6XX_RB_BLEND_CNTL(.enable_blend = mrt_blend,135.alpha_to_coverage = cso->alpha_to_coverage,136.alpha_to_one = cso->alpha_to_one,137.independent_blend = cso->independent_blend_enable,138.sample_mask = sample_mask,139.dual_color_in_enable = blend->use_dual_src_blend, ));140141so->sample_mask = sample_mask;142143util_dynarray_append(&blend->variants, struct fd6_blend_variant *, so);144145return so;146}147148void *149fd6_blend_state_create(struct pipe_context *pctx,150const struct pipe_blend_state *cso)151{152struct fd6_blend_stateobj *so;153154so = rzalloc_size(NULL, sizeof(*so));155if (!so)156return NULL;157158so->base = *cso;159so->ctx = fd_context(pctx);160161if (cso->logicop_enable) {162so->reads_dest |= util_logicop_reads_dest(cso->logicop_func);163}164165so->use_dual_src_blend =166cso->rt[0].blend_enable && util_blend_state_is_dual(cso, 0);167168unsigned nr = cso->independent_blend_enable ? cso->max_rt : 0;169for (unsigned i = 0; i <= nr; i++) {170const struct pipe_rt_blend_state *rt = &cso->rt[i];171172so->reads_dest |= rt->blend_enable;173174/* From the PoV of LRZ, having masked color channels is175* the same as having blend enabled, in that the draw will176* care about the fragments from an earlier draw.177*178* NOTE we actually don't care about masked color channels179* that don't actually exist in the render target, but we180* don't know the render target format here to determine181* that. It is probably not worth worrying about, but if182* we find a game/benchmark that goes out of it's way to183* mask off non-existent channels, we should fixup the184* pipe_blend_state to give us more info.185*/186if (rt->blend_enable || (rt->colormask != 0xf)) {187so->reads_dest = true;188}189}190191util_dynarray_init(&so->variants, so);192193return so;194}195196void197fd6_blend_state_delete(struct pipe_context *pctx, void *hwcso)198{199struct fd6_blend_stateobj *so = hwcso;200201util_dynarray_foreach (&so->variants, struct fd6_blend_variant *, vp) {202struct fd6_blend_variant *v = *vp;203fd_ringbuffer_del(v->stateobj);204}205206ralloc_free(so);207}208209210