Home | History | Annotate | Download | only in util
      1 #!/usr/bin/env python
      2 
      3 '''
      4 /**************************************************************************
      5  *
      6  * Copyright 2009-2010 VMware, Inc.
      7  * All Rights Reserved.
      8  *
      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:
     16  *
     17  * The above copyright notice and this permission notice (including the
     18  * next paragraph) shall be included in all copies or substantial portions
     19  * of the Software.
     20  *
     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.
     28  *
     29  **************************************************************************/
     30 
     31 /**
     32  * @file
     33  * Pixel format packing and unpacking functions.
     34  *
     35  * @author Jose Fonseca <jfonseca (at] vmware.com>
     36  */
     37 '''
     38 
     39 
     40 from u_format_parse import *
     41 
     42 
     43 def inv_swizzles(swizzles):
     44     '''Return an array[4] of inverse swizzle terms'''
     45     '''Only pick the first matching value to avoid l8 getting blue and i8 getting alpha'''
     46     inv_swizzle = [None]*4
     47     for i in range(4):
     48         swizzle = swizzles[i]
     49         if swizzle < 4 and inv_swizzle[swizzle] == None:
     50             inv_swizzle[swizzle] = i
     51     return inv_swizzle
     52 
     53 def print_channels(format, func):
     54     if format.nr_channels() <= 1:
     55         func(format.le_channels, format.le_swizzles)
     56     else:
     57         print '#ifdef PIPE_ARCH_BIG_ENDIAN'
     58         func(format.be_channels, format.be_swizzles)
     59         print '#else'
     60         func(format.le_channels, format.le_swizzles)
     61         print '#endif'
     62 
     63 def generate_format_type(format):
     64     '''Generate a structure that describes the format.'''
     65 
     66     assert format.layout == PLAIN
     67     
     68     def generate_bitfields(channels, swizzles):
     69         for channel in channels:
     70             if channel.type == VOID:
     71                 if channel.size:
     72                     print '      unsigned %s:%u;' % (channel.name, channel.size)
     73             elif channel.type == UNSIGNED:
     74                 print '      unsigned %s:%u;' % (channel.name, channel.size)
     75             elif channel.type in (SIGNED, FIXED):
     76                 print '      int %s:%u;' % (channel.name, channel.size)
     77             elif channel.type == FLOAT:
     78                 if channel.size == 64:
     79                     print '      double %s;' % (channel.name)
     80                 elif channel.size == 32:
     81                     print '      float %s;' % (channel.name)
     82                 else:
     83                     print '      unsigned %s:%u;' % (channel.name, channel.size)
     84             else:
     85                 assert 0
     86 
     87     def generate_full_fields(channels, swizzles):
     88         for channel in channels:
     89             assert channel.size % 8 == 0 and is_pot(channel.size)
     90             if channel.type == VOID:
     91                 if channel.size:
     92                     print '      uint%u_t %s;' % (channel.size, channel.name)
     93             elif channel.type == UNSIGNED:
     94                 print '      uint%u_t %s;' % (channel.size, channel.name)
     95             elif channel.type in (SIGNED, FIXED):
     96                 print '      int%u_t %s;' % (channel.size, channel.name)
     97             elif channel.type == FLOAT:
     98                 if channel.size == 64:
     99                     print '      double %s;' % (channel.name)
    100                 elif channel.size == 32:
    101                     print '      float %s;' % (channel.name)
    102                 elif channel.size == 16:
    103                     print '      uint16_t %s;' % (channel.name)
    104                 else:
    105                     assert 0
    106             else:
    107                 assert 0
    108 
    109     print 'union util_format_%s {' % format.short_name()
    110     
    111     if format.block_size() in (8, 16, 32, 64):
    112         print '   uint%u_t value;' % (format.block_size(),)
    113 
    114     use_bitfields = False
    115     for channel in format.le_channels:
    116         if channel.size % 8 or not is_pot(channel.size):
    117             use_bitfields = True
    118 
    119     print '   struct {'
    120     if use_bitfields:
    121         print_channels(format, generate_bitfields)
    122     else:
    123         print_channels(format, generate_full_fields)
    124     print '   } chan;'
    125     print '};'
    126     print
    127 
    128 
    129 def is_format_supported(format):
    130     '''Determines whether we actually have the plumbing necessary to generate the 
    131     to read/write to/from this format.'''
    132 
    133     # FIXME: Ideally we would support any format combination here.
    134 
    135     if format.layout != PLAIN:
    136         return False
    137 
    138     for i in range(4):
    139         channel = format.le_channels[i]
    140         if channel.type not in (VOID, UNSIGNED, SIGNED, FLOAT, FIXED):
    141             return False
    142         if channel.type == FLOAT and channel.size not in (16, 32, 64):
    143             return False
    144 
    145     return True
    146 
    147 def native_type(format):
    148     '''Get the native appropriate for a format.'''
    149 
    150     if format.name == 'PIPE_FORMAT_R11G11B10_FLOAT':
    151         return 'uint32_t'
    152     if format.name == 'PIPE_FORMAT_R9G9B9E5_FLOAT':
    153         return 'uint32_t'
    154 
    155     if format.layout == PLAIN:
    156         if not format.is_array():
    157             # For arithmetic pixel formats return the integer type that matches the whole pixel
    158             return 'uint%u_t' % format.block_size()
    159         else:
    160             # For array pixel formats return the integer type that matches the color channel
    161             channel = format.array_element()
    162             if channel.type in (UNSIGNED, VOID):
    163                 return 'uint%u_t' % channel.size
    164             elif channel.type in (SIGNED, FIXED):
    165                 return 'int%u_t' % channel.size
    166             elif channel.type == FLOAT:
    167                 if channel.size == 16:
    168                     return 'uint16_t'
    169                 elif channel.size == 32:
    170                     return 'float'
    171                 elif channel.size == 64:
    172                     return 'double'
    173                 else:
    174                     assert False
    175             else:
    176                 assert False
    177     else:
    178         assert False
    179 
    180 
    181 def intermediate_native_type(bits, sign):
    182     '''Find a native type adequate to hold intermediate results of the request bit size.'''
    183 
    184     bytes = 4 # don't use anything smaller than 32bits
    185     while bytes * 8 < bits:
    186         bytes *= 2
    187     bits = bytes*8
    188 
    189     if sign:
    190         return 'int%u_t' % bits
    191     else:
    192         return 'uint%u_t' % bits
    193 
    194 
    195 def get_one_shift(type):
    196     '''Get the number of the bit that matches unity for this type.'''
    197     if type.type == 'FLOAT':
    198         assert False
    199     if not type.norm:
    200         return 0
    201     if type.type == UNSIGNED:
    202         return type.size
    203     if type.type == SIGNED:
    204         return type.size - 1
    205     if type.type == FIXED:
    206         return type.size / 2
    207     assert False
    208 
    209 
    210 def truncate_mantissa(x, bits):
    211     '''Truncate an integer so it can be represented exactly with a floating
    212     point mantissa'''
    213 
    214     assert isinstance(x, (int, long))
    215 
    216     s = 1
    217     if x < 0:
    218         s = -1
    219         x = -x
    220 
    221     # We can represent integers up to mantissa + 1 bits exactly
    222     mask = (1 << (bits + 1)) - 1
    223 
    224     # Slide the mask until the MSB matches
    225     shift = 0
    226     while (x >> shift) & ~mask:
    227         shift += 1
    228 
    229     x &= mask << shift
    230     x *= s
    231     return x
    232 
    233 
    234 def value_to_native(type, value):
    235     '''Get the value of unity for this type.'''
    236     if type.type == FLOAT:
    237         if type.size <= 32 \
    238             and isinstance(value, (int, long)):
    239             return truncate_mantissa(value, 23)
    240         return value
    241     if type.type == FIXED:
    242         return int(value * (1 << (type.size/2)))
    243     if not type.norm:
    244         return int(value)
    245     if type.type == UNSIGNED:
    246         return int(value * ((1 << type.size) - 1))
    247     if type.type == SIGNED:
    248         return int(value * ((1 << (type.size - 1)) - 1))
    249     assert False
    250 
    251 
    252 def native_to_constant(type, value):
    253     '''Get the value of unity for this type.'''
    254     if type.type == FLOAT:
    255         if type.size <= 32:
    256             return "%.1ff" % float(value)
    257         else:
    258             return "%.1f" % float(value)
    259     else:
    260         return str(int(value))
    261 
    262 
    263 def get_one(type):
    264     '''Get the value of unity for this type.'''
    265     return value_to_native(type, 1)
    266 
    267 
    268 def clamp_expr(src_channel, dst_channel, dst_native_type, value):
    269     '''Generate the expression to clamp the value in the source type to the
    270     destination type range.'''
    271 
    272     if src_channel == dst_channel:
    273         return value
    274 
    275     src_min = src_channel.min()
    276     src_max = src_channel.max()
    277     dst_min = dst_channel.min()
    278     dst_max = dst_channel.max()
    279     
    280     # Translate the destination range to the src native value
    281     dst_min_native = native_to_constant(src_channel, value_to_native(src_channel, dst_min))
    282     dst_max_native = native_to_constant(src_channel, value_to_native(src_channel, dst_max))
    283 
    284     if src_min < dst_min and src_max > dst_max:
    285         return 'CLAMP(%s, %s, %s)' % (value, dst_min_native, dst_max_native)
    286 
    287     if src_max > dst_max:
    288         return 'MIN2(%s, %s)' % (value, dst_max_native)
    289         
    290     if src_min < dst_min:
    291         return 'MAX2(%s, %s)' % (value, dst_min_native)
    292 
    293     return value
    294 
    295 
    296 def conversion_expr(src_channel, 
    297                     dst_channel, dst_native_type, 
    298                     value, 
    299                     clamp=True, 
    300                     src_colorspace = RGB, 
    301                     dst_colorspace = RGB):
    302     '''Generate the expression to convert a value between two types.'''
    303 
    304     if src_colorspace != dst_colorspace:
    305         if src_colorspace == SRGB:
    306             assert src_channel.type == UNSIGNED
    307             assert src_channel.norm
    308             assert src_channel.size <= 8
    309             assert src_channel.size >= 4
    310             assert dst_colorspace == RGB
    311             if src_channel.size < 8:
    312                 value = '%s << %x | %s >> %x' % (value, 8 - src_channel.size, value, 2 * src_channel.size - 8)
    313             if dst_channel.type == FLOAT:
    314                 return 'util_format_srgb_8unorm_to_linear_float(%s)' % value
    315             else:
    316                 assert dst_channel.type == UNSIGNED
    317                 assert dst_channel.norm
    318                 assert dst_channel.size == 8
    319                 return 'util_format_srgb_to_linear_8unorm(%s)' % value
    320         elif dst_colorspace == SRGB:
    321             assert dst_channel.type == UNSIGNED
    322             assert dst_channel.norm
    323             assert dst_channel.size <= 8
    324             assert src_colorspace == RGB
    325             if src_channel.type == FLOAT:
    326                 value =  'util_format_linear_float_to_srgb_8unorm(%s)' % value
    327             else:
    328                 assert src_channel.type == UNSIGNED
    329                 assert src_channel.norm
    330                 assert src_channel.size == 8
    331                 value = 'util_format_linear_to_srgb_8unorm(%s)' % value
    332             # XXX rounding is all wrong.
    333             if dst_channel.size < 8:
    334                 return '%s >> %x' % (value, 8 - dst_channel.size)
    335             else:
    336                 return value
    337         elif src_colorspace == ZS:
    338             pass
    339         elif dst_colorspace == ZS:
    340             pass
    341         else:
    342             assert 0
    343 
    344     if src_channel == dst_channel:
    345         return value
    346 
    347     src_type = src_channel.type
    348     src_size = src_channel.size
    349     src_norm = src_channel.norm
    350     src_pure = src_channel.pure
    351 
    352     # Promote half to float
    353     if src_type == FLOAT and src_size == 16:
    354         value = 'util_half_to_float(%s)' % value
    355         src_size = 32
    356 
    357     # Special case for float <-> ubytes for more accurate results
    358     # Done before clamping since these functions already take care of that
    359     if src_type == UNSIGNED and src_norm and src_size == 8 and dst_channel.type == FLOAT and dst_channel.size == 32:
    360         return 'ubyte_to_float(%s)' % value
    361     if src_type == FLOAT and src_size == 32 and dst_channel.type == UNSIGNED and dst_channel.norm and dst_channel.size == 8:
    362         return 'float_to_ubyte(%s)' % value
    363 
    364     if clamp:
    365         if dst_channel.type != FLOAT or src_type != FLOAT:
    366             value = clamp_expr(src_channel, dst_channel, dst_native_type, value)
    367 
    368     if src_type in (SIGNED, UNSIGNED) and dst_channel.type in (SIGNED, UNSIGNED):
    369         if not src_norm and not dst_channel.norm:
    370             # neither is normalized -- just cast
    371             return '(%s)%s' % (dst_native_type, value)
    372 
    373         src_one = get_one(src_channel)
    374         dst_one = get_one(dst_channel)
    375 
    376         if src_one > dst_one and src_norm and dst_channel.norm:
    377             # We can just bitshift
    378             src_shift = get_one_shift(src_channel)
    379             dst_shift = get_one_shift(dst_channel)
    380             value = '(%s >> %s)' % (value, src_shift - dst_shift)
    381         else:
    382             # We need to rescale using an intermediate type big enough to hold the multiplication of both
    383             tmp_native_type = intermediate_native_type(src_size + dst_channel.size, src_channel.sign and dst_channel.sign)
    384             value = '((%s)%s)' % (tmp_native_type, value)
    385             value = '(%s * 0x%x / 0x%x)' % (value, dst_one, src_one)
    386         value = '(%s)%s' % (dst_native_type, value)
    387         return value
    388 
    389     # Promote to either float or double
    390     if src_type != FLOAT:
    391         if src_norm or src_type == FIXED:
    392             one = get_one(src_channel)
    393             if src_size <= 23:
    394                 value = '(%s * (1.0f/0x%x))' % (value, one)
    395                 if dst_channel.size <= 32:
    396                     value = '(float)%s' % value
    397                 src_size = 32
    398             else:
    399                 # bigger than single precision mantissa, use double
    400                 value = '(%s * (1.0/0x%x))' % (value, one)
    401                 src_size = 64
    402             src_norm = False
    403         else:
    404             if src_size <= 23 or dst_channel.size <= 32:
    405                 value = '(float)%s' % value
    406                 src_size = 32
    407             else:
    408                 # bigger than single precision mantissa, use double
    409                 value = '(double)%s' % value
    410                 src_size = 64
    411         src_type = FLOAT
    412 
    413     # Convert double or float to non-float
    414     if dst_channel.type != FLOAT:
    415         if dst_channel.norm or dst_channel.type == FIXED:
    416             dst_one = get_one(dst_channel)
    417             if dst_channel.size <= 23:
    418                 value = 'util_iround(%s * 0x%x)' % (value, dst_one)
    419             else:
    420                 # bigger than single precision mantissa, use double
    421                 value = '(%s * (double)0x%x)' % (value, dst_one)
    422         value = '(%s)%s' % (dst_native_type, value)
    423     else:
    424         # Cast double to float when converting to either half or float
    425         if dst_channel.size <= 32 and src_size > 32:
    426             value = '(float)%s' % value
    427             src_size = 32
    428 
    429         if dst_channel.size == 16:
    430             value = 'util_float_to_half(%s)' % value
    431         elif dst_channel.size == 64 and src_size < 64:
    432             value = '(double)%s' % value
    433 
    434     return value
    435 
    436 
    437 def generate_unpack_kernel(format, dst_channel, dst_native_type):
    438 
    439     if not is_format_supported(format):
    440         return
    441     
    442     assert format.layout == PLAIN
    443 
    444     src_native_type = native_type(format)
    445 
    446     def unpack_from_bitmask(channels, swizzles):
    447         depth = format.block_size()
    448         print '         uint%u_t value = *(const uint%u_t *)src;' % (depth, depth) 
    449 
    450         # Declare the intermediate variables
    451         for i in range(format.nr_channels()):
    452             src_channel = channels[i]
    453             if src_channel.type == UNSIGNED:
    454                 print '         uint%u_t %s;' % (depth, src_channel.name)
    455             elif src_channel.type == SIGNED:
    456                 print '         int%u_t %s;' % (depth, src_channel.name)
    457 
    458         # Compute the intermediate unshifted values 
    459         for i in range(format.nr_channels()):
    460             src_channel = channels[i]
    461             value = 'value'
    462             shift = src_channel.shift
    463             if src_channel.type == UNSIGNED:
    464                 if shift:
    465                     value = '%s >> %u' % (value, shift)
    466                 if shift + src_channel.size < depth:
    467                     value = '(%s) & 0x%x' % (value, (1 << src_channel.size) - 1)
    468             elif src_channel.type == SIGNED:
    469                 if shift + src_channel.size < depth:
    470                     # Align the sign bit
    471                     lshift = depth - (shift + src_channel.size)
    472                     value = '%s << %u' % (value, lshift)
    473                 # Cast to signed
    474                 value = '(int%u_t)(%s) ' % (depth, value)
    475                 if src_channel.size < depth:
    476                     # Align the LSB bit
    477                     rshift = depth - src_channel.size
    478                     value = '(%s) >> %u' % (value, rshift)
    479             else:
    480                 value = None
    481                 
    482             if value is not None:
    483                 print '         %s = %s;' % (src_channel.name, value)
    484                 
    485         # Convert, swizzle, and store final values
    486         for i in range(4):
    487             swizzle = swizzles[i]
    488             if swizzle < 4:
    489                 src_channel = channels[swizzle]
    490                 src_colorspace = format.colorspace
    491                 if src_colorspace == SRGB and i == 3:
    492                     # Alpha channel is linear
    493                     src_colorspace = RGB
    494                 value = src_channel.name 
    495                 value = conversion_expr(src_channel, 
    496                                         dst_channel, dst_native_type, 
    497                                         value,
    498                                         src_colorspace = src_colorspace)
    499             elif swizzle == SWIZZLE_0:
    500                 value = '0'
    501             elif swizzle == SWIZZLE_1:
    502                 value = get_one(dst_channel)
    503             elif swizzle == SWIZZLE_NONE:
    504                 value = '0'
    505             else:
    506                 assert False
    507             print '         dst[%u] = %s; /* %s */' % (i, value, 'rgba'[i])
    508         
    509     def unpack_from_union(channels, swizzles):
    510         print '         union util_format_%s pixel;' % format.short_name()
    511         print '         memcpy(&pixel, src, sizeof pixel);'
    512     
    513         for i in range(4):
    514             swizzle = swizzles[i]
    515             if swizzle < 4:
    516                 src_channel = channels[swizzle]
    517                 src_colorspace = format.colorspace
    518                 if src_colorspace == SRGB and i == 3:
    519                     # Alpha channel is linear
    520                     src_colorspace = RGB
    521                 value = 'pixel.chan.%s' % src_channel.name 
    522                 value = conversion_expr(src_channel, 
    523                                         dst_channel, dst_native_type, 
    524                                         value,
    525                                         src_colorspace = src_colorspace)
    526             elif swizzle == SWIZZLE_0:
    527                 value = '0'
    528             elif swizzle == SWIZZLE_1:
    529                 value = get_one(dst_channel)
    530             elif swizzle == SWIZZLE_NONE:
    531                 value = '0'
    532             else:
    533                 assert False
    534             print '         dst[%u] = %s; /* %s */' % (i, value, 'rgba'[i])
    535     
    536     if format.is_bitmask():
    537         print_channels(format, unpack_from_bitmask)
    538     else:
    539         print_channels(format, unpack_from_union)
    540 
    541 
    542 def generate_pack_kernel(format, src_channel, src_native_type):
    543 
    544     if not is_format_supported(format):
    545         return
    546     
    547     dst_native_type = native_type(format)
    548 
    549     assert format.layout == PLAIN
    550 
    551     def pack_into_bitmask(channels, swizzles):
    552         inv_swizzle = inv_swizzles(swizzles)
    553 
    554         depth = format.block_size()
    555         print '         uint%u_t value = 0;' % depth 
    556 
    557         for i in range(4):
    558             dst_channel = channels[i]
    559             shift = dst_channel.shift
    560             if inv_swizzle[i] is not None:
    561                 value ='src[%u]' % inv_swizzle[i]
    562                 dst_colorspace = format.colorspace
    563                 if dst_colorspace == SRGB and inv_swizzle[i] == 3:
    564                     # Alpha channel is linear
    565                     dst_colorspace = RGB
    566                 value = conversion_expr(src_channel, 
    567                                         dst_channel, dst_native_type, 
    568                                         value,
    569                                         dst_colorspace = dst_colorspace)
    570                 if dst_channel.type in (UNSIGNED, SIGNED):
    571                     if shift + dst_channel.size < depth:
    572                         value = '(%s) & 0x%x' % (value, (1 << dst_channel.size) - 1)
    573                     if shift:
    574                         value = '(%s) << %u' % (value, shift)
    575                     if dst_channel.type == SIGNED:
    576                         # Cast to unsigned
    577                         value = '(uint%u_t)(%s) ' % (depth, value)
    578                 else:
    579                     value = None
    580                 if value is not None:
    581                     print '         value |= %s;' % (value)
    582                 
    583         print '         *(uint%u_t *)dst = value;' % depth 
    584 
    585     def pack_into_union(channels, swizzles):
    586         inv_swizzle = inv_swizzles(swizzles)
    587 
    588         print '         union util_format_%s pixel;' % format.short_name()
    589     
    590         for i in range(4):
    591             dst_channel = channels[i]
    592             width = dst_channel.size
    593             if inv_swizzle[i] is None:
    594                 continue
    595             dst_colorspace = format.colorspace
    596             if dst_colorspace == SRGB and inv_swizzle[i] == 3:
    597                 # Alpha channel is linear
    598                 dst_colorspace = RGB
    599             value ='src[%u]' % inv_swizzle[i]
    600             value = conversion_expr(src_channel, 
    601                                     dst_channel, dst_native_type, 
    602                                     value, 
    603                                     dst_colorspace = dst_colorspace)
    604             print '         pixel.chan.%s = %s;' % (dst_channel.name, value)
    605     
    606         print '         memcpy(dst, &pixel, sizeof pixel);'
    607     
    608     if format.is_bitmask():
    609         print_channels(format, pack_into_bitmask)
    610     else:
    611         print_channels(format, pack_into_union)
    612 
    613 
    614 def generate_format_unpack(format, dst_channel, dst_native_type, dst_suffix):
    615     '''Generate the function to unpack pixels from a particular format'''
    616 
    617     name = format.short_name()
    618 
    619     print 'static inline void'
    620     print 'util_format_%s_unpack_%s(%s *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)' % (name, dst_suffix, dst_native_type)
    621     print '{'
    622 
    623     if is_format_supported(format):
    624         print '   unsigned x, y;'
    625         print '   for(y = 0; y < height; y += %u) {' % (format.block_height,)
    626         print '      %s *dst = dst_row;' % (dst_native_type)
    627         print '      const uint8_t *src = src_row;'
    628         print '      for(x = 0; x < width; x += %u) {' % (format.block_width,)
    629         
    630         generate_unpack_kernel(format, dst_channel, dst_native_type)
    631     
    632         print '         src += %u;' % (format.block_size() / 8,)
    633         print '         dst += 4;'
    634         print '      }'
    635         print '      src_row += src_stride;'
    636         print '      dst_row += dst_stride/sizeof(*dst_row);'
    637         print '   }'
    638 
    639     print '}'
    640     print
    641     
    642 
    643 def generate_format_pack(format, src_channel, src_native_type, src_suffix):
    644     '''Generate the function to pack pixels to a particular format'''
    645 
    646     name = format.short_name()
    647 
    648     print 'static inline void'
    649     print 'util_format_%s_pack_%s(uint8_t *dst_row, unsigned dst_stride, const %s *src_row, unsigned src_stride, unsigned width, unsigned height)' % (name, src_suffix, src_native_type)
    650     print '{'
    651     
    652     if is_format_supported(format):
    653         print '   unsigned x, y;'
    654         print '   for(y = 0; y < height; y += %u) {' % (format.block_height,)
    655         print '      const %s *src = src_row;' % (src_native_type)
    656         print '      uint8_t *dst = dst_row;'
    657         print '      for(x = 0; x < width; x += %u) {' % (format.block_width,)
    658     
    659         generate_pack_kernel(format, src_channel, src_native_type)
    660             
    661         print '         src += 4;'
    662         print '         dst += %u;' % (format.block_size() / 8,)
    663         print '      }'
    664         print '      dst_row += dst_stride;'
    665         print '      src_row += src_stride/sizeof(*src_row);'
    666         print '   }'
    667         
    668     print '}'
    669     print
    670     
    671 
    672 def generate_format_fetch(format, dst_channel, dst_native_type, dst_suffix):
    673     '''Generate the function to unpack pixels from a particular format'''
    674 
    675     name = format.short_name()
    676 
    677     print 'static inline void'
    678     print 'util_format_%s_fetch_%s(%s *dst, const uint8_t *src, unsigned i, unsigned j)' % (name, dst_suffix, dst_native_type)
    679     print '{'
    680 
    681     if is_format_supported(format):
    682         generate_unpack_kernel(format, dst_channel, dst_native_type)
    683 
    684     print '}'
    685     print
    686 
    687 
    688 def is_format_hand_written(format):
    689     return format.layout in ('s3tc', 'rgtc', 'etc', 'bptc', 'astc', 'subsampled', 'other') or format.colorspace == ZS
    690 
    691 
    692 def generate(formats):
    693     print
    694     print '#include "pipe/p_compiler.h"'
    695     print '#include "u_math.h"'
    696     print '#include "u_half.h"'
    697     print '#include "u_format.h"'
    698     print '#include "u_format_other.h"'
    699     print '#include "util/format_srgb.h"'
    700     print '#include "u_format_yuv.h"'
    701     print '#include "u_format_zs.h"'
    702     print
    703 
    704     for format in formats:
    705         if not is_format_hand_written(format):
    706             
    707             if is_format_supported(format):
    708                 generate_format_type(format)
    709 
    710             if format.is_pure_unsigned():
    711                 native_type = 'unsigned'
    712                 suffix = 'unsigned'
    713                 channel = Channel(UNSIGNED, False, True, 32)
    714 
    715                 generate_format_unpack(format, channel, native_type, suffix)
    716                 generate_format_pack(format, channel, native_type, suffix)
    717                 generate_format_fetch(format, channel, native_type, suffix)
    718 
    719                 channel = Channel(SIGNED, False, True, 32)
    720                 native_type = 'int'
    721                 suffix = 'signed'
    722                 generate_format_unpack(format, channel, native_type, suffix)
    723                 generate_format_pack(format, channel, native_type, suffix)   
    724             elif format.is_pure_signed():
    725                 native_type = 'int'
    726                 suffix = 'signed'
    727                 channel = Channel(SIGNED, False, True, 32)
    728 
    729                 generate_format_unpack(format, channel, native_type, suffix)
    730                 generate_format_pack(format, channel, native_type, suffix)   
    731                 generate_format_fetch(format, channel, native_type, suffix)
    732 
    733                 native_type = 'unsigned'
    734                 suffix = 'unsigned'
    735                 channel = Channel(UNSIGNED, False, True, 32)
    736                 generate_format_unpack(format, channel, native_type, suffix)
    737                 generate_format_pack(format, channel, native_type, suffix)   
    738             else:
    739                 channel = Channel(FLOAT, False, False, 32)
    740                 native_type = 'float'
    741                 suffix = 'rgba_float'
    742 
    743                 generate_format_unpack(format, channel, native_type, suffix)
    744                 generate_format_pack(format, channel, native_type, suffix)
    745                 generate_format_fetch(format, channel, native_type, suffix)
    746 
    747                 channel = Channel(UNSIGNED, True, False, 8)
    748                 native_type = 'uint8_t'
    749                 suffix = 'rgba_8unorm'
    750 
    751                 generate_format_unpack(format, channel, native_type, suffix)
    752                 generate_format_pack(format, channel, native_type, suffix)
    753 
    754