• 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 "pipe/p_defines.h"
27 #include "util/u_bitmask.h"
28 #include "util/u_format.h"
29 #include "util/u_inlines.h"
30 #include "util/u_memory.h"
31 #include "util/u_math.h"
32 #include "util/u_memory.h"
33 
34 #include "svga_context.h"
35 #include "svga_screen.h"
36 #include "svga_state.h"
37 #include "svga_cmd.h"
38 #include "svga_format.h"
39 #include "svga_shader.h"
40 
41 
42 struct rs_queue {
43    unsigned rs_count;
44    SVGA3dRenderState rs[SVGA3D_RS_MAX];
45 };
46 
47 
48 #define EMIT_RS(svga, value, token, fail)                       \
49 do {                                                            \
50    STATIC_ASSERT(SVGA3D_RS_##token < ARRAY_SIZE(svga->state.hw_draw.rs)); \
51    if (svga->state.hw_draw.rs[SVGA3D_RS_##token] != value) {    \
52       svga_queue_rs( &queue, SVGA3D_RS_##token, value );        \
53       svga->state.hw_draw.rs[SVGA3D_RS_##token] = value;        \
54    }                                                            \
55 } while (0)
56 
57 #define EMIT_RS_FLOAT(svga, fvalue, token, fail)                \
58 do {                                                            \
59    unsigned value = fui(fvalue);                                \
60    STATIC_ASSERT(SVGA3D_RS_##token < ARRAY_SIZE(svga->state.hw_draw.rs)); \
61    if (svga->state.hw_draw.rs[SVGA3D_RS_##token] != value) {    \
62       svga_queue_rs( &queue, SVGA3D_RS_##token, value );        \
63       svga->state.hw_draw.rs[SVGA3D_RS_##token] = value;        \
64    }                                                            \
65 } while (0)
66 
67 
68 static inline void
svga_queue_rs(struct rs_queue * q,unsigned rss,unsigned value)69 svga_queue_rs( struct rs_queue *q,
70                unsigned rss,
71                unsigned value )
72 {
73    q->rs[q->rs_count].state = rss;
74    q->rs[q->rs_count].uintValue = value;
75    q->rs_count++;
76 }
77 
78 
79 /* Compare old and new render states and emit differences between them
80  * to hardware.  Simplest implementation would be to emit the whole of
81  * the "to" state.
82  */
83 static enum pipe_error
emit_rss_vgpu9(struct svga_context * svga,unsigned dirty)84 emit_rss_vgpu9(struct svga_context *svga, unsigned dirty)
85 {
86    struct svga_screen *screen = svga_screen(svga->pipe.screen);
87    struct rs_queue queue;
88    float point_size_min;
89 
90    queue.rs_count = 0;
91 
92    if (dirty & (SVGA_NEW_BLEND | SVGA_NEW_BLEND_COLOR)) {
93       const struct svga_blend_state *curr = svga->curr.blend;
94 
95       EMIT_RS( svga, curr->rt[0].writemask, COLORWRITEENABLE, fail );
96       EMIT_RS( svga, curr->rt[0].blend_enable, BLENDENABLE, fail );
97 
98       if (curr->rt[0].blend_enable) {
99          EMIT_RS( svga, curr->rt[0].srcblend, SRCBLEND, fail );
100          EMIT_RS( svga, curr->rt[0].dstblend, DSTBLEND, fail );
101          EMIT_RS( svga, curr->rt[0].blendeq, BLENDEQUATION, fail );
102 
103          EMIT_RS( svga, curr->rt[0].separate_alpha_blend_enable,
104                   SEPARATEALPHABLENDENABLE, fail );
105 
106          if (curr->rt[0].separate_alpha_blend_enable) {
107             EMIT_RS( svga, curr->rt[0].srcblend_alpha, SRCBLENDALPHA, fail );
108             EMIT_RS( svga, curr->rt[0].dstblend_alpha, DSTBLENDALPHA, fail );
109             EMIT_RS( svga, curr->rt[0].blendeq_alpha, BLENDEQUATIONALPHA, fail );
110          }
111       }
112    }
113 
114    if (dirty & SVGA_NEW_BLEND_COLOR) {
115       uint32 color;
116       uint32 r = float_to_ubyte(svga->curr.blend_color.color[0]);
117       uint32 g = float_to_ubyte(svga->curr.blend_color.color[1]);
118       uint32 b = float_to_ubyte(svga->curr.blend_color.color[2]);
119       uint32 a = float_to_ubyte(svga->curr.blend_color.color[3]);
120 
121       color = (a << 24) | (r << 16) | (g << 8) | b;
122 
123       EMIT_RS( svga, color, BLENDCOLOR, fail );
124    }
125 
126    if (dirty & (SVGA_NEW_DEPTH_STENCIL_ALPHA | SVGA_NEW_RAST)) {
127       const struct svga_depth_stencil_state *curr = svga->curr.depth;
128       const struct svga_rasterizer_state *rast = svga->curr.rast;
129 
130       if (!curr->stencil[0].enabled)
131       {
132          /* Stencil disabled
133           */
134          EMIT_RS( svga, FALSE, STENCILENABLE, fail );
135          EMIT_RS( svga, FALSE, STENCILENABLE2SIDED, fail );
136       }
137       else if (curr->stencil[0].enabled && !curr->stencil[1].enabled)
138       {
139          /* Regular stencil
140           */
141          EMIT_RS( svga, TRUE, STENCILENABLE, fail );
142          EMIT_RS( svga, FALSE, STENCILENABLE2SIDED, fail );
143 
144          EMIT_RS( svga, curr->stencil[0].func,  STENCILFUNC, fail );
145          EMIT_RS( svga, curr->stencil[0].fail,  STENCILFAIL, fail );
146          EMIT_RS( svga, curr->stencil[0].zfail, STENCILZFAIL, fail );
147          EMIT_RS( svga, curr->stencil[0].pass,  STENCILPASS, fail );
148 
149          EMIT_RS( svga, curr->stencil_mask, STENCILMASK, fail );
150          EMIT_RS( svga, curr->stencil_writemask, STENCILWRITEMASK, fail );
151       }
152       else
153       {
154          int cw, ccw;
155 
156          /* Hardware frontwinding is always CW, so if ours is also CW,
157           * then our definition of front face agrees with hardware.
158           * Otherwise need to flip.
159           */
160          if (rast->templ.front_ccw) {
161             ccw = 0;
162             cw = 1;
163          }
164          else {
165             ccw = 1;
166             cw = 0;
167          }
168 
169          /* Twoside stencil
170           */
171          EMIT_RS( svga, TRUE, STENCILENABLE, fail );
172          EMIT_RS( svga, TRUE, STENCILENABLE2SIDED, fail );
173 
174          EMIT_RS( svga, curr->stencil[cw].func,  STENCILFUNC, fail );
175          EMIT_RS( svga, curr->stencil[cw].fail,  STENCILFAIL, fail );
176          EMIT_RS( svga, curr->stencil[cw].zfail, STENCILZFAIL, fail );
177          EMIT_RS( svga, curr->stencil[cw].pass,  STENCILPASS, fail );
178 
179          EMIT_RS( svga, curr->stencil[ccw].func,  CCWSTENCILFUNC, fail );
180          EMIT_RS( svga, curr->stencil[ccw].fail,  CCWSTENCILFAIL, fail );
181          EMIT_RS( svga, curr->stencil[ccw].zfail, CCWSTENCILZFAIL, fail );
182          EMIT_RS( svga, curr->stencil[ccw].pass,  CCWSTENCILPASS, fail );
183 
184          EMIT_RS( svga, curr->stencil_mask, STENCILMASK, fail );
185          EMIT_RS( svga, curr->stencil_writemask, STENCILWRITEMASK, fail );
186       }
187 
188       EMIT_RS( svga, curr->zenable, ZENABLE, fail );
189       if (curr->zenable) {
190          EMIT_RS( svga, curr->zfunc, ZFUNC, fail );
191          EMIT_RS( svga, curr->zwriteenable, ZWRITEENABLE, fail );
192       }
193 
194       EMIT_RS( svga, curr->alphatestenable, ALPHATESTENABLE, fail );
195       if (curr->alphatestenable) {
196          EMIT_RS( svga, curr->alphafunc, ALPHAFUNC, fail );
197          EMIT_RS_FLOAT( svga, curr->alpharef, ALPHAREF, fail );
198       }
199    }
200 
201    if (dirty & SVGA_NEW_STENCIL_REF) {
202       EMIT_RS( svga, svga->curr.stencil_ref.ref_value[0], STENCILREF, fail );
203    }
204 
205    if (dirty & (SVGA_NEW_RAST | SVGA_NEW_NEED_PIPELINE))
206    {
207       const struct svga_rasterizer_state *curr = svga->curr.rast;
208       unsigned cullmode = curr->cullmode;
209 
210       /* Shademode: still need to rearrange index list to move
211        * flat-shading PV first vertex.
212        */
213       EMIT_RS( svga, curr->shademode, SHADEMODE, fail );
214 
215       /* Don't do culling while the software pipeline is active.  It
216        * does it for us, and additionally introduces potentially
217        * back-facing triangles.
218        */
219       if (svga->state.sw.need_pipeline)
220          cullmode = SVGA3D_FACE_NONE;
221 
222       point_size_min = util_get_min_point_size(&curr->templ);
223 
224       EMIT_RS( svga, cullmode, CULLMODE, fail );
225       EMIT_RS( svga, curr->scissortestenable, SCISSORTESTENABLE, fail );
226       EMIT_RS( svga, curr->multisampleantialias, MULTISAMPLEANTIALIAS, fail );
227       EMIT_RS( svga, curr->lastpixel, LASTPIXEL, fail );
228       EMIT_RS_FLOAT( svga, curr->pointsize, POINTSIZE, fail );
229       EMIT_RS_FLOAT( svga, point_size_min, POINTSIZEMIN, fail );
230       EMIT_RS_FLOAT( svga, screen->maxPointSize, POINTSIZEMAX, fail );
231       EMIT_RS( svga, curr->pointsprite, POINTSPRITEENABLE, fail);
232 
233       /* Emit line state, when the device understands it */
234       if (screen->haveLineStipple)
235          EMIT_RS( svga, curr->linepattern, LINEPATTERN, fail );
236       if (screen->haveLineSmooth)
237          EMIT_RS( svga, curr->antialiasedlineenable, ANTIALIASEDLINEENABLE, fail );
238       if (screen->maxLineWidth > 1.0F)
239          EMIT_RS_FLOAT( svga, curr->linewidth, LINEWIDTH, fail );
240    }
241 
242    if (dirty & (SVGA_NEW_RAST | SVGA_NEW_FRAME_BUFFER | SVGA_NEW_NEED_PIPELINE))
243    {
244       const struct svga_rasterizer_state *curr = svga->curr.rast;
245       float slope = 0.0;
246       float bias  = 0.0;
247 
248       /* Need to modify depth bias according to bound depthbuffer
249        * format.  Don't do hardware depthbias while the software
250        * pipeline is active.
251        */
252       if (!svga->state.sw.need_pipeline &&
253           svga->curr.framebuffer.zsbuf)
254       {
255          slope = curr->slopescaledepthbias;
256          bias  = svga->curr.depthscale * curr->depthbias;
257       }
258 
259       EMIT_RS_FLOAT( svga, slope, SLOPESCALEDEPTHBIAS, fail );
260       EMIT_RS_FLOAT( svga, bias, DEPTHBIAS, fail );
261    }
262 
263    if (dirty & SVGA_NEW_FRAME_BUFFER) {
264       /* XXX: we only look at the first color buffer's sRGB state */
265       float gamma = 1.0f;
266       if (svga->curr.framebuffer.cbufs[0] &&
267           util_format_is_srgb(svga->curr.framebuffer.cbufs[0]->format)) {
268          gamma = 2.2f;
269       }
270       EMIT_RS_FLOAT(svga, gamma, OUTPUTGAMMA, fail);
271    }
272 
273    if (dirty & SVGA_NEW_RAST) {
274       /* bitmask of the enabled clip planes */
275       unsigned enabled = svga->curr.rast->templ.clip_plane_enable;
276       EMIT_RS( svga, enabled, CLIPPLANEENABLE, fail );
277    }
278 
279    if (queue.rs_count) {
280       SVGA3dRenderState *rs;
281 
282       if (SVGA3D_BeginSetRenderState( svga->swc,
283                                       &rs,
284                                       queue.rs_count ) != PIPE_OK)
285          goto fail;
286 
287       memcpy( rs,
288               queue.rs,
289               queue.rs_count * sizeof queue.rs[0]);
290 
291       SVGA_FIFOCommitAll( svga->swc );
292    }
293 
294    return PIPE_OK;
295 
296 fail:
297    /* XXX: need to poison cached hardware state on failure to ensure
298     * dirty state gets re-emitted.  Fix this by re-instating partial
299     * FIFOCommit command and only updating cached hw state once the
300     * initial allocation has succeeded.
301     */
302    memset(svga->state.hw_draw.rs, 0xcd, sizeof(svga->state.hw_draw.rs));
303 
304    return PIPE_ERROR_OUT_OF_MEMORY;
305 }
306 
307 /** Returns a non-culling rasterizer state object to be used with
308  *  point sprite.
309  */
310 static struct svga_rasterizer_state *
get_no_cull_rasterizer_state(struct svga_context * svga)311 get_no_cull_rasterizer_state(struct svga_context *svga)
312 {
313    const struct svga_rasterizer_state *r = svga->curr.rast;
314    unsigned int aa_point = r->templ.point_smooth;
315 
316    if (!svga->rasterizer_no_cull[aa_point]) {
317       struct pipe_rasterizer_state rast;
318 
319       memset(&rast, 0, sizeof(rast));
320       rast.flatshade = 1;
321       rast.front_ccw = 1;
322       rast.point_smooth = r->templ.point_smooth;
323 
324       /* All rasterizer states have the same half_pixel_center,
325        * bottom_edge_rule and clip_halfz values since they are
326        * constant for a context. If we ever implement
327        * GL_ARB_clip_control, the clip_halfz field would have to be observed.
328        */
329       rast.half_pixel_center = r->templ.half_pixel_center;
330       rast.bottom_edge_rule = r->templ.bottom_edge_rule;
331       rast.clip_halfz = r->templ.clip_halfz;
332 
333       svga->rasterizer_no_cull[aa_point] =
334                svga->pipe.create_rasterizer_state(&svga->pipe, &rast);
335    }
336    return svga->rasterizer_no_cull[aa_point];
337 }
338 
339 static enum pipe_error
emit_rss_vgpu10(struct svga_context * svga,unsigned dirty)340 emit_rss_vgpu10(struct svga_context *svga, unsigned dirty)
341 {
342    enum pipe_error ret = PIPE_OK;
343 
344    svga_hwtnl_flush_retry(svga);
345 
346    if (dirty & (SVGA_NEW_BLEND | SVGA_NEW_BLEND_COLOR)) {
347       const struct svga_blend_state *curr;
348       float blend_factor[4];
349 
350       if (svga_has_any_integer_cbufs(svga)) {
351          /* Blending is not supported in integer-valued render targets. */
352          curr = svga->noop_blend;
353          blend_factor[0] =
354          blend_factor[1] =
355          blend_factor[2] =
356          blend_factor[3] = 0;
357       }
358       else {
359          curr = svga->curr.blend;
360 
361          if (curr->blend_color_alpha) {
362             blend_factor[0] =
363             blend_factor[1] =
364             blend_factor[2] =
365             blend_factor[3] = svga->curr.blend_color.color[3];
366          }
367          else {
368             blend_factor[0] = svga->curr.blend_color.color[0];
369             blend_factor[1] = svga->curr.blend_color.color[1];
370             blend_factor[2] = svga->curr.blend_color.color[2];
371             blend_factor[3] = svga->curr.blend_color.color[3];
372          }
373       }
374 
375       /* Set/bind the blend state object */
376       if (svga->state.hw_draw.blend_id != curr->id ||
377           svga->state.hw_draw.blend_factor[0] != blend_factor[0] ||
378           svga->state.hw_draw.blend_factor[1] != blend_factor[1] ||
379           svga->state.hw_draw.blend_factor[2] != blend_factor[2] ||
380           svga->state.hw_draw.blend_factor[3] != blend_factor[3] ||
381           svga->state.hw_draw.blend_sample_mask != svga->curr.sample_mask) {
382          ret = SVGA3D_vgpu10_SetBlendState(svga->swc, curr->id,
383                                            blend_factor,
384                                            svga->curr.sample_mask);
385          if (ret != PIPE_OK)
386             return ret;
387 
388          svga->state.hw_draw.blend_id = curr->id;
389          svga->state.hw_draw.blend_factor[0] = blend_factor[0];
390          svga->state.hw_draw.blend_factor[1] = blend_factor[1];
391          svga->state.hw_draw.blend_factor[2] = blend_factor[2];
392          svga->state.hw_draw.blend_factor[3] = blend_factor[3];
393          svga->state.hw_draw.blend_sample_mask = svga->curr.sample_mask;
394       }
395    }
396 
397    if (dirty & (SVGA_NEW_DEPTH_STENCIL_ALPHA | SVGA_NEW_STENCIL_REF)) {
398       const struct svga_depth_stencil_state *curr = svga->curr.depth;
399       unsigned curr_ref = svga->curr.stencil_ref.ref_value[0];
400 
401       if (curr->id != svga->state.hw_draw.depth_stencil_id ||
402           curr_ref != svga->state.hw_draw.stencil_ref) {
403          /* Set/bind the depth/stencil state object */
404          ret = SVGA3D_vgpu10_SetDepthStencilState(svga->swc, curr->id,
405                                                   curr_ref);
406          if (ret != PIPE_OK)
407             return ret;
408 
409          svga->state.hw_draw.depth_stencil_id = curr->id;
410          svga->state.hw_draw.stencil_ref = curr_ref;
411       }
412    }
413 
414    if (dirty & (SVGA_NEW_REDUCED_PRIMITIVE | SVGA_NEW_RAST)) {
415       const struct svga_rasterizer_state *rast;
416 
417       if (svga->curr.reduced_prim == PIPE_PRIM_POINTS &&
418           svga->curr.gs && svga->curr.gs->wide_point) {
419 
420          /* If we are drawing a point sprite, we will need to
421           * bind a non-culling rasterizer state object
422           */
423          rast = get_no_cull_rasterizer_state(svga);
424       }
425       else {
426          rast = svga->curr.rast;
427       }
428 
429       if (svga->state.hw_draw.rasterizer_id != rast->id) {
430          /* Set/bind the rasterizer state object */
431          ret = SVGA3D_vgpu10_SetRasterizerState(svga->swc, rast->id);
432          if (ret != PIPE_OK)
433             return ret;
434          svga->state.hw_draw.rasterizer_id = rast->id;
435       }
436    }
437    return PIPE_OK;
438 }
439 
440 
441 static enum pipe_error
emit_rss(struct svga_context * svga,unsigned dirty)442 emit_rss(struct svga_context *svga, unsigned dirty)
443 {
444    if (svga_have_vgpu10(svga)) {
445       return emit_rss_vgpu10(svga, dirty);
446    }
447    else {
448       return emit_rss_vgpu9(svga, dirty);
449    }
450 }
451 
452 
453 struct svga_tracked_state svga_hw_rss =
454 {
455    "hw rss state",
456 
457    (SVGA_NEW_BLEND |
458     SVGA_NEW_BLEND_COLOR |
459     SVGA_NEW_DEPTH_STENCIL_ALPHA |
460     SVGA_NEW_STENCIL_REF |
461     SVGA_NEW_RAST |
462     SVGA_NEW_FRAME_BUFFER |
463     SVGA_NEW_NEED_PIPELINE |
464     SVGA_NEW_REDUCED_PRIMITIVE),
465 
466    emit_rss
467 };
468