xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/svga/svga_pipe_blend.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright (c) 2008-2024 Broadcom. All Rights Reserved.
3  * The term “Broadcom” refers to Broadcom Inc.
4  * and/or its subsidiaries.
5  * SPDX-License-Identifier: MIT
6  */
7 
8 #include "util/u_inlines.h"
9 #include "pipe/p_defines.h"
10 #include "util/u_math.h"
11 #include "util/u_memory.h"
12 #include "util/u_bitmask.h"
13 
14 #include "svga_context.h"
15 #include "svga_hw_reg.h"
16 #include "svga_cmd.h"
17 
18 
19 static inline unsigned
svga_translate_blend_factor(const struct svga_context * svga,unsigned factor)20 svga_translate_blend_factor(const struct svga_context *svga, unsigned factor)
21 {
22    /* Note: there is no SVGA3D_BLENDOP_[INV]BLENDFACTORALPHA so
23     * we can't translate PIPE_BLENDFACTOR_[INV_]CONST_ALPHA properly.
24     */
25    switch (factor) {
26    case PIPE_BLENDFACTOR_ZERO:            return SVGA3D_BLENDOP_ZERO;
27    case PIPE_BLENDFACTOR_SRC_ALPHA:       return SVGA3D_BLENDOP_SRCALPHA;
28    case PIPE_BLENDFACTOR_ONE:             return SVGA3D_BLENDOP_ONE;
29    case PIPE_BLENDFACTOR_SRC_COLOR:       return SVGA3D_BLENDOP_SRCCOLOR;
30    case PIPE_BLENDFACTOR_INV_SRC_COLOR:   return SVGA3D_BLENDOP_INVSRCCOLOR;
31    case PIPE_BLENDFACTOR_DST_COLOR:       return SVGA3D_BLENDOP_DESTCOLOR;
32    case PIPE_BLENDFACTOR_INV_DST_COLOR:   return SVGA3D_BLENDOP_INVDESTCOLOR;
33    case PIPE_BLENDFACTOR_INV_SRC_ALPHA:   return SVGA3D_BLENDOP_INVSRCALPHA;
34    case PIPE_BLENDFACTOR_DST_ALPHA:       return SVGA3D_BLENDOP_DESTALPHA;
35    case PIPE_BLENDFACTOR_INV_DST_ALPHA:   return SVGA3D_BLENDOP_INVDESTALPHA;
36    case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: return SVGA3D_BLENDOP_SRCALPHASAT;
37    case PIPE_BLENDFACTOR_CONST_COLOR:     return SVGA3D_BLENDOP_BLENDFACTOR;
38    case PIPE_BLENDFACTOR_INV_CONST_COLOR: return SVGA3D_BLENDOP_INVBLENDFACTOR;
39    case PIPE_BLENDFACTOR_CONST_ALPHA:
40       if (svga_have_vgpu10(svga))
41          return SVGA3D_BLENDOP_BLENDFACTORALPHA;
42       else
43          return SVGA3D_BLENDOP_BLENDFACTOR; /* as close as we can get */
44    case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
45       if (svga_have_vgpu10(svga))
46          return SVGA3D_BLENDOP_INVBLENDFACTORALPHA;
47       else
48          return SVGA3D_BLENDOP_INVBLENDFACTOR; /* as close as we can get */
49    case PIPE_BLENDFACTOR_SRC1_COLOR:      return SVGA3D_BLENDOP_SRC1COLOR;
50    case PIPE_BLENDFACTOR_INV_SRC1_COLOR:  return SVGA3D_BLENDOP_INVSRC1COLOR;
51    case PIPE_BLENDFACTOR_SRC1_ALPHA:      return SVGA3D_BLENDOP_SRC1ALPHA;
52    case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:  return SVGA3D_BLENDOP_INVSRC1ALPHA;
53    case 0:                                return SVGA3D_BLENDOP_ONE;
54    default:
55       assert(0);
56       return SVGA3D_BLENDOP_ZERO;
57    }
58 }
59 
60 static inline unsigned
svga_translate_blend_func(unsigned mode)61 svga_translate_blend_func(unsigned mode)
62 {
63    switch (mode) {
64    case PIPE_BLEND_ADD:              return SVGA3D_BLENDEQ_ADD;
65    case PIPE_BLEND_SUBTRACT:         return SVGA3D_BLENDEQ_SUBTRACT;
66    case PIPE_BLEND_REVERSE_SUBTRACT: return SVGA3D_BLENDEQ_REVSUBTRACT;
67    case PIPE_BLEND_MIN:              return SVGA3D_BLENDEQ_MINIMUM;
68    case PIPE_BLEND_MAX:              return SVGA3D_BLENDEQ_MAXIMUM;
69    default:
70       assert(0);
71       return SVGA3D_BLENDEQ_ADD;
72    }
73 }
74 
75 
76 /**
77  * Translate gallium logicop mode to SVGA3D logicop mode.
78  */
79 static int
translate_logicop(enum pipe_logicop op)80 translate_logicop(enum pipe_logicop op)
81 {
82    switch (op) {
83    case PIPE_LOGICOP_CLEAR:
84       return SVGA3D_DX11_LOGICOP_CLEAR;
85    case PIPE_LOGICOP_NOR:
86       return SVGA3D_DX11_LOGICOP_NOR;
87    case PIPE_LOGICOP_AND_INVERTED:
88       return SVGA3D_DX11_LOGICOP_AND_INVERTED;
89    case PIPE_LOGICOP_COPY_INVERTED:
90       return SVGA3D_DX11_LOGICOP_COPY_INVERTED;
91    case PIPE_LOGICOP_AND_REVERSE:
92       return SVGA3D_DX11_LOGICOP_AND_REVERSE;
93    case PIPE_LOGICOP_INVERT:
94       return SVGA3D_DX11_LOGICOP_INVERT;
95    case PIPE_LOGICOP_XOR:
96       return SVGA3D_DX11_LOGICOP_XOR;
97    case PIPE_LOGICOP_NAND:
98       return SVGA3D_DX11_LOGICOP_NAND;
99    case PIPE_LOGICOP_AND:
100       return SVGA3D_DX11_LOGICOP_AND;
101    case PIPE_LOGICOP_EQUIV:
102       return SVGA3D_DX11_LOGICOP_EQUIV;
103    case PIPE_LOGICOP_NOOP:
104       return SVGA3D_DX11_LOGICOP_NOOP;
105    case PIPE_LOGICOP_OR_INVERTED:
106       return SVGA3D_DX11_LOGICOP_OR_INVERTED;
107    case PIPE_LOGICOP_COPY:
108       return SVGA3D_DX11_LOGICOP_COPY;
109    case PIPE_LOGICOP_OR_REVERSE:
110       return SVGA3D_DX11_LOGICOP_OR_REVERSE;
111    case PIPE_LOGICOP_OR:
112       return SVGA3D_DX11_LOGICOP_OR;
113    case PIPE_LOGICOP_SET:
114       return SVGA3D_DX11_LOGICOP_SET;
115    default:
116       return SVGA3D_DX11_LOGICOP_COPY;
117    }
118 };
119 
120 
121 /**
122  * Define a vgpu10 blend state object for the given
123  * svga blend state.
124  */
125 static void
define_blend_state_object(struct svga_context * svga,struct svga_blend_state * bs)126 define_blend_state_object(struct svga_context *svga,
127                           struct svga_blend_state *bs)
128 {
129    SVGA3dDXBlendStatePerRT perRT[SVGA3D_MAX_RENDER_TARGETS];
130    int i;
131 
132    assert(svga_have_vgpu10(svga));
133 
134    bs->id = util_bitmask_add(svga->blend_object_id_bm);
135 
136    for (i = 0; i < SVGA3D_DX_MAX_RENDER_TARGETS; i++) {
137       perRT[i].blendEnable = bs->rt[i].blend_enable;
138       perRT[i].srcBlend = bs->rt[i].srcblend;
139       perRT[i].destBlend = bs->rt[i].dstblend;
140       perRT[i].blendOp = bs->rt[i].blendeq;
141       perRT[i].srcBlendAlpha = bs->rt[i].srcblend_alpha;
142       perRT[i].destBlendAlpha = bs->rt[i].dstblend_alpha;
143       perRT[i].blendOpAlpha = bs->rt[i].blendeq_alpha;
144       perRT[i].renderTargetWriteMask = bs->rt[i].writemask;
145       perRT[i].logicOpEnable = bs->logicop_enabled;
146       perRT[i].logicOp = bs->logicop_mode;
147    }
148 
149    SVGA_RETRY(svga, SVGA3D_vgpu10_DefineBlendState(svga->swc,
150                                                    bs->id,
151                                                    bs->alpha_to_coverage,
152                                                    bs->independent_blend_enable,
153                                                    perRT));
154 }
155 
156 
157 /**
158  * If SVGA3D_DEVCAP_LOGIC_BLENDOPS is false, we can't directly implement
159  * GL's logicops.  But we can emulate some of them.  We set up the blending
160  * state for that here.
161  */
162 static void
emulate_logicop(struct svga_context * svga,unsigned logicop_func,struct svga_blend_state * blend,unsigned buffer)163 emulate_logicop(struct svga_context *svga,
164                 unsigned logicop_func,
165                 struct svga_blend_state *blend,
166                 unsigned buffer)
167 {
168    switch (logicop_func) {
169    case PIPE_LOGICOP_XOR:
170    case PIPE_LOGICOP_INVERT:
171       blend->need_white_fragments = true;
172       blend->rt[buffer].blend_enable = true;
173       blend->rt[buffer].srcblend       = SVGA3D_BLENDOP_ONE;
174       blend->rt[buffer].dstblend       = SVGA3D_BLENDOP_ONE;
175       blend->rt[buffer].blendeq        = SVGA3D_BLENDEQ_SUBTRACT;
176       break;
177    case PIPE_LOGICOP_CLEAR:
178       blend->rt[buffer].blend_enable = true;
179       blend->rt[buffer].srcblend       = SVGA3D_BLENDOP_ZERO;
180       blend->rt[buffer].dstblend       = SVGA3D_BLENDOP_ZERO;
181       blend->rt[buffer].blendeq        = SVGA3D_BLENDEQ_MINIMUM;
182       break;
183    case PIPE_LOGICOP_COPY:
184       blend->rt[buffer].blend_enable = false;
185       blend->rt[buffer].srcblend       = SVGA3D_BLENDOP_ONE;
186       blend->rt[buffer].dstblend       = SVGA3D_BLENDOP_ZERO;
187       blend->rt[buffer].blendeq        = SVGA3D_BLENDEQ_ADD;
188       break;
189    case PIPE_LOGICOP_COPY_INVERTED:
190       blend->rt[buffer].blend_enable   = true;
191       blend->rt[buffer].srcblend       = SVGA3D_BLENDOP_INVSRCCOLOR;
192       blend->rt[buffer].dstblend       = SVGA3D_BLENDOP_ZERO;
193       blend->rt[buffer].blendeq        = SVGA3D_BLENDEQ_ADD;
194       break;
195    case PIPE_LOGICOP_NOOP:
196       blend->rt[buffer].blend_enable   = true;
197       blend->rt[buffer].srcblend       = SVGA3D_BLENDOP_ZERO;
198       blend->rt[buffer].dstblend       = SVGA3D_BLENDOP_DESTCOLOR;
199       blend->rt[buffer].blendeq        = SVGA3D_BLENDEQ_ADD;
200       break;
201    case PIPE_LOGICOP_SET:
202       blend->rt[buffer].blend_enable = true;
203       blend->rt[buffer].srcblend       = SVGA3D_BLENDOP_ONE;
204       blend->rt[buffer].dstblend       = SVGA3D_BLENDOP_ONE;
205       blend->rt[buffer].blendeq        = SVGA3D_BLENDEQ_MAXIMUM;
206       break;
207    case PIPE_LOGICOP_AND:
208       /* Approximate with minimum - works for the 0 & anything case: */
209       blend->rt[buffer].blend_enable = true;
210       blend->rt[buffer].srcblend       = SVGA3D_BLENDOP_SRCCOLOR;
211       blend->rt[buffer].dstblend       = SVGA3D_BLENDOP_DESTCOLOR;
212       blend->rt[buffer].blendeq        = SVGA3D_BLENDEQ_MINIMUM;
213       break;
214    case PIPE_LOGICOP_AND_REVERSE:
215       blend->rt[buffer].blend_enable = true;
216       blend->rt[buffer].srcblend       = SVGA3D_BLENDOP_SRCCOLOR;
217       blend->rt[buffer].dstblend       = SVGA3D_BLENDOP_INVDESTCOLOR;
218       blend->rt[buffer].blendeq        = SVGA3D_BLENDEQ_MINIMUM;
219       break;
220    case PIPE_LOGICOP_AND_INVERTED:
221       blend->rt[buffer].blend_enable = true;
222       blend->rt[buffer].srcblend       = SVGA3D_BLENDOP_INVSRCCOLOR;
223       blend->rt[buffer].dstblend       = SVGA3D_BLENDOP_DESTCOLOR;
224       blend->rt[buffer].blendeq        = SVGA3D_BLENDEQ_MINIMUM;
225       break;
226    case PIPE_LOGICOP_OR:
227       /* Approximate with maximum - works for the 1 | anything case: */
228       blend->rt[buffer].blend_enable = true;
229       blend->rt[buffer].srcblend       = SVGA3D_BLENDOP_SRCCOLOR;
230       blend->rt[buffer].dstblend       = SVGA3D_BLENDOP_DESTCOLOR;
231       blend->rt[buffer].blendeq        = SVGA3D_BLENDEQ_MAXIMUM;
232       break;
233    case PIPE_LOGICOP_OR_REVERSE:
234       blend->rt[buffer].blend_enable = true;
235       blend->rt[buffer].srcblend       = SVGA3D_BLENDOP_SRCCOLOR;
236       blend->rt[buffer].dstblend       = SVGA3D_BLENDOP_INVDESTCOLOR;
237       blend->rt[buffer].blendeq        = SVGA3D_BLENDEQ_MAXIMUM;
238       break;
239    case PIPE_LOGICOP_OR_INVERTED:
240       blend->rt[buffer].blend_enable = true;
241       blend->rt[buffer].srcblend       = SVGA3D_BLENDOP_INVSRCCOLOR;
242       blend->rt[buffer].dstblend       = SVGA3D_BLENDOP_DESTCOLOR;
243       blend->rt[buffer].blendeq        = SVGA3D_BLENDEQ_MAXIMUM;
244       break;
245    case PIPE_LOGICOP_NAND:
246    case PIPE_LOGICOP_NOR:
247    case PIPE_LOGICOP_EQUIV:
248       /* Fill these in with plausible values */
249       blend->rt[buffer].blend_enable = false;
250       blend->rt[buffer].srcblend       = SVGA3D_BLENDOP_ONE;
251       blend->rt[buffer].dstblend       = SVGA3D_BLENDOP_ZERO;
252       blend->rt[buffer].blendeq        = SVGA3D_BLENDEQ_ADD;
253       break;
254    default:
255       assert(0);
256       break;
257    }
258    blend->rt[buffer].srcblend_alpha = blend->rt[buffer].srcblend;
259    blend->rt[buffer].dstblend_alpha = blend->rt[buffer].dstblend;
260    blend->rt[buffer].blendeq_alpha = blend->rt[buffer].blendeq;
261 
262    if (logicop_func == PIPE_LOGICOP_XOR) {
263       util_debug_message(&svga->debug.callback, CONFORMANCE,
264                          "XOR logicop mode has limited support");
265    }
266    else if (logicop_func != PIPE_LOGICOP_COPY) {
267       util_debug_message(&svga->debug.callback, CONFORMANCE,
268                          "general logicops are not supported");
269    }
270 }
271 
272 
273 
274 static void *
svga_create_blend_state(struct pipe_context * pipe,const struct pipe_blend_state * templ)275 svga_create_blend_state(struct pipe_context *pipe,
276                         const struct pipe_blend_state *templ)
277 {
278    struct svga_context *svga = svga_context(pipe);
279    struct svga_screen *ss = svga_screen(pipe->screen);
280    struct svga_blend_state *blend = CALLOC_STRUCT( svga_blend_state );
281    unsigned i;
282 
283    if (!blend)
284       return NULL;
285 
286    /* Find index of first target with blending enabled.  If no blending is
287     * enabled at all, first_enabled will be zero.
288     */
289    unsigned first_enabled = 0;
290    for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
291       if (templ->rt[i].blend_enable) {
292          first_enabled = i;
293          break;
294       }
295    }
296 
297    /* Fill in the per-rendertarget blend state.  We currently only
298     * support independent blend enable and colormask per render target.
299     */
300    for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
301       /* No way to set this in SVGA3D, and no way to correctly implement it on
302        * top of D3D9 API.  Instead we try to simulate with various blend modes.
303        */
304       if (templ->logicop_enable) {
305          if (ss->haveBlendLogicops) {
306             blend->logicop_enabled = true;
307             blend->logicop_mode = translate_logicop(templ->logicop_func);
308             blend->rt[i].blendeq = SVGA3D_BLENDEQ_ADD;
309             blend->rt[i].blendeq_alpha = SVGA3D_BLENDEQ_ADD;
310             blend->rt[i].srcblend = SVGA3D_BLENDOP_ZERO;
311             blend->rt[i].dstblend = SVGA3D_BLENDOP_ZERO;
312             blend->rt[i].srcblend_alpha = SVGA3D_BLENDOP_ZERO;
313             blend->rt[i].dstblend_alpha = SVGA3D_BLENDOP_ZERO;
314          }
315          else {
316             emulate_logicop(svga, templ->logicop_func, blend, i);
317          }
318       }
319       else {
320          /* Note: per-target blend terms are only supported for sm4_1
321           * device. For vgpu10 device, the blending terms must be identical
322           * for all targets (this is why we need the first_enabled index).
323           */
324          const unsigned j =
325             svga_have_sm4_1(svga) && templ->independent_blend_enable
326             ? i : first_enabled;
327          if (templ->independent_blend_enable || templ->rt[j].blend_enable) {
328             blend->rt[i].srcblend =
329                svga_translate_blend_factor(svga, templ->rt[j].rgb_src_factor);
330             blend->rt[i].dstblend =
331                svga_translate_blend_factor(svga, templ->rt[j].rgb_dst_factor);
332             blend->rt[i].blendeq =
333                svga_translate_blend_func(templ->rt[j].rgb_func);
334             blend->rt[i].srcblend_alpha =
335                svga_translate_blend_factor(svga, templ->rt[j].alpha_src_factor);
336             blend->rt[i].dstblend_alpha =
337                svga_translate_blend_factor(svga, templ->rt[j].alpha_dst_factor);
338             blend->rt[i].blendeq_alpha =
339                svga_translate_blend_func(templ->rt[j].alpha_func);
340 
341             if (blend->rt[i].srcblend_alpha != blend->rt[i].srcblend ||
342                 blend->rt[i].dstblend_alpha != blend->rt[i].dstblend ||
343                 blend->rt[i].blendeq_alpha  != blend->rt[i].blendeq) {
344                blend->rt[i].separate_alpha_blend_enable = true;
345             }
346          }
347          else {
348             /* disabled - default blend terms */
349             blend->rt[i].srcblend = SVGA3D_BLENDOP_ONE;
350             blend->rt[i].dstblend = SVGA3D_BLENDOP_ZERO;
351             blend->rt[i].blendeq = SVGA3D_BLENDEQ_ADD;
352             blend->rt[i].srcblend_alpha = SVGA3D_BLENDOP_ONE;
353             blend->rt[i].dstblend_alpha = SVGA3D_BLENDOP_ZERO;
354             blend->rt[i].blendeq_alpha = SVGA3D_BLENDEQ_ADD;
355          }
356 
357          if (templ->independent_blend_enable) {
358             blend->rt[i].blend_enable = templ->rt[i].blend_enable;
359          }
360          else {
361             blend->rt[i].blend_enable = templ->rt[0].blend_enable;
362          }
363       }
364 
365       /* Some GL blend modes are not supported by the VGPU9 device (there's
366        * no equivalent of PIPE_BLENDFACTOR_[INV_]CONST_ALPHA).
367        * When we set this flag, we copy the constant blend alpha value
368        * to the R, G, B components.
369        * This works as long as the src/dst RGB blend factors doesn't use
370        * PIPE_BLENDFACTOR_CONST_COLOR and PIPE_BLENDFACTOR_CONST_ALPHA
371        * at the same time.  There's no work-around for that.
372        */
373       if (!svga_have_vgpu10(svga)) {
374          if (templ->rt[0].rgb_src_factor == PIPE_BLENDFACTOR_CONST_ALPHA ||
375              templ->rt[0].rgb_dst_factor == PIPE_BLENDFACTOR_CONST_ALPHA ||
376              templ->rt[0].rgb_src_factor == PIPE_BLENDFACTOR_INV_CONST_ALPHA ||
377              templ->rt[0].rgb_dst_factor == PIPE_BLENDFACTOR_INV_CONST_ALPHA) {
378             blend->blend_color_alpha = true;
379          }
380       }
381 
382       if (templ->independent_blend_enable) {
383          blend->rt[i].writemask = templ->rt[i].colormask;
384       }
385       else {
386          blend->rt[i].writemask = templ->rt[0].colormask;
387       }
388    }
389 
390    blend->independent_blend_enable = templ->independent_blend_enable;
391 
392    blend->alpha_to_coverage = templ->alpha_to_coverage;
393    blend->alpha_to_one = templ->alpha_to_one;
394 
395    if (svga_have_vgpu10(svga)) {
396       define_blend_state_object(svga, blend);
397    }
398 
399    svga->hud.num_blend_objects++;
400    SVGA_STATS_COUNT_INC(svga_screen(svga->pipe.screen)->sws,
401                         SVGA_STATS_COUNT_BLENDSTATE);
402 
403    return blend;
404 }
405 
406 
svga_bind_blend_state(struct pipe_context * pipe,void * blend)407 static void svga_bind_blend_state(struct pipe_context *pipe,
408                                   void *blend)
409 {
410    struct svga_context *svga = svga_context(pipe);
411 
412    svga->curr.blend = (struct svga_blend_state*)blend;
413    svga->dirty |= SVGA_NEW_BLEND;
414 }
415 
svga_delete_blend_state(struct pipe_context * pipe,void * blend)416 static void svga_delete_blend_state(struct pipe_context *pipe,
417                                     void *blend)
418 {
419    struct svga_context *svga = svga_context(pipe);
420    struct svga_blend_state *bs =
421       (struct svga_blend_state *) blend;
422 
423    if (svga_have_vgpu10(svga) && bs->id != SVGA3D_INVALID_ID) {
424       SVGA_RETRY(svga, SVGA3D_vgpu10_DestroyBlendState(svga->swc, bs->id));
425 
426       if (bs->id == svga->state.hw_draw.blend_id)
427          svga->state.hw_draw.blend_id = SVGA3D_INVALID_ID;
428 
429       util_bitmask_clear(svga->blend_object_id_bm, bs->id);
430       bs->id = SVGA3D_INVALID_ID;
431    }
432 
433    FREE(blend);
434    svga->hud.num_blend_objects--;
435 }
436 
svga_set_blend_color(struct pipe_context * pipe,const struct pipe_blend_color * blend_color)437 static void svga_set_blend_color( struct pipe_context *pipe,
438                                   const struct pipe_blend_color *blend_color )
439 {
440    struct svga_context *svga = svga_context(pipe);
441 
442    svga->curr.blend_color = *blend_color;
443 
444    svga->dirty |= SVGA_NEW_BLEND_COLOR;
445 }
446 
447 
svga_init_blend_functions(struct svga_context * svga)448 void svga_init_blend_functions( struct svga_context *svga )
449 {
450    svga->pipe.create_blend_state = svga_create_blend_state;
451    svga->pipe.bind_blend_state = svga_bind_blend_state;
452    svga->pipe.delete_blend_state = svga_delete_blend_state;
453 
454    svga->pipe.set_blend_color = svga_set_blend_color;
455 }
456