Path: blob/21.2-virgl/src/gallium/drivers/svga/svga_pipe_blend.c
4570 views
/**********************************************************1* Copyright 2008-2009 VMware, Inc. All rights reserved.2*3* Permission is hereby granted, free of charge, to any person4* obtaining a copy of this software and associated documentation5* files (the "Software"), to deal in the Software without6* restriction, including without limitation the rights to use, copy,7* modify, merge, publish, distribute, sublicense, and/or sell copies8* of the Software, and to permit persons to whom the Software is9* furnished to do so, subject to the following conditions:10*11* The above copyright notice and this permission notice shall be12* included in all copies or substantial portions of the Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,15* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF16* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND17* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS18* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN19* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN20* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE21* SOFTWARE.22*23**********************************************************/2425#include "util/u_inlines.h"26#include "pipe/p_defines.h"27#include "util/u_math.h"28#include "util/u_memory.h"29#include "util/u_bitmask.h"3031#include "svga_context.h"32#include "svga_hw_reg.h"33#include "svga_cmd.h"343536static inline unsigned37svga_translate_blend_factor(const struct svga_context *svga, unsigned factor)38{39/* Note: there is no SVGA3D_BLENDOP_[INV]BLENDFACTORALPHA so40* we can't translate PIPE_BLENDFACTOR_[INV_]CONST_ALPHA properly.41*/42switch (factor) {43case PIPE_BLENDFACTOR_ZERO: return SVGA3D_BLENDOP_ZERO;44case PIPE_BLENDFACTOR_SRC_ALPHA: return SVGA3D_BLENDOP_SRCALPHA;45case PIPE_BLENDFACTOR_ONE: return SVGA3D_BLENDOP_ONE;46case PIPE_BLENDFACTOR_SRC_COLOR: return SVGA3D_BLENDOP_SRCCOLOR;47case PIPE_BLENDFACTOR_INV_SRC_COLOR: return SVGA3D_BLENDOP_INVSRCCOLOR;48case PIPE_BLENDFACTOR_DST_COLOR: return SVGA3D_BLENDOP_DESTCOLOR;49case PIPE_BLENDFACTOR_INV_DST_COLOR: return SVGA3D_BLENDOP_INVDESTCOLOR;50case PIPE_BLENDFACTOR_INV_SRC_ALPHA: return SVGA3D_BLENDOP_INVSRCALPHA;51case PIPE_BLENDFACTOR_DST_ALPHA: return SVGA3D_BLENDOP_DESTALPHA;52case PIPE_BLENDFACTOR_INV_DST_ALPHA: return SVGA3D_BLENDOP_INVDESTALPHA;53case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: return SVGA3D_BLENDOP_SRCALPHASAT;54case PIPE_BLENDFACTOR_CONST_COLOR: return SVGA3D_BLENDOP_BLENDFACTOR;55case PIPE_BLENDFACTOR_INV_CONST_COLOR: return SVGA3D_BLENDOP_INVBLENDFACTOR;56case PIPE_BLENDFACTOR_CONST_ALPHA:57if (svga_have_vgpu10(svga))58return SVGA3D_BLENDOP_BLENDFACTORALPHA;59else60return SVGA3D_BLENDOP_BLENDFACTOR; /* as close as we can get */61case PIPE_BLENDFACTOR_INV_CONST_ALPHA:62if (svga_have_vgpu10(svga))63return SVGA3D_BLENDOP_INVBLENDFACTORALPHA;64else65return SVGA3D_BLENDOP_INVBLENDFACTOR; /* as close as we can get */66case PIPE_BLENDFACTOR_SRC1_COLOR: return SVGA3D_BLENDOP_SRC1COLOR;67case PIPE_BLENDFACTOR_INV_SRC1_COLOR: return SVGA3D_BLENDOP_INVSRC1COLOR;68case PIPE_BLENDFACTOR_SRC1_ALPHA: return SVGA3D_BLENDOP_SRC1ALPHA;69case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: return SVGA3D_BLENDOP_INVSRC1ALPHA;70case 0: return SVGA3D_BLENDOP_ONE;71default:72assert(0);73return SVGA3D_BLENDOP_ZERO;74}75}7677static inline unsigned78svga_translate_blend_func(unsigned mode)79{80switch (mode) {81case PIPE_BLEND_ADD: return SVGA3D_BLENDEQ_ADD;82case PIPE_BLEND_SUBTRACT: return SVGA3D_BLENDEQ_SUBTRACT;83case PIPE_BLEND_REVERSE_SUBTRACT: return SVGA3D_BLENDEQ_REVSUBTRACT;84case PIPE_BLEND_MIN: return SVGA3D_BLENDEQ_MINIMUM;85case PIPE_BLEND_MAX: return SVGA3D_BLENDEQ_MAXIMUM;86default:87assert(0);88return SVGA3D_BLENDEQ_ADD;89}90}919293/**94* Translate gallium logicop mode to SVGA3D logicop mode.95*/96static int97translate_logicop(enum pipe_logicop op)98{99switch (op) {100case PIPE_LOGICOP_CLEAR:101return SVGA3D_DX11_LOGICOP_CLEAR;102case PIPE_LOGICOP_NOR:103return SVGA3D_DX11_LOGICOP_NOR;104case PIPE_LOGICOP_AND_INVERTED:105return SVGA3D_DX11_LOGICOP_AND_INVERTED;106case PIPE_LOGICOP_COPY_INVERTED:107return SVGA3D_DX11_LOGICOP_COPY_INVERTED;108case PIPE_LOGICOP_AND_REVERSE:109return SVGA3D_DX11_LOGICOP_AND_REVERSE;110case PIPE_LOGICOP_INVERT:111return SVGA3D_DX11_LOGICOP_INVERT;112case PIPE_LOGICOP_XOR:113return SVGA3D_DX11_LOGICOP_XOR;114case PIPE_LOGICOP_NAND:115return SVGA3D_DX11_LOGICOP_NAND;116case PIPE_LOGICOP_AND:117return SVGA3D_DX11_LOGICOP_AND;118case PIPE_LOGICOP_EQUIV:119return SVGA3D_DX11_LOGICOP_EQUIV;120case PIPE_LOGICOP_NOOP:121return SVGA3D_DX11_LOGICOP_NOOP;122case PIPE_LOGICOP_OR_INVERTED:123return SVGA3D_DX11_LOGICOP_OR_INVERTED;124case PIPE_LOGICOP_COPY:125return SVGA3D_DX11_LOGICOP_COPY;126case PIPE_LOGICOP_OR_REVERSE:127return SVGA3D_DX11_LOGICOP_OR_REVERSE;128case PIPE_LOGICOP_OR:129return SVGA3D_DX11_LOGICOP_OR;130case PIPE_LOGICOP_SET:131return SVGA3D_DX11_LOGICOP_SET;132default:133return SVGA3D_DX11_LOGICOP_COPY;134}135};136137138/**139* Define a vgpu10 blend state object for the given140* svga blend state.141*/142static void143define_blend_state_object(struct svga_context *svga,144struct svga_blend_state *bs)145{146SVGA3dDXBlendStatePerRT perRT[SVGA3D_MAX_RENDER_TARGETS];147int i;148149assert(svga_have_vgpu10(svga));150151bs->id = util_bitmask_add(svga->blend_object_id_bm);152153for (i = 0; i < SVGA3D_DX_MAX_RENDER_TARGETS; i++) {154perRT[i].blendEnable = bs->rt[i].blend_enable;155perRT[i].srcBlend = bs->rt[i].srcblend;156perRT[i].destBlend = bs->rt[i].dstblend;157perRT[i].blendOp = bs->rt[i].blendeq;158perRT[i].srcBlendAlpha = bs->rt[i].srcblend_alpha;159perRT[i].destBlendAlpha = bs->rt[i].dstblend_alpha;160perRT[i].blendOpAlpha = bs->rt[i].blendeq_alpha;161perRT[i].renderTargetWriteMask = bs->rt[i].writemask;162perRT[i].logicOpEnable = bs->logicop_enabled;163perRT[i].logicOp = bs->logicop_mode;164}165166SVGA_RETRY(svga, SVGA3D_vgpu10_DefineBlendState(svga->swc,167bs->id,168bs->alpha_to_coverage,169bs->independent_blend_enable,170perRT));171}172173174/**175* If SVGA3D_DEVCAP_LOGIC_BLENDOPS is false, we can't directly implement176* GL's logicops. But we can emulate some of them. We set up the blending177* state for that here.178*/179static void180emulate_logicop(struct svga_context *svga,181unsigned logicop_func,182struct svga_blend_state *blend,183unsigned buffer)184{185switch (logicop_func) {186case PIPE_LOGICOP_XOR:187case PIPE_LOGICOP_INVERT:188blend->need_white_fragments = TRUE;189blend->rt[buffer].blend_enable = TRUE;190blend->rt[buffer].srcblend = SVGA3D_BLENDOP_ONE;191blend->rt[buffer].dstblend = SVGA3D_BLENDOP_ONE;192blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_SUBTRACT;193break;194case PIPE_LOGICOP_CLEAR:195blend->rt[buffer].blend_enable = TRUE;196blend->rt[buffer].srcblend = SVGA3D_BLENDOP_ZERO;197blend->rt[buffer].dstblend = SVGA3D_BLENDOP_ZERO;198blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_MINIMUM;199break;200case PIPE_LOGICOP_COPY:201blend->rt[buffer].blend_enable = FALSE;202blend->rt[buffer].srcblend = SVGA3D_BLENDOP_ONE;203blend->rt[buffer].dstblend = SVGA3D_BLENDOP_ZERO;204blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_ADD;205break;206case PIPE_LOGICOP_COPY_INVERTED:207blend->rt[buffer].blend_enable = TRUE;208blend->rt[buffer].srcblend = SVGA3D_BLENDOP_INVSRCCOLOR;209blend->rt[buffer].dstblend = SVGA3D_BLENDOP_ZERO;210blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_ADD;211break;212case PIPE_LOGICOP_NOOP:213blend->rt[buffer].blend_enable = TRUE;214blend->rt[buffer].srcblend = SVGA3D_BLENDOP_ZERO;215blend->rt[buffer].dstblend = SVGA3D_BLENDOP_DESTCOLOR;216blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_ADD;217break;218case PIPE_LOGICOP_SET:219blend->rt[buffer].blend_enable = TRUE;220blend->rt[buffer].srcblend = SVGA3D_BLENDOP_ONE;221blend->rt[buffer].dstblend = SVGA3D_BLENDOP_ONE;222blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_MAXIMUM;223break;224case PIPE_LOGICOP_AND:225/* Approximate with minimum - works for the 0 & anything case: */226blend->rt[buffer].blend_enable = TRUE;227blend->rt[buffer].srcblend = SVGA3D_BLENDOP_SRCCOLOR;228blend->rt[buffer].dstblend = SVGA3D_BLENDOP_DESTCOLOR;229blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_MINIMUM;230break;231case PIPE_LOGICOP_AND_REVERSE:232blend->rt[buffer].blend_enable = TRUE;233blend->rt[buffer].srcblend = SVGA3D_BLENDOP_SRCCOLOR;234blend->rt[buffer].dstblend = SVGA3D_BLENDOP_INVDESTCOLOR;235blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_MINIMUM;236break;237case PIPE_LOGICOP_AND_INVERTED:238blend->rt[buffer].blend_enable = TRUE;239blend->rt[buffer].srcblend = SVGA3D_BLENDOP_INVSRCCOLOR;240blend->rt[buffer].dstblend = SVGA3D_BLENDOP_DESTCOLOR;241blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_MINIMUM;242break;243case PIPE_LOGICOP_OR:244/* Approximate with maximum - works for the 1 | anything case: */245blend->rt[buffer].blend_enable = TRUE;246blend->rt[buffer].srcblend = SVGA3D_BLENDOP_SRCCOLOR;247blend->rt[buffer].dstblend = SVGA3D_BLENDOP_DESTCOLOR;248blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_MAXIMUM;249break;250case PIPE_LOGICOP_OR_REVERSE:251blend->rt[buffer].blend_enable = TRUE;252blend->rt[buffer].srcblend = SVGA3D_BLENDOP_SRCCOLOR;253blend->rt[buffer].dstblend = SVGA3D_BLENDOP_INVDESTCOLOR;254blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_MAXIMUM;255break;256case PIPE_LOGICOP_OR_INVERTED:257blend->rt[buffer].blend_enable = TRUE;258blend->rt[buffer].srcblend = SVGA3D_BLENDOP_INVSRCCOLOR;259blend->rt[buffer].dstblend = SVGA3D_BLENDOP_DESTCOLOR;260blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_MAXIMUM;261break;262case PIPE_LOGICOP_NAND:263case PIPE_LOGICOP_NOR:264case PIPE_LOGICOP_EQUIV:265/* Fill these in with plausible values */266blend->rt[buffer].blend_enable = FALSE;267blend->rt[buffer].srcblend = SVGA3D_BLENDOP_ONE;268blend->rt[buffer].dstblend = SVGA3D_BLENDOP_ZERO;269blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_ADD;270break;271default:272assert(0);273break;274}275blend->rt[buffer].srcblend_alpha = blend->rt[buffer].srcblend;276blend->rt[buffer].dstblend_alpha = blend->rt[buffer].dstblend;277blend->rt[buffer].blendeq_alpha = blend->rt[buffer].blendeq;278279if (logicop_func == PIPE_LOGICOP_XOR) {280pipe_debug_message(&svga->debug.callback, CONFORMANCE,281"XOR logicop mode has limited support");282}283else if (logicop_func != PIPE_LOGICOP_COPY) {284pipe_debug_message(&svga->debug.callback, CONFORMANCE,285"general logicops are not supported");286}287}288289290291static void *292svga_create_blend_state(struct pipe_context *pipe,293const struct pipe_blend_state *templ)294{295struct svga_context *svga = svga_context(pipe);296struct svga_screen *ss = svga_screen(pipe->screen);297struct svga_blend_state *blend = CALLOC_STRUCT( svga_blend_state );298unsigned i;299300if (!blend)301return NULL;302303/* Find index of first target with blending enabled. If no blending is304* enabled at all, first_enabled will be zero.305*/306unsigned first_enabled = 0;307for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {308if (templ->rt[i].blend_enable) {309first_enabled = i;310break;311}312}313314/* Fill in the per-rendertarget blend state. We currently only315* support independent blend enable and colormask per render target.316*/317for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {318/* No way to set this in SVGA3D, and no way to correctly implement it on319* top of D3D9 API. Instead we try to simulate with various blend modes.320*/321if (templ->logicop_enable) {322if (ss->haveBlendLogicops) {323blend->logicop_enabled = TRUE;324blend->logicop_mode = translate_logicop(templ->logicop_func);325blend->rt[i].blendeq = SVGA3D_BLENDEQ_ADD;326blend->rt[i].blendeq_alpha = SVGA3D_BLENDEQ_ADD;327blend->rt[i].srcblend = SVGA3D_BLENDOP_ZERO;328blend->rt[i].dstblend = SVGA3D_BLENDOP_ZERO;329blend->rt[i].srcblend_alpha = SVGA3D_BLENDOP_ZERO;330blend->rt[i].dstblend_alpha = SVGA3D_BLENDOP_ZERO;331}332else {333emulate_logicop(svga, templ->logicop_func, blend, i);334}335}336else {337/* Note: per-target blend terms are only supported for sm4_1338* device. For vgpu10 device, the blending terms must be identical339* for all targets (this is why we need the first_enabled index).340*/341const unsigned j =342svga_have_sm4_1(svga) && templ->independent_blend_enable343? i : first_enabled;344if (templ->independent_blend_enable || templ->rt[j].blend_enable) {345blend->rt[i].srcblend =346svga_translate_blend_factor(svga, templ->rt[j].rgb_src_factor);347blend->rt[i].dstblend =348svga_translate_blend_factor(svga, templ->rt[j].rgb_dst_factor);349blend->rt[i].blendeq =350svga_translate_blend_func(templ->rt[j].rgb_func);351blend->rt[i].srcblend_alpha =352svga_translate_blend_factor(svga, templ->rt[j].alpha_src_factor);353blend->rt[i].dstblend_alpha =354svga_translate_blend_factor(svga, templ->rt[j].alpha_dst_factor);355blend->rt[i].blendeq_alpha =356svga_translate_blend_func(templ->rt[j].alpha_func);357358if (blend->rt[i].srcblend_alpha != blend->rt[i].srcblend ||359blend->rt[i].dstblend_alpha != blend->rt[i].dstblend ||360blend->rt[i].blendeq_alpha != blend->rt[i].blendeq) {361blend->rt[i].separate_alpha_blend_enable = TRUE;362}363}364else {365/* disabled - default blend terms */366blend->rt[i].srcblend = SVGA3D_BLENDOP_ONE;367blend->rt[i].dstblend = SVGA3D_BLENDOP_ZERO;368blend->rt[i].blendeq = SVGA3D_BLENDEQ_ADD;369blend->rt[i].srcblend_alpha = SVGA3D_BLENDOP_ONE;370blend->rt[i].dstblend_alpha = SVGA3D_BLENDOP_ZERO;371blend->rt[i].blendeq_alpha = SVGA3D_BLENDEQ_ADD;372}373374if (templ->independent_blend_enable) {375blend->rt[i].blend_enable = templ->rt[i].blend_enable;376}377else {378blend->rt[i].blend_enable = templ->rt[0].blend_enable;379}380}381382/* Some GL blend modes are not supported by the VGPU9 device (there's383* no equivalent of PIPE_BLENDFACTOR_[INV_]CONST_ALPHA).384* When we set this flag, we copy the constant blend alpha value385* to the R, G, B components.386* This works as long as the src/dst RGB blend factors doesn't use387* PIPE_BLENDFACTOR_CONST_COLOR and PIPE_BLENDFACTOR_CONST_ALPHA388* at the same time. There's no work-around for that.389*/390if (!svga_have_vgpu10(svga)) {391if (templ->rt[0].rgb_src_factor == PIPE_BLENDFACTOR_CONST_ALPHA ||392templ->rt[0].rgb_dst_factor == PIPE_BLENDFACTOR_CONST_ALPHA ||393templ->rt[0].rgb_src_factor == PIPE_BLENDFACTOR_INV_CONST_ALPHA ||394templ->rt[0].rgb_dst_factor == PIPE_BLENDFACTOR_INV_CONST_ALPHA) {395blend->blend_color_alpha = TRUE;396}397}398399if (templ->independent_blend_enable) {400blend->rt[i].writemask = templ->rt[i].colormask;401}402else {403blend->rt[i].writemask = templ->rt[0].colormask;404}405}406407blend->independent_blend_enable = templ->independent_blend_enable;408409blend->alpha_to_coverage = templ->alpha_to_coverage;410blend->alpha_to_one = templ->alpha_to_one;411412if (svga_have_vgpu10(svga)) {413define_blend_state_object(svga, blend);414}415416svga->hud.num_blend_objects++;417SVGA_STATS_COUNT_INC(svga_screen(svga->pipe.screen)->sws,418SVGA_STATS_COUNT_BLENDSTATE);419420return blend;421}422423424static void svga_bind_blend_state(struct pipe_context *pipe,425void *blend)426{427struct svga_context *svga = svga_context(pipe);428429svga->curr.blend = (struct svga_blend_state*)blend;430svga->dirty |= SVGA_NEW_BLEND;431}432433static void svga_delete_blend_state(struct pipe_context *pipe,434void *blend)435{436struct svga_context *svga = svga_context(pipe);437struct svga_blend_state *bs =438(struct svga_blend_state *) blend;439440if (svga_have_vgpu10(svga) && bs->id != SVGA3D_INVALID_ID) {441SVGA_RETRY(svga, SVGA3D_vgpu10_DestroyBlendState(svga->swc, bs->id));442443if (bs->id == svga->state.hw_draw.blend_id)444svga->state.hw_draw.blend_id = SVGA3D_INVALID_ID;445446util_bitmask_clear(svga->blend_object_id_bm, bs->id);447bs->id = SVGA3D_INVALID_ID;448}449450FREE(blend);451svga->hud.num_blend_objects--;452}453454static void svga_set_blend_color( struct pipe_context *pipe,455const struct pipe_blend_color *blend_color )456{457struct svga_context *svga = svga_context(pipe);458459svga->curr.blend_color = *blend_color;460461svga->dirty |= SVGA_NEW_BLEND_COLOR;462}463464465void svga_init_blend_functions( struct svga_context *svga )466{467svga->pipe.create_blend_state = svga_create_blend_state;468svga->pipe.bind_blend_state = svga_bind_blend_state;469svga->pipe.delete_blend_state = svga_delete_blend_state;470471svga->pipe.set_blend_color = svga_set_blend_color;472}473474475