1 /**************************************************************************
2 
3 Copyright 2002 ATI Technologies Inc., Ontario, Canada, and
4                      Tungsten Graphics Inc, Cedar Park, TX.
5 
6 All Rights Reserved.
7 
8 Permission is hereby granted, free of charge, to any person obtaining a
9 copy of this software and associated documentation files (the "Software"),
10 to deal in the Software without restriction, including without limitation
11 on the rights to use, copy, modify, merge, publish, distribute, sub
12 license, and/or sell copies of the Software, and to permit persons to whom
13 the Software is furnished to do so, subject to the following conditions:
14 
15 The above copyright notice and this permission notice (including the next
16 paragraph) shall be included in all copies or substantial portions of the
17 Software.
18 
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
22 ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
23 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
25 USE 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  */
58 static 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 
160 struct reg_names {
161    int idx;
162    const char *name;
163 };
164 
165 static 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 
271 static 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  */
287 static struct reg_names vector_names[] = {
288    { RADEON_VS_MATRIX_0_ADDR * 4, "MATRIX_0" },
289    { RADEON_VS_MATRIX_1_ADDR * 4, "MATRIX_1" },
290    { RADEON_VS_MATRIX_2_ADDR * 4, "MATRIX_2" },
291    { RADEON_VS_MATRIX_3_ADDR * 4, "MATRIX_3" },
292    { RADEON_VS_MATRIX_4_ADDR * 4, "MATRIX_4" },
293    { RADEON_VS_MATRIX_5_ADDR * 4, "MATRIX_5" },
294    { RADEON_VS_MATRIX_6_ADDR * 4, "MATRIX_6" },
295    { RADEON_VS_MATRIX_7_ADDR * 4, "MATRIX_7" },
296    { RADEON_VS_MATRIX_8_ADDR * 4, "MATRIX_8" },
297    { RADEON_VS_MATRIX_9_ADDR * 4, "MATRIX_9" },
298    { RADEON_VS_MATRIX_10_ADDR * 4, "MATRIX_10" },
299    { RADEON_VS_MATRIX_11_ADDR * 4, "MATRIX_11" },
300    { RADEON_VS_MATRIX_12_ADDR * 4, "MATRIX_12" },
301    { RADEON_VS_MATRIX_13_ADDR * 4, "MATRIX_13" },
302    { RADEON_VS_MATRIX_14_ADDR * 4, "MATRIX_14" },
303    { RADEON_VS_MATRIX_15_ADDR * 4, "MATRIX_15" },
304    { RADEON_VS_LIGHT_AMBIENT_ADDR * 4, "LIGHT_AMBIENT" },
305    { RADEON_VS_LIGHT_DIFFUSE_ADDR * 4, "LIGHT_DIFFUSE" },
306    { RADEON_VS_LIGHT_SPECULAR_ADDR * 4, "LIGHT_SPECULAR" },
307    { RADEON_VS_LIGHT_DIRPOS_ADDR * 4, "LIGHT_DIRPOS" },
308    { RADEON_VS_LIGHT_HWVSPOT_ADDR * 4, "LIGHT_HWVSPOT" },
309    { RADEON_VS_LIGHT_ATTENUATION_ADDR * 4, "LIGHT_ATTENUATION" },
310    { RADEON_VS_MATRIX_EYE2CLIP_ADDR * 4, "MATRIX_EYE2CLIP" },
311    { RADEON_VS_UCP_ADDR * 4, "UCP" },
312    { RADEON_VS_GLOBAL_AMBIENT_ADDR * 4, "GLOBAL_AMBIENT" },
313    { RADEON_VS_FOG_PARAM_ADDR * 4, "FOG_PARAM" },
314    { RADEON_VS_EYE_VECTOR_ADDR * 4, "EYE_VECTOR" },
315    { 1000, "" },
316 };
317 
318 union fi { float f; int i; };
319 
320 #define ISVEC   1
321 #define ISFLOAT 2
322 #define TOUCHED 4
323 
324 struct 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 
336 static struct reg regs[Elements(reg_names)+1];
337 static struct reg scalars[512+1];
338 static struct reg vectors[512*4+1];
339 
340 static int total, total_changed, bufs;
341 
init_regs(void)342 static 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 
find_or_add_value(struct reg * reg,int val)372 static 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 
lookup_reg(struct reg * tab,int reg)391 static 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 
get_reg_name(struct reg * reg)405 static 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 
print_int_reg_assignment(struct reg * reg,int data)432 static 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 
print_float_reg_assignment(struct reg * reg,float data)456 static 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 
print_reg_assignment(struct reg * reg,int data)487 static 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 
print_reg(struct reg * reg)498 static 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 
dump_state(void)510 static 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 
radeon_emit_packets(drm_radeon_cmd_header_t header,drm_radeon_cmd_buffer_t * cmdbuf)526 static 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 
radeon_emit_scalars(drm_radeon_cmd_header_t header,drm_radeon_cmd_buffer_t * cmdbuf)562 static 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 
radeon_emit_scalars2(drm_radeon_cmd_header_t header,drm_radeon_cmd_buffer_t * cmdbuf)590 static 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  */
radeon_emit_vectors(drm_radeon_cmd_header_t header,drm_radeon_cmd_buffer_t * cmdbuf)624 static 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 
print_vertex_format(int vfmt)662 static 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 
701 static 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 
print_prim_and_flags(int prim)715 static 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  */
radeon_emit_packet3(drm_radeon_cmd_buffer_t * cmdbuf)786 static 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  */
radeon_emit_packet3_cliprect(drm_radeon_cmd_buffer_t * cmdbuf)947 static 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 
radeonSanityCmdBuffer(r100ContextPtr rmesa,int nbox,drm_clip_rect_t * boxes)975 int 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