Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4245 Serge 1
/*
2
 * Copyright © 2007-2011 Intel Corporation
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining a
5
 * copy of this software and associated documentation files (the "Software"),
6
 * to deal in the Software without restriction, including without limitation
7
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
 * and/or sell copies of the Software, and to permit persons to whom the
9
 * Software is furnished to do so, subject to the following conditions:
10
 *
11
 * The above copyright notice and this permission notice (including the next
12
 * paragraph) shall be included in all copies or substantial portions of the
13
 * Software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
 * SOFTWARE.
22
 *
23
 * Authors:
24
 *    Eric Anholt 
25
 *
26
 */
27
 
28
#ifdef HAVE_CONFIG_H
29
#include "config.h"
30
#endif
31
 
32
//#include 
33
#include 
34
 
35
#include "sna.h"
36
#include "sna_reg.h"
37
 
38
#include "kgem_debug.h"
39
 
40
#include 
41
 
42
/*
43
void
44
ErrorF(const char *f, ...)
45
{
46
    va_list args;
47
 
48
    va_start(args, f);
49
    VErrorF(f, args);
50
    va_end(args);
51
}
52
*/
53
 
54
#define ErrorF printf
55
 
56
struct drm_i915_gem_relocation_entry *
57
kgem_debug_get_reloc_entry(struct kgem *kgem, uint32_t offset)
58
{
59
	int i;
60
 
61
	offset *= sizeof(uint32_t);
62
 
63
	for (i = 0; i < kgem->nreloc; i++)
64
		if (kgem->reloc[i].offset == offset)
65
			return kgem->reloc+i;
66
 
67
	assert(!"valid relocation entry, unknown batch offset");
68
	return NULL;
69
}
70
 
71
struct kgem_bo *
72
kgem_debug_get_bo_for_reloc_entry(struct kgem *kgem,
73
				  struct drm_i915_gem_relocation_entry *reloc)
74
{
75
	struct kgem_bo *bo;
76
 
77
	if (reloc == NULL)
78
		return NULL;
79
 
80
	list_for_each_entry(bo, &kgem->next_request->buffers, request)
81
		if (bo->target_handle == reloc->target_handle && bo->proxy == NULL)
82
			break;
83
 
84
	assert(&bo->request != &kgem->next_request->buffers);
85
 
86
	return bo;
87
}
88
 
89
static int kgem_debug_handle_is_fenced(struct kgem *kgem, uint32_t handle)
90
{
91
	int i;
92
 
93
	if (kgem->has_handle_lut)
94
		return kgem->exec[handle].flags & EXEC_OBJECT_NEEDS_FENCE;
95
 
96
	for (i = 0; i < kgem->nexec; i++)
97
		if (kgem->exec[i].handle == handle)
98
			return kgem->exec[i].flags & EXEC_OBJECT_NEEDS_FENCE;
99
 
100
	return 0;
101
}
102
 
103
static int kgem_debug_handle_tiling(struct kgem *kgem, uint32_t handle)
104
{
105
	struct kgem_bo *bo;
106
 
107
	list_for_each_entry(bo, &kgem->next_request->buffers, request)
108
		if (bo->target_handle == handle)
109
			return bo->tiling;
110
 
111
	return 0;
112
}
113
 
114
void
115
kgem_debug_print(const uint32_t *data,
116
		 uint32_t offset, unsigned int index,
117
		 const char *fmt, ...)
118
{
119
	va_list va;
120
	char buf[240];
121
	int len;
122
 
123
	len = snprintf(buf, sizeof(buf),
124
		       "0x%08x: 0x%08x: %s",
125
		       (offset + index) * 4,
126
		       data[index],
127
		       index == 0 ? "" : "   ");
128
 
129
	va_start(va, fmt);
130
	vsnprintf(buf + len, sizeof(buf) - len, fmt, va);
131
	va_end(va);
132
 
133
	ErrorF("%s", buf);
134
    delay(1);
135
}
136
 
