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