1/**************************************************************************
2
3Copyright 2002 ATI Technologies Inc., Ontario, Canada, and
4                     Tungsten Graphics Inc, Cedar Park, TX.
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, TUNGSTEN GRAPHICS 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 <keith@tungstengraphics.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
318union fi { float f; int i; };
319
320#define ISVEC   1
321#define ISFLOAT 2
322#define TOUCHED 4
323
324struct reg {
325   int idx;
326   struct reg_names *closest;
327   int flags;
328   union fi current;
329   union fi *values;
330   int nvalues;
331   int nalloc;
332   float vmin, vmax;
333};
334
335
336static struct reg regs[Elements(reg_names)+1];
337static struct reg scalars[512+1];
338static struct reg vectors[512*4+1];
339
340static int total, total_changed, bufs;
341
342static void init_regs( void )
343{
344   struct reg_names *tmp;
345   int i;
346
347   for (i = 0 ; i < Elements(regs)-1 ; i++) {
348      regs[i].idx = reg_names[i].idx;
349      regs[i].closest = &reg_names[i];
350      regs[i].flags = 0;
351   }
352
353   for (i = 0, tmp = scalar_names ; i < Elements(scalars) ; i++) {
354      if (tmp[1].idx == i) tmp++;
355      scalars[i].idx = i;
356      scalars[i].closest = tmp;
357      scalars[i].flags = ISFLOAT;
358   }
359
360   for (i = 0, tmp = vector_names ; i < Elements(vectors) ; i++) {
361      if (tmp[1].idx*4 == i) tmp++;
362      vectors[i].idx = i;
363      vectors[i].closest = tmp;
364      vectors[i].flags = ISFLOAT|ISVEC;
365   }
366
367   regs[Elements(regs)-1].idx = -1;
368   scalars[Elements(scalars)-1].idx = -1;
369   vectors[Elements(vectors)-1].idx = -1;
370}
371
372static int find_or_add_value( struct reg *reg, int val )
373{
374   int j;
375
376   for ( j = 0 ; j < reg->nvalues ; j++)
377      if ( val == reg->values[j].i )
378	 return 1;
379
380   if (j == reg->nalloc) {
381      reg->nalloc += 5;
382      reg->nalloc *= 2;
383      reg->values = (union fi *) realloc( reg->values,
384					  reg->nalloc * sizeof(union fi) );
385   }
386
387   reg->values[reg->nvalues++].i = val;
388   return 0;
389}
390
391static struct reg *lookup_reg( struct reg *tab, int reg )
392{
393   int i;
394
395   for (i = 0 ; tab[i].idx != -1 ; i++) {
396      if (tab[i].idx == reg)
397	 return &tab[i];
398   }
399
400   fprintf(stderr, "*** unknown reg 0x%x\n", reg);
401   return NULL;
402}
403
404
405static const char *get_reg_name( struct reg *reg )
406{
407   static char tmp[80];
408
409   if (reg->idx == reg->closest->idx)
410      return reg->closest->name;
411
412
413   if (reg->flags & ISVEC) {
414      if (reg->idx/4 != reg->closest->idx)
415	 sprintf(tmp, "%s+%d[%d]",
416		 reg->closest->name,
417		 (reg->idx/4) - reg->closest->idx,
418		 reg->idx%4);
419      else
420	 sprintf(tmp, "%s[%d]", reg->closest->name, reg->idx%4);
421   }
422   else {
423      if (reg->idx != reg->closest->idx)
424	 sprintf(tmp, "%s+%d", reg->closest->name, reg->idx - reg->closest->idx);
425      else
426	 sprintf(tmp, "%s", reg->closest->name);
427   }
428
429   return tmp;
430}
431
432static int print_int_reg_assignment( struct reg *reg, int data )
433{
434   int changed = (reg->current.i != data);
435   int ever_seen = find_or_add_value( reg, data );
436
437   if (VERBOSE || (NORMAL && (changed || !ever_seen)))
438       fprintf(stderr, "   %s <-- 0x%x", get_reg_name(reg), data);
439
440   if (NORMAL) {
441      if (!ever_seen)
442	 fprintf(stderr, " *** BRAND NEW VALUE");
443      else if (changed)
444	 fprintf(stderr, " *** CHANGED");
445   }
446
447   reg->current.i = data;
448
449   if (VERBOSE || (NORMAL && (changed || !ever_seen)))
450      fprintf(stderr, "\n");
451
452   return changed;
453}
454
455
456static int print_float_reg_assignment( struct reg *reg, float data )
457{
458   int changed = (reg->current.f != data);
459   int newmin = (data < reg->vmin);
460   int newmax = (data > reg->vmax);
461
462   if (VERBOSE || (NORMAL && (newmin || newmax || changed)))
463      fprintf(stderr, "   %s <-- %.3f", get_reg_name(reg), data);
464
465   if (NORMAL) {
466      if (newmin) {
467	 fprintf(stderr, " *** NEW MIN (prev %.3f)", reg->vmin);
468	 reg->vmin = data;
469      }
470      else if (newmax) {
471	 fprintf(stderr, " *** NEW MAX (prev %.3f)", reg->vmax);
472	 reg->vmax = data;
473      }
474      else if (changed) {
475	 fprintf(stderr, " *** CHANGED");
476      }
477   }
478
479   reg->current.f = data;
480
481   if (VERBOSE || (NORMAL && (newmin || newmax || changed)))
482      fprintf(stderr, "\n");
483
484   return changed;
485}
486
487static int print_reg_assignment( struct reg *reg, int data )
488{
489   float_ui32_type datau;
490   datau.ui32 = data;
491   reg->flags |= TOUCHED;
492   if (reg->flags & ISFLOAT)
493      return print_float_reg_assignment( reg, datau.f );
494   else
495      return print_int_reg_assignment( reg, data );
496}
497
498static void print_reg( struct reg *reg )
499{
500   if (reg->flags & TOUCHED) {
501      if (reg->flags & ISFLOAT) {
502	 fprintf(stderr, "   %s == %f\n", get_reg_name(reg), reg->current.f);
503      } else {
504	 fprintf(stderr, "   %s == 0x%x\n", get_reg_name(reg), reg->current.i);
505      }
506   }
507}
508
509
510static void dump_state( void )
511{
512   int i;
513
514   for (i = 0 ; i < Elements(regs) ; i++)
515      print_reg( &regs[i] );
516
517   for (i = 0 ; i < Elements(scalars) ; i++)
518      print_reg( &scalars[i] );
519
520   for (i = 0 ; i < Elements(vectors) ; i++)
521      print_reg( &vectors[i] );
522}
523
524
525
526static int radeon_emit_packets(
527   drm_radeon_cmd_header_t header,
528   drm_radeon_cmd_buffer_t *cmdbuf )
529{
530   int id = (int)header.packet.packet_id;
531   int sz = packet[id].len;
532   int *data = (int *)cmdbuf->buf;
533   int i;
534
535   if (sz * sizeof(int) > cmdbuf->bufsz) {
536      fprintf(stderr, "Packet overflows cmdbuf\n");
537      return -EINVAL;
538   }
539
540   if (!packet[id].name) {
541      fprintf(stderr, "*** Unknown packet 0 nr %d\n", id );
542      return -EINVAL;
543   }
544
545
546   if (VERBOSE)
547      fprintf(stderr, "Packet 0 reg %s nr %d\n", packet[id].name, sz );
548
549   for ( i = 0 ; i < sz ; i++) {
550      struct reg *reg = lookup_reg( regs, packet[id].start + i*4 );
551      if (print_reg_assignment( reg, data[i] ))
552	 total_changed++;
553      total++;
554   }
555
556   cmdbuf->buf += sz * sizeof(int);
557   cmdbuf->bufsz -= sz * sizeof(int);
558   return 0;
559}
560
561
562static int radeon_emit_scalars(
563   drm_radeon_cmd_header_t header,
564   drm_radeon_cmd_buffer_t *cmdbuf )
565{
566   int sz = header.scalars.count;
567   int *data = (int *)cmdbuf->buf;
568   int start = header.scalars.offset;
569   int stride = header.scalars.stride;
570   int i;
571
572   if (VERBOSE)
573      fprintf(stderr, "emit scalars, start %d stride %d nr %d (end %d)\n",
574	      start, stride, sz, start + stride * sz);
575
576
577   for (i = 0 ; i < sz ; i++, start += stride) {
578      struct reg *reg = lookup_reg( scalars, start );
579      if (print_reg_assignment( reg, data[i] ))
580	 total_changed++;
581      total++;
582   }
583
584   cmdbuf->buf += sz * sizeof(int);
585   cmdbuf->bufsz -= sz * sizeof(int);
586   return 0;
587}
588
589
590static int radeon_emit_scalars2(
591   drm_radeon_cmd_header_t header,
592   drm_radeon_cmd_buffer_t *cmdbuf )
593{
594   int sz = header.scalars.count;
595   int *data = (int *)cmdbuf->buf;
596   int start = header.scalars.offset + 0x100;
597   int stride = header.scalars.stride;
598   int i;
599
600   if (VERBOSE)
601      fprintf(stderr, "emit scalars2, start %d stride %d nr %d (end %d)\n",
602	      start, stride, sz, start + stride * sz);
603
604   if (start + stride * sz > 257) {
605      fprintf(stderr, "emit scalars OVERFLOW %d/%d/%d\n", start, stride, sz);
606      return -1;
607   }
608
609   for (i = 0 ; i < sz ; i++, start += stride) {
610      struct reg *reg = lookup_reg( scalars, start );
611      if (print_reg_assignment( reg, data[i] ))
612	 total_changed++;
613      total++;
614   }
615
616   cmdbuf->buf += sz * sizeof(int);
617   cmdbuf->bufsz -= sz * sizeof(int);
618   return 0;
619}
620
621/* Check: inf/nan/extreme-size?
622 * Check: table start, end, nr, etc.
623 */
624static int radeon_emit_vectors(
625   drm_radeon_cmd_header_t header,
626   drm_radeon_cmd_buffer_t *cmdbuf )
627{
628   int sz = header.vectors.count;
629   int *data = (int *)cmdbuf->buf;
630   int start = header.vectors.offset;
631   int stride = header.vectors.stride;
632   int i,j;
633
634   if (VERBOSE)
635      fprintf(stderr, "emit vectors, start %d stride %d nr %d (end %d) (0x%x)\n",
636	      start, stride, sz, start + stride * sz, header.i);
637
638/*    if (start + stride * (sz/4) > 128) { */
639/*       fprintf(stderr, "emit vectors OVERFLOW %d/%d/%d\n", start, stride, sz); */
640/*       return -1; */
641/*    } */
642
643   for (i = 0 ; i < sz ;  start += stride) {
644      int changed = 0;
645      for (j = 0 ; j < 4 ; i++,j++) {
646	 struct reg *reg = lookup_reg( vectors, start*4+j );
647	 if (print_reg_assignment( reg, data[i] ))
648	    changed = 1;
649      }
650      if (changed)
651	 total_changed += 4;
652      total += 4;
653   }
654
655
656   cmdbuf->buf += sz * sizeof(int);
657   cmdbuf->bufsz -= sz * sizeof(int);
658   return 0;
659}
660
661
662static int print_vertex_format( int vfmt )
663{
664   if (NORMAL) {
665      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",
666	      "vertex format",
667	      vfmt,
668	      "xy,",
669	      (vfmt & RADEON_CP_VC_FRMT_Z) ? "z," : "",
670	      (vfmt & RADEON_CP_VC_FRMT_W0) ? "w0," : "",
671	      (vfmt & RADEON_CP_VC_FRMT_FPCOLOR) ? "fpcolor," : "",
672	      (vfmt & RADEON_CP_VC_FRMT_FPALPHA) ? "fpalpha," : "",
673	      (vfmt & RADEON_CP_VC_FRMT_PKCOLOR) ? "pkcolor," : "",
674	      (vfmt & RADEON_CP_VC_FRMT_FPSPEC) ? "fpspec," : "",
675	      (vfmt & RADEON_CP_VC_FRMT_FPFOG) ? "fpfog," : "",
676	      (vfmt & RADEON_CP_VC_FRMT_PKSPEC) ? "pkspec," : "",
677	      (vfmt & RADEON_CP_VC_FRMT_ST0) ? "st0," : "",
678	      (vfmt & RADEON_CP_VC_FRMT_ST1) ? "st1," : "",
679	      (vfmt & RADEON_CP_VC_FRMT_Q1) ? "q1," : "",
680	      (vfmt & RADEON_CP_VC_FRMT_ST2) ? "st2," : "",
681	      (vfmt & RADEON_CP_VC_FRMT_Q2) ? "q2," : "",
682	      (vfmt & RADEON_CP_VC_FRMT_ST3) ? "st3," : "",
683	      (vfmt & RADEON_CP_VC_FRMT_Q3) ? "q3," : "",
684	      (vfmt & RADEON_CP_VC_FRMT_Q0) ? "q0," : "",
685	      (vfmt & RADEON_CP_VC_FRMT_N0) ? "n0," : "",
686	      (vfmt & RADEON_CP_VC_FRMT_XY1) ? "xy1," : "",
687	      (vfmt & RADEON_CP_VC_FRMT_Z1) ? "z1," : "",
688	      (vfmt & RADEON_CP_VC_FRMT_W1) ? "w1," : "",
689	      (vfmt & RADEON_CP_VC_FRMT_N1) ? "n1," : "");
690
691
692/*       if (!find_or_add_value( &others[V_VTXFMT], vfmt )) */
693/* 	 fprintf(stderr, " *** NEW VALUE"); */
694
695      fprintf(stderr, "\n");
696   }
697
698   return 0;
699}
700
701static char *primname[0xf] = {
702   "NONE",
703   "POINTS",
704   "LINES",
705   "LINE_STRIP",
706   "TRIANGLES",
707   "TRIANGLE_FAN",
708   "TRIANGLE_STRIP",
709   "TRI_TYPE_2",
710   "RECT_LIST",
711   "3VRT_POINTS",
712   "3VRT_LINES",
713};
714
715static int print_prim_and_flags( int prim )
716{
717   int numverts;
718
719   if (NORMAL)
720      fprintf(stderr, "   %s(%x): %s%s%s%s%s%s%s\n",
721	      "prim flags",
722	      prim,
723	      ((prim & 0x30) == RADEON_CP_VC_CNTL_PRIM_WALK_IND) ? "IND," : "",
724	      ((prim & 0x30) == RADEON_CP_VC_CNTL_PRIM_WALK_LIST) ? "LIST," : "",
725	      ((prim & 0x30) == RADEON_CP_VC_CNTL_PRIM_WALK_RING) ? "RING," : "",
726	      (prim & RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA) ? "RGBA," : "BGRA, ",
727	      (prim & RADEON_CP_VC_CNTL_MAOS_ENABLE) ? "MAOS," : "",
728	      (prim & RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE) ? "RADEON," : "",
729	      (prim & RADEON_CP_VC_CNTL_TCL_ENABLE) ? "TCL," : "");
730
731   if ((prim & 0xf) > RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_LINE_LIST) {
732      fprintf(stderr, "   *** Bad primitive: %x\n", prim & 0xf);
733      return -1;
734   }
735
736   numverts = prim>>16;
737
738   if (NORMAL)
739      fprintf(stderr, "   prim: %s numverts %d\n", primname[prim&0xf], numverts);
740
741   switch (prim & 0xf) {
742   case RADEON_CP_VC_CNTL_PRIM_TYPE_NONE:
743   case RADEON_CP_VC_CNTL_PRIM_TYPE_POINT:
744      if (numverts < 1) {
745	 fprintf(stderr, "Bad nr verts for line %d\n", numverts);
746	 return -1;
747      }
748      break;
749   case RADEON_CP_VC_CNTL_PRIM_TYPE_LINE:
750      if ((numverts & 1) || numverts == 0) {
751	 fprintf(stderr, "Bad nr verts for line %d\n", numverts);
752	 return -1;
753      }
754      break;
755   case RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP:
756      if (numverts < 2) {
757	 fprintf(stderr, "Bad nr verts for line_strip %d\n", numverts);
758	 return -1;
759      }
760      break;
761   case RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST:
762   case RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_POINT_LIST:
763   case RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_LINE_LIST:
764   case RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST:
765      if (numverts % 3 || numverts == 0) {
766	 fprintf(stderr, "Bad nr verts for tri %d\n", numverts);
767	 return -1;
768      }
769      break;
770   case RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN:
771   case RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP:
772      if (numverts < 3) {
773	 fprintf(stderr, "Bad nr verts for strip/fan %d\n", numverts);
774	 return -1;
775      }
776      break;
777   default:
778      fprintf(stderr, "Bad primitive\n");
779      return -1;
780   }
781   return 0;
782}
783
784/* build in knowledge about each packet type
785 */
786static int radeon_emit_packet3( drm_radeon_cmd_buffer_t *cmdbuf )
787{
788   int cmdsz;
789   int *cmd = (int *)cmdbuf->buf;
790   int *tmp;
791   int i, stride, size, start;
792
793   cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16);
794
795   if ((cmd[0] & RADEON_CP_PACKET_MASK) != RADEON_CP_PACKET3 ||
796       cmdsz * 4 > cmdbuf->bufsz ||
797       cmdsz > RADEON_CP_PACKET_MAX_DWORDS) {
798      fprintf(stderr, "Bad packet\n");
799      return -EINVAL;
800   }
801
802   switch( cmd[0] & ~RADEON_CP_PACKET_COUNT_MASK ) {
803   case RADEON_CP_PACKET3_NOP:
804      if (NORMAL)
805	 fprintf(stderr, "PACKET3_NOP, %d dwords\n", cmdsz);
806      break;
807   case RADEON_CP_PACKET3_NEXT_CHAR:
808      if (NORMAL)
809	 fprintf(stderr, "PACKET3_NEXT_CHAR, %d dwords\n", cmdsz);
810      break;
811   case RADEON_CP_PACKET3_PLY_NEXTSCAN:
812      if (NORMAL)
813	 fprintf(stderr, "PACKET3_PLY_NEXTSCAN, %d dwords\n", cmdsz);
814      break;
815   case RADEON_CP_PACKET3_SET_SCISSORS:
816      if (NORMAL)
817	 fprintf(stderr, "PACKET3_SET_SCISSORS, %d dwords\n", cmdsz);
818      break;
819   case RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM:
820      if (NORMAL)
821	 fprintf(stderr, "PACKET3_3D_RNDR_GEN_INDX_PRIM, %d dwords\n",
822	      cmdsz);
823      break;
824   case RADEON_CP_PACKET3_LOAD_MICROCODE:
825      if (NORMAL)
826	 fprintf(stderr, "PACKET3_LOAD_MICROCODE, %d dwords\n", cmdsz);
827      break;
828   case RADEON_CP_PACKET3_WAIT_FOR_IDLE:
829      if (NORMAL)
830	 fprintf(stderr, "PACKET3_WAIT_FOR_IDLE, %d dwords\n", cmdsz);
831      break;
832
833   case RADEON_CP_PACKET3_3D_DRAW_VBUF:
834      if (NORMAL)
835	 fprintf(stderr, "PACKET3_3D_DRAW_VBUF, %d dwords\n", cmdsz);
836      print_vertex_format(cmd[1]);
837      print_prim_and_flags(cmd[2]);
838      break;
839
840   case RADEON_CP_PACKET3_3D_DRAW_IMMD:
841      if (NORMAL)
842	 fprintf(stderr, "PACKET3_3D_DRAW_IMMD, %d dwords\n", cmdsz);
843      break;
844   case RADEON_CP_PACKET3_3D_DRAW_INDX: {
845      int neltdwords;
846      if (NORMAL)
847	 fprintf(stderr, "PACKET3_3D_DRAW_INDX, %d dwords\n", cmdsz);
848      print_vertex_format(cmd[1]);
849      print_prim_and_flags(cmd[2]);
850      neltdwords = cmd[2]>>16;
851      neltdwords += neltdwords & 1;
852      neltdwords /= 2;
853      if (neltdwords + 3 != cmdsz)
854	 fprintf(stderr, "Mismatch in DRAW_INDX, %d vs cmdsz %d\n",
855		 neltdwords, cmdsz);
856      break;
857   }
858   case RADEON_CP_PACKET3_LOAD_PALETTE:
859      if (NORMAL)
860	 fprintf(stderr, "PACKET3_LOAD_PALETTE, %d dwords\n", cmdsz);
861      break;
862   case RADEON_CP_PACKET3_3D_LOAD_VBPNTR:
863      if (NORMAL) {
864	 fprintf(stderr, "PACKET3_3D_LOAD_VBPNTR, %d dwords\n", cmdsz);
865	 fprintf(stderr, "   nr arrays: %d\n", cmd[1]);
866      }
867
868      if (cmd[1]/2 + cmd[1]%2 != cmdsz - 3) {
869	 fprintf(stderr, "  ****** MISMATCH %d/%d *******\n",
870		 cmd[1]/2 + cmd[1]%2 + 3, cmdsz);
871	 return -EINVAL;
872      }
873
874      if (NORMAL) {
875	 tmp = cmd+2;
876	 for (i = 0 ; i < cmd[1] ; i++) {
877	    if (i & 1) {
878	       stride = (tmp[0]>>24) & 0xff;
879	       size = (tmp[0]>>16) & 0xff;
880	       start = tmp[2];
881	       tmp += 3;
882	    }
883	    else {
884	       stride = (tmp[0]>>8) & 0xff;
885	       size = (tmp[0]) & 0xff;
886	       start = tmp[1];
887	    }
888	    fprintf(stderr, "   array %d: start 0x%x vsize %d vstride %d\n",
889		    i, start, size, stride );
890	 }
891      }
892      break;
893   case RADEON_CP_PACKET3_CNTL_PAINT:
894      if (NORMAL)
895	 fprintf(stderr, "PACKET3_CNTL_PAINT, %d dwords\n", cmdsz);
896      break;
897   case RADEON_CP_PACKET3_CNTL_BITBLT:
898      if (NORMAL)
899	 fprintf(stderr, "PACKET3_CNTL_BITBLT, %d dwords\n", cmdsz);
900      break;
901   case RADEON_CP_PACKET3_CNTL_SMALLTEXT:
902      if (NORMAL)
903	 fprintf(stderr, "PACKET3_CNTL_SMALLTEXT, %d dwords\n", cmdsz);
904      break;
905   case RADEON_CP_PACKET3_CNTL_HOSTDATA_BLT:
906      if (NORMAL)
907	 fprintf(stderr, "PACKET3_CNTL_HOSTDATA_BLT, %d dwords\n",
908	      cmdsz);
909      break;
910   case RADEON_CP_PACKET3_CNTL_POLYLINE:
911      if (NORMAL)
912	 fprintf(stderr, "PACKET3_CNTL_POLYLINE, %d dwords\n", cmdsz);
913      break;
914   case RADEON_CP_PACKET3_CNTL_POLYSCANLINES:
915      if (NORMAL)
916	 fprintf(stderr, "PACKET3_CNTL_POLYSCANLINES, %d dwords\n",
917	      cmdsz);
918      break;
919   case RADEON_CP_PACKET3_CNTL_PAINT_MULTI:
920      if (NORMAL)
921	 fprintf(stderr, "PACKET3_CNTL_PAINT_MULTI, %d dwords\n",
922	      cmdsz);
923      break;
924   case RADEON_CP_PACKET3_CNTL_BITBLT_MULTI:
925      if (NORMAL)
926	 fprintf(stderr, "PACKET3_CNTL_BITBLT_MULTI, %d dwords\n",
927	      cmdsz);
928      break;
929   case RADEON_CP_PACKET3_CNTL_TRANS_BITBLT:
930      if (NORMAL)
931	 fprintf(stderr, "PACKET3_CNTL_TRANS_BITBLT, %d dwords\n",
932	      cmdsz);
933      break;
934   default:
935      fprintf(stderr, "UNKNOWN PACKET, %d dwords\n", cmdsz);
936      break;
937   }
938
939   cmdbuf->buf += cmdsz * 4;
940   cmdbuf->bufsz -= cmdsz * 4;
941   return 0;
942}
943
944
945/* Check cliprects for bounds, then pass on to above:
946 */
947static int radeon_emit_packet3_cliprect( drm_radeon_cmd_buffer_t *cmdbuf )
948{
949   drm_clip_rect_t *boxes = cmdbuf->boxes;
950   int i = 0;
951
952   if (VERBOSE && total_changed) {
953      dump_state();
954      total_changed = 0;
955   }
956   else fprintf(stderr, "total_changed zero\n");
957
958   if (NORMAL) {
959      do {
960	 if ( i < cmdbuf->nbox ) {
961	    fprintf(stderr, "Emit box %d/%d %d,%d %d,%d\n",
962		    i, cmdbuf->nbox,
963		    boxes[i].x1, boxes[i].y1, boxes[i].x2, boxes[i].y2);
964	 }
965      } while ( ++i < cmdbuf->nbox );
966   }
967
968   if (cmdbuf->nbox == 1)
969      cmdbuf->nbox = 0;
970
971   return radeon_emit_packet3( cmdbuf );
972}
973
974
975int radeonSanityCmdBuffer( r100ContextPtr rmesa,
976			   int nbox,
977			   drm_clip_rect_t *boxes )
978{
979   int idx;
980   drm_radeon_cmd_buffer_t cmdbuf;
981   drm_radeon_cmd_header_t header;
982   static int inited = 0;
983
984   if (!inited) {
985      init_regs();
986      inited = 1;
987   }
988
989   cmdbuf.buf = rmesa->store.cmd_buf;
990   cmdbuf.bufsz = rmesa->store.cmd_used;
991   cmdbuf.boxes = boxes;
992   cmdbuf.nbox = nbox;
993
994   while ( cmdbuf.bufsz >= sizeof(header) ) {
995
996      header.i = *(int *)cmdbuf.buf;
997      cmdbuf.buf += sizeof(header);
998      cmdbuf.bufsz -= sizeof(header);
999
1000      switch (header.header.cmd_type) {
1001      case RADEON_CMD_PACKET:
1002	 if (radeon_emit_packets( header, &cmdbuf )) {
1003	    fprintf(stderr,"radeon_emit_packets failed\n");
1004	    return -EINVAL;
1005	 }
1006	 break;
1007
1008      case RADEON_CMD_SCALARS:
1009	 if (radeon_emit_scalars( header, &cmdbuf )) {
1010	    fprintf(stderr,"radeon_emit_scalars failed\n");
1011	    return -EINVAL;
1012	 }
1013	 break;
1014
1015      case RADEON_CMD_SCALARS2:
1016	 if (radeon_emit_scalars2( header, &cmdbuf )) {
1017	    fprintf(stderr,"radeon_emit_scalars failed\n");
1018	    return -EINVAL;
1019	 }
1020	 break;
1021
1022      case RADEON_CMD_VECTORS:
1023	 if (radeon_emit_vectors( header, &cmdbuf )) {
1024	    fprintf(stderr,"radeon_emit_vectors failed\n");
1025	    return -EINVAL;
1026	 }
1027	 break;
1028
1029      case RADEON_CMD_DMA_DISCARD:
1030	 idx = header.dma.buf_idx;
1031	 if (NORMAL)
1032	    fprintf(stderr, "RADEON_CMD_DMA_DISCARD buf %d\n", idx);
1033	 bufs++;
1034	 break;
1035
1036      case RADEON_CMD_PACKET3:
1037	 if (radeon_emit_packet3( &cmdbuf )) {
1038	    fprintf(stderr,"radeon_emit_packet3 failed\n");
1039	    return -EINVAL;
1040	 }
1041	 break;
1042
1043      case RADEON_CMD_PACKET3_CLIP:
1044	 if (radeon_emit_packet3_cliprect( &cmdbuf )) {
1045	    fprintf(stderr,"radeon_emit_packet3_clip failed\n");
1046	    return -EINVAL;
1047	 }
1048	 break;
1049
1050      case RADEON_CMD_WAIT:
1051	 break;
1052
1053      default:
1054	 fprintf(stderr,"bad cmd_type %d at %p\n",
1055		   header.header.cmd_type,
1056		   cmdbuf.buf - sizeof(header));
1057	 return -EINVAL;
1058      }
1059   }
1060
1061   if (0)
1062   {
1063      static int n = 0;
1064      n++;
1065      if (n == 10) {
1066	 fprintf(stderr, "Bufs %d Total emitted %d real changes %d (%.2f%%)\n",
1067		 bufs,
1068		 total, total_changed,
1069		 ((float)total_changed/(float)total*100.0));
1070	 fprintf(stderr, "Total emitted per buf: %.2f\n",
1071		 (float)total/(float)bufs);
1072	 fprintf(stderr, "Real changes per buf: %.2f\n",
1073		 (float)total_changed/(float)bufs);
1074
1075	 bufs = n = total = total_changed = 0;
1076      }
1077   }
1078
1079   return 0;
1080}
1081