137
static int
138
decode_nop(struct kgem *kgem, uint32_t offset)
139
{
140
	uint32_t *data = kgem->batch + offset;
141
	kgem_debug_print(data, offset, 0, "UNKNOWN\n");
142
	assert(0);
143
	return 1;
144
}
145
 
146
static int
147
decode_mi(struct kgem *kgem, uint32_t offset)
148
{
149
	static const struct {
150
		uint32_t opcode;
151
		int len_mask;
152
		int min_len;
153
		int max_len;
154
		const char *name;
155
	} opcodes[] = {
156
		{ 0x08, 0, 1, 1, "MI_ARB_ON_OFF" },
157
		{ 0x0a, 0, 1, 1, "MI_BATCH_BUFFER_END" },
158
		{ 0x30, 0x3f, 3, 3, "MI_BATCH_BUFFER" },
159
		{ 0x31, 0x3f, 2, 2, "MI_BATCH_BUFFER_START" },
160
		{ 0x14, 0x3f, 3, 3, "MI_DISPLAY_BUFFER_INFO" },
161
		{ 0x04, 0, 1, 1, "MI_FLUSH" },
162
		{ 0x22, 0x1f, 3, 3, "MI_LOAD_REGISTER_IMM" },
163
		{ 0x13, 0x3f, 2, 2, "MI_LOAD_SCAN_LINES_EXCL" },
164
		{ 0x12, 0x3f, 2, 2, "MI_LOAD_SCAN_LINES_INCL" },
165
		{ 0x00, 0, 1, 1, "MI_NOOP" },
166
		{ 0x11, 0x3f, 2, 2, "MI_OVERLAY_FLIP" },
167
		{ 0x07, 0, 1, 1, "MI_REPORT_HEAD" },
168
		{ 0x18, 0x3f, 2, 2, "MI_SET_CONTEXT" },
169
		{ 0x20, 0x3f, 3, 4, "MI_STORE_DATA_IMM" },
170
		{ 0x21, 0x3f, 3, 4, "MI_STORE_DATA_INDEX" },
171
		{ 0x24, 0x3f, 3, 3, "MI_STORE_REGISTER_MEM" },
172
		{ 0x02, 0, 1, 1, "MI_USER_INTERRUPT" },
173
		{ 0x03, 0, 1, 1, "MI_WAIT_FOR_EVENT" },
174
		{ 0x16, 0x7f, 3, 3, "MI_SEMAPHORE_MBOX" },
175
		{ 0x26, 0x1f, 3, 4, "MI_FLUSH_DW" },
176
		{ 0x0b, 0, 1, 1, "MI_SUSPEND_FLUSH" },
177
	};
178
	uint32_t *data = kgem->batch + offset;
179
	int op;
180
 
181
	for (op = 0; op < ARRAY_SIZE(opcodes); op++) {
182
		if ((data[0] & 0x1f800000) >> 23 == opcodes[op].opcode) {
183
			unsigned int len = 1, i;
184
 
185
			kgem_debug_print(data, offset, 0, "%s\n", opcodes[op].name);
186
			if (opcodes[op].max_len > 1) {
187
				len = (data[0] & opcodes[op].len_mask) + 2;
188
				if (len < opcodes[op].min_len ||
189
				    len > opcodes[op].max_len)
190
				{
191
					ErrorF("Bad length (%d) in %s, [%d, %d]\n",
192
					       len, opcodes[op].name,
193
					       opcodes[op].min_len,
194
					       opcodes[op].max_len);
195
					assert(0);
196
				}
197
			}
198
 
199
			for (i = 1; i < len; i++)
200
				kgem_debug_print(data, offset, i, "dword %d\n", i);
201
 
202
			return len;
203
		}
204
	}
205
 
206
	kgem_debug_print(data, offset, 0, "MI UNKNOWN\n");
207
	assert(0);
208
	return 1;
209
}
210
 
