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