intel/isl/format: Add field locations informations to channel_layout
[mesa.git] / src / intel / isl / gen_format_layout.py
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(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
65 const struct isl_format_layout
66 isl_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.start}, ${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
92 bool
93 isl_format_is_valid(enum isl_format format)
94 {
95 if (format >= sizeof(isl_format_layouts) / sizeof(isl_format_layouts[0]))
96 return false;
97 return isl_format_layouts[format].name;
98 }
99
100 enum isl_format
101 isl_format_srgb_to_linear(enum isl_format format)
102 {
103 switch (format) {
104 % for srgb, rgb in srgb_to_linear_map:
105 case ISL_FORMAT_${srgb}:
106 return ISL_FORMAT_${rgb};
107 %endfor
108 default:
109 return format;
110 }
111 }
112 """)
113
114
115 class Channel(object):
116 """Class representing a Channel.
117
118 Converts the csv encoded data into the format that the template (and thus
119 the consuming C code) expects.
120
121 """
122 # If the csv file grew very large this class could be put behind a factory
123 # to increase efficiency. Right now though it's fast enough that It didn't
124 # seem worthwhile to add all of the boilerplate
125 _types = {
126 'x': 'void',
127 'r': 'raw',
128 'un': 'unorm',
129 'sn': 'snorm',
130 'uf': 'ufloat',
131 'sf': 'sfloat',
132 'ux': 'ufixed',
133 'sx': 'sfixed',
134 'ui': 'uint',
135 'si': 'sint',
136 'us': 'uscaled',
137 'ss': 'sscaled',
138 }
139 _splitter = re.compile(r'\s*(?P<type>[a-z]+)(?P<size>[0-9]+)')
140
141 def __init__(self, line):
142 # If the line is just whitespace then just set everything to None to
143 # save on the regex cost and let the template skip on None.
144 if line.isspace():
145 self.size = None
146 self.type = None
147 else:
148 grouped = self._splitter.match(line)
149 self.type = self._types[grouped.group('type')].upper()
150 self.size = int(grouped.group('size'))
151
152 # Default the start bit to -1
153 self.start = -1;
154
155
156 class Format(object):
157 """Class taht contains all values needed by the template."""
158 def __init__(self, line):
159 # pylint: disable=invalid-name
160 self.name = line[0].strip()
161
162 # Future division makes this work in python 2.
163 self.bpb = int(line[1])
164 self.bw = line[2].strip()
165 self.bh = line[3].strip()
166 self.bd = line[4].strip()
167 self.r = Channel(line[5])
168 self.g = Channel(line[6])
169 self.b = Channel(line[7])
170 self.a = Channel(line[8])
171 self.l = Channel(line[9])
172 self.i = Channel(line[10])
173 self.p = Channel(line[11])
174
175 # Set the start bit value for each channel
176 self.order = line[12].strip()
177 bit = 0
178 for c in self.order:
179 chan = getattr(self, c)
180 chan.start = bit;
181 bit = bit + chan.size
182
183 # alpha doesn't have a colorspace of it's own.
184 self.colorspace = line[13].strip().upper()
185 if self.colorspace in ['', 'ALPHA']:
186 self.colorspace = 'NONE'
187
188 # This sets it to the line value, or if it's an empty string 'NONE'
189 self.txc = line[14].strip().upper() or 'NONE'
190
191
192 def reader(csvfile):
193 """Wrapper around csv.reader that skips comments and blanks."""
194 # csv.reader actually reads the file one line at a time (it was designed to
195 # open excel generated sheets), so hold the file until all of the lines are
196 # read.
197 with open(csvfile, 'r') as f:
198 for line in csv.reader(f):
199 if line and not line[0].startswith('#'):
200 yield line
201
202 def get_srgb_to_linear_map(formats):
203 """Compute a map from sRGB to linear formats.
204
205 This function uses some probably somewhat fragile string munging to do
206 the conversion. However, we do assert that, if it's SRGB, the munging
207 succeeded so that gives some safety.
208 """
209 names = {f.name for f in formats}
210 for fmt in formats:
211 if fmt.colorspace != 'SRGB':
212 continue
213
214 replacements = [
215 ('_SRGB', ''),
216 ('SRGB', 'RGB'),
217 ('U8SRGB', 'FLT16'),
218 ]
219
220 found = False;
221 for rep in replacements:
222 rgb_name = fmt.name.replace(rep[0], rep[1])
223 if rgb_name in names:
224 found = True
225 yield fmt.name, rgb_name
226 break;
227
228 # We should have found a format name
229 assert found
230
231 def main():
232 """Main function."""
233 parser = argparse.ArgumentParser()
234 parser.add_argument('--csv', action='store', help='The CSV file to parse.')
235 parser.add_argument(
236 '--out',
237 action='store',
238 help='The location to put the generated C file.')
239 args = parser.parse_args()
240
241 # This generator opens and writes the file itself, and it does so in bytes
242 # mode. This solves both python 2 vs 3 problems and solves the locale
243 # problem: Unicode can be rendered even if the shell calling this script
244 # doesn't.
245 with open(args.out, 'wb') as f:
246 formats = [Format(l) for l in reader(args.csv)]
247 try:
248 # This basically does lazy evaluation and initialization, which
249 # saves on memory and startup overhead.
250 f.write(TEMPLATE.render(
251 formats = formats,
252 srgb_to_linear_map = list(get_srgb_to_linear_map(formats)),
253 ))
254 except Exception:
255 # In the even there's an error this imports some helpers from mako
256 # to print a useful stack trace and prints it, then exits with
257 # status 1, if python is run with debug; otherwise it just raises
258 # the exception
259 if __debug__:
260 import sys
261 from mako import exceptions
262 print(exceptions.text_error_template().render(),
263 file=sys.stderr)
264 sys.exit(1)
265 raise
266
267
268 if __name__ == '__main__':
269 main()