svga: separate HUD counters for state objects
[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 switch (factor) {
41 case PIPE_BLENDFACTOR_ZERO: return SVGA3D_BLENDOP_ZERO;
42 case PIPE_BLENDFACTOR_SRC_ALPHA: return SVGA3D_BLENDOP_SRCALPHA;
43 case PIPE_BLENDFACTOR_ONE: return SVGA3D_BLENDOP_ONE;
44 case PIPE_BLENDFACTOR_SRC_COLOR: return SVGA3D_BLENDOP_SRCCOLOR;
45 case PIPE_BLENDFACTOR_INV_SRC_COLOR: return SVGA3D_BLENDOP_INVSRCCOLOR;
46 case PIPE_BLENDFACTOR_DST_COLOR: return SVGA3D_BLENDOP_DESTCOLOR;
47 case PIPE_BLENDFACTOR_INV_DST_COLOR: return SVGA3D_BLENDOP_INVDESTCOLOR;
48 case PIPE_BLENDFACTOR_INV_SRC_ALPHA: return SVGA3D_BLENDOP_INVSRCALPHA;
49 case PIPE_BLENDFACTOR_DST_ALPHA: return SVGA3D_BLENDOP_DESTALPHA;
50 case PIPE_BLENDFACTOR_INV_DST_ALPHA: return SVGA3D_BLENDOP_INVDESTALPHA;
51 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: return SVGA3D_BLENDOP_SRCALPHASAT;
52 case PIPE_BLENDFACTOR_CONST_COLOR: return SVGA3D_BLENDOP_BLENDFACTOR;
53 case PIPE_BLENDFACTOR_INV_CONST_COLOR: return SVGA3D_BLENDOP_INVBLENDFACTOR;
54 case PIPE_BLENDFACTOR_CONST_ALPHA:
55 if (svga_have_vgpu10(svga))
56 return SVGA3D_BLENDOP_BLENDFACTORALPHA;
57 else
58 return SVGA3D_BLENDOP_BLENDFACTOR; /* as close as we can get */
59 case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
60 if (svga_have_vgpu10(svga))
61 return SVGA3D_BLENDOP_INVBLENDFACTORALPHA;
62 else
63 return SVGA3D_BLENDOP_INVBLENDFACTOR; /* as close as we can get */
64 case PIPE_BLENDFACTOR_SRC1_COLOR: return SVGA3D_BLENDOP_SRC1COLOR;
65 case PIPE_BLENDFACTOR_INV_SRC1_COLOR: return SVGA3D_BLENDOP_INVSRC1COLOR;
66 case PIPE_BLENDFACTOR_SRC1_ALPHA: return SVGA3D_BLENDOP_SRC1ALPHA;
67 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: return SVGA3D_BLENDOP_INVSRC1ALPHA;
68 case 0: return SVGA3D_BLENDOP_ONE;
69 default:
70 assert(0);
71 return SVGA3D_BLENDOP_ZERO;
72 }
73 }
74
75 static inline unsigned
76 svga_translate_blend_func(unsigned mode)
77 {
78 switch (mode) {
79 case PIPE_BLEND_ADD: return SVGA3D_BLENDEQ_ADD;
80 case PIPE_BLEND_SUBTRACT: return SVGA3D_BLENDEQ_SUBTRACT;
81 case PIPE_BLEND_REVERSE_SUBTRACT: return SVGA3D_BLENDEQ_REVSUBTRACT;
82 case PIPE_BLEND_MIN: return SVGA3D_BLENDEQ_MINIMUM;
83 case PIPE_BLEND_MAX: return SVGA3D_BLENDEQ_MAXIMUM;
84 default:
85 assert(0);
86 return SVGA3D_BLENDEQ_ADD;
87 }
88 }
89
90
91 /**
92 * Define a vgpu10 blend state object for the given
93 * svga blend state.
94 */
95 static void
96 define_blend_state_object(struct svga_context *svga,
97 struct svga_blend_state *bs)
98 {
99 SVGA3dDXBlendStatePerRT perRT[SVGA3D_MAX_RENDER_TARGETS];
100 unsigned try;
101 int i;
102
103 assert(svga_have_vgpu10(svga));
104
105 bs->id = util_bitmask_add(svga->blend_object_id_bm);
106
107 for (i = 0; i < SVGA3D_DX_MAX_RENDER_TARGETS; i++) {
108 perRT[i].blendEnable = bs->rt[i].blend_enable;
109 perRT[i].srcBlend = bs->rt[i].srcblend;
110 perRT[i].destBlend = bs->rt[i].dstblend;
111 perRT[i].blendOp = bs->rt[i].blendeq;
112 perRT[i].srcBlendAlpha = bs->rt[i].srcblend_alpha;
113 perRT[i].destBlendAlpha = bs->rt[i].dstblend_alpha;
114 perRT[i].blendOpAlpha = bs->rt[i].blendeq_alpha;
115 perRT[i].renderTargetWriteMask = bs->rt[i].writemask;
116 perRT[i].logicOpEnable = 0;
117 perRT[i].logicOp = SVGA3D_LOGICOP_COPY;
118 assert(perRT[i].srcBlend == perRT[0].srcBlend);
119 }
120
121 /* Loop in case command buffer is full and we need to flush and retry */
122 for (try = 0; try < 2; try++) {
123 enum pipe_error ret;
124
125 ret = SVGA3D_vgpu10_DefineBlendState(svga->swc,
126 bs->id,
127 bs->alpha_to_coverage,
128 bs->independent_blend_enable,
129 perRT);
130 if (ret == PIPE_OK)
131 return;
132 svga_context_flush(svga, NULL);
133 }
134 }
135
136
137 static void *
138 svga_create_blend_state(struct pipe_context *pipe,
139 const struct pipe_blend_state *templ)
140 {
141 struct svga_context *svga = svga_context(pipe);
142 struct svga_blend_state *blend = CALLOC_STRUCT( svga_blend_state );
143 unsigned i;
144
145 if (!blend)
146 return NULL;
147
148 /* Fill in the per-rendertarget blend state. We currently only
149 * support independent blend enable and colormask per render target.
150 */
151 for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
152 /* No way to set this in SVGA3D, and no way to correctly implement it on
153 * top of D3D9 API. Instead we try to simulate with various blend modes.
154 */
155 if (templ->logicop_enable) {
156 switch (templ->logicop_func) {
157 case PIPE_LOGICOP_XOR:
158 case PIPE_LOGICOP_INVERT:
159 blend->need_white_fragments = TRUE;
160 blend->rt[i].blend_enable = TRUE;
161 blend->rt[i].srcblend = SVGA3D_BLENDOP_ONE;
162 blend->rt[i].dstblend = SVGA3D_BLENDOP_ONE;
163 blend->rt[i].blendeq = SVGA3D_BLENDEQ_SUBTRACT;
164 break;
165 case PIPE_LOGICOP_CLEAR:
166 blend->rt[i].blend_enable = TRUE;
167 blend->rt[i].srcblend = SVGA3D_BLENDOP_ZERO;
168 blend->rt[i].dstblend = SVGA3D_BLENDOP_ZERO;
169 blend->rt[i].blendeq = SVGA3D_BLENDEQ_MINIMUM;
170 break;
171 case PIPE_LOGICOP_COPY:
172 blend->rt[i].blend_enable = FALSE;
173 blend->rt[i].srcblend = SVGA3D_BLENDOP_ONE;
174 blend->rt[i].dstblend = SVGA3D_BLENDOP_ZERO;
175 blend->rt[i].blendeq = SVGA3D_BLENDEQ_ADD;
176 break;
177 case PIPE_LOGICOP_COPY_INVERTED:
178 blend->rt[i].blend_enable = TRUE;
179 blend->rt[i].srcblend = SVGA3D_BLENDOP_INVSRCCOLOR;
180 blend->rt[i].dstblend = SVGA3D_BLENDOP_ZERO;
181 blend->rt[i].blendeq = SVGA3D_BLENDEQ_ADD;
182 break;
183 case PIPE_LOGICOP_NOOP:
184 blend->rt[i].blend_enable = TRUE;
185 blend->rt[i].srcblend = SVGA3D_BLENDOP_ZERO;
186 blend->rt[i].dstblend = SVGA3D_BLENDOP_DESTCOLOR;
187 blend->rt[i].blendeq = SVGA3D_BLENDEQ_ADD;
188 break;
189 case PIPE_LOGICOP_SET:
190 blend->rt[i].blend_enable = TRUE;
191 blend->rt[i].srcblend = SVGA3D_BLENDOP_ONE;
192 blend->rt[i].dstblend = SVGA3D_BLENDOP_ONE;
193 blend->rt[i].blendeq = SVGA3D_BLENDEQ_MAXIMUM;
194 break;
195 case PIPE_LOGICOP_AND:
196 /* Approximate with minimum - works for the 0 & anything case: */
197 blend->rt[i].blend_enable = TRUE;
198 blend->rt[i].srcblend = SVGA3D_BLENDOP_SRCCOLOR;
199 blend->rt[i].dstblend = SVGA3D_BLENDOP_DESTCOLOR;
200 blend->rt[i].blendeq = SVGA3D_BLENDEQ_MINIMUM;
201 break;
202 case PIPE_LOGICOP_AND_REVERSE:
203 blend->rt[i].blend_enable = TRUE;
204 blend->rt[i].srcblend = SVGA3D_BLENDOP_SRCCOLOR;
205 blend->rt[i].dstblend = SVGA3D_BLENDOP_INVDESTCOLOR;
206 blend->rt[i].blendeq = SVGA3D_BLENDEQ_MINIMUM;
207 break;
208 case PIPE_LOGICOP_AND_INVERTED:
209 blend->rt[i].blend_enable = TRUE;
210 blend->rt[i].srcblend = SVGA3D_BLENDOP_INVSRCCOLOR;
211 blend->rt[i].dstblend = SVGA3D_BLENDOP_DESTCOLOR;
212 blend->rt[i].blendeq = SVGA3D_BLENDEQ_MINIMUM;
213 break;
214 case PIPE_LOGICOP_OR:
215 /* Approximate with maximum - works for the 1 | anything case: */
216 blend->rt[i].blend_enable = TRUE;
217 blend->rt[i].srcblend = SVGA3D_BLENDOP_SRCCOLOR;
218 blend->rt[i].dstblend = SVGA3D_BLENDOP_DESTCOLOR;
219 blend->rt[i].blendeq = SVGA3D_BLENDEQ_MAXIMUM;
220 break;
221 case PIPE_LOGICOP_OR_REVERSE:
222 blend->rt[i].blend_enable = TRUE;
223 blend->rt[i].srcblend = SVGA3D_BLENDOP_SRCCOLOR;
224 blend->rt[i].dstblend = SVGA3D_BLENDOP_INVDESTCOLOR;
225 blend->rt[i].blendeq = SVGA3D_BLENDEQ_MAXIMUM;
226 break;
227 case PIPE_LOGICOP_OR_INVERTED:
228 blend->rt[i].blend_enable = TRUE;
229 blend->rt[i].srcblend = SVGA3D_BLENDOP_INVSRCCOLOR;
230 blend->rt[i].dstblend = SVGA3D_BLENDOP_DESTCOLOR;
231 blend->rt[i].blendeq = SVGA3D_BLENDEQ_MAXIMUM;
232 break;
233 case PIPE_LOGICOP_NAND:
234 case PIPE_LOGICOP_NOR:
235 case PIPE_LOGICOP_EQUIV:
236 /* Fill these in with plausible values */
237 blend->rt[i].blend_enable = FALSE;
238 blend->rt[i].srcblend = SVGA3D_BLENDOP_ONE;
239 blend->rt[i].dstblend = SVGA3D_BLENDOP_ZERO;
240 blend->rt[i].blendeq = SVGA3D_BLENDEQ_ADD;
241 break;
242 default:
243 assert(0);
244 break;
245 }
246 blend->rt[i].srcblend_alpha = blend->rt[i].srcblend;
247 blend->rt[i].dstblend_alpha = blend->rt[i].dstblend;
248 blend->rt[i].blendeq_alpha = blend->rt[i].blendeq;
249
250 if (templ->logicop_func == PIPE_LOGICOP_XOR) {
251 pipe_debug_message(&svga->debug.callback, CONFORMANCE,
252 "XOR logicop mode has limited support");
253 }
254 else if (templ->logicop_func != PIPE_LOGICOP_COPY) {
255 pipe_debug_message(&svga->debug.callback, CONFORMANCE,
256 "general logicops are not supported");
257 }
258 }
259 else {
260 /* Note: the vgpu10 device does not yet support independent
261 * blend terms per render target. Target[0] always specifies the
262 * blending terms.
263 */
264 if (templ->independent_blend_enable || templ->rt[0].blend_enable) {
265 /* always use the 0th target's blending terms for now */
266 blend->rt[i].srcblend =
267 svga_translate_blend_factor(svga, templ->rt[0].rgb_src_factor);
268 blend->rt[i].dstblend =
269 svga_translate_blend_factor(svga, templ->rt[0].rgb_dst_factor);
270 blend->rt[i].blendeq =
271 svga_translate_blend_func(templ->rt[0].rgb_func);
272 blend->rt[i].srcblend_alpha =
273 svga_translate_blend_factor(svga, templ->rt[0].alpha_src_factor);
274 blend->rt[i].dstblend_alpha =
275 svga_translate_blend_factor(svga, templ->rt[0].alpha_dst_factor);
276 blend->rt[i].blendeq_alpha =
277 svga_translate_blend_func(templ->rt[0].alpha_func);
278
279 if (blend->rt[i].srcblend_alpha != blend->rt[i].srcblend ||
280 blend->rt[i].dstblend_alpha != blend->rt[i].dstblend ||
281 blend->rt[i].blendeq_alpha != blend->rt[i].blendeq) {
282 blend->rt[i].separate_alpha_blend_enable = TRUE;
283 }
284 }
285 else {
286 /* disabled - default blend terms */
287 blend->rt[i].srcblend = SVGA3D_BLENDOP_ONE;
288 blend->rt[i].dstblend = SVGA3D_BLENDOP_ZERO;
289 blend->rt[i].blendeq = SVGA3D_BLENDEQ_ADD;
290 blend->rt[i].srcblend_alpha = SVGA3D_BLENDOP_ONE;
291 blend->rt[i].dstblend_alpha = SVGA3D_BLENDOP_ZERO;
292 blend->rt[i].blendeq_alpha = SVGA3D_BLENDEQ_ADD;
293 }
294
295 if (templ->independent_blend_enable) {
296 blend->rt[i].blend_enable = templ->rt[i].blend_enable;
297 }
298 else {
299 blend->rt[i].blend_enable = templ->rt[0].blend_enable;
300 }
301 }
302
303 /* Some GL blend modes are not supported by the VGPU9 device (there's
304 * no equivalent of PIPE_BLENDFACTOR_[INV_]CONST_ALPHA).
305 * When we set this flag, we copy the constant blend alpha value
306 * to the R, G, B components.
307 * This works as long as the src/dst RGB blend factors doesn't use
308 * PIPE_BLENDFACTOR_CONST_COLOR and PIPE_BLENDFACTOR_CONST_ALPHA
309 * at the same time. There's no work-around for that.
310 */
311 if (!svga_have_vgpu10(svga)) {
312 if (templ->rt[0].rgb_src_factor == PIPE_BLENDFACTOR_CONST_ALPHA ||
313 templ->rt[0].rgb_dst_factor == PIPE_BLENDFACTOR_CONST_ALPHA ||
314 templ->rt[0].rgb_src_factor == PIPE_BLENDFACTOR_INV_CONST_ALPHA ||
315 templ->rt[0].rgb_dst_factor == PIPE_BLENDFACTOR_INV_CONST_ALPHA) {
316 blend->blend_color_alpha = TRUE;
317 }
318 }
319
320 if (templ->independent_blend_enable) {
321 blend->rt[i].writemask = templ->rt[i].colormask;
322 }
323 else {
324 blend->rt[i].writemask = templ->rt[0].colormask;
325 }
326 }
327
328 blend->independent_blend_enable = templ->independent_blend_enable;
329
330 blend->alpha_to_coverage = templ->alpha_to_coverage;
331
332 if (svga_have_vgpu10(svga)) {
333 define_blend_state_object(svga, blend);
334 }
335
336 svga->hud.num_blend_objects++;
337
338 return blend;
339 }
340
341
342 static void svga_bind_blend_state(struct pipe_context *pipe,
343 void *blend)
344 {
345 struct svga_context *svga = svga_context(pipe);
346
347 svga->curr.blend = (struct svga_blend_state*)blend;
348 svga->dirty |= SVGA_NEW_BLEND;
349 }
350
351 static void svga_delete_blend_state(struct pipe_context *pipe,
352 void *blend)
353 {
354 struct svga_context *svga = svga_context(pipe);
355 struct svga_blend_state *bs =
356 (struct svga_blend_state *) blend;
357
358 if (bs->id != SVGA3D_INVALID_ID) {
359 enum pipe_error ret;
360
361 ret = SVGA3D_vgpu10_DestroyBlendState(svga->swc, bs->id);
362 if (ret != PIPE_OK) {
363 svga_context_flush(svga, NULL);
364 ret = SVGA3D_vgpu10_DestroyBlendState(svga->swc, bs->id);
365 assert(ret == PIPE_OK);
366 }
367
368 if (bs->id == svga->state.hw_draw.blend_id)
369 svga->state.hw_draw.blend_id = SVGA3D_INVALID_ID;
370
371 util_bitmask_clear(svga->blend_object_id_bm, bs->id);
372 bs->id = SVGA3D_INVALID_ID;
373 }
374
375 FREE(blend);
376 svga->hud.num_blend_objects--;
377 }
378
379 static void svga_set_blend_color( struct pipe_context *pipe,
380 const struct pipe_blend_color *blend_color )
381 {
382 struct svga_context *svga = svga_context(pipe);
383
384 svga->curr.blend_color = *blend_color;
385
386 svga->dirty |= SVGA_NEW_BLEND_COLOR;
387 }
388
389
390 void svga_init_blend_functions( struct svga_context *svga )
391 {
392 svga->pipe.create_blend_state = svga_create_blend_state;
393 svga->pipe.bind_blend_state = svga_bind_blend_state;
394 svga->pipe.delete_blend_state = svga_delete_blend_state;
395
396 svga->pipe.set_blend_color = svga_set_blend_color;
397 }