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