1/**************************************************************************
2
3Copyright 2002 ATI Technologies Inc., Ontario, Canada, and
4                     VMware, Inc.
5
6All Rights Reserved.
7
8Permission is hereby granted, free of charge, to any person obtaining a
9copy of this software and associated documentation files (the "Software"),
10to deal in the Software without restriction, including without limitation
11on the rights to use, copy, modify, merge, publish, distribute, sub
12license, and/or sell copies of the Software, and to permit persons to whom
13the Software is furnished to do so, subject to the following conditions:
14
15The above copyright notice and this permission notice (including the next
16paragraph) shall be included in all copies or substantial portions of the
17Software.
18
19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
22ATI, VMWARE AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
23DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
25USE OR OTHER DEALINGS IN THE SOFTWARE.
26
27**************************************************************************/
28
29/*
30 * Authors:
31 *   Keith Whitwell <keithw@vmware.com>
32 *
33 */
34#include <errno.h>
35
36#include "main/glheader.h"
37
38#include "radeon_context.h"
39#include "radeon_sanity.h"
40
41/* Set this '1' to get more verbiage.
42 */
43#define MORE_VERBOSE 1
44
45#if MORE_VERBOSE
46#define VERBOSE (RADEON_DEBUG & RADEON_VERBOSE)
47#define NORMAL  (1)
48#else
49#define VERBOSE 0
50#define NORMAL  (RADEON_DEBUG & RADEON_VERBOSE)
51#endif
52
53
54/* New (1.3) state mechanism.  3 commands (packet, scalar, vector) in
55 * 1.3 cmdbuffers allow all previous state to be updated as well as
56 * the tcl scalar and vector areas.
57 */
58static struct {
59   int start;
60   int len;
61   const char *name;
62} packet[RADEON_MAX_STATE_PACKETS] = {
63   { RADEON_PP_MISC,7,"RADEON_PP_MISC" },
64   { RADEON_PP_CNTL,3,"RADEON_PP_CNTL" },
65   { RADEON_RB3D_COLORPITCH,1,"RADEON_RB3D_COLORPITCH" },
66   { RADEON_RE_LINE_PATTERN,2,"RADEON_RE_LINE_PATTERN" },
67   { RADEON_SE_LINE_WIDTH,1,"RADEON_SE_LINE_WIDTH" },
68   { RADEON_PP_LUM_MATRIX,1,"RADEON_PP_LUM_MATRIX" },
69   { RADEON_PP_ROT_MATRIX_0,2,"RADEON_PP_ROT_MATRIX_0" },
70   { RADEON_RB3D_STENCILREFMASK,3,"RADEON_RB3D_STENCILREFMASK" },
71   { RADEON_SE_VPORT_XSCALE,6,"RADEON_SE_VPORT_XSCALE" },
72   { RADEON_SE_CNTL,2,"RADEON_SE_CNTL" },
73   { RADEON_SE_CNTL_STATUS,1,"RADEON_SE_CNTL_STATUS" },
74   { RADEON_RE_MISC,1,"RADEON_RE_MISC" },
75   { RADEON_PP_TXFILTER_0,6,"RADEON_PP_TXFILTER_0" },
76   { RADEON_PP_BORDER_COLOR_0,1,"RADEON_PP_BORDER_COLOR_0" },
77   { RADEON_PP_TXFILTER_1,6,"RADEON_PP_TXFILTER_1" },
78   { RADEON_PP_BORDER_COLOR_1,1,"RADEON_PP_BORDER_COLOR_1" },
79   { RADEON_PP_TXFILTER_2,6,"RADEON_PP_TXFILTER_2" },
80   { RADEON_PP_BORDER_COLOR_2,1,"RADEON_PP_BORDER_COLOR_2" },
81   { RADEON_SE_ZBIAS_FACTOR,2,"RADEON_SE_ZBIAS_FACTOR" },
82   { RADEON_SE_TCL_OUTPUT_VTX_FMT,11,"RADEON_SE_TCL_OUTPUT_VTX_FMT" },
83   { RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED,17,"RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED" },
84	{ 0, 4, "R200_PP_TXCBLEND_0" },
85	{ 0, 4, "R200_PP_TXCBLEND_1" },
86	{ 0, 4, "R200_PP_TXCBLEND_2" },
87	{ 0, 4, "R200_PP_TXCBLEND_3" },
88	{ 0, 4, "R200_PP_TXCBLEND_4" },
89	{ 0, 4, "R200_PP_TXCBLEND_5" },
90	{ 0, 4, "R200_PP_TXCBLEND_6" },
91	{ 0, 4, "R200_PP_TXCBLEND_7" },
92	{ 0, 6, "R200_SE_TCL_LIGHT_MODEL_CTL_0" },
93	{ 0, 6, "R200_PP_TFACTOR_0" },
94	{ 0, 4, "R200_SE_VTX_FMT_0" },
95	{ 0, 1, "R200_SE_VAP_CNTL" },
96	{ 0, 5, "R200_SE_TCL_MATRIX_SEL_0" },
97	{ 0, 5, "R200_SE_TCL_TEX_PROC_CTL_2" },
98	{ 0, 1, "R200_SE_TCL_UCP_VERT_BLEND_CTL" },
99	{ 0, 6, "R200_PP_TXFILTER_0" },
100	{ 0, 6, "R200_PP_TXFILTER_1" },
101	{ 0, 6, "R200_PP_TXFILTER_2" },
102	{ 0, 6, "R200_PP_TXFILTER_3" },
103	{ 0, 6, "R200_PP_TXFILTER_4" },
104	{ 0, 6, "R200_PP_TXFILTER_5" },
105	{ 0, 1, "R200_PP_TXOFFSET_0" },
106	{ 0, 1, "R200_PP_TXOFFSET_1" },
107	{ 0, 1, "R200_PP_TXOFFSET_2" },
108	{ 0, 1, "R200_PP_TXOFFSET_3" },
109	{ 0, 1, "R200_PP_TXOFFSET_4" },
110	{ 0, 1, "R200_PP_TXOFFSET_5" },
111	{ 0, 1, "R200_SE_VTE_CNTL" },
112	{ 0, 1, "R200_SE_TCL_OUTPUT_VTX_COMP_SEL" },
113	{ 0, 1, "R200_PP_TAM_DEBUG3" },
114	{ 0, 1, "R200_PP_CNTL_X" },
115	{ 0, 1, "R200_RB3D_DEPTHXY_OFFSET" },
116	{ 0, 1, "R200_RE_AUX_SCISSOR_CNTL" },
117	{ 0, 2, "R200_RE_SCISSOR_TL_0" },
118	{ 0, 2, "R200_RE_SCISSOR_TL_1" },
119	{ 0, 2, "R200_RE_SCISSOR_TL_2" },
120	{ 0, 1, "R200_SE_VAP_CNTL_STATUS" },
121	{ 0, 1, "R200_SE_VTX_STATE_CNTL" },
122	{ 0, 1, "R200_RE_POINTSIZE" },
123	{ 0, 4, "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0" },
124	{ 0, 1, "R200_PP_CUBIC_FACES_0" }, /* 61 */
125	{ 0, 5, "R200_PP_CUBIC_OFFSET_F1_0" }, /* 62 */
126	{ 0, 1, "R200_PP_CUBIC_FACES_1" },
127	{ 0, 5, "R200_PP_CUBIC_OFFSET_F1_1" },
128	{ 0, 1, "R200_PP_CUBIC_FACES_2" },
129	{ 0, 5, "R200_PP_CUBIC_OFFSET_F1_2" },
130	{ 0, 1, "R200_PP_CUBIC_FACES_3" },
131	{ 0, 5, "R200_PP_CUBIC_OFFSET_F1_3" },
132	{ 0, 1, "R200_PP_CUBIC_FACES_4" },
133	{ 0, 5, "R200_PP_CUBIC_OFFSET_F1_4" },
134	{ 0, 1, "R200_PP_CUBIC_FACES_5" },
135	{ 0, 5, "R200_PP_CUBIC_OFFSET_F1_5" },
136   { RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0" },
137   { RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1" },
138   { RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_2" },
139	{ 0, 3, "R200_RB3D_BLENDCOLOR" },
140	{ 0, 1, "R200_SE_TCL_POINT_SPRITE_CNTL" },
141   { RADEON_PP_CUBIC_FACES_0, 1, "RADEON_PP_CUBIC_FACES_0" },
142   { RADEON_PP_CUBIC_OFFSET_T0_0, 5, "RADEON_PP_CUBIC_OFFSET_T0_0" },
143   { RADEON_PP_CUBIC_FACES_1, 1, "RADEON_PP_CUBIC_FACES_1" },
144   { RADEON_PP_CUBIC_OFFSET_T1_0, 5, "RADEON_PP_CUBIC_OFFSET_T1_0" },
145   { RADEON_PP_CUBIC_FACES_2, 1, "RADEON_PP_CUBIC_FACES_2" },
146   { RADEON_PP_CUBIC_OFFSET_T2_0, 5, "RADEON_PP_CUBIC_OFFSET_T2_0" },
147   { 0, 2, "R200_PP_TRI_PERF" },
148   { 0, 32, "R200_PP_AFS_0"},   /* 85 */
149   { 0, 32, "R200_PP_AFS_1"},
150   { 0, 8, "R200_ATF_TFACTOR"},
151   { 0, 8, "R200_PP_TXCTLALL_0"},
152   { 0, 8, "R200_PP_TXCTLALL_1"},
153   { 0, 8, "R200_PP_TXCTLALL_2"},
154   { 0, 8, "R200_PP_TXCTLALL_3"},
155   { 0, 8, "R200_PP_TXCTLALL_4"},
156   { 0, 8, "R200_PP_TXCTLALL_5"},
157   { 0, 2, "R200_VAP_PVS_CNTL"},
158};
159
160struct reg_names {
161   int idx;
162   const char *name;
163};
164
165static struct reg_names reg_names[] = {
166   { RADEON_PP_MISC, "RADEON_PP_MISC" },
167   { RADEON_PP_FOG_COLOR, "RADEON_PP_FOG_COLOR" },
168   { RADEON_RE_SOLID_COLOR, "RADEON_RE_SOLID_COLOR" },
169   { RADEON_RB3D_BLENDCNTL, "RADEON_RB3D_BLENDCNTL" },
170   { RADEON_RB3D_DEPTHOFFSET, "RADEON_RB3D_DEPTHOFFSET" },
171   { RADEON_RB3D_DEPTHPITCH, "RADEON_RB3D_DEPTHPITCH" },
172   { RADEON_RB3D_ZSTENCILCNTL, "RADEON_RB3D_ZSTENCILCNTL" },
173   { RADEON_PP_CNTL, "RADEON_PP_CNTL" },
174   { RADEON_RB3D_CNTL, "RADEON_RB3D_CNTL" },
175   { RADEON_RB3D_COLOROFFSET, "RADEON_RB3D_COLOROFFSET" },
176   { RADEON_RB3D_COLORPITCH, "RADEON_RB3D_COLORPITCH" },
177   { RADEON_SE_CNTL, "RADEON_SE_CNTL" },
178   { RADEON_SE_COORD_FMT, "RADEON_SE_COORDFMT" },
179   { RADEON_SE_CNTL_STATUS, "RADEON_SE_CNTL_STATUS" },
180   { RADEON_RE_LINE_PATTERN, "RADEON_RE_LINE_PATTERN" },
181   { RADEON_RE_LINE_STATE, "RADEON_RE_LINE_STATE" },
182   { RADEON_SE_LINE_WIDTH, "RADEON_SE_LINE_WIDTH" },
183   { RADEON_RB3D_STENCILREFMASK, "RADEON_RB3D_STENCILREFMASK" },
184   { RADEON_RB3D_ROPCNTL, "RADEON_RB3D_ROPCNTL" },
185   { RADEON_RB3D_PLANEMASK, "RADEON_RB3D_PLANEMASK" },
186   { RADEON_SE_VPORT_XSCALE, "RADEON_SE_VPORT_XSCALE" },
187   { RADEON_SE_VPORT_XOFFSET, "RADEON_SE_VPORT_XOFFSET" },
188   { RADEON_SE_VPORT_YSCALE, "RADEON_SE_VPORT_YSCALE" },
189   { RADEON_SE_VPORT_YOFFSET, "RADEON_SE_VPORT_YOFFSET" },
190   { RADEON_SE_VPORT_ZSCALE, "RADEON_SE_VPORT_ZSCALE" },
191   { RADEON_SE_VPORT_ZOFFSET, "RADEON_SE_VPORT_ZOFFSET" },
192   { RADEON_RE_MISC, "RADEON_RE_MISC" },
193   { RADEON_PP_TXFILTER_0, "RADEON_PP_TXFILTER_0" },
194   { RADEON_PP_TXFILTER_1, "RADEON_PP_TXFILTER_1" },
195   { RADEON_PP_TXFILTER_2, "RADEON_PP_TXFILTER_2" },
196   { RADEON_PP_TXFORMAT_0, "RADEON_PP_TXFORMAT_0" },
197   { RADEON_PP_TXFORMAT_1, "RADEON_PP_TXFORMAT_1" },
198   { RADEON_PP_TXFORMAT_2, "RADEON_PP_TXFORMAT_2" },
199   { RADEON_PP_TXOFFSET_0, "RADEON_PP_TXOFFSET_0" },
200   { RADEON_PP_TXOFFSET_1, "RADEON_PP_TXOFFSET_1" },
201   { RADEON_PP_TXOFFSET_2, "RADEON_PP_TXOFFSET_2" },
202   { RADEON_PP_TXCBLEND_0, "RADEON_PP_TXCBLEND_0" },
203   { RADEON_PP_TXCBLEND_1, "RADEON_PP_TXCBLEND_1" },
204   { RADEON_PP_TXCBLEND_2, "RADEON_PP_TXCBLEND_2" },
205   { RADEON_PP_TXABLEND_0, "RADEON_PP_TXABLEND_0" },
206   { RADEON_PP_TXABLEND_1, "RADEON_PP_TXABLEND_1" },
207   { RADEON_PP_TXABLEND_2, "RADEON_PP_TXABLEND_2" },
208   { RADEON_PP_TFACTOR_0, "RADEON_PP_TFACTOR_0" },
209   { RADEON_PP_TFACTOR_1, "RADEON_PP_TFACTOR_1" },
210   { RADEON_PP_TFACTOR_2, "RADEON_PP_TFACTOR_2" },
211   { RADEON_PP_BORDER_COLOR_0, "RADEON_PP_BORDER_COLOR_0" },
212   { RADEON_PP_BORDER_COLOR_1, "RADEON_PP_BORDER_COLOR_1" },
213   { RADEON_PP_BORDER_COLOR_2, "RADEON_PP_BORDER_COLOR_2" },
214   { RADEON_SE_ZBIAS_FACTOR, "RADEON_SE_ZBIAS_FACTOR" },
215   { RADEON_SE_ZBIAS_CONSTANT, "RADEON_SE_ZBIAS_CONSTANT" },
216   { RADEON_SE_TCL_OUTPUT_VTX_FMT, "RADEON_SE_TCL_OUTPUT_VTXFMT" },
217   { RADEON_SE_TCL_OUTPUT_VTX_SEL, "RADEON_SE_TCL_OUTPUT_VTXSEL" },
218   { RADEON_SE_TCL_MATRIX_SELECT_0, "RADEON_SE_TCL_MATRIX_SELECT_0" },
219   { RADEON_SE_TCL_MATRIX_SELECT_1, "RADEON_SE_TCL_MATRIX_SELECT_1" },
220   { RADEON_SE_TCL_UCP_VERT_BLEND_CTL, "RADEON_SE_TCL_UCP_VERT_BLEND_CTL" },
221   { RADEON_SE_TCL_TEXTURE_PROC_CTL, "RADEON_SE_TCL_TEXTURE_PROC_CTL" },
222   { RADEON_SE_TCL_LIGHT_MODEL_CTL, "RADEON_SE_TCL_LIGHT_MODEL_CTL" },
223   { RADEON_SE_TCL_PER_LIGHT_CTL_0, "RADEON_SE_TCL_PER_LIGHT_CTL_0" },
224   { RADEON_SE_TCL_PER_LIGHT_CTL_1, "RADEON_SE_TCL_PER_LIGHT_CTL_1" },
225   { RADEON_SE_TCL_PER_LIGHT_CTL_2, "RADEON_SE_TCL_PER_LIGHT_CTL_2" },
226   { RADEON_SE_TCL_PER_LIGHT_CTL_3, "RADEON_SE_TCL_PER_LIGHT_CTL_3" },
227   { RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, "RADEON_SE_TCL_EMMISSIVE_RED" },
228   { RADEON_SE_TCL_MATERIAL_EMMISSIVE_GREEN, "RADEON_SE_TCL_EMMISSIVE_GREEN" },
229   { RADEON_SE_TCL_MATERIAL_EMMISSIVE_BLUE, "RADEON_SE_TCL_EMMISSIVE_BLUE" },
230   { RADEON_SE_TCL_MATERIAL_EMMISSIVE_ALPHA, "RADEON_SE_TCL_EMMISSIVE_ALPHA" },
231   { RADEON_SE_TCL_MATERIAL_AMBIENT_RED, "RADEON_SE_TCL_AMBIENT_RED" },
232   { RADEON_SE_TCL_MATERIAL_AMBIENT_GREEN, "RADEON_SE_TCL_AMBIENT_GREEN" },
233   { RADEON_SE_TCL_MATERIAL_AMBIENT_BLUE, "RADEON_SE_TCL_AMBIENT_BLUE" },
234   { RADEON_SE_TCL_MATERIAL_AMBIENT_ALPHA, "RADEON_SE_TCL_AMBIENT_ALPHA" },
235   { RADEON_SE_TCL_MATERIAL_DIFFUSE_RED, "RADEON_SE_TCL_DIFFUSE_RED" },
236   { RADEON_SE_TCL_MATERIAL_DIFFUSE_GREEN, "RADEON_SE_TCL_DIFFUSE_GREEN" },
237   { RADEON_SE_TCL_MATERIAL_DIFFUSE_BLUE, "RADEON_SE_TCL_DIFFUSE_BLUE" },
238   { RADEON_SE_TCL_MATERIAL_DIFFUSE_ALPHA, "RADEON_SE_TCL_DIFFUSE_ALPHA" },
239   { RADEON_SE_TCL_MATERIAL_SPECULAR_RED, "RADEON_SE_TCL_SPECULAR_RED" },
240   { RADEON_SE_TCL_MATERIAL_SPECULAR_GREEN, "RADEON_SE_TCL_SPECULAR_GREEN" },
241   { RADEON_SE_TCL_MATERIAL_SPECULAR_BLUE, "RADEON_SE_TCL_SPECULAR_BLUE" },
242   { RADEON_SE_TCL_MATERIAL_SPECULAR_ALPHA, "RADEON_SE_TCL_SPECULAR_ALPHA" },
243   { RADEON_SE_TCL_SHININESS, "RADEON_SE_TCL_SHININESS" },
244   { RADEON_SE_COORD_FMT, "RADEON_SE_COORD_FMT" },
245   { RADEON_PP_TEX_SIZE_0, "RADEON_PP_TEX_SIZE_0" },
246   { RADEON_PP_TEX_SIZE_1, "RADEON_PP_TEX_SIZE_1" },
247   { RADEON_PP_TEX_SIZE_2, "RADEON_PP_TEX_SIZE_2" },
248   { RADEON_PP_TEX_SIZE_0+4, "RADEON_PP_TEX_PITCH_0" },
249   { RADEON_PP_TEX_SIZE_1+4, "RADEON_PP_TEX_PITCH_1" },
250   { RADEON_PP_TEX_SIZE_2+4, "RADEON_PP_TEX_PITCH_2" },
251   { RADEON_PP_CUBIC_FACES_0, "RADEON_PP_CUBIC_FACES_0" },
252   { RADEON_PP_CUBIC_FACES_1, "RADEON_PP_CUBIC_FACES_1" },
253   { RADEON_PP_CUBIC_FACES_2, "RADEON_PP_CUBIC_FACES_2" },
254   { RADEON_PP_CUBIC_OFFSET_T0_0, "RADEON_PP_CUBIC_OFFSET_T0_0" },
255   { RADEON_PP_CUBIC_OFFSET_T0_1, "RADEON_PP_CUBIC_OFFSET_T0_1" },
256   { RADEON_PP_CUBIC_OFFSET_T0_2, "RADEON_PP_CUBIC_OFFSET_T0_2" },
257   { RADEON_PP_CUBIC_OFFSET_T0_3, "RADEON_PP_CUBIC_OFFSET_T0_3" },
258   { RADEON_PP_CUBIC_OFFSET_T0_4, "RADEON_PP_CUBIC_OFFSET_T0_4" },
259   { RADEON_PP_CUBIC_OFFSET_T1_0, "RADEON_PP_CUBIC_OFFSET_T1_0" },
260   { RADEON_PP_CUBIC_OFFSET_T1_1, "RADEON_PP_CUBIC_OFFSET_T1_1" },
261   { RADEON_PP_CUBIC_OFFSET_T1_2, "RADEON_PP_CUBIC_OFFSET_T1_2" },
262   { RADEON_PP_CUBIC_OFFSET_T1_3, "RADEON_PP_CUBIC_OFFSET_T1_3" },
263   { RADEON_PP_CUBIC_OFFSET_T1_4, "RADEON_PP_CUBIC_OFFSET_T1_4" },
264   { RADEON_PP_CUBIC_OFFSET_T2_0, "RADEON_PP_CUBIC_OFFSET_T2_0" },
265   { RADEON_PP_CUBIC_OFFSET_T2_1, "RADEON_PP_CUBIC_OFFSET_T2_1" },
266   { RADEON_PP_CUBIC_OFFSET_T2_2, "RADEON_PP_CUBIC_OFFSET_T2_2" },
267   { RADEON_PP_CUBIC_OFFSET_T2_3, "RADEON_PP_CUBIC_OFFSET_T2_3" },
268   { RADEON_PP_CUBIC_OFFSET_T2_4, "RADEON_PP_CUBIC_OFFSET_T2_4" },
269};
270
271static struct reg_names scalar_names[] = {
272   { RADEON_SS_LIGHT_DCD_ADDR, "LIGHT_DCD" },
273   { RADEON_SS_LIGHT_SPOT_EXPONENT_ADDR, "LIGHT_SPOT_EXPONENT" },
274   { RADEON_SS_LIGHT_SPOT_CUTOFF_ADDR, "LIGHT_SPOT_CUTOFF" },
275   { RADEON_SS_LIGHT_SPECULAR_THRESH_ADDR, "LIGHT_SPECULAR_THRESH" },
276   { RADEON_SS_LIGHT_RANGE_CUTOFF_ADDR, "LIGHT_RANGE_CUTOFF" },
277   { RADEON_SS_VERT_GUARD_CLIP_ADJ_ADDR, "VERT_GUARD_CLIP" },
278   { RADEON_SS_VERT_GUARD_DISCARD_ADJ_ADDR, "VERT_GUARD_DISCARD" },
279   { RADEON_SS_HORZ_GUARD_CLIP_ADJ_ADDR, "HORZ_GUARD_CLIP" },
280   { RADEON_SS_HORZ_GUARD_DISCARD_ADJ_ADDR, "HORZ_GUARD_DISCARD" },
281   { RADEON_SS_SHININESS, "SHININESS" },
282   { 1000, "" },
283};
284
285/* Puff these out to make them look like normal (dword) registers.
286 */
287static struct reg_names vector_names[] = {
288   { RADEON_VS_MATRIX_0_ADDR * 4, "MATRIX_0" },
289   { RADEON_VS_MATRIX_1_ADDR * 4, "MATRIX_1" },
290   { RADEON_VS_MATRIX_2_ADDR * 4, "MATRIX_2" },
291   { RADEON_VS_MATRIX_3_ADDR * 4, "MATRIX_3" },
292   { RADEON_VS_MATRIX_4_ADDR * 4, "MATRIX_4" },
293   { RADEON_VS_MATRIX_5_ADDR * 4, "MATRIX_5" },
294   { RADEON_VS_MATRIX_6_ADDR * 4, "MATRIX_6" },
295   { RADEON_VS_MATRIX_7_ADDR * 4, "MATRIX_7" },
296   { RADEON_VS_MATRIX_8_ADDR * 4, "MATRIX_8" },
297   { RADEON_VS_MATRIX_9_ADDR * 4, "MATRIX_9" },
298   { RADEON_VS_MATRIX_10_ADDR * 4, "MATRIX_10" },
299   { RADEON_VS_MATRIX_11_ADDR * 4, "MATRIX_11" },
300   { RADEON_VS_MATRIX_12_ADDR * 4, "MATRIX_12" },
301   { RADEON_VS_MATRIX_13_ADDR * 4, "MATRIX_13" },
302   { RADEON_VS_MATRIX_14_ADDR * 4, "MATRIX_14" },
303   { RADEON_VS_MATRIX_15_ADDR * 4, "MATRIX_15" },
304   { RADEON_VS_LIGHT_AMBIENT_ADDR * 4, "LIGHT_AMBIENT" },
305   { RADEON_VS_LIGHT_DIFFUSE_ADDR * 4, "LIGHT_DIFFUSE" },
306   { RADEON_VS_LIGHT_SPECULAR_ADDR * 4, "LIGHT_SPECULAR" },
307   { RADEON_VS_LIGHT_DIRPOS_ADDR * 4, "LIGHT_DIRPOS" },
308   { RADEON_VS_LIGHT_HWVSPOT_ADDR * 4, "LIGHT_HWVSPOT" },
309   { RADEON_VS_LIGHT_ATTENUATION_ADDR * 4, "LIGHT_ATTENUATION" },
310   { RADEON_VS_MATRIX_EYE2CLIP_ADDR * 4, "MATRIX_EYE2CLIP" },
311   { RADEON_VS_UCP_ADDR * 4, "UCP" },
312   { RADEON_VS_GLOBAL_AMBIENT_ADDR * 4, "GLOBAL_AMBIENT" },
313   { RADEON_VS_FOG_PARAM_ADDR * 4, "FOG_PARAM" },
314   { RADEON_VS_EYE_VECTOR_ADDR * 4, "EYE_VECTOR" },
315   { 1000, "" },
316};
317
318#define ISVEC   1
319#define ISFLOAT 2
320#define TOUCHED 4
321
322struct reg {
323   int idx;
324   struct reg_names *closest;
325   int flags;
326   union fi current;
327   union fi *values;
328   int nvalues;
329   int nalloc;
330   float vmin, vmax;
331};
332
333
334static struct reg regs[ARRAY_SIZE(reg_names)+1];
335static struct reg scalars[512+1];
336static struct reg vectors[512*4+1];
337
338static int total, total_changed, bufs;
339
340static void init_regs( void )
341{
342   struct reg_names *tmp;
343   int i;
344
345   for (i = 0 ; i < ARRAY_SIZE(regs)-1 ; i++) {
346      regs[i].idx = reg_names[i].idx;
347      regs[i].closest = &reg_names[i];
348      regs[i].flags = 0;
349   }
350
351   for (i = 0, tmp = scalar_names ; i < ARRAY_SIZE(scalars) ; i++) {
352      if (tmp[1].idx == i) tmp++;
353      scalars[i].idx = i;
354      scalars[i].closest = tmp;
355      scalars[i].flags = ISFLOAT;
356   }
357
358   for (i = 0, tmp = vector_names ; i < ARRAY_SIZE(vectors) ; i++) {
359      if (tmp[1].idx*4 == i) tmp++;
360      vectors[i].idx = i;
361      vectors[i].closest = tmp;
362      vectors[i].flags = ISFLOAT|ISVEC;
363   }
364
365   regs[ARRAY_SIZE(regs)-1].idx = -1;
366   scalars[ARRAY_SIZE(scalars)-1].idx = -1;
367   vectors[ARRAY_SIZE(vectors)-1].idx = -1;
368}
369
370static int find_or_add_value( struct reg *reg, int val )
371{
372   int j;
373
374   for ( j = 0 ; j < reg->nvalues ; j++)
375      if ( val == reg->values[j].i )
376	 return 1;
377
378   if (j == reg->nalloc) {
379      reg->nalloc += 5;
380      reg->nalloc *= 2;
381      reg->values = realloc( reg->values, reg->nalloc * sizeof(union fi) );
382   }
383
384   reg->values[reg->nvalues++].i = val;
385   return 0;
386}
387
388static struct reg *lookup_reg( struct reg *tab, int reg )
389{
390   int i;
391
392   for (i = 0 ; tab[i].idx != -1 ; i++) {
393      if (tab[i].idx == reg)
394	 return &tab[i];
395   }
396
397   fprintf(stderr, "*** unknown reg 0x%x\n", reg);
398   return NULL;
399}
400
401
402static const char *get_reg_name( struct reg *reg )
403{
404   static char tmp[80];
405
406   if (reg->idx == reg->closest->idx)
407      return reg->closest->name;
408
409
410   if (reg->flags & ISVEC) {
411      if (reg->idx/4 != reg->closest->idx)
412	 sprintf(tmp, "%s+%d[%d]",
413		 reg->closest->name,
414		 (reg->idx/4) - reg->closest->idx,
415		 reg->idx%4);
416      else
417	 sprintf(tmp, "%s[%d]", reg->closest->name, reg->idx%4);
418   }
419   else {
420      if (reg->idx != reg->closest->idx)
421	 sprintf(tmp, "%s+%d", reg->closest->name, reg->idx - reg->closest->idx);
422      else
423	 sprintf(tmp, "%s", reg->closest->name);
424   }
425
426   return tmp;
427}
428
429static int print_int_reg_assignment( struct reg *reg, int data )
430{
431   int changed = (reg->current.i != data);
432   int ever_seen = find_or_add_value( reg, data );
433
434   if (VERBOSE || (NORMAL && (changed || !ever_seen)))
435       fprintf(stderr, "   %s <-- 0x%x", get_reg_name(reg), data);
436
437   if (NORMAL) {
438      if (!ever_seen)
439	 fprintf(stderr, " *** BRAND NEW VALUE");
440      else if (changed)
441	 fprintf(stderr, " *** CHANGED");
442   }
443
444   reg->current.i = data;
445
446   if (VERBOSE || (NORMAL && (changed || !ever_seen)))
447      fprintf(stderr, "\n");
448
449   return changed;
450}
451
452
453static int print_float_reg_assignment( struct reg *reg, float data )
454{
455   int changed = (reg->current.f != data);
456   int newmin = (data < reg->vmin);
457   int newmax = (data > reg->vmax);
458
459   if (VERBOSE || (NORMAL && (newmin || newmax || changed)))
460      fprintf(stderr, "   %s <-- %.3f", get_reg_name(reg), data);
461
462   if (NORMAL) {
463      if (newmin) {
464	 fprintf(stderr, " *** NEW MIN (prev %.3f)", reg->vmin);
465	 reg->vmin = data;
466      }
467      else if (newmax) {
468	 fprintf(stderr, " *** NEW MAX (prev %.3f)", reg->vmax);
469	 reg->vmax = data;
470      }
471      else if (changed) {
472	 fprintf(stderr, " *** CHANGED");
473      }
474   }
475
476   reg->current.f = data;
477
478   if (VERBOSE || (NORMAL && (newmin || newmax || changed)))
479      fprintf(stderr, "\n");
480
481   return changed;
482}
483
484static int print_reg_assignment( struct reg *reg, int data )
485{
486   float_ui32_type datau;
487   datau.ui32 = data;
488   reg->flags |= TOUCHED;
489   if (reg->flags & ISFLOAT)
490      return print_float_reg_assignment( reg, datau.f );
491   else
492      return print_int_reg_assignment( reg, data );
493}
494
495static void print_reg( struct reg *reg )
496{
497   if (reg->flags & TOUCHED) {
498      if (reg->flags & ISFLOAT) {
499	 fprintf(stderr, "   %s == %f\n", get_reg_name(reg), reg->current.f);
500      } else {
501	 fprintf(stderr, "   %s == 0x%x\n", get_reg_name(reg), reg->current.i);
502      }
503   }
504}
505
506
507static void dump_state( void )
508{
509   int i;
510
511   for (i = 0 ; i < ARRAY_SIZE(regs) ; i++)
512      print_reg( &regs[i] );
513
514   for (i = 0 ; i < ARRAY_SIZE(scalars) ; i++)
515      print_reg( &scalars[i] );
516
517   for (i = 0 ; i < ARRAY_SIZE(vectors) ; i++)
518      print_reg( &vectors[i] );
519}
520
521
522
523static int radeon_emit_packets(
524   drm_radeon_cmd_header_t header,
525   drm_radeon_cmd_buffer_t *cmdbuf )
526{
527   int id = (int)header.packet.packet_id;
528   int sz = packet[id].len;
529   int *data = (int *)cmdbuf->buf;
530   int i;
531
532   if (sz * sizeof(int) > cmdbuf->bufsz) {
533      fprintf(stderr, "Packet overflows cmdbuf\n");
534      return -EINVAL;
535   }
536
537   if (!packet[id].name) {
538      fprintf(stderr, "*** Unknown packet 0 nr %d\n", id );
539      return -EINVAL;
540   }
541
542
543   if (VERBOSE)
544      fprintf(stderr, "Packet 0 reg %s nr %d\n", packet[id].name, sz );
545
546   for ( i = 0 ; i < sz ; i++) {
547      struct reg *reg = lookup_reg( regs, packet[id].start + i*4 );
548      if (print_reg_assignment( reg, data[i] ))
549	 total_changed++;
550      total++;
551   }
552
553   cmdbuf->buf += sz * sizeof(int);
554   cmdbuf->bufsz -= sz * sizeof(int);
555   return 0;
556}
557
558
559static int radeon_emit_scalars(
560   drm_radeon_cmd_header_t header,
561   drm_radeon_cmd_buffer_t *cmdbuf )
562{
563   int sz = header.scalars.count;
564   int *data = (int *)cmdbuf->buf;
565   int start = header.scalars.offset;
566   int stride = header.scalars.stride;
567   int i;
568
569   if (VERBOSE)
570      fprintf(stderr, "emit scalars, start %d stride %d nr %d (end %d)\n",
571	      start, stride, sz, start + stride * sz);
572
573
574   for (i = 0 ; i < sz ; i++, start += stride) {
575      struct reg *reg = lookup_reg( scalars, start );
576      if (print_reg_assignment( reg, data[i] ))
577	 total_changed++;
578      total++;
579   }
580
581   cmdbuf->buf += sz * sizeof(int);
582   cmdbuf->bufsz -= sz * sizeof(int);
583   return 0;
584}
585
586
587static int radeon_emit_scalars2(
588   drm_radeon_cmd_header_t header,
589   drm_radeon_cmd_buffer_t *cmdbuf )
590{
591   int sz = header.scalars.count;
592   int *data = (int *)cmdbuf->buf;
593   int start = header.scalars.offset + 0x100;
594   int stride = header.scalars.stride;
595   int i;
596
597   if (VERBOSE)
598      fprintf(stderr, "emit scalars2, start %d stride %d nr %d (end %d)\n",
599	      start, stride, sz, start + stride * sz);
600
601   if (start + stride * sz > 257) {
602      fprintf(stderr, "emit scalars OVERFLOW %d/%d/%d\n", start, stride, sz);
603      return -1;
604   }
605
606   for (i = 0 ; i < sz ; i++, start += stride) {
607      struct reg *reg = lookup_reg( scalars, start );
608      if (print_reg_assignment( reg, data[i] ))
609	 total_changed++;
610      total++;
611   }
612
613   cmdbuf->buf += sz * sizeof(int);
614   cmdbuf->bufsz -= sz * sizeof(int);
615   return 0;
616}
617
618/* Check: inf/nan/extreme-size?
619 * Check: table start, end, nr, etc.
620 */
621static int radeon_emit_vectors(
622   drm_radeon_cmd_header_t header,
623   drm_radeon_cmd_buffer_t *cmdbuf )
624{
625   int sz = header.vectors.count;
626   int *data = (int *)cmdbuf->buf;
627   int start = header.vectors.offset;
628   int stride = header.vectors.stride;
629   int i,j;
630
631   if (VERBOSE)
632      fprintf(stderr, "emit vectors, start %d stride %d nr %d (end %d) (0x%x)\n",
633	      start, stride, sz, start + stride * sz, header.i);
634
635/*    if (start + stride * (sz/4) > 128) { */
636/*       fprintf(stderr, "emit vectors OVERFLOW %d/%d/%d\n", start, stride, sz); */
637/*       return -1; */
638/*    } */
639
640   for (i = 0 ; i < sz ;  start += stride) {
641      int changed = 0;
642      for (j = 0 ; j < 4 ; i++,j++) {
643	 struct reg *reg = lookup_reg( vectors, start*4+j );
644	 if (print_reg_assignment( reg, data[i] ))
645	    changed = 1;
646      }
647      if (changed)
648	 total_changed += 4;
649      total += 4;
650   }
651
652
653   cmdbuf->buf += sz * sizeof(int);
654   cmdbuf->bufsz -= sz * sizeof(int);
655   return 0;
656}
657
658
659static int print_vertex_format( int vfmt )
660{
661   if (NORMAL) {
662      fprintf(stderr, "   %s(%x): %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
663	      "vertex format",
664	      vfmt,
665	      "xy,",
666	      (vfmt & RADEON_CP_VC_FRMT_Z) ? "z," : "",
667	      (vfmt & RADEON_CP_VC_FRMT_W0) ? "w0," : "",
668	      (vfmt & RADEON_CP_VC_FRMT_FPCOLOR) ? "fpcolor," : "",
669	      (vfmt & RADEON_CP_VC_FRMT_FPALPHA) ? "fpalpha," : "",
670	      (vfmt & RADEON_CP_VC_FRMT_PKCOLOR) ? "pkcolor," : "",
671	      (vfmt & RADEON_CP_VC_FRMT_FPSPEC) ? "fpspec," : "",
672	      (vfmt & RADEON_CP_VC_FRMT_FPFOG) ? "fpfog," : "",
673	      (vfmt & RADEON_CP_VC_FRMT_PKSPEC) ? "pkspec," : "",
674	      (vfmt & RADEON_CP_VC_FRMT_ST0) ? "st0," : "",
675	      (vfmt & RADEON_CP_VC_FRMT_ST1) ? "st1," : "",
676	      (vfmt & RADEON_CP_VC_FRMT_Q1) ? "q1," : "",
677	      (vfmt & RADEON_CP_VC_FRMT_ST2) ? "st2," : "",
678	      (vfmt & RADEON_CP_VC_FRMT_Q2) ? "q2," : "",
679	      (vfmt & RADEON_CP_VC_FRMT_ST3) ? "st3," : "",
680	      (vfmt & RADEON_CP_VC_FRMT_Q3) ? "q3," : "",
681	      (vfmt & RADEON_CP_VC_FRMT_Q0) ? "q0," : "",
682	      (vfmt & RADEON_CP_VC_FRMT_N0) ? "n0," : "",
683	      (vfmt & RADEON_CP_VC_FRMT_XY1) ? "xy1," : "",
684	      (vfmt & RADEON_CP_VC_FRMT_Z1) ? "z1," : "",
685	      (vfmt & RADEON_CP_VC_FRMT_W1) ? "w1," : "",
686	      (vfmt & RADEON_CP_VC_FRMT_N1) ? "n1," : "");
687
688
689/*       if (!find_or_add_value( &others[V_VTXFMT], vfmt )) */
690/* 	 fprintf(stderr, " *** NEW VALUE"); */
691
692      fprintf(stderr, "\n");
693   }
694
695   return 0;
696}
697
698static char *primname[0xf] = {
699   "NONE",
700   "POINTS",
701   "LINES",
702   "LINE_STRIP",
703   "TRIANGLES",
704   "TRIANGLE_FAN",
705   "TRIANGLE_STRIP",
706   "TRI_TYPE_2",
707   "RECT_LIST",
708   "3VRT_POINTS",
709   "3VRT_LINES",
710};
711
712static int print_prim_and_flags( int prim )
713{
714   int numverts;
715
716   if (NORMAL)
717      fprintf(stderr, "   %s(%x): %s%s%s%s%s%s%s\n",
718	      "prim flags",
719	      prim,
720	      ((prim & 0x30) == RADEON_CP_VC_CNTL_PRIM_WALK_IND) ? "IND," : "",
721	      ((prim & 0x30) == RADEON_CP_VC_CNTL_PRIM_WALK_LIST) ? "LIST," : "",
722	      ((prim & 0x30) == RADEON_CP_VC_CNTL_PRIM_WALK_RING) ? "RING," : "",
723	      (prim & RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA) ? "RGBA," : "BGRA, ",
724	      (prim & RADEON_CP_VC_CNTL_MAOS_ENABLE) ? "MAOS," : "",
725	      (prim & RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE) ? "RADEON," : "",
726	      (prim & RADEON_CP_VC_CNTL_TCL_ENABLE) ? "TCL," : "");
727
728   if ((prim & 0xf) > RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_LINE_LIST) {
729      fprintf(stderr, "   *** Bad primitive: %x\n", prim & 0xf);
730      return -1;
731   }
732
733   numverts = prim>>16;
734
735   if (NORMAL)
736      fprintf(stderr, "   prim: %s numverts %d\n", primname[prim&0xf], numverts);
737
738   switch (prim & 0xf) {
739   case RADEON_CP_VC_CNTL_PRIM_TYPE_NONE:
740   case RADEON_CP_VC_CNTL_PRIM_TYPE_POINT:
741      if (numverts < 1) {
742	 fprintf(stderr, "Bad nr verts for line %d\n", numverts);
743	 return -1;
744      }
745      break;
746   case RADEON_CP_VC_CNTL_PRIM_TYPE_LINE:
747      if ((numverts & 1) || numverts == 0) {
748	 fprintf(stderr, "Bad nr verts for line %d\n", numverts);
749	 return -1;
750      }
751      break;
752   case RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP:
753      if (numverts < 2) {
754	 fprintf(stderr, "Bad nr verts for line_strip %d\n", numverts);
755	 return -1;
756      }
757      break;
758   case RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST:
759   case RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_POINT_LIST:
760   case RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_LINE_LIST:
761   case RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST:
762      if (numverts % 3 || numverts == 0) {
763	 fprintf(stderr, "Bad nr verts for tri %d\n", numverts);
764	 return -1;
765      }
766      break;
767   case RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN:
768   case RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP:
769      if (numverts < 3) {
770	 fprintf(stderr, "Bad nr verts for strip/fan %d\n", numverts);
771	 return -1;
772      }
773      break;
774   default:
775      fprintf(stderr, "Bad primitive\n");
776      return -1;
777   }
778   return 0;
779}
780
781/* build in knowledge about each packet type
782 */
783static int radeon_emit_packet3( drm_radeon_cmd_buffer_t *cmdbuf )
784{
785   int cmdsz;
786   int *cmd = (int *)cmdbuf->buf;
787   int *tmp;
788   int i, stride, size, start;
789
790   cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16);
791
792   if ((cmd[0] & RADEON_CP_PACKET_MASK) != RADEON_CP_PACKET3 ||
793       cmdsz * 4 > cmdbuf->bufsz ||
794       cmdsz > RADEON_CP_PACKET_MAX_DWORDS) {
795      fprintf(stderr, "Bad packet\n");
796      return -EINVAL;
797   }
798
799   switch( cmd[0] & ~RADEON_CP_PACKET_COUNT_MASK ) {
800   case RADEON_CP_PACKET3_NOP:
801      if (NORMAL)
802	 fprintf(stderr, "PACKET3_NOP, %d dwords\n", cmdsz);
803      break;
804   case RADEON_CP_PACKET3_NEXT_CHAR:
805      if (NORMAL)
806	 fprintf(stderr, "PACKET3_NEXT_CHAR, %d dwords\n", cmdsz);
807      break;
808   case RADEON_CP_PACKET3_PLY_NEXTSCAN:
809      if (NORMAL)
810	 fprintf(stderr, "PACKET3_PLY_NEXTSCAN, %d dwords\n", cmdsz);
811      break;
812   case RADEON_CP_PACKET3_SET_SCISSORS:
813      if (NORMAL)
814	 fprintf(stderr, "PACKET3_SET_SCISSORS, %d dwords\n", cmdsz);
815      break;
816   case RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM:
817      if (NORMAL)
818	 fprintf(stderr, "PACKET3_3D_RNDR_GEN_INDX_PRIM, %d dwords\n",
819	      cmdsz);
820      break;
821   case RADEON_CP_PACKET3_LOAD_MICROCODE:
822      if (NORMAL)
823	 fprintf(stderr, "PACKET3_LOAD_MICROCODE, %d dwords\n", cmdsz);
824      break;
825   case RADEON_CP_PACKET3_WAIT_FOR_IDLE:
826      if (NORMAL)
827	 fprintf(stderr, "PACKET3_WAIT_FOR_IDLE, %d dwords\n", cmdsz);
828      break;
829
830   case RADEON_CP_PACKET3_3D_DRAW_VBUF:
831      if (NORMAL)
832	 fprintf(stderr, "PACKET3_3D_DRAW_VBUF, %d dwords\n", cmdsz);
833      print_vertex_format(cmd[1]);
834      print_prim_and_flags(cmd[2]);
835      break;
836
837   case RADEON_CP_PACKET3_3D_DRAW_IMMD:
838      if (NORMAL)
839	 fprintf(stderr, "PACKET3_3D_DRAW_IMMD, %d dwords\n", cmdsz);
840      break;
841   case RADEON_CP_PACKET3_3D_DRAW_INDX: {
842      int neltdwords;
843      if (NORMAL)
844	 fprintf(stderr, "PACKET3_3D_DRAW_INDX, %d dwords\n", cmdsz);
845      print_vertex_format(cmd[1]);
846      print_prim_and_flags(cmd[2]);
847      neltdwords = cmd[2]>>16;
848      neltdwords += neltdwords & 1;
849      neltdwords /= 2;
850      if (neltdwords + 3 != cmdsz)
851	 fprintf(stderr, "Mismatch in DRAW_INDX, %d vs cmdsz %d\n",
852		 neltdwords, cmdsz);
853      break;
854   }
855   case RADEON_CP_PACKET3_LOAD_PALETTE:
856      if (NORMAL)
857	 fprintf(stderr, "PACKET3_LOAD_PALETTE, %d dwords\n", cmdsz);
858      break;
859   case RADEON_CP_PACKET3_3D_LOAD_VBPNTR:
860      if (NORMAL) {
861	 fprintf(stderr, "PACKET3_3D_LOAD_VBPNTR, %d dwords\n", cmdsz);
862	 fprintf(stderr, "   nr arrays: %d\n", cmd[1]);
863      }
864
865      if (cmd[1]/2 + cmd[1]%2 != cmdsz - 3) {
866	 fprintf(stderr, "  ****** MISMATCH %d/%d *******\n",
867		 cmd[1]/2 + cmd[1]%2 + 3, cmdsz);
868	 return -EINVAL;
869      }
870
871      if (NORMAL) {
872	 tmp = cmd+2;
873	 for (i = 0 ; i < cmd[1] ; i++) {
874	    if (i & 1) {
875	       stride = (tmp[0]>>24) & 0xff;
876	       size = (tmp[0]>>16) & 0xff;
877	       start = tmp[2];
878	       tmp += 3;
879	    }
880	    else {
881	       stride = (tmp[0]>>8) & 0xff;
882	       size = (tmp[0]) & 0xff;
883	       start = tmp[1];
884	    }
885	    fprintf(stderr, "   array %d: start 0x%x vsize %d vstride %d\n",
886		    i, start, size, stride );
887	 }
888      }
889      break;
890   case RADEON_CP_PACKET3_CNTL_PAINT:
891      if (NORMAL)
892	 fprintf(stderr, "PACKET3_CNTL_PAINT, %d dwords\n", cmdsz);
893      break;
894   case RADEON_CP_PACKET3_CNTL_BITBLT:
895      if (NORMAL)
896	 fprintf(stderr, "PACKET3_CNTL_BITBLT, %d dwords\n", cmdsz);
897      break;
898   case RADEON_CP_PACKET3_CNTL_SMALLTEXT:
899      if (NORMAL)
900	 fprintf(stderr, "PACKET3_CNTL_SMALLTEXT, %d dwords\n", cmdsz);
901      break;
902   case RADEON_CP_PACKET3_CNTL_HOSTDATA_BLT:
903      if (NORMAL)
904	 fprintf(stderr, "PACKET3_CNTL_HOSTDATA_BLT, %d dwords\n",
905	      cmdsz);
906      break;
907   case RADEON_CP_PACKET3_CNTL_POLYLINE:
908      if (NORMAL)
909	 fprintf(stderr, "PACKET3_CNTL_POLYLINE, %d dwords\n", cmdsz);
910      break;
911   case RADEON_CP_PACKET3_CNTL_POLYSCANLINES:
912      if (NORMAL)
913	 fprintf(stderr, "PACKET3_CNTL_POLYSCANLINES, %d dwords\n",
914	      cmdsz);
915      break;
916   case RADEON_CP_PACKET3_CNTL_PAINT_MULTI:
917      if (NORMAL)
918	 fprintf(stderr, "PACKET3_CNTL_PAINT_MULTI, %d dwords\n",
919	      cmdsz);
920      break;
921   case RADEON_CP_PACKET3_CNTL_BITBLT_MULTI:
922      if (NORMAL)
923	 fprintf(stderr, "PACKET3_CNTL_BITBLT_MULTI, %d dwords\n",
924	      cmdsz);
925      break;
926   case RADEON_CP_PACKET3_CNTL_TRANS_BITBLT:
927      if (NORMAL)
928	 fprintf(stderr, "PACKET3_CNTL_TRANS_BITBLT, %d dwords\n",
929	      cmdsz);
930      break;
931   default:
932      fprintf(stderr, "UNKNOWN PACKET, %d dwords\n", cmdsz);
933      break;
934   }
935
936   cmdbuf->buf += cmdsz * 4;
937   cmdbuf->bufsz -= cmdsz * 4;
938   return 0;
939}
940
941
942/* Check cliprects for bounds, then pass on to above:
943 */
944static int radeon_emit_packet3_cliprect( drm_radeon_cmd_buffer_t *cmdbuf )
945{
946   drm_clip_rect_t *boxes = cmdbuf->boxes;
947   int i = 0;
948
949   if (VERBOSE && total_changed) {
950      dump_state();
951      total_changed = 0;
952   }
953   else fprintf(stderr, "total_changed zero\n");
954
955   if (NORMAL) {
956      do {
957	 if ( i < cmdbuf->nbox ) {
958	    fprintf(stderr, "Emit box %d/%d %d,%d %d,%d\n",
959		    i, cmdbuf->nbox,
960		    boxes[i].x1, boxes[i].y1, boxes[i].x2, boxes[i].y2);
961	 }
962      } while ( ++i < cmdbuf->nbox );
963   }
964
965   if (cmdbuf->nbox == 1)
966      cmdbuf->nbox = 0;
967
968   return radeon_emit_packet3( cmdbuf );
969}
970
971
972int radeonSanityCmdBuffer( r100ContextPtr rmesa,
973			   int nbox,
974			   drm_clip_rect_t *boxes )
975{
976   int idx;
977   drm_radeon_cmd_buffer_t cmdbuf;
978   drm_radeon_cmd_header_t header;
979   static int inited = 0;
980
981   if (!inited) {
982      init_regs();
983      inited = 1;
984   }
985
986   cmdbuf.buf = rmesa->store.cmd_buf;
987   cmdbuf.bufsz = rmesa->store.cmd_used;
988   cmdbuf.boxes = boxes;
989   cmdbuf.nbox = nbox;
990
991   while ( cmdbuf.bufsz >= sizeof(header) ) {
992
993      header.i = *(int *)cmdbuf.buf;
994      cmdbuf.buf += sizeof(header);
995      cmdbuf.bufsz -= sizeof(header);
996
997      switch (header.header.cmd_type) {
998      case RADEON_CMD_PACKET:
999	 if (radeon_emit_packets( header, &cmdbuf )) {
1000	    fprintf(stderr,"radeon_emit_packets failed\n");
1001	    return -EINVAL;
1002	 }
1003	 break;
1004
1005      case RADEON_CMD_SCALARS:
1006	 if (radeon_emit_scalars( header, &cmdbuf )) {
1007	    fprintf(stderr,"radeon_emit_scalars failed\n");
1008	    return -EINVAL;
1009	 }
1010	 break;
1011
1012      case RADEON_CMD_SCALARS2:
1013	 if (radeon_emit_scalars2( header, &cmdbuf )) {
1014	    fprintf(stderr,"radeon_emit_scalars failed\n");
1015	    return -EINVAL;
1016	 }
1017	 break;
1018
1019      case RADEON_CMD_VECTORS:
1020	 if (radeon_emit_vectors( header, &cmdbuf )) {
1021	    fprintf(stderr,"radeon_emit_vectors failed\n");
1022	    return -EINVAL;
1023	 }
1024	 break;
1025
1026      case RADEON_CMD_DMA_DISCARD:
1027	 idx = header.dma.buf_idx;
1028	 if (NORMAL)
1029	    fprintf(stderr, "RADEON_CMD_DMA_DISCARD buf %d\n", idx);
1030	 bufs++;
1031	 break;
1032
1033      case RADEON_CMD_PACKET3:
1034	 if (radeon_emit_packet3( &cmdbuf )) {
1035	    fprintf(stderr,"radeon_emit_packet3 failed\n");
1036	    return -EINVAL;
1037	 }
1038	 break;
1039
1040      case RADEON_CMD_PACKET3_CLIP:
1041	 if (radeon_emit_packet3_cliprect( &cmdbuf )) {
1042	    fprintf(stderr,"radeon_emit_packet3_clip failed\n");
1043	    return -EINVAL;
1044	 }
1045	 break;
1046
1047      case RADEON_CMD_WAIT:
1048	 break;
1049
1050      default:
1051	 fprintf(stderr,"bad cmd_type %d at %p\n",
1052		   header.header.cmd_type,
1053		   cmdbuf.buf - sizeof(header));
1054	 return -EINVAL;
1055      }
1056   }
1057
1058   if (0)
1059   {
1060      static int n = 0;
1061      n++;
1062      if (n == 10) {
1063	 fprintf(stderr, "Bufs %d Total emitted %d real changes %d (%.2f%%)\n",
1064		 bufs,
1065		 total, total_changed,
1066		 ((float)total_changed/(float)total*100.0));
1067	 fprintf(stderr, "Total emitted per buf: %.2f\n",
1068		 (float)total/(float)bufs);
1069	 fprintf(stderr, "Real changes per buf: %.2f\n",
1070		 (float)total_changed/(float)bufs);
1071
1072	 bufs = n = total = total_changed = 0;
1073      }
1074   }
1075
1076   return 0;
1077}
1078