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