Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | 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 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', '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.