1428d7b3dSmrg/*
2428d7b3dSmrg * Copyright © 2007-2011 Intel Corporation
3428d7b3dSmrg *
4428d7b3dSmrg * Permission is hereby granted, free of charge, to any person obtaining a
5428d7b3dSmrg * copy of this software and associated documentation files (the "Software"),
6428d7b3dSmrg * to deal in the Software without restriction, including without limitation
7428d7b3dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8428d7b3dSmrg * and/or sell copies of the Software, and to permit persons to whom the
9428d7b3dSmrg * Software is furnished to do so, subject to the following conditions:
10428d7b3dSmrg *
11428d7b3dSmrg * The above copyright notice and this permission notice (including the next
12428d7b3dSmrg * paragraph) shall be included in all copies or substantial portions of the
13428d7b3dSmrg * Software.
14428d7b3dSmrg *
15428d7b3dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16428d7b3dSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17428d7b3dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18428d7b3dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19428d7b3dSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20428d7b3dSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21428d7b3dSmrg * SOFTWARE.
22428d7b3dSmrg *
23428d7b3dSmrg * Authors:
24428d7b3dSmrg *    Eric Anholt <eric@anholt.net>
25428d7b3dSmrg *    Chris Wilson <chris"chris-wilson.co.uk>
26428d7b3dSmrg *
27428d7b3dSmrg */
28428d7b3dSmrg
29428d7b3dSmrg#ifdef HAVE_CONFIG_H
30428d7b3dSmrg#include "config.h"
31428d7b3dSmrg#endif
32428d7b3dSmrg
33428d7b3dSmrg#include <sys/mman.h>
34428d7b3dSmrg#include <assert.h>
35428d7b3dSmrg
36428d7b3dSmrg#include "sna.h"
37428d7b3dSmrg#include "sna_reg.h"
38428d7b3dSmrg#include "gen6_render.h"
39428d7b3dSmrg
40428d7b3dSmrg#include "kgem_debug.h"
41428d7b3dSmrg
42428d7b3dSmrgstatic struct state {
43428d7b3dSmrg	struct vertex_buffer {
44428d7b3dSmrg		int handle;
45428d7b3dSmrg		const char *ptr;
46428d7b3dSmrg		int pitch;
47428d7b3dSmrg
48428d7b3dSmrg		struct kgem_bo *current;
49428d7b3dSmrg	} vb[33];
50428d7b3dSmrg	struct vertex_elements {
51428d7b3dSmrg		int buffer;
52428d7b3dSmrg		int offset;
53428d7b3dSmrg		bool valid;
54428d7b3dSmrg		uint32_t type;
55428d7b3dSmrg		uint8_t swizzle[4];
56428d7b3dSmrg	} ve[33];
57428d7b3dSmrg	int num_ve;
58428d7b3dSmrg
59428d7b3dSmrg	struct dynamic_state {
60428d7b3dSmrg		struct kgem_bo *current;
61428d7b3dSmrg		void *base, *ptr;
62428d7b3dSmrg	} dynamic_state;
63428d7b3dSmrg} state;
64428d7b3dSmrg
65428d7b3dSmrgstatic void gen6_update_vertex_buffer(struct kgem *kgem, const uint32_t *data)
66428d7b3dSmrg{
67428d7b3dSmrg	uint32_t reloc = sizeof(uint32_t) * (&data[1] - kgem->batch);
68428d7b3dSmrg	struct kgem_bo *bo = NULL;
69428d7b3dSmrg	void *base;
70428d7b3dSmrg	int i;
71428d7b3dSmrg
72428d7b3dSmrg	for (i = 0; i < kgem->nreloc; i++)
73428d7b3dSmrg		if (kgem->reloc[i].offset == reloc)
74428d7b3dSmrg			break;
75428d7b3dSmrg	assert(i < kgem->nreloc);
76428d7b3dSmrg	reloc = kgem->reloc[i].target_handle;
77428d7b3dSmrg
78428d7b3dSmrg	if (reloc == -1) {
79428d7b3dSmrg		base = kgem->batch;
80428d7b3dSmrg	} else {
81428d7b3dSmrg		list_for_each_entry(bo, &kgem->next_request->buffers, request)
82428d7b3dSmrg			if (bo->target_handle == reloc)
83428d7b3dSmrg				break;
84428d7b3dSmrg		assert(&bo->request != &kgem->next_request->buffers);
85428d7b3dSmrg		base = kgem_bo_map__debug(kgem, bo);
86428d7b3dSmrg	}
87428d7b3dSmrg
88428d7b3dSmrg	base = (char *)base + kgem->reloc[i].delta;
89428d7b3dSmrg	i = data[0] >> 26;
90428d7b3dSmrg
91428d7b3dSmrg	state.vb[i].current = bo;
92428d7b3dSmrg	state.vb[i].ptr = base;
93428d7b3dSmrg	state.vb[i].pitch = data[0] & 0x7ff;
94428d7b3dSmrg}
95428d7b3dSmrg
96428d7b3dSmrgstatic void gen6_update_dynamic_buffer(struct kgem *kgem, const uint32_t offset)
97428d7b3dSmrg{
98428d7b3dSmrg	uint32_t reloc = sizeof(uint32_t) * offset;
99428d7b3dSmrg	struct kgem_bo *bo = NULL;
100428d7b3dSmrg	void *base, *ptr;
101428d7b3dSmrg	int i;
102428d7b3dSmrg
103428d7b3dSmrg	if ((kgem->batch[offset] & 1) == 0)
104428d7b3dSmrg		return;
105428d7b3dSmrg
106428d7b3dSmrg	for (i = 0; i < kgem->nreloc; i++)
107428d7b3dSmrg		if (kgem->reloc[i].offset == reloc)
108428d7b3dSmrg			break;
109428d7b3dSmrg	if(i < kgem->nreloc) {
110428d7b3dSmrg		reloc = kgem->reloc[i].target_handle;
111428d7b3dSmrg
112428d7b3dSmrg		if (reloc == 0) {
113428d7b3dSmrg			base = kgem->batch;
114428d7b3dSmrg		} else {
115428d7b3dSmrg			list_for_each_entry(bo, &kgem->next_request->buffers, request)
116428d7b3dSmrg				if (bo->handle == reloc)
117428d7b3dSmrg					break;
118428d7b3dSmrg			assert(&bo->request != &kgem->next_request->buffers);
119428d7b3dSmrg			base = kgem_bo_map__debug(kgem, bo);
120428d7b3dSmrg		}
121428d7b3dSmrg		ptr = (char *)base + (kgem->reloc[i].delta & ~1);
122428d7b3dSmrg	} else {
123428d7b3dSmrg		bo = NULL;
124428d7b3dSmrg		base = NULL;
125428d7b3dSmrg		ptr = NULL;
126428d7b3dSmrg	}
127428d7b3dSmrg
128428d7b3dSmrg	state.dynamic_state.current = bo;
129428d7b3dSmrg	state.dynamic_state.base = base;
130428d7b3dSmrg	state.dynamic_state.ptr = ptr;
131428d7b3dSmrg}
132428d7b3dSmrg
133428d7b3dSmrgstatic uint32_t
134428d7b3dSmrgget_ve_component(uint32_t data, int component)
135428d7b3dSmrg{
136428d7b3dSmrg	return (data >> (16 + (3 - component) * 4)) & 0x7;
137428d7b3dSmrg}
138428d7b3dSmrg
139428d7b3dSmrgstatic void gen6_update_vertex_elements(struct kgem *kgem, int id, const uint32_t *data)
140428d7b3dSmrg{
141428d7b3dSmrg	state.ve[id].buffer = data[0] >> 26;
142428d7b3dSmrg	state.ve[id].valid = !!(data[0] & (1 << 25));
143428d7b3dSmrg	state.ve[id].type = (data[0] >> 16) & 0x1ff;
144428d7b3dSmrg	state.ve[id].offset = data[0] & 0x7ff;
145428d7b3dSmrg	state.ve[id].swizzle[0] = get_ve_component(data[1], 0);
146428d7b3dSmrg	state.ve[id].swizzle[1] = get_ve_component(data[1], 1);
147428d7b3dSmrg	state.ve[id].swizzle[2] = get_ve_component(data[1], 2);
148428d7b3dSmrg	state.ve[id].swizzle[3] = get_ve_component(data[1], 3);
149428d7b3dSmrg}
150428d7b3dSmrg
151428d7b3dSmrgstatic void gen6_update_sf_state(struct kgem *kgem, uint32_t *data)
152428d7b3dSmrg{
153428d7b3dSmrg	state.num_ve = 1 + ((data[1] >> 22) & 0x3f);
154428d7b3dSmrg}
155428d7b3dSmrg
156428d7b3dSmrgstatic void vertices_sint16_out(const struct vertex_elements *ve, const int16_t *v, int max)
157428d7b3dSmrg{
158428d7b3dSmrg	int c;
159428d7b3dSmrg
160428d7b3dSmrg	ErrorF("(");
161428d7b3dSmrg	for (c = 0; c < max; c++) {
162428d7b3dSmrg		switch (ve->swizzle[c]) {
163428d7b3dSmrg		case 0: ErrorF("#"); break;
164428d7b3dSmrg		case 1: ErrorF("%d", v[c]); break;
165428d7b3dSmrg		case 2: ErrorF("0.0"); break;
166428d7b3dSmrg		case 3: ErrorF("1.0"); break;
167428d7b3dSmrg		case 4: ErrorF("0x1"); break;
168428d7b3dSmrg		case 5: break;
169428d7b3dSmrg		default: ErrorF("?");
170428d7b3dSmrg		}
171428d7b3dSmrg		if (c < 3)
172428d7b3dSmrg			ErrorF(", ");
173428d7b3dSmrg	}
174428d7b3dSmrg	for (; c < 4; c++) {
175428d7b3dSmrg		switch (ve->swizzle[c]) {
176428d7b3dSmrg		case 0: ErrorF("#"); break;
177428d7b3dSmrg		case 1: ErrorF("1.0"); break;
178428d7b3dSmrg		case 2: ErrorF("0.0"); break;
179428d7b3dSmrg		case 3: ErrorF("1.0"); break;
180428d7b3dSmrg		case 4: ErrorF("0x1"); break;
181428d7b3dSmrg		case 5: break;
182428d7b3dSmrg		default: ErrorF("?");
183428d7b3dSmrg		}
184428d7b3dSmrg		if (c < 3)
185428d7b3dSmrg			ErrorF(", ");
186428d7b3dSmrg	}
187428d7b3dSmrg	ErrorF(")");
188428d7b3dSmrg}
189428d7b3dSmrg
190428d7b3dSmrgstatic void vertices_float_out(const struct vertex_elements *ve, const float *f, int max)
191428d7b3dSmrg{
192428d7b3dSmrg	int c, o;
193428d7b3dSmrg
194428d7b3dSmrg	ErrorF("(");
195428d7b3dSmrg	for (c = o = 0; c < 4 && o < max; c++) {
196428d7b3dSmrg		switch (ve->swizzle[c]) {
197428d7b3dSmrg		case 0: ErrorF("#"); break;
198428d7b3dSmrg		case 1: ErrorF("%f", f[o++]); break;
199428d7b3dSmrg		case 2: ErrorF("0.0"); break;
200428d7b3dSmrg		case 3: ErrorF("1.0"); break;
201428d7b3dSmrg		case 4: ErrorF("0x1"); break;
202428d7b3dSmrg		case 5: break;
203428d7b3dSmrg		default: ErrorF("?");
204428d7b3dSmrg		}
205428d7b3dSmrg		if (c < 3)
206428d7b3dSmrg			ErrorF(", ");
207428d7b3dSmrg	}
208428d7b3dSmrg	for (; c < 4; c++) {
209428d7b3dSmrg		switch (ve->swizzle[c]) {
210428d7b3dSmrg		case 0: ErrorF("#"); break;
211428d7b3dSmrg		case 1: ErrorF("1.0"); break;
212428d7b3dSmrg		case 2: ErrorF("0.0"); break;
213428d7b3dSmrg		case 3: ErrorF("1.0"); break;
214428d7b3dSmrg		case 4: ErrorF("0x1"); break;
215428d7b3dSmrg		case 5: break;
216428d7b3dSmrg		default: ErrorF("?");
217428d7b3dSmrg		}
218428d7b3dSmrg		if (c < 3)
219428d7b3dSmrg			ErrorF(", ");
220428d7b3dSmrg	}
221428d7b3dSmrg	ErrorF(")");
222428d7b3dSmrg}
223428d7b3dSmrg
224428d7b3dSmrgstatic void ve_out(const struct vertex_elements *ve, const void *ptr)
225428d7b3dSmrg{
226428d7b3dSmrg	switch (ve->type) {
227428d7b3dSmrg	case GEN6_SURFACEFORMAT_R32_FLOAT:
228428d7b3dSmrg		vertices_float_out(ve, ptr, 1);
229428d7b3dSmrg		break;
230428d7b3dSmrg	case GEN6_SURFACEFORMAT_R32G32_FLOAT:
231428d7b3dSmrg		vertices_float_out(ve, ptr, 2);
232428d7b3dSmrg		break;
233428d7b3dSmrg	case GEN6_SURFACEFORMAT_R32G32B32_FLOAT:
234428d7b3dSmrg		vertices_float_out(ve, ptr, 3);
235428d7b3dSmrg		break;
236428d7b3dSmrg	case GEN6_SURFACEFORMAT_R32G32B32A32_FLOAT:
237428d7b3dSmrg		vertices_float_out(ve, ptr, 4);
238428d7b3dSmrg		break;
239428d7b3dSmrg	case GEN6_SURFACEFORMAT_R16_SINT:
240428d7b3dSmrg		vertices_sint16_out(ve, ptr, 1);
241428d7b3dSmrg		break;
242428d7b3dSmrg	case GEN6_SURFACEFORMAT_R16G16_SINT:
243428d7b3dSmrg		vertices_sint16_out(ve, ptr, 2);
244428d7b3dSmrg		break;
245428d7b3dSmrg	case GEN6_SURFACEFORMAT_R16G16B16A16_SINT:
246428d7b3dSmrg		vertices_sint16_out(ve, ptr, 4);
247428d7b3dSmrg		break;
248428d7b3dSmrg	case GEN6_SURFACEFORMAT_R16_SSCALED:
249428d7b3dSmrg		vertices_sint16_out(ve, ptr, 1);
250428d7b3dSmrg		break;
251428d7b3dSmrg	case GEN6_SURFACEFORMAT_R16G16_SSCALED:
252428d7b3dSmrg		vertices_sint16_out(ve, ptr, 2);
253428d7b3dSmrg		break;
254428d7b3dSmrg	case GEN6_SURFACEFORMAT_R16G16B16A16_SSCALED:
255428d7b3dSmrg		vertices_sint16_out(ve, ptr, 4);
256428d7b3dSmrg		break;
257428d7b3dSmrg	}
258428d7b3dSmrg}
259428d7b3dSmrg
260428d7b3dSmrgstatic void indirect_vertex_out(struct kgem *kgem, uint32_t v)
261428d7b3dSmrg{
262428d7b3dSmrg	int i = 1;
263428d7b3dSmrg
264428d7b3dSmrg	do {
265428d7b3dSmrg		const struct vertex_elements *ve = &state.ve[i];
266428d7b3dSmrg		const struct vertex_buffer *vb = &state.vb[ve->buffer];
267428d7b3dSmrg		const void *ptr = vb->ptr + v * vb->pitch + ve->offset;
268428d7b3dSmrg
269428d7b3dSmrg		if (ve->valid)
270428d7b3dSmrg			ve_out(ve, ptr);
271428d7b3dSmrg
272428d7b3dSmrg		while (++i <= state.num_ve && !state.ve[i].valid)
273428d7b3dSmrg			;
274428d7b3dSmrg
275428d7b3dSmrg		if (i <= state.num_ve)
276428d7b3dSmrg			ErrorF(", ");
277428d7b3dSmrg	} while (i <= state.num_ve);
278428d7b3dSmrg}
279428d7b3dSmrg
280428d7b3dSmrgstatic void primitive_out(struct kgem *kgem, uint32_t *data)
281428d7b3dSmrg{
282428d7b3dSmrg	int n;
283428d7b3dSmrg
284428d7b3dSmrg	assert((data[0] & (1<<15)) == 0); /* XXX index buffers */
285428d7b3dSmrg
286428d7b3dSmrg	for (n = 0; n < data[1]; n++) {
287428d7b3dSmrg		int v = data[2] + n;
288428d7b3dSmrg		ErrorF("	[%d:%d] = ", n, v);
289428d7b3dSmrg		indirect_vertex_out(kgem, v);
290428d7b3dSmrg		ErrorF("\n");
291428d7b3dSmrg	}
292428d7b3dSmrg}
293428d7b3dSmrg
294428d7b3dSmrgstatic void finish_state(struct kgem *kgem)
295428d7b3dSmrg{
296428d7b3dSmrg	memset(&state, 0, sizeof(state));
297428d7b3dSmrg}
298428d7b3dSmrg
299428d7b3dSmrgstatic void
300428d7b3dSmrgstate_base_out(uint32_t *data, uint32_t offset, unsigned int index,
301428d7b3dSmrg	       const char *name)
302428d7b3dSmrg{
303428d7b3dSmrg    if (data[index] & 1)
304428d7b3dSmrg	kgem_debug_print(data, offset, index,
305428d7b3dSmrg		  "%s state base address 0x%08x\n",
306428d7b3dSmrg		  name, data[index] & ~1);
307428d7b3dSmrg    else
308428d7b3dSmrg	kgem_debug_print(data, offset, index,
309428d7b3dSmrg		  "%s state base not updated\n",
310428d7b3dSmrg		  name);
311428d7b3dSmrg}
312428d7b3dSmrg
313428d7b3dSmrgstatic void
314428d7b3dSmrgstate_max_out(uint32_t *data, uint32_t offset, unsigned int index,
315428d7b3dSmrg	      const char *name)
316428d7b3dSmrg{
317428d7b3dSmrg	if (data[index] == 1)
318428d7b3dSmrg		kgem_debug_print(data, offset, index,
319428d7b3dSmrg			  "%s state upper bound disabled\n", name);
320428d7b3dSmrg	else if (data[index] & 1)
321428d7b3dSmrg		kgem_debug_print(data, offset, index,
322428d7b3dSmrg			  "%s state upper bound 0x%08x\n",
323428d7b3dSmrg			  name, data[index] & ~1);
324428d7b3dSmrg	else
325428d7b3dSmrg		kgem_debug_print(data, offset, index,
326428d7b3dSmrg			  "%s state upper bound not updated\n",
327428d7b3dSmrg			  name);
328428d7b3dSmrg}
329428d7b3dSmrg
330428d7b3dSmrgstatic const char *
331428d7b3dSmrgget_965_surfacetype(unsigned int surfacetype)
332428d7b3dSmrg{
333428d7b3dSmrg	switch (surfacetype) {
334428d7b3dSmrg	case 0: return "1D";
335428d7b3dSmrg	case 1: return "2D";
336428d7b3dSmrg	case 2: return "3D";
337428d7b3dSmrg	case 3: return "CUBE";
338428d7b3dSmrg	case 4: return "BUFFER";
339428d7b3dSmrg	case 7: return "NULL";
340428d7b3dSmrg	default: return "unknown";
341428d7b3dSmrg	}
342428d7b3dSmrg}
343428d7b3dSmrg
344428d7b3dSmrgstatic const char *
345428d7b3dSmrgget_965_depthformat(unsigned int depthformat)
346428d7b3dSmrg{
347428d7b3dSmrg	switch (depthformat) {
348428d7b3dSmrg	case 0: return "s8_z24float";
349428d7b3dSmrg	case 1: return "z32float";
350428d7b3dSmrg	case 2: return "z24s8";
351428d7b3dSmrg	case 5: return "z16";
352428d7b3dSmrg	default: return "unknown";
353428d7b3dSmrg	}
354428d7b3dSmrg}
355428d7b3dSmrg
356428d7b3dSmrgstatic const char *
357428d7b3dSmrgget_965_element_component(uint32_t data, int component)
358428d7b3dSmrg{
359428d7b3dSmrg	uint32_t component_control = (data >> (16 + (3 - component) * 4)) & 0x7;
360428d7b3dSmrg
361428d7b3dSmrg	switch (component_control) {
362428d7b3dSmrg	case 0:
363428d7b3dSmrg		return "nostore";
364428d7b3dSmrg	case 1:
365428d7b3dSmrg		switch (component) {
366428d7b3dSmrg		case 0: return "X";
367428d7b3dSmrg		case 1: return "Y";
368428d7b3dSmrg		case 2: return "Z";
369428d7b3dSmrg		case 3: return "W";
370428d7b3dSmrg		default: return "fail";
371428d7b3dSmrg		}
372428d7b3dSmrg	case 2:
373428d7b3dSmrg		return "0.0";
374428d7b3dSmrg	case 3:
375428d7b3dSmrg		return "1.0";
376428d7b3dSmrg	case 4:
377428d7b3dSmrg		return "0x1";
378428d7b3dSmrg	case 5:
379428d7b3dSmrg		return "VID";
380428d7b3dSmrg	default:
381428d7b3dSmrg		return "fail";
382428d7b3dSmrg	}
383428d7b3dSmrg}
384428d7b3dSmrg
385428d7b3dSmrgstatic const char *
386428d7b3dSmrgget_965_prim_type(uint32_t data)
387428d7b3dSmrg{
388428d7b3dSmrg	uint32_t primtype = (data >> 10) & 0x1f;
389428d7b3dSmrg
390428d7b3dSmrg	switch (primtype) {
391428d7b3dSmrg	case 0x01: return "point list";
392428d7b3dSmrg	case 0x02: return "line list";
393428d7b3dSmrg	case 0x03: return "line strip";
394428d7b3dSmrg	case 0x04: return "tri list";
395428d7b3dSmrg	case 0x05: return "tri strip";
396428d7b3dSmrg	case 0x06: return "tri fan";
397428d7b3dSmrg	case 0x07: return "quad list";
398428d7b3dSmrg	case 0x08: return "quad strip";
399428d7b3dSmrg	case 0x09: return "line list adj";
400428d7b3dSmrg	case 0x0a: return "line strip adj";
401428d7b3dSmrg	case 0x0b: return "tri list adj";
402428d7b3dSmrg	case 0x0c: return "tri strip adj";
403428d7b3dSmrg	case 0x0d: return "tri strip reverse";
404428d7b3dSmrg	case 0x0e: return "polygon";
405428d7b3dSmrg	case 0x0f: return "rect list";
406428d7b3dSmrg	case 0x10: return "line loop";
407428d7b3dSmrg	case 0x11: return "point list bf";
408428d7b3dSmrg	case 0x12: return "line strip cont";
409428d7b3dSmrg	case 0x13: return "line strip bf";
410428d7b3dSmrg	case 0x14: return "line strip cont bf";
411428d7b3dSmrg	case 0x15: return "tri fan no stipple";
412428d7b3dSmrg	default: return "fail";
413428d7b3dSmrg	}
414428d7b3dSmrg}
415428d7b3dSmrg
416428d7b3dSmrgstruct reloc {
417428d7b3dSmrg	struct kgem_bo *bo;
418428d7b3dSmrg	void *base;
419428d7b3dSmrg};
420428d7b3dSmrg
421428d7b3dSmrgstatic void *
422428d7b3dSmrgget_reloc(struct kgem *kgem,
423428d7b3dSmrg	  void *base, const uint32_t *reloc,
424428d7b3dSmrg	  struct reloc *r)
425428d7b3dSmrg{
426428d7b3dSmrg	uint32_t delta = *reloc;
427428d7b3dSmrg
428428d7b3dSmrg	memset(r, 0, sizeof(*r));
429428d7b3dSmrg
430428d7b3dSmrg	if (base == 0) {
431428d7b3dSmrg		uint32_t handle = sizeof(uint32_t) * (reloc - kgem->batch);
432428d7b3dSmrg		struct kgem_bo *bo = NULL;
433428d7b3dSmrg		int i;
434428d7b3dSmrg
435428d7b3dSmrg		for (i = 0; i < kgem->nreloc; i++)
436428d7b3dSmrg			if (kgem->reloc[i].offset == handle)
437428d7b3dSmrg				break;
438428d7b3dSmrg		assert(i < kgem->nreloc);
439428d7b3dSmrg		handle = kgem->reloc[i].target_handle;
440428d7b3dSmrg		delta = kgem->reloc[i].delta;
441428d7b3dSmrg
442428d7b3dSmrg		if (handle == 0) {
443428d7b3dSmrg			base = kgem->batch;
444428d7b3dSmrg		} else {
445428d7b3dSmrg			list_for_each_entry(bo, &kgem->next_request->buffers, request)
446428d7b3dSmrg				if (bo->handle == handle)
447428d7b3dSmrg					break;
448428d7b3dSmrg			assert(&bo->request != &kgem->next_request->buffers);
449428d7b3dSmrg			base = kgem_bo_map__debug(kgem, bo);
450428d7b3dSmrg			r->bo = bo;
451428d7b3dSmrg			r->base = base;
452428d7b3dSmrg		}
453428d7b3dSmrg	}
454428d7b3dSmrg
455428d7b3dSmrg	return (char *)base + (delta & ~3);
456428d7b3dSmrg}
457428d7b3dSmrg
458428d7b3dSmrgstatic const char *
459428d7b3dSmrggen6_filter_to_string(uint32_t filter)
460428d7b3dSmrg{
461428d7b3dSmrg	switch (filter) {
462428d7b3dSmrg	default:
463428d7b3dSmrg	case GEN6_MAPFILTER_NEAREST: return "nearest";
464428d7b3dSmrg	case GEN6_MAPFILTER_LINEAR: return "linear";
465428d7b3dSmrg	}
466428d7b3dSmrg}
467428d7b3dSmrg
468428d7b3dSmrgstatic const char *
469428d7b3dSmrggen6_repeat_to_string(uint32_t repeat)
470428d7b3dSmrg{
471428d7b3dSmrg	switch (repeat) {
472428d7b3dSmrg	default:
473428d7b3dSmrg	case GEN6_TEXCOORDMODE_CLAMP_BORDER: return "border";
474428d7b3dSmrg	case GEN6_TEXCOORDMODE_WRAP: return "wrap";
475428d7b3dSmrg	case GEN6_TEXCOORDMODE_CLAMP: return "clamp";
476428d7b3dSmrg	case GEN6_TEXCOORDMODE_MIRROR: return "mirror";
477428d7b3dSmrg	}
478428d7b3dSmrg}
479428d7b3dSmrg
480428d7b3dSmrgstatic void
481428d7b3dSmrggen6_decode_sampler_state(struct kgem *kgem, const uint32_t *reloc)
482428d7b3dSmrg{
483428d7b3dSmrg	const struct gen6_sampler_state *ss;
484428d7b3dSmrg	struct reloc r;
485428d7b3dSmrg	const char *min, *mag;
486428d7b3dSmrg	const char *s_wrap, *t_wrap, *r_wrap;
487428d7b3dSmrg
488428d7b3dSmrg	ss = get_reloc(kgem, state.dynamic_state.ptr, reloc, &r);
489428d7b3dSmrg
490428d7b3dSmrg	min = gen6_filter_to_string(ss->ss0.min_filter);
491428d7b3dSmrg	mag = gen6_filter_to_string(ss->ss0.mag_filter);
492428d7b3dSmrg
493428d7b3dSmrg	s_wrap = gen6_repeat_to_string(ss->ss1.s_wrap_mode);
494428d7b3dSmrg	t_wrap = gen6_repeat_to_string(ss->ss1.t_wrap_mode);
495428d7b3dSmrg	r_wrap = gen6_repeat_to_string(ss->ss1.r_wrap_mode);
496428d7b3dSmrg
497428d7b3dSmrg	ErrorF("  Sampler 0:\n");
498428d7b3dSmrg	ErrorF("    filter: min=%s, mag=%s\n", min, mag);
499428d7b3dSmrg	ErrorF("    wrap: s=%s, t=%s, r=%s\n", s_wrap, t_wrap, r_wrap);
500428d7b3dSmrg
501428d7b3dSmrg	ss++;
502428d7b3dSmrg	min = gen6_filter_to_string(ss->ss0.min_filter);
503428d7b3dSmrg	mag = gen6_filter_to_string(ss->ss0.mag_filter);
504428d7b3dSmrg
505428d7b3dSmrg	s_wrap = gen6_repeat_to_string(ss->ss1.s_wrap_mode);
506428d7b3dSmrg	t_wrap = gen6_repeat_to_string(ss->ss1.t_wrap_mode);
507428d7b3dSmrg	r_wrap = gen6_repeat_to_string(ss->ss1.r_wrap_mode);
508428d7b3dSmrg
509428d7b3dSmrg	ErrorF("  Sampler 1:\n");
510428d7b3dSmrg	ErrorF("    filter: min=%s, mag=%s\n", min, mag);
511428d7b3dSmrg	ErrorF("    wrap: s=%s, t=%s, r=%s\n", s_wrap, t_wrap, r_wrap);
512428d7b3dSmrg}
513428d7b3dSmrg
514428d7b3dSmrgstatic const char *
515428d7b3dSmrggen6_blend_factor_to_string(uint32_t v)
516428d7b3dSmrg{
517428d7b3dSmrg	switch (v) {
518428d7b3dSmrg#define C(x) case GEN6_BLENDFACTOR_##x: return #x;
519428d7b3dSmrg		C(ONE);
520428d7b3dSmrg		C(SRC_COLOR);
521428d7b3dSmrg		C(SRC_ALPHA);
522428d7b3dSmrg		C(DST_ALPHA);
523428d7b3dSmrg		C(DST_COLOR);
524428d7b3dSmrg		C(SRC_ALPHA_SATURATE);
525428d7b3dSmrg		C(CONST_COLOR);
526428d7b3dSmrg		C(CONST_ALPHA);
527428d7b3dSmrg		C(SRC1_COLOR);
528428d7b3dSmrg		C(SRC1_ALPHA);
529428d7b3dSmrg		C(ZERO);
530428d7b3dSmrg		C(INV_SRC_COLOR);
531428d7b3dSmrg		C(INV_SRC_ALPHA);
532428d7b3dSmrg		C(INV_DST_ALPHA);
533428d7b3dSmrg		C(INV_DST_COLOR);
534428d7b3dSmrg		C(INV_CONST_COLOR);
535428d7b3dSmrg		C(INV_CONST_ALPHA);
536428d7b3dSmrg		C(INV_SRC1_COLOR);
537428d7b3dSmrg		C(INV_SRC1_ALPHA);
538428d7b3dSmrg#undef C
539428d7b3dSmrg	default: return "???";
540428d7b3dSmrg	}
541428d7b3dSmrg}
542428d7b3dSmrg
543428d7b3dSmrgstatic const char *
544428d7b3dSmrggen6_blend_function_to_string(uint32_t v)
545428d7b3dSmrg{
546428d7b3dSmrg	switch (v) {
547428d7b3dSmrg#define C(x) case GEN6_BLENDFUNCTION_##x: return #x;
548428d7b3dSmrg		C(ADD);
549428d7b3dSmrg		C(SUBTRACT);
550428d7b3dSmrg		C(REVERSE_SUBTRACT);
551428d7b3dSmrg		C(MIN);
552428d7b3dSmrg		C(MAX);
553428d7b3dSmrg#undef C
554428d7b3dSmrg	default: return "???";
555428d7b3dSmrg	}
556428d7b3dSmrg}
557428d7b3dSmrg
558428d7b3dSmrgstatic float unpack_float(uint32_t dw)
559428d7b3dSmrg{
560428d7b3dSmrg	union {
561428d7b3dSmrg		float f;
562428d7b3dSmrg		uint32_t dw;
563428d7b3dSmrg	} u;
564428d7b3dSmrg	u.dw = dw;
565428d7b3dSmrg	return u.f;
566428d7b3dSmrg}
567428d7b3dSmrg
568428d7b3dSmrgstatic void
569428d7b3dSmrggen6_decode_blend(struct kgem *kgem, const uint32_t *reloc)
570428d7b3dSmrg{
571428d7b3dSmrg	const struct gen6_blend_state *blend;
572428d7b3dSmrg	struct reloc r;
573428d7b3dSmrg	const char *dst, *src;
574428d7b3dSmrg	const char *func;
575428d7b3dSmrg
576428d7b3dSmrg	blend = get_reloc(kgem, state.dynamic_state.ptr, reloc, &r);
577428d7b3dSmrg
578428d7b3dSmrg	dst = gen6_blend_factor_to_string(blend->blend0.dest_blend_factor);
579428d7b3dSmrg	src = gen6_blend_factor_to_string(blend->blend0.source_blend_factor);
580428d7b3dSmrg	func = gen6_blend_function_to_string(blend->blend0.blend_func);
581428d7b3dSmrg
582428d7b3dSmrg	ErrorF("  Blend (%s): function %s, src=%s, dst=%s\n",
583428d7b3dSmrg	       blend->blend0.blend_enable ? "enabled" : "disabled",
584428d7b3dSmrg	       func, src, dst);
585428d7b3dSmrg}
586428d7b3dSmrg
587428d7b3dSmrgint kgem_gen6_decode_3d(struct kgem *kgem, uint32_t offset)
588428d7b3dSmrg{
589428d7b3dSmrg	static const struct {
590428d7b3dSmrg		uint32_t opcode;
591428d7b3dSmrg		int min_len;
592428d7b3dSmrg		int max_len;
593428d7b3dSmrg		const char *name;
594428d7b3dSmrg	} opcodes[] = {
595428d7b3dSmrg		{ 0x6101, 6, 6, "STATE_BASE_ADDRESS" },
596428d7b3dSmrg		{ 0x6102, 2, 2 , "STATE_SIP" },
597428d7b3dSmrg		{ 0x6104, 1, 1, "3DSTATE_PIPELINE_SELECT" },
598428d7b3dSmrg		{ 0x680b, 1, 1, "3DSTATE_VF_STATISTICS" },
599428d7b3dSmrg		{ 0x6904, 1, 1, "3DSTATE_PIPELINE_SELECT" },
600428d7b3dSmrg		{ 0x7800, 7, 7, "3DSTATE_PIPELINED_POINTERS" },
601428d7b3dSmrg		{ 0x7801, 6, 6, "3DSTATE_BINDING_TABLE_POINTERS" },
602428d7b3dSmrg		{ 0x7808, 5, 257, "3DSTATE_VERTEX_BUFFERS" },
603428d7b3dSmrg		{ 0x7809, 3, 256, "3DSTATE_VERTEX_ELEMENTS" },
604428d7b3dSmrg		{ 0x780a, 3, 3, "3DSTATE_INDEX_BUFFER" },
605428d7b3dSmrg		{ 0x780b, 1, 1, "3DSTATE_VF_STATISTICS" },
606428d7b3dSmrg		{ 0x7900, 4, 4, "3DSTATE_DRAWING_RECTANGLE" },
607428d7b3dSmrg		{ 0x7901, 5, 5, "3DSTATE_CONSTANT_COLOR" },
608428d7b3dSmrg		{ 0x7905, 5, 7, "3DSTATE_DEPTH_BUFFER" },
609428d7b3dSmrg		{ 0x7906, 2, 2, "3DSTATE_POLY_STIPPLE_OFFSET" },
610428d7b3dSmrg		{ 0x7907, 33, 33, "3DSTATE_POLY_STIPPLE_PATTERN" },
611428d7b3dSmrg		{ 0x7908, 3, 3, "3DSTATE_LINE_STIPPLE" },
612428d7b3dSmrg		{ 0x7909, 2, 2, "3DSTATE_GLOBAL_DEPTH_OFFSET_CLAMP" },
613428d7b3dSmrg		{ 0x7909, 2, 2, "3DSTATE_CLEAR_PARAMS" },
614428d7b3dSmrg		{ 0x790a, 3, 3, "3DSTATE_AA_LINE_PARAMETERS" },
615428d7b3dSmrg		{ 0x790b, 4, 4, "3DSTATE_GS_SVB_INDEX" },
616428d7b3dSmrg		{ 0x790d, 3, 3, "3DSTATE_MULTISAMPLE" },
617428d7b3dSmrg		{ 0x7910, 2, 2, "3DSTATE_CLEAR_PARAMS" },
618428d7b3dSmrg		{ 0x7b00, 6, 6, "3DPRIMITIVE" },
619428d7b3dSmrg		{ 0x7802, 4, 4, "3DSTATE_SAMPLER_STATE_POINTERS" },
620428d7b3dSmrg		{ 0x7805, 3, 3, "3DSTATE_URB" },
621428d7b3dSmrg		{ 0x780d, 4, 4, "3DSTATE_VIEWPORT_STATE_POINTERS" },
622428d7b3dSmrg		{ 0x780e, 4, 4, "3DSTATE_CC_STATE_POINTERS" },
623428d7b3dSmrg		{ 0x780f, 2, 2, "3DSTATE_SCISSOR_STATE_POINTERS" },
624428d7b3dSmrg		{ 0x7810, 6, 6, "3DSTATE_VS_STATE" },
625428d7b3dSmrg		{ 0x7811, 7, 7, "3DSTATE_GS_STATE" },
626428d7b3dSmrg		{ 0x7812, 4, 4, "3DSTATE_CLIP_STATE" },
627428d7b3dSmrg		{ 0x7813, 20, 20, "3DSTATE_SF_STATE" },
628428d7b3dSmrg		{ 0x7814, 9, 9, "3DSTATE_WM_STATE" },
629428d7b3dSmrg		{ 0x7815, 5, 5, "3DSTATE_CONSTANT_VS_STATE" },
630428d7b3dSmrg		{ 0x7816, 5, 5, "3DSTATE_CONSTANT_GS_STATE" },
631428d7b3dSmrg		{ 0x7817, 5, 5, "3DSTATE_CONSTANT_WM_STATE" },
632428d7b3dSmrg		{ 0x7818, 2, 2, "3DSTATE_SAMPLE_MASK" },
633428d7b3dSmrg	};
634428d7b3dSmrg	uint32_t *data = kgem->batch + offset;
635428d7b3dSmrg	uint32_t op;
636428d7b3dSmrg	unsigned int len;
637428d7b3dSmrg	int i, j;
638428d7b3dSmrg	const char *desc1 = NULL;
639428d7b3dSmrg
640428d7b3dSmrg	len = (data[0] & 0xff) + 2;
641428d7b3dSmrg	op = (data[0] & 0xffff0000) >> 16;
642428d7b3dSmrg	switch (op) {
643428d7b3dSmrg	case 0x6101:
644428d7b3dSmrg		i = 0;
645428d7b3dSmrg		kgem_debug_print(data, offset, i++, "STATE_BASE_ADDRESS\n");
646428d7b3dSmrg		if (kgem->gen >= 060) {
647428d7b3dSmrg			assert(len == 10);
648428d7b3dSmrg
649428d7b3dSmrg			state_base_out(data, offset, i++, "general");
650428d7b3dSmrg			state_base_out(data, offset, i++, "surface");
651428d7b3dSmrg			state_base_out(data, offset, i++, "dynamic");
652428d7b3dSmrg			state_base_out(data, offset, i++, "indirect");
653428d7b3dSmrg			state_base_out(data, offset, i++, "instruction");
654428d7b3dSmrg
655428d7b3dSmrg			state_max_out(data, offset, i++, "general");
656428d7b3dSmrg			state_max_out(data, offset, i++, "dynamic");
657428d7b3dSmrg			state_max_out(data, offset, i++, "indirect");
658428d7b3dSmrg			state_max_out(data, offset, i++, "instruction");
659428d7b3dSmrg
660428d7b3dSmrg			gen6_update_dynamic_buffer(kgem, offset + 3);
661428d7b3dSmrg		} else if (kgem->gen >= 050) {
662428d7b3dSmrg			assert(len == 8);
663428d7b3dSmrg
664428d7b3dSmrg			state_base_out(data, offset, i++, "general");
665428d7b3dSmrg			state_base_out(data, offset, i++, "surface");
666428d7b3dSmrg			state_base_out(data, offset, i++, "media");
667428d7b3dSmrg			state_base_out(data, offset, i++, "instruction");
668428d7b3dSmrg
669428d7b3dSmrg			state_max_out(data, offset, i++, "general");
670428d7b3dSmrg			state_max_out(data, offset, i++, "media");
671428d7b3dSmrg			state_max_out(data, offset, i++, "instruction");
672428d7b3dSmrg		}
673428d7b3dSmrg
674428d7b3dSmrg		return len;
675428d7b3dSmrg
676428d7b3dSmrg	case 0x7801:
677428d7b3dSmrg		if (kgem->gen >= 060) {
678428d7b3dSmrg			assert(len == 4);
679428d7b3dSmrg
680428d7b3dSmrg			kgem_debug_print(data, offset, 0,
681428d7b3dSmrg				  "3DSTATE_BINDING_TABLE_POINTERS: VS mod %d, "
682428d7b3dSmrg				  "GS mod %d, WM mod %d\n",
683428d7b3dSmrg				  (data[0] & (1 << 8)) != 0,
684428d7b3dSmrg				  (data[0] & (1 << 9)) != 0,
685428d7b3dSmrg				  (data[0] & (1 << 12)) != 0);
686428d7b3dSmrg			kgem_debug_print(data, offset, 1, "VS binding table\n");
687428d7b3dSmrg			kgem_debug_print(data, offset, 2, "GS binding table\n");
688428d7b3dSmrg			kgem_debug_print(data, offset, 3, "WM binding table\n");
689428d7b3dSmrg		} else if (kgem->gen >= 040) {
690428d7b3dSmrg			assert(len == 6);
691428d7b3dSmrg
692428d7b3dSmrg			kgem_debug_print(data, offset, 0,
693428d7b3dSmrg				  "3DSTATE_BINDING_TABLE_POINTERS\n");
694428d7b3dSmrg			kgem_debug_print(data, offset, 1, "VS binding table\n");
695428d7b3dSmrg			kgem_debug_print(data, offset, 2, "GS binding table\n");
696428d7b3dSmrg			kgem_debug_print(data, offset, 3, "CLIP binding table\n");
697428d7b3dSmrg			kgem_debug_print(data, offset, 4, "SF binding table\n");
698428d7b3dSmrg			kgem_debug_print(data, offset, 5, "WM binding table\n");
699428d7b3dSmrg		}
700428d7b3dSmrg
701428d7b3dSmrg		return len;
702428d7b3dSmrg
703428d7b3dSmrg	case 0x7802:
704428d7b3dSmrg		assert(len == 4);
705428d7b3dSmrg		kgem_debug_print(data, offset, 0, "3DSTATE_SAMPLER_STATE_POINTERS: VS mod %d, "
706428d7b3dSmrg			  "GS mod %d, WM mod %d\n",
707428d7b3dSmrg			  (data[0] & (1 << 8)) != 0,
708428d7b3dSmrg			  (data[0] & (1 << 9)) != 0,
709428d7b3dSmrg			  (data[0] & (1 << 12)) != 0);
710428d7b3dSmrg		kgem_debug_print(data, offset, 1, "VS sampler state\n");
711428d7b3dSmrg		kgem_debug_print(data, offset, 2, "GS sampler state\n");
712428d7b3dSmrg		kgem_debug_print(data, offset, 3, "WM sampler state\n");
713428d7b3dSmrg		gen6_decode_sampler_state(kgem, &data[3]);
714428d7b3dSmrg		return len;
715428d7b3dSmrg
716428d7b3dSmrg	case 0x7808:
717428d7b3dSmrg		assert((len - 1) % 4 == 0);
718428d7b3dSmrg		kgem_debug_print(data, offset, 0, "3DSTATE_VERTEX_BUFFERS\n");
719428d7b3dSmrg
720428d7b3dSmrg		for (i = 1; i < len;) {
721428d7b3dSmrg			gen6_update_vertex_buffer(kgem, data + i);
722428d7b3dSmrg
723428d7b3dSmrg			kgem_debug_print(data, offset, i, "buffer %d: %s, pitch %db\n",
724428d7b3dSmrg				  data[i] >> 26,
725428d7b3dSmrg				  data[i] & (1 << 20) ? "random" : "sequential",
726428d7b3dSmrg				  data[i] & 0x07ff);
727428d7b3dSmrg			i++;
728428d7b3dSmrg			kgem_debug_print(data, offset, i++, "buffer address\n");
729428d7b3dSmrg			kgem_debug_print(data, offset, i++, "max index\n");
730428d7b3dSmrg			kgem_debug_print(data, offset, i++, "mbz\n");
731428d7b3dSmrg		}
732428d7b3dSmrg		return len;
733428d7b3dSmrg
734428d7b3dSmrg	case 0x7809:
735428d7b3dSmrg		assert((len + 1) % 2 == 0);
736428d7b3dSmrg		kgem_debug_print(data, offset, 0, "3DSTATE_VERTEX_ELEMENTS\n");
737428d7b3dSmrg
738428d7b3dSmrg		for (i = 1; i < len;) {
739428d7b3dSmrg			gen6_update_vertex_elements(kgem, (i - 1)/2, data + i);
740428d7b3dSmrg
741428d7b3dSmrg			kgem_debug_print(data, offset, i, "buffer %d: %svalid, type 0x%04x, "
742428d7b3dSmrg				  "src offset 0x%04x bytes\n",
743428d7b3dSmrg				  data[i] >> 26,
744428d7b3dSmrg				  data[i] & (1 << 25) ? "" : "in",
745428d7b3dSmrg				  (data[i] >> 16) & 0x1ff,
746428d7b3dSmrg				  data[i] & 0x07ff);
747428d7b3dSmrg			i++;
748428d7b3dSmrg			kgem_debug_print(data, offset, i, "(%s, %s, %s, %s), "
749428d7b3dSmrg				  "dst offset 0x%02x bytes\n",
750428d7b3dSmrg				  get_965_element_component(data[i], 0),
751428d7b3dSmrg				  get_965_element_component(data[i], 1),
752428d7b3dSmrg				  get_965_element_component(data[i], 2),
753428d7b3dSmrg				  get_965_element_component(data[i], 3),
754428d7b3dSmrg				  (data[i] & 0xff) * 4);
755428d7b3dSmrg			i++;
756428d7b3dSmrg		}
757428d7b3dSmrg		return len;
758428d7b3dSmrg
759428d7b3dSmrg	case 0x780d:
760428d7b3dSmrg		assert(len == 4);
761428d7b3dSmrg		kgem_debug_print(data, offset, 0, "3DSTATE_VIEWPORT_STATE_POINTERS\n");
762428d7b3dSmrg		kgem_debug_print(data, offset, 1, "clip\n");
763428d7b3dSmrg		kgem_debug_print(data, offset, 2, "sf\n");
764428d7b3dSmrg		kgem_debug_print(data, offset, 3, "cc\n");
765428d7b3dSmrg		return len;
766428d7b3dSmrg
767428d7b3dSmrg	case 0x780a:
768428d7b3dSmrg		assert(len == 3);
769428d7b3dSmrg		kgem_debug_print(data, offset, 0, "3DSTATE_INDEX_BUFFER\n");
770428d7b3dSmrg		kgem_debug_print(data, offset, 1, "beginning buffer address\n");
771428d7b3dSmrg		kgem_debug_print(data, offset, 2, "ending buffer address\n");
772428d7b3dSmrg		return len;
773428d7b3dSmrg
774428d7b3dSmrg	case 0x780e:
775428d7b3dSmrg		assert(len == 4);
776428d7b3dSmrg		kgem_debug_print(data, offset, 0, "3DSTATE_CC_STATE_POINTERS\n");
777428d7b3dSmrg		kgem_debug_print(data, offset, 1, "blend%s\n",
778428d7b3dSmrg				 data[1] & 1 ? " update" : "");
779428d7b3dSmrg		if (data[1] & 1)
780428d7b3dSmrg			gen6_decode_blend(kgem, data+1);
781428d7b3dSmrg		kgem_debug_print(data, offset, 2, "depth+stencil%s\n",
782428d7b3dSmrg				 data[2] & 1 ? " update" : "");
783428d7b3dSmrg		kgem_debug_print(data, offset, 3, "cc%s\n",
784428d7b3dSmrg				 data[3] & 1 ? " update" : "");
785428d7b3dSmrg		return len;
786428d7b3dSmrg
787428d7b3dSmrg	case 0x780f:
788428d7b3dSmrg		assert(len == 2);
789428d7b3dSmrg		kgem_debug_print(data, offset, 0, "3DSTATE_SCISSOR_POINTERS\n");
790428d7b3dSmrg		kgem_debug_print(data, offset, 1, "scissor rect offset\n");
791428d7b3dSmrg		return len;
792428d7b3dSmrg
793428d7b3dSmrg	case 0x7810:
794428d7b3dSmrg		assert(len == 6);
795428d7b3dSmrg		kgem_debug_print(data, offset, 0, "3DSTATE_VS\n");
796428d7b3dSmrg		kgem_debug_print(data, offset, 1, "kernel pointer\n");
797428d7b3dSmrg		kgem_debug_print(data, offset, 2, "SPF=%d, VME=%d, Sampler Count %d, "
798428d7b3dSmrg			  "Binding table count %d\n",
799428d7b3dSmrg			  (data[2] >> 31) & 1,
800428d7b3dSmrg			  (data[2] >> 30) & 1,
801428d7b3dSmrg			  (data[2] >> 27) & 7,
802428d7b3dSmrg			  (data[2] >> 18) & 0xff);
803428d7b3dSmrg		kgem_debug_print(data, offset, 3, "scratch offset\n");
804428d7b3dSmrg		kgem_debug_print(data, offset, 4, "Dispatch GRF start %d, VUE read length %d, "
805428d7b3dSmrg			  "VUE read offset %d\n",
806428d7b3dSmrg			  (data[4] >> 20) & 0x1f,
807428d7b3dSmrg			  (data[4] >> 11) & 0x3f,
808428d7b3dSmrg			  (data[4] >> 4) & 0x3f);
809428d7b3dSmrg		kgem_debug_print(data, offset, 5, "Max Threads %d, Vertex Cache %sable, "
810428d7b3dSmrg			  "VS func %sable\n",
811428d7b3dSmrg			  ((data[5] >> 25) & 0x7f) + 1,
812428d7b3dSmrg			  (data[5] & (1 << 1)) != 0 ? "dis" : "en",
813428d7b3dSmrg			  (data[5] & 1) != 0 ? "en" : "dis");
814428d7b3dSmrg		return len;
815428d7b3dSmrg
816428d7b3dSmrg	case 0x7811:
817428d7b3dSmrg		assert(len == 7);
818428d7b3dSmrg		kgem_debug_print(data, offset, 0, "3DSTATE_GS\n");
819428d7b3dSmrg		kgem_debug_print(data, offset, 1, "kernel pointer\n");
820428d7b3dSmrg		kgem_debug_print(data, offset, 2, "SPF=%d, VME=%d, Sampler Count %d, "
821428d7b3dSmrg			  "Binding table count %d\n",
822428d7b3dSmrg			  (data[2] >> 31) & 1,
823428d7b3dSmrg			  (data[2] >> 30) & 1,
824428d7b3dSmrg			  (data[2] >> 27) & 7,
825428d7b3dSmrg			  (data[2] >> 18) & 0xff);
826428d7b3dSmrg		kgem_debug_print(data, offset, 3, "scratch offset\n");
827428d7b3dSmrg		kgem_debug_print(data, offset, 4, "Dispatch GRF start %d, VUE read length %d, "
828428d7b3dSmrg			  "VUE read offset %d\n",
829428d7b3dSmrg			  (data[4] & 0xf),
830428d7b3dSmrg			  (data[4] >> 11) & 0x3f,
831428d7b3dSmrg			  (data[4] >> 4) & 0x3f);
832428d7b3dSmrg		kgem_debug_print(data, offset, 5, "Max Threads %d, Rendering %sable\n",
833428d7b3dSmrg			  ((data[5] >> 25) & 0x7f) + 1,
834428d7b3dSmrg			  (data[5] & (1 << 8)) != 0 ? "en" : "dis");
835428d7b3dSmrg		kgem_debug_print(data, offset, 6, "Reorder %sable, Discard Adjaceny %sable, "
836428d7b3dSmrg			  "GS %sable\n",
837428d7b3dSmrg			  (data[6] & (1 << 30)) != 0 ? "en" : "dis",
838428d7b3dSmrg			  (data[6] & (1 << 29)) != 0 ? "en" : "dis",
839428d7b3dSmrg			  (data[6] & (1 << 15)) != 0 ? "en" : "dis");
840428d7b3dSmrg		return len;
841428d7b3dSmrg
842428d7b3dSmrg	case 0x7812:
843428d7b3dSmrg		assert(len == 4);
844428d7b3dSmrg		kgem_debug_print(data, offset, 0, "3DSTATE_CLIP\n");
845428d7b3dSmrg		kgem_debug_print(data, offset, 1, "UserClip distance cull test mask 0x%x\n",
846428d7b3dSmrg			  data[1] & 0xff);
847428d7b3dSmrg		kgem_debug_print(data, offset, 2, "Clip %sable, API mode %s, Viewport XY test %sable, "
848428d7b3dSmrg			  "Viewport Z test %sable, Guardband test %sable, Clip mode %d, "
849428d7b3dSmrg			  "Perspective Divide %sable, Non-Perspective Barycentric %sable, "
850428d7b3dSmrg			  "Tri Provoking %d, Line Provoking %d, Trifan Provoking %d\n",
851428d7b3dSmrg			  (data[2] & (1 << 31)) != 0 ? "en" : "dis",
852428d7b3dSmrg			  (data[2] & (1 << 30)) != 0 ? "D3D" : "OGL",
853428d7b3dSmrg			  (data[2] & (1 << 28)) != 0 ? "en" : "dis",
854428d7b3dSmrg			  (data[2] & (1 << 27)) != 0 ? "en" : "dis",
855428d7b3dSmrg			  (data[2] & (1 << 26)) != 0 ? "en" : "dis",
856428d7b3dSmrg			  (data[2] >> 13) & 7,
857428d7b3dSmrg			  (data[2] & (1 << 9)) != 0 ? "dis" : "en",
858428d7b3dSmrg			  (data[2] & (1 << 8)) != 0 ? "en" : "dis",
859428d7b3dSmrg			  (data[2] >> 4) & 3,
860428d7b3dSmrg			  (data[2] >> 2) & 3,
861428d7b3dSmrg			  (data[2] & 3));
862428d7b3dSmrg		kgem_debug_print(data, offset, 3, "Min PointWidth %d, Max PointWidth %d, "
863428d7b3dSmrg			  "Force Zero RTAIndex %sable, Max VPIndex %d\n",
864428d7b3dSmrg			  (data[3] >> 17) & 0x7ff,
865428d7b3dSmrg			  (data[3] >> 6) & 0x7ff,
866428d7b3dSmrg			  (data[3] & (1 << 5)) != 0 ? "en" : "dis",
867428d7b3dSmrg			  (data[3] & 0xf));
868428d7b3dSmrg		return len;
869428d7b3dSmrg
870428d7b3dSmrg	case 0x7813:
871428d7b3dSmrg		gen6_update_sf_state(kgem, data);
872428d7b3dSmrg		assert(len == 20);
873428d7b3dSmrg		kgem_debug_print(data, offset, 0, "3DSTATE_SF\n");
874428d7b3dSmrg		kgem_debug_print(data, offset, 1, "Attrib Out %d, Attrib Swizzle %sable, VUE read length %d, "
875428d7b3dSmrg			  "VUE read offset %d\n",
876428d7b3dSmrg			  (data[1] >> 22) & 0x3f,
877428d7b3dSmrg			  (data[1] & (1 << 21)) != 0 ? "en" : "dis",
878428d7b3dSmrg			  (data[1] >> 11) & 0x1f,
879428d7b3dSmrg			  (data[1] >> 4) & 0x3f);
880428d7b3dSmrg		kgem_debug_print(data, offset, 2, "Legacy Global DepthBias %sable, FrontFace fill %d, BF fill %d, "
881428d7b3dSmrg			  "VP transform %sable, FrontWinding_%s\n",
882428d7b3dSmrg			  (data[2] & (1 << 11)) != 0 ? "en" : "dis",
883428d7b3dSmrg			  (data[2] >> 5) & 3,
884428d7b3dSmrg			  (data[2] >> 3) & 3,
885428d7b3dSmrg			  (data[2] & (1 << 1)) != 0 ? "en" : "dis",
886428d7b3dSmrg			  (data[2] & 1) != 0 ? "CCW" : "CW");
887428d7b3dSmrg		kgem_debug_print(data, offset, 3, "AA %sable, CullMode %d, Scissor %sable, Multisample m ode %d\n",
888428d7b3dSmrg			  (data[3] & (1 << 31)) != 0 ? "en" : "dis",
889428d7b3dSmrg			  (data[3] >> 29) & 3,
890428d7b3dSmrg			  (data[3] & (1 << 11)) != 0 ? "en" : "dis",
891428d7b3dSmrg			  (data[3] >> 8) & 3);
892428d7b3dSmrg		kgem_debug_print(data, offset, 4, "Last Pixel %sable, SubPixel Precision %d, Use PixelWidth %d\n",
893428d7b3dSmrg			  (data[4] & (1 << 31)) != 0 ? "en" : "dis",
894428d7b3dSmrg			  (data[4] & (1 << 12)) != 0 ? 4 : 8,
895428d7b3dSmrg			  (data[4] & (1 << 11)) != 0);
896428d7b3dSmrg		kgem_debug_print(data, offset, 5, "Global Depth Offset Constant %f\n", unpack_float(data[5]));
897428d7b3dSmrg		kgem_debug_print(data, offset, 6, "Global Depth Offset Scale %f\n", unpack_float(data[6]));
898428d7b3dSmrg		kgem_debug_print(data, offset, 7, "Global Depth Offset Clamp %f\n", unpack_float(data[7]));
899428d7b3dSmrg		for (i = 0, j = 0; i < 8; i++, j+=2)
900428d7b3dSmrg			kgem_debug_print(data, offset, i+8, "Attrib %d (Override %s%s%s%s, Const Source %d, Swizzle Select %d, "
901428d7b3dSmrg				  "Source %d); Attrib %d (Override %s%s%s%s, Const Source %d, Swizzle Select %d, Source %d)\n",
902428d7b3dSmrg				  j+1,
903428d7b3dSmrg				  (data[8+i] & (1 << 31)) != 0 ? "W":"",
904428d7b3dSmrg				  (data[8+i] & (1 << 30)) != 0 ? "Z":"",
905428d7b3dSmrg				  (data[8+i] & (1 << 29)) != 0 ? "Y":"",
906428d7b3dSmrg				  (data[8+i] & (1 << 28)) != 0 ? "X":"",
907428d7b3dSmrg				  (data[8+i] >> 25) & 3, (data[8+i] >> 22) & 3,
908428d7b3dSmrg				  (data[8+i] >> 16) & 0x1f,
909428d7b3dSmrg				  j,
910428d7b3dSmrg				  (data[8+i] & (1 << 15)) != 0 ? "W":"",
911428d7b3dSmrg				  (data[8+i] & (1 << 14)) != 0 ? "Z":"",
912428d7b3dSmrg				  (data[8+i] & (1 << 13)) != 0 ? "Y":"",
913428d7b3dSmrg				  (data[8+i] & (1 << 12)) != 0 ? "X":"",
914428d7b3dSmrg				  (data[8+i] >> 9) & 3, (data[8+i] >> 6) & 3,
915428d7b3dSmrg				  (data[8+i] & 0x1f));
916428d7b3dSmrg		kgem_debug_print(data, offset, 16, "Point Sprite TexCoord Enable\n");
917428d7b3dSmrg		kgem_debug_print(data, offset, 17, "Const Interp Enable\n");
918428d7b3dSmrg		kgem_debug_print(data, offset, 18, "Attrib 7-0 WrapShortest Enable\n");
919428d7b3dSmrg		kgem_debug_print(data, offset, 19, "Attrib 15-8 WrapShortest Enable\n");
920428d7b3dSmrg
921428d7b3dSmrg		return len;
922428d7b3dSmrg
923428d7b3dSmrg	case 0x7814:
924428d7b3dSmrg		assert(len == 9);
925428d7b3dSmrg		kgem_debug_print(data, offset, 0, "3DSTATE_WM\n");
926428d7b3dSmrg		kgem_debug_print(data, offset, 1, "kernel start pointer 0\n");
927428d7b3dSmrg		kgem_debug_print(data, offset, 2, "SPF=%d, VME=%d, Sampler Count %d, "
928428d7b3dSmrg			  "Binding table count %d\n",
929428d7b3dSmrg			  (data[2] >> 31) & 1,
930428d7b3dSmrg			  (data[2] >> 30) & 1,
931428d7b3dSmrg			  (data[2] >> 27) & 7,
932428d7b3dSmrg			  (data[2] >> 18) & 0xff);
933428d7b3dSmrg		kgem_debug_print(data, offset, 3, "scratch offset\n");
934428d7b3dSmrg		kgem_debug_print(data, offset, 4, "Depth Clear %d, Depth Resolve %d, HiZ Resolve %d, "
935428d7b3dSmrg			  "Dispatch GRF start[0] %d, start[1] %d, start[2] %d\n",
936428d7b3dSmrg			  (data[4] & (1 << 30)) != 0,
937428d7b3dSmrg			  (data[4] & (1 << 28)) != 0,
938428d7b3dSmrg			  (data[4] & (1 << 27)) != 0,
939428d7b3dSmrg			  (data[4] >> 16) & 0x7f,
940428d7b3dSmrg			  (data[4] >> 8) & 0x7f,
941428d7b3dSmrg			  (data[4] & 0x7f));
942428d7b3dSmrg		kgem_debug_print(data, offset, 5, "MaxThreads %d, PS KillPixel %d, PS computed Z %d, "
943428d7b3dSmrg			  "PS use sourceZ %d, Thread Dispatch %d, PS use sourceW %d, Dispatch32 %d, "
944428d7b3dSmrg			  "Dispatch16 %d, Dispatch8 %d\n",
945428d7b3dSmrg			  ((data[5] >> 25) & 0x7f) + 1,
946428d7b3dSmrg			  (data[5] & (1 << 22)) != 0,
947428d7b3dSmrg			  (data[5] & (1 << 21)) != 0,
948428d7b3dSmrg			  (data[5] & (1 << 20)) != 0,
949428d7b3dSmrg			  (data[5] & (1 << 19)) != 0,
950428d7b3dSmrg			  (data[5] & (1 << 8)) != 0,
951428d7b3dSmrg			  (data[5] & (1 << 2)) != 0,
952428d7b3dSmrg			  (data[5] & (1 << 1)) != 0,
953428d7b3dSmrg			  (data[5] & (1 << 0)) != 0);
954428d7b3dSmrg		kgem_debug_print(data, offset, 6, "Num SF output %d, Pos XY offset %d, ZW interp mode %d , "
955428d7b3dSmrg			  "Barycentric interp mode 0x%x, Point raster rule %d, Multisample mode %d, "
956428d7b3dSmrg			  "Multisample Dispatch mode %d\n",
957428d7b3dSmrg			  (data[6] >> 20) & 0x3f,
958428d7b3dSmrg			  (data[6] >> 18) & 3,
959428d7b3dSmrg			  (data[6] >> 16) & 3,
960428d7b3dSmrg			  (data[6] >> 10) & 0x3f,
961428d7b3dSmrg			  (data[6] & (1 << 9)) != 0,
962428d7b3dSmrg			  (data[6] >> 1) & 3,
963428d7b3dSmrg			  (data[6] & 1));
964428d7b3dSmrg		kgem_debug_print(data, offset, 7, "kernel start pointer 1\n");
965428d7b3dSmrg		kgem_debug_print(data, offset, 8, "kernel start pointer 2\n");
966428d7b3dSmrg
967428d7b3dSmrg		return len;
968428d7b3dSmrg
969428d7b3dSmrg	case 0x7900:
970428d7b3dSmrg		assert(len == 4);
971428d7b3dSmrg		kgem_debug_print(data, offset, 0,
972428d7b3dSmrg				 "3DSTATE_DRAWING_RECTANGLE\n");
973428d7b3dSmrg		kgem_debug_print(data, offset, 1, "top left: %d, %d\n",
974428d7b3dSmrg				 (uint16_t)(data[1] & 0xffff),
975428d7b3dSmrg				 (uint16_t)(data[1] >> 16));
976428d7b3dSmrg		kgem_debug_print(data, offset, 2, "bottom right: %d, %d\n",
977428d7b3dSmrg				 (uint16_t)(data[2] & 0xffff),
978428d7b3dSmrg				 (uint16_t)(data[2] >> 16));
979428d7b3dSmrg		kgem_debug_print(data, offset, 3, "origin: %d, %d\n",
980428d7b3dSmrg				 (int16_t)(data[3] & 0xffff),
981428d7b3dSmrg				 (int16_t)(data[3] >> 16));
982428d7b3dSmrg		return len;
983428d7b3dSmrg
984428d7b3dSmrg	case 0x7905:
985428d7b3dSmrg		assert(len == 7);
986428d7b3dSmrg		kgem_debug_print(data, offset, 0,
987428d7b3dSmrg			  "3DSTATE_DEPTH_BUFFER\n");
988428d7b3dSmrg		kgem_debug_print(data, offset, 1, "%s, %s, pitch = %d bytes, %stiled, HiZ %d, Seperate Stencil %d\n",
989428d7b3dSmrg			  get_965_surfacetype(data[1] >> 29),
990428d7b3dSmrg			  get_965_depthformat((data[1] >> 18) & 0x7),
991428d7b3dSmrg			  (data[1] & 0x0001ffff) + 1,
992428d7b3dSmrg			  data[1] & (1 << 27) ? "" : "not ",
993428d7b3dSmrg			  (data[1] & (1 << 22)) != 0,
994428d7b3dSmrg			  (data[1] & (1 << 21)) != 0);
995428d7b3dSmrg		kgem_debug_print(data, offset, 2, "depth offset\n");
996428d7b3dSmrg		kgem_debug_print(data, offset, 3, "%dx%d\n",
997428d7b3dSmrg			  ((data[3] & 0x0007ffc0) >> 6) + 1,
998428d7b3dSmrg			  ((data[3] & 0xfff80000) >> 19) + 1);
999428d7b3dSmrg		kgem_debug_print(data, offset, 4, "volume depth\n");
1000428d7b3dSmrg		kgem_debug_print(data, offset, 5, "\n");
1001428d7b3dSmrg		kgem_debug_print(data, offset, 6, "\n");
1002428d7b3dSmrg		return len;
1003428d7b3dSmrg
1004428d7b3dSmrg	case 0x7a00:
1005428d7b3dSmrg		assert(len == 4 || len == 5);
1006428d7b3dSmrg		switch ((data[1] >> 14) & 0x3) {
1007428d7b3dSmrg		case 0: desc1 = "no write"; break;
1008428d7b3dSmrg		case 1: desc1 = "qword write"; break;
1009428d7b3dSmrg		case 2: desc1 = "PS_DEPTH_COUNT write"; break;
1010428d7b3dSmrg		case 3: desc1 = "TIMESTAMP write"; break;
1011428d7b3dSmrg		}
1012428d7b3dSmrg		kgem_debug_print(data, offset, 0, "PIPE_CONTROL\n");
1013428d7b3dSmrg		kgem_debug_print(data, offset, 1,
1014428d7b3dSmrg			  "%s, %scs stall, %stlb invalidate, "
1015428d7b3dSmrg			  "%ssync gfdt, %sdepth stall, %sRC write flush, "
1016428d7b3dSmrg			  "%sinst flush, %sTC flush\n",
1017428d7b3dSmrg			  desc1,
1018428d7b3dSmrg			  data[1] & (1 << 20) ? "" : "no ",
1019428d7b3dSmrg			  data[1] & (1 << 18) ? "" : "no ",
1020428d7b3dSmrg			  data[1] & (1 << 17) ? "" : "no ",
1021428d7b3dSmrg			  data[1] & (1 << 13) ? "" : "no ",
1022428d7b3dSmrg			  data[1] & (1 << 12) ? "" : "no ",
1023428d7b3dSmrg			  data[1] & (1 << 11) ? "" : "no ",
1024428d7b3dSmrg			  data[1] & (1 << 10) ? "" : "no ");
1025428d7b3dSmrg		if (len == 5) {
1026428d7b3dSmrg			kgem_debug_print(data, offset, 2, "destination address\n");
1027428d7b3dSmrg			kgem_debug_print(data, offset, 3, "immediate dword low\n");
1028428d7b3dSmrg			kgem_debug_print(data, offset, 4, "immediate dword high\n");
1029428d7b3dSmrg		} else {
1030428d7b3dSmrg			for (i = 2; i < len; i++) {
1031428d7b3dSmrg				kgem_debug_print(data, offset, i, "\n");
1032428d7b3dSmrg			}
1033428d7b3dSmrg		}
1034428d7b3dSmrg		return len;
1035428d7b3dSmrg
1036428d7b3dSmrg	case 0x7b00:
1037428d7b3dSmrg		assert(len == 6);
1038428d7b3dSmrg		kgem_debug_print(data, offset, 0,
1039428d7b3dSmrg			  "3DPRIMITIVE: %s %s\n",
1040428d7b3dSmrg			  get_965_prim_type(data[0]),
1041428d7b3dSmrg			  (data[0] & (1 << 15)) ? "random" : "sequential");
1042428d7b3dSmrg		kgem_debug_print(data, offset, 1, "vertex count\n");
1043428d7b3dSmrg		kgem_debug_print(data, offset, 2, "start vertex\n");
1044428d7b3dSmrg		kgem_debug_print(data, offset, 3, "instance count\n");
1045428d7b3dSmrg		kgem_debug_print(data, offset, 4, "start instance\n");
1046428d7b3dSmrg		kgem_debug_print(data, offset, 5, "index bias\n");
1047428d7b3dSmrg		primitive_out(kgem, data);
1048428d7b3dSmrg		return len;
1049428d7b3dSmrg	}
1050428d7b3dSmrg
1051428d7b3dSmrg	/* For the rest, just dump the bytes */
1052428d7b3dSmrg	for (i = 0; i < ARRAY_SIZE(opcodes); i++)
1053428d7b3dSmrg		if (op == opcodes[i].opcode)
1054428d7b3dSmrg			break;
1055428d7b3dSmrg
1056428d7b3dSmrg	assert(i < ARRAY_SIZE(opcodes));
1057428d7b3dSmrg
1058428d7b3dSmrg	len = 1;
1059428d7b3dSmrg	kgem_debug_print(data, offset, 0, "%s\n", opcodes[i].name);
1060428d7b3dSmrg	if (opcodes[i].max_len > 1) {
1061428d7b3dSmrg		len = (data[0] & 0xff) + 2;
1062428d7b3dSmrg		assert(len >= opcodes[i].min_len &&
1063428d7b3dSmrg		       len <= opcodes[i].max_len);
1064428d7b3dSmrg	}
1065428d7b3dSmrg
1066428d7b3dSmrg	for (i = 1; i < len; i++)
1067428d7b3dSmrg		kgem_debug_print(data, offset, i, "dword %d\n", i);
1068428d7b3dSmrg
1069428d7b3dSmrg	return len;
1070428d7b3dSmrg}
1071428d7b3dSmrg
1072428d7b3dSmrgvoid kgem_gen6_finish_state(struct kgem *kgem)
1073428d7b3dSmrg{
1074428d7b3dSmrg	finish_state(kgem);
1075428d7b3dSmrg}
1076