211
static int
212
decode_2d(struct kgem *kgem, uint32_t offset)
213
{
214
	static const struct {
215
		uint32_t opcode;
216
		int min_len;
217
		int max_len;
218
		const char *name;
219
	} opcodes[] = {
220
		{ 0x40, 5, 5, "COLOR_BLT" },
221
		{ 0x43, 6, 6, "SRC_COPY_BLT" },
222
		{ 0x01, 8, 8, "XY_SETUP_BLT" },
223
		{ 0x11, 9, 9, "XY_SETUP_MONO_PATTERN_SL_BLT" },
224
		{ 0x03, 3, 3, "XY_SETUP_CLIP_BLT" },
225
		{ 0x24, 2, 2, "XY_PIXEL_BLT" },
226
		{ 0x25, 3, 3, "XY_SCANLINES_BLT" },
227
		{ 0x26, 4, 4, "Y_TEXT_BLT" },
228
		{ 0x31, 5, 134, "XY_TEXT_IMMEDIATE_BLT" },
229
		{ 0x50, 6, 6, "XY_COLOR_BLT" },
230
		{ 0x51, 6, 6, "XY_PAT_BLT" },
231
		{ 0x76, 8, 8, "XY_PAT_CHROMA_BLT" },
232
		{ 0x72, 7, 135, "XY_PAT_BLT_IMMEDIATE" },
233
		{ 0x77, 9, 137, "XY_PAT_CHROMA_BLT_IMMEDIATE" },
234
		{ 0x52, 9, 9, "XY_MONO_PAT_BLT" },
235
		{ 0x59, 7, 7, "XY_MONO_PAT_FIXED_BLT" },
236
		{ 0x53, 8, 8, "XY_SRC_COPY_BLT" },
237
		{ 0x54, 8, 8, "XY_MONO_SRC_COPY_BLT" },
238
		{ 0x71, 9, 137, "XY_MONO_SRC_COPY_IMMEDIATE_BLT" },
239
		{ 0x55, 9, 9, "XY_FULL_BLT" },
240
		{ 0x55, 9, 137, "XY_FULL_IMMEDIATE_PATTERN_BLT" },
241
		{ 0x56, 9, 9, "XY_FULL_MONO_SRC_BLT" },
242
		{ 0x75, 10, 138, "XY_FULL_MONO_SRC_IMMEDIATE_PATTERN_BLT" },
243
		{ 0x57, 12, 12, "XY_FULL_MONO_PATTERN_BLT" },
244
		{ 0x58, 12, 12, "XY_FULL_MONO_PATTERN_MONO_SRC_BLT" },
245
	};
246
 
247
	unsigned int op, len;
248
	const char *format = NULL;
249
	uint32_t *data = kgem->batch + offset;
250
	struct drm_i915_gem_relocation_entry *reloc;
251
 
252
	/* Special case the two most common ops that we detail in full */
253
	switch ((data[0] & 0x1fc00000) >> 22) {
254
	case 0x50:
255
		kgem_debug_print(data, offset, 0,
256
			  "XY_COLOR_BLT (rgb %sabled, alpha %sabled, dst tile %d)\n",
257
			  (data[0] & (1 << 20)) ? "en" : "dis",
258
			  (data[0] & (1 << 21)) ? "en" : "dis",
259
			  (data[0] >> 11) & 1);
260
 
261
		len = (data[0] & 0x000000ff) + 2;
262
		assert(len == 6);
263
 
264
		switch ((data[1] >> 24) & 0x3) {
265
		case 0:
266
			format="8";
267
			break;
268
		case 1:
269
			format="565";
270
			break;
271
		case 2:
272
			format="1555";
273
			break;
274
		case 3:
275
			format="8888";
276
			break;
277
		}
278
 
279
		kgem_debug_print(data, offset, 1, "format %s, rop %x, pitch %d, "
280
			  "clipping %sabled\n", format,
281
			  (data[1] >> 16) & 0xff,
282
			  (short)(data[1] & 0xffff),
283
			  data[1] & (1 << 30) ? "en" : "dis");
284
		kgem_debug_print(data, offset, 2, "(%d,%d)\n",
285
			  data[2] & 0xffff, data[2] >> 16);
286
		kgem_debug_print(data, offset, 3, "(%d,%d)\n",
287
			  data[3] & 0xffff, data[3] >> 16);
288
		reloc = kgem_debug_get_reloc_entry(kgem, offset+4);
289
		kgem_debug_print(data, offset, 4, "dst offset 0x%08x [handle=%d, delta=%d, read=%x, write=%x (fenced? %d, tiling? %d)]\n",
290
				 data[4],
291
				 reloc->target_handle, reloc->delta,
292
				 reloc->read_domains, reloc->write_domain,
293
				 kgem_debug_handle_is_fenced(kgem, reloc->target_handle),
294
				 kgem_debug_handle_tiling(kgem, reloc->target_handle));
295
		kgem_debug_print(data, offset, 5, "color\n");
296
		assert(kgem->gen >= 040 ||
297
		       kgem_debug_handle_is_fenced(kgem, reloc->target_handle));
298
		return len;
299
 
300
	case 0x53:
301
		kgem_debug_print(data, offset, 0,
302
			  "XY_SRC_COPY_BLT (rgb %sabled, alpha %sabled, "
303
			  "src tile %d, dst tile %d)\n",
304
			  (data[0] & (1 << 20)) ? "en" : "dis",
305
			  (data[0] & (1 << 21)) ? "en" : "dis",
306
			  (data[0] >> 15) & 1,
307
			  (data[0] >> 11) & 1);
308
 
309
		len = (data[0] & 0x000000ff) + 2;
310
		assert(len == 8);
311
 
312
		switch ((data[1] >> 24) & 0x3) {
313
		case 0:
314
			format="8";
315
			break;
316
		case 1:
317
			format="565";
318
			break;
319
		case 2:
320
			format="1555";
321
			break;
322
		case 3:
323
			format="8888";
324
			break;
325
		}
326
 
327
		kgem_debug_print(data, offset, 1, "format %s, rop %x, dst pitch %d, "
328
				 "clipping %sabled\n", format,
329
				 (data[1] >> 16) & 0xff,
330
				 (short)(data[1] & 0xffff),
331
				 data[1] & (1 << 30) ? "en" : "dis");
332
		kgem_debug_print(data, offset, 2, "dst (%d,%d)\n",
333
				 data[2] & 0xffff, data[2] >> 16);
334
		kgem_debug_print(data, offset, 3, "dst (%d,%d)\n",
335
				 data[3] & 0xffff, data[3] >> 16);
336
		reloc = kgem_debug_get_reloc_entry(kgem, offset+4);
337
		assert(reloc);
338
		kgem_debug_print(data, offset, 4, "dst offset 0x%08x [handle=%d, delta=%d, read=%x, write=%x, (fenced? %d, tiling? %d)]\n",
339
				 data[4],
340
				 reloc->target_handle, reloc->delta,
341
				 reloc->read_domains, reloc->write_domain,
342
				 kgem_debug_handle_is_fenced(kgem, reloc->target_handle),
343
				 kgem_debug_handle_tiling(kgem, reloc->target_handle));
344
		assert(kgem->gen >= 040 ||
345
		       kgem_debug_handle_is_fenced(kgem, reloc->target_handle));
346
 
347
		kgem_debug_print(data, offset, 5, "src (%d,%d)\n",
348
				 data[5] & 0xffff, data[5] >> 16);
349
		kgem_debug_print(data, offset, 6, "src pitch %d\n",
350
				 (short)(data[6] & 0xffff));
351
		reloc = kgem_debug_get_reloc_entry(kgem, offset+7);
352
		assert(reloc);
353
		kgem_debug_print(data, offset, 7, "src offset 0x%08x [handle=%d, delta=%d, read=%x, write=%x (fenced? %d, tiling? %d)]\n",
354
				 data[7],
355
				 reloc->target_handle, reloc->delta,
356
				 reloc->read_domains, reloc->write_domain,
357
				 kgem_debug_handle_is_fenced(kgem, reloc->target_handle),
358
				 kgem_debug_handle_tiling(kgem, reloc->target_handle));
359
		assert(kgem->gen >= 040 ||
360
		       kgem_debug_handle_is_fenced(kgem, reloc->target_handle));
361
 
362
		return len;
363
	}
364
 
365
	for (op = 0; op < ARRAY_SIZE(opcodes); op++) {
366
		if ((data[0] & 0x1fc00000) >> 22 == opcodes[op].opcode) {
367
			unsigned int i;
368
 
369
			len = 1;
370
			kgem_debug_print(data, offset, 0, "%s\n", opcodes[op].name);
371
			if (opcodes[op].max_len > 1) {
372
				len = (data[0] & 0x000000ff) + 2;
373
				assert(len >= opcodes[op].min_len &&
374
				       len <= opcodes[op].max_len);
375
			}
376
 
377
			for (i = 1; i < len; i++)
378
				kgem_debug_print(data, offset, i, "dword %d\n", i);
379
 
380
			return len;
381
		}
382
	}
383
 
384
	kgem_debug_print(data, offset, 0, "2D UNKNOWN\n");
385
	assert(0);
386
	return 1;
387
}
388
 
