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 */ 42 static 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 */ 54 static 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 */ 65 static 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 85 static 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 */ 95 static 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 105 static unsigned 106 check_state(unsigned a, unsigned b) 107 { 108 return (a & b); 109 } 110 111 static void 112 accumulate_state(unsigned *a, unsigned b) 113 { 114 *a |= b; 115 } 116 117 118 static void 119 xor_states(unsigned *result, unsigned a, unsigned b) 120 { 121 *result = a ^ b; 122 } 123 124 125 static enum pipe_error 126 update_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 195 enum pipe_error 196 svga_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 234 done: 235 SVGA_STATS_TIME_POP(screen->sws); 236 return ret; 237 } 238 239 240 void 241 svga_update_state_retry(struct svga_context *svga, unsigned max_level) 242 { 243 enum pipe_error ret; 244 245 ret = svga_update_state( svga, max_level ); 246 247 if (ret == PIPE_ERROR_OUT_OF_MEMORY) { 248 svga_context_flush(svga, NULL); 249 ret = svga_update_state( svga, max_level ); 250 } 251 252 assert( ret == PIPE_OK ); 253 } 254 255 256 257 #define EMIT_RS(_rs, _count, _name, _value) \ 258 do { \ 259 _rs[_count].state = _name; \ 260 _rs[_count].uintValue = _value; \ 261 _count++; \ 262 } while (0) 263 264 265 /* Setup any hardware state which will be constant through the life of 266 * a context. 267 */ 268 enum pipe_error 269 svga_emit_initial_state(struct svga_context *svga) 270 { 271 if (svga_have_vgpu10(svga)) { 272 SVGA3dRasterizerStateId id = util_bitmask_add(svga->rast_object_id_bm); 273 enum pipe_error ret; 274 275 /* XXX preliminary code */ 276 ret = SVGA3D_vgpu10_DefineRasterizerState(svga->swc, 277 id, 278 SVGA3D_FILLMODE_FILL, 279 SVGA3D_CULL_NONE, 280 1, /* frontCounterClockwise */ 281 0, /* depthBias */ 282 0.0f, /* depthBiasClamp */ 283 0.0f, /* slopeScaledDepthBiasClamp */ 284 0, /* depthClampEnable */ 285 0, /* scissorEnable */ 286 0, /* multisampleEnable */ 287 0, /* aalineEnable */ 288 1.0f, /* lineWidth */ 289 0, /* lineStippleEnable */ 290 0, /* lineStippleFactor */ 291 0, /* lineStipplePattern */ 292 0); /* provokingVertexLast */ 293 294 295 assert(ret == PIPE_OK); 296 297 ret = SVGA3D_vgpu10_SetRasterizerState(svga->swc, id); 298 return ret; 299 } 300 else { 301 SVGA3dRenderState *rs; 302 unsigned count = 0; 303 const unsigned COUNT = 2; 304 enum pipe_error ret; 305 306 ret = SVGA3D_BeginSetRenderState( svga->swc, &rs, COUNT ); 307 if (ret != PIPE_OK) 308 return ret; 309 310 /* Always use D3D style coordinate space as this is the only one 311 * which is implemented on all backends. 312 */ 313 EMIT_RS(rs, count, SVGA3D_RS_COORDINATETYPE, 314 SVGA3D_COORDINATE_LEFTHANDED ); 315 EMIT_RS(rs, count, SVGA3D_RS_FRONTWINDING, SVGA3D_FRONTWINDING_CW ); 316 317 assert( COUNT == count ); 318 SVGA_FIFOCommitAll( svga->swc ); 319 320 return PIPE_OK; 321 } 322 } 323