15c887af5e697491d493cc69803a597007dbfe75
[mesa.git] / src / gallium / auxiliary / util / u_format_parse.py
1 #!/usr/bin/env python
2
3 '''
4 /**************************************************************************
5 *
6 * Copyright 2009 VMware, Inc.
7 * All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the
11 * "Software"), to deal in the Software without restriction, including
12 * without limitation the rights to use, copy, modify, merge, publish,
13 * distribute, sub license, and/or sell copies of the Software, and to
14 * permit persons to whom the Software is furnished to do so, subject to
15 * the following conditions:
16 *
17 * The above copyright notice and this permission notice (including the
18 * next paragraph) shall be included in all copies or substantial portions
19 * of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
24 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
25 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 *
29 **************************************************************************/
30 '''
31
32
33 VOID, UNSIGNED, SIGNED, FIXED, FLOAT = range(5)
34
35 SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W, SWIZZLE_0, SWIZZLE_1, SWIZZLE_NONE, = range(7)
36
37 PLAIN = 'plain'
38
39
40 class Type:
41 '''Describe the type of a color channel.'''
42
43 def __init__(self, kind, norm, size):
44 self.kind = kind
45 self.norm = norm
46 self.size = size
47 self.sign = kind in (SIGNED, FIXED, FLOAT)
48
49 def __str__(self):
50 s = str(self.kind)
51 if self.norm:
52 s += 'n'
53 s += str(self.size)
54 return s
55
56 def __eq__(self, other):
57 return self.kind == other.kind and self.norm == other.norm and self.size == other.size
58
59
60 class Format:
61 '''Describe a pixel format.'''
62
63 def __init__(self, name, layout, block_width, block_height, in_types, out_swizzle, colorspace):
64 self.name = name
65 self.layout = layout
66 self.block_width = block_width
67 self.block_height = block_height
68 self.in_types = in_types
69 self.out_swizzle = out_swizzle
70 self.name = name
71 self.colorspace = colorspace
72
73 def __str__(self):
74 return self.name
75
76 def short_name(self):
77 '''Make up a short norm for a format, suitable to be used as suffix in
78 function names.'''
79
80 name = self.name
81 if name.startswith('PIPE_FORMAT_'):
82 name = name[len('PIPE_FORMAT_'):]
83 name = name.lower()
84 return name
85
86 def block_size(self):
87 size = 0
88 for type in self.in_types:
89 size += type.size
90 return size
91
92 def nr_channels(self):
93 nr_channels = 0
94 for type in self.in_types:
95 if type.size:
96 nr_channels += 1
97 return nr_channels
98
99 def is_array(self):
100 ref_type = self.in_types[0]
101 for type in self.in_types[1:]:
102 if type.size and (type.size != ref_type.size or type.size % 8):
103 return False
104 return True
105
106 def is_mixed(self):
107 ref_type = self.in_types[0]
108 for type in self.in_types[1:]:
109 if type.kind != VOID:
110 if type.kind != ref_type.kind:
111 return True
112 if type.norm != ref_type.norm:
113 return True
114 return False
115
116 def stride(self):
117 return self.block_size()/8
118
119
120 _kind_parse_map = {
121 '': VOID,
122 'x': VOID,
123 'u': UNSIGNED,
124 's': SIGNED,
125 'h': FIXED,
126 'f': FLOAT,
127 }
128
129 _swizzle_parse_map = {
130 'x': SWIZZLE_X,
131 'y': SWIZZLE_Y,
132 'z': SWIZZLE_Z,
133 'w': SWIZZLE_W,
134 '0': SWIZZLE_0,
135 '1': SWIZZLE_1,
136 '_': SWIZZLE_NONE,
137 }
138
139 def parse(filename):
140 '''Parse the format descrition in CSV format in terms of the
141 Type and Format classes above.'''
142
143 stream = open(filename)
144 formats = []
145 for line in stream:
146 try:
147 comment = line.index('#')
148 except ValueError:
149 pass
150 else:
151 line = line[:comment]
152 line = line.strip()
153 if not line:
154 continue
155 fields = [field.strip() for field in line.split(',')]
156 name = fields[0]
157 layout = fields[1]
158 block_width, block_height = map(int, fields[2:4])
159 in_types = []
160 for field in fields[4:8]:
161 if field:
162 kind = _kind_parse_map[field[0]]
163 if field[1] == 'n':
164 norm = True
165 size = int(field[2:])
166 else:
167 norm = False
168 size = int(field[1:])
169 else:
170 kind = VOID
171 norm = False
172 size = 0
173 in_type = Type(kind, norm, size)
174 in_types.append(in_type)
175 out_swizzle = [_swizzle_parse_map[swizzle] for swizzle in fields[8]]
176 colorspace = fields[9]
177 formats.append(Format(name, layout, block_width, block_height, in_types, out_swizzle, colorspace))
178 return formats
179