49cc967716e1535fb63e75f93bf9b952d127f3c6
[mesa.git] / src / mesa / drivers / dri / i965 / brw_aub_playback.c
1
2 #include <stdio.h>
3 #include <sys/mman.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <unistd.h>
7 #include <fcntl.h>
8
9 #include "brw_aub.h"
10 #include "brw_defines.h"
11 #include "brw_context.h"
12 #include "intel_ioctl.h"
13 #include "bufmgr.h"
14
15 struct aub_state {
16 struct intel_context *intel;
17 const char *map;
18 unsigned int csr;
19 unsigned int sz;
20 };
21
22
23 static int gobble( struct aub_state *s, int size )
24 {
25 if (s->csr + size > s->sz) {
26 _mesa_printf("EOF in %s\n", __FUNCTION__);
27 return 1;
28 }
29
30 s->csr += size;
31 return 0;
32 }
33
34 static void flush_and_fence( struct aub_state *s )
35 {
36 struct intel_context *intel = s->intel;
37 GLuint buf[2];
38
39 buf[0] = intel->vtbl.flush_cmd();
40 buf[1] = 0;
41
42 intel_cmd_ioctl(intel, (char *)&buf, sizeof(buf), GL_TRUE);
43
44 intelWaitIrq( intel, intelEmitIrqLocked( intel ));
45 }
46
47 static void flush_cmds( struct aub_state *s,
48 const void *data,
49 int len )
50 {
51 DBG("%s %d\n", __FUNCTION__, len);
52
53 if (len & 0x4) {
54 unsigned int *tmp = malloc(len + 4);
55 DBG("padding to octword\n");
56 memcpy(tmp, data, len);
57 tmp[len/4] = MI_NOOP;
58 flush_cmds(s, tmp, len+4);
59 free(tmp);
60 return;
61 }
62
63 /* For ring data, just send off immediately via an ioctl.
64 * This differs slightly from how the stream was executed
65 * initially as this would have been a batchbuffer.
66 */
67 intel_cmd_ioctl(s->intel, (void *)data, len, GL_TRUE);
68
69 if (1)
70 flush_and_fence(s);
71 }
72
73 static const char *pstrings[] = {
74 "none",
75 "POINTLIST",
76 "LINELIST",
77 "LINESTRIP",
78 "TRILIST",
79 "TRISTRIP",
80 "TRIFAN",
81 "QUADLIST",
82 "QUADSTRIP",
83 "LINELIST_ADJ",
84 "LINESTRIP_ADJ",
85 "TRILIST_ADJ",
86 "TRISTRIP_ADJ",
87 "TRISTRIP_REVERSE",
88 "POLYGON",
89 "RECTLIST",
90 "LINELOOP",
91 "POINTLIST_BF",
92 "LINESTRIP_CONT",
93 "LINESTRIP_BF",
94 "LINESTRIP_CONT_BF",
95 "TRIFAN_NOSTIPPLE",
96 };
97
98 static void do_3d_prim( struct aub_state *s,
99 const void *data,
100 int len )
101 {
102 struct brw_3d_primitive prim;
103 const struct brw_3d_primitive *orig = data;
104 int i;
105
106 assert(len == sizeof(prim));
107 memcpy(&prim, data, sizeof(prim));
108
109 #define START 0
110 #define BLOCK (12*28)
111
112 if (orig->verts_per_instance < BLOCK)
113 flush_cmds(s, &prim, sizeof(prim));
114 else {
115 for (i = START; i + BLOCK < orig->verts_per_instance; i += BLOCK/2) {
116 prim.start_vert_location = i;
117 prim.verts_per_instance = BLOCK;
118 _mesa_printf("%sprim %d/%s verts %d..%d (of %d)\n",
119 prim.header.indexed ? "INDEXED " : "",
120 prim.header.topology, pstrings[prim.header.topology%16],
121 prim.start_vert_location,
122 prim.start_vert_location + prim.verts_per_instance,
123 orig->verts_per_instance);
124 flush_cmds(s, &prim, sizeof(prim));
125 }
126 }
127 }
128
129
130
131 static struct {
132 int cmd;
133 const char *name;
134 int has_length;
135 } cmd_info[] = {
136 { 0, "NOOP", 0 },
137 { 0x5410, "XY_COLOR_BLT_RGB", 1 },
138 { 0x5430, "XY_COLOR_BLT_RGBA", 1 },
139 { 0x54d0, "XY_SRC_COPY_BLT_RGB", 1 },
140 { 0x54f0, "XY_SRC_COPY_BLT_RGBA", 1 },
141 { CMD_URB_FENCE, "URB_FENCE", 1 },
142 { CMD_CONST_BUFFER_STATE, "CONST_BUFFER_STATE", 1 },
143 { CMD_CONST_BUFFER, "CONST_BUFFER", 1 },
144 { CMD_STATE_BASE_ADDRESS, "STATE_BASE_ADDRESS", 1 },
145 { CMD_STATE_INSN_POINTER, "STATE_INSN_POINTER", 1 },
146 { CMD_PIPELINE_SELECT, "PIPELINE_SELECT", 0, },
147 { CMD_PIPELINED_STATE_POINTERS, "PIPELINED_STATE_POINTERS", 1 },
148 { CMD_BINDING_TABLE_PTRS, "BINDING_TABLE_PTRS", 1 },
149 { CMD_VERTEX_BUFFER, "VERTEX_BUFFER", 1 },
150 { CMD_VERTEX_ELEMENT, "VERTEX_ELEMENT", 1 },
151 { CMD_INDEX_BUFFER, "INDEX_BUFFER", 1 },
152 { CMD_VF_STATISTICS, "VF_STATISTICS", 0 },
153 { CMD_DRAW_RECT, "DRAW_RECT", 1 },
154 { CMD_BLEND_CONSTANT_COLOR, "BLEND_CONSTANT_COLOR", 1 },
155 { CMD_CHROMA_KEY, "CHROMA_KEY", 1 },
156 { CMD_DEPTH_BUFFER, "DEPTH_BUFFER", 1 },
157 { CMD_POLY_STIPPLE_OFFSET, "POLY_STIPPLE_OFFSET", 1 },
158 { CMD_POLY_STIPPLE_PATTERN, "POLY_STIPPLE_PATTERN", 1 },
159 { CMD_LINE_STIPPLE_PATTERN, "LINE_STIPPLE_PATTERN", 1 },
160 { CMD_GLOBAL_DEPTH_OFFSET_CLAMP, "GLOBAL_DEPTH_OFFSET_CLAMP", 1 },
161 { CMD_PIPE_CONTROL, "PIPE_CONTROL", 1 },
162 { CMD_MI_FLUSH, "MI_FLUSH", 0 },
163 { CMD_3D_PRIM, "3D_PRIM", 1 },
164 };
165
166 #define NR_CMDS (sizeof(cmd_info)/sizeof(cmd_info[0]))
167
168
169 static int find_command( unsigned int cmd )
170 {
171 int i;
172
173 for (i = 0; i < NR_CMDS; i++)
174 if (cmd == cmd_info[i].cmd)
175 return i;
176
177 return -1;
178 }
179
180
181
182 static int parse_commands( struct aub_state *s,
183 const unsigned int *data,
184 int len )
185 {
186 while (len) {
187 int cmd = data[0] >> 16;
188 int dwords;
189 int i;
190
191 i = find_command(cmd);
192
193 if (i < 0) {
194 _mesa_printf("couldn't find info for cmd %x\n", cmd);
195 return 1;
196 }
197
198 if (cmd_info[i].has_length)
199 dwords = (data[0] & 0xff) + 2;
200 else
201 dwords = 1;
202
203 _mesa_printf("%s (%d dwords) 0x%x\n", cmd_info[i].name, dwords, data[0]);
204
205 if (len < dwords * 4) {
206 _mesa_printf("EOF in %s (%d bytes)\n", __FUNCTION__, len);
207 return 1;
208 }
209
210
211 if (0 && cmd == CMD_3D_PRIM)
212 do_3d_prim(s, data, dwords * 4);
213 else
214 flush_cmds(s, data, dwords * 4);
215
216 data += dwords;
217 len -= dwords * 4;
218 }
219
220 return 0;
221 }
222
223
224
225 static void parse_data_write( struct aub_state *s,
226 const struct aub_block_header *bh,
227 void *dest,
228 const unsigned int *data,
229 int len )
230 {
231 switch (bh->type) {
232 case DW_GENERAL_STATE:
233 switch (bh->general_state_type) {
234 case DWGS_VERTEX_SHADER_STATE: {
235 struct brw_vs_unit_state vs;
236 assert(len == sizeof(vs));
237
238 _mesa_printf("DWGS_VERTEX_SHADER_STATE\n");
239 memcpy(&vs, data, sizeof(vs));
240
241 /* vs.vs6.vert_cache_disable = 1; */
242 /* vs.thread4.max_threads = 4; */
243
244 memcpy(dest, &vs, sizeof(vs));
245 return;
246 }
247 case DWGS_CLIPPER_STATE: {
248 struct brw_clip_unit_state clip;
249 assert(len == sizeof(clip));
250
251 _mesa_printf("DWGS_CLIPPER_STATE\n");
252 memcpy(&clip, data, sizeof(clip));
253
254 /* clip.thread4.max_threads = 0; */
255 /* clip.clip5.clip_mode = BRW_CLIPMODE_REJECT_ALL; */
256
257 memcpy(dest, &clip, sizeof(clip));
258 return;
259 }
260
261 case DWGS_NOTYPE:
262 case DWGS_GEOMETRY_SHADER_STATE:
263 case DWGS_STRIPS_FANS_STATE:
264 break;
265
266 case DWGS_WINDOWER_IZ_STATE: {
267 struct brw_wm_unit_state wm;
268 assert(len == sizeof(wm));
269
270 _mesa_printf("DWGS_WINDOWER_IZ_STATE\n");
271 memcpy(&wm, data, sizeof(wm));
272
273 /* wm.wm5.max_threads = 10; */
274
275 memcpy(dest, &wm, sizeof(wm));
276 return;
277 }
278
279 case DWGS_COLOR_CALC_STATE:
280 case DWGS_CLIPPER_VIEWPORT_STATE:
281 case DWGS_STRIPS_FANS_VIEWPORT_STATE:
282 case DWGS_COLOR_CALC_VIEWPORT_STATE:
283 case DWGS_SAMPLER_STATE:
284 case DWGS_KERNEL_INSTRUCTIONS:
285 case DWGS_SCRATCH_SPACE:
286 case DWGS_SAMPLER_DEFAULT_COLOR:
287 case DWGS_INTERFACE_DESCRIPTOR:
288 case DWGS_VLD_STATE:
289 case DWGS_VFE_STATE:
290 default:
291 break;
292 }
293 break;
294 case DW_SURFACE_STATE:
295 break;
296 case DW_1D_MAP:
297 case DW_2D_MAP:
298 case DW_CUBE_MAP:
299 case DW_VOLUME_MAP:
300 case DW_CONSTANT_BUFFER:
301 case DW_CONSTANT_URB_ENTRY:
302 case DW_VERTEX_BUFFER:
303 case DW_INDEX_BUFFER:
304 default:
305 break;
306 }
307
308 memcpy(dest, data, len);
309 }
310
311
312 /* In order to work, the memory layout has to be the same as the X
313 * server which created the aubfile.
314 */
315 static int parse_block_header( struct aub_state *s )
316 {
317 struct aub_block_header *bh = (struct aub_block_header *)(s->map + s->csr);
318 void *data = (void *)(bh + 1);
319 unsigned int len = (bh->length + 3) & ~3;
320
321 _mesa_printf("block header at 0x%x\n", s->csr);
322
323 if (s->csr + len + sizeof(*bh) > s->sz) {
324 _mesa_printf("EOF in data in %s\n", __FUNCTION__);
325 return 1;
326 }
327
328 if (bh->address_space == ADDR_GTT) {
329
330 switch (bh->operation)
331 {
332 case BH_DATA_WRITE: {
333 void *dest = bmFindVirtual( s->intel, bh->address, len );
334 if (dest == NULL) {
335 _mesa_printf("Couldn't find virtual address for offset %x\n", bh->address);
336 return 1;
337 }
338
339 #if 1
340 parse_data_write(s, bh, dest, data, len);
341 #else
342 memcpy(dest, data, len);
343 #endif
344 break;
345 }
346 case BH_COMMAND_WRITE:
347 #if 0
348 intel_cmd_ioctl(s->intel, (void *)data, len, GL_TRUE);
349 #else
350 if (parse_commands(s, data, len) != 0)
351 _mesa_printf("parse_commands failed\n");
352 #endif
353 break;
354 default:
355 break;
356 }
357 }
358
359 s->csr += sizeof(*bh) + len;
360 return 0;
361 }
362
363
364 #define AUB_FILE_HEADER 0xe085000b
365 #define AUB_BLOCK_HEADER 0xe0c10003
366 #define AUB_DUMP_BMP 0xe09e0004
367
368 int brw_playback_aubfile(struct brw_context *brw,
369 const char *filename)
370 {
371 struct intel_context *intel = &brw->intel;
372 struct aub_state state;
373 struct stat sb;
374 int fd;
375 int retval = 0;
376
377 state.intel = intel;
378
379 fd = open(filename, O_RDONLY, 0);
380 if (fd < 0) {
381 _mesa_printf("couldn't open aubfile: %s\n", filename);
382 return 1;
383 }
384
385 if (fstat(fd, &sb) != 0) {
386 _mesa_printf("couldn't open %s\n", filename);
387 return 1;
388 }
389
390 state.csr = 0;
391 state.sz = sb.st_size;
392 state.map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
393
394 if (state.map == NULL) {
395 _mesa_printf("couldn't mmap %s\n", filename);
396 return 1;
397 }
398
399 LOCK_HARDWARE(intel);
400 {
401 /* Make sure we don't confuse anything that might happen to be
402 * going on with the hardware:
403 */
404 /* bmEvictAll(intel); */
405 /* intel->vtbl.lost_hardware(intel); */
406
407
408 /* Replay the aubfile item by item:
409 */
410 while (retval == 0 &&
411 state.csr != state.sz) {
412 unsigned int insn = *(unsigned int *)(state.map + state.csr);
413
414 switch (insn) {
415 case AUB_FILE_HEADER:
416 retval = gobble(&state, sizeof(struct aub_file_header));
417 break;
418
419 case AUB_BLOCK_HEADER:
420 retval = parse_block_header(&state);
421 break;
422
423 case AUB_DUMP_BMP:
424 retval = gobble(&state, sizeof(struct aub_dump_bmp));
425 break;
426
427 default:
428 _mesa_printf("unknown instruction %x\n", insn);
429 retval = 1;
430 break;
431 }
432 }
433 }
434 UNLOCK_HARDWARE(intel);
435 return retval;
436 }
437
438
439
440
441
442
443