util: Use bitshift arithmetic to unpack pixels.
authorJosé Fonseca <jfonseca@vmware.com>
Sat, 6 Mar 2010 14:22:56 +0000 (14:22 +0000)
committerJosé Fonseca <jfonseca@vmware.com>
Sat, 6 Mar 2010 14:36:51 +0000 (14:36 +0000)
All test cases pass now.

src/gallium/auxiliary/util/u_format_pack.py

index 1fc58cd3de0e1ba1d2612ba556500d83a2de48e9..b49039db39b03990c7b98fc3c8c9bd479675681f 100644 (file)
@@ -304,6 +304,8 @@ def conversion_expr(src_channel, dst_channel, dst_native_type, value, clamp=True
 def generate_format_unpack(format, dst_channel, dst_native_type, dst_suffix):
     '''Generate the function to unpack pixels from a particular format'''
 
+    assert format.layout == PLAIN
+
     name = format.short_name()
 
     src_native_type = native_type(format)
@@ -311,32 +313,99 @@ def generate_format_unpack(format, dst_channel, dst_native_type, dst_suffix):
     print 'static INLINE void'
     print 'util_format_%s_unpack_%s(%s *dst, const void *src)' % (name, dst_suffix, dst_native_type)
     print '{'
-    print '   union util_format_%s pixel;' % format.short_name()
-    print '   memcpy(&pixel, src, sizeof pixel);'
-    bswap_format(format)
+    
+    if format.is_bitmask():
+        depth = format.block_size()
+        print '   uint%u_t value = *(uint%u_t *)src;' % (depth, depth) 
 
-    assert format.layout == PLAIN
+        # Declare the intermediate variables
+        for i in range(format.nr_channels()):
+            src_channel = format.channels[i]
+            if src_channel.type == UNSIGNED:
+                print '   uint%u_t %s;' % (depth, src_channel.name)
+            elif src_channel.type == SIGNED:
+                print '   int%u_t %s;' % (depth, src_channel.name)
 
-    for i in range(4):
-        swizzle = format.swizzles[i]
-        if swizzle < 4:
-            src_channel = format.channels[swizzle]
-            value = 'pixel.chan.%s' % src_channel.name 
-            value = conversion_expr(src_channel, dst_channel, dst_native_type, value)
-        elif swizzle == SWIZZLE_0:
-            value = '0'
-        elif swizzle == SWIZZLE_1:
-            value = get_one(dst_channel)
-        elif swizzle == SWIZZLE_NONE:
-            value = '0'
-        else:
-            assert False
-        if format.colorspace == ZS:
-            if i == 3:
+        print '#ifdef PIPE_ARCH_BIG_ENDIAN'
+        print '   value = util_bswap%u(value);' % depth
+        print '#endif'
+
+        # Compute the intermediate unshifted values 
+        shift = 0
+        for i in range(format.nr_channels()):
+            src_channel = format.channels[i]
+            value = 'value'
+            if src_channel.type == UNSIGNED:
+                if shift:
+                    value = '%s >> %u' % (value, shift)
+                if shift + src_channel.size < depth:
+                    value = '(%s) & 0x%x' % (value, (1 << src_channel.size) - 1)
+            elif src_channel.type == SIGNED:
+                if shift + src_channel.size < depth:
+                    # Align the sign bit
+                    lshift = depth - (shift + src_channel.size)
+                    value = '%s << %u' % (value, lshift)
+                # Cast to signed
+                value = '(int%u_t)(%s) ' % (depth, value)
+                if src_channel.size < depth:
+                    # Align the LSB bit
+                    rshift = depth - src_channel.size
+                    value = '(%s) >> %u' % (value, rshift)
+            else:
+                value = None
+                
+            if value is not None:
+                print '   %s = %s;' % (src_channel.name, value)
+                
+            shift += src_channel.size
+
+        # Convert, swizzle, and store final values
+        for i in range(4):
+            swizzle = format.swizzles[i]
+            if swizzle < 4:
+                src_channel = format.channels[swizzle]
+                value = src_channel.name 
+                value = conversion_expr(src_channel, dst_channel, dst_native_type, value)
+            elif swizzle == SWIZZLE_0:
+                value = '0'
+            elif swizzle == SWIZZLE_1:
                 value = get_one(dst_channel)
-            elif i >= 1:
-                value = 'dst[0]'
-        print '   dst[%u] = %s; /* %s */' % (i, value, 'rgba'[i])
+            elif swizzle == SWIZZLE_NONE:
+                value = '0'
+            else:
+                assert False
+            if format.colorspace == ZS:
+                if i == 3:
+                    value = get_one(dst_channel)
+                elif i >= 1:
+                    value = 'dst[0]'
+            print '   dst[%u] = %s; /* %s */' % (i, value, 'rgba'[i])
+        
+    else:
+        print '   union util_format_%s pixel;' % format.short_name()
+        print '   memcpy(&pixel, src, sizeof pixel);'
+        bswap_format(format)
+    
+        for i in range(4):
+            swizzle = format.swizzles[i]
+            if swizzle < 4:
+                src_channel = format.channels[swizzle]
+                value = 'pixel.chan.%s' % src_channel.name 
+                value = conversion_expr(src_channel, dst_channel, dst_native_type, value)
+            elif swizzle == SWIZZLE_0:
+                value = '0'
+            elif swizzle == SWIZZLE_1:
+                value = get_one(dst_channel)
+            elif swizzle == SWIZZLE_NONE:
+                value = '0'
+            else:
+                assert False
+            if format.colorspace == ZS:
+                if i == 3:
+                    value = get_one(dst_channel)
+                elif i >= 1:
+                    value = 'dst[0]'
+            print '   dst[%u] = %s; /* %s */' % (i, value, 'rgba'[i])
 
     print '}'
     print