Home | History | Annotate | Download | only in radeon
      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 (at) 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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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  */
    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 
    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 
    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  */
    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  */
    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 
    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