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 <eric@anholt.net>
25 *    Chris Wilson <chris@chris-wilson.co.uk>
26 *
27 */
28
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#include <sys/mman.h>
34#include <assert.h>
35
36#include "sna.h"
37
38#include "gen2_render.h"
39
40#include "kgem_debug.h"
41
42static struct state {
43	int vertex_format;
44} state;
45
46static inline float int_as_float(uint32_t dw)
47{
48	union {
49		float f;
50		uint32_t dw;
51	} u;
52	u.dw = dw;
53	return u.f;
54}
55
56static int
57decode_3d_primitive(struct kgem *kgem, uint32_t offset)
58{
59    uint32_t *data = kgem->batch + offset;
60    char immediate = (data[0] & (1 << 23)) == 0;
61    unsigned int len;
62    const char *primtype;
63
64    switch ((data[0] >> 18) & 0xf) {
65    case 0x0: primtype = "TRILIST"; break;
66    case 0x1: primtype = "TRISTRIP"; break;
67    case 0x2: primtype = "TRISTRIP_REVERSE"; break;
68    case 0x3: primtype = "TRIFAN"; break;
69    case 0x4: primtype = "POLYGON"; break;
70    case 0x5: primtype = "LINELIST"; break;
71    case 0x6: primtype = "LINESTRIP"; break;
72    case 0x7: primtype = "RECTLIST"; break;
73    case 0x8: primtype = "POINTLIST"; break;
74    case 0x9: primtype = "DIB"; break;
75    case 0xa: primtype = "CLEAR_RECT"; break;
76    default: primtype = "unknown"; break;
77    }
78
79    /* XXX: 3DPRIM_DIB not supported */
80    if (immediate) {
81	len = (data[0] & 0x0003ffff) + 2;
82	kgem_debug_print(data, offset, 0, "3DPRIMITIVE inline %s\n", primtype);
83#if 0
84	if (!saved_s2_set || !saved_s4_set) {
85	    fprintf(out, "unknown vertex format\n");
86	    for (i = 1; i < len; i++) {
87		kgem_debug_print(data, offset, i,
88			  "           vertex data (%f float)\n",
89			  int_as_float(data[i]));
90	    }
91	} else {
92	    unsigned int vertex = 0;
93	    for (i = 1; i < len;) {
94		unsigned int tc;
95
96#define VERTEX_OUT(fmt, ...) do {					\
97    if (i < len)							\
98	kgem_debug_print(data, offset, i, " V%d."fmt"\n", vertex, __VA_ARGS__); \
99    else								\
100	fprintf(out, " missing data in V%d\n", vertex);			\
101    i++;								\
102} while (0)
103
104		VERTEX_OUT("X = %f", int_as_float(data[i]));
105		VERTEX_OUT("Y = %f", int_as_float(data[i]));
106	        switch (saved_s4 >> 6 & 0x7) {
107		case 0x1:
108		    VERTEX_OUT("Z = %f", int_as_float(data[i]));
109		    break;
110		case 0x2:
111		    VERTEX_OUT("Z = %f", int_as_float(data[i]));
112		    VERTEX_OUT("W = %f", int_as_float(data[i]));
113		    break;
114		case 0x3:
115		    break;
116		case 0x4:
117		    VERTEX_OUT("W = %f", int_as_float(data[i]));
118		    break;
119		default:
120		    fprintf(out, "bad S4 position mask\n");
121		}
122
123		if (saved_s4 & (1 << 10)) {
124		    VERTEX_OUT("color = (A=0x%02x, R=0x%02x, G=0x%02x, "
125			       "B=0x%02x)",
126			       data[i] >> 24,
127			       (data[i] >> 16) & 0xff,
128			       (data[i] >> 8) & 0xff,
129			       data[i] & 0xff);
130		}
131		if (saved_s4 & (1 << 11)) {
132		    VERTEX_OUT("spec = (A=0x%02x, R=0x%02x, G=0x%02x, "
133			       "B=0x%02x)",
134			       data[i] >> 24,
135			       (data[i] >> 16) & 0xff,
136			       (data[i] >> 8) & 0xff,
137			       data[i] & 0xff);
138		}
139		if (saved_s4 & (1 << 12))
140		    VERTEX_OUT("width = 0x%08x)", data[i]);
141
142		for (tc = 0; tc <= 7; tc++) {
143		    switch ((saved_s2 >> (tc * 4)) & 0xf) {
144		    case 0x0:
145			VERTEX_OUT("T%d.X = %f", tc, int_as_float(data[i]));
146			VERTEX_OUT("T%d.Y = %f", tc, int_as_float(data[i]));
147			break;
148		    case 0x1:
149			VERTEX_OUT("T%d.X = %f", tc, int_as_float(data[i]));
150			VERTEX_OUT("T%d.Y = %f", tc, int_as_float(data[i]));
151			VERTEX_OUT("T%d.Z = %f", tc, int_as_float(data[i]));
152			break;
153		    case 0x2:
154			VERTEX_OUT("T%d.X = %f", tc, int_as_float(data[i]));
155			VERTEX_OUT("T%d.Y = %f", tc, int_as_float(data[i]));
156			VERTEX_OUT("T%d.Z = %f", tc, int_as_float(data[i]));
157			VERTEX_OUT("T%d.W = %f", tc, int_as_float(data[i]));
158			break;
159		    case 0x3:
160			VERTEX_OUT("T%d.X = %f", tc, int_as_float(data[i]));
161			break;
162		    case 0x4:
163			VERTEX_OUT("T%d.XY = 0x%08x half-float", tc, data[i]);
164			break;
165		    case 0x5:
166			VERTEX_OUT("T%d.XY = 0x%08x half-float", tc, data[i]);
167			VERTEX_OUT("T%d.ZW = 0x%08x half-float", tc, data[i]);
168			break;
169		    case 0xf:
170			break;
171		    default:
172			fprintf(out, "bad S2.T%d format\n", tc);
173		    }
174		}
175		vertex++;
176	    }
177	}
178#endif
179    } else {
180	/* indirect vertices */
181	len = data[0] & 0x0000ffff; /* index count */
182#if 0
183	if (data[0] & (1 << 17)) {
184	    /* random vertex access */
185	    kgem_debug_print(data, offset, 0,
186		      "3DPRIMITIVE random indirect %s (%d)\n", primtype, len);
187	    if (len == 0) {
188		/* vertex indices continue until 0xffff is found */
189		for (i = 1; i < count; i++) {
190		    if ((data[i] & 0xffff) == 0xffff) {
191			kgem_debug_print(data, offset, i,
192				  "    indices: (terminator)\n");
193			ret = i;
194			goto out;
195		    } else if ((data[i] >> 16) == 0xffff) {
196			kgem_debug_print(data, offset, i,
197				  "    indices: 0x%04x, (terminator)\n",
198				  data[i] & 0xffff);
199			ret = i;
200			goto out;
201		    } else {
202			kgem_debug_print(data, offset, i,
203				  "    indices: 0x%04x, 0x%04x\n",
204				  data[i] & 0xffff, data[i] >> 16);
205		    }
206		}
207		fprintf(out,
208			"3DPRIMITIVE: no terminator found in index buffer\n");
209		ret = count;
210		goto out;
211	    } else {
212		/* fixed size vertex index buffer */
213		for (j = 1, i = 0; i < len; i += 2, j++) {
214		    if (i * 2 == len - 1) {
215			kgem_debug_print(data, offset, j,
216				  "    indices: 0x%04x\n",
217				  data[j] & 0xffff);
218		    } else {
219			kgem_debug_print(data, offset, j,
220				  "    indices: 0x%04x, 0x%04x\n",
221				  data[j] & 0xffff, data[j] >> 16);
222		    }
223		}
224	    }
225	    ret = (len + 1) / 2 + 1;
226	    goto out;
227	} else {
228	    /* sequential vertex access */
229	    kgem_debug_print(data, offset, 0,
230		      "3DPRIMITIVE sequential indirect %s, %d starting from "
231		      "%d\n", primtype, len, data[1] & 0xffff);
232	    kgem_debug_print(data, offset, 1, "           start\n");
233	    ret = 2;
234	    goto out;
235	}
236#endif
237    }
238
239    return len;
240}
241
242static int
243decode_3d_1d(struct kgem *kgem, uint32_t offset)
244{
245    uint32_t *data = kgem->batch + offset;
246    unsigned int len, i, idx, word, map;
247    const char *format, *zformat, *type;
248    uint32_t opcode;
249
250    static const struct {
251	uint32_t opcode;
252	int min_len;
253	int max_len;
254	const char *name;
255    } opcodes_3d_1d[] = {
256	{ 0x86, 4, 4, "3DSTATE_CHROMA_KEY" },
257	{ 0x88, 2, 2, "3DSTATE_CONSTANT_BLEND_COLOR" },
258	{ 0x99, 2, 2, "3DSTATE_DEFAULT_DIFFUSE" },
259	{ 0x9a, 2, 2, "3DSTATE_DEFAULT_SPECULAR" },
260	{ 0x98, 2, 2, "3DSTATE_DEFAULT_Z" },
261	{ 0x97, 2, 2, "3DSTATE_DEPTH_OFFSET_SCALE" },
262	{ 0x9d, 65, 65, "3DSTATE_FILTER_COEFFICIENTS_4X4" },
263	{ 0x9e, 4, 4, "3DSTATE_MONO_FILTER" },
264	{ 0x89, 4, 4, "3DSTATE_FOG_MODE" },
265	{ 0x8f, 2, 16, "3DSTATE_MAP_PALLETE_LOAD_32" },
266	{ 0x83, 2, 2, "3DSTATE_SPAN_STIPPLE" },
267	{ 0x8c, 2, 2, "3DSTATE_MAP_COORD_TRANSFORM" },
268	{ 0x8b, 2, 2, "3DSTATE_MAP_VERTEX_TRANSFORM" },
269	{ 0x8d, 3, 3, "3DSTATE_W_STATE" },
270	{ 0x01, 2, 2, "3DSTATE_COLOR_FACTOR" },
271	{ 0x02, 2, 2, "3DSTATE_MAP_COORD_SETBIND" },
272    }, *opcode_3d_1d;
273
274    opcode = (data[0] & 0x00ff0000) >> 16;
275
276    switch (opcode) {
277    case 0x07:
278	/* This instruction is unusual.  A 0 length means just 1 DWORD instead of
279	 * 2.  The 0 length is specified in one place to be unsupported, but
280	 * stated to be required in another, and 0 length LOAD_INDIRECTs appear
281	 * to cause no harm at least.
282	 */
283	kgem_debug_print(data, offset, 0, "3DSTATE_LOAD_INDIRECT\n");
284	len = (data[0] & 0x000000ff) + 1;
285	i = 1;
286	if (data[0] & (0x01 << 8)) {
287	    kgem_debug_print(data, offset, i++, "SIS.0\n");
288	    kgem_debug_print(data, offset, i++, "SIS.1\n");
289	}
290	if (data[0] & (0x02 << 8)) {
291	    kgem_debug_print(data, offset, i++, "DIS.0\n");
292	}
293	if (data[0] & (0x04 << 8)) {
294	    kgem_debug_print(data, offset, i++, "SSB.0\n");
295	    kgem_debug_print(data, offset, i++, "SSB.1\n");
296	}
297	if (data[0] & (0x08 << 8)) {
298	    kgem_debug_print(data, offset, i++, "MSB.0\n");
299	    kgem_debug_print(data, offset, i++, "MSB.1\n");
300	}
301	if (data[0] & (0x10 << 8)) {
302	    kgem_debug_print(data, offset, i++, "PSP.0\n");
303	    kgem_debug_print(data, offset, i++, "PSP.1\n");
304	}
305	if (data[0] & (0x20 << 8)) {
306	    kgem_debug_print(data, offset, i++, "PSC.0\n");
307	    kgem_debug_print(data, offset, i++, "PSC.1\n");
308	}
309	assert(len == i);
310	return len;
311    case 0x04:
312	kgem_debug_print(data, offset, 0, "3DSTATE_LOAD_STATE_IMMEDIATE_1\n");
313	len = (data[0] & 0x0000000f) + 2;
314	i = 1;
315	for (word = 0; word <= 8; word++) {
316	    if (data[0] & (1 << (4 + word))) {
317		kgem_debug_print(data, offset, i, "S%d: 0x%08x\n", i, data[i]);
318		i++;
319	    }
320	}
321	assert (len ==i);
322	return len;
323    case 0x03:
324	kgem_debug_print(data, offset, 0, "3DSTATE_LOAD_STATE_IMMEDIATE_2\n");
325	len = (data[0] & 0x0000000f) + 2;
326	i = 1;
327	for (word = 6; word <= 14; word++) {
328	    if (data[0] & (1 << word)) {
329		if (word == 6)
330		    kgem_debug_print(data, offset, i++, "TBCF\n");
331		else if (word >= 7 && word <= 10) {
332		    kgem_debug_print(data, offset, i++, "TB%dC\n", word - 7);
333		    kgem_debug_print(data, offset, i++, "TB%dA\n", word - 7);
334		} else if (word >= 11 && word <= 14) {
335		    kgem_debug_print(data, offset, i, "TM%dS0: offset=0x%08x, %s\n",
336			      word - 11,
337			      data[i]&0xfffffffe,
338			      data[i]&1?"use fence":"");
339		    i++;
340		    kgem_debug_print(data, offset, i, "TM%dS1: height=%i, width=%i, %s\n",
341			      word - 11,
342			      data[i]>>21, (data[i]>>10)&0x3ff,
343			      data[i]&2?(data[i]&1?"y-tiled":"x-tiled"):"");
344		    i++;
345		    kgem_debug_print(data, offset, i, "TM%dS2: pitch=%i, \n",
346			      word - 11,
347			      ((data[i]>>21) + 1)*4);
348		    i++;
349		    kgem_debug_print(data, offset, i++, "TM%dS3\n", word - 11);
350		    kgem_debug_print(data, offset, i++, "TM%dS4: dflt color\n", word - 11);
351		}
352	    }
353	}
354	assert (len == i);
355	return len;
356    case 0x00:
357	kgem_debug_print(data, offset, 0, "3DSTATE_MAP_STATE\n");
358	len = (data[0] & 0x0000003f) + 2;
359	kgem_debug_print(data, offset, 1, "mask\n");
360
361	i = 2;
362	for (map = 0; map <= 15; map++) {
363	    if (data[1] & (1 << map)) {
364		int width, height, pitch, dword;
365		const char *tiling;
366
367		dword = data[i];
368		kgem_debug_print(data, offset, i++, "map %d MS2 %s%s%s\n", map,
369			  dword&(1<<31)?"untrusted surface, ":"",
370			  dword&(1<<1)?"vertical line stride enable, ":"",
371			  dword&(1<<0)?"vertical ofs enable, ":"");
372
373		dword = data[i];
374		width = ((dword >> 10) & ((1 << 11) - 1))+1;
375		height = ((dword >> 21) & ((1 << 11) - 1))+1;
376
377		tiling = "none";
378		if (dword & (1 << 2))
379			tiling = "fenced";
380		else if (dword & (1 << 1))
381			tiling = dword & (1 << 0) ? "Y" : "X";
382		type = " BAD";
383		format = "BAD";
384		switch ((dword>>7) & 0x7) {
385		case 1:
386		    type = "8b";
387		    switch ((dword>>3) & 0xf) {
388		    case 0: format = "I"; break;
389		    case 1: format = "L"; break;
390		    case 2: format = "A"; break;
391		    case 3: format = " mono"; break; }
392		    break;
393		case 2:
394		    type = "16b";
395		    switch ((dword>>3) & 0xf) {
396		    case 0: format = " rgb565"; break;
397		    case 1: format = " argb1555"; break;
398		    case 2: format = " argb4444"; break;
399		    case 5: format = " ay88"; break;
400		    case 6: format = " bump655"; break;
401		    case 7: format = "I"; break;
402		    case 8: format = "L"; break;
403		    case 9: format = "A"; break; }
404		    break;
405		case 3:
406		    type = "32b";
407		    switch ((dword>>3) & 0xf) {
408		    case 0: format = " argb8888"; break;
409		    case 1: format = " abgr8888"; break;
410		    case 2: format = " xrgb8888"; break;
411		    case 3: format = " xbgr8888"; break;
412		    case 4: format = " qwvu8888"; break;
413		    case 5: format = " axvu8888"; break;
414		    case 6: format = " lxvu8888"; break;
415		    case 7: format = " xlvu8888"; break;
416		    case 8: format = " argb2101010"; break;
417		    case 9: format = " abgr2101010"; break;
418		    case 10: format = " awvu2101010"; break;
419		    case 11: format = " gr1616"; break;
420		    case 12: format = " vu1616"; break;
421		    case 13: format = " xI824"; break;
422		    case 14: format = " xA824"; break;
423		    case 15: format = " xL824"; break; }
424		    break;
425		case 5:
426		    type = "422";
427		    switch ((dword>>3) & 0xf) {
428		    case 0: format = " yuv_swapy"; break;
429		    case 1: format = " yuv"; break;
430		    case 2: format = " yuv_swapuv"; break;
431		    case 3: format = " yuv_swapuvy"; break; }
432		    break;
433		case 6:
434		    type = "compressed";
435		    switch ((dword>>3) & 0x7) {
436		    case 0: format = " dxt1"; break;
437		    case 1: format = " dxt2_3"; break;
438		    case 2: format = " dxt4_5"; break;
439		    case 3: format = " fxt1"; break;
440		    case 4: format = " dxt1_rb"; break; }
441		    break;
442		case 7:
443		    type = "4b indexed";
444		    switch ((dword>>3) & 0xf) {
445		    case 7: format = " argb8888"; break; }
446		    break;
447		}
448		dword = data[i];
449		kgem_debug_print(data, offset, i++, "map %d MS3 [width=%d, height=%d, format=%s%s, tiling=%s%s]\n",
450			  map, width, height, type, format, tiling,
451			  dword&(1<<9)?" palette select":"");
452
453		dword = data[i];
454		pitch = 4*(((dword >> 21) & ((1 << 11) - 1))+1);
455		kgem_debug_print(data, offset, i++, "map %d MS4 [pitch=%d, max_lod=%i, vol_depth=%i, cube_face_ena=%x, %s]\n",
456			  map, pitch,
457			  (dword>>9)&0x3f, dword&0xff, (dword>>15)&0x3f,
458			  dword&(1<<8)?"miplayout legacy":"miplayout right");
459	    }
460	}
461	assert (len == i);
462	return len;
463    case 0x85:
464	len = (data[0] & 0x0000000f) + 2;
465	assert (len == 2);
466	kgem_debug_print(data, offset, 0,
467		  "3DSTATE_DEST_BUFFER_VARIABLES\n");
468
469	switch ((data[1] >> 8) & 0xf) {
470	case 0x0: format = "g8"; break;
471	case 0x1: format = "x1r5g5b5"; break;
472	case 0x2: format = "r5g6b5"; break;
473	case 0x3: format = "a8r8g8b8"; break;
474	case 0x4: format = "ycrcb_swapy"; break;
475	case 0x5: format = "ycrcb_normal"; break;
476	case 0x6: format = "ycrcb_swapuv"; break;
477	case 0x7: format = "ycrcb_swapuvy"; break;
478	case 0x8: format = "a4r4g4b4"; break;
479	case 0x9: format = "a1r5g5b5"; break;
480	case 0xa: format = "a2r10g10b10"; break;
481	default: format = "BAD"; break;
482	}
483	switch ((data[1] >> 2) & 0x3) {
484	case 0x0: zformat = "u16"; break;
485	case 0x1: zformat = "f16"; break;
486	case 0x2: zformat = "u24x8"; break;
487	default: zformat = "BAD"; break;
488	}
489	kgem_debug_print(data, offset, 1, "%s format, %s depth format, early Z %sabled\n",
490		  format, zformat,
491		  (data[1] & (1 << 31)) ? "en" : "dis");
492	return len;
493
494    case 0x8e:
495	{
496	    const char *name, *tiling;
497
498	    len = (data[0] & 0x0000000f) + 2;
499	    assert (len == 3);
500
501	    switch((data[1] >> 24) & 0x7) {
502	    case 0x3: name = "color"; break;
503	    case 0x7: name = "depth"; break;
504	    default: name = "unknown"; break;
505	    }
506
507	    tiling = "none";
508	    if (data[1] & (1 << 23))
509		tiling = "fenced";
510	    else if (data[1] & (1 << 22))
511		tiling = data[1] & (1 << 21) ? "Y" : "X";
512
513	    kgem_debug_print(data, offset, 0, "3DSTATE_BUFFER_INFO\n");
514	    kgem_debug_print(data, offset, 1, "%s, tiling = %s, pitch=%d\n", name, tiling, data[1]&0xffff);
515
516	    kgem_debug_print(data, offset, 2, "address\n");
517	    return len;
518	}
519
520    case 0x81:
521	len = (data[0] & 0x0000000f) + 2;
522	assert (len == 3);
523
524	kgem_debug_print(data, offset, 0,
525		  "3DSTATE_SCISSOR_RECTANGLE\n");
526	kgem_debug_print(data, offset, 1, "(%d,%d)\n",
527		  data[1] & 0xffff, data[1] >> 16);
528	kgem_debug_print(data, offset, 2, "(%d,%d)\n",
529		  data[2] & 0xffff, data[2] >> 16);
530	return len;
531
532    case 0x80:
533	len = (data[0] & 0x0000000f) + 2;
534	assert (len == 5);
535
536	kgem_debug_print(data, offset, 0,
537		  "3DSTATE_DRAWING_RECTANGLE\n");
538	kgem_debug_print(data, offset, 1, "%s\n",
539		  data[1]&(1<<30)?"depth ofs disabled ":"");
540	kgem_debug_print(data, offset, 2, "(%d,%d)\n",
541		  data[2] & 0xffff, data[2] >> 16);
542	kgem_debug_print(data, offset, 3, "(%d,%d)\n",
543		  data[3] & 0xffff, data[3] >> 16);
544	kgem_debug_print(data, offset, 4, "(%d,%d)\n",
545		  data[4] & 0xffff, data[4] >> 16);
546	return len;
547
548    case 0x9c:
549	len = (data[0] & 0x0000000f) + 2;
550	assert (len == 7);
551
552	kgem_debug_print(data, offset, 0,
553		  "3DSTATE_CLEAR_PARAMETERS\n");
554	kgem_debug_print(data, offset, 1, "prim_type=%s, clear=%s%s%s\n",
555		  data[1]&(1<<16)?"CLEAR_RECT":"ZONE_INIT",
556		  data[1]&(1<<2)?"color,":"",
557		  data[1]&(1<<1)?"depth,":"",
558		  data[1]&(1<<0)?"stencil,":"");
559	kgem_debug_print(data, offset, 2, "clear color\n");
560	kgem_debug_print(data, offset, 3, "clear depth/stencil\n");
561	kgem_debug_print(data, offset, 4, "color value (rgba8888)\n");
562	kgem_debug_print(data, offset, 5, "depth value %f\n",
563		  int_as_float(data[5]));
564	kgem_debug_print(data, offset, 6, "clear stencil\n");
565	return len;
566    }
567
568    for (idx = 0; idx < ARRAY_SIZE(opcodes_3d_1d); idx++) {
569	opcode_3d_1d = &opcodes_3d_1d[idx];
570	if (((data[0] & 0x00ff0000) >> 16) == opcode_3d_1d->opcode) {
571	    len = 1;
572
573	    kgem_debug_print(data, offset, 0, "%s\n", opcode_3d_1d->name);
574	    if (opcode_3d_1d->max_len > 1) {
575		len = (data[0] & 0x0000ffff) + 2;
576		assert (len >= opcode_3d_1d->min_len &&
577			len <= opcode_3d_1d->max_len);
578	    }
579
580	    for (i = 1; i < len; i++)
581		kgem_debug_print(data, offset, i, "dword %d\n", i);
582
583	    return len;
584	}
585    }
586
587    kgem_debug_print(data, offset, 0, "3D UNKNOWN: 3d_1d opcode = 0x%x\n", opcode);
588    return 1;
589}
590
591static int
592decode_3d_1c(struct kgem *kgem, uint32_t offset)
593{
594    uint32_t *data = kgem->batch + offset;
595    uint32_t opcode;
596
597    opcode = (data[0] & 0x00f80000) >> 19;
598
599    switch (opcode) {
600    case 0x11:
601	kgem_debug_print(data, offset, 0, "3DSTATE_DEPTH_SUBRECTANGLE_DISABLE\n");
602	return 1;
603    case 0x10:
604	kgem_debug_print(data, offset, 0, "3DSTATE_SCISSOR_ENABLE %s\n",
605		data[0]&1?"enabled":"disabled");
606	return 1;
607    case 0x01:
608	kgem_debug_print(data, offset, 0, "3DSTATE_MAP_COORD_SET_I830\n");
609	return 1;
610    case 0x0a:
611	kgem_debug_print(data, offset, 0, "3DSTATE_MAP_CUBE_I830\n");
612	return 1;
613    case 0x05:
614	kgem_debug_print(data, offset, 0, "3DSTATE_MAP_TEX_STREAM_I830\n");
615	return 1;
616    }
617
618    kgem_debug_print(data, offset, 0, "3D UNKNOWN: 3d_1c opcode = 0x%x\n",
619	      opcode);
620    return 1;
621}
622
623int kgem_gen2_decode_3d(struct kgem *kgem, uint32_t offset)
624{
625    const static struct {
626	uint32_t opcode;
627	int min_len;
628	int max_len;
629	const char *name;
630    } opcodes[] = {
631	{ 0x02, 1, 1, "3DSTATE_MODES_3" },
632	{ 0x03, 1, 1, "3DSTATE_ENABLES_1"},
633	{ 0x04, 1, 1, "3DSTATE_ENABLES_2"},
634	{ 0x05, 1, 1, "3DSTATE_VFT0"},
635	{ 0x06, 1, 1, "3DSTATE_AA"},
636	{ 0x07, 1, 1, "3DSTATE_RASTERIZATION_RULES" },
637	{ 0x08, 1, 1, "3DSTATE_MODES_1" },
638	{ 0x09, 1, 1, "3DSTATE_STENCIL_TEST" },
639	{ 0x0a, 1, 1, "3DSTATE_VFT1"},
640	{ 0x0b, 1, 1, "3DSTATE_INDPT_ALPHA_BLEND" },
641	{ 0x0c, 1, 1, "3DSTATE_MODES_5" },
642	{ 0x0d, 1, 1, "3DSTATE_MAP_BLEND_OP" },
643	{ 0x0e, 1, 1, "3DSTATE_MAP_BLEND_ARG" },
644	{ 0x0f, 1, 1, "3DSTATE_MODES_2" },
645	{ 0x15, 1, 1, "3DSTATE_FOG_COLOR" },
646	{ 0x16, 1, 1, "3DSTATE_MODES_4" },
647    };
648    uint32_t *data = kgem->batch + offset;
649    uint32_t opcode = (data[0] & 0x1f000000) >> 24;
650    uint32_t idx;
651
652    switch (opcode) {
653    case 0x1f:
654	return decode_3d_primitive(kgem, offset);
655    case 0x1d:
656	return decode_3d_1d(kgem, offset);
657    case 0x1c:
658	return decode_3d_1c(kgem, offset);
659    }
660
661    /* Catch the known instructions */
662    for (idx = 0; idx < ARRAY_SIZE(opcodes); idx++) {
663	if (opcode == opcodes[idx].opcode) {
664	    unsigned int len = 1, i;
665
666	    kgem_debug_print(data, offset, 0, "%s\n", opcodes[idx].name);
667	    if (opcodes[idx].max_len > 1) {
668		len = (data[0] & 0xf) + 2;
669		assert(len >= opcodes[idx].min_len &&
670		       len <= opcodes[idx].max_len);
671	    }
672
673	    for (i = 1; i < len; i++)
674		kgem_debug_print(data, offset, i, "dword %d\n", i);
675	    return len;
676	}
677    }
678
679    kgem_debug_print(data, offset, 0, "3D UNKNOWN: 3d opcode = 0x%x\n", opcode);
680    return 1;
681}
682
683void kgem_gen2_finish_state(struct kgem *kgem)
684{
685	memset(&state, 0, sizeof(state));
686}
687