"Fossies" - the Fresh Open Source Software Archive

Member "mesa-20.1.8/src/amd/vulkan/vk_format_parse.py" (16 Sep 2020, 12450 Bytes) of package /linux/misc/mesa-20.1.8.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "vk_format_parse.py" see the Fossies "Dox" file reference documentation.

    1 
    2 '''
    3 /**************************************************************************
    4  *
    5  * Copyright 2009 VMware, Inc.
    6  * All Rights Reserved.
    7  *
    8  * Permission is hereby granted, free of charge, to any person obtaining a
    9  * copy of this software and associated documentation files (the
   10  * "Software"), to deal in the Software without restriction, including
   11  * without limitation the rights to use, copy, modify, merge, publish,
   12  * distribute, sub license, and/or sell copies of the Software, and to
   13  * permit persons to whom the Software is furnished to do so, subject to
   14  * the following conditions:
   15  *
   16  * The above copyright notice and this permission notice (including the
   17  * next paragraph) shall be included in all copies or substantial portions
   18  * of the Software.
   19  *
   20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   21  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
   22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
   23  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
   24  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
   25  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
   26  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
   27  *
   28  **************************************************************************/
   29 '''
   30 
   31 
   32 VOID, UNSIGNED, SIGNED, FIXED, FLOAT = range(5)
   33 
   34 SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W, SWIZZLE_0, SWIZZLE_1, SWIZZLE_NONE, = range(7)
   35 
   36 PLAIN = 'plain'
   37 SCALED = 'scaled'
   38 
   39 RGB = 'rgb'
   40 SRGB = 'srgb'
   41 YUV = 'yuv'
   42 ZS = 'zs'
   43 
   44 
   45 def is_pot(x):
   46    return (x & (x - 1)) == 0
   47 
   48 
   49 VERY_LARGE = 99999999999999999999999
   50 
   51 
   52 class Channel:
   53     '''Describe the channel of a color channel.'''
   54     
   55     def __init__(self, type, norm, pure, scaled, size, name = ''):
   56         self.type = type
   57         self.norm = norm
   58         self.pure = pure
   59         self.size = size
   60         self.scaled = scaled
   61         self.sign = type in (SIGNED, FIXED, FLOAT)
   62         self.name = name
   63 
   64     def __str__(self):
   65         s = str(self.type)
   66         if self.norm:
   67             s += 'n'
   68         if self.pure:
   69             s += 'p'
   70         if self.scaled:
   71             s += 's'
   72         s += str(self.size)
   73         return s
   74 
   75     def __eq__(self, other):
   76         if other is None:
   77             return False
   78 
   79         return self.type == other.type and self.norm == other.norm and self.pure == other.pure and self.size == other.size and self.scaled == other.scaled
   80 
   81     def __ne__(self, other):
   82         return not self == other
   83 
   84     def max(self):
   85         '''Maximum representable number.'''
   86         if self.type == FLOAT:
   87             return VERY_LARGE
   88         if self.type == FIXED:
   89             return (1 << (self.size/2)) - 1
   90         if self.norm:
   91             return 1
   92         if self.type == UNSIGNED:
   93             return (1 << self.size) - 1
   94         if self.type == SIGNED:
   95             return (1 << (self.size - 1)) - 1
   96         assert False
   97     
   98     def min(self):
   99         '''Minimum representable number.'''
  100         if self.type == FLOAT:
  101             return -VERY_LARGE
  102         if self.type == FIXED:
  103             return -(1 << (self.size/2))
  104         if self.type == UNSIGNED:
  105             return 0
  106         if self.norm:
  107             return -1
  108         if self.type == SIGNED:
  109             return -(1 << (self.size - 1))
  110         assert False
  111 
  112 
  113 class Format:
  114     '''Describe a pixel format.'''
  115 
  116     def __init__(self, name, layout, block_width, block_height, le_channels, le_swizzles, be_channels, be_swizzles, colorspace, width_divisor, height_divisor, plane_formats):
  117         self.name = name
  118         self.layout = layout
  119         self.block_width = block_width
  120         self.block_height = block_height
  121         self.le_channels = le_channels
  122         self.le_swizzles = le_swizzles
  123         self.be_channels = be_channels
  124         self.be_swizzles = be_swizzles
  125         self.name = name
  126         self.colorspace = colorspace
  127         self.plane_count = len(plane_formats)
  128         self.width_divisor = width_divisor
  129         self.height_divisor = height_divisor
  130         self.plane_formats = plane_formats
  131 
  132         while len(self.plane_formats) < 3:
  133             self.plane_formats.append("VK_FORMAT_UNDEFINED")
  134 
  135     def __str__(self):
  136         return self.name
  137 
  138     def short_name(self):
  139         '''Make up a short norm for a format, suitable to be used as suffix in
  140         function names.'''
  141 
  142         name = self.name
  143         if name.startswith('VK_FORMAT_'):
  144             name = name[len('VK_FORMAT_'):]
  145         name = name.lower()
  146         return name
  147 
  148     def block_size(self):
  149         size = 0
  150         for channel in self.le_channels:
  151             size += channel.size
  152         return size
  153 
  154     def nr_channels(self):
  155         nr_channels = 0
  156         for channel in self.le_channels:
  157             if channel.size:
  158                 nr_channels += 1
  159         return nr_channels
  160 
  161     def array_element(self):
  162         if self.layout != PLAIN:
  163             return None
  164         ref_channel = self.le_channels[0]
  165         if ref_channel.type == VOID:
  166            ref_channel = self.le_channels[1]
  167         for channel in self.le_channels:
  168             if channel.size and (channel.size != ref_channel.size or channel.size % 8):
  169                 return None
  170             if channel.type != VOID:
  171                 if channel.type != ref_channel.type:
  172                     return None
  173                 if channel.norm != ref_channel.norm:
  174                     return None
  175                 if channel.pure != ref_channel.pure:
  176                     return None
  177                 if channel.scaled != ref_channel.scaled:
  178                     return None
  179         return ref_channel
  180 
  181     def is_array(self):
  182         return self.array_element() != None
  183 
  184     def is_mixed(self):
  185         if self.layout != PLAIN:
  186             return False
  187         ref_channel = self.le_channels[0]
  188         if ref_channel.type == VOID:
  189            ref_channel = self.le_channels[1]
  190         for channel in self.le_channels[1:]:
  191             if channel.type != VOID:
  192                 if channel.type != ref_channel.type:
  193                     return True
  194                 if channel.norm != ref_channel.norm:
  195                     return True
  196                 if channel.pure != ref_channel.pure:
  197                     return True
  198                 if channel.scaled != ref_channel.scaled:
  199                     return True
  200         return False
  201 
  202     def is_pot(self):
  203         return is_pot(self.block_size())
  204 
  205     def is_int(self):
  206         if self.layout != PLAIN:
  207             return False
  208         for channel in self.le_channels:
  209             if channel.type not in (VOID, UNSIGNED, SIGNED):
  210                 return False
  211         return True
  212 
  213     def is_float(self):
  214         if self.layout != PLAIN:
  215             return False
  216         for channel in self.le_channels:
  217             if channel.type not in (VOID, FLOAT):
  218                 return False
  219         return True
  220 
  221     def is_bitmask(self):
  222         if self.layout != PLAIN:
  223             return False
  224         if self.block_size() not in (8, 16, 32):
  225             return False
  226         for channel in self.le_channels:
  227             if channel.type not in (VOID, UNSIGNED, SIGNED):
  228                 return False
  229         return True
  230 
  231     def is_pure_color(self):
  232         if self.layout != PLAIN or self.colorspace == ZS:
  233             return False
  234         pures = [channel.pure
  235                  for channel in self.le_channels
  236                  if channel.type != VOID]
  237         for x in pures:
  238            assert x == pures[0]
  239         return pures[0]
  240 
  241     def channel_type(self):
  242         types = [channel.type
  243                  for channel in self.le_channels
  244                  if channel.type != VOID]
  245         for x in types:
  246            assert x == types[0]
  247         return types[0]
  248 
  249     def is_pure_signed(self):
  250         return self.is_pure_color() and self.channel_type() == SIGNED
  251 
  252     def is_pure_unsigned(self):
  253         return self.is_pure_color() and self.channel_type() == UNSIGNED
  254 
  255     def has_channel(self, id):
  256         return self.le_swizzles[id] != SWIZZLE_NONE
  257 
  258     def has_depth(self):
  259         return self.colorspace == ZS and self.has_channel(0)
  260 
  261     def has_stencil(self):
  262         return self.colorspace == ZS and self.has_channel(1)
  263 
  264     def stride(self):
  265         return self.block_size()/8
  266 
  267 
  268 _type_parse_map = {
  269     '':  VOID,
  270     'x': VOID,
  271     'u': UNSIGNED,
  272     's': SIGNED,
  273     'h': FIXED,
  274     'f': FLOAT,
  275 }
  276 
  277 _swizzle_parse_map = {
  278     'x': SWIZZLE_X,
  279     'y': SWIZZLE_Y,
  280     'z': SWIZZLE_Z,
  281     'w': SWIZZLE_W,
  282     '0': SWIZZLE_0,
  283     '1': SWIZZLE_1,
  284     '_': SWIZZLE_NONE,
  285 }
  286 
  287 def _parse_channels(fields, layout, colorspace, swizzles):
  288     if layout == PLAIN:
  289         names = ['']*4
  290         if colorspace in (RGB, SRGB):
  291             for i in range(4):
  292                 swizzle = swizzles[i]
  293                 if swizzle < 4:
  294                     names[swizzle] += 'rgba'[i]
  295         elif colorspace == ZS:
  296             for i in range(4):
  297                 swizzle = swizzles[i]
  298                 if swizzle < 4:
  299                     names[swizzle] += 'zs'[i]
  300         else:
  301             assert False
  302         for i in range(4):
  303             if names[i] == '':
  304                 names[i] = 'x'
  305     else:
  306         names = ['x', 'y', 'z', 'w']
  307 
  308     channels = []
  309     for i in range(0, 4):
  310         field = fields[i]
  311         if field:
  312             type = _type_parse_map[field[0]]
  313             if field[1] == 'n':
  314                 norm = True
  315                 pure = False
  316                 scaled = False
  317                 size = int(field[2:])
  318             elif field[1] == 'p':
  319                 pure = True
  320                 norm = False
  321                 scaled = False
  322                 size = int(field[2:])
  323             elif field[1] == 's':
  324                 pure = False
  325                 norm = False
  326                 scaled = True
  327                 size = int(field[2:])
  328             else:
  329                 norm = False
  330                 pure = False
  331                 scaled = False
  332                 size = int(field[1:])
  333         else:
  334             type = VOID
  335             norm = False
  336             pure = False
  337             scaled = False
  338             size = 0
  339         channel = Channel(type, norm, pure, scaled, size, names[i])
  340         channels.append(channel)
  341 
  342     return channels
  343 
  344 def parse_plane_divisor(format):
  345     if format == '444':
  346         return (1, 1)
  347     elif format == '422':
  348         return (2, 1)
  349     elif format == '420':
  350         return (2, 2)
  351     else:
  352         return (1, 1)
  353 
  354 def parse(filename):
  355     '''Parse the format description in CSV format in terms of the
  356     Channel and Format classes above.'''
  357 
  358     stream = open(filename)
  359     formats = []
  360     for line in stream:
  361         try:
  362             comment = line.index('#')
  363         except ValueError:
  364             pass
  365         else:
  366             line = line[:comment]
  367         line = line.strip()
  368         if not line:
  369             continue
  370 
  371         fields = [field.strip() for field in line.split(',')]
  372         if len (fields) < 10:
  373            continue
  374 
  375         be_fields = fields[4:9]
  376 
  377         name = fields[0]
  378         layout = fields[1]
  379         block_width, block_height = map(int, fields[2:4])
  380         colorspace = fields[9]
  381 
  382         le_swizzles = [_swizzle_parse_map[swizzle] for swizzle in fields[8]]
  383         le_channels = _parse_channels(fields[4:8], layout, colorspace, le_swizzles)
  384 
  385         be_swizzles = [_swizzle_parse_map[swizzle] for swizzle in be_fields[4]]
  386         be_channels = _parse_channels(be_fields, layout, colorspace, be_swizzles)
  387 
  388         le_shift = 0
  389         for channel in le_channels:
  390             channel.shift = le_shift
  391             le_shift += channel.size
  392 
  393         be_shift = 0
  394         for channel in be_channels[3::-1]:
  395             channel.shift = be_shift
  396             be_shift += channel.size
  397 
  398         assert le_shift == be_shift
  399         for i in range(4):
  400             assert (le_swizzles[i] != SWIZZLE_NONE) == (be_swizzles[i] != SWIZZLE_NONE)
  401 
  402         width_divisor = 1
  403         height_divisor = 1
  404         plane_formats = [name]
  405         if layout == "multiplane":
  406             plane_formats = []
  407             (width_divisor, height_divisor) = parse_plane_divisor(fields[10])
  408 
  409             for i in range(11, len(fields)):
  410                 plane_formats.append(fields[i])
  411             assert (len(plane_formats) > 1)
  412 
  413         format = Format(name, layout, block_width, block_height, le_channels, le_swizzles, be_channels, be_swizzles, colorspace, width_divisor, height_divisor, plane_formats)
  414         formats.append(format)
  415     return formats
  416