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