Home | History | Annotate | Download | only in svgadump
      1 #!/usr/bin/env python
      2 '''
      3 Generates dumper for the SVGA 3D command stream using pygccxml.
      4 
      5 Jose Fonseca <jfonseca (at] vmware.com>
      6 '''
      7 
      8 copyright = '''
      9 /**********************************************************
     10  * Copyright 2009 VMware, Inc.  All rights reserved.
     11  *
     12  * Permission is hereby granted, free of charge, to any person
     13  * obtaining a copy of this software and associated documentation
     14  * files (the "Software"), to deal in the Software without
     15  * restriction, including without limitation the rights to use, copy,
     16  * modify, merge, publish, distribute, sublicense, and/or sell copies
     17  * of the Software, and to permit persons to whom the Software is
     18  * furnished to do so, subject to the following conditions:
     19  *
     20  * The above copyright notice and this permission notice shall be
     21  * included in all copies or substantial portions of the Software.
     22  *
     23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     26  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
     27  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
     28  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     29  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     30  * SOFTWARE.
     31  *
     32  **********************************************************/
     33  '''
     34 
     35 import os
     36 import sys
     37 
     38 from pygccxml import parser
     39 from pygccxml import declarations
     40 
     41 from pygccxml.declarations import algorithm
     42 from pygccxml.declarations import decl_visitor
     43 from pygccxml.declarations import type_traits
     44 from pygccxml.declarations import type_visitor
     45 
     46 
     47 enums = True
     48 
     49 
     50 class decl_dumper_t(decl_visitor.decl_visitor_t):
     51 
     52     def __init__(self, instance = '', decl = None):
     53         decl_visitor.decl_visitor_t.__init__(self)
     54         self._instance = instance
     55         self.decl = decl
     56 
     57     def clone(self):
     58         return decl_dumper_t(self._instance, self.decl)
     59 
     60     def visit_class(self):
     61         class_ = self.decl
     62         assert self.decl.class_type in ('struct', 'union')
     63 
     64         for variable in class_.variables():
     65             if variable.name != '':
     66                 #print 'variable = %r' % variable.name
     67                 dump_type(self._instance + '.' + variable.name, variable.type)
     68 
     69     def visit_enumeration(self):
     70         if enums:
     71             print '   switch(%s) {' % ("(*cmd)" + self._instance,)
     72             for name, value in self.decl.values:
     73                 print '   case %s:' % (name,)
     74                 print '      _debug_printf("\\t\\t%s = %s\\n");' % (self._instance, name)
     75                 print '      break;'
     76             print '   default:'
     77             print '      _debug_printf("\\t\\t%s = %%i\\n", %s);' % (self._instance, "(*cmd)" + self._instance)
     78             print '      break;'
     79             print '   }'
     80         else:
     81             print '   _debug_printf("\\t\\t%s = %%i\\n", %s);' % (self._instance, "(*cmd)" + self._instance)
     82 
     83 
     84 def dump_decl(instance, decl):
     85     dumper = decl_dumper_t(instance, decl)
     86     algorithm.apply_visitor(dumper, decl)
     87 
     88 
     89 class type_dumper_t(type_visitor.type_visitor_t):
     90 
     91     def __init__(self, instance, type_):
     92         type_visitor.type_visitor_t.__init__(self)
     93         self.instance = instance
     94         self.type = type_
     95 
     96     def clone(self):
     97         return type_dumper_t(self.instance, self.type)
     98 
     99     def visit_char(self):
    100         self.print_instance('%i')
    101         
    102     def visit_unsigned_char(self):
    103         self.print_instance('%u')
    104 
    105     def visit_signed_char(self):
    106         self.print_instance('%i')
    107     
    108     def visit_wchar(self):
    109         self.print_instance('%i')
    110         
    111     def visit_short_int(self):
    112         self.print_instance('%i')
    113         
    114     def visit_short_unsigned_int(self):
    115         self.print_instance('%u')
    116         
    117     def visit_bool(self):
    118         self.print_instance('%i')
    119         
    120     def visit_int(self):
    121         self.print_instance('%i')
    122         
    123     def visit_unsigned_int(self):
    124         self.print_instance('%u')
    125         
    126     def visit_long_int(self):
    127         self.print_instance('%li')
    128         
    129     def visit_long_unsigned_int(self):
    130         self.print_instance('%lu')
    131         
    132     def visit_long_long_int(self):
    133         self.print_instance('%lli')
    134         
    135     def visit_long_long_unsigned_int(self):
    136         self.print_instance('%llu')
    137         
    138     def visit_float(self):
    139         self.print_instance('%f')
    140         
    141     def visit_double(self):
    142         self.print_instance('%f')
    143         
    144     def visit_array(self):
    145         for i in range(type_traits.array_size(self.type)):
    146             dump_type(self.instance + '[%i]' % i, type_traits.base_type(self.type))
    147 
    148     def visit_pointer(self):
    149         self.print_instance('%p')
    150 
    151     def visit_declarated(self):
    152         #print 'decl = %r' % self.type.decl_string
    153         decl = type_traits.remove_declarated(self.type)
    154         dump_decl(self.instance, decl)
    155 
    156     def print_instance(self, format):
    157         print '   _debug_printf("\\t\\t%s = %s\\n", %s);' % (self.instance, format, "(*cmd)" + self.instance)
    158 
    159 
    160 def dump_type(instance, type_):
    161     type_ = type_traits.remove_alias(type_)
    162     visitor = type_dumper_t(instance, type_)
    163     algorithm.apply_visitor(visitor, type_)
    164 
    165 
    166 def dump_struct(decls, class_):
    167     print 'static void'
    168     print 'dump_%s(const %s *cmd)' % (class_.name, class_.name)
    169     print '{'
    170     dump_decl('', class_)
    171     print '}'
    172     print ''
    173 
    174 
    175 cmds = [
    176     ('SVGA_3D_CMD_SURFACE_DEFINE', 'SVGA3dCmdDefineSurface', (), 'SVGA3dSize'),
    177     ('SVGA_3D_CMD_SURFACE_DESTROY', 'SVGA3dCmdDestroySurface', (), None),
    178     ('SVGA_3D_CMD_SURFACE_COPY', 'SVGA3dCmdSurfaceCopy', (), 'SVGA3dCopyBox'),
    179     ('SVGA_3D_CMD_SURFACE_STRETCHBLT', 'SVGA3dCmdSurfaceStretchBlt', (), None),
    180     ('SVGA_3D_CMD_SURFACE_DMA', 'SVGA3dCmdSurfaceDMA', (), 'SVGA3dCopyBox'),
    181     ('SVGA_3D_CMD_CONTEXT_DEFINE', 'SVGA3dCmdDefineContext', (), None),
    182     ('SVGA_3D_CMD_CONTEXT_DESTROY', 'SVGA3dCmdDestroyContext', (), None),
    183     ('SVGA_3D_CMD_SETTRANSFORM', 'SVGA3dCmdSetTransform', (), None),
    184     ('SVGA_3D_CMD_SETZRANGE', 'SVGA3dCmdSetZRange', (), None),
    185     ('SVGA_3D_CMD_SETRENDERSTATE', 'SVGA3dCmdSetRenderState', (), 'SVGA3dRenderState'),
    186     ('SVGA_3D_CMD_SETRENDERTARGET', 'SVGA3dCmdSetRenderTarget', (), None),
    187     ('SVGA_3D_CMD_SETTEXTURESTATE', 'SVGA3dCmdSetTextureState', (), 'SVGA3dTextureState'),
    188     ('SVGA_3D_CMD_SETMATERIAL', 'SVGA3dCmdSetMaterial', (), None),
    189     ('SVGA_3D_CMD_SETLIGHTDATA', 'SVGA3dCmdSetLightData', (), None),
    190     ('SVGA_3D_CMD_SETLIGHTENABLED', 'SVGA3dCmdSetLightEnabled', (), None),
    191     ('SVGA_3D_CMD_SETVIEWPORT', 'SVGA3dCmdSetViewport', (), None),
    192     ('SVGA_3D_CMD_SETCLIPPLANE', 'SVGA3dCmdSetClipPlane', (), None),
    193     ('SVGA_3D_CMD_CLEAR', 'SVGA3dCmdClear', (), 'SVGA3dRect'),
    194     ('SVGA_3D_CMD_PRESENT', 'SVGA3dCmdPresent', (), 'SVGA3dCopyRect'),
    195     ('SVGA_3D_CMD_SHADER_DEFINE', 'SVGA3dCmdDefineShader', (), None),
    196     ('SVGA_3D_CMD_SHADER_DESTROY', 'SVGA3dCmdDestroyShader', (), None),
    197     ('SVGA_3D_CMD_SET_SHADER', 'SVGA3dCmdSetShader', (), None),
    198     ('SVGA_3D_CMD_SET_SHADER_CONST', 'SVGA3dCmdSetShaderConst', (), None),
    199     ('SVGA_3D_CMD_DRAW_PRIMITIVES', 'SVGA3dCmdDrawPrimitives', (('SVGA3dVertexDecl', 'numVertexDecls'), ('SVGA3dPrimitiveRange', 'numRanges')), 'SVGA3dVertexDivisor'),
    200     ('SVGA_3D_CMD_SETSCISSORRECT', 'SVGA3dCmdSetScissorRect', (), None),
    201     ('SVGA_3D_CMD_BEGIN_QUERY', 'SVGA3dCmdBeginQuery', (), None),
    202     ('SVGA_3D_CMD_END_QUERY', 'SVGA3dCmdEndQuery', (), None),
    203     ('SVGA_3D_CMD_WAIT_FOR_QUERY', 'SVGA3dCmdWaitForQuery', (), None),
    204     #('SVGA_3D_CMD_PRESENT_READBACK', None, (), None),
    205     ('SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN', 'SVGA3dCmdBlitSurfaceToScreen', (), 'SVGASignedRect'),
    206 ]
    207 
    208 def dump_cmds():
    209     print r'''
    210 void            
    211 svga_dump_command(uint32_t cmd_id, const void *data, uint32_t size)
    212 {
    213    const uint8_t *body = (const uint8_t *)data;
    214    const uint8_t *next = body + size;
    215 '''
    216     print '   switch(cmd_id) {'
    217     indexes = 'ijklmn'
    218     for id, header, body, footer in cmds:
    219         print '   case %s:' % id
    220         print '      _debug_printf("\\t%s\\n");' % id
    221         print '      {'
    222         print '         const %s *cmd = (const %s *)body;' % (header, header)
    223         if len(body):
    224             print '         unsigned ' + ', '.join(indexes[:len(body)]) + ';'
    225         print '         dump_%s(cmd);' % header
    226         print '         body = (const uint8_t *)&cmd[1];'
    227         for i in range(len(body)):
    228             struct, count = body[i]
    229             idx = indexes[i]
    230             print '         for(%s = 0; %s < cmd->%s; ++%s) {' % (idx, idx, count, idx)
    231             print '            dump_%s((const %s *)body);' % (struct, struct)
    232             print '            body += sizeof(%s);' % struct
    233             print '         }'
    234         if footer is not None:
    235             print '         while(body + sizeof(%s) <= next) {' % footer
    236             print '            dump_%s((const %s *)body);' % (footer, footer)
    237             print '            body += sizeof(%s);' % footer
    238             print '         }'
    239         if id == 'SVGA_3D_CMD_SHADER_DEFINE':
    240             print '         svga_shader_dump((const uint32_t *)body,'
    241             print '                          (unsigned)(next - body)/sizeof(uint32_t),'
    242             print '                          FALSE);'
    243             print '         body = next;'
    244         print '      }'
    245         print '      break;'
    246     print '   default:'
    247     print '      _debug_printf("\\t0x%08x\\n", cmd_id);'
    248     print '      break;'
    249     print '   }'
    250     print r'''
    251    while(body + sizeof(uint32_t) <= next) {
    252       _debug_printf("\t\t0x%08x\n", *(const uint32_t *)body);
    253       body += sizeof(uint32_t);
    254    }
    255    while(body + sizeof(uint32_t) <= next)
    256       _debug_printf("\t\t0x%02x\n", *body++);
    257 }
    258 '''
    259     print r'''
    260 void            
    261 svga_dump_commands(const void *commands, uint32_t size)
    262 {
    263    const uint8_t *next = commands;
    264    const uint8_t *last = next + size;
    265    
    266    assert(size % sizeof(uint32_t) == 0);
    267    
    268    while(next < last) {
    269       const uint32_t cmd_id = *(const uint32_t *)next;
    270 
    271       if(SVGA_3D_CMD_BASE <= cmd_id && cmd_id < SVGA_3D_CMD_MAX) {
    272          const SVGA3dCmdHeader *header = (const SVGA3dCmdHeader *)next;
    273          const uint8_t *body = (const uint8_t *)&header[1];
    274 
    275          next = body + header->size;
    276          if(next > last)
    277             break;
    278 
    279          svga_dump_command(cmd_id, body, header->size);
    280       }
    281       else if(cmd_id == SVGA_CMD_FENCE) {
    282          _debug_printf("\tSVGA_CMD_FENCE\n");
    283          _debug_printf("\t\t0x%08x\n", ((const uint32_t *)next)[1]);
    284          next += 2*sizeof(uint32_t);
    285       }
    286       else {
    287          _debug_printf("\t0x%08x\n", cmd_id);
    288          next += sizeof(uint32_t);
    289       }
    290    }
    291 }
    292 '''
    293 
    294 def main():
    295     print copyright.strip()
    296     print
    297     print '/**'
    298     print ' * @file'
    299     print ' * Dump SVGA commands.'
    300     print ' *'
    301     print ' * Generated automatically from svga3d_reg.h by svga_dump.py.'
    302     print ' */'
    303     print
    304     print '#include "svga_types.h"'
    305     print '#include "svga_shader_dump.h"'
    306     print '#include "svga3d_reg.h"'
    307     print
    308     print '#include "util/u_debug.h"'
    309     print '#include "svga_dump.h"'
    310     print
    311 
    312     config = parser.config_t(
    313         include_paths = ['../../../include', '../include'],
    314         compiler = 'gcc',
    315     )
    316 
    317     headers = [
    318         'svga_types.h', 
    319         'svga3d_reg.h', 
    320     ]
    321 
    322     decls = parser.parse(headers, config, parser.COMPILATION_MODE.ALL_AT_ONCE)
    323     global_ns = declarations.get_global_namespace(decls)
    324 
    325     names = set()
    326     for id, header, body, footer in cmds:
    327         names.add(header)
    328         for struct, count in body:
    329             names.add(struct)
    330         if footer is not None:
    331             names.add(footer)
    332 
    333     for class_ in global_ns.classes(lambda decl: decl.name in names):
    334         dump_struct(decls, class_)
    335 
    336     dump_cmds()
    337 
    338 
    339 if __name__ == '__main__':
    340     main()
    341