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