1848b8605Smrg/**********************************************************
2848b8605Smrg * Copyright 2008-2009 VMware, Inc.  All rights reserved.
3848b8605Smrg *
4848b8605Smrg * Permission is hereby granted, free of charge, to any person
5848b8605Smrg * obtaining a copy of this software and associated documentation
6848b8605Smrg * files (the "Software"), to deal in the Software without
7848b8605Smrg * restriction, including without limitation the rights to use, copy,
8848b8605Smrg * modify, merge, publish, distribute, sublicense, and/or sell copies
9848b8605Smrg * of the Software, and to permit persons to whom the Software is
10848b8605Smrg * furnished to do so, subject to the following conditions:
11848b8605Smrg *
12848b8605Smrg * The above copyright notice and this permission notice shall be
13848b8605Smrg * included in all copies or substantial portions of the Software.
14848b8605Smrg *
15848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16848b8605Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17848b8605Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18848b8605Smrg * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19848b8605Smrg * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20848b8605Smrg * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21848b8605Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22848b8605Smrg * SOFTWARE.
23848b8605Smrg *
24848b8605Smrg **********************************************************/
25848b8605Smrg
26b8e80941Smrg#include "util/u_bitmask.h"
27848b8605Smrg#include "util/u_debug.h"
28848b8605Smrg#include "pipe/p_defines.h"
29848b8605Smrg#include "util/u_memory.h"
30848b8605Smrg#include "draw/draw_context.h"
31848b8605Smrg
32848b8605Smrg#include "svga_context.h"
33848b8605Smrg#include "svga_screen.h"
34848b8605Smrg#include "svga_state.h"
35848b8605Smrg#include "svga_draw.h"
36848b8605Smrg#include "svga_cmd.h"
37848b8605Smrg#include "svga_hw_reg.h"
38848b8605Smrg
39848b8605Smrg/* This is just enough to decide whether we need to use the draw
40848b8605Smrg * module (swtnl) or not.
41848b8605Smrg */
42848b8605Smrgstatic const struct svga_tracked_state *need_swtnl_state[] =
43848b8605Smrg{
44848b8605Smrg   &svga_update_need_swvfetch,
45848b8605Smrg   &svga_update_need_pipeline,
46848b8605Smrg   &svga_update_need_swtnl,
47848b8605Smrg   NULL
48848b8605Smrg};
49848b8605Smrg
50848b8605Smrg
51848b8605Smrg/* Atoms to update hardware state prior to emitting a clear or draw
52848b8605Smrg * packet.
53848b8605Smrg */
54848b8605Smrgstatic const struct svga_tracked_state *hw_clear_state[] =
55848b8605Smrg{
56848b8605Smrg   &svga_hw_scissor,
57848b8605Smrg   &svga_hw_viewport,
58848b8605Smrg   &svga_hw_framebuffer,
59848b8605Smrg   NULL
60848b8605Smrg};
61848b8605Smrg
62848b8605Smrg
63848b8605Smrg/* Atoms to update hardware state prior to emitting a draw packet.
64848b8605Smrg */
65848b8605Smrgstatic const struct svga_tracked_state *hw_draw_state[] =
66848b8605Smrg{
67b8e80941Smrg   &svga_need_tgsi_transform,
68848b8605Smrg   &svga_hw_fs,
69b8e80941Smrg   &svga_hw_gs,
70848b8605Smrg   &svga_hw_vs,
71848b8605Smrg   &svga_hw_rss,
72b8e80941Smrg   &svga_hw_sampler,           /* VGPU10 */
73b8e80941Smrg   &svga_hw_sampler_bindings,  /* VGPU10 */
74b8e80941Smrg   &svga_hw_tss,               /* pre-VGPU10 */
75b8e80941Smrg   &svga_hw_tss_binding,       /* pre-VGPU10 */
76848b8605Smrg   &svga_hw_clip_planes,
77848b8605Smrg   &svga_hw_vdecl,
78848b8605Smrg   &svga_hw_fs_constants,
79b8e80941Smrg   &svga_hw_gs_constants,
80848b8605Smrg   &svga_hw_vs_constants,
81848b8605Smrg   NULL
82848b8605Smrg};
83848b8605Smrg
84848b8605Smrg
85848b8605Smrgstatic const struct svga_tracked_state *swtnl_draw_state[] =
86848b8605Smrg{
87848b8605Smrg   &svga_update_swtnl_draw,
88848b8605Smrg   &svga_update_swtnl_vdecl,
89848b8605Smrg   NULL
90848b8605Smrg};
91848b8605Smrg
92848b8605Smrg/* Flattens the graph of state dependencies.  Could swap the positions
93848b8605Smrg * of hw_clear_state and need_swtnl_state without breaking anything.
94848b8605Smrg */
95b8e80941Smrgstatic const struct svga_tracked_state **state_levels[] =
96848b8605Smrg{
97848b8605Smrg   need_swtnl_state,
98848b8605Smrg   hw_clear_state,
99848b8605Smrg   hw_draw_state,
100848b8605Smrg   swtnl_draw_state
101848b8605Smrg};
102848b8605Smrg
103848b8605Smrg
104848b8605Smrg
105b8e80941Smrgstatic unsigned
106b8e80941Smrgcheck_state(unsigned a, unsigned b)
107848b8605Smrg{
108848b8605Smrg   return (a & b);
109848b8605Smrg}
110848b8605Smrg
111b8e80941Smrgstatic void
112b8e80941Smrgaccumulate_state(unsigned *a, unsigned b)
113848b8605Smrg{
114848b8605Smrg   *a |= b;
115848b8605Smrg}
116848b8605Smrg
117848b8605Smrg
118b8e80941Smrgstatic void
119b8e80941Smrgxor_states(unsigned *result, unsigned a, unsigned b)
120848b8605Smrg{
121848b8605Smrg   *result = a ^ b;
122848b8605Smrg}
123848b8605Smrg
124848b8605Smrg
125848b8605Smrgstatic enum pipe_error
126848b8605Smrgupdate_state(struct svga_context *svga,
127848b8605Smrg             const struct svga_tracked_state *atoms[],
128848b8605Smrg             unsigned *state)
129848b8605Smrg{
130b8e80941Smrg#ifdef DEBUG
131848b8605Smrg   boolean debug = TRUE;
132b8e80941Smrg#else
133b8e80941Smrg   boolean debug = FALSE;
134b8e80941Smrg#endif
135848b8605Smrg   enum pipe_error ret = PIPE_OK;
136848b8605Smrg   unsigned i;
137848b8605Smrg
138848b8605Smrg   ret = svga_hwtnl_flush( svga->hwtnl );
139848b8605Smrg   if (ret != PIPE_OK)
140848b8605Smrg      return ret;
141848b8605Smrg
142848b8605Smrg   if (debug) {
143848b8605Smrg      /* Debug version which enforces various sanity checks on the
144848b8605Smrg       * state flags which are generated and checked to help ensure
145848b8605Smrg       * state atoms are ordered correctly in the list.
146848b8605Smrg       */
147b8e80941Smrg      unsigned examined, prev;
148848b8605Smrg
149848b8605Smrg      examined = 0;
150848b8605Smrg      prev = *state;
151848b8605Smrg
152b8e80941Smrg      for (i = 0; atoms[i] != NULL; i++) {
153b8e80941Smrg         unsigned generated;
154848b8605Smrg
155b8e80941Smrg         assert(atoms[i]->dirty);
156b8e80941Smrg         assert(atoms[i]->update);
157848b8605Smrg
158b8e80941Smrg         if (check_state(*state, atoms[i]->dirty)) {
159b8e80941Smrg            if (0)
160848b8605Smrg               debug_printf("update: %s\n", atoms[i]->name);
161b8e80941Smrg            ret = atoms[i]->update( svga, *state );
162848b8605Smrg            if (ret != PIPE_OK)
163848b8605Smrg               return ret;
164b8e80941Smrg         }
165b8e80941Smrg
166b8e80941Smrg         /* generated = (prev ^ state)
167b8e80941Smrg          * if (examined & generated)
168b8e80941Smrg          *     fail;
169b8e80941Smrg          */
170b8e80941Smrg         xor_states(&generated, prev, *state);
171b8e80941Smrg         if (check_state(examined, generated)) {
172b8e80941Smrg            debug_printf("state atom %s generated state already examined\n",
173848b8605Smrg                         atoms[i]->name);
174b8e80941Smrg            assert(0);
175b8e80941Smrg         }
176b8e80941Smrg
177b8e80941Smrg         prev = *state;
178b8e80941Smrg         accumulate_state(&examined, atoms[i]->dirty);
179848b8605Smrg      }
180848b8605Smrg   }
181848b8605Smrg   else {
182b8e80941Smrg      for (i = 0; atoms[i] != NULL; i++) {
183b8e80941Smrg         if (check_state(*state, atoms[i]->dirty)) {
184b8e80941Smrg            ret = atoms[i]->update( svga, *state );
185848b8605Smrg            if (ret != PIPE_OK)
186848b8605Smrg               return ret;
187848b8605Smrg         }
188848b8605Smrg      }
189848b8605Smrg   }
190848b8605Smrg
191848b8605Smrg   return PIPE_OK;
192848b8605Smrg}
193848b8605Smrg
194848b8605Smrg
195848b8605Smrgenum pipe_error
196848b8605Smrgsvga_update_state(struct svga_context *svga, unsigned max_level)
197848b8605Smrg{
198848b8605Smrg   struct svga_screen *screen = svga_screen(svga->pipe.screen);
199848b8605Smrg   enum pipe_error ret = PIPE_OK;
200848b8605Smrg   unsigned i;
201848b8605Smrg
202b8e80941Smrg   SVGA_STATS_TIME_PUSH(screen->sws, SVGA_STATS_TIME_UPDATESTATE);
203b8e80941Smrg
204848b8605Smrg   /* Check for updates to bound textures.  This can't be done in an
205848b8605Smrg    * atom as there is no flag which could provoke this test, and we
206848b8605Smrg    * cannot create one.
207848b8605Smrg    */
208848b8605Smrg   if (svga->state.texture_timestamp != screen->texture_timestamp) {
209848b8605Smrg      svga->state.texture_timestamp = screen->texture_timestamp;
210848b8605Smrg      svga->dirty |= SVGA_NEW_TEXTURE;
211848b8605Smrg   }
212848b8605Smrg
213848b8605Smrg   for (i = 0; i <= max_level; i++) {
214848b8605Smrg      svga->dirty |= svga->state.dirty[i];
215848b8605Smrg
216848b8605Smrg      if (svga->dirty) {
217b8e80941Smrg         ret = update_state( svga,
218b8e80941Smrg                             state_levels[i],
219848b8605Smrg                             &svga->dirty );
220848b8605Smrg         if (ret != PIPE_OK)
221b8e80941Smrg            goto done;
222848b8605Smrg
223848b8605Smrg         svga->state.dirty[i] = 0;
224848b8605Smrg      }
225848b8605Smrg   }
226b8e80941Smrg
227b8e80941Smrg   for (; i < SVGA_STATE_MAX; i++)
228848b8605Smrg      svga->state.dirty[i] |= svga->dirty;
229848b8605Smrg
230848b8605Smrg   svga->dirty = 0;
231848b8605Smrg
232b8e80941Smrg   svga->hud.num_validations++;
233848b8605Smrg
234b8e80941Smrgdone:
235b8e80941Smrg   SVGA_STATS_TIME_POP(screen->sws);
236b8e80941Smrg   return ret;
237b8e80941Smrg}
238848b8605Smrg
239848b8605Smrg
240b8e80941Smrg/**
241b8e80941Smrg * Update state.  If the first attempt fails, flush the command buffer
242b8e80941Smrg * and retry.
243b8e80941Smrg * \return  true if success, false if second attempt fails.
244b8e80941Smrg */
245b8e80941Smrgbool
246b8e80941Smrgsvga_update_state_retry(struct svga_context *svga, unsigned max_level)
247848b8605Smrg{
248848b8605Smrg   enum pipe_error ret;
249848b8605Smrg
250848b8605Smrg   ret = svga_update_state( svga, max_level );
251848b8605Smrg
252b8e80941Smrg   if (ret != PIPE_OK) {
253848b8605Smrg      svga_context_flush(svga, NULL);
254848b8605Smrg      ret = svga_update_state( svga, max_level );
255848b8605Smrg   }
256848b8605Smrg
257b8e80941Smrg   return ret == PIPE_OK;
258848b8605Smrg}
259848b8605Smrg
260848b8605Smrg
261848b8605Smrg
262848b8605Smrg#define EMIT_RS(_rs, _count, _name, _value)     \
263848b8605Smrgdo {                                            \
264848b8605Smrg   _rs[_count].state = _name;                   \
265848b8605Smrg   _rs[_count].uintValue = _value;              \
266848b8605Smrg   _count++;                                    \
267848b8605Smrg} while (0)
268848b8605Smrg
269848b8605Smrg
270848b8605Smrg/* Setup any hardware state which will be constant through the life of
271848b8605Smrg * a context.
272848b8605Smrg */
273b8e80941Smrgenum pipe_error
274b8e80941Smrgsvga_emit_initial_state(struct svga_context *svga)
275848b8605Smrg{
276b8e80941Smrg   if (svga_have_vgpu10(svga)) {
277b8e80941Smrg      SVGA3dRasterizerStateId id = util_bitmask_add(svga->rast_object_id_bm);
278b8e80941Smrg      enum pipe_error ret;
279b8e80941Smrg
280b8e80941Smrg      /* XXX preliminary code */
281b8e80941Smrg      ret = SVGA3D_vgpu10_DefineRasterizerState(svga->swc,
282b8e80941Smrg                                             id,
283b8e80941Smrg                                             SVGA3D_FILLMODE_FILL,
284b8e80941Smrg                                             SVGA3D_CULL_NONE,
285b8e80941Smrg                                             1, /* frontCounterClockwise */
286b8e80941Smrg                                             0, /* depthBias */
287b8e80941Smrg                                             0.0f, /* depthBiasClamp */
288b8e80941Smrg                                             0.0f, /* slopeScaledDepthBiasClamp */
289b8e80941Smrg                                             0, /* depthClampEnable */
290b8e80941Smrg                                             0, /* scissorEnable */
291b8e80941Smrg                                             0, /* multisampleEnable */
292b8e80941Smrg                                             0, /* aalineEnable */
293b8e80941Smrg                                             1.0f, /* lineWidth */
294b8e80941Smrg                                             0, /* lineStippleEnable */
295b8e80941Smrg                                             0, /* lineStippleFactor */
296b8e80941Smrg                                             0, /* lineStipplePattern */
297b8e80941Smrg                                             0); /* provokingVertexLast */
298b8e80941Smrg
299b8e80941Smrg
300b8e80941Smrg      assert(ret == PIPE_OK);
301b8e80941Smrg
302b8e80941Smrg      ret = SVGA3D_vgpu10_SetRasterizerState(svga->swc, id);
303848b8605Smrg      return ret;
304b8e80941Smrg   }
305b8e80941Smrg   else {
306b8e80941Smrg      SVGA3dRenderState *rs;
307b8e80941Smrg      unsigned count = 0;
308b8e80941Smrg      const unsigned COUNT = 2;
309b8e80941Smrg      enum pipe_error ret;
310848b8605Smrg
311b8e80941Smrg      ret = SVGA3D_BeginSetRenderState( svga->swc, &rs, COUNT );
312b8e80941Smrg      if (ret != PIPE_OK)
313b8e80941Smrg         return ret;
314848b8605Smrg
315b8e80941Smrg      /* Always use D3D style coordinate space as this is the only one
316b8e80941Smrg       * which is implemented on all backends.
317b8e80941Smrg       */
318b8e80941Smrg      EMIT_RS(rs, count, SVGA3D_RS_COORDINATETYPE,
319b8e80941Smrg              SVGA3D_COORDINATE_LEFTHANDED );
320b8e80941Smrg      EMIT_RS(rs, count, SVGA3D_RS_FRONTWINDING, SVGA3D_FRONTWINDING_CW );
321b8e80941Smrg
322b8e80941Smrg      assert( COUNT == count );
323b8e80941Smrg      SVGA_FIFOCommitAll( svga->swc );
324b8e80941Smrg
325b8e80941Smrg      return PIPE_OK;
326b8e80941Smrg   }
327848b8605Smrg}
328