i915_state_emit.c revision ee7acf6493e934dbc78d98738195a3804c23722e
1/************************************************************************** 2 * 3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 29#include "i915_reg.h" 30#include "i915_context.h" 31#include "i915_batch.h" 32#include "i915_debug.h" 33#include "i915_resource.h" 34 35#include "pipe/p_context.h" 36#include "pipe/p_defines.h" 37 38#include "util/u_math.h" 39#include "util/u_memory.h" 40 41struct i915_tracked_hw_state { 42 const char *name; 43 void (*validate)(struct i915_context *, unsigned *batch_space); 44 void (*emit)(struct i915_context *); 45 unsigned dirty, batch_space; 46}; 47 48 49static void 50validate_flush(struct i915_context *i915, unsigned *batch_space) 51{ 52 *batch_space = i915->flush_dirty ? 1 : 0; 53} 54 55static void 56emit_flush(struct i915_context *i915) 57{ 58 /* Cache handling is very cheap atm. State handling can request to flushes: 59 * - I915_FLUSH_CACHE which is a flush everything request and 60 * - I915_PIPELINE_FLUSH which is specifically for the draw_offset flush. 61 * Because the cache handling is so dumb, no explicit "invalidate map cache". 62 * Also, the first is a strict superset of the latter, so the following logic 63 * works. */ 64 if (i915->flush_dirty & I915_FLUSH_CACHE) 65 OUT_BATCH(MI_FLUSH | FLUSH_MAP_CACHE); 66 else if (i915->flush_dirty & I915_PIPELINE_FLUSH) 67 OUT_BATCH(MI_FLUSH | INHIBIT_FLUSH_RENDER_CACHE); 68} 69 70uint32_t invariant_state[] = { 71 _3DSTATE_AA_CMD | AA_LINE_ECAAR_WIDTH_ENABLE | AA_LINE_ECAAR_WIDTH_1_0 | 72 AA_LINE_REGION_WIDTH_ENABLE | AA_LINE_REGION_WIDTH_1_0, 73 74 _3DSTATE_DFLT_DIFFUSE_CMD, 0, 75 76 _3DSTATE_DFLT_SPEC_CMD, 0, 77 78 _3DSTATE_DFLT_Z_CMD, 0, 79 80 _3DSTATE_COORD_SET_BINDINGS | 81 CSB_TCB(0, 0) | 82 CSB_TCB(1, 1) | 83 CSB_TCB(2, 2) | 84 CSB_TCB(3, 3) | 85 CSB_TCB(4, 4) | 86 CSB_TCB(5, 5) | 87 CSB_TCB(6, 6) | 88 CSB_TCB(7, 7), 89 90 _3DSTATE_RASTER_RULES_CMD | 91 ENABLE_POINT_RASTER_RULE | 92 OGL_POINT_RASTER_RULE | 93 ENABLE_LINE_STRIP_PROVOKE_VRTX | 94 ENABLE_TRI_FAN_PROVOKE_VRTX | 95 LINE_STRIP_PROVOKE_VRTX(1) | 96 TRI_FAN_PROVOKE_VRTX(2) | 97 ENABLE_TEXKILL_3D_4D | 98 TEXKILL_4D, 99 100 _3DSTATE_DEPTH_SUBRECT_DISABLE, 101 102 /* disable indirect state for now 103 */ 104 _3DSTATE_LOAD_INDIRECT | 0, 0}; 105 106static void 107emit_invariant(struct i915_context *i915) 108{ 109 i915_winsys_batchbuffer_write(i915->batch, invariant_state, 110 Elements(invariant_state)*sizeof(uint32_t)); 111} 112 113static void 114validate_immediate(struct i915_context *i915, unsigned *batch_space) 115{ 116 unsigned dirty = (1 << I915_IMMEDIATE_S0 | 1 << I915_IMMEDIATE_S1 | 117 1 << I915_IMMEDIATE_S2 | 1 << I915_IMMEDIATE_S3 | 118 1 << I915_IMMEDIATE_S3 | 1 << I915_IMMEDIATE_S4 | 119 1 << I915_IMMEDIATE_S5 | 1 << I915_IMMEDIATE_S6) & 120 i915->immediate_dirty; 121 122 if (i915->immediate_dirty & (1 << I915_IMMEDIATE_S0)) 123 i915->validation_buffers[i915->num_validation_buffers++] = i915->vbo; 124 125 *batch_space = 1 + util_bitcount(dirty); 126} 127 128static void 129emit_immediate(struct i915_context *i915) 130{ 131 /* remove unwatned bits and S7 */ 132 unsigned dirty = (1 << I915_IMMEDIATE_S0 | 1 << I915_IMMEDIATE_S1 | 133 1 << I915_IMMEDIATE_S2 | 1 << I915_IMMEDIATE_S3 | 134 1 << I915_IMMEDIATE_S3 | 1 << I915_IMMEDIATE_S4 | 135 1 << I915_IMMEDIATE_S5 | 1 << I915_IMMEDIATE_S6) & 136 i915->immediate_dirty; 137 int i, num = util_bitcount(dirty); 138 assert(num && num <= I915_MAX_IMMEDIATE); 139 140 OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | 141 dirty << 4 | (num - 1)); 142 143 if (i915->immediate_dirty & (1 << I915_IMMEDIATE_S0)) { 144 if (i915->vbo) 145 OUT_RELOC(i915->vbo, I915_USAGE_VERTEX, 146 i915->current.immediate[I915_IMMEDIATE_S0]); 147 else 148 OUT_BATCH(0); 149 } 150 151 for (i = 1; i < I915_MAX_IMMEDIATE; i++) { 152 if (dirty & (1 << i)) 153 OUT_BATCH(i915->current.immediate[i]); 154 } 155} 156 157static void 158validate_dynamic(struct i915_context *i915, unsigned *batch_space) 159{ 160 *batch_space = util_bitcount(i915->dynamic_dirty & ((1 << I915_MAX_DYNAMIC) - 1)); 161} 162 163static void 164emit_dynamic(struct i915_context *i915) 165{ 166 int i; 167 for (i = 0; i < I915_MAX_DYNAMIC; i++) { 168 if (i915->dynamic_dirty & (1 << i)) 169 OUT_BATCH(i915->current.dynamic[i]); 170 } 171} 172 173static void 174validate_static(struct i915_context *i915, unsigned *batch_space) 175{ 176 *batch_space = 2 + 5; /* including DRAW_RECT */ 177 178 if (i915->current.cbuf_bo) { 179 i915->validation_buffers[i915->num_validation_buffers++] 180 = i915->current.cbuf_bo; 181 *batch_space += 3; 182 } 183 184 if (i915->current.depth_bo) { 185 i915->validation_buffers[i915->num_validation_buffers++] 186 = i915->current.depth_bo; 187 *batch_space += 3; 188 } 189} 190 191static void 192emit_static(struct i915_context *i915) 193{ 194 if (i915->current.cbuf_bo) { 195 OUT_BATCH(_3DSTATE_BUF_INFO_CMD); 196 OUT_BATCH(i915->current.cbuf_flags); 197 OUT_RELOC(i915->current.cbuf_bo, 198 I915_USAGE_RENDER, 199 0); 200 } 201 202 /* What happens if no zbuf?? 203 */ 204 if (i915->current.depth_bo) { 205 OUT_BATCH(_3DSTATE_BUF_INFO_CMD); 206 OUT_BATCH(i915->current.depth_flags); 207 OUT_RELOC(i915->current.depth_bo, 208 I915_USAGE_RENDER, 209 0); 210 } 211 212 { 213 OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD); 214 OUT_BATCH(i915->current.dst_buf_vars); 215 } 216} 217 218static void 219validate_map(struct i915_context *i915, unsigned *batch_space) 220{ 221 const uint enabled = i915->current.sampler_enable_flags; 222 uint unit; 223 struct i915_texture *tex; 224 225 *batch_space = i915->current.sampler_enable_nr ? 226 2 + 3*i915->current.sampler_enable_nr : 0; 227 228 for (unit = 0; unit < I915_TEX_UNITS; unit++) { 229 if (enabled & (1 << unit)) { 230 tex = i915_texture(i915->fragment_sampler_views[unit]->texture); 231 i915->validation_buffers[i915->num_validation_buffers++] = tex->buffer; 232 } 233 } 234} 235 236static void 237emit_map(struct i915_context *i915) 238{ 239 const uint nr = i915->current.sampler_enable_nr; 240 if (nr) { 241 const uint enabled = i915->current.sampler_enable_flags; 242 uint unit; 243 uint count = 0; 244 OUT_BATCH(_3DSTATE_MAP_STATE | (3 * nr)); 245 OUT_BATCH(enabled); 246 for (unit = 0; unit < I915_TEX_UNITS; unit++) { 247 if (enabled & (1 << unit)) { 248 struct i915_texture *texture = i915_texture(i915->fragment_sampler_views[unit]->texture); 249 struct i915_winsys_buffer *buf = texture->buffer; 250 assert(buf); 251 252 count++; 253 254 OUT_RELOC(buf, I915_USAGE_SAMPLER, 0); 255 OUT_BATCH(i915->current.texbuffer[unit][0]); /* MS3 */ 256 OUT_BATCH(i915->current.texbuffer[unit][1]); /* MS4 */ 257 } 258 } 259 assert(count == nr); 260 } 261} 262 263static void 264validate_sampler(struct i915_context *i915, unsigned *batch_space) 265{ 266 *batch_space = i915->current.sampler_enable_nr ? 267 2 + 3*i915->current.sampler_enable_nr : 0; 268} 269 270static void 271emit_sampler(struct i915_context *i915) 272{ 273 if (i915->current.sampler_enable_nr) { 274 int i; 275 276 OUT_BATCH( _3DSTATE_SAMPLER_STATE | 277 (3 * i915->current.sampler_enable_nr) ); 278 279 OUT_BATCH( i915->current.sampler_enable_flags ); 280 281 for (i = 0; i < I915_TEX_UNITS; i++) { 282 if (i915->current.sampler_enable_flags & (1<<i)) { 283 OUT_BATCH( i915->current.sampler[i][0] ); 284 OUT_BATCH( i915->current.sampler[i][1] ); 285 OUT_BATCH( i915->current.sampler[i][2] ); 286 } 287 } 288 } 289} 290 291static void 292validate_constants(struct i915_context *i915, unsigned *batch_space) 293{ 294 *batch_space = i915->fs->num_constants ? 295 2 + 4*i915->fs->num_constants : 0; 296} 297 298static void 299emit_constants(struct i915_context *i915) 300{ 301 /* Collate the user-defined constants with the fragment shader's 302 * immediates according to the constant_flags[] array. 303 */ 304 const uint nr = i915->fs->num_constants; 305 if (nr) { 306 uint i; 307 308 OUT_BATCH( _3DSTATE_PIXEL_SHADER_CONSTANTS | (nr * 4) ); 309 OUT_BATCH((1 << nr) - 1); 310 311 for (i = 0; i < nr; i++) { 312 const uint *c; 313 if (i915->fs->constant_flags[i] == I915_CONSTFLAG_USER) { 314 /* grab user-defined constant */ 315 c = (uint *) i915_buffer(i915->constants[PIPE_SHADER_FRAGMENT])->data; 316 c += 4 * i; 317 } 318 else { 319 /* emit program constant */ 320 c = (uint *) i915->fs->constants[i]; 321 } 322#if 0 /* debug */ 323 { 324 float *f = (float *) c; 325 printf("Const %2d: %f %f %f %f %s\n", i, f[0], f[1], f[2], f[3], 326 (i915->fs->constant_flags[i] == I915_CONSTFLAG_USER 327 ? "user" : "immediate")); 328 } 329#endif 330 OUT_BATCH(*c++); 331 OUT_BATCH(*c++); 332 OUT_BATCH(*c++); 333 OUT_BATCH(*c++); 334 } 335 } 336} 337 338static void 339validate_program(struct i915_context *i915, unsigned *batch_space) 340{ 341 *batch_space = i915->fs->program_len; 342} 343 344static void 345emit_program(struct i915_context *i915) 346{ 347 uint i; 348 /* we should always have, at least, a pass-through program */ 349 assert(i915->fs->program_len > 0); 350 for (i = 0; i < i915->fs->program_len; i++) { 351 OUT_BATCH(i915->fs->program[i]); 352 } 353} 354 355static void 356emit_draw_rect(struct i915_context *i915) 357{ 358 OUT_BATCH(_3DSTATE_DRAW_RECT_CMD); 359 OUT_BATCH(DRAW_RECT_DIS_DEPTH_OFS); 360 OUT_BATCH(i915->current.draw_offset); 361 OUT_BATCH(i915->current.draw_size); 362 OUT_BATCH(i915->current.draw_offset); 363} 364 365static boolean 366i915_validate_state(struct i915_context *i915, unsigned *batch_space) 367{ 368 unsigned tmp; 369 370 i915->num_validation_buffers = 0; 371 if (i915->hardware_dirty & I915_HW_INVARIANT) 372 *batch_space = Elements(invariant_state); 373 else 374 *batch_space = 0; 375 376#define VALIDATE_ATOM(atom, hw_dirty) \ 377 if (i915->hardware_dirty & hw_dirty) { \ 378 validate_##atom(i915, &tmp); \ 379 *batch_space += tmp; } 380 VALIDATE_ATOM(flush, I915_HW_FLUSH); 381 VALIDATE_ATOM(immediate, I915_HW_IMMEDIATE); 382 VALIDATE_ATOM(dynamic, I915_HW_DYNAMIC); 383 VALIDATE_ATOM(static, I915_HW_STATIC); 384 VALIDATE_ATOM(map, I915_HW_MAP); 385 VALIDATE_ATOM(sampler, I915_HW_SAMPLER); 386 VALIDATE_ATOM(constants, I915_HW_CONSTANTS); 387 VALIDATE_ATOM(program, I915_HW_PROGRAM); 388#undef VALIDATE_ATOM 389 390 if (i915->num_validation_buffers == 0) 391 return TRUE; 392 393 if (!i915_winsys_validate_buffers(i915->batch, i915->validation_buffers, 394 i915->num_validation_buffers)) 395 return FALSE; 396 397 return TRUE; 398} 399 400/* Push the state into the sarea and/or texture memory. 401 */ 402void 403i915_emit_hardware_state(struct i915_context *i915 ) 404{ 405 unsigned batch_space; 406 /* XXX: there must be an easier way */ 407 const unsigned relocs = ( I915_TEX_UNITS + 408 3 409 ) * 3/2; /* plus 50% margin */ 410 411 uintptr_t save_ptr; 412 size_t save_relocs; 413 414 if (I915_DBG_ON(DBG_ATOMS)) 415 i915_dump_hardware_dirty(i915, __FUNCTION__); 416 417 if (!i915_validate_state(i915, &batch_space)) { 418 FLUSH_BATCH(NULL); 419 assert(i915_validate_state(i915, &batch_space)); 420 } 421 422 if(!BEGIN_BATCH(batch_space, relocs)) { 423 FLUSH_BATCH(NULL); 424 assert(i915_validate_state(i915, &batch_space)); 425 assert(BEGIN_BATCH(batch_space, relocs)); 426 } 427 428 save_ptr = (uintptr_t)i915->batch->ptr; 429 save_relocs = i915->batch->relocs; 430 431#define EMIT_ATOM(atom, hw_dirty) \ 432 if (i915->hardware_dirty & hw_dirty) \ 433 emit_##atom(i915); 434 EMIT_ATOM(flush, I915_HW_FLUSH); 435 EMIT_ATOM(invariant, I915_HW_INVARIANT); 436 EMIT_ATOM(immediate, I915_HW_IMMEDIATE); 437 EMIT_ATOM(dynamic, I915_HW_DYNAMIC); 438 EMIT_ATOM(static, I915_HW_STATIC); 439 EMIT_ATOM(map, I915_HW_MAP); 440 EMIT_ATOM(sampler, I915_HW_SAMPLER); 441 EMIT_ATOM(constants, I915_HW_CONSTANTS); 442 EMIT_ATOM(program, I915_HW_PROGRAM); 443 EMIT_ATOM(draw_rect, I915_HW_STATIC); 444#undef EMIT_ATOM 445 446 I915_DBG(DBG_EMIT, "%s: used %d dwords, %d dwords reserved\n", __FUNCTION__, 447 ((uintptr_t)i915->batch->ptr - save_ptr) / 4, 448 batch_space); 449 assert(((uintptr_t)i915->batch->ptr - save_ptr) / 4 == batch_space); 450 451 i915->hardware_dirty = 0; 452 i915->immediate_dirty = 0; 453 i915->dynamic_dirty = 0; 454 i915->flush_dirty = 0; 455} 456