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 
31 #include "svga_context.h"
32 
33 #include "svga_hw_reg.h"
34 
35 
36 static INLINE unsigned
svga_translate_blend_factor(unsigned factor)37 svga_translate_blend_factor(unsigned factor)
38 {
39    switch (factor) {
40    case PIPE_BLENDFACTOR_ZERO:            return SVGA3D_BLENDOP_ZERO;
41    case PIPE_BLENDFACTOR_SRC_ALPHA:       return SVGA3D_BLENDOP_SRCALPHA;
42    case PIPE_BLENDFACTOR_ONE:             return SVGA3D_BLENDOP_ONE;
43    case PIPE_BLENDFACTOR_SRC_COLOR:       return SVGA3D_BLENDOP_SRCCOLOR;
44    case PIPE_BLENDFACTOR_INV_SRC_COLOR:   return SVGA3D_BLENDOP_INVSRCCOLOR;
45    case PIPE_BLENDFACTOR_DST_COLOR:       return SVGA3D_BLENDOP_DESTCOLOR;
46    case PIPE_BLENDFACTOR_INV_DST_COLOR:   return SVGA3D_BLENDOP_INVDESTCOLOR;
47    case PIPE_BLENDFACTOR_INV_SRC_ALPHA:   return SVGA3D_BLENDOP_INVSRCALPHA;
48    case PIPE_BLENDFACTOR_DST_ALPHA:       return SVGA3D_BLENDOP_DESTALPHA;
49    case PIPE_BLENDFACTOR_INV_DST_ALPHA:   return SVGA3D_BLENDOP_INVDESTALPHA;
50    case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: return SVGA3D_BLENDOP_SRCALPHASAT;
51    case PIPE_BLENDFACTOR_CONST_COLOR:     return SVGA3D_BLENDOP_BLENDFACTOR;
52    case PIPE_BLENDFACTOR_INV_CONST_COLOR: return SVGA3D_BLENDOP_INVBLENDFACTOR;
53    case PIPE_BLENDFACTOR_CONST_ALPHA:     return SVGA3D_BLENDOP_BLENDFACTOR; /* ? */
54    case PIPE_BLENDFACTOR_INV_CONST_ALPHA: return SVGA3D_BLENDOP_INVBLENDFACTOR; /* ? */
55    default:
56       assert(0);
57       return SVGA3D_BLENDOP_ZERO;
58    }
59 }
60 
61 static INLINE unsigned
svga_translate_blend_func(unsigned mode)62 svga_translate_blend_func(unsigned mode)
63 {
64    switch (mode) {
65    case PIPE_BLEND_ADD:              return SVGA3D_BLENDEQ_ADD;
66    case PIPE_BLEND_SUBTRACT:         return SVGA3D_BLENDEQ_SUBTRACT;
67    case PIPE_BLEND_REVERSE_SUBTRACT: return SVGA3D_BLENDEQ_REVSUBTRACT;
68    case PIPE_BLEND_MIN:              return SVGA3D_BLENDEQ_MINIMUM;
69    case PIPE_BLEND_MAX:              return SVGA3D_BLENDEQ_MAXIMUM;
70    default:
71       assert(0);
72       return SVGA3D_BLENDEQ_ADD;
73    }
74 }
75 
76 
77 static void *
svga_create_blend_state(struct pipe_context * pipe,const struct pipe_blend_state * templ)78 svga_create_blend_state(struct pipe_context *pipe,
79                         const struct pipe_blend_state *templ)
80 {
81    struct svga_blend_state *blend = CALLOC_STRUCT( svga_blend_state );
82    unsigned i;
83 
84 
85    /* Fill in the per-rendertarget blend state.  We currently only
86     * have one rendertarget.
87     */
88    for (i = 0; i < 1; i++) {
89       /* No way to set this in SVGA3D, and no way to correctly implement it on
90        * top of D3D9 API.  Instead we try to simulate with various blend modes.
91        */
92       if (templ->logicop_enable) {
93          switch (templ->logicop_func) {
94          case PIPE_LOGICOP_XOR:
95          case PIPE_LOGICOP_INVERT:
96             blend->need_white_fragments = TRUE;
97             blend->rt[i].blend_enable = TRUE;
98             blend->rt[i].srcblend       = SVGA3D_BLENDOP_ONE;
99             blend->rt[i].dstblend       = SVGA3D_BLENDOP_ONE;
100             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_SUBTRACT;
101             break;
102          case PIPE_LOGICOP_CLEAR:
103             blend->rt[i].blend_enable = TRUE;
104             blend->rt[i].srcblend       = SVGA3D_BLENDOP_ZERO;
105             blend->rt[i].dstblend       = SVGA3D_BLENDOP_ZERO;
106             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_MINIMUM;
107             break;
108          case PIPE_LOGICOP_COPY:
109             blend->rt[i].blend_enable = FALSE;
110             break;
111          case PIPE_LOGICOP_COPY_INVERTED:
112             blend->rt[i].blend_enable   = TRUE;
113             blend->rt[i].srcblend       = SVGA3D_BLENDOP_INVSRCCOLOR;
114             blend->rt[i].dstblend       = SVGA3D_BLENDOP_ZERO;
115             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_ADD;
116             break;
117          case PIPE_LOGICOP_NOOP:
118             blend->rt[i].blend_enable   = TRUE;
119             blend->rt[i].srcblend       = SVGA3D_BLENDOP_ZERO;
120             blend->rt[i].dstblend       = SVGA3D_BLENDOP_DESTCOLOR;
121             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_ADD;
122             break;
123          case PIPE_LOGICOP_SET:
124             blend->rt[i].blend_enable = TRUE;
125             blend->rt[i].srcblend       = SVGA3D_BLENDOP_ONE;
126             blend->rt[i].dstblend       = SVGA3D_BLENDOP_ONE;
127             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_MAXIMUM;
128             break;
129          case PIPE_LOGICOP_AND:
130             /* Approximate with minimum - works for the 0 & anything case: */
131             blend->rt[i].blend_enable = TRUE;
132             blend->rt[i].srcblend       = SVGA3D_BLENDOP_SRCCOLOR;
133             blend->rt[i].dstblend       = SVGA3D_BLENDOP_DESTCOLOR;
134             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_MINIMUM;
135             break;
136          case PIPE_LOGICOP_AND_REVERSE:
137             blend->rt[i].blend_enable = TRUE;
138             blend->rt[i].srcblend       = SVGA3D_BLENDOP_SRCCOLOR;
139             blend->rt[i].dstblend       = SVGA3D_BLENDOP_INVDESTCOLOR;
140             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_MINIMUM;
141             break;
142          case PIPE_LOGICOP_AND_INVERTED:
143             blend->rt[i].blend_enable = TRUE;
144             blend->rt[i].srcblend       = SVGA3D_BLENDOP_INVSRCCOLOR;
145             blend->rt[i].dstblend       = SVGA3D_BLENDOP_DESTCOLOR;
146             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_MINIMUM;
147             break;
148          case PIPE_LOGICOP_OR:
149             /* Approximate with maximum - works for the 1 | anything case: */
150             blend->rt[i].blend_enable = TRUE;
151             blend->rt[i].srcblend       = SVGA3D_BLENDOP_SRCCOLOR;
152             blend->rt[i].dstblend       = SVGA3D_BLENDOP_DESTCOLOR;
153             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_MAXIMUM;
154             break;
155          case PIPE_LOGICOP_OR_REVERSE:
156             blend->rt[i].blend_enable = TRUE;
157             blend->rt[i].srcblend       = SVGA3D_BLENDOP_SRCCOLOR;
158             blend->rt[i].dstblend       = SVGA3D_BLENDOP_INVDESTCOLOR;
159             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_MAXIMUM;
160             break;
161          case PIPE_LOGICOP_OR_INVERTED:
162             blend->rt[i].blend_enable = TRUE;
163             blend->rt[i].srcblend       = SVGA3D_BLENDOP_INVSRCCOLOR;
164             blend->rt[i].dstblend       = SVGA3D_BLENDOP_DESTCOLOR;
165             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_MAXIMUM;
166             break;
167          case PIPE_LOGICOP_NAND:
168          case PIPE_LOGICOP_NOR:
169          case PIPE_LOGICOP_EQUIV:
170             /* Fill these in with plausible values */
171             blend->rt[i].blend_enable = FALSE;
172             break;
173          default:
174             assert(0);
175             break;
176          }
177       }
178       else {
179          blend->rt[i].blend_enable   = templ->rt[0].blend_enable;
180 
181          if (templ->rt[0].blend_enable) {
182             blend->rt[i].srcblend       = svga_translate_blend_factor(templ->rt[0].rgb_src_factor);
183             blend->rt[i].dstblend       = svga_translate_blend_factor(templ->rt[0].rgb_dst_factor);
184             blend->rt[i].blendeq        = svga_translate_blend_func(templ->rt[0].rgb_func);
185             blend->rt[i].srcblend_alpha = svga_translate_blend_factor(templ->rt[0].alpha_src_factor);
186             blend->rt[i].dstblend_alpha = svga_translate_blend_factor(templ->rt[0].alpha_dst_factor);
187             blend->rt[i].blendeq_alpha  = svga_translate_blend_func(templ->rt[0].alpha_func);
188 
189             if (blend->rt[i].srcblend_alpha != blend->rt[i].srcblend ||
190                 blend->rt[i].dstblend_alpha != blend->rt[i].dstblend ||
191                 blend->rt[i].blendeq_alpha  != blend->rt[i].blendeq)
192             {
193                blend->rt[i].separate_alpha_blend_enable = TRUE;
194             }
195          }
196       }
197 
198       blend->rt[i].writemask = templ->rt[0].colormask;
199    }
200 
201    return blend;
202 }
203 
svga_bind_blend_state(struct pipe_context * pipe,void * blend)204 static void svga_bind_blend_state(struct pipe_context *pipe,
205                                   void *blend)
206 {
207    struct svga_context *svga = svga_context(pipe);
208 
209    svga->curr.blend = (struct svga_blend_state*)blend;
210    svga->dirty |= SVGA_NEW_BLEND;
211 }
212 
213 
svga_delete_blend_state(struct pipe_context * pipe,void * blend)214 static void svga_delete_blend_state(struct pipe_context *pipe, void *blend)
215 {
216    FREE(blend);
217 }
218 
svga_set_blend_color(struct pipe_context * pipe,const struct pipe_blend_color * blend_color)219 static void svga_set_blend_color( struct pipe_context *pipe,
220                                   const struct pipe_blend_color *blend_color )
221 {
222    struct svga_context *svga = svga_context(pipe);
223 
224    svga->curr.blend_color = *blend_color;
225 
226    svga->dirty |= SVGA_NEW_BLEND_COLOR;
227 }
228 
229 
svga_init_blend_functions(struct svga_context * svga)230 void svga_init_blend_functions( struct svga_context *svga )
231 {
232    svga->pipe.create_blend_state = svga_create_blend_state;
233    svga->pipe.bind_blend_state = svga_bind_blend_state;
234    svga->pipe.delete_blend_state = svga_delete_blend_state;
235 
236    svga->pipe.set_blend_color = svga_set_blend_color;
237 }
238 
239 
240 
241