Merge branch 'master' of ssh://git.freedesktop.org/git/mesa/mesa into pipe-video
[mesa.git] / src / gallium / auxiliary / util / u_format_parse.py
index edc6bba79591489d442603d85037272250aec2a6..ddb9f2443d9b805fba7b9b78f77940c59fa230c0 100755 (executable)
@@ -36,19 +36,28 @@ SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W, SWIZZLE_0, SWIZZLE_1, SWIZZLE_NONE,
 
 PLAIN = 'plain'
 
+RGB = 'rgb'
+SRGB = 'srgb'
+YUV = 'yuv'
+ZS = 'zs'
+
 
 def is_pot(x):
-   return (x & (x - 1)) == 0;
+   return (x & (x - 1)) == 0
+
+
+VERY_LARGE = 99999999999999999999999
 
 
 class Channel:
     '''Describe the channel of a color channel.'''
     
-    def __init__(self, type, norm, size):
+    def __init__(self, type, norm, size, name = ''):
         self.type = type
         self.norm = norm
         self.size = size
         self.sign = type in (SIGNED, FIXED, FLOAT)
+        self.name = name
 
     def __str__(self):
         s = str(self.type)
@@ -60,6 +69,34 @@ class Channel:
     def __eq__(self, other):
         return self.type == other.type and self.norm == other.norm and self.size == other.size
 
+    def max(self):
+        '''Maximum representable number.'''
+        if self.type == FLOAT:
+            return VERY_LARGE
+        if self.type == FIXED:
+            return (1 << (self.size/2)) - 1
+        if self.norm:
+            return 1
+        if self.type == UNSIGNED:
+            return (1 << self.size) - 1
+        if self.type == SIGNED:
+            return (1 << (self.size - 1)) - 1
+        assert False
+    
+    def min(self):
+        '''Minimum representable number.'''
+        if self.type == FLOAT:
+            return -VERY_LARGE
+        if self.type == FIXED:
+            return -(1 << (self.size/2))
+        if self.type == UNSIGNED:
+            return 0
+        if self.norm:
+            return -1
+        if self.type == SIGNED:
+            return -(1 << (self.size - 1))
+        assert False
+
 
 class Format:
     '''Describe a pixel format.'''
@@ -101,6 +138,8 @@ class Format:
         return nr_channels
 
     def is_array(self):
+        if self.layout != PLAIN:
+            return False
         ref_channel = self.channels[0]
         for channel in self.channels[1:]:
             if channel.size and (channel.size != ref_channel.size or channel.size % 8):
@@ -108,7 +147,11 @@ class Format:
         return True
 
     def is_mixed(self):
+        if self.layout != PLAIN:
+            return False
         ref_channel = self.channels[0]
+        if ref_channel.type == VOID:
+           ref_channel = self.channels[1]
         for channel in self.channels[1:]:
             if channel.type != VOID:
                 if channel.type != ref_channel.type:
@@ -121,17 +164,40 @@ class Format:
         return is_pot(self.block_size())
 
     def is_int(self):
+        if self.layout != PLAIN:
+            return False
         for channel in self.channels:
             if channel.type not in (VOID, UNSIGNED, SIGNED):
                 return False
         return True
 
     def is_float(self):
+        if self.layout != PLAIN:
+            return False
         for channel in self.channels:
             if channel.type not in (VOID, FLOAT):
                 return False
         return True
 
+    def is_bitmask(self):
+        if self.layout != PLAIN:
+            return False
+        if self.block_size() not in (8, 16, 32):
+            return False
+        for channel in self.channels:
+            if channel.type not in (VOID, UNSIGNED, SIGNED):
+                return False
+        return True
+
+    def inv_swizzles(self):
+        '''Return an array[4] of inverse swizzle terms'''
+        inv_swizzle = [None]*4
+        for i in range(4):
+            swizzle = self.swizzles[i]
+            if swizzle < 4:
+                inv_swizzle[swizzle] = i
+        return inv_swizzle
+
     def stride(self):
         return self.block_size()/8
 
@@ -171,12 +237,39 @@ def parse(filename):
         line = line.strip()
         if not line:
             continue
+
         fields = [field.strip() for field in line.split(',')]
+        
         name = fields[0]
         layout = fields[1]
         block_width, block_height = map(int, fields[2:4])
+
+        swizzles = [_swizzle_parse_map[swizzle] for swizzle in fields[8]]
+        colorspace = fields[9]
+        
+        if layout == PLAIN:
+            names = ['']*4
+            if colorspace in (RGB, SRGB):
+                for i in range(4):
+                    swizzle = swizzles[i]
+                    if swizzle < 4:
+                        names[swizzle] += 'rgba'[i]
+            elif colorspace == ZS:
+                for i in range(4):
+                    swizzle = swizzles[i]
+                    if swizzle < 4:
+                        names[swizzle] += 'zs'[i]
+            else:
+                assert False
+            for i in range(4):
+                if names[i] == '':
+                    names[i] = 'x'
+        else:
+            names = ['x', 'y', 'z', 'w']
+
         channels = []
-        for field in fields[4:8]:
+        for i in range(0, 4):
+            field = fields[4 + i]
             if field:
                 type = _type_parse_map[field[0]]
                 if field[1] == 'n':
@@ -189,10 +282,10 @@ def parse(filename):
                 type = VOID
                 norm = False
                 size = 0
-            channel = Channel(type, norm, size)
+            channel = Channel(type, norm, size, names[i])
             channels.append(channel)
-        swizzles = [_swizzle_parse_map[swizzle] for swizzle in fields[8]]
-        colorspace = fields[9]
-        formats.append(Format(name, layout, block_width, block_height, channels, swizzles, colorspace))
+
+        format = Format(name, layout, block_width, block_height, channels, swizzles, colorspace)
+        formats.append(format)
     return formats