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
141static const struct svga_tracked_state *swtnl_draw_state[] =
142{
143   &svga_update_swtnl_draw,
144   &svga_update_swtnl_vdecl,
145   NULL
146};
147
148
149/* Flattens the graph of state dependencies.  Could swap the positions
150 * of hw_clear_state and need_swtnl_state without breaking anything.
151 */
152static const struct svga_tracked_state **state_levels[] =
153{
154   need_swtnl_state,
155   hw_clear_state,
156   NULL,              /* hw_draw_state, to be set to the right version */
157   swtnl_draw_state
158};
159
160
161static uint64_t
162check_state(uint64_t a, uint64_t b)
163{
164   return (a & b);
165}
166
167static void
168accumulate_state(uint64_t *a, uint64_t b)
169{
170   *a |= b;
171}
172
173
174static void
175xor_states(uint64_t *result, uint64_t a, uint64_t b)
176{
177   *result = a ^ b;
178}
179
180
181static enum pipe_error
182update_state(struct svga_context *svga,
183             const struct svga_tracked_state *atoms[],
184             uint64_t *state)
185{
186#ifdef DEBUG
187   boolean debug = TRUE;
188#else
189   boolean debug = FALSE;
190#endif
191   enum pipe_error ret = PIPE_OK;
192   unsigned i;
193
194   ret = svga_hwtnl_flush( svga->hwtnl );
195   if (ret != PIPE_OK)
196      return ret;
197
198   if (debug) {
199      /* Debug version which enforces various sanity checks on the
200       * state flags which are generated and checked to help ensure
201       * state atoms are ordered correctly in the list.
202       */
203      uint64_t examined, prev;
204
205      examined = 0;
206      prev = *state;
207
208      for (i = 0; atoms[i] != NULL; i++) {
209         uint64_t generated;
210
211         assert(atoms[i]->dirty);
212         assert(atoms[i]->update);
213
214         if (check_state(*state, atoms[i]->dirty)) {
215            if (0)
216               debug_printf("update: %s\n", atoms[i]->name);
217            ret = atoms[i]->update( svga, *state );
218            if (ret != PIPE_OK)
219               return ret;
220         }
221
222         /* generated = (prev ^ state)
223          * if (examined & generated)
224          *     fail;
225          */
226         xor_states(&generated, prev, *state);
227         if (check_state(examined, generated)) {
228            debug_printf("state atom %s generated state already examined\n",
229                         atoms[i]->name);
230            assert(0);
231         }
232
233         prev = *state;
234         accumulate_state(&examined, atoms[i]->dirty);
235      }
236   }
237   else {
238      for (i = 0; atoms[i] != NULL; i++) {
239         if (check_state(*state, atoms[i]->dirty)) {
240            ret = atoms[i]->update( svga, *state );
241            if (ret != PIPE_OK)
242               return ret;
243         }
244      }
245   }
246
247   return PIPE_OK;
248}
249
250
251enum pipe_error
252svga_update_state(struct svga_context *svga, unsigned max_level)
253{
254   struct svga_screen *screen = svga_screen(svga->pipe.screen);
255   enum pipe_error ret = PIPE_OK;
256   unsigned i;
257
258   SVGA_STATS_TIME_PUSH(screen->sws, SVGA_STATS_TIME_UPDATESTATE);
259
260   /* Check for updates to bound textures.  This can't be done in an
261    * atom as there is no flag which could provoke this test, and we
262    * cannot create one.
263    */
264   if (svga->state.texture_timestamp != screen->texture_timestamp) {
265      svga->state.texture_timestamp = screen->texture_timestamp;
266      svga->dirty |= SVGA_NEW_TEXTURE;
267   }
268
269   for (i = 0; i <= max_level; i++) {
270      svga->dirty |= svga->state.dirty[i];
271
272      if (svga->dirty) {
273         ret = update_state( svga,
274                             state_levels[i],
275                             &svga->dirty );
276         if (ret != PIPE_OK)
277            goto done;
278
279         svga->state.dirty[i] = 0;
280      }
281   }
282
283   for (; i < SVGA_STATE_MAX; i++)
284      svga->state.dirty[i] |= svga->dirty;
285
286   svga->dirty = 0;
287
288   svga->hud.num_validations++;
289
290done:
291   SVGA_STATS_TIME_POP(screen->sws);
292   return ret;
293}
294
295
296/**
297 * Update state.  If the first attempt fails, flush the command buffer
298 * and retry.
299 * \return  true if success, false if second attempt fails.
300 */
301bool
302svga_update_state_retry(struct svga_context *svga, unsigned max_level)
303{
304   enum pipe_error ret;
305
306   SVGA_RETRY_OOM(svga, ret, svga_update_state( svga, max_level ));
307
308   return ret == PIPE_OK;
309}
310
311
312
313#define EMIT_RS(_rs, _count, _name, _value)     \
314do {                                            \
315   _rs[_count].state = _name;                   \
316   _rs[_count].uintValue = _value;              \
317   _count++;                                    \
318} while (0)
319
320
321/* Setup any hardware state which will be constant through the life of
322 * a context.
323 */
324enum pipe_error
325svga_emit_initial_state(struct svga_context *svga)
326{
327   if (svga_have_vgpu10(svga)) {
328      SVGA3dRasterizerStateId id = util_bitmask_add(svga->rast_object_id_bm);
329      enum pipe_error ret;
330
331      /* XXX preliminary code */
332      ret = SVGA3D_vgpu10_DefineRasterizerState(svga->swc,
333                                             id,
334                                             SVGA3D_FILLMODE_FILL,
335                                             SVGA3D_CULL_NONE,
336                                             1, /* frontCounterClockwise */
337                                             0, /* depthBias */
338                                             0.0f, /* depthBiasClamp */
339                                             0.0f, /* slopeScaledDepthBiasClamp */
340                                             0, /* depthClampEnable */
341                                             0, /* scissorEnable */
342                                             0, /* multisampleEnable */
343                                             0, /* aalineEnable */
344                                             1.0f, /* lineWidth */
345                                             0, /* lineStippleEnable */
346                                             0, /* lineStippleFactor */
347                                             0, /* lineStipplePattern */
348                                             0); /* provokingVertexLast */
349
350
351      assert(ret == PIPE_OK);
352
353      ret = SVGA3D_vgpu10_SetRasterizerState(svga->swc, id);
354      return ret;
355   }
356   else {
357      SVGA3dRenderState *rs;
358      unsigned count = 0;
359      const unsigned COUNT = 2;
360      enum pipe_error ret;
361
362      ret = SVGA3D_BeginSetRenderState( svga->swc, &rs, COUNT );
363      if (ret != PIPE_OK)
364         return ret;
365
366      /* Always use D3D style coordinate space as this is the only one
367       * which is implemented on all backends.
368       */
369      EMIT_RS(rs, count, SVGA3D_RS_COORDINATETYPE,
370              SVGA3D_COORDINATE_LEFTHANDED );
371      EMIT_RS(rs, count, SVGA3D_RS_FRONTWINDING, SVGA3D_FRONTWINDING_CW );
372
373      assert( COUNT == count );
374      SVGA_FIFOCommitAll( svga->swc );
375
376      return PIPE_OK;
377   }
378}
379
380
381void
382svga_init_tracked_state(struct svga_context *svga)
383{
384   /* Set the hw_draw_state atom list to the one for the particular gpu version.
385    */
386   state_levels[2] = svga_have_sm5(svga) ? hw_draw_state_sm5 :
387                       (svga_have_vgpu10(svga) ? hw_draw_state_vgpu10 :
388                                                 hw_draw_state_vgpu9);
389}
390