Home | History | Annotate | Download | only in isl
      1 # encoding=utf-8
      2 # Copyright  2016 Intel Corporation
      3 
      4 # Permission is hereby granted, free of charge, to any person obtaining a copy
      5 # of this software and associated documentation files (the "Software"), to deal
      6 # in the Software without restriction, including without limitation the rights
      7 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      8 # copies of the Software, and to permit persons to whom the Software is
      9 # furnished to do so, subject to the following conditions:
     10 
     11 # The above copyright notice and this permission notice shall be included in
     12 # all copies or substantial portions of the Software.
     13 
     14 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     17 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     18 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     19 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     20 # SOFTWARE.
     21 
     22 """Generates isl_format_layout.c."""
     23 
     24 from __future__ import absolute_import, division, print_function
     25 import argparse
     26 import csv
     27 import re
     28 import textwrap
     29 
     30 from mako import template
     31 
     32 # Load the template, ensure that __future__.division is imported, and set the
     33 # bytes encoding to be utf-8. This last bit is important to getting simple
     34 # consistent behavior for python 3 when we get there.
     35 TEMPLATE = template.Template(
     36     text=textwrap.dedent("""\
     37         /* This file is autogenerated by gen_format_layout.py. DO NOT EDIT! */
     38 
     39         /*
     40          * Copyright 2015 Intel Corporation
     41          *
     42          *  Permission is hereby granted, free of charge, to any person obtaining a
     43          *  copy of this software and associated documentation files (the "Software"),
     44          *  to deal in the Software without restriction, including without limitation
     45          *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
     46          *  and/or sell copies of the Software, and to permit persons to whom the
     47          *  Software is furnished to do so, subject to the following conditions:
     48          *
     49          *  The above copyright notice and this permission notice (including the next
     50          *  paragraph) shall be included in all copies or substantial portions of the
     51          *  Software.
     52          *
     53          *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     54          *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     55          *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     56          *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     57          *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     58          *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     59          *  IN THE SOFTWARE.
     60          */
     61 
     62         #include "isl/isl.h"
     63 
     64         const struct isl_format_layout
     65         isl_format_layouts[] = {
     66         % for format in formats:
     67           [ISL_FORMAT_${format.name}] = {
     68             .format = ISL_FORMAT_${format.name},
     69             .name = "ISL_FORMAT_${format.name}",
     70             .bpb = ${format.bpb},
     71             .bw = ${format.bw},
     72             .bh = ${format.bh},
     73             .bd = ${format.bd},
     74             .channels = {
     75             % for mask in ['r', 'g', 'b', 'a', 'l', 'i', 'p']:
     76               <% channel = getattr(format, mask, None) %>\\
     77               % if channel.type is not None:
     78                 .${mask} = { ISL_${channel.type}, ${channel.size} },
     79               % else:
     80                 .${mask} = {},
     81               % endif
     82             % endfor
     83             },
     84             .colorspace = ISL_COLORSPACE_${format.colorspace},
     85             .txc = ISL_TXC_${format.txc},
     86           },
     87 
     88         % endfor
     89         };
     90     """),
     91     future_imports=['division'],
     92     output_encoding='utf-8')
     93 
     94 
     95 class Channel(object):
     96     """Class representing a Channel.
     97 
     98     Converts the csv encoded data into the format that the template (and thus
     99     the consuming C code) expects.
    100 
    101     """
    102     # If the csv file grew very large this class could be put behind a factory
    103     # to increase efficiency. Right now though it's fast enough that It didn't
    104     # seem worthwhile to add all of the boilerplate
    105     _types = {
    106         'x': 'void',
    107         'r': 'raw',
    108         'un': 'unorm',
    109         'sn': 'snorm',
    110         'uf': 'ufloat',
    111         'sf': 'sfloat',
    112         'ux': 'ufixed',
    113         'sx': 'sfixed',
    114         'ui': 'uint',
    115         'si': 'sint',
    116         'us': 'uscaled',
    117         'ss': 'sscaled',
    118     }
    119     _splitter = re.compile(r'\s*(?P<type>[a-z]+)(?P<size>[0-9]+)')
    120 
    121     def __init__(self, line):
    122         # If the line is just whitespace then just set everything to None to
    123         # save on the regex cost and let the template skip on None.
    124         if line.isspace():
    125             self.size = None
    126             self.type = None
    127         else:
    128             grouped = self._splitter.match(line)
    129             self.type = self._types[grouped.group('type')].upper()
    130             self.size = grouped.group('size')
    131 
    132 
    133 class Format(object):
    134     """Class taht contains all values needed by the template."""
    135     def __init__(self, line):
    136         # pylint: disable=invalid-name
    137         self.name = line[0].strip()
    138 
    139         # Future division makes this work in python 2.
    140         self.bpb = int(line[1])
    141         self.bw = line[2].strip()
    142         self.bh = line[3].strip()
    143         self.bd = line[4].strip()
    144         self.r = Channel(line[5])
    145         self.g = Channel(line[6])
    146         self.b = Channel(line[7])
    147         self.a = Channel(line[8])
    148         self.l = Channel(line[9])
    149         self.i = Channel(line[10])
    150         self.p = Channel(line[11])
    151 
    152         # alpha doesn't have a colorspace of it's own.
    153         self.colorspace = line[12].strip().upper()
    154         if self.colorspace in ['', 'ALPHA']:
    155             self.colorspace = 'NONE'
    156 
    157         # This sets it to the line value, or if it's an empty string 'NONE'
    158         self.txc = line[13].strip().upper() or 'NONE'
    159 
    160 
    161 def reader(csvfile):
    162     """Wrapper around csv.reader that skips comments and blanks."""
    163     # csv.reader actually reads the file one line at a time (it was designed to
    164     # open excel generated sheets), so hold the file until all of the lines are
    165     # read.
    166     with open(csvfile, 'r') as f:
    167         for line in csv.reader(f):
    168             if line and not line[0].startswith('#'):
    169                 yield line
    170 
    171 
    172 def main():
    173     """Main function."""
    174     parser = argparse.ArgumentParser()
    175     parser.add_argument('--csv', action='store', help='The CSV file to parse.')
    176     parser.add_argument(
    177         '--out',
    178         action='store',
    179         help='The location to put the generated C file.')
    180     args = parser.parse_args()
    181 
    182     # This generator opens and writes the file itself, and it does so in bytes
    183     # mode. This solves both python 2 vs 3 problems and solves the locale
    184     # problem: Unicode can be rendered even if the shell calling this script
    185     # doesn't.
    186     with open(args.out, 'wb') as f:
    187         try:
    188             # This basically does lazy evaluation and initialization, which
    189             # saves on memory and startup overhead.
    190             f.write(TEMPLATE.render(
    191                 formats=(Format(l) for l in reader(args.csv))))
    192         except Exception:
    193             # In the even there's an error this imports some helpers from mako
    194             # to print a useful stack trace and prints it, then exits with
    195             # status 1, if python is run with debug; otherwise it just raises
    196             # the exception
    197             if __debug__:
    198                 import sys
    199                 from mako import exceptions
    200                 print(exceptions.text_error_template().render(),
    201                       file=sys.stderr)
    202                 sys.exit(1)
    203             raise
    204 
    205 
    206 if __name__ == '__main__':
    207     main()
    208