OSDN Git Service

i965_drv_video: add support for H264 on Clarkdale/Arrandale
[android-x86/hardware-intel-common-libva.git] / i965_drv_video / intel_batchbuffer_dump.c
1 #include <stdio.h>
2 #include <stdarg.h>
3 #include <string.h>
4 #include <inttypes.h>
5
6 #include "intel_driver.h"
7 #include "intel_batchbuffer_dump.h"
8
9 #define BUFFER_FAIL(_count, _len, _name) do {                   \
10     fprintf(gout, "Buffer size too small in %s (%d < %d)\n",    \
11             (_name), (_count), (_len));                         \
12     (*failures)++;                                              \
13     return count;                                               \
14 } while (0)
15
16 static FILE *gout;
17
18 static void
19 instr_out(unsigned int *data, unsigned int offset, unsigned int index, char *fmt, ...)
20 {
21     va_list va;
22
23     fprintf(gout, "0x%08x: 0x%08x:%s ", offset + index * 4, data[index],
24             index == 0 ? "" : "  ");
25     va_start(va, fmt);
26     vfprintf(gout, fmt, va);
27     va_end(va);
28 }
29
30
31 static int
32 dump_mi(unsigned int *data, unsigned int offset, int count, unsigned int device, int *failures)
33 {
34     unsigned int opcode;
35     int length, i;
36
37     struct {
38         unsigned int opcode;
39         int mask_length;
40         int min_len;
41         int max_len;
42         char *name;
43     } mi_commands[] = {
44         { 0x00, 0, 1, 1, "MI_NOOP" },
45         { 0x04, 0, 1, 1, "MI_FLUSH" },
46         { 0x0a, 0, 1, 1, "MI_BATCH_BUFFER_END" },
47     };
48
49     opcode = ((data[0] & MASK_MI_OPCODE) >> SHIFT_MI_OPCODE);
50
51     for (i = 0; i < sizeof(mi_commands) / sizeof(mi_commands[0]); i++) {
52         if (opcode == mi_commands[i].opcode) {
53             int index;
54
55             length = 1;
56             instr_out(data, offset, 0, "%s\n", mi_commands[i].name);
57
58             if (mi_commands[i].max_len > 1) {
59                 length = (data[0] & mi_commands[i].mask_length) + 2;
60
61                 if (length < mi_commands[i].min_len ||
62                     length > mi_commands[i].max_len) {
63                     fprintf(gout, "Bad length (%d) in %s, [%d, %d]\n",
64                             length, mi_commands[i].name,
65                             mi_commands[i].min_len,
66                             mi_commands[i].max_len);
67                 }
68             }
69
70             for (index = 1; index < length; index++) {
71                 if (index >= count)
72                     BUFFER_FAIL(count, length, mi_commands[i].name);
73
74                 instr_out(data, offset, index, "dword %d\n", index);
75             }
76
77             return length;
78         }
79     }
80
81     instr_out(data, offset, 0, "UNKNOWN MI COMMAND\n");
82     (*failures)++;
83     return 1;
84 }
85
86 static int
87 dump_gfxpipe_3d(unsigned int *data, unsigned int offset, int count, unsigned int device, int *failures)
88 {
89     instr_out(data, offset, 0, "UNKNOWN 3D COMMAND\n");
90     (*failures)++;
91
92     return 1;
93 }
94
95 static void
96 dump_avc_bsd_img_state(unsigned int *data, unsigned int offset, unsigned int device, int *failures)
97 {
98     int img_struct = ((data[3] >> 8) & 0x3);
99
100     instr_out(data, offset, 1, "frame size: %d\n", (data[1] & 0xffff));
101     instr_out(data, offset, 2, "width: %d, height: %d\n", (data[2] & 0xff), (data[2] >> 16) & 0xff);
102     instr_out(data, offset, 3, 
103               "second_chroma_qp_offset: %d,"
104               "chroma_qp_offset: %d,"
105               "QM present flag: %d," 
106               "image struct: %s,"
107               "img_dec_fs_idc: %d,"
108               "\n",
109               (data[3] >> 24) & 0x1f,
110               (data[3] >> 16) & 0x1f,
111               (data[3] >> 10) & 0x1,
112               (img_struct == 0) ? "frame" : (img_struct == 2) ? "invalid" : (img_struct == 1) ? "top field" : "bottom field",
113               data[3] & 0xff);
114     instr_out(data, offset, 4,
115               "residual off: 0x%x,"
116               "16MV: %d,"
117               "chroma fmt: %d,"
118               "CABAC: %d,"
119               "non-ref: %d,"
120               "constrained intra: %d,"
121               "direct8x8: %d,"
122               "trans8x8: %d,"
123               "MB only: %d,"
124               "MBAFF: %d,"
125               "\n",
126               (data[4] >> 24) & 0xff,
127               (data[4] >> 12) & 0x1,
128               (data[4] >> 10) & 0x3,
129               (data[4] >> 7) & 0x1,
130               (data[4] >> 6) & 0x1,
131               (data[4] >> 5) & 0x1,
132               (data[4] >> 4) & 0x1,
133               (data[4] >> 3) & 0x1,
134               (data[4] >> 2) & 0x1,
135               (data[4] >> 1) & 0x1);
136     instr_out(data, offset, 5, "AVC-IT Command Header\n");
137 }
138
139 static void
140 dump_avc_bsd_qm_state(unsigned int *data, unsigned int offset, unsigned int device, int *failures)
141 {
142     unsigned int length = ((data[0] & MASK_GFXPIPE_LENGTH) >> SHIFT_GFXPIPE_LENGTH) + 2;
143     int i;
144
145     instr_out(data, offset, 1, "user default: %02x, QM list present: %02x\n", 
146               (data[1] >> 8) & 0xff, data[1] & 0xff);
147
148     for (i = 2; i < length; i++) {
149         instr_out(data, offset, i, "dword %d\n", i);
150     }
151 }
152
153 static void
154 dump_avc_bsd_slice_state(unsigned int *data, unsigned int offset, unsigned int device, int *failures)
155 {
156
157 }
158
159 static void
160 dump_avc_bsd_buf_base_state(unsigned int *data, unsigned int offset, unsigned int device, int *failures)
161 {
162     int i;
163
164     instr_out(data, offset, 1, "BSD row store base address\n");
165     instr_out(data, offset, 2, "MPR row store base address\n");
166     instr_out(data, offset, 3, "AVC-IT command buffer base address\n");
167     instr_out(data, offset, 4, "AVC-IT data buffer: 0x%08x, write offset: 0x%x\n", 
168               data[4] & 0xFFFFF000, data[4] & 0xFC0);
169     instr_out(data, offset, 5, "ILDB data buffer\n");
170
171     for (i = 6; i < 38; i++) {
172         instr_out(data, offset, i, "Direct MV read base address for reference frame %d\n", i - 6);
173     }
174
175     instr_out(data, offset, 38, "direct mv wr0 top\n");
176     instr_out(data, offset, 39, "direct mv wr0 bottom\n");
177
178     for (i = 40; i < 74; i++) {
179         instr_out(data, offset, i, "POC List %d\n", i - 40);
180     }
181 }
182
183 static void
184 dump_bsd_ind_obj_base_addr(unsigned int *data, unsigned int offset, unsigned int device, int *failures)
185 {
186     instr_out(data, offset, 1, "AVC indirect object base address\n");
187     instr_out(data, offset, 2, "AVC Indirect Object Access Upper Bound\n");
188 }
189
190 static void 
191 dump_ironlake_avc_bsd_object(unsigned int *data, unsigned int offset, int *failures)
192 {
193     int slice_type = data[3] & 0xf;
194     int i, is_phantom = ((data[1] & 0x3fffff) == 0);
195
196     if (!is_phantom) {
197         instr_out(data, offset, 1, "Encrypted: %d, bitsteam length: %d\n", data[1] >> 31, data[1] & 0x3fffff);
198         instr_out(data, offset, 2, "Indirect Data Start Address: %d\n", data[2] & 0x1fffffff);
199         instr_out(data, offset, 3, "%s Slice\n", slice_type == 0 ? "P" : slice_type == 1 ? "B" : "I");
200         instr_out(data, offset, 4, 
201                   "Num_Ref_Idx_L1: %d,"
202                   "Num_Ref_Idx_L0: %d,"
203                   "Log2WeightDenomChroma: %d,"
204                   "Log2WeightDenomLuma: %d"
205                   "\n",
206                   (data[4] >> 24) & 0x3f,
207                   (data[4] >> 16) & 0x3f,
208                   (data[4] >> 8) & 0x3,
209                   (data[4] >> 0) & 0x3);
210         instr_out(data, offset, 5,
211                   "WeightedPredIdc: %d,"
212                   "DirectPredType: %d,"
213                   "DisableDeblockingFilter: %d,"
214                   "CabacInitIdc: %d,"
215                   "SliceQp: %d,"
216                   "SliceBetaOffsetDiv2: %d,"
217                   "SliceAlphaC0OffsetDiv2: %d"
218                   "\n",
219                   (data[5] >> 30) & 0x3,
220                   (data[5] >> 29) & 0x1,
221                   (data[5] >> 27) & 0x3,
222                   (data[5] >> 24) & 0x3,
223                   (data[5] >> 16) & 0x3f,
224                   (data[5] >> 8) & 0xf,
225                   (data[5] >> 0) & 0xf);
226         instr_out(data, offset, 6,
227                   "Slice_MB_Start_Vert_Pos: %d,"
228                   "Slice_MB_Start_Hor_Pos: %d,"
229                   "Slice_Start_Mb_Num: %d"
230                   "\n",
231                   (data[6] >> 24) & 0xff,
232                   (data[6] >> 16) & 0xff,
233                   (data[6] >> 0) & 0x7fff);
234         instr_out(data, offset, 7,
235                   "Fix_Prev_Mb_Skipped: %d,"
236                   "First_MB_Bit_Offset: %d"
237                   "\n",
238                   (data[7] >> 7) & 0x1,
239                   (data[7] >> 0) & 0x7);
240
241         for (i = 8; i < 16; i++)
242             instr_out(data, offset, i, "dword %d\n", i);
243     } else {
244         instr_out(data, offset, 1, "phantom slice\n");
245
246         for (i = 2; i < 6; i++)
247             instr_out(data, offset, i, "dword %d\n", i);
248
249         instr_out(data, offset, 6,
250                   "Slice_Start_Mb_Num: %d"
251                   "\n",
252                   (data[6] >> 0) & 0x7fff);
253
254         for (i = 7; i < 16; i++)
255             instr_out(data, offset, i, "dword %d\n", i);
256
257     }
258 }
259
260 static void 
261 dump_g4x_avc_bsd_object(unsigned int *data, unsigned int offset, int *failures)
262 {
263
264 }
265
266 static void 
267 dump_avc_bsd_object(unsigned int *data, unsigned int offset, unsigned int device, int *failures)
268 {
269     if (IS_IRONLAKE(device))
270         dump_ironlake_avc_bsd_object(data, offset, failures);
271     else
272         dump_g4x_avc_bsd_object(data, offset, failures);
273 }
274
275 static int
276 dump_bsd_avc(unsigned int *data, unsigned int offset, int count, unsigned int device, int *failures)
277 {
278     unsigned int subopcode;
279     int length, i;
280
281     struct {
282         unsigned int subopcode;
283         int min_len;
284         int max_len;
285         char *name;
286         void (*detail)(unsigned int *data, unsigned int offset, unsigned int device, int  *failures);
287     } avc_commands[] = {
288         { 0x00, 0x06, 0x06, "AVC_BSD_IMG_STATE", dump_avc_bsd_img_state },
289         { 0x01, 0x02, 0x3a, "AVC_BSD_QM_STATE", dump_avc_bsd_qm_state },
290         { 0x02, 0x02, 0xd2, "AVC_BSD_SLICE_STATE", NULL },
291         { 0x03, 0x4a, 0x4a, "AVC_BSD_BUF_BASE_STATE", dump_avc_bsd_buf_base_state },
292         { 0x04, 0x03, 0x03, "BSD_IND_OBJ_BASE_ADDR", dump_bsd_ind_obj_base_addr },
293         { 0x08, 0x08, 0x10, "AVC_BSD_OBJECT", dump_avc_bsd_object },
294     };
295
296     subopcode = ((data[0] & MASK_GFXPIPE_SUBOPCODE) >> SHIFT_GFXPIPE_SUBOPCODE);
297
298     for (i = 0; i < sizeof(avc_commands) / sizeof(avc_commands[0]); i++) {
299         if (subopcode == avc_commands[i].subopcode) {
300             unsigned int index;
301
302             length = (data[0] & MASK_GFXPIPE_LENGTH) >> SHIFT_GFXPIPE_LENGTH;
303             length += 2;
304             instr_out(data, offset, 0, "%s\n", avc_commands[i].name);
305
306             if (length < avc_commands[i].min_len || 
307                 length > avc_commands[i].max_len) {
308                 fprintf(gout, "Bad length(%d) in %s [%d, %d]\n", 
309                         length, avc_commands[i].name,
310                         avc_commands[i].min_len,
311                         avc_commands[i].max_len);
312             }
313
314             if (length - 1 >= count)
315                 BUFFER_FAIL(count, length, avc_commands[i].name);
316
317             if (avc_commands[i].detail)
318                 avc_commands[i].detail(data, offset, device, failures);
319             else {
320                 for (index = 1; index < length; index++)
321                     instr_out(data, offset, index, "dword %d\n", index);
322             }
323
324             return length;
325         }
326     }
327
328     instr_out(data, offset, 0, "UNKNOWN AVC COMMAND\n");
329     (*failures)++;
330     return 1;
331 }
332
333 static int
334 dump_gfxpipe_bsd(unsigned int *data, unsigned int offset, int count, unsigned int device, int *failures)
335 {
336     int length;
337
338     switch ((data[0] & MASK_GFXPIPE_OPCODE) >> SHIFT_GFXPIPE_OPCODE) {
339     case OPCODE_BSD_AVC:
340         length = dump_bsd_avc(data, offset, count, device, failures);
341         break;
342
343     default:
344         length = 1;
345         (*failures)++;
346         instr_out(data, offset, 0, "UNKNOWN BSD OPCODE\n");
347         break;
348     }
349
350     return length;
351 }
352
353 static int
354 dump_gfxpipe(unsigned int *data, unsigned int offset, int count, unsigned int device, int *failures)
355 {
356     int length;
357
358     switch ((data[0] & MASK_GFXPIPE_SUBTYPE) >> SHIFT_GFXPIPE_SUBTYPE) {
359     case GFXPIPE_3D:
360         length = dump_gfxpipe_3d(data, offset, count, device, failures);
361         break;
362
363     case GFXPIPE_BSD:
364         length = dump_gfxpipe_bsd(data, offset, count, device, failures);
365         break;
366
367     default:
368         length = 1;
369         (*failures)++;
370         instr_out(data, offset, 0, "UNKNOWN GFXPIPE COMMAND\n");
371         break;
372     }
373
374     return length;
375 }
376
377 int intel_batchbuffer_dump(unsigned int *data, unsigned int offset, int count, unsigned int device)
378 {
379     int index = 0;
380     int failures = 0;
381
382     gout = fopen("/tmp/bsd_command_dump.txt", "w+");
383
384     while (index < count) {
385         switch ((data[index] & MASK_CMD_TYPE) >> SHIFT_CMD_TYPE) {
386         case CMD_TYPE_MI:
387             index += dump_mi(data + index, offset + index * 4,
388                              count - index, device, &failures);
389             break;
390
391         case CMD_TYPE_GFXPIPE:
392             index += dump_gfxpipe(data + index, offset + index * 4,
393                                   count - index, device, &failures);
394             break;
395
396         default:
397             instr_out(data, offset, index, "UNKNOWN COMMAND\n");
398             failures++;
399             index++;
400             break;
401         }
402
403         fflush(gout);
404     }
405
406     fclose(gout);
407
408     return failures;
409 }