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
37static inline unsigned
38svga_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
78static inline unsigned
79svga_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 */
97static int
98translate_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 */
143static void
144define_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 */
180static void
181emulate_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      util_debug_message(&svga->debug.callback, CONFORMANCE,
282                         "XOR logicop mode has limited support");
283   }
284   else if (logicop_func != PIPE_LOGICOP_COPY) {
285      util_debug_message(&svga->debug.callback, CONFORMANCE,
286                         "general logicops are not supported");
287   }
288}
289
290
291
292static void *
293svga_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
425static 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
434static 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
455static 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
466void 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}
474