Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 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 | |
Brian Paul | e054251 | 2015-08-13 11:00:58 -0700 | [diff] [blame] | 26 | #include "util/u_bitmask.h" |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 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 | { |
Brian Paul | e054251 | 2015-08-13 11:00:58 -0700 | [diff] [blame] | 67 | &svga_need_tgsi_transform, |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 68 | &svga_hw_fs, |
Brian Paul | e054251 | 2015-08-13 11:00:58 -0700 | [diff] [blame] | 69 | &svga_hw_gs, |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 70 | &svga_hw_vs, |
| 71 | &svga_hw_rss, |
Brian Paul | e054251 | 2015-08-13 11:00:58 -0700 | [diff] [blame] | 72 | &svga_hw_sampler, /* VGPU10 */ |
| 73 | &svga_hw_sampler_bindings, /* VGPU10 */ |
| 74 | &svga_hw_tss, /* pre-VGPU10 */ |
| 75 | &svga_hw_tss_binding, /* pre-VGPU10 */ |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 76 | &svga_hw_clip_planes, |
| 77 | &svga_hw_vdecl, |
Brian Paul | 2a5eeea | 2012-08-09 10:14:51 -0600 | [diff] [blame] | 78 | &svga_hw_fs_constants, |
Brian Paul | e054251 | 2015-08-13 11:00:58 -0700 | [diff] [blame] | 79 | &svga_hw_gs_constants, |
Brian Paul | 2a5eeea | 2012-08-09 10:14:51 -0600 | [diff] [blame] | 80 | &svga_hw_vs_constants, |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 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 | */ |
Brian Paul | 49134c0 | 2017-03-01 13:48:28 -0700 | [diff] [blame] | 95 | static const struct svga_tracked_state **state_levels[] = |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 96 | { |
| 97 | need_swtnl_state, |
| 98 | hw_clear_state, |
| 99 | hw_draw_state, |
| 100 | swtnl_draw_state |
| 101 | }; |
| 102 | |
| 103 | |
| 104 | |
Brian Paul | 49134c0 | 2017-03-01 13:48:28 -0700 | [diff] [blame] | 105 | static unsigned |
| 106 | check_state(unsigned a, unsigned b) |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 107 | { |
| 108 | return (a & b); |
| 109 | } |
| 110 | |
Brian Paul | 49134c0 | 2017-03-01 13:48:28 -0700 | [diff] [blame] | 111 | static void |
| 112 | accumulate_state(unsigned *a, unsigned b) |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 113 | { |
| 114 | *a |= b; |
| 115 | } |
| 116 | |
| 117 | |
Brian Paul | 49134c0 | 2017-03-01 13:48:28 -0700 | [diff] [blame] | 118 | static void |
| 119 | xor_states(unsigned *result, unsigned a, unsigned b) |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 120 | { |
| 121 | *result = a ^ b; |
| 122 | } |
| 123 | |
| 124 | |
Brian Paul | 5f053bf | 2011-09-22 17:02:59 -0600 | [diff] [blame] | 125 | static enum pipe_error |
| 126 | update_state(struct svga_context *svga, |
| 127 | const struct svga_tracked_state *atoms[], |
| 128 | unsigned *state) |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 129 | { |
Brian Paul | c2c0983 | 2015-12-14 09:32:48 -0700 | [diff] [blame] | 130 | #ifdef DEBUG |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 131 | boolean debug = TRUE; |
Brian Paul | c2c0983 | 2015-12-14 09:32:48 -0700 | [diff] [blame] | 132 | #else |
| 133 | boolean debug = FALSE; |
| 134 | #endif |
Brian Paul | 5f053bf | 2011-09-22 17:02:59 -0600 | [diff] [blame] | 135 | enum pipe_error ret = PIPE_OK; |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 136 | unsigned i; |
| 137 | |
| 138 | ret = svga_hwtnl_flush( svga->hwtnl ); |
Brian Paul | 5f053bf | 2011-09-22 17:02:59 -0600 | [diff] [blame] | 139 | if (ret != PIPE_OK) |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 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 | */ |
Brian Paul | 49134c0 | 2017-03-01 13:48:28 -0700 | [diff] [blame] | 147 | unsigned examined, prev; |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 148 | |
| 149 | examined = 0; |
| 150 | prev = *state; |
| 151 | |
Brian Paul | 49134c0 | 2017-03-01 13:48:28 -0700 | [diff] [blame] | 152 | for (i = 0; atoms[i] != NULL; i++) { |
| 153 | unsigned generated; |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 154 | |
Brian Paul | 49134c0 | 2017-03-01 13:48:28 -0700 | [diff] [blame] | 155 | assert(atoms[i]->dirty); |
| 156 | assert(atoms[i]->update); |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 157 | |
Brian Paul | 49134c0 | 2017-03-01 13:48:28 -0700 | [diff] [blame] | 158 | if (check_state(*state, atoms[i]->dirty)) { |
| 159 | if (0) |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 160 | debug_printf("update: %s\n", atoms[i]->name); |
Brian Paul | 49134c0 | 2017-03-01 13:48:28 -0700 | [diff] [blame] | 161 | ret = atoms[i]->update( svga, *state ); |
Brian Paul | 5f053bf | 2011-09-22 17:02:59 -0600 | [diff] [blame] | 162 | if (ret != PIPE_OK) |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 163 | return ret; |
Brian Paul | 49134c0 | 2017-03-01 13:48:28 -0700 | [diff] [blame] | 164 | } |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 165 | |
Brian Paul | 49134c0 | 2017-03-01 13:48:28 -0700 | [diff] [blame] | 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", |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 173 | atoms[i]->name); |
Brian Paul | 49134c0 | 2017-03-01 13:48:28 -0700 | [diff] [blame] | 174 | assert(0); |
| 175 | } |
| 176 | |
| 177 | prev = *state; |
| 178 | accumulate_state(&examined, atoms[i]->dirty); |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 179 | } |
| 180 | } |
| 181 | else { |
Brian Paul | 49134c0 | 2017-03-01 13:48:28 -0700 | [diff] [blame] | 182 | for (i = 0; atoms[i] != NULL; i++) { |
| 183 | if (check_state(*state, atoms[i]->dirty)) { |
| 184 | ret = atoms[i]->update( svga, *state ); |
Brian Paul | 5f053bf | 2011-09-22 17:02:59 -0600 | [diff] [blame] | 185 | if (ret != PIPE_OK) |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 186 | return ret; |
| 187 | } |
| 188 | } |
| 189 | } |
| 190 | |
Brian Paul | 5f053bf | 2011-09-22 17:02:59 -0600 | [diff] [blame] | 191 | return PIPE_OK; |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 192 | } |
| 193 | |
| 194 | |
Brian Paul | 5f053bf | 2011-09-22 17:02:59 -0600 | [diff] [blame] | 195 | enum pipe_error |
| 196 | svga_update_state(struct svga_context *svga, unsigned max_level) |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 197 | { |
| 198 | struct svga_screen *screen = svga_screen(svga->pipe.screen); |
Brian Paul | 5f053bf | 2011-09-22 17:02:59 -0600 | [diff] [blame] | 199 | enum pipe_error ret = PIPE_OK; |
Brian Paul | 25cd2c2 | 2012-10-16 17:54:37 -0600 | [diff] [blame] | 200 | unsigned i; |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 201 | |
Charmaine Lee | 2e1cfcc | 2016-08-19 08:49:17 -0600 | [diff] [blame] | 202 | SVGA_STATS_TIME_PUSH(screen->sws, SVGA_STATS_TIME_UPDATESTATE); |
| 203 | |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 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) { |
Brian Paul | 49134c0 | 2017-03-01 13:48:28 -0700 | [diff] [blame] | 217 | ret = update_state( svga, |
| 218 | state_levels[i], |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 219 | &svga->dirty ); |
Brian Paul | 5f053bf | 2011-09-22 17:02:59 -0600 | [diff] [blame] | 220 | if (ret != PIPE_OK) |
Charmaine Lee | 2e1cfcc | 2016-08-19 08:49:17 -0600 | [diff] [blame] | 221 | goto done; |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 222 | |
| 223 | svga->state.dirty[i] = 0; |
| 224 | } |
| 225 | } |
Brian Paul | 49134c0 | 2017-03-01 13:48:28 -0700 | [diff] [blame] | 226 | |
| 227 | for (; i < SVGA_STATE_MAX; i++) |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 228 | svga->state.dirty[i] |= svga->dirty; |
| 229 | |
| 230 | svga->dirty = 0; |
Neha Bhende | 9bc7e31 | 2015-10-09 16:10:16 -0600 | [diff] [blame] | 231 | |
| 232 | svga->hud.num_validations++; |
| 233 | |
Charmaine Lee | 2e1cfcc | 2016-08-19 08:49:17 -0600 | [diff] [blame] | 234 | done: |
| 235 | SVGA_STATS_TIME_POP(screen->sws); |
| 236 | return ret; |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 237 | } |
| 238 | |
| 239 | |
Brian Paul | 49134c0 | 2017-03-01 13:48:28 -0700 | [diff] [blame] | 240 | void |
| 241 | svga_update_state_retry(struct svga_context *svga, unsigned max_level) |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 242 | { |
Brian Paul | 5f053bf | 2011-09-22 17:02:59 -0600 | [diff] [blame] | 243 | enum pipe_error ret; |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 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 | |
Brian Paul | 5f053bf | 2011-09-22 17:02:59 -0600 | [diff] [blame] | 252 | assert( ret == PIPE_OK ); |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 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 | */ |
Brian Paul | 49134c0 | 2017-03-01 13:48:28 -0700 | [diff] [blame] | 268 | enum pipe_error |
| 269 | svga_emit_initial_state(struct svga_context *svga) |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 270 | { |
Brian Paul | e054251 | 2015-08-13 11:00:58 -0700 | [diff] [blame] | 271 | if (svga_have_vgpu10(svga)) { |
| 272 | SVGA3dRasterizerStateId id = util_bitmask_add(svga->rast_object_id_bm); |
| 273 | enum pipe_error ret; |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 274 | |
Brian Paul | e054251 | 2015-08-13 11:00:58 -0700 | [diff] [blame] | 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); |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 298 | return ret; |
Brian Paul | e054251 | 2015-08-13 11:00:58 -0700 | [diff] [blame] | 299 | } |
| 300 | else { |
| 301 | SVGA3dRenderState *rs; |
| 302 | unsigned count = 0; |
| 303 | const unsigned COUNT = 2; |
| 304 | enum pipe_error ret; |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 305 | |
Brian Paul | e054251 | 2015-08-13 11:00:58 -0700 | [diff] [blame] | 306 | ret = SVGA3D_BeginSetRenderState( svga->swc, &rs, COUNT ); |
| 307 | if (ret != PIPE_OK) |
| 308 | return ret; |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 309 | |
Brian Paul | e054251 | 2015-08-13 11:00:58 -0700 | [diff] [blame] | 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 | } |
Jakob Bornecrantz | 3192633 | 2009-11-16 19:56:18 +0100 | [diff] [blame] | 322 | } |