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