4 /**************************************************************************
6 * Copyright 2009 VMware, Inc.
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:
17 * The above copyright notice and this permission notice (including the
18 * next paragraph) shall be included in all copies or substantial portions
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.
29 **************************************************************************/
33 VOID, UNSIGNED, SIGNED, FIXED, FLOAT = range(5)
35 SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W, SWIZZLE_0, SWIZZLE_1, SWIZZLE_NONE, = range(7)
46 return (x & (x - 1)) == 0
49 VERY_LARGE = 99999999999999999999999
53 '''Describe the channel of a color channel.'''
55 def __init__(self, type, norm, pure, size, name = ''):
60 self.sign = type in (SIGNED, FIXED, FLOAT)
72 def __eq__(self, other):
73 return self.type == other.type and self.norm == other.norm and self.pure == other.pure and self.size == other.size
76 '''Maximum representable number.'''
77 if self.type == FLOAT:
79 if self.type == FIXED:
80 return (1 << (self.size/2)) - 1
83 if self.type == UNSIGNED:
84 return (1 << self.size) - 1
85 if self.type == SIGNED:
86 return (1 << (self.size - 1)) - 1
90 '''Minimum representable number.'''
91 if self.type == FLOAT:
93 if self.type == FIXED:
94 return -(1 << (self.size/2))
95 if self.type == UNSIGNED:
99 if self.type == SIGNED:
100 return -(1 << (self.size - 1))
105 '''Describe a pixel format.'''
107 def __init__(self, name, layout, block_width, block_height, channels, swizzles, colorspace):
110 self.block_width = block_width
111 self.block_height = block_height
112 self.channels = channels
113 self.swizzles = swizzles
115 self.colorspace = colorspace
120 def short_name(self):
121 '''Make up a short norm for a format, suitable to be used as suffix in
125 if name.startswith('PIPE_FORMAT_'):
126 name = name[len('PIPE_FORMAT_'):]
130 def block_size(self):
132 for channel in self.channels:
136 def nr_channels(self):
138 for channel in self.channels:
144 if self.layout != PLAIN:
146 ref_channel = self.channels[0]
147 for channel in self.channels[1:]:
148 if channel.size and (channel.size != ref_channel.size or channel.size % 8):
153 if self.layout != PLAIN:
155 ref_channel = self.channels[0]
156 if ref_channel.type == VOID:
157 ref_channel = self.channels[1]
158 for channel in self.channels[1:]:
159 if channel.type != VOID:
160 if channel.type != ref_channel.type:
162 if channel.norm != ref_channel.norm:
164 if channel.pure != ref_channel.pure:
169 return is_pot(self.block_size())
172 if self.layout != PLAIN:
174 for channel in self.channels:
175 if channel.type not in (VOID, UNSIGNED, SIGNED):
180 if self.layout != PLAIN:
182 for channel in self.channels:
183 if channel.type not in (VOID, FLOAT):
187 def is_bitmask(self):
188 if self.layout != PLAIN:
190 if self.block_size() not in (8, 16, 32):
192 for channel in self.channels:
193 if channel.type not in (VOID, UNSIGNED, SIGNED):
197 def inv_swizzles(self):
198 '''Return an array[4] of inverse swizzle terms'''
199 '''Only pick the first matching value to avoid l8 getting blue and i8 getting alpha'''
200 inv_swizzle = [None]*4
202 swizzle = self.swizzles[i]
203 if swizzle < 4 and inv_swizzle[swizzle] == None:
204 inv_swizzle[swizzle] = i
208 return self.block_size()/8
220 _swizzle_parse_map = {
231 '''Parse the format descrition in CSV format in terms of the
232 Channel and Format classes above.'''
234 stream = open(filename)
238 comment = line.index('#')
242 line = line[:comment]
247 fields = [field.strip() for field in line.split(',')]
251 block_width, block_height = map(int, fields[2:4])
253 swizzles = [_swizzle_parse_map[swizzle] for swizzle in fields[8]]
254 colorspace = fields[9]
258 if colorspace in (RGB, SRGB):
260 swizzle = swizzles[i]
262 names[swizzle] += 'rgba'[i]
263 elif colorspace == ZS:
265 swizzle = swizzles[i]
267 names[swizzle] += 'zs'[i]
274 names = ['x', 'y', 'z', 'w']
277 for i in range(0, 4):
278 field = fields[4 + i]
280 type = _type_parse_map[field[0]]
284 size = int(field[2:])
285 elif field[1] == 'p':
288 size = int(field[2:])
292 size = int(field[1:])
298 channel = Channel(type, norm, pure, size, names[i])
299 channels.append(channel)
301 format = Format(name, layout, block_width, block_height, channels, swizzles, colorspace)
302 formats.append(format)