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