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_bitmask.h"
27#include "util/u_debug.h"
28#include "pipe/p_defines.h"
29#include "util/u_memory.h"
30#include "draw/draw_context.h"
31
32#include "svga_context.h"
33#include "svga_screen.h"
34#include "svga_state.h"
35#include "svga_draw.h"
36#include "svga_cmd.h"
37#include "svga_hw_reg.h"
38
39/* This is just enough to decide whether we need to use the draw
40 * module (swtnl) or not.
41 */
42static const struct svga_tracked_state *need_swtnl_state[] =
43{
44   &svga_update_need_swvfetch,
45   &svga_update_need_pipeline,
46   &svga_update_need_swtnl,
47   NULL
48};
49
50
51/* Atoms to update hardware state prior to emitting a clear or draw
52 * packet.
53 */
54static const struct svga_tracked_state *hw_clear_state[] =
55{
56   &svga_hw_scissor,
57   &svga_hw_viewport,
58   &svga_hw_framebuffer,
59   NULL
60};
61
62
63/**
64 * Atoms to update hardware state prior to emitting a draw packet
65 * for VGPU9 device.
66 */
67static const struct svga_tracked_state *hw_draw_state_vgpu9[] =
68{
69   &svga_hw_fs,
70   &svga_hw_vs,
71   &svga_hw_rss,
72   &svga_hw_tss,
73   &svga_hw_tss_binding,
74   &svga_hw_clip_planes,
75   &svga_hw_vdecl,
76   &svga_hw_fs_constants,
77   &svga_hw_vs_constants,
78   NULL
79};
80
81
82/**
83 * Atoms to update hardware state prior to emitting a draw packet
84 * for VGPU10 device.
85 * Geometry Shader is new to VGPU10.
86 * TSS and TSS bindings are replaced by sampler and sampler bindings.
87 */
88static const struct svga_tracked_state *hw_draw_state_vgpu10[] =
89{
90   &svga_need_tgsi_transform,
91   &svga_hw_fs,
92   &svga_hw_gs,
93   &svga_hw_vs,
94   &svga_hw_rss,
95   &svga_hw_sampler,
96   &svga_hw_sampler_bindings,
97   &svga_hw_clip_planes,
98   &svga_hw_vdecl,
99   &svga_hw_fs_constants,
100   &svga_hw_fs_constbufs,
101   &svga_hw_gs_constants,
102   &svga_hw_gs_constbufs,
103   &svga_hw_vs_constants,
104   &svga_hw_vs_constbufs,
105   NULL
106};
107
108
109/**
110 * Atoms to update hardware state prior to emitting a draw packet
111 * for SM5 device.
112 * TCS and TES Shaders are new to SM5 device.
113 */
114static const struct svga_tracked_state *hw_draw_state_sm5[] =
115{
116   &svga_need_tgsi_transform,
117   &svga_hw_fs,
118   &svga_hw_gs,
119   &svga_hw_tes,
120   &svga_hw_tcs,
121   &svga_hw_vs,
122   &svga_hw_rss,
123   &svga_hw_sampler,
124   &svga_hw_sampler_bindings,
125   &svga_hw_clip_planes,
126   &svga_hw_vdecl,
127   &svga_hw_fs_constants,
128   &svga_hw_fs_constbufs,
129   &svga_hw_gs_constants,
130   &svga_hw_gs_constbufs,
131   &svga_hw_tes_constants,
132   &svga_hw_tes_constbufs,
133   &svga_hw_tcs_constants,
134   &svga_hw_tcs_constbufs,
135   &svga_hw_vs_constants,
136   &svga_hw_vs_constbufs,
137   NULL
138};
139
140
141/**
142 * Atoms to update hardware state prior to emitting a draw packet
143 * for GL43 device which includes uav update.
144 */
145static const struct svga_tracked_state *hw_draw_state_gl43[] =
146{
147   &svga_need_tgsi_transform,
148   &svga_hw_uav,
149   &svga_need_rawbuf_srv,
150   &svga_hw_fs,
151   &svga_hw_gs,
152   &svga_hw_tes,
153   &svga_hw_tcs,
154   &svga_hw_vs,
155   &svga_hw_rss,
156   &svga_hw_sampler,
157   &svga_hw_sampler_bindings,
158   &svga_hw_clip_planes,
159   &svga_hw_vdecl,
160   &svga_hw_fs_constants,
161   &svga_hw_fs_constbufs,
162   &svga_hw_gs_constants,
163   &svga_hw_gs_constbufs,
164   &svga_hw_tes_constants,
165   &svga_hw_tes_constbufs,
166   &svga_hw_tcs_constants,
167   &svga_hw_tcs_constbufs,
168   &svga_hw_vs_constants,
169   &svga_hw_vs_constbufs,
170   NULL
171};
172
173
174static const struct svga_tracked_state *swtnl_draw_state[] =
175{
176   &svga_update_swtnl_draw,
177   &svga_update_swtnl_vdecl,
178   NULL
179};
180
181
182/* Flattens the graph of state dependencies.  Could swap the positions
183 * of hw_clear_state and need_swtnl_state without breaking anything.
184 */
185static const struct svga_tracked_state **state_levels[] =
186{
187   need_swtnl_state,
188   hw_clear_state,
189   NULL,              /* hw_draw_state, to be set to the right version */
190   swtnl_draw_state
191};
192
193
194static uint64_t
195check_state(uint64_t a, uint64_t b)
196{
197   return (a & b);
198}
199
200static void
201accumulate_state(uint64_t *a, uint64_t b)
202{
203   *a |= b;
204}
205
206
207static void
208xor_states(uint64_t *result, uint64_t a, uint64_t b)
209{
210   *result = a ^ b;
211}
212
213
214static enum pipe_error
215update_state(struct svga_context *svga,
216             const struct svga_tracked_state *atoms[],
217             uint64_t *state)
218{
219#ifdef DEBUG
220   boolean debug = TRUE;
221#else
222   boolean debug = FALSE;
223#endif
224   enum pipe_error ret = PIPE_OK;
225   unsigned i;
226
227   ret = svga_hwtnl_flush( svga->hwtnl );
228   if (ret != PIPE_OK)
229      return ret;
230
231   if (debug) {
232      /* Debug version which enforces various sanity checks on the
233       * state flags which are generated and checked to help ensure
234       * state atoms are ordered correctly in the list.
235       */
236      uint64_t examined, prev;
237
238      examined = 0;
239      prev = *state;
240
241      for (i = 0; atoms[i] != NULL; i++) {
242         uint64_t generated;
243
244         assert(atoms[i]->dirty);
245         assert(atoms[i]->update);
246
247         if (check_state(*state, atoms[i]->dirty)) {
248            if (0)
249               debug_printf("update: %s\n", atoms[i]->name);
250            ret = atoms[i]->update( svga, *state );
251            if (ret != PIPE_OK)
252               return ret;
253         }
254
255         /* generated = (prev ^ state)
256          * if (examined & generated)
257          *     fail;
258          */
259         xor_states(&generated, prev, *state);
260         if (check_state(examined, generated)) {
261            debug_printf("state atom %s generated state already examined\n",
262                         atoms[i]->name);
263            assert(0);
264         }
265
266         prev = *state;
267         accumulate_state(&examined, atoms[i]->dirty);
268      }
269   }
270   else {
271      for (i = 0; atoms[i] != NULL; i++) {
272         if (check_state(*state, atoms[i]->dirty)) {
273            ret = atoms[i]->update( svga, *state );
274            if (ret != PIPE_OK)
275               return ret;
276         }
277      }
278   }
279
280   return PIPE_OK;
281}
282
283
284enum pipe_error
285svga_update_state(struct svga_context *svga, unsigned max_level)
286{
287   struct svga_screen *screen = svga_screen(svga->pipe.screen);
288   enum pipe_error ret = PIPE_OK;
289   unsigned i;
290
291   SVGA_STATS_TIME_PUSH(screen->sws, SVGA_STATS_TIME_UPDATESTATE);
292
293   /* Check for updates to bound textures.  This can't be done in an
294    * atom as there is no flag which could provoke this test, and we
295    * cannot create one.
296    */
297   if (svga->state.texture_timestamp != screen->texture_timestamp) {
298      svga->state.texture_timestamp = screen->texture_timestamp;
299      svga->dirty |= SVGA_NEW_TEXTURE;
300   }
301
302   for (i = 0; i <= max_level; i++) {
303      svga->dirty |= svga->state.dirty[i];
304
305      if (svga->dirty) {
306         ret = update_state( svga,
307                             state_levels[i],
308                             &svga->dirty );
309         if (ret != PIPE_OK)
310            goto done;
311
312         svga->state.dirty[i] = 0;
313      }
314   }
315
316   for (; i < SVGA_STATE_MAX; i++)
317      svga->state.dirty[i] |= svga->dirty;
318
319   svga->dirty = 0;
320
321   svga->hud.num_validations++;
322
323done:
324   SVGA_STATS_TIME_POP(screen->sws);
325   return ret;
326}
327
328
329/**
330 * Update state.  If the first attempt fails, flush the command buffer
331 * and retry.
332 * \return  true if success, false if second attempt fails.
333 */
334bool
335svga_update_state_retry(struct svga_context *svga, unsigned max_level)
336{
337   enum pipe_error ret;
338
339   SVGA_RETRY_OOM(svga, ret, svga_update_state( svga, max_level ));
340
341   return ret == PIPE_OK;
342}
343
344
345#define EMIT_RS(_rs, _count, _name, _value)     \
346do {                                            \
347   _rs[_count].state = _name;                   \
348   _rs[_count].uintValue = _value;              \
349   _count++;                                    \
350} while (0)
351
352
353/* Setup any hardware state which will be constant through the life of
354 * a context.
355 */
356enum pipe_error
357svga_emit_initial_state(struct svga_context *svga)
358{
359   if (svga_have_vgpu10(svga)) {
360      SVGA3dRasterizerStateId id = util_bitmask_add(svga->rast_object_id_bm);
361      enum pipe_error ret;
362
363      /* XXX preliminary code */
364      ret = SVGA3D_vgpu10_DefineRasterizerState(svga->swc,
365                                             id,
366                                             SVGA3D_FILLMODE_FILL,
367                                             SVGA3D_CULL_NONE,
368                                             1, /* frontCounterClockwise */
369                                             0, /* depthBias */
370                                             0.0f, /* depthBiasClamp */
371                                             0.0f, /* slopeScaledDepthBiasClamp */
372                                             0, /* depthClampEnable */
373                                             0, /* scissorEnable */
374                                             0, /* multisampleEnable */
375                                             0, /* aalineEnable */
376                                             1.0f, /* lineWidth */
377                                             0, /* lineStippleEnable */
378                                             0, /* lineStippleFactor */
379                                             0, /* lineStipplePattern */
380                                             0); /* provokingVertexLast */
381
382
383      assert(ret == PIPE_OK);
384
385      ret = SVGA3D_vgpu10_SetRasterizerState(svga->swc, id);
386      return ret;
387   }
388   else {
389      SVGA3dRenderState *rs;
390      unsigned count = 0;
391      const unsigned COUNT = 2;
392      enum pipe_error ret;
393
394      ret = SVGA3D_BeginSetRenderState( svga->swc, &rs, COUNT );
395      if (ret != PIPE_OK)
396         return ret;
397
398      /* Always use D3D style coordinate space as this is the only one
399       * which is implemented on all backends.
400       */
401      EMIT_RS(rs, count, SVGA3D_RS_COORDINATETYPE,
402              SVGA3D_COORDINATE_LEFTHANDED );
403      EMIT_RS(rs, count, SVGA3D_RS_FRONTWINDING, SVGA3D_FRONTWINDING_CW );
404
405      assert( COUNT == count );
406      SVGA_FIFOCommitAll( svga->swc );
407
408      return PIPE_OK;
409   }
410}
411
412
413void
414svga_init_tracked_state(struct svga_context *svga)
415{
416   /* Set the hw_draw_state atom list to the one for the particular gpu version.
417    */
418   state_levels[2] =
419      svga_have_gl43(svga) ? hw_draw_state_gl43 :
420         (svga_have_sm5(svga) ? hw_draw_state_sm5 :
421            ((svga_have_vgpu10(svga) ? hw_draw_state_vgpu10 :
422                                       hw_draw_state_vgpu9)));
423}
424
425
426static const struct svga_tracked_state *compute_state[] =
427{
428   &svga_hw_cs_uav,
429   &svga_hw_cs_sampler,
430   &svga_hw_cs_sampler_bindings,
431   &svga_hw_cs,
432   &svga_hw_cs_constants,
433   &svga_hw_cs_constbufs,
434   NULL
435};
436
437/**
438 * Update compute state.
439 * If the first attempt fails, flush the command buffer and retry.
440 * \return  true if success, false if second attempt fails.
441 */
442bool
443svga_update_compute_state(struct svga_context *svga)
444{
445   enum pipe_error ret = PIPE_OK;
446   uint64_t compute_dirty = svga->dirty;
447
448   if (compute_dirty) {
449      SVGA_RETRY_OOM(svga, ret, update_state(svga, compute_state,
450                                             &compute_dirty));
451
452      /* Set the dirty flag to the remaining dirty bits which are
453       * not processed in the compute pipeline.
454       */
455      svga->dirty = compute_dirty;
456   }
457
458   return ret == PIPE_OK;
459}
460