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/* Atoms to update hardware state prior to emitting a draw packet. 64 */ 65static const struct svga_tracked_state *hw_draw_state[] = 66{ 67 &svga_need_tgsi_transform, 68 &svga_hw_fs, 69 &svga_hw_gs, 70 &svga_hw_vs, 71 &svga_hw_rss, 72 &svga_hw_sampler, /* VGPU10 */ 73 &svga_hw_sampler_bindings, /* VGPU10 */ 74 &svga_hw_tss, /* pre-VGPU10 */ 75 &svga_hw_tss_binding, /* pre-VGPU10 */ 76 &svga_hw_clip_planes, 77 &svga_hw_vdecl, 78 &svga_hw_fs_constants, 79 &svga_hw_gs_constants, 80 &svga_hw_vs_constants, 81 NULL 82}; 83 84 85static const struct svga_tracked_state *swtnl_draw_state[] = 86{ 87 &svga_update_swtnl_draw, 88 &svga_update_swtnl_vdecl, 89 NULL 90}; 91 92/* Flattens the graph of state dependencies. Could swap the positions 93 * of hw_clear_state and need_swtnl_state without breaking anything. 94 */ 95static const struct svga_tracked_state **state_levels[] = 96{ 97 need_swtnl_state, 98 hw_clear_state, 99 hw_draw_state, 100 swtnl_draw_state 101}; 102 103 104 105static unsigned 106check_state(unsigned a, unsigned b) 107{ 108 return (a & b); 109} 110 111static void 112accumulate_state(unsigned *a, unsigned b) 113{ 114 *a |= b; 115} 116 117 118static void 119xor_states(unsigned *result, unsigned a, unsigned b) 120{ 121 *result = a ^ b; 122} 123 124 125static enum pipe_error 126update_state(struct svga_context *svga, 127 const struct svga_tracked_state *atoms[], 128 unsigned *state) 129{ 130#ifdef DEBUG 131 boolean debug = TRUE; 132#else 133 boolean debug = FALSE; 134#endif 135 enum pipe_error ret = PIPE_OK; 136 unsigned i; 137 138 ret = svga_hwtnl_flush( svga->hwtnl ); 139 if (ret != PIPE_OK) 140 return ret; 141 142 if (debug) { 143 /* Debug version which enforces various sanity checks on the 144 * state flags which are generated and checked to help ensure 145 * state atoms are ordered correctly in the list. 146 */ 147 unsigned examined, prev; 148 149 examined = 0; 150 prev = *state; 151 152 for (i = 0; atoms[i] != NULL; i++) { 153 unsigned generated; 154 155 assert(atoms[i]->dirty); 156 assert(atoms[i]->update); 157 158 if (check_state(*state, atoms[i]->dirty)) { 159 if (0) 160 debug_printf("update: %s\n", atoms[i]->name); 161 ret = atoms[i]->update( svga, *state ); 162 if (ret != PIPE_OK) 163 return ret; 164 } 165 166 /* generated = (prev ^ state) 167 * if (examined & generated) 168 * fail; 169 */ 170 xor_states(&generated, prev, *state); 171 if (check_state(examined, generated)) { 172 debug_printf("state atom %s generated state already examined\n", 173 atoms[i]->name); 174 assert(0); 175 } 176 177 prev = *state; 178 accumulate_state(&examined, atoms[i]->dirty); 179 } 180 } 181 else { 182 for (i = 0; atoms[i] != NULL; i++) { 183 if (check_state(*state, atoms[i]->dirty)) { 184 ret = atoms[i]->update( svga, *state ); 185 if (ret != PIPE_OK) 186 return ret; 187 } 188 } 189 } 190 191 return PIPE_OK; 192} 193 194 195enum pipe_error 196svga_update_state(struct svga_context *svga, unsigned max_level) 197{ 198 struct svga_screen *screen = svga_screen(svga->pipe.screen); 199 enum pipe_error ret = PIPE_OK; 200 unsigned i; 201 202 SVGA_STATS_TIME_PUSH(screen->sws, SVGA_STATS_TIME_UPDATESTATE); 203 204 /* Check for updates to bound textures. This can't be done in an 205 * atom as there is no flag which could provoke this test, and we 206 * cannot create one. 207 */ 208 if (svga->state.texture_timestamp != screen->texture_timestamp) { 209 svga->state.texture_timestamp = screen->texture_timestamp; 210 svga->dirty |= SVGA_NEW_TEXTURE; 211 } 212 213 for (i = 0; i <= max_level; i++) { 214 svga->dirty |= svga->state.dirty[i]; 215 216 if (svga->dirty) { 217 ret = update_state( svga, 218 state_levels[i], 219 &svga->dirty ); 220 if (ret != PIPE_OK) 221 goto done; 222 223 svga->state.dirty[i] = 0; 224 } 225 } 226 227 for (; i < SVGA_STATE_MAX; i++) 228 svga->state.dirty[i] |= svga->dirty; 229 230 svga->dirty = 0; 231 232 svga->hud.num_validations++; 233 234done: 235 SVGA_STATS_TIME_POP(screen->sws); 236 return ret; 237} 238 239 240/** 241 * Update state. If the first attempt fails, flush the command buffer 242 * and retry. 243 * \return true if success, false if second attempt fails. 244 */ 245bool 246svga_update_state_retry(struct svga_context *svga, unsigned max_level) 247{ 248 enum pipe_error ret; 249 250 ret = svga_update_state( svga, max_level ); 251 252 if (ret != PIPE_OK) { 253 svga_context_flush(svga, NULL); 254 ret = svga_update_state( svga, max_level ); 255 } 256 257 return ret == PIPE_OK; 258} 259 260 261 262#define EMIT_RS(_rs, _count, _name, _value) \ 263do { \ 264 _rs[_count].state = _name; \ 265 _rs[_count].uintValue = _value; \ 266 _count++; \ 267} while (0) 268 269 270/* Setup any hardware state which will be constant through the life of 271 * a context. 272 */ 273enum pipe_error 274svga_emit_initial_state(struct svga_context *svga) 275{ 276 if (svga_have_vgpu10(svga)) { 277 SVGA3dRasterizerStateId id = util_bitmask_add(svga->rast_object_id_bm); 278 enum pipe_error ret; 279 280 /* XXX preliminary code */ 281 ret = SVGA3D_vgpu10_DefineRasterizerState(svga->swc, 282 id, 283 SVGA3D_FILLMODE_FILL, 284 SVGA3D_CULL_NONE, 285 1, /* frontCounterClockwise */ 286 0, /* depthBias */ 287 0.0f, /* depthBiasClamp */ 288 0.0f, /* slopeScaledDepthBiasClamp */ 289 0, /* depthClampEnable */ 290 0, /* scissorEnable */ 291 0, /* multisampleEnable */ 292 0, /* aalineEnable */ 293 1.0f, /* lineWidth */ 294 0, /* lineStippleEnable */ 295 0, /* lineStippleFactor */ 296 0, /* lineStipplePattern */ 297 0); /* provokingVertexLast */ 298 299 300 assert(ret == PIPE_OK); 301 302 ret = SVGA3D_vgpu10_SetRasterizerState(svga->swc, id); 303 return ret; 304 } 305 else { 306 SVGA3dRenderState *rs; 307 unsigned count = 0; 308 const unsigned COUNT = 2; 309 enum pipe_error ret; 310 311 ret = SVGA3D_BeginSetRenderState( svga->swc, &rs, COUNT ); 312 if (ret != PIPE_OK) 313 return ret; 314 315 /* Always use D3D style coordinate space as this is the only one 316 * which is implemented on all backends. 317 */ 318 EMIT_RS(rs, count, SVGA3D_RS_COORDINATETYPE, 319 SVGA3D_COORDINATE_LEFTHANDED ); 320 EMIT_RS(rs, count, SVGA3D_RS_FRONTWINDING, SVGA3D_FRONTWINDING_CW ); 321 322 assert( COUNT == count ); 323 SVGA_FIFOCommitAll( svga->swc ); 324 325 return PIPE_OK; 326 } 327} 328