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, size, name = ''):
59 self.sign = type in (SIGNED, FIXED, FLOAT)
69 def __eq__(self, other):
70 return self.type == other.type and self.norm == other.norm and self.size == other.size
73 '''Maximum representable number.'''
74 if self.type == FLOAT:
76 if self.type == FIXED:
77 return (1 << (self.size/2)) - 1
80 if self.type == UNSIGNED:
81 return (1 << self.size) - 1
82 if self.type == SIGNED:
83 return (1 << (self.size - 1)) - 1
87 '''Minimum representable number.'''
88 if self.type == FLOAT:
90 if self.type == FIXED:
91 return -(1 << (self.size/2))
92 if self.type == UNSIGNED:
96 if self.type == SIGNED:
97 return -(1 << (self.size - 1))
102 '''Describe a pixel format.'''
104 def __init__(self, name, layout, block_width, block_height, channels, swizzles, colorspace):
107 self.block_width = block_width
108 self.block_height = block_height
109 self.channels = channels
110 self.swizzles = swizzles
112 self.colorspace = colorspace
117 def short_name(self):
118 '''Make up a short norm for a format, suitable to be used as suffix in
122 if name.startswith('PIPE_FORMAT_'):
123 name = name[len('PIPE_FORMAT_'):]
127 def block_size(self):
129 for channel in self.channels:
133 def nr_channels(self):
135 for channel in self.channels:
141 if self.layout != PLAIN:
143 ref_channel = self.channels[0]
144 for channel in self.channels[1:]:
145 if channel.size and (channel.size != ref_channel.size or channel.size % 8):
150 if self.layout != PLAIN:
152 ref_channel = self.channels[0]
153 if ref_channel.type == VOID:
154 ref_channel = self.channels[1]
155 for channel in self.channels[1:]:
156 if channel.type != VOID:
157 if channel.type != ref_channel.type:
159 if channel.norm != ref_channel.norm:
164 return is_pot(self.block_size())
167 if self.layout != PLAIN:
169 for channel in self.channels:
170 if channel.type not in (VOID, UNSIGNED, SIGNED):
175 if self.layout != PLAIN:
177 for channel in self.channels:
178 if channel.type not in (VOID, FLOAT):
182 def is_bitmask(self):
183 if self.layout != PLAIN:
185 if self.block_size() not in (8, 16, 32):
187 for channel in self.channels:
188 if channel.type not in (VOID, UNSIGNED, SIGNED):
192 def inv_swizzles(self):
193 '''Return an array[4] of inverse swizzle terms'''
194 inv_swizzle = [None]*4
196 swizzle = self.swizzles[i]
198 inv_swizzle[swizzle] = i
202 return self.block_size()/8
214 _swizzle_parse_map = {
225 '''Parse the format descrition in CSV format in terms of the
226 Channel and Format classes above.'''
228 stream = open(filename)
232 comment = line.index('#')
236 line = line[:comment]
241 fields = [field.strip() for field in line.split(',')]
245 block_width, block_height = map(int, fields[2:4])
247 swizzles = [_swizzle_parse_map[swizzle] for swizzle in fields[8]]
248 colorspace = fields[9]
252 if colorspace in (RGB, SRGB):
254 swizzle = swizzles[i]
256 names[swizzle] += 'rgba'[i]
257 elif colorspace == ZS:
259 swizzle = swizzles[i]
261 names[swizzle] += 'zs'[i]
268 names = ['x', 'y', 'z', 'w']
271 for i in range(0, 4):
272 field = fields[4 + i]
274 type = _type_parse_map[field[0]]
277 size = int(field[2:])
280 size = int(field[1:])
285 channel = Channel(type, norm, size, names[i])
286 channels.append(channel)
288 format = Format(name, layout, block_width, block_height, channels, swizzles, colorspace)
289 formats.append(format)