(Stephane Marchesin, me) add hyperz support to radeon and r200 drivers. Only fast...
[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         { 0, 1, "R200_SE_TCL_POINT_SPRITE_CNTL" },
143
144 };
145
146 struct reg_names {
147    int idx;
148    const char *name;
149 };
150
151 static struct reg_names reg_names[] = {
152    { RADEON_PP_MISC, "RADEON_PP_MISC" },
153    { RADEON_PP_FOG_COLOR, "RADEON_PP_FOG_COLOR" },
154    { RADEON_RE_SOLID_COLOR, "RADEON_RE_SOLID_COLOR" },
155    { RADEON_RB3D_BLENDCNTL, "RADEON_RB3D_BLENDCNTL" },
156    { RADEON_RB3D_DEPTHOFFSET, "RADEON_RB3D_DEPTHOFFSET" },
157    { RADEON_RB3D_DEPTHPITCH, "RADEON_RB3D_DEPTHPITCH" },
158    { RADEON_RB3D_ZSTENCILCNTL, "RADEON_RB3D_ZSTENCILCNTL" },
159    { RADEON_PP_CNTL, "RADEON_PP_CNTL" },
160    { RADEON_RB3D_CNTL, "RADEON_RB3D_CNTL" },
161    { RADEON_RB3D_COLOROFFSET, "RADEON_RB3D_COLOROFFSET" },
162    { RADEON_RB3D_COLORPITCH, "RADEON_RB3D_COLORPITCH" },
163    { RADEON_SE_CNTL, "RADEON_SE_CNTL" },
164    { RADEON_SE_COORD_FMT, "RADEON_SE_COORDFMT" },
165    { RADEON_SE_CNTL_STATUS, "RADEON_SE_CNTL_STATUS" },
166    { RADEON_RE_LINE_PATTERN, "RADEON_RE_LINE_PATTERN" },
167    { RADEON_RE_LINE_STATE, "RADEON_RE_LINE_STATE" },
168    { RADEON_SE_LINE_WIDTH, "RADEON_SE_LINE_WIDTH" },
169    { RADEON_RB3D_STENCILREFMASK, "RADEON_RB3D_STENCILREFMASK" },
170    { RADEON_RB3D_ROPCNTL, "RADEON_RB3D_ROPCNTL" },
171    { RADEON_RB3D_PLANEMASK, "RADEON_RB3D_PLANEMASK" },
172    { RADEON_SE_VPORT_XSCALE, "RADEON_SE_VPORT_XSCALE" },
173    { RADEON_SE_VPORT_XOFFSET, "RADEON_SE_VPORT_XOFFSET" },
174    { RADEON_SE_VPORT_YSCALE, "RADEON_SE_VPORT_YSCALE" },
175    { RADEON_SE_VPORT_YOFFSET, "RADEON_SE_VPORT_YOFFSET" },
176    { RADEON_SE_VPORT_ZSCALE, "RADEON_SE_VPORT_ZSCALE" },
177    { RADEON_SE_VPORT_ZOFFSET, "RADEON_SE_VPORT_ZOFFSET" },
178    { RADEON_RE_MISC, "RADEON_RE_MISC" },
179    { RADEON_PP_TXFILTER_0, "RADEON_PP_TXFILTER_0" },
180    { RADEON_PP_TXFILTER_1, "RADEON_PP_TXFILTER_1" },
181    { RADEON_PP_TXFILTER_2, "RADEON_PP_TXFILTER_2" },
182    { RADEON_PP_TXFORMAT_0, "RADEON_PP_TXFORMAT_0" },
183    { RADEON_PP_TXFORMAT_1, "RADEON_PP_TXFORMAT_1" },
184    { RADEON_PP_TXFORMAT_2, "RADEON_PP_TXFORMAT_2" },
185    { RADEON_PP_TXOFFSET_0, "RADEON_PP_TXOFFSET_0" },
186    { RADEON_PP_TXOFFSET_1, "RADEON_PP_TXOFFSET_1" },
187    { RADEON_PP_TXOFFSET_2, "RADEON_PP_TXOFFSET_2" },
188    { RADEON_PP_TXCBLEND_0, "RADEON_PP_TXCBLEND_0" },
189    { RADEON_PP_TXCBLEND_1, "RADEON_PP_TXCBLEND_1" },
190    { RADEON_PP_TXCBLEND_2, "RADEON_PP_TXCBLEND_2" },
191    { RADEON_PP_TXABLEND_0, "RADEON_PP_TXABLEND_0" },
192    { RADEON_PP_TXABLEND_1, "RADEON_PP_TXABLEND_1" },
193    { RADEON_PP_TXABLEND_2, "RADEON_PP_TXABLEND_2" },
194    { RADEON_PP_TFACTOR_0, "RADEON_PP_TFACTOR_0" },
195    { RADEON_PP_TFACTOR_1, "RADEON_PP_TFACTOR_1" },
196    { RADEON_PP_TFACTOR_2, "RADEON_PP_TFACTOR_2" },
197    { RADEON_PP_BORDER_COLOR_0, "RADEON_PP_BORDER_COLOR_0" },
198    { RADEON_PP_BORDER_COLOR_1, "RADEON_PP_BORDER_COLOR_1" },
199    { RADEON_PP_BORDER_COLOR_2, "RADEON_PP_BORDER_COLOR_2" },
200    { RADEON_SE_ZBIAS_FACTOR, "RADEON_SE_ZBIAS_FACTOR" },
201    { RADEON_SE_ZBIAS_CONSTANT, "RADEON_SE_ZBIAS_CONSTANT" },
202    { RADEON_SE_TCL_OUTPUT_VTX_FMT, "RADEON_SE_TCL_OUTPUT_VTXFMT" },
203    { RADEON_SE_TCL_OUTPUT_VTX_SEL, "RADEON_SE_TCL_OUTPUT_VTXSEL" },
204    { RADEON_SE_TCL_MATRIX_SELECT_0, "RADEON_SE_TCL_MATRIX_SELECT_0" },
205    { RADEON_SE_TCL_MATRIX_SELECT_1, "RADEON_SE_TCL_MATRIX_SELECT_1" },
206    { RADEON_SE_TCL_UCP_VERT_BLEND_CTL, "RADEON_SE_TCL_UCP_VERT_BLEND_CTL" },
207    { RADEON_SE_TCL_TEXTURE_PROC_CTL, "RADEON_SE_TCL_TEXTURE_PROC_CTL" },
208    { RADEON_SE_TCL_LIGHT_MODEL_CTL, "RADEON_SE_TCL_LIGHT_MODEL_CTL" },
209    { RADEON_SE_TCL_PER_LIGHT_CTL_0, "RADEON_SE_TCL_PER_LIGHT_CTL_0" },
210    { RADEON_SE_TCL_PER_LIGHT_CTL_1, "RADEON_SE_TCL_PER_LIGHT_CTL_1" },
211    { RADEON_SE_TCL_PER_LIGHT_CTL_2, "RADEON_SE_TCL_PER_LIGHT_CTL_2" },
212    { RADEON_SE_TCL_PER_LIGHT_CTL_3, "RADEON_SE_TCL_PER_LIGHT_CTL_3" },
213    { RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, "RADEON_SE_TCL_EMMISSIVE_RED" },
214    { RADEON_SE_TCL_MATERIAL_EMMISSIVE_GREEN, "RADEON_SE_TCL_EMMISSIVE_GREEN" },
215    { RADEON_SE_TCL_MATERIAL_EMMISSIVE_BLUE, "RADEON_SE_TCL_EMMISSIVE_BLUE" },
216    { RADEON_SE_TCL_MATERIAL_EMMISSIVE_ALPHA, "RADEON_SE_TCL_EMMISSIVE_ALPHA" },
217    { RADEON_SE_TCL_MATERIAL_AMBIENT_RED, "RADEON_SE_TCL_AMBIENT_RED" },
218    { RADEON_SE_TCL_MATERIAL_AMBIENT_GREEN, "RADEON_SE_TCL_AMBIENT_GREEN" },
219    { RADEON_SE_TCL_MATERIAL_AMBIENT_BLUE, "RADEON_SE_TCL_AMBIENT_BLUE" },
220    { RADEON_SE_TCL_MATERIAL_AMBIENT_ALPHA, "RADEON_SE_TCL_AMBIENT_ALPHA" },
221    { RADEON_SE_TCL_MATERIAL_DIFFUSE_RED, "RADEON_SE_TCL_DIFFUSE_RED" },
222    { RADEON_SE_TCL_MATERIAL_DIFFUSE_GREEN, "RADEON_SE_TCL_DIFFUSE_GREEN" },
223    { RADEON_SE_TCL_MATERIAL_DIFFUSE_BLUE, "RADEON_SE_TCL_DIFFUSE_BLUE" },
224    { RADEON_SE_TCL_MATERIAL_DIFFUSE_ALPHA, "RADEON_SE_TCL_DIFFUSE_ALPHA" },
225    { RADEON_SE_TCL_MATERIAL_SPECULAR_RED, "RADEON_SE_TCL_SPECULAR_RED" },
226    { RADEON_SE_TCL_MATERIAL_SPECULAR_GREEN, "RADEON_SE_TCL_SPECULAR_GREEN" },
227    { RADEON_SE_TCL_MATERIAL_SPECULAR_BLUE, "RADEON_SE_TCL_SPECULAR_BLUE" },
228    { RADEON_SE_TCL_MATERIAL_SPECULAR_ALPHA, "RADEON_SE_TCL_SPECULAR_ALPHA" },
229    { RADEON_SE_TCL_SHININESS, "RADEON_SE_TCL_SHININESS" },
230    { RADEON_SE_COORD_FMT, "RADEON_SE_COORD_FMT" },
231    { RADEON_PP_TEX_SIZE_0, "RADEON_PP_TEX_SIZE_0" },
232    { RADEON_PP_TEX_SIZE_1, "RADEON_PP_TEX_SIZE_1" },
233    { RADEON_PP_TEX_SIZE_2, "RADEON_PP_TEX_SIZE_2" },
234    { RADEON_PP_TEX_SIZE_0+4, "RADEON_PP_TEX_PITCH_0" },
235    { RADEON_PP_TEX_SIZE_1+4, "RADEON_PP_TEX_PITCH_1" },
236    { RADEON_PP_TEX_SIZE_2+4, "RADEON_PP_TEX_PITCH_2" },
237 };
238
239 static struct reg_names scalar_names[] = {
240    { RADEON_SS_LIGHT_DCD_ADDR, "LIGHT_DCD" },
241    { RADEON_SS_LIGHT_SPOT_EXPONENT_ADDR, "LIGHT_SPOT_EXPONENT" },
242    { RADEON_SS_LIGHT_SPOT_CUTOFF_ADDR, "LIGHT_SPOT_CUTOFF" },
243    { RADEON_SS_LIGHT_SPECULAR_THRESH_ADDR, "LIGHT_SPECULAR_THRESH" },
244    { RADEON_SS_LIGHT_RANGE_CUTOFF_ADDR, "LIGHT_RANGE_CUTOFF" },
245    { RADEON_SS_VERT_GUARD_CLIP_ADJ_ADDR, "VERT_GUARD_CLIP" },
246    { RADEON_SS_VERT_GUARD_DISCARD_ADJ_ADDR, "VERT_GUARD_DISCARD" },
247    { RADEON_SS_HORZ_GUARD_CLIP_ADJ_ADDR, "HORZ_GUARD_CLIP" },
248    { RADEON_SS_HORZ_GUARD_DISCARD_ADJ_ADDR, "HORZ_GUARD_DISCARD" },
249    { RADEON_SS_SHININESS, "SHININESS" },
250    { 1000, "" },
251 };
252
253 /* Puff these out to make them look like normal (dword) registers.
254  */
255 static struct reg_names vector_names[] = {
256    { RADEON_VS_MATRIX_0_ADDR * 4, "MATRIX_0" },
257    { RADEON_VS_MATRIX_1_ADDR * 4, "MATRIX_1" },
258    { RADEON_VS_MATRIX_2_ADDR * 4, "MATRIX_2" },
259    { RADEON_VS_MATRIX_3_ADDR * 4, "MATRIX_3" },
260    { RADEON_VS_MATRIX_4_ADDR * 4, "MATRIX_4" },
261    { RADEON_VS_MATRIX_5_ADDR * 4, "MATRIX_5" },
262    { RADEON_VS_MATRIX_6_ADDR * 4, "MATRIX_6" },
263    { RADEON_VS_MATRIX_7_ADDR * 4, "MATRIX_7" },
264    { RADEON_VS_MATRIX_8_ADDR * 4, "MATRIX_8" },
265    { RADEON_VS_MATRIX_9_ADDR * 4, "MATRIX_9" },
266    { RADEON_VS_MATRIX_10_ADDR * 4, "MATRIX_10" },
267    { RADEON_VS_MATRIX_11_ADDR * 4, "MATRIX_11" },
268    { RADEON_VS_MATRIX_12_ADDR * 4, "MATRIX_12" },
269    { RADEON_VS_MATRIX_13_ADDR * 4, "MATRIX_13" },
270    { RADEON_VS_MATRIX_14_ADDR * 4, "MATRIX_14" },
271    { RADEON_VS_MATRIX_15_ADDR * 4, "MATRIX_15" },
272    { RADEON_VS_LIGHT_AMBIENT_ADDR * 4, "LIGHT_AMBIENT" },
273    { RADEON_VS_LIGHT_DIFFUSE_ADDR * 4, "LIGHT_DIFFUSE" },
274    { RADEON_VS_LIGHT_SPECULAR_ADDR * 4, "LIGHT_SPECULAR" },
275    { RADEON_VS_LIGHT_DIRPOS_ADDR * 4, "LIGHT_DIRPOS" },
276    { RADEON_VS_LIGHT_HWVSPOT_ADDR * 4, "LIGHT_HWVSPOT" },
277    { RADEON_VS_LIGHT_ATTENUATION_ADDR * 4, "LIGHT_ATTENUATION" },
278    { RADEON_VS_MATRIX_EYE2CLIP_ADDR * 4, "MATRIX_EYE2CLIP" },
279    { RADEON_VS_UCP_ADDR * 4, "UCP" },
280    { RADEON_VS_GLOBAL_AMBIENT_ADDR * 4, "GLOBAL_AMBIENT" },
281    { RADEON_VS_FOG_PARAM_ADDR * 4, "FOG_PARAM" },
282    { RADEON_VS_EYE_VECTOR_ADDR * 4, "EYE_VECTOR" },
283    { 1000, "" },
284 };
285
286 union fi { float f; int i; };
287
288 #define ISVEC   1
289 #define ISFLOAT 2
290 #define TOUCHED 4
291
292 struct reg {
293    int idx; 
294    struct reg_names *closest;
295    int flags;
296    union fi current;
297    union fi *values;
298    int nvalues;
299    int nalloc;
300    float vmin, vmax;
301 };
302
303
304 static struct reg regs[Elements(reg_names)+1];
305 static struct reg scalars[512+1];
306 static struct reg vectors[512*4+1];
307
308 static int total, total_changed, bufs;
309
310 static void init_regs( void )
311 {
312    struct reg_names *tmp;
313    int i;
314
315    for (i = 0 ; i < Elements(regs) ; i++) {
316       regs[i].idx = reg_names[i].idx;
317       regs[i].closest = &reg_names[i];
318       regs[i].flags = 0;
319    }
320
321    for (i = 0, tmp = scalar_names ; i < Elements(scalars) ; i++) {
322       if (tmp[1].idx == i) tmp++;
323       scalars[i].idx = i;
324       scalars[i].closest = tmp;
325       scalars[i].flags = ISFLOAT;
326    }
327
328    for (i = 0, tmp = vector_names ; i < Elements(vectors) ; i++) {
329       if (tmp[1].idx*4 == i) tmp++;
330       vectors[i].idx = i;
331       vectors[i].closest = tmp;
332       vectors[i].flags = ISFLOAT|ISVEC;
333    }
334
335    regs[Elements(regs)-1].idx = -1;
336    scalars[Elements(scalars)-1].idx = -1;
337    vectors[Elements(vectors)-1].idx = -1;
338 }
339
340 static int find_or_add_value( struct reg *reg, int val )
341 {
342    int j;
343
344    for ( j = 0 ; j < reg->nvalues ; j++)
345       if ( val == reg->values[j].i )
346          return 1;
347
348    if (j == reg->nalloc) {
349       reg->nalloc += 5;
350       reg->nalloc *= 2;
351       reg->values = (union fi *) realloc( reg->values, 
352                                           reg->nalloc * sizeof(union fi) );
353    }
354
355    reg->values[reg->nvalues++].i = val;
356    return 0;
357 }
358
359 static struct reg *lookup_reg( struct reg *tab, int reg )
360 {
361    int i;
362
363    for (i = 0 ; tab[i].idx != -1 ; i++) {
364       if (tab[i].idx == reg)
365          return &tab[i];
366    }
367
368    fprintf(stderr, "*** unknown reg 0x%x\n", reg);
369    return 0;
370 }
371
372
373 static const char *get_reg_name( struct reg *reg )
374 {
375    static char tmp[80];
376
377    if (reg->idx == reg->closest->idx) 
378       return reg->closest->name;
379
380    
381    if (reg->flags & ISVEC) {
382       if (reg->idx/4 != reg->closest->idx)
383          sprintf(tmp, "%s+%d[%d]", 
384                  reg->closest->name, 
385                  (reg->idx/4) - reg->closest->idx,
386                  reg->idx%4);
387       else
388          sprintf(tmp, "%s[%d]", reg->closest->name, reg->idx%4);
389    }
390    else {
391       if (reg->idx != reg->closest->idx)
392          sprintf(tmp, "%s+%d", reg->closest->name, reg->idx - reg->closest->idx);
393       else
394          sprintf(tmp, "%s", reg->closest->name);
395    }
396
397    return tmp;
398 }
399
400 static int print_int_reg_assignment( struct reg *reg, int data )
401 {
402    int changed = (reg->current.i != data);
403    int ever_seen = find_or_add_value( reg, data );
404    
405    if (VERBOSE || (NORMAL && (changed || !ever_seen)))
406        fprintf(stderr, "   %s <-- 0x%x", get_reg_name(reg), data);
407        
408    if (NORMAL) {
409       if (!ever_seen) 
410          fprintf(stderr, " *** BRAND NEW VALUE");
411       else if (changed) 
412          fprintf(stderr, " *** CHANGED"); 
413    }
414    
415    reg->current.i = data;
416
417    if (VERBOSE || (NORMAL && (changed || !ever_seen)))
418       fprintf(stderr, "\n");
419
420    return changed;
421 }
422
423
424 static int print_float_reg_assignment( struct reg *reg, float data )
425 {
426    int changed = (reg->current.f != data);
427    int newmin = (data < reg->vmin);
428    int newmax = (data > reg->vmax);
429
430    if (VERBOSE || (NORMAL && (newmin || newmax || changed)))
431       fprintf(stderr, "   %s <-- %.3f", get_reg_name(reg), data);
432
433    if (NORMAL) {
434       if (newmin) {
435          fprintf(stderr, " *** NEW MIN (prev %.3f)", reg->vmin);
436          reg->vmin = data;
437       }
438       else if (newmax) {
439          fprintf(stderr, " *** NEW MAX (prev %.3f)", reg->vmax);
440          reg->vmax = data;
441       }
442       else if (changed) {
443          fprintf(stderr, " *** CHANGED");
444       }
445    }
446
447    reg->current.f = data;
448
449    if (VERBOSE || (NORMAL && (newmin || newmax || changed)))
450       fprintf(stderr, "\n");
451
452    return changed;
453 }
454
455 static int print_reg_assignment( struct reg *reg, int data )
456 {
457    reg->flags |= TOUCHED;
458    if (reg->flags & ISFLOAT)
459       return print_float_reg_assignment( reg, *(float *)&data );
460    else
461       return print_int_reg_assignment( reg, data );
462 }
463
464 static void print_reg( struct reg *reg )
465 {
466    if (reg->flags & TOUCHED) {
467       if (reg->flags & ISFLOAT) {
468          fprintf(stderr, "   %s == %f\n", get_reg_name(reg), reg->current.f);
469       } else {
470          fprintf(stderr, "   %s == 0x%x\n", get_reg_name(reg), reg->current.i);
471       }
472    }
473 }
474
475
476 static void dump_state( void )
477 {
478    int i;
479
480    for (i = 0 ; i < Elements(regs) ; i++) 
481       print_reg( &regs[i] );
482
483    for (i = 0 ; i < Elements(scalars) ; i++) 
484       print_reg( &scalars[i] );
485
486    for (i = 0 ; i < Elements(vectors) ; i++) 
487       print_reg( &vectors[i] );
488 }
489
490
491
492 static int radeon_emit_packets( 
493    drm_radeon_cmd_header_t header,
494    drm_radeon_cmd_buffer_t *cmdbuf )
495 {
496    int id = (int)header.packet.packet_id;
497    int sz = packet[id].len;
498    int *data = (int *)cmdbuf->buf;
499    int i;
500    
501    if (sz * sizeof(int) > cmdbuf->bufsz) {
502       fprintf(stderr, "Packet overflows cmdbuf\n");      
503       return -EINVAL;
504    }
505
506    if (!packet[id].name) {
507       fprintf(stderr, "*** Unknown packet 0 nr %d\n", id );
508       return -EINVAL;
509    }
510
511    
512    if (VERBOSE) 
513       fprintf(stderr, "Packet 0 reg %s nr %d\n", packet[id].name, sz );
514
515    for ( i = 0 ; i < sz ; i++) {
516       struct reg *reg = lookup_reg( regs, packet[id].start + i*4 );
517       if (print_reg_assignment( reg, data[i] ))
518          total_changed++;
519       total++;
520    }
521
522    cmdbuf->buf += sz * sizeof(int);
523    cmdbuf->bufsz -= sz * sizeof(int);
524    return 0;
525 }
526
527
528 static int radeon_emit_scalars( 
529    drm_radeon_cmd_header_t header,
530    drm_radeon_cmd_buffer_t *cmdbuf )
531 {
532    int sz = header.scalars.count;
533    int *data = (int *)cmdbuf->buf;
534    int start = header.scalars.offset;
535    int stride = header.scalars.stride;
536    int i;
537
538    if (VERBOSE)
539       fprintf(stderr, "emit scalars, start %d stride %d nr %d (end %d)\n",
540               start, stride, sz, start + stride * sz);
541
542
543    for (i = 0 ; i < sz ; i++, start += stride) {
544       struct reg *reg = lookup_reg( scalars, start );
545       if (print_reg_assignment( reg, data[i] ))
546          total_changed++;
547       total++;
548    }
549          
550    cmdbuf->buf += sz * sizeof(int);
551    cmdbuf->bufsz -= sz * sizeof(int);
552    return 0;
553 }
554
555
556 static int radeon_emit_scalars2( 
557    drm_radeon_cmd_header_t header,
558    drm_radeon_cmd_buffer_t *cmdbuf )
559 {
560    int sz = header.scalars.count;
561    int *data = (int *)cmdbuf->buf;
562    int start = header.scalars.offset + 0x100;
563    int stride = header.scalars.stride;
564    int i;
565
566    if (VERBOSE)
567       fprintf(stderr, "emit scalars2, start %d stride %d nr %d (end %d)\n",
568               start, stride, sz, start + stride * sz);
569
570    if (start + stride * sz > 257) {
571       fprintf(stderr, "emit scalars OVERFLOW %d/%d/%d\n", start, stride, sz);
572       return -1;
573    }
574
575    for (i = 0 ; i < sz ; i++, start += stride) {
576       struct reg *reg = lookup_reg( scalars, start );
577       if (print_reg_assignment( reg, data[i] ))
578          total_changed++;
579       total++;
580    }
581          
582    cmdbuf->buf += sz * sizeof(int);
583    cmdbuf->bufsz -= sz * sizeof(int);
584    return 0;
585 }
586
587 /* Check: inf/nan/extreme-size?
588  * Check: table start, end, nr, etc.
589  */
590 static int radeon_emit_vectors( 
591    drm_radeon_cmd_header_t header,
592    drm_radeon_cmd_buffer_t *cmdbuf )
593 {
594    int sz = header.vectors.count;
595    int *data = (int *)cmdbuf->buf;
596    int start = header.vectors.offset;
597    int stride = header.vectors.stride;
598    int i,j;
599
600    if (VERBOSE)
601       fprintf(stderr, "emit vectors, start %d stride %d nr %d (end %d) (0x%x)\n",
602               start, stride, sz, start + stride * sz, header.i);
603
604 /*    if (start + stride * (sz/4) > 128) { */
605 /*       fprintf(stderr, "emit vectors OVERFLOW %d/%d/%d\n", start, stride, sz); */
606 /*       return -1; */
607 /*    } */
608
609    for (i = 0 ; i < sz ;  start += stride) {
610       int changed = 0;
611       for (j = 0 ; j < 4 ; i++,j++) {
612          struct reg *reg = lookup_reg( vectors, start*4+j );
613          if (print_reg_assignment( reg, data[i] ))
614             changed = 1;
615       }
616       if (changed)
617          total_changed += 4;
618       total += 4;
619    }
620          
621
622    cmdbuf->buf += sz * sizeof(int);
623    cmdbuf->bufsz -= sz * sizeof(int);
624    return 0;
625 }
626
627
628 static int print_vertex_format( int vfmt )
629 {
630    if (NORMAL) {
631       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",
632               "vertex format",
633               vfmt,
634               "xy,",
635               (vfmt & RADEON_CP_VC_FRMT_Z) ? "z," : "",
636               (vfmt & RADEON_CP_VC_FRMT_W0) ? "w0," : "",
637               (vfmt & RADEON_CP_VC_FRMT_FPCOLOR) ? "fpcolor," : "",
638               (vfmt & RADEON_CP_VC_FRMT_FPALPHA) ? "fpalpha," : "",
639               (vfmt & RADEON_CP_VC_FRMT_PKCOLOR) ? "pkcolor," : "",
640               (vfmt & RADEON_CP_VC_FRMT_FPSPEC) ? "fpspec," : "",
641               (vfmt & RADEON_CP_VC_FRMT_FPFOG) ? "fpfog," : "",
642               (vfmt & RADEON_CP_VC_FRMT_PKSPEC) ? "pkspec," : "",
643               (vfmt & RADEON_CP_VC_FRMT_ST0) ? "st0," : "",
644               (vfmt & RADEON_CP_VC_FRMT_ST1) ? "st1," : "",
645               (vfmt & RADEON_CP_VC_FRMT_Q1) ? "q1," : "",
646               (vfmt & RADEON_CP_VC_FRMT_ST2) ? "st2," : "",
647               (vfmt & RADEON_CP_VC_FRMT_Q2) ? "q2," : "",
648               (vfmt & RADEON_CP_VC_FRMT_ST3) ? "st3," : "",
649               (vfmt & RADEON_CP_VC_FRMT_Q3) ? "q3," : "",
650               (vfmt & RADEON_CP_VC_FRMT_Q0) ? "q0," : "",
651               (vfmt & RADEON_CP_VC_FRMT_N0) ? "n0," : "",
652               (vfmt & RADEON_CP_VC_FRMT_XY1) ? "xy1," : "",
653               (vfmt & RADEON_CP_VC_FRMT_Z1) ? "z1," : "",
654               (vfmt & RADEON_CP_VC_FRMT_W1) ? "w1," : "",
655               (vfmt & RADEON_CP_VC_FRMT_N1) ? "n1," : "");
656
657    
658 /*       if (!find_or_add_value( &others[V_VTXFMT], vfmt )) */
659 /*       fprintf(stderr, " *** NEW VALUE"); */
660
661       fprintf(stderr, "\n");
662    }
663
664    return 0;
665 }
666
667 static char *primname[0xf] = {
668    "NONE",
669    "POINTS",
670    "LINES",
671    "LINE_STRIP",
672    "TRIANGLES",
673    "TRIANGLE_FAN",
674    "TRIANGLE_STRIP",
675    "TRI_TYPE_2",
676    "RECT_LIST",
677    "3VRT_POINTS",
678    "3VRT_LINES",
679 };
680
681 static int print_prim_and_flags( int prim )
682 {
683    int numverts;
684    
685    if (NORMAL)
686       fprintf(stderr, "   %s(%x): %s%s%s%s%s%s%s\n",
687               "prim flags",
688               prim,
689               ((prim & 0x30) == RADEON_CP_VC_CNTL_PRIM_WALK_IND) ? "IND," : "",
690               ((prim & 0x30) == RADEON_CP_VC_CNTL_PRIM_WALK_LIST) ? "LIST," : "",
691               ((prim & 0x30) == RADEON_CP_VC_CNTL_PRIM_WALK_RING) ? "RING," : "",
692               (prim & RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA) ? "RGBA," : "BGRA, ",
693               (prim & RADEON_CP_VC_CNTL_MAOS_ENABLE) ? "MAOS," : "",
694               (prim & RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE) ? "RADEON," : "",
695               (prim & RADEON_CP_VC_CNTL_TCL_ENABLE) ? "TCL," : "");
696
697    if ((prim & 0xf) > RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_LINE_LIST) {
698       fprintf(stderr, "   *** Bad primitive: %x\n", prim & 0xf);
699       return -1;
700    }
701
702    numverts = prim>>16;
703    
704    if (NORMAL)
705       fprintf(stderr, "   prim: %s numverts %d\n", primname[prim&0xf], numverts);
706
707    switch (prim & 0xf) {
708    case RADEON_CP_VC_CNTL_PRIM_TYPE_NONE:
709    case RADEON_CP_VC_CNTL_PRIM_TYPE_POINT:
710       if (numverts < 1) {
711          fprintf(stderr, "Bad nr verts for line %d\n", numverts);
712          return -1;
713       }
714       break;
715    case RADEON_CP_VC_CNTL_PRIM_TYPE_LINE:
716       if ((numverts & 1) || numverts == 0) {
717          fprintf(stderr, "Bad nr verts for line %d\n", numverts);
718          return -1;
719       }
720       break;
721    case RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP:
722       if (numverts < 2) {
723          fprintf(stderr, "Bad nr verts for line_strip %d\n", numverts);
724          return -1;
725       }
726       break;
727    case RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST:
728    case RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_POINT_LIST:
729    case RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_LINE_LIST:
730    case RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST:
731       if (numverts % 3 || numverts == 0) {
732          fprintf(stderr, "Bad nr verts for tri %d\n", numverts);
733          return -1;
734       }
735       break;
736    case RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN:
737    case RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP:
738       if (numverts < 3) {
739          fprintf(stderr, "Bad nr verts for strip/fan %d\n", numverts);
740          return -1;
741       }
742       break;
743    default:
744       fprintf(stderr, "Bad primitive\n");
745       return -1;
746    }    
747    return 0;
748 }
749
750 /* build in knowledge about each packet type
751  */
752 static int radeon_emit_packet3( drm_radeon_cmd_buffer_t *cmdbuf )
753 {
754    int cmdsz;
755    int *cmd = (int *)cmdbuf->buf;
756    int *tmp;
757    int i, stride, size, start;
758
759    cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16);
760
761    if ((cmd[0] & RADEON_CP_PACKET_MASK) != RADEON_CP_PACKET3 ||
762        cmdsz * 4 > cmdbuf->bufsz ||
763        cmdsz > RADEON_CP_PACKET_MAX_DWORDS) {
764       fprintf(stderr, "Bad packet\n");
765       return -EINVAL;
766    }
767
768    switch( cmd[0] & ~RADEON_CP_PACKET_COUNT_MASK ) {
769    case RADEON_CP_PACKET3_NOP:
770       if (NORMAL)
771          fprintf(stderr, "PACKET3_NOP, %d dwords\n", cmdsz);
772       break;
773    case RADEON_CP_PACKET3_NEXT_CHAR:
774       if (NORMAL)
775          fprintf(stderr, "PACKET3_NEXT_CHAR, %d dwords\n", cmdsz);
776       break;
777    case RADEON_CP_PACKET3_PLY_NEXTSCAN:
778       if (NORMAL)
779          fprintf(stderr, "PACKET3_PLY_NEXTSCAN, %d dwords\n", cmdsz);
780       break;
781    case RADEON_CP_PACKET3_SET_SCISSORS:
782       if (NORMAL)
783          fprintf(stderr, "PACKET3_SET_SCISSORS, %d dwords\n", cmdsz);
784       break;
785    case RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM:
786       if (NORMAL)
787          fprintf(stderr, "PACKET3_3D_RNDR_GEN_INDX_PRIM, %d dwords\n",
788               cmdsz);
789       break;
790    case RADEON_CP_PACKET3_LOAD_MICROCODE:
791       if (NORMAL)
792          fprintf(stderr, "PACKET3_LOAD_MICROCODE, %d dwords\n", cmdsz);
793       break;
794    case RADEON_CP_PACKET3_WAIT_FOR_IDLE:
795       if (NORMAL)
796          fprintf(stderr, "PACKET3_WAIT_FOR_IDLE, %d dwords\n", cmdsz);
797       break;
798
799    case RADEON_CP_PACKET3_3D_DRAW_VBUF:
800       if (NORMAL)
801          fprintf(stderr, "PACKET3_3D_DRAW_VBUF, %d dwords\n", cmdsz);
802       print_vertex_format(cmd[1]);
803       print_prim_and_flags(cmd[2]);
804       break;
805
806    case RADEON_CP_PACKET3_3D_DRAW_IMMD:
807       if (NORMAL)
808          fprintf(stderr, "PACKET3_3D_DRAW_IMMD, %d dwords\n", cmdsz);
809       break;
810    case RADEON_CP_PACKET3_3D_DRAW_INDX: {
811       int neltdwords;
812       if (NORMAL)
813          fprintf(stderr, "PACKET3_3D_DRAW_INDX, %d dwords\n", cmdsz);
814       print_vertex_format(cmd[1]);
815       print_prim_and_flags(cmd[2]);
816       neltdwords = cmd[2]>>16;
817       neltdwords += neltdwords & 1;
818       neltdwords /= 2;
819       if (neltdwords + 3 != cmdsz)
820          fprintf(stderr, "Mismatch in DRAW_INDX, %d vs cmdsz %d\n",
821                  neltdwords, cmdsz);
822       break;
823    }
824    case RADEON_CP_PACKET3_LOAD_PALETTE:
825       if (NORMAL)
826          fprintf(stderr, "PACKET3_LOAD_PALETTE, %d dwords\n", cmdsz);
827       break;
828    case RADEON_CP_PACKET3_3D_LOAD_VBPNTR:
829       if (NORMAL) {
830          fprintf(stderr, "PACKET3_3D_LOAD_VBPNTR, %d dwords\n", cmdsz);
831          fprintf(stderr, "   nr arrays: %d\n", cmd[1]);
832       }
833
834       if (cmd[1]/2 + cmd[1]%2 != cmdsz - 3) {
835          fprintf(stderr, "  ****** MISMATCH %d/%d *******\n",
836                  cmd[1]/2 + cmd[1]%2 + 3, cmdsz);
837          return -EINVAL;
838       }
839
840       if (NORMAL) {
841          tmp = cmd+2;
842          for (i = 0 ; i < cmd[1] ; i++) {
843             if (i & 1) {
844                stride = (tmp[0]>>24) & 0xff;
845                size = (tmp[0]>>16) & 0xff;
846                start = tmp[2];
847                tmp += 3;
848             }
849             else {
850                stride = (tmp[0]>>8) & 0xff;
851                size = (tmp[0]) & 0xff;
852                start = tmp[1];
853             }
854             fprintf(stderr, "   array %d: start 0x%x vsize %d vstride %d\n",
855                     i, start, size, stride );
856          }
857       }
858       break;
859    case RADEON_CP_PACKET3_CNTL_PAINT:
860       if (NORMAL)
861          fprintf(stderr, "PACKET3_CNTL_PAINT, %d dwords\n", cmdsz);
862       break;
863    case RADEON_CP_PACKET3_CNTL_BITBLT:
864       if (NORMAL)
865          fprintf(stderr, "PACKET3_CNTL_BITBLT, %d dwords\n", cmdsz);
866       break;
867    case RADEON_CP_PACKET3_CNTL_SMALLTEXT:
868       if (NORMAL)
869          fprintf(stderr, "PACKET3_CNTL_SMALLTEXT, %d dwords\n", cmdsz);
870       break;
871    case RADEON_CP_PACKET3_CNTL_HOSTDATA_BLT:
872       if (NORMAL)
873          fprintf(stderr, "PACKET3_CNTL_HOSTDATA_BLT, %d dwords\n", 
874               cmdsz);
875       break;
876    case RADEON_CP_PACKET3_CNTL_POLYLINE:
877       if (NORMAL)
878          fprintf(stderr, "PACKET3_CNTL_POLYLINE, %d dwords\n", cmdsz);
879       break;
880    case RADEON_CP_PACKET3_CNTL_POLYSCANLINES:
881       if (NORMAL)
882          fprintf(stderr, "PACKET3_CNTL_POLYSCANLINES, %d dwords\n", 
883               cmdsz);
884       break;
885    case RADEON_CP_PACKET3_CNTL_PAINT_MULTI:
886       if (NORMAL)
887          fprintf(stderr, "PACKET3_CNTL_PAINT_MULTI, %d dwords\n", 
888               cmdsz);
889       break;
890    case RADEON_CP_PACKET3_CNTL_BITBLT_MULTI:
891       if (NORMAL)
892          fprintf(stderr, "PACKET3_CNTL_BITBLT_MULTI, %d dwords\n", 
893               cmdsz);
894       break;
895    case RADEON_CP_PACKET3_CNTL_TRANS_BITBLT:
896       if (NORMAL)
897          fprintf(stderr, "PACKET3_CNTL_TRANS_BITBLT, %d dwords\n", 
898               cmdsz);
899       break;
900    default:
901       fprintf(stderr, "UNKNOWN PACKET, %d dwords\n", cmdsz);
902       break;
903    }
904       
905    cmdbuf->buf += cmdsz * 4;
906    cmdbuf->bufsz -= cmdsz * 4;
907    return 0;
908 }
909
910
911 /* Check cliprects for bounds, then pass on to above:
912  */
913 static int radeon_emit_packet3_cliprect( drm_radeon_cmd_buffer_t *cmdbuf )
914 {   
915    drm_clip_rect_t *boxes = cmdbuf->boxes;
916    int i = 0;
917
918    if (VERBOSE && total_changed) {
919       dump_state();
920       total_changed = 0;
921    }
922    else fprintf(stderr, "total_changed zero\n");
923
924    if (NORMAL) {
925       do {
926          if ( i < cmdbuf->nbox ) {
927             fprintf(stderr, "Emit box %d/%d %d,%d %d,%d\n",
928                     i, cmdbuf->nbox,
929                     boxes[i].x1, boxes[i].y1, boxes[i].x2, boxes[i].y2);
930          }
931       } while ( ++i < cmdbuf->nbox );
932    }
933
934    if (cmdbuf->nbox == 1)
935       cmdbuf->nbox = 0;
936
937    return radeon_emit_packet3( cmdbuf );
938 }
939
940
941 int radeonSanityCmdBuffer( radeonContextPtr rmesa,
942                            int nbox,
943                            drm_clip_rect_t *boxes )
944 {
945    int idx;
946    drm_radeon_cmd_buffer_t cmdbuf;
947    drm_radeon_cmd_header_t header;
948    static int inited = 0;
949
950    if (!inited) {
951       init_regs();
952       inited = 1;
953    }
954
955    cmdbuf.buf = rmesa->store.cmd_buf;
956    cmdbuf.bufsz = rmesa->store.cmd_used;
957    cmdbuf.boxes = boxes;
958    cmdbuf.nbox = nbox;
959
960    while ( cmdbuf.bufsz >= sizeof(header) ) {
961                 
962       header.i = *(int *)cmdbuf.buf;
963       cmdbuf.buf += sizeof(header);
964       cmdbuf.bufsz -= sizeof(header);
965
966       switch (header.header.cmd_type) {
967       case RADEON_CMD_PACKET: 
968          if (radeon_emit_packets( header, &cmdbuf )) {
969             fprintf(stderr,"radeon_emit_packets failed\n");
970             return -EINVAL;
971          }
972          break;
973
974       case RADEON_CMD_SCALARS:
975          if (radeon_emit_scalars( header, &cmdbuf )) {
976             fprintf(stderr,"radeon_emit_scalars failed\n");
977             return -EINVAL;
978          }
979          break;
980
981       case RADEON_CMD_SCALARS2:
982          if (radeon_emit_scalars2( header, &cmdbuf )) {
983             fprintf(stderr,"radeon_emit_scalars failed\n");
984             return -EINVAL;
985          }
986          break;
987
988       case RADEON_CMD_VECTORS:
989          if (radeon_emit_vectors( header, &cmdbuf )) {
990             fprintf(stderr,"radeon_emit_vectors failed\n");
991             return -EINVAL;
992          }
993          break;
994
995       case RADEON_CMD_DMA_DISCARD:
996          idx = header.dma.buf_idx;
997          if (NORMAL)
998             fprintf(stderr, "RADEON_CMD_DMA_DISCARD buf %d\n", idx);
999          bufs++;
1000          break;
1001
1002       case RADEON_CMD_PACKET3:
1003          if (radeon_emit_packet3( &cmdbuf )) {
1004             fprintf(stderr,"radeon_emit_packet3 failed\n");
1005             return -EINVAL;
1006          }
1007          break;
1008
1009       case RADEON_CMD_PACKET3_CLIP:
1010          if (radeon_emit_packet3_cliprect( &cmdbuf )) {
1011             fprintf(stderr,"radeon_emit_packet3_clip failed\n");
1012             return -EINVAL;
1013          }
1014          break;
1015
1016       case RADEON_CMD_WAIT:
1017          break;
1018
1019       default:
1020          fprintf(stderr,"bad cmd_type %d at %p\n", 
1021                    header.header.cmd_type,
1022                    cmdbuf.buf - sizeof(header));
1023          return -EINVAL;
1024       }
1025    }
1026
1027    if (0)
1028    {
1029       static int n = 0;
1030       n++;
1031       if (n == 10) {
1032          fprintf(stderr, "Bufs %d Total emitted %d real changes %d (%.2f%%)\n",
1033                  bufs,
1034                  total, total_changed, 
1035                  ((float)total_changed/(float)total*100.0));
1036          fprintf(stderr, "Total emitted per buf: %.2f\n",
1037                  (float)total/(float)bufs);
1038          fprintf(stderr, "Real changes per buf: %.2f\n",
1039                  (float)total_changed/(float)bufs);
1040
1041          bufs = n = total = total_changed = 0;
1042       }
1043    }
1044
1045    return 0;
1046 }