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