14a49301eSmrg/**********************************************************
24a49301eSmrg * Copyright 2008-2009 VMware, Inc.  All rights reserved.
34a49301eSmrg *
44a49301eSmrg * Permission is hereby granted, free of charge, to any person
54a49301eSmrg * obtaining a copy of this software and associated documentation
64a49301eSmrg * files (the "Software"), to deal in the Software without
74a49301eSmrg * restriction, including without limitation the rights to use, copy,
84a49301eSmrg * modify, merge, publish, distribute, sublicense, and/or sell copies
94a49301eSmrg * of the Software, and to permit persons to whom the Software is
104a49301eSmrg * furnished to do so, subject to the following conditions:
114a49301eSmrg *
124a49301eSmrg * The above copyright notice and this permission notice shall be
134a49301eSmrg * included in all copies or substantial portions of the Software.
144a49301eSmrg *
154a49301eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
164a49301eSmrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
174a49301eSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
184a49301eSmrg * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
194a49301eSmrg * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
204a49301eSmrg * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
214a49301eSmrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
224a49301eSmrg * SOFTWARE.
234a49301eSmrg *
244a49301eSmrg **********************************************************/
254a49301eSmrg
2601e04c3fSmrg#include "util/u_bitmask.h"
274a49301eSmrg#include "util/u_debug.h"
284a49301eSmrg#include "pipe/p_defines.h"
294a49301eSmrg#include "util/u_memory.h"
304a49301eSmrg#include "draw/draw_context.h"
314a49301eSmrg
324a49301eSmrg#include "svga_context.h"
334a49301eSmrg#include "svga_screen.h"
344a49301eSmrg#include "svga_state.h"
354a49301eSmrg#include "svga_draw.h"
364a49301eSmrg#include "svga_cmd.h"
374a49301eSmrg#include "svga_hw_reg.h"
384a49301eSmrg
394a49301eSmrg/* This is just enough to decide whether we need to use the draw
404a49301eSmrg * module (swtnl) or not.
414a49301eSmrg */
424a49301eSmrgstatic const struct svga_tracked_state *need_swtnl_state[] =
434a49301eSmrg{
444a49301eSmrg   &svga_update_need_swvfetch,
454a49301eSmrg   &svga_update_need_pipeline,
464a49301eSmrg   &svga_update_need_swtnl,
474a49301eSmrg   NULL
484a49301eSmrg};
494a49301eSmrg
504a49301eSmrg
514a49301eSmrg/* Atoms to update hardware state prior to emitting a clear or draw
524a49301eSmrg * packet.
534a49301eSmrg */
544a49301eSmrgstatic const struct svga_tracked_state *hw_clear_state[] =
554a49301eSmrg{
564a49301eSmrg   &svga_hw_scissor,
574a49301eSmrg   &svga_hw_viewport,
584a49301eSmrg   &svga_hw_framebuffer,
594a49301eSmrg   NULL
604a49301eSmrg};
614a49301eSmrg
624a49301eSmrg
637ec681f3Smrg/**
647ec681f3Smrg * Atoms to update hardware state prior to emitting a draw packet
657ec681f3Smrg * for VGPU9 device.
664a49301eSmrg */
677ec681f3Smrgstatic const struct svga_tracked_state *hw_draw_state_vgpu9[] =
687ec681f3Smrg{
697ec681f3Smrg   &svga_hw_fs,
707ec681f3Smrg   &svga_hw_vs,
717ec681f3Smrg   &svga_hw_rss,
727ec681f3Smrg   &svga_hw_tss,
737ec681f3Smrg   &svga_hw_tss_binding,
747ec681f3Smrg   &svga_hw_clip_planes,
757ec681f3Smrg   &svga_hw_vdecl,
767ec681f3Smrg   &svga_hw_fs_constants,
777ec681f3Smrg   &svga_hw_vs_constants,
787ec681f3Smrg   NULL
797ec681f3Smrg};
807ec681f3Smrg
817ec681f3Smrg
827ec681f3Smrg/**
837ec681f3Smrg * Atoms to update hardware state prior to emitting a draw packet
847ec681f3Smrg * for VGPU10 device.
857ec681f3Smrg * Geometry Shader is new to VGPU10.
867ec681f3Smrg * TSS and TSS bindings are replaced by sampler and sampler bindings.
877ec681f3Smrg */
887ec681f3Smrgstatic const struct svga_tracked_state *hw_draw_state_vgpu10[] =
894a49301eSmrg{
9001e04c3fSmrg   &svga_need_tgsi_transform,
914a49301eSmrg   &svga_hw_fs,
9201e04c3fSmrg   &svga_hw_gs,
934a49301eSmrg   &svga_hw_vs,
944a49301eSmrg   &svga_hw_rss,
957ec681f3Smrg   &svga_hw_sampler,
967ec681f3Smrg   &svga_hw_sampler_bindings,
974a49301eSmrg   &svga_hw_clip_planes,
984a49301eSmrg   &svga_hw_vdecl,
99af69d88dSmrg   &svga_hw_fs_constants,
1007ec681f3Smrg   &svga_hw_fs_constbufs,
10101e04c3fSmrg   &svga_hw_gs_constants,
1027ec681f3Smrg   &svga_hw_gs_constbufs,
103af69d88dSmrg   &svga_hw_vs_constants,
1047ec681f3Smrg   &svga_hw_vs_constbufs,
1057ec681f3Smrg   NULL
1067ec681f3Smrg};
1077ec681f3Smrg
1087ec681f3Smrg
1097ec681f3Smrg/**
1107ec681f3Smrg * Atoms to update hardware state prior to emitting a draw packet
1117ec681f3Smrg * for SM5 device.
1127ec681f3Smrg * TCS and TES Shaders are new to SM5 device.
1137ec681f3Smrg */
1147ec681f3Smrgstatic const struct svga_tracked_state *hw_draw_state_sm5[] =
1157ec681f3Smrg{
1167ec681f3Smrg   &svga_need_tgsi_transform,
1177ec681f3Smrg   &svga_hw_fs,
1187ec681f3Smrg   &svga_hw_gs,
1197ec681f3Smrg   &svga_hw_tes,
1207ec681f3Smrg   &svga_hw_tcs,
1217ec681f3Smrg   &svga_hw_vs,
1227ec681f3Smrg   &svga_hw_rss,
1237ec681f3Smrg   &svga_hw_sampler,
1247ec681f3Smrg   &svga_hw_sampler_bindings,
1257ec681f3Smrg   &svga_hw_clip_planes,
1267ec681f3Smrg   &svga_hw_vdecl,
1277ec681f3Smrg   &svga_hw_fs_constants,
1287ec681f3Smrg   &svga_hw_fs_constbufs,
1297ec681f3Smrg   &svga_hw_gs_constants,
1307ec681f3Smrg   &svga_hw_gs_constbufs,
1317ec681f3Smrg   &svga_hw_tes_constants,
1327ec681f3Smrg   &svga_hw_tes_constbufs,
1337ec681f3Smrg   &svga_hw_tcs_constants,
1347ec681f3Smrg   &svga_hw_tcs_constbufs,
1357ec681f3Smrg   &svga_hw_vs_constants,
1367ec681f3Smrg   &svga_hw_vs_constbufs,
1374a49301eSmrg   NULL
1384a49301eSmrg};
1394a49301eSmrg
1404a49301eSmrg
1414a49301eSmrgstatic const struct svga_tracked_state *swtnl_draw_state[] =
1424a49301eSmrg{
1434a49301eSmrg   &svga_update_swtnl_draw,
1444a49301eSmrg   &svga_update_swtnl_vdecl,
1454a49301eSmrg   NULL
1464a49301eSmrg};
1474a49301eSmrg
1487ec681f3Smrg
1494a49301eSmrg/* Flattens the graph of state dependencies.  Could swap the positions
1504a49301eSmrg * of hw_clear_state and need_swtnl_state without breaking anything.
1514a49301eSmrg */
15201e04c3fSmrgstatic const struct svga_tracked_state **state_levels[] =
1534a49301eSmrg{
1544a49301eSmrg   need_swtnl_state,
1554a49301eSmrg   hw_clear_state,
1567ec681f3Smrg   NULL,              /* hw_draw_state, to be set to the right version */
1574a49301eSmrg   swtnl_draw_state
1584a49301eSmrg};
1594a49301eSmrg
1604a49301eSmrg
1617ec681f3Smrgstatic uint64_t
1627ec681f3Smrgcheck_state(uint64_t a, uint64_t b)
1634a49301eSmrg{
1644a49301eSmrg   return (a & b);
1654a49301eSmrg}
1664a49301eSmrg
16701e04c3fSmrgstatic void
1687ec681f3Smrgaccumulate_state(uint64_t *a, uint64_t b)
1694a49301eSmrg{
1704a49301eSmrg   *a |= b;
1714a49301eSmrg}
1724a49301eSmrg
1734a49301eSmrg
17401e04c3fSmrgstatic void
1757ec681f3Smrgxor_states(uint64_t *result, uint64_t a, uint64_t b)
1764a49301eSmrg{
1774a49301eSmrg   *result = a ^ b;
1784a49301eSmrg}
1794a49301eSmrg
1804a49301eSmrg
181af69d88dSmrgstatic enum pipe_error
182af69d88dSmrgupdate_state(struct svga_context *svga,
183af69d88dSmrg             const struct svga_tracked_state *atoms[],
1847ec681f3Smrg             uint64_t *state)
1854a49301eSmrg{
18601e04c3fSmrg#ifdef DEBUG
1874a49301eSmrg   boolean debug = TRUE;
18801e04c3fSmrg#else
18901e04c3fSmrg   boolean debug = FALSE;
19001e04c3fSmrg#endif
191af69d88dSmrg   enum pipe_error ret = PIPE_OK;
1924a49301eSmrg   unsigned i;
1934a49301eSmrg
1944a49301eSmrg   ret = svga_hwtnl_flush( svga->hwtnl );
195af69d88dSmrg   if (ret != PIPE_OK)
1964a49301eSmrg      return ret;
1974a49301eSmrg
1984a49301eSmrg   if (debug) {
1994a49301eSmrg      /* Debug version which enforces various sanity checks on the
2004a49301eSmrg       * state flags which are generated and checked to help ensure
2014a49301eSmrg       * state atoms are ordered correctly in the list.
2024a49301eSmrg       */
2037ec681f3Smrg      uint64_t examined, prev;
2044a49301eSmrg
2054a49301eSmrg      examined = 0;
2064a49301eSmrg      prev = *state;
2074a49301eSmrg
20801e04c3fSmrg      for (i = 0; atoms[i] != NULL; i++) {
2097ec681f3Smrg         uint64_t generated;
2104a49301eSmrg
21101e04c3fSmrg         assert(atoms[i]->dirty);
21201e04c3fSmrg         assert(atoms[i]->update);
2134a49301eSmrg
21401e04c3fSmrg         if (check_state(*state, atoms[i]->dirty)) {
21501e04c3fSmrg            if (0)
2164a49301eSmrg               debug_printf("update: %s\n", atoms[i]->name);
21701e04c3fSmrg            ret = atoms[i]->update( svga, *state );
218af69d88dSmrg            if (ret != PIPE_OK)
2194a49301eSmrg               return ret;
22001e04c3fSmrg         }
22101e04c3fSmrg
22201e04c3fSmrg         /* generated = (prev ^ state)
22301e04c3fSmrg          * if (examined & generated)
22401e04c3fSmrg          *     fail;
22501e04c3fSmrg          */
22601e04c3fSmrg         xor_states(&generated, prev, *state);
22701e04c3fSmrg         if (check_state(examined, generated)) {
22801e04c3fSmrg            debug_printf("state atom %s generated state already examined\n",
2294a49301eSmrg                         atoms[i]->name);
23001e04c3fSmrg            assert(0);
23101e04c3fSmrg         }
23201e04c3fSmrg
23301e04c3fSmrg         prev = *state;
23401e04c3fSmrg         accumulate_state(&examined, atoms[i]->dirty);
2354a49301eSmrg      }
2364a49301eSmrg   }
2374a49301eSmrg   else {
23801e04c3fSmrg      for (i = 0; atoms[i] != NULL; i++) {
23901e04c3fSmrg         if (check_state(*state, atoms[i]->dirty)) {
24001e04c3fSmrg            ret = atoms[i]->update( svga, *state );
241af69d88dSmrg            if (ret != PIPE_OK)
2424a49301eSmrg               return ret;
2434a49301eSmrg         }
2444a49301eSmrg      }
2454a49301eSmrg   }
2464a49301eSmrg
247af69d88dSmrg   return PIPE_OK;
2484a49301eSmrg}
2494a49301eSmrg
2504a49301eSmrg
251af69d88dSmrgenum pipe_error
252af69d88dSmrgsvga_update_state(struct svga_context *svga, unsigned max_level)
2534a49301eSmrg{
2544a49301eSmrg   struct svga_screen *screen = svga_screen(svga->pipe.screen);
255af69d88dSmrg   enum pipe_error ret = PIPE_OK;
256af69d88dSmrg   unsigned i;
2574a49301eSmrg
25801e04c3fSmrg   SVGA_STATS_TIME_PUSH(screen->sws, SVGA_STATS_TIME_UPDATESTATE);
25901e04c3fSmrg
2604a49301eSmrg   /* Check for updates to bound textures.  This can't be done in an
2614a49301eSmrg    * atom as there is no flag which could provoke this test, and we
2624a49301eSmrg    * cannot create one.
2634a49301eSmrg    */
2644a49301eSmrg   if (svga->state.texture_timestamp != screen->texture_timestamp) {
2654a49301eSmrg      svga->state.texture_timestamp = screen->texture_timestamp;
2664a49301eSmrg      svga->dirty |= SVGA_NEW_TEXTURE;
2674a49301eSmrg   }
2684a49301eSmrg
2694a49301eSmrg   for (i = 0; i <= max_level; i++) {
2704a49301eSmrg      svga->dirty |= svga->state.dirty[i];
2714a49301eSmrg
2724a49301eSmrg      if (svga->dirty) {
27301e04c3fSmrg         ret = update_state( svga,
27401e04c3fSmrg                             state_levels[i],
2754a49301eSmrg                             &svga->dirty );
276af69d88dSmrg         if (ret != PIPE_OK)
27701e04c3fSmrg            goto done;
2784a49301eSmrg
2794a49301eSmrg         svga->state.dirty[i] = 0;
2804a49301eSmrg      }
2814a49301eSmrg   }
28201e04c3fSmrg
28301e04c3fSmrg   for (; i < SVGA_STATE_MAX; i++)
2844a49301eSmrg      svga->state.dirty[i] |= svga->dirty;
2854a49301eSmrg
2864a49301eSmrg   svga->dirty = 0;
2874a49301eSmrg
28801e04c3fSmrg   svga->hud.num_validations++;
2894a49301eSmrg
29001e04c3fSmrgdone:
29101e04c3fSmrg   SVGA_STATS_TIME_POP(screen->sws);
29201e04c3fSmrg   return ret;
29301e04c3fSmrg}
2944a49301eSmrg
2954a49301eSmrg
29601e04c3fSmrg/**
29701e04c3fSmrg * Update state.  If the first attempt fails, flush the command buffer
29801e04c3fSmrg * and retry.
29901e04c3fSmrg * \return  true if success, false if second attempt fails.
30001e04c3fSmrg */
30101e04c3fSmrgbool
30201e04c3fSmrgsvga_update_state_retry(struct svga_context *svga, unsigned max_level)
3034a49301eSmrg{
304af69d88dSmrg   enum pipe_error ret;
3054a49301eSmrg
3067ec681f3Smrg   SVGA_RETRY_OOM(svga, ret, svga_update_state( svga, max_level ));
3074a49301eSmrg
30801e04c3fSmrg   return ret == PIPE_OK;
3094a49301eSmrg}
3104a49301eSmrg
3114a49301eSmrg
3124a49301eSmrg
3134a49301eSmrg#define EMIT_RS(_rs, _count, _name, _value)     \
3144a49301eSmrgdo {                                            \
3154a49301eSmrg   _rs[_count].state = _name;                   \
3164a49301eSmrg   _rs[_count].uintValue = _value;              \
3174a49301eSmrg   _count++;                                    \
3184a49301eSmrg} while (0)
3194a49301eSmrg
3204a49301eSmrg
3214a49301eSmrg/* Setup any hardware state which will be constant through the life of
3224a49301eSmrg * a context.
3234a49301eSmrg */
32401e04c3fSmrgenum pipe_error
32501e04c3fSmrgsvga_emit_initial_state(struct svga_context *svga)
3264a49301eSmrg{
32701e04c3fSmrg   if (svga_have_vgpu10(svga)) {
32801e04c3fSmrg      SVGA3dRasterizerStateId id = util_bitmask_add(svga->rast_object_id_bm);
32901e04c3fSmrg      enum pipe_error ret;
33001e04c3fSmrg
33101e04c3fSmrg      /* XXX preliminary code */
33201e04c3fSmrg      ret = SVGA3D_vgpu10_DefineRasterizerState(svga->swc,
33301e04c3fSmrg                                             id,
33401e04c3fSmrg                                             SVGA3D_FILLMODE_FILL,
33501e04c3fSmrg                                             SVGA3D_CULL_NONE,
33601e04c3fSmrg                                             1, /* frontCounterClockwise */
33701e04c3fSmrg                                             0, /* depthBias */
33801e04c3fSmrg                                             0.0f, /* depthBiasClamp */
33901e04c3fSmrg                                             0.0f, /* slopeScaledDepthBiasClamp */
34001e04c3fSmrg                                             0, /* depthClampEnable */
34101e04c3fSmrg                                             0, /* scissorEnable */
34201e04c3fSmrg                                             0, /* multisampleEnable */
34301e04c3fSmrg                                             0, /* aalineEnable */
34401e04c3fSmrg                                             1.0f, /* lineWidth */
34501e04c3fSmrg                                             0, /* lineStippleEnable */
34601e04c3fSmrg                                             0, /* lineStippleFactor */
34701e04c3fSmrg                                             0, /* lineStipplePattern */
34801e04c3fSmrg                                             0); /* provokingVertexLast */
34901e04c3fSmrg
35001e04c3fSmrg
35101e04c3fSmrg      assert(ret == PIPE_OK);
35201e04c3fSmrg
35301e04c3fSmrg      ret = SVGA3D_vgpu10_SetRasterizerState(svga->swc, id);
3544a49301eSmrg      return ret;
35501e04c3fSmrg   }
35601e04c3fSmrg   else {
35701e04c3fSmrg      SVGA3dRenderState *rs;
35801e04c3fSmrg      unsigned count = 0;
35901e04c3fSmrg      const unsigned COUNT = 2;
36001e04c3fSmrg      enum pipe_error ret;
3614a49301eSmrg
36201e04c3fSmrg      ret = SVGA3D_BeginSetRenderState( svga->swc, &rs, COUNT );
36301e04c3fSmrg      if (ret != PIPE_OK)
36401e04c3fSmrg         return ret;
3654a49301eSmrg
36601e04c3fSmrg      /* Always use D3D style coordinate space as this is the only one
36701e04c3fSmrg       * which is implemented on all backends.
36801e04c3fSmrg       */
36901e04c3fSmrg      EMIT_RS(rs, count, SVGA3D_RS_COORDINATETYPE,
37001e04c3fSmrg              SVGA3D_COORDINATE_LEFTHANDED );
37101e04c3fSmrg      EMIT_RS(rs, count, SVGA3D_RS_FRONTWINDING, SVGA3D_FRONTWINDING_CW );
37201e04c3fSmrg
37301e04c3fSmrg      assert( COUNT == count );
37401e04c3fSmrg      SVGA_FIFOCommitAll( svga->swc );
37501e04c3fSmrg
37601e04c3fSmrg      return PIPE_OK;
37701e04c3fSmrg   }
3784a49301eSmrg}
3797ec681f3Smrg
3807ec681f3Smrg
3817ec681f3Smrgvoid
3827ec681f3Smrgsvga_init_tracked_state(struct svga_context *svga)
3837ec681f3Smrg{
3847ec681f3Smrg   /* Set the hw_draw_state atom list to the one for the particular gpu version.
3857ec681f3Smrg    */
3867ec681f3Smrg   state_levels[2] = svga_have_sm5(svga) ? hw_draw_state_sm5 :
3877ec681f3Smrg                       (svga_have_vgpu10(svga) ? hw_draw_state_vgpu10 :
3887ec681f3Smrg                                                 hw_draw_state_vgpu9);
3897ec681f3Smrg}
390