util: Auto generate pixel format accessor functions from
authorJosé Fonseca <jfonseca@vmware.com>
Sun, 30 Aug 2009 11:02:36 +0000 (12:02 +0100)
committerJosé Fonseca <jfonseca@vmware.com>
Sun, 30 Aug 2009 11:37:03 +0000 (12:37 +0100)
This has several advantages over the u_
 - not hand written
 - no intermediate memcpy of raw pixels
 - supports 4 ubytes in addition to floats
 - no need to pass a pipe_transfer

It also has (hopefully temporary) limitations:
 - no support for YUV
 - no support for SRGB

src/gallium/auxiliary/util/.gitignore
src/gallium/auxiliary/util/Makefile
src/gallium/auxiliary/util/SConscript
src/gallium/auxiliary/util/u_format.csv
src/gallium/auxiliary/util/u_format.h
src/gallium/auxiliary/util/u_format_access.py [new file with mode: 0644]
src/gallium/auxiliary/util/u_format_parse.py [new file with mode: 0755]
src/gallium/auxiliary/util/u_format_table.py

index 53fe9b8a6529f02a1756e1d18ffa5981a61b0bfc..29c586c9b514d3dce0a42285494aaf946f09a8b5 100644 (file)
@@ -1 +1,2 @@
+u_format_access.c
 u_format_table.c
index 77f1133096eebda11f1c5c6d966f1ff43eb0cba9..ae8d330a78716d8817589eb9a9d32fe5027c3514 100644 (file)
@@ -12,6 +12,7 @@ C_SOURCES = \
        u_cache.c \
        u_draw_quad.c \
        u_format.c \
+       u_format_access.c \
        u_format_table.c \
        u_gen_mipmap.c \
        u_handle_table.c \
@@ -36,5 +37,8 @@ C_SOURCES = \
 
 include ../../Makefile.template
 
-u_format_table.c: u_format_table.py u_format.csv
+u_format_table.c: u_format_table.py u_format_parse.py u_format.csv
        python u_format_table.py u_format.csv > $@
+
+u_format_access.c: u_format_access.py u_format_parse.py u_format.csv
+       python u_format_access.py u_format.csv > $@
index 5ceb1970b5c152b111ebb46adc3f17391aa2087b..28a5ab42569df1f9015eb5331cb1406f1ac49940 100644 (file)
@@ -11,6 +11,13 @@ env.CodeGenerate(
        command = 'python $SCRIPT $SOURCE > $TARGET'
 )
 
