13d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca#!/usr/bin/env python
23d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca
33d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca'''
43d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca/**************************************************************************
53d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca *
63d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca * Copyright 2009 VMware, Inc.
73d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca * All Rights Reserved.
83d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca *
93d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca * Permission is hereby granted, free of charge, to any person obtaining a
103d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca * copy of this software and associated documentation files (the
113d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca * "Software"), to deal in the Software without restriction, including
123d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca * without limitation the rights to use, copy, modify, merge, publish,
133d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca * distribute, sub license, and/or sell copies of the Software, and to
143d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca * permit persons to whom the Software is furnished to do so, subject to
153d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca * the following conditions:
163d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca *
173d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca * The above copyright notice and this permission notice (including the
183d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca * next paragraph) shall be included in all copies or substantial portions
193d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca * of the Software.
203d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca *
213d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
223d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
233d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
243d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
253d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
263d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
273d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
283d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca *
293d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca **************************************************************************/
303d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca'''
313d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca
323d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca
333d305243938980af520c6d3e0ce02f4ee3a6126cJosé FonsecaVOID, UNSIGNED, SIGNED, FIXED, FLOAT = range(5)
343d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca
353d305243938980af520c6d3e0ce02f4ee3a6126cJosé FonsecaSWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W, SWIZZLE_0, SWIZZLE_1, SWIZZLE_NONE, = range(7)
363d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca
37816d23505abbcd789e7390c515178bc0df8e49c4José FonsecaPLAIN = 'plain'
383d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca
394757325951e35460975e77d70dacf8b6eb10ab11José FonsecaRGB = 'rgb'
404757325951e35460975e77d70dacf8b6eb10ab11José FonsecaSRGB = 'srgb'
414757325951e35460975e77d70dacf8b6eb10ab11José FonsecaYUV = 'yuv'
424757325951e35460975e77d70dacf8b6eb10ab11José FonsecaZS = 'zs'
434757325951e35460975e77d70dacf8b6eb10ab11José Fonseca
443d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca
45e2b02ea9db1a01fd2c4e431edff237d9909863efJosé Fonsecadef is_pot(x):
4682049b95950cf164932242f375fc0922b1865f5eVinson Lee   return (x & (x - 1)) == 0
47e2b02ea9db1a01fd2c4e431edff237d9909863efJosé Fonseca
48e2b02ea9db1a01fd2c4e431edff237d9909863efJosé Fonseca
494757325951e35460975e77d70dacf8b6eb10ab11José FonsecaVERY_LARGE = 99999999999999999999999
504757325951e35460975e77d70dacf8b6eb10ab11José Fonseca
514757325951e35460975e77d70dacf8b6eb10ab11José Fonseca
52092010db3798f9a49ff9184bf238099af849e885José Fonsecaclass Channel:
53092010db3798f9a49ff9184bf238099af849e885José Fonseca    '''Describe the channel of a color channel.'''
543d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca
55a441feb757b1be4845ba378f0207dcdc5cc1a407Dave Airlie    def __init__(self, type, norm, pure, size, name = ''):
56092010db3798f9a49ff9184bf238099af849e885José Fonseca        self.type = type
573d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca        self.norm = norm
58a441feb757b1be4845ba378f0207dcdc5cc1a407Dave Airlie        self.pure = pure
593d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca        self.size = size
60092010db3798f9a49ff9184bf238099af849e885José Fonseca        self.sign = type in (SIGNED, FIXED, FLOAT)
614757325951e35460975e77d70dacf8b6eb10ab11José Fonseca        self.name = name
623d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca
633d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca    def __str__(self):
64092010db3798f9a49ff9184bf238099af849e885José Fonseca        s = str(self.type)
653d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca        if self.norm:
663d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca            s += 'n'
67a441feb757b1be4845ba378f0207dcdc5cc1a407Dave Airlie        if self.pure:
68a441feb757b1be4845ba378f0207dcdc5cc1a407Dave Airlie            s += 'p'
693d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca        s += str(self.size)
703d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca        return s
713d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca
723d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca    def __eq__(self, other):
73a441feb757b1be4845ba378f0207dcdc5cc1a407Dave Airlie        return self.type == other.type and self.norm == other.norm and self.pure == other.pure and self.size == other.size
743d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca
754757325951e35460975e77d70dacf8b6eb10ab11José Fonseca    def max(self):
764757325951e35460975e77d70dacf8b6eb10ab11José Fonseca        '''Maximum representable number.'''
774757325951e35460975e77d70dacf8b6eb10ab11José Fonseca        if self.type == FLOAT:
784757325951e35460975e77d70dacf8b6eb10ab11José Fonseca            return VERY_LARGE
792c06fa4682ec0dd8a9f9d15ace867a6b952fd2e8José Fonseca        if self.type == FIXED:
802c06fa4682ec0dd8a9f9d15ace867a6b952fd2e8José Fonseca            return (1 << (self.size/2)) - 1
814757325951e35460975e77d70dacf8b6eb10ab11José Fonseca        if self.norm:
824757325951e35460975e77d70dacf8b6eb10ab11José Fonseca            return 1
834757325951e35460975e77d70dacf8b6eb10ab11José Fonseca        if self.type == UNSIGNED:
844757325951e35460975e77d70dacf8b6eb10ab11José Fonseca            return (1 << self.size) - 1
854757325951e35460975e77d70dacf8b6eb10ab11José Fonseca        if self.type == SIGNED:
86f342ceca3852d5b9607d1f375be26de9304a11f6José Fonseca            return (1 << (self.size - 1)) - 1
874757325951e35460975e77d70dacf8b6eb10ab11José Fonseca        assert False
884757325951e35460975e77d70dacf8b6eb10ab11José Fonseca
894757325951e35460975e77d70dacf8b6eb10ab11José Fonseca    def min(self):
904757325951e35460975e77d70dacf8b6eb10ab11José Fonseca        '''Minimum representable number.'''
914757325951e35460975e77d70dacf8b6eb10ab11José Fonseca        if self.type == FLOAT:
924757325951e35460975e77d70dacf8b6eb10ab11José Fonseca            return -VERY_LARGE
932c06fa4682ec0dd8a9f9d15ace867a6b952fd2e8José Fonseca        if self.type == FIXED:
942c06fa4682ec0dd8a9f9d15ace867a6b952fd2e8José Fonseca            return -(1 << (self.size/2))
954757325951e35460975e77d70dacf8b6eb10ab11José Fonseca        if self.type == UNSIGNED:
964757325951e35460975e77d70dacf8b6eb10ab11José Fonseca            return 0
974757325951e35460975e77d70dacf8b6eb10ab11José Fonseca        if self.norm:
984757325951e35460975e77d70dacf8b6eb10ab11José Fonseca            return -1
994757325951e35460975e77d70dacf8b6eb10ab11José Fonseca        if self.type == SIGNED:
1004757325951e35460975e77d70dacf8b6eb10ab11José Fonseca            return -(1 << (self.size - 1))
1014757325951e35460975e77d70dacf8b6eb10ab11José Fonseca        assert False
1024757325951e35460975e77d70dacf8b6eb10ab11José Fonseca
1033d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca
1043d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonsecaclass Format:
1053d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca    '''Describe a pixel format.'''
1063d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca
1076c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford    def __init__(self, name, layout, block_width, block_height, le_channels, le_swizzles, be_channels, be_swizzles, colorspace):
1083d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca        self.name = name
1093d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca        self.layout = layout
1103d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca        self.block_width = block_width
1113d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca        self.block_height = block_height
1126c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford        self.le_channels = le_channels
1136c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford        self.le_swizzles = le_swizzles
1146c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford        self.be_channels = be_channels
1156c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford        self.be_swizzles = be_swizzles
1163d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca        self.name = name
1173d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca        self.colorspace = colorspace
1183d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca
1193d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca    def __str__(self):
1203d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca        return self.name
1213d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca
122943314f38f1224d4929b41acc9ef8fde81ef9dbeJosé Fonseca    def short_name(self):
123943314f38f1224d4929b41acc9ef8fde81ef9dbeJosé Fonseca        '''Make up a short norm for a format, suitable to be used as suffix in
124943314f38f1224d4929b41acc9ef8fde81ef9dbeJosé Fonseca        function names.'''
125943314f38f1224d4929b41acc9ef8fde81ef9dbeJosé Fonseca
126943314f38f1224d4929b41acc9ef8fde81ef9dbeJosé Fonseca        name = self.name
127943314f38f1224d4929b41acc9ef8fde81ef9dbeJosé Fonseca        if name.startswith('PIPE_FORMAT_'):
128943314f38f1224d4929b41acc9ef8fde81ef9dbeJosé Fonseca            name = name[len('PIPE_FORMAT_'):]
129943314f38f1224d4929b41acc9ef8fde81ef9dbeJosé Fonseca        name = name.lower()
130943314f38f1224d4929b41acc9ef8fde81ef9dbeJosé Fonseca        return name
131943314f38f1224d4929b41acc9ef8fde81ef9dbeJosé Fonseca
1323d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca    def block_size(self):
1333d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca        size = 0
1346c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford        for channel in self.le_channels:
135092010db3798f9a49ff9184bf238099af849e885José Fonseca            size += channel.size
1363d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca        return size
1373d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca
1385dce9b252b65102ed69956fdd47862d5cb1c4af1José Fonseca    def nr_channels(self):
1395dce9b252b65102ed69956fdd47862d5cb1c4af1José Fonseca        nr_channels = 0
1406c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford        for channel in self.le_channels:
141092010db3798f9a49ff9184bf238099af849e885José Fonseca            if channel.size:
1425dce9b252b65102ed69956fdd47862d5cb1c4af1José Fonseca                nr_channels += 1
1435dce9b252b65102ed69956fdd47862d5cb1c4af1José Fonseca        return nr_channels
1445dce9b252b65102ed69956fdd47862d5cb1c4af1José Fonseca
145227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford    def array_element(self):
146948ac631123d814f3223b7fd9a00aa60e3c8bdf0José Fonseca        if self.layout != PLAIN:
147227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford            return None
1486c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford        ref_channel = self.le_channels[0]
149a47674ee89f9f41c3be96ee47c476144bf6b779bJosé Fonseca        if ref_channel.type == VOID:
1506c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford           ref_channel = self.le_channels[1]
1516c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford        for channel in self.le_channels:
152092010db3798f9a49ff9184bf238099af849e885José Fonseca            if channel.size and (channel.size != ref_channel.size or channel.size % 8):
153227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford                return None
154a47674ee89f9f41c3be96ee47c476144bf6b779bJosé Fonseca            if channel.type != VOID:
155a47674ee89f9f41c3be96ee47c476144bf6b779bJosé Fonseca                if channel.type != ref_channel.type:
156227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford                    return None
157a47674ee89f9f41c3be96ee47c476144bf6b779bJosé Fonseca                if channel.norm != ref_channel.norm:
158227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford                    return None
159a47674ee89f9f41c3be96ee47c476144bf6b779bJosé Fonseca                if channel.pure != ref_channel.pure:
160227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford                    return None
161227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford        return ref_channel
162227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford
163227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford    def is_array(self):
164227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford        return self.array_element() != None
1655dce9b252b65102ed69956fdd47862d5cb1c4af1José Fonseca
1665dce9b252b65102ed69956fdd47862d5cb1c4af1José Fonseca    def is_mixed(self):
167948ac631123d814f3223b7fd9a00aa60e3c8bdf0José Fonseca        if self.layout != PLAIN:
168948ac631123d814f3223b7fd9a00aa60e3c8bdf0José Fonseca            return False
1696c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford        ref_channel = self.le_channels[0]
1704e9690f00ca67e42e31367c50f9c216ad10ef553Roland Scheidegger        if ref_channel.type == VOID:
1716c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford           ref_channel = self.le_channels[1]
1726c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford        for channel in self.le_channels[1:]:
173092010db3798f9a49ff9184bf238099af849e885José Fonseca            if channel.type != VOID:
174092010db3798f9a49ff9184bf238099af849e885José Fonseca                if channel.type != ref_channel.type:
1755dce9b252b65102ed69956fdd47862d5cb1c4af1José Fonseca                    return True
176092010db3798f9a49ff9184bf238099af849e885José Fonseca                if channel.norm != ref_channel.norm:
1775dce9b252b65102ed69956fdd47862d5cb1c4af1José Fonseca                    return True
178a441feb757b1be4845ba378f0207dcdc5cc1a407Dave Airlie                if channel.pure != ref_channel.pure:
179a441feb757b1be4845ba378f0207dcdc5cc1a407Dave Airlie                    return True
1805dce9b252b65102ed69956fdd47862d5cb1c4af1José Fonseca        return False
1815dce9b252b65102ed69956fdd47862d5cb1c4af1José Fonseca
182e2b02ea9db1a01fd2c4e431edff237d9909863efJosé Fonseca    def is_pot(self):
183e2b02ea9db1a01fd2c4e431edff237d9909863efJosé Fonseca        return is_pot(self.block_size())
184e2b02ea9db1a01fd2c4e431edff237d9909863efJosé Fonseca
185092010db3798f9a49ff9184bf238099af849e885José Fonseca    def is_int(self):
186948ac631123d814f3223b7fd9a00aa60e3c8bdf0José Fonseca        if self.layout != PLAIN:
187948ac631123d814f3223b7fd9a00aa60e3c8bdf0José Fonseca            return False
1886c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford        for channel in self.le_channels:
189092010db3798f9a49ff9184bf238099af849e885José Fonseca            if channel.type not in (VOID, UNSIGNED, SIGNED):
190092010db3798f9a49ff9184bf238099af849e885José Fonseca                return False
191092010db3798f9a49ff9184bf238099af849e885José Fonseca        return True
192092010db3798f9a49ff9184bf238099af849e885José Fonseca
193092010db3798f9a49ff9184bf238099af849e885José Fonseca    def is_float(self):
194948ac631123d814f3223b7fd9a00aa60e3c8bdf0José Fonseca        if self.layout != PLAIN:
195948ac631123d814f3223b7fd9a00aa60e3c8bdf0José Fonseca            return False
1966c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford        for channel in self.le_channels:
197092010db3798f9a49ff9184bf238099af849e885José Fonseca            if channel.type not in (VOID, FLOAT):
198092010db3798f9a49ff9184bf238099af849e885José Fonseca                return False
199092010db3798f9a49ff9184bf238099af849e885José Fonseca        return True
200092010db3798f9a49ff9184bf238099af849e885José Fonseca
2014757325951e35460975e77d70dacf8b6eb10ab11José Fonseca    def is_bitmask(self):
202948ac631123d814f3223b7fd9a00aa60e3c8bdf0José Fonseca        if self.layout != PLAIN:
203948ac631123d814f3223b7fd9a00aa60e3c8bdf0José Fonseca            return False
204cfde6c50ae6c3ce7912a3d1231c459d020d77f13José Fonseca        if self.block_size() not in (8, 16, 32):
2054757325951e35460975e77d70dacf8b6eb10ab11José Fonseca            return False
2066c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford        for channel in self.le_channels:
2074757325951e35460975e77d70dacf8b6eb10ab11José Fonseca            if channel.type not in (VOID, UNSIGNED, SIGNED):
2084757325951e35460975e77d70dacf8b6eb10ab11José Fonseca                return False
2094757325951e35460975e77d70dacf8b6eb10ab11José Fonseca        return True
2104757325951e35460975e77d70dacf8b6eb10ab11José Fonseca
211227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford    def is_pure_color(self):
212227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford        if self.layout != PLAIN or self.colorspace == ZS:
213227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford            return False
214227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford        pures = [channel.pure
2156c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford                 for channel in self.le_channels
216227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford                 if channel.type != VOID]
217227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford        for x in pures:
218227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford           assert x == pures[0]
219227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford        return pures[0]
220227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford
221227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford    def channel_type(self):
222227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford        types = [channel.type
2236c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford                 for channel in self.le_channels
224227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford                 if channel.type != VOID]
225227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford        for x in types:
226227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford           assert x == types[0]
227227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford        return types[0]
228227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford
229227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford    def is_pure_signed(self):
230227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford        return self.is_pure_color() and self.channel_type() == SIGNED
231227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford
232227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford    def is_pure_unsigned(self):
233227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford        return self.is_pure_color() and self.channel_type() == UNSIGNED
234227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford
235227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford    def has_channel(self, id):
2366c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford        return self.le_swizzles[id] != SWIZZLE_NONE
237227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford
238227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford    def has_depth(self):
239227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford        return self.colorspace == ZS and self.has_channel(0)
240227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford
241227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford    def has_stencil(self):
242227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford        return self.colorspace == ZS and self.has_channel(1)
243227d7a6a3ca0e32df2c87cf50112c5d7f02b2aaeRichard Sandiford
2443d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca    def stride(self):
2453d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca        return self.block_size()/8
2463d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca
2473d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca
248092010db3798f9a49ff9184bf238099af849e885José Fonseca_type_parse_map = {
2493d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca    '':  VOID,
2503d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca    'x': VOID,
2513d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca    'u': UNSIGNED,
2523d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca    's': SIGNED,
2533d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca    'h': FIXED,
2543d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca    'f': FLOAT,
2553d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca}
2563d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca
2573d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca_swizzle_parse_map = {
2583d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca    'x': SWIZZLE_X,
2593d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca    'y': SWIZZLE_Y,
2603d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca    'z': SWIZZLE_Z,
2613d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca    'w': SWIZZLE_W,
2623d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca    '0': SWIZZLE_0,
2633d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca    '1': SWIZZLE_1,
2643d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca    '_': SWIZZLE_NONE,
2653d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca}
2663d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca
2676944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiforddef _parse_channels(fields, layout, colorspace, swizzles):
2686944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford    if layout == PLAIN:
2696944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford        names = ['']*4
2706944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford        if colorspace in (RGB, SRGB):
2716944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford            for i in range(4):
2726944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford                swizzle = swizzles[i]
2736944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford                if swizzle < 4:
2746944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford                    names[swizzle] += 'rgba'[i]
2756944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford        elif colorspace == ZS:
2766944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford            for i in range(4):
2776944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford                swizzle = swizzles[i]
2786944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford                if swizzle < 4:
2796944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford                    names[swizzle] += 'zs'[i]
2806944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford        else:
2816944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford            assert False
2826944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford        for i in range(4):
2836944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford            if names[i] == '':
2846944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford                names[i] = 'x'
2856944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford    else:
2866944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford        names = ['x', 'y', 'z', 'w']
2876944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford
2886944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford    channels = []
2896944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford    for i in range(0, 4):
2906944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford        field = fields[i]
2916944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford        if field:
2926944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford            type = _type_parse_map[field[0]]
2936944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford            if field[1] == 'n':
2946944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford                norm = True
2956944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford                pure = False
2966944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford                size = int(field[2:])
2976944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford            elif field[1] == 'p':
2986944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford                pure = True
2996944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford                norm = False
3006944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford                size = int(field[2:])
3016944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford            else:
3026944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford                norm = False
3036944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford                pure = False
3046944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford                size = int(field[1:])
3056944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford        else:
3066944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford            type = VOID
3076944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford            norm = False
3086944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford            pure = False
3096944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford            size = 0
3106944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford        channel = Channel(type, norm, pure, size, names[i])
3116944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford        channels.append(channel)
3126944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford
3136944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford    return channels
3146944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford
3153d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonsecadef parse(filename):
316116e4dc995af27e5fbd218240785fc4422feeb1cRoland Scheidegger    '''Parse the format description in CSV format in terms of the
317092010db3798f9a49ff9184bf238099af849e885José Fonseca    Channel and Format classes above.'''
3183d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca
3193d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca    stream = open(filename)
3203d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca    formats = []
3213d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca    for line in stream:
322b57d80da7765b2f06ba37758c05819456c27d0b9José Fonseca        try:
323b57d80da7765b2f06ba37758c05819456c27d0b9José Fonseca            comment = line.index('#')
324b57d80da7765b2f06ba37758c05819456c27d0b9José Fonseca        except ValueError:
325b57d80da7765b2f06ba37758c05819456c27d0b9José Fonseca            pass
326b57d80da7765b2f06ba37758c05819456c27d0b9José Fonseca        else:
327b57d80da7765b2f06ba37758c05819456c27d0b9José Fonseca            line = line[:comment]
328b57d80da7765b2f06ba37758c05819456c27d0b9José Fonseca        line = line.strip()
329b57d80da7765b2f06ba37758c05819456c27d0b9José Fonseca        if not line:
330b57d80da7765b2f06ba37758c05819456c27d0b9José Fonseca            continue
3314757325951e35460975e77d70dacf8b6eb10ab11José Fonseca
3323d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca        fields = [field.strip() for field in line.split(',')]
333f93b6d8cc5b0e3830e0c095772795e606fd1fe3aRichard Sandiford        if len (fields) == 10:
334f93b6d8cc5b0e3830e0c095772795e606fd1fe3aRichard Sandiford           fields += fields[4:9]
335f93b6d8cc5b0e3830e0c095772795e606fd1fe3aRichard Sandiford        assert len (fields) == 15
3364757325951e35460975e77d70dacf8b6eb10ab11José Fonseca
3373d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca        name = fields[0]
3383d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca        layout = fields[1]
3393d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca        block_width, block_height = map(int, fields[2:4])
3406944796cbe880311e920745d5aa0a793cf76e30aRichard Sandiford        colorspace = fields[9]
3414757325951e35460975e77d70dacf8b6eb10ab11José Fonseca
3426c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford        le_swizzles = [_swizzle_parse_map[swizzle] for swizzle in fields[8]]
3436c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford        le_channels = _parse_channels(fields[4:8], layout, colorspace, le_swizzles)
3446c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford
345f93b6d8cc5b0e3830e0c095772795e606fd1fe3aRichard Sandiford        be_swizzles = [_swizzle_parse_map[swizzle] for swizzle in fields[14]]
346f93b6d8cc5b0e3830e0c095772795e606fd1fe3aRichard Sandiford        be_channels = _parse_channels(fields[10:14], layout, colorspace, be_swizzles)
3476c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford
3486c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford        le_shift = 0
3496c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford        for channel in le_channels:
3506c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford            channel.shift = le_shift
3516c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford            le_shift += channel.size
3526c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford
3536c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford        be_shift = 0
3546c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford        for channel in be_channels[3::-1]:
3556c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford            channel.shift = be_shift
3566c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford            be_shift += channel.size
3574757325951e35460975e77d70dacf8b6eb10ab11José Fonseca
3586c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford        assert le_shift == be_shift
359f93b6d8cc5b0e3830e0c095772795e606fd1fe3aRichard Sandiford        for i in range(4):
360f93b6d8cc5b0e3830e0c095772795e606fd1fe3aRichard Sandiford            assert (le_swizzles[i] != SWIZZLE_NONE) == (be_swizzles[i] != SWIZZLE_NONE)
3612151d893fbd4a4be092098170e2fbca8c35797a5Adam Jackson
3626c8f547f66e68b495c708f8ffcb67370caa5ffe8Richard Sandiford        format = Format(name, layout, block_width, block_height, le_channels, le_swizzles, be_channels, be_swizzles, colorspace)
3634757325951e35460975e77d70dacf8b6eb10ab11José Fonseca        formats.append(format)
3643d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca    return formats
3653d305243938980af520c6d3e0ce02f4ee3a6126cJosé Fonseca
366