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 check_state( unsigned a, 106 unsigned b ) 107{ 108 return (a & b); 109} 110 111static void accumulate_state( unsigned *a, 112 unsigned b ) 113{ 114 *a |= b; 115} 116 117 118static void xor_states( unsigned *result, 119 unsigned a, 120 unsigned b ) 121{ 122 *result = a ^ b; 123} 124 125 126 127static enum pipe_error 128update_state(struct svga_context *svga, 129 const struct svga_tracked_state *atoms[], 130 unsigned *state) 131{ 132#ifdef DEBUG 133 boolean debug = TRUE; 134#else 135 boolean debug = FALSE; 136#endif 137 enum pipe_error ret = PIPE_OK; 138 unsigned i; 139 140 ret = svga_hwtnl_flush( svga->hwtnl ); 141 if (ret != PIPE_OK) 142 return ret; 143 144 if (debug) { 145 /* Debug version which enforces various sanity checks on the 146 * state flags which are generated and checked to help ensure 147 * state atoms are ordered correctly in the list. 148 */ 149 unsigned examined, prev; 150 151 examined = 0; 152 prev = *state; 153 154 for (i = 0; atoms[i] != NULL; i++) { 155 unsigned generated; 156 157 assert(atoms[i]->dirty); 158 assert(atoms[i]->update); 159 160 if (check_state(*state, atoms[i]->dirty)) { 161 if (0) 162 debug_printf("update: %s\n", atoms[i]->name); 163 ret = atoms[i]->update( svga, *state ); 164 if (ret != PIPE_OK) 165 return ret; 166 } 167 168 /* generated = (prev ^ state) 169 * if (examined & generated) 170 * fail; 171 */ 172 xor_states(&generated, prev, *state); 173 if (check_state(examined, generated)) { 174 debug_printf("state atom %s generated state already examined\n", 175 atoms[i]->name); 176 assert(0); 177 } 178 179 prev = *state; 180 accumulate_state(&examined, atoms[i]->dirty); 181 } 182 } 183 else { 184 for (i = 0; atoms[i] != NULL; i++) { 185 if (check_state(*state, atoms[i]->dirty)) { 186 ret = atoms[i]->update( svga, *state ); 187 if (ret != PIPE_OK) 188 return ret; 189 } 190 } 191 } 192 193 return PIPE_OK; 194} 195 196 197 198enum pipe_error 199svga_update_state(struct svga_context *svga, unsigned max_level) 200{ 201 struct svga_screen *screen = svga_screen(svga->pipe.screen); 202 enum pipe_error ret = PIPE_OK; 203 unsigned i; 204 205 SVGA_STATS_TIME_PUSH(screen->sws, SVGA_STATS_TIME_UPDATESTATE); 206 207 /* Check for updates to bound textures. This can't be done in an 208 * atom as there is no flag which could provoke this test, and we 209 * cannot create one. 210 */ 211 if (svga->state.texture_timestamp != screen->texture_timestamp) { 212 svga->state.texture_timestamp = screen->texture_timestamp; 213 svga->dirty |= SVGA_NEW_TEXTURE; 214 } 215 216 for (i = 0; i <= max_level; i++) { 217 svga->dirty |= svga->state.dirty[i]; 218 219 if (svga->dirty) { 220 ret = update_state( svga, 221 state_levels[i], 222 &svga->dirty ); 223 if (ret != PIPE_OK) 224 goto done; 225 226 svga->state.dirty[i] = 0; 227 } 228 } 229 230 for (; i < SVGA_STATE_MAX; i++) 231 svga->state.dirty[i] |= svga->dirty; 232 233 svga->dirty = 0; 234 235 svga->hud.num_validations++; 236 237done: 238 SVGA_STATS_TIME_POP(screen->sws); 239 return ret; 240} 241 242 243 244 245void svga_update_state_retry( struct svga_context *svga, 246 unsigned max_level ) 247{ 248 enum pipe_error ret; 249 250 ret = svga_update_state( svga, max_level ); 251 252 if (ret == PIPE_ERROR_OUT_OF_MEMORY) { 253 svga_context_flush(svga, NULL); 254 ret = svga_update_state( svga, max_level ); 255 } 256 257 assert( 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 svga_emit_initial_state( struct svga_context *svga ) 274{ 275 if (svga_have_vgpu10(svga)) { 276 SVGA3dRasterizerStateId id = util_bitmask_add(svga->rast_object_id_bm); 277 enum pipe_error ret; 278 279 /* XXX preliminary code */ 280 ret = SVGA3D_vgpu10_DefineRasterizerState(svga->swc, 281 id, 282 SVGA3D_FILLMODE_FILL, 283 SVGA3D_CULL_NONE, 284 1, /* frontCounterClockwise */ 285 0, /* depthBias */ 286 0.0f, /* depthBiasClamp */ 287 0.0f, /* slopeScaledDepthBiasClamp */ 288 0, /* depthClampEnable */ 289 0, /* scissorEnable */ 290 0, /* multisampleEnable */ 291 0, /* aalineEnable */ 292 1.0f, /* lineWidth */ 293 0, /* lineStippleEnable */ 294 0, /* lineStippleFactor */ 295 0, /* lineStipplePattern */ 296 0); /* provokingVertexLast */ 297 298 299 assert(ret == PIPE_OK); 300 301 ret = SVGA3D_vgpu10_SetRasterizerState(svga->swc, id); 302 return ret; 303 } 304 else { 305 SVGA3dRenderState *rs; 306 unsigned count = 0; 307 const unsigned COUNT = 2; 308 enum pipe_error ret; 309 310 ret = SVGA3D_BeginSetRenderState( svga->swc, &rs, COUNT ); 311 if (ret != PIPE_OK) 312 return ret; 313 314 /* Always use D3D style coordinate space as this is the only one 315 * which is implemented on all backends. 316 */ 317 EMIT_RS(rs, count, SVGA3D_RS_COORDINATETYPE, 318 SVGA3D_COORDINATE_LEFTHANDED ); 319 EMIT_RS(rs, count, SVGA3D_RS_FRONTWINDING, SVGA3D_FRONTWINDING_CW ); 320 321 assert( COUNT == count ); 322 SVGA_FIFOCommitAll( svga->swc ); 323 324 return PIPE_OK; 325 } 326} 327