+env.CodeGenerate(
+       target = 'u_format_access.c',
+       script = 'u_format_access.py',
+       source = ['u_format.csv'],
+       command = 'python $SCRIPT $SOURCE > $TARGET'
+)
+
 util = env.ConvenienceLibrary(
        target = 'util',
        source = [
@@ -25,6 +32,7 @@ util = env.ConvenienceLibrary(
                'u_debug_symbol.c',
                'u_draw_quad.c',
                'u_format.c',
+               'u_format_access.c',
                'u_format_table.c',
                'u_gen_mipmap.c',
                'u_handle_table.c',
index 74bd21a838d08769ca500ebf7e1f5a9f52ca00e2..00a46d0cc48c6895a778ce0a7603e34023c4f9f1 100644 (file)
@@ -2,23 +2,23 @@ PIPE_FORMAT_A8R8G8B8_UNORM        , arith , 1, 1, un8 , un8 , un8 , un8 , zyxw,
 PIPE_FORMAT_X8R8G8B8_UNORM        , arith , 1, 1, un8 , un8 , un8 , un8 , zyx1, rgb
 PIPE_FORMAT_B8G8R8A8_UNORM        , arith , 1, 1, un8 , un8 , un8 , un8 , yzwx, rgb
 PIPE_FORMAT_B8G8R8X8_UNORM        , arith , 1, 1, un8 , un8 , un8 , un8 , yzw1, rgb
-PIPE_FORMAT_A1R5G5B5_UNORM        , arith , 1, 1, un5 , un5 , un5 , un1 , zyxw, rgb
+PIPE_FORMAT_A1R5G5B5_UNORM        , arith , 1, 1, un1 , un5 , un5 , un5 , zyxw, rgb
 PIPE_FORMAT_A4R4G4B4_UNORM        , arith , 1, 1, un4 , un4 , un4 , un4 , zyxw, rgb
 PIPE_FORMAT_R5G6B5_UNORM          , arith , 1, 1, un5 , un6 , un5 ,     , zyx1, rgb
-PIPE_FORMAT_A2B10G10R10_UNORM     , arith , 1, 1, un10, un10, un10, un2 , wzyx, rgb
+PIPE_FORMAT_A2B10G10R10_UNORM     , arith , 1, 1, un10, un10, un10, un2 , xyzw, rgb
 PIPE_FORMAT_L8_UNORM              , arith , 1, 1, un8 ,     ,     ,     , xxx1, rgb
 PIPE_FORMAT_A8_UNORM              , arith , 1, 1, un8 ,     ,     ,     , 000x, rgb
 PIPE_FORMAT_I8_UNORM              , arith , 1, 1, un8 ,     ,     ,     , xxxx, rgb
 PIPE_FORMAT_A8L8_UNORM            , arith , 1, 1, un8 , un8 ,     ,     , xxxy, rgb
 PIPE_FORMAT_L16_UNORM             , arith , 1, 1, un16,     ,     ,     , xxx1, rgb
-PIPE_FORMAT_Z16_UNORM             , arith , 1, 1, un16,     ,     ,     , x0__, zs 
-PIPE_FORMAT_Z32_UNORM             , arith , 1, 1, un32,     ,     ,     , x0__, zs 
-PIPE_FORMAT_Z32_FLOAT             , arith , 1, 1, f32 ,     ,     ,     , x0__, zs 
+PIPE_FORMAT_Z16_UNORM             , array , 1, 1, un16,     ,     ,     , x___, zs 
+PIPE_FORMAT_Z32_UNORM             , array , 1, 1, un32,     ,     ,     , x___, zs 
+PIPE_FORMAT_Z32_FLOAT             , array , 1, 1, f32 ,     ,     ,     , x___, zs 
 PIPE_FORMAT_S8Z24_UNORM           , arith , 1, 1, un8 , un24,     ,     , yx__, zs 
 PIPE_FORMAT_Z24S8_UNORM           , arith , 1, 1, un24, un8 ,     ,     , xy__, zs 
-PIPE_FORMAT_X8Z24_UNORM           , arith , 1, 1, un8 , un24,     ,     , y0__, zs 
-PIPE_FORMAT_Z24X8_UNORM           , arith , 1, 1, un24, un8 ,     ,     , x0__, zs 
-PIPE_FORMAT_S8_UNORM              , arith , 1, 1, un8 ,     ,     ,     , 0x__, zs 
+PIPE_FORMAT_X8Z24_UNORM           , arith , 1, 1, un8 , un24,     ,     , y___, zs 
+PIPE_FORMAT_Z24X8_UNORM           , arith , 1, 1, un24, un8 ,     ,     , x___, zs 
+PIPE_FORMAT_S8_UNORM              , array , 1, 1, un8 ,     ,     ,     , _x__, zs 
 PIPE_FORMAT_R64_FLOAT             , array , 1, 1, f64 ,     ,     ,     , x001, rgb
 PIPE_FORMAT_R64G64_FLOAT          , array , 1, 1, f64 , f64 ,     ,     , xy01, rgb
 PIPE_FORMAT_R64G64B64_FLOAT       , array , 1, 1, f64 , f64 , f64 ,     , xyz1, rgb
index b5504ebe05600090f74b8748424f5da7af9873dc..7b5b7fcda5bea8018339af61aed20e7399db1b0b 100644 (file)
@@ -111,4 +111,28 @@ const struct util_format_description *
 util_format_description(enum pipe_format format);
 
 
+void
+util_format_read_4f(enum pipe_format format,
+                    float *dst, unsigned dst_stride, 
+                    const void *src, unsigned src_stride, 
+                    unsigned x, unsigned y, unsigned w, unsigned h);
+
+void
+util_format_write_4f(enum pipe_format format,
+                     const float *src, unsigned src_stride, 
+                     void *dst, unsigned dst_stride, 
+                     unsigned x, unsigned y, unsigned w, unsigned h);
+
+void
+util_format_read_4ub(enum pipe_format format,
+                     uint8_t *dst, unsigned dst_stride, 
+                     const void *src, unsigned src_stride, 
+                     unsigned x, unsigned y, unsigned w, unsigned h);
+
+void
+util_format_write_4ub(enum pipe_format format,
+                      const uint8_t *src, unsigned src_stride, 
+                      void *dst, unsigned dst_stride, 
+                      unsigned x, unsigned y, unsigned w, unsigned h);
+
 #endif /* ! U_FORMAT_H */
diff --git a/src/gallium/auxiliary/util/u_format_access.py b/src/gallium/auxiliary/util/u_format_access.py
new file mode 100644 (file)
index 0000000..eeb1a96
--- /dev/null
@@ -0,0 +1,498 @@
+#!/usr/bin/env python
+
+'''
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Pixel format accessor functions.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+'''
+
+
+import sys
+
+from u_format_parse import *
+
+
+def short_name(format):
+    '''Make up a short norm for a format, suitable to be used as suffix in
+    function names.'''
+
+    name = format.name
+    if name.startswith('PIPE_FORMAT_'):
+        name = name[len('PIPE_FORMAT_'):]
+    name = name.lower()
+    return name
+
+
+def is_format_supported(format):
+    '''Determines whether we actually have the plumbing necessary to generate the 
+    to read/write to/from this format.'''
+
+    # FIXME: Ideally we would support any format combination here.
+
+    # XXX: It should be straightforward to support srgb
+    if format.colorspace not in ('rgb', 'zs'):
+        return False
+
+    if format.layout not in (ARITH, ARRAY):
+        return False
+
+    for i in range(4):
+        type = format.in_types[i]
+        if type.kind not in (VOID, UNSIGNED, FLOAT):
+            return False
+
+    # We can only read a color from a depth/stencil format if the depth channel is present
+    if format.colorspace == 'zs' and format.out_swizzle[0] == SWIZZLE_NONE:
+        return False
+
+    return True
+
+
+def native_type(format):
+    '''Get the native appropriate for a format.'''
+
+    if format.layout == ARITH:
+        # For arithmetic pixel formats return the integer type that matches the whole pixel
+        return 'uint%u_t' % format.block_size()
+    elif format.layout == ARRAY:
+        # For array pixel formats return the integer type that matches the color channel
+        type = format.in_types[0]
+        if type.kind == UNSIGNED:
+            return 'uint%u_t' % type.size
+        elif type.kind == SIGNED:
+            return 'int%u_t' % type.size
+        elif type.kind == FLOAT:
+            if type.size == 32:
+                return 'float'
+            elif type.size == 64:
+                return 'double'
+            else:
+                assert False
+        else:
+            assert False
+    else:
+        assert False
+
+
+def intermediate_native_type(bits, sign):
+    '''Find a native type adequate to hold intermediate results of the request bit size.'''
+
+    bytes = 4 # don't use anything smaller than 32bits
+    while bytes * 8 < bits:
+        bytes *= 2
+    bits = bytes*8
+
+    if sign:
+        return 'int%u_t' % bits
+    else:
+        return 'uint%u_t' % bits
+
+
+def get_one_shift(type):
+    '''Get the number of the bit that matches unity for this type.'''
+    if type.kind == 'FLOAT':
+        assert False
+    if not type.norm:
+        return 0
+    if type.kind == UNSIGNED:
+        return type.size
+    if type.kind == SIGNED:
+        return type.size - 1
+    if type.kind == FIXED:
+        return type.size / 2
+    assert False
+
+
+def get_one(type):
+    '''Get the value of unity for this type.'''
+    if type.kind == 'FLOAT' or not type.norm:
+        return 1
+    else:
+        return (1 << get_one_shift(type)) - 1
+
+
+def generate_clamp():
+    '''Code generate the clamping functions for each type.
+
+    We don't use a macro so that arguments with side effects, 
+    like *src_pixel++ are correctly handled.
+    '''
+
+    for suffix, native_type in [
+        ('', 'double'),
+        ('f', 'float'),
+        ('ui', 'unsigned int'),
+        ('si', 'int'),
+    ]:
+        print 'static INLINE %s' % native_type
+        print 'clamp%s(%s value, %s lbound, %s ubound)' % (suffix, native_type, native_type, native_type)
+        print '{'
+        print '   if(value < lbound)'
+        print '      return lbound;'
+        print '   if(value > ubound)'
+        print '      return ubound;'
+        print '   return value;'
+        print '}'
+        print
+
+
+def clamp_expr(src_type, dst_type, dst_native_type, value):
+    '''Generate the expression to clamp the value in the source type to the
+    destination type range.'''
+
+    if src_type == dst_type:
+        return value
+
+    # Pick the approriate clamp function
+    if src_type.kind == FLOAT:
+        if src_type.size == 32:
+            func = 'clampf'
+        elif src_type.size == 64:
+            func = 'clamp'
+        else:
+            assert False
+    elif src_type.kind == UNSIGNED:
+        func = 'clampui'
+    elif src_type.kind == SIGNED:
+        func = 'clampsi'
+    else:
+        assert False
+
+    # Clamp floats to [-1, 1] or [0, 1] range
+    if src_type.kind == FLOAT and dst_type.norm:
+        max = 1
+        if src_type.sign and dst_type.sign:
+            min = -1
+        else:
+            min = 0
+        return '%s(%s, %s, %s)' % (func, value, min, max)
+                
+    # FIXME: Also clamp scaled values
+
+    return value
+
+
+def conversion_expr(src_type, dst_type, dst_native_type, value):
+    '''Generate the expression to convert a value between two types.'''
+
+    if src_type == dst_type:
+        return value
+
+    if src_type.kind == FLOAT and dst_type.kind == FLOAT:
+        return '(%s)%s' % (dst_native_type, value)
+    
+    if not src_type.norm and not dst_type.norm:
+        return '(%s)%s' % (dst_native_type, value)
+
+    value = clamp_expr(src_type, dst_type, dst_native_type, value)
+
+    if dst_type.kind == FLOAT:
+        if src_type.norm:
+            one = get_one(src_type)
+            if src_type.size <= 23:
+                scale = '(1.0f/0x%x)' % one
+            else:
+                # bigger than single precision mantissa, use double
+                scale = '(1.0/0x%x)' % one
+            value = '(%s * %s)' % (value, scale)
+        return '(%s)%s' % (dst_native_type, value)
+
+    if src_type.kind == FLOAT:
+        if dst_type.norm:
+            dst_one = get_one(dst_type)
+            if dst_type.size <= 23:
+                scale = '0x%x' % dst_one
+            else:
+                # bigger than single precision mantissa, use double
+                scale = '(double)0x%x' % dst_one
+            value = '(%s * %s)' % (value, scale)
+        return '(%s)%s' % (dst_native_type, value)
+
+    if src_type.kind == dst_type.kind:
+        src_one = get_one(src_type)
+        dst_one = get_one(dst_type)
+
+        if src_one > dst_one and src_type.norm and dst_type.norm:
+            # We can just bitshift
+            src_shift = get_one_shift(src_type)
+            dst_shift = get_one_shift(dst_type)
+            value = '(%s >> %s)' % (value, src_shift - dst_shift)
+        else:
+            # We need to rescale using an intermediate type big enough to hold the multiplication of both
+            tmp_native_type = intermediate_native_type(src_type.size + dst_type.size, src_type.sign and dst_type.sign)
+            value = '(%s)%s' % (tmp_native_type, value)
+            value = '%s * 0x%x / 0x%x' % (value, dst_one, src_one)
+        value = '(%s)%s' % (dst_native_type, value)
+        return value
+
+    assert False
+
+
+def generate_format_read(format, dst_type, dst_native_type, dst_suffix):
+    '''Generate the function to read pixels from a particular format'''
+
+    name = short_name(format)
+
+    src_native_type = native_type(format)
+
+    print 'static void'
+    print 'util_format_%s_read_%s(%s *dst, unsigned dst_stride, const uint8_t *src, unsigned src_stride, unsigned x0, unsigned y0, unsigned w, unsigned h)' % (name, dst_suffix, dst_native_type)
+    print '{'
+    print '   unsigned x, y;'
+    print '   const uint8_t *src_row = src + y0*src_stride;'
+    print '   %s *dst_row = dst;' % dst_native_type
+    print '   for (y = 0; y < h; ++y) {'
+    print '      const %s *src_pixel = (const %s *)(src_row + x0*%u);' % (src_native_type, src_native_type, format.stride())
+    print '      %s *dst_pixel = dst_row;' %dst_native_type
+    print '      for (x = 0; x < w; ++x) {'
+
+    names = ['']*4
+    if format.colorspace == 'rgb':
+        for i in range(4):
+            swizzle = format.out_swizzle[i]
+            if swizzle < 4:
+                names[swizzle] += 'rgba'[i]
+    elif format.colorspace == 'zs':
+        swizzle = format.out_swizzle[0]
+        if swizzle < 4:
+            names[swizzle] = 'z'
+        else:
+            assert False
+    else:
+        assert False
+
+    if format.layout == ARITH:
+        print '         %s pixel = *src_pixel++;' % src_native_type
+        shift = 0;
+        for i in range(4):
+            src_type = format.in_types[i]
+            width = src_type.size
+            if names[i]:
+                value = 'pixel'
+                mask = (1 << width) - 1
+                if shift:
+                    value = '(%s >> %u)' % (value, shift)
+                if shift + width < format.block_size():
+                    value = '(%s & 0x%x)' % (value, mask)
+                value = conversion_expr(src_type, dst_type, dst_native_type, value)
+                print '         %s %s = %s;' % (dst_native_type, names[i], value)
+            shift += width
+    elif format.layout == ARRAY:
+        for i in range(4):
+            src_type = format.in_types[i]
+            if names[i]:
+                value = '(*src_pixel++)'
+                value = conversion_expr(src_type, dst_type, dst_native_type, value)
+                print '         %s %s = %s;' % (dst_native_type, names[i], value)
+    else:
+        assert False
+
+    for i in range(4):
+        if format.colorspace == 'rgb':
+            swizzle = format.out_swizzle[i]
+            if swizzle < 4:
+                value = names[swizzle]
+            elif swizzle == SWIZZLE_0:
+                value = '0'
+            elif swizzle == SWIZZLE_1:
+                value = '1'
+            else:
+                assert False
+        elif format.colorspace == 'zs':
+            if i < 3:
+                value = 'z'
+            else:
+                value = '1'
+        else:
+            assert False
+        print '         *dst_pixel++ = %s; /* %s */' % (value, 'rgba'[i])
+
+    print '      }'
+    print '      src_row += src_stride;'
+    print '      dst_row += dst_stride/sizeof(%s);' % dst_native_type
+    print '   }'
+    print '}'
+    print
+    
+
+def generate_format_write(format, src_type, src_native_type, src_suffix):
+    '''Generate the function to write pixels to a particular format'''
+
+    name = short_name(format)
+
+    dst_native_type = native_type(format)
+
+    print 'static void'
+    print 'util_format_%s_write_%s(const %s *src, unsigned src_stride, uint8_t *dst, unsigned dst_stride, unsigned x0, unsigned y0, unsigned w, unsigned h)' % (name, src_suffix, src_native_type)
+    print '{'
+    print '   unsigned x, y;'
+    print '   uint8_t *dst_row = dst + y0*dst_stride;'
+    print '   const %s *src_row = src;' % src_native_type
+    print '   for (y = 0; y < h; ++y) {'
+    print '      %s *dst_pixel = (%s *)(dst_row + x0*%u);' % (dst_native_type, dst_native_type, format.stride())
+    print '      const %s *src_pixel = src_row;' %src_native_type
+    print '      for (x = 0; x < w; ++x) {'
+
+    inv_swizzle = [None]*4
+    if format.colorspace == 'rgb':
+        for i in range(4):
+            swizzle = format.out_swizzle[i]
+            if swizzle < 4:
+                inv_swizzle[swizzle] = i
+    elif format.colorspace == 'zs':
+        swizzle = format.out_swizzle[0]
+        if swizzle < 4:
+            inv_swizzle[swizzle] = 0
+    else:
+        assert False
+
+    if format.layout == ARITH:
+        print '         %s pixel = 0;' % dst_native_type
+        shift = 0;
+        for i in range(4):
+            dst_type = format.in_types[i]
+            width = dst_type.size
+            if inv_swizzle[i] is not None:
+                value = 'src_pixel[%u]' % inv_swizzle[i]
+                value = conversion_expr(src_type, dst_type, dst_native_type, value)
+                if shift:
+                    value = '(%s << %u)' % (value, shift)
+                print '         pixel |= %s;' % value
+            shift += width
+        print '         *dst_pixel++ = pixel;'
+    elif format.layout == ARRAY:
+        for i in range(4):
+            dst_type = format.in_types[i]
+            if inv_swizzle[i] is not None:
+                value = 'src_pixel[%u]' % inv_swizzle[i]
+                value = conversion_expr(src_type, dst_type, dst_native_type, value)
+                print '         *dst_pixel++ = %s;' % value
+    else:
+        assert False
+    print '         src_pixel += 4;'
+
+    print '      }'
+    print '      dst_row += dst_stride;'
+    print '      src_row += src_stride/sizeof(%s);' % src_native_type
+    print '   }'
+    print '}'
+    print
+    
+
+def generate_read(formats, dst_type, dst_native_type, dst_suffix):
+    '''Generate the dispatch function to read pixels from any format'''
+
+    for format in formats:
+        if is_format_supported(format):
+            generate_format_read(format, dst_type, dst_native_type, dst_suffix)
+
+    print 'void'
+    print 'util_format_read_%s(enum pipe_format format, %s *dst, unsigned dst_stride, const void *src, unsigned src_stride, unsigned x, unsigned y, unsigned w, unsigned h)' % (dst_suffix, dst_native_type)
+    print '{'
+    print '   void (*func)(%s *dst, unsigned dst_stride, const uint8_t *src, unsigned src_stride, unsigned x0, unsigned y0, unsigned w, unsigned h);' % dst_native_type
+    print '   switch(format) {'
+    for format in formats:
+        if is_format_supported(format):
+            print '   case %s:' % format.name
+            print '      func = &util_format_%s_read_%s;' % (short_name(format), dst_suffix)
+            print '      break;'
+    print '   default:'
+    print '      debug_printf("unsupported format\\n");'
+    print '      return;'
+    print '   }'
+    print '   func(dst, dst_stride, (const uint8_t *)src, src_stride, x, y, w, h);'
+    print '}'
+    print
+
+
+def generate_write(formats, src_type, src_native_type, src_suffix):
+    '''Generate the dispatch function to write pixels to any format'''
+
+    for format in formats:
+        if is_format_supported(format):
+            generate_format_write(format, src_type, src_native_type, src_suffix)
+
+    print 'void'
+    print 'util_format_write_%s(enum pipe_format format, const %s *src, unsigned src_stride, void *dst, unsigned dst_stride, unsigned x, unsigned y, unsigned w, unsigned h)' % (src_suffix, src_native_type)
+    
+    print '{'
+    print '   void (*func)(const %s *src, unsigned src_stride, uint8_t *dst, unsigned dst_stride, unsigned x0, unsigned y0, unsigned w, unsigned h);' % src_native_type
+    print '   switch(format) {'
+    for format in formats:
+        if is_format_supported(format):
+            print '   case %s:' % format.name
+            print '      func = &util_format_%s_write_%s;' % (short_name(format), src_suffix)
+            print '      break;'
+    print '   default:'
+    print '      debug_printf("unsupported format\\n");'
+    print '      return;'
+    print '   }'
+    print '   func(src, src_stride, (uint8_t *)dst, dst_stride, x, y, w, h);'
+    print '}'
+    print
+
+
+def main():
+    formats = []
+    for arg in sys.argv[1:]:
+        formats.extend(parse(arg))
+
+    print '/* This file is autogenerated by u_format_access.py from u_format.csv. Do not edit directly. */'
+    print
+    # This will print the copyright message on the top of this file
+    print __doc__.strip()
+    print
+    print '#include "pipe/p_compiler.h"'
+    print '#include "u_format.h"'
+    print '#include "u_math.h"'
+    print
+
+    generate_clamp()
+
+    type = Type(FLOAT, False, 32)
+    native_type = 'float'
+    suffix = '4f'
+
+    generate_read(formats, type, native_type, suffix)
+    generate_write(formats, type, native_type, suffix)
+
+    type = Type(UNSIGNED, True, 8)
+    native_type = 'uint8_t'
+    suffix = '4ub'
+
+    generate_read(formats, type, native_type, suffix)
+    generate_write(formats, type, native_type, suffix)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/src/gallium/auxiliary/util/u_format_parse.py b/src/gallium/auxiliary/util/u_format_parse.py
new file mode 100755 (executable)
index 0000000..493aff7
--- /dev/null
@@ -0,0 +1,141 @@
+#!/usr/bin/env python
+
+'''
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+'''
+
+
+import sys
+
+
+VOID, UNSIGNED, SIGNED, FIXED, FLOAT = range(5)
+
+SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W, SWIZZLE_0, SWIZZLE_1, SWIZZLE_NONE, = range(7)
+
+ARITH = 'arith'
+ARRAY = 'array'
+
+
+class Type:
+    '''Describe the type of a color channel.'''
+    
+    def __init__(self, kind, norm, size):
+        self.kind = kind
+        self.norm = norm
+        self.size = size
+        self.sign = kind in (SIGNED, FIXED, FLOAT)
+
+    def __str__(self):
+        s = str(self.kind)
+        if self.norm:
+            s += 'n'
+        s += str(self.size)
+        return s
+
+    def __eq__(self, other):
+        return self.kind == other.kind and self.norm == other.norm and self.size == other.size
+
+
+class Format:
+    '''Describe a pixel format.'''
+
+    def __init__(self, name, layout, block_width, block_height, in_types, out_swizzle, colorspace):
+        self.name = name
+        self.layout = layout
+        self.block_width = block_width
+        self.block_height = block_height
+        self.in_types = in_types
+        self.out_swizzle = out_swizzle
+        self.name = name
+        self.colorspace = colorspace
+
+    def __str__(self):
+        return self.name
+
+    def block_size(self):
+        size = 0
+        for type in self.in_types:
+            size += type.size
+        return size
+
+    def stride(self):
+        return self.block_size()/8
+
+
+_kind_parse_map = {
+    '':  VOID,
+    'x': VOID,
+    'u': UNSIGNED,
+    's': SIGNED,
+    'h': FIXED,
+    'f': FLOAT,
+}
+
+_swizzle_parse_map = {
+    'x': SWIZZLE_X,
+    'y': SWIZZLE_Y,
+    'z': SWIZZLE_Z,
+    'w': SWIZZLE_W,
+    '0': SWIZZLE_0,
+    '1': SWIZZLE_1,
+    '_': SWIZZLE_NONE,
+}
+
+def parse(filename):
+    '''Parse the format descrition in CSV format in terms of the 
+    Type and Format classes above.'''
+
+    stream = open(filename)
+    formats = []
+    for line in stream:
+        line = line.rstrip()
+        fields = [field.strip() for field in line.split(',')]
+        name = fields[0]
+        layout = fields[1]
+        block_width, block_height = map(int, fields[2:4])
+        in_types = []
+        for field in fields[4:8]:
+            if field:
+                kind = _kind_parse_map[field[0]]
+                if field[1] == 'n':
+                    norm = True
+                    size = int(field[2:])
+                else:
+                    norm = False
+                    size = int(field[1:])
+            else:
+                kind = VOID
+                norm = False
+                size = 0
+            in_type = Type(kind, norm, size)
+            in_types.append(in_type)
+        out_swizzle = [_swizzle_parse_map[swizzle] for swizzle in fields[8]]
+        colorspace = fields[9]
+        formats.append(Format(name, layout, block_width, block_height, in_types, out_swizzle, colorspace))
+    return formats
+
index c536e39171c4a582d599425221c97fb14754b791..8834568e8ee607022381eef0bd5a85c6388d3e77 100755 (executable)
@@ -3,7 +3,7 @@
 '''
 /**************************************************************************
  *
- * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright 2009 VMware, Inc.
  * All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -21,7 +21,7 @@
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 import sys
 
-
-UNSIGNED, SIGNED, FIXED, FLOAT = 'u', 's', 'h', 'f'
-
-
-class Type:
-    
-    def __init__(self, kind, norm, size):
-        self.kind = kind
-        self.norm = norm
-        self.size = size
-
-    def __str__(self):
-        s = str(self.kind)
-        if norm:
-            s += 'n'
-        s += str(self.size)
-        return s
-
-
-class Format:
-
-    def __init__(self, name, layout, block_width, block_height, in_types, out_swizzle, colorspace):
-        self.name = name
-        self.layout = layout
-        self.block_width = block_width
-        self.block_height = block_height
-        self.in_types = in_types
-        self.out_swizzle = out_swizzle
-        self.name = name
-        self.colorspace = colorspace
-
-    def __str__(self):
-        return self.name
-
-    def block_size(self):
-        size = 0
-        for type in self.in_types:
-            size += type.size
-        return size
-
-
-def parse(filename):
-    stream = open(filename)
-    formats = []
-    for line in stream:
-        line = line.rstrip()
-        fields = [field.strip() for field in line.split(',')]
-        name = fields[0]
-        layout = fields[1]
-        block_width, block_height = map(int, fields[2:4])
-        in_types = []
-        for field in fields[4:8]:
-            if field:
-                kind = field[0]
-                if field[1] == 'n':
-                    norm = True
-                    size = int(field[2:])
-                else:
-                    norm = False
-                    size = int(field[1:])
-            else:
-                kind = ''
-                norm = False
-                size = 0
-            in_type = Type(kind, norm, size)
-            in_types.append(in_type)
-        out_swizzle = fields[8]
-        colorspace = fields[9]
-        formats.append(Format(name, layout, block_width, block_height, in_types, out_swizzle, colorspace))
-    return formats
+from u_format_parse import *
 
 
 def layout_map(layout):
@@ -122,12 +53,11 @@ colorspace_channels_map = {
 
 
 kind_map = {
-    '': "UTIL_FORMAT_TYPE_VOID",
-    'x': "UTIL_FORMAT_TYPE_VOID",
+    VOID:     "UTIL_FORMAT_TYPE_VOID",
     UNSIGNED: "UTIL_FORMAT_TYPE_UNSIGNED",
-    SIGNED: "UTIL_FORMAT_TYPE_SIGNED",
-    FIXED: "UTIL_FORMAT_TYPE_FIXED",
-    FLOAT: "UTIL_FORMAT_TYPE_FLOAT",
+    SIGNED:   "UTIL_FORMAT_TYPE_SIGNED",
+    FIXED:    "UTIL_FORMAT_TYPE_FIXED",
+    FLOAT:    "UTIL_FORMAT_TYPE_FLOAT",
 }
 
 
@@ -139,13 +69,13 @@ def bool_map(value):
 
 
 swizzle_map = {
-    'x': "UTIL_FORMAT_SWIZZLE_X",
-    'y': "UTIL_FORMAT_SWIZZLE_Y",
-    'z': "UTIL_FORMAT_SWIZZLE_Z",
-    'w': "UTIL_FORMAT_SWIZZLE_W",
-    '0': "UTIL_FORMAT_SWIZZLE_0",
-    '1': "UTIL_FORMAT_SWIZZLE_1",
-    '_': "UTIL_FORMAT_SWIZZLE_NONE",
+    SWIZZLE_X:    "UTIL_FORMAT_SWIZZLE_X",
+    SWIZZLE_Y:    "UTIL_FORMAT_SWIZZLE_Y",
+    SWIZZLE_Z:    "UTIL_FORMAT_SWIZZLE_Z",
+    SWIZZLE_W:    "UTIL_FORMAT_SWIZZLE_W",
+    SWIZZLE_0:    "UTIL_FORMAT_SWIZZLE_0",
+    SWIZZLE_1:    "UTIL_FORMAT_SWIZZLE_1",
+    SWIZZLE_NONE: "UTIL_FORMAT_SWIZZLE_NONE",
 }