389
static int (*decode_3d(int gen))(struct kgem*, uint32_t)
390
{
391
	return kgem_gen6_decode_3d;
392
/*
393
	if (gen >= 0100) {
394
	} else if (gen >= 070) {
395
		return kgem_gen7_decode_3d;
396
	} else if (gen >= 060) {
397
		return kgem_gen6_decode_3d;
398
	} else if (gen >= 050) {
399
		return kgem_gen5_decode_3d;
400
	} else if (gen >= 040) {
401
		return kgem_gen4_decode_3d;
402
	} else if (gen >= 030) {
403
		return kgem_gen3_decode_3d;
404
	} else if (gen >= 020) {
405
		return kgem_gen2_decode_3d;
406
	}
407
	assert(0);
408
*/
409
}
410
 
411
static void (*finish_state(int gen))(struct kgem*)
412
{
413
 
414
    return kgem_gen6_finish_state;
415
/*
416
	if (gen >= 0100) {
417
	} else if (gen >= 070) {
418
		return kgem_gen7_finish_state;
419
	} else if (gen >= 060) {
420
		return kgem_gen6_finish_state;
421
	} else if (gen >= 050) {
422
		return kgem_gen5_finish_state;
423
	} else if (gen >= 040) {
424
		return kgem_gen4_finish_state;
425
	} else if (gen >= 030) {
426
		return kgem_gen3_finish_state;
427
	} else if (gen >= 020) {
428
		return kgem_gen2_finish_state;
429
	}
430
	assert(0);
431
*/
432
}
433
 
434
void __kgem_batch_debug(struct kgem *kgem, uint32_t nbatch)
435
{
436
	int (*const decode[])(struct kgem *, uint32_t) = {
437
		decode_mi,
438
		decode_nop,
439
		decode_2d,
440
		decode_3d(kgem->gen),
441
	};
442
	uint32_t offset = 0;
443
 
444
	while (offset < nbatch) {
445
		int class = (kgem->batch[offset] & 0xe0000000) >> 29;
446
		assert(class < ARRAY_SIZE(decode));
447
		offset += decode[class](kgem, offset);
448
	}
449
 
450
	finish_state(kgem->gen)(kgem);
451
}