Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

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