return False
for i in range(4):
- type = format.in_types[i]
- if type.kind not in (VOID, UNSIGNED, FLOAT):
+ channel = format.channels[i]
+ if channel.type not in (VOID, UNSIGNED, FLOAT):
return False
# We can only read a color from a depth/stencil format if the depth channel is present
- if format.colorspace == 'zs' and format.out_swizzle[0] == SWIZZLE_NONE:
+ if format.colorspace == 'zs' and format.swizzles[0] == SWIZZLE_NONE:
return False
return True
return 'uint%u_t' % format.block_size()
else:
# For array pixel formats return the integer type that matches the color channel
- type = format.in_types[0]
- if type.kind == UNSIGNED:
- return 'uint%u_t' % type.size
- elif type.kind == SIGNED:
- return 'int%u_t' % type.size
- elif type.kind == FLOAT:
- if type.size == 32:
+ channel = format.channels[0]
+ if channel.type == UNSIGNED:
+ return 'uint%u_t' % channel.size
+ elif channel.type == SIGNED:
+ return 'int%u_t' % channel.size
+ elif channel.type == FLOAT:
+ if channel.size == 32:
return 'float'
- elif type.size == 64:
+ elif channel.size == 64:
return 'double'
else:
assert False
return 'uint%u_t' % bits
-def get_one_shift(type):
- '''Get the number of the bit that matches unity for this type.'''
- if type.kind == 'FLOAT':
+def get_one_shift(channel):
+ '''Get the number of the bit that matches unity for this channel.'''
+ if channel.type == 'FLOAT':
assert False
- if not type.norm:
+ if not channel.norm:
return 0
- if type.kind == UNSIGNED:
- return type.size
- if type.kind == SIGNED:
- return type.size - 1
- if type.kind == FIXED:
- return type.size / 2
+ if channel.type == UNSIGNED:
+ return channel.size
+ if channel.type == SIGNED:
+ return channel.size - 1
+ if channel.type == FIXED:
+ return channel.size / 2
assert False
-def get_one(type):
- '''Get the value of unity for this type.'''
- if type.kind == 'FLOAT' or not type.norm:
+def get_one(channel):
+ '''Get the value of unity for this channel.'''
+ if channel.type == 'FLOAT' or not channel.norm:
return 1
else:
- return (1 << get_one_shift(type)) - 1
+ return (1 << get_one_shift(channel)) - 1
def generate_clamp():
print
-def clamp_expr(src_type, dst_type, dst_native_type, value):
+def clamp_expr(src_channel, dst_channel, dst_native_type, value):
'''Generate the expression to clamp the value in the source type to the
destination type range.'''
- if src_type == dst_type:
+ if src_channel == dst_channel:
return value
# Pick the approriate clamp function
- if src_type.kind == FLOAT:
- if src_type.size == 32:
+ if src_channel.type == FLOAT:
+ if src_channel.size == 32:
func = 'clampf'
- elif src_type.size == 64:
+ elif src_channel.size == 64:
func = 'clamp'
else:
assert False
- elif src_type.kind == UNSIGNED:
+ elif src_channel.type == UNSIGNED:
func = 'clampui'
- elif src_type.kind == SIGNED:
+ elif src_channel.type == SIGNED:
func = 'clampsi'
else:
assert False
# Clamp floats to [-1, 1] or [0, 1] range
- if src_type.kind == FLOAT and dst_type.norm:
+ if src_channel.type == FLOAT and dst_channel.norm:
max = 1
- if src_type.sign and dst_type.sign:
+ if src_channel.sign and dst_channel.sign:
min = -1
else:
min = 0
return value
-def conversion_expr(src_type, dst_type, dst_native_type, value):
+def conversion_expr(src_channel, dst_channel, dst_native_type, value):
'''Generate the expression to convert a value between two types.'''
- if src_type == dst_type:
+ if src_channel == dst_channel:
return value
- if src_type.kind == FLOAT and dst_type.kind == FLOAT:
+ if src_channel.type == FLOAT and dst_channel.type == FLOAT:
return '(%s)%s' % (dst_native_type, value)
- if not src_type.norm and not dst_type.norm:
+ if not src_channel.norm and not dst_channel.norm:
return '(%s)%s' % (dst_native_type, value)
- value = clamp_expr(src_type, dst_type, dst_native_type, value)
+ value = clamp_expr(src_channel, dst_channel, dst_native_type, value)
- if dst_type.kind == FLOAT:
- if src_type.norm:
- one = get_one(src_type)
- if src_type.size <= 23:
+ if dst_channel.type == FLOAT:
+ if src_channel.norm:
+ one = get_one(src_channel)
+ if src_channel.size <= 23:
scale = '(1.0f/0x%x)' % one
else:
# bigger than single precision mantissa, use double
value = '(%s * %s)' % (value, scale)
return '(%s)%s' % (dst_native_type, value)
- if src_type.kind == FLOAT:
- if dst_type.norm:
- dst_one = get_one(dst_type)
- if dst_type.size <= 23:
+ if src_channel.type == FLOAT:
+ if dst_channel.norm:
+ dst_one = get_one(dst_channel)
+ if dst_channel.size <= 23:
scale = '0x%x' % dst_one
else:
# bigger than single precision mantissa, use double
value = '(%s * %s)' % (value, scale)
return '(%s)%s' % (dst_native_type, value)
- if src_type.kind == dst_type.kind:
- src_one = get_one(src_type)
- dst_one = get_one(dst_type)
+ if src_channel.type == dst_channel.type:
+ src_one = get_one(src_channel)
+ dst_one = get_one(dst_channel)
- if src_one > dst_one and src_type.norm and dst_type.norm:
+ if src_one > dst_one and src_channel.norm and dst_channel.norm:
# We can just bitshift
- src_shift = get_one_shift(src_type)
- dst_shift = get_one_shift(dst_type)
+ src_shift = get_one_shift(src_channel)
+ dst_shift = get_one_shift(dst_channel)
value = '(%s >> %s)' % (value, src_shift - dst_shift)
else:
# We need to rescale using an intermediate type big enough to hold the multiplication of both
- tmp_native_type = intermediate_native_type(src_type.size + dst_type.size, src_type.sign and dst_type.sign)
+ tmp_native_type = intermediate_native_type(src_channel.size + dst_channel.size, src_channel.sign and dst_channel.sign)
value = '(%s)%s' % (tmp_native_type, value)
value = '%s * 0x%x / 0x%x' % (value, dst_one, src_one)
value = '(%s)%s' % (dst_native_type, value)
inv_swizzle = [None]*4
if format.colorspace == 'rgb':
for i in range(4):
- swizzle = format.out_swizzle[i]
+ swizzle = format.swizzles[i]
if swizzle < 4:
inv_swizzle[swizzle] = i
elif format.colorspace == 'zs':
- swizzle = format.out_swizzle[0]
+ swizzle = format.swizzles[0]
if swizzle < 4:
inv_swizzle[swizzle] = 0
else:
return inv_swizzle
-def generate_format_read(format, dst_type, dst_native_type, dst_suffix):
+def generate_format_read(format, dst_channel, dst_native_type, dst_suffix):
'''Generate the function to read pixels from a particular format'''
name = format.short_name()
names = ['']*4
if format.colorspace == 'rgb':
for i in range(4):
- swizzle = format.out_swizzle[i]
+ swizzle = format.swizzles[i]
if swizzle < 4:
names[swizzle] += 'rgba'[i]
elif format.colorspace == 'zs':
- swizzle = format.out_swizzle[0]
+ swizzle = format.swizzles[0]
if swizzle < 4:
names[swizzle] = 'z'
else:
print ' %s pixel = *src_pixel++;' % src_native_type
shift = 0;
for i in range(4):
- src_type = format.in_types[i]
- width = src_type.size
+ src_channel = format.channels[i]
+ width = src_channel.size
if names[i]:
value = 'pixel'
mask = (1 << width) - 1
value = '(%s >> %u)' % (value, shift)
if shift + width < format.block_size():
value = '(%s & 0x%x)' % (value, mask)
- value = conversion_expr(src_type, dst_type, dst_native_type, value)
+ value = conversion_expr(src_channel, dst_channel, dst_native_type, value)
print ' %s %s = %s;' % (dst_native_type, names[i], value)
shift += width
else:
for i in range(4):
- src_type = format.in_types[i]
+ src_channel = format.channels[i]
if names[i]:
value = '(*src_pixel++)'
- value = conversion_expr(src_type, dst_type, dst_native_type, value)
+ value = conversion_expr(src_channel, dst_channel, dst_native_type, value)
print ' %s %s = %s;' % (dst_native_type, names[i], value)
else:
assert False
for i in range(4):
if format.colorspace == 'rgb':
- swizzle = format.out_swizzle[i]
+ swizzle = format.swizzles[i]
if swizzle < 4:
value = names[swizzle]
elif swizzle == SWIZZLE_0:
value = '0'
elif swizzle == SWIZZLE_1:
- value = get_one(dst_type)
+ value = get_one(dst_channel)
else:
assert False
elif format.colorspace == 'zs':
if i < 3:
value = 'z'
else:
- value = get_one(dst_type)
+ value = get_one(dst_channel)
else:
assert False
print ' *dst_pixel++ = %s; /* %s */' % (value, 'rgba'[i])
print
-def generate_format_write(format, src_type, src_native_type, src_suffix):
+def generate_format_write(format, src_channel, src_native_type, src_suffix):
'''Generate the function to write pixels to a particular format'''
name = format.short_name()
print ' %s pixel = 0;' % dst_native_type
shift = 0;
for i in range(4):
- dst_type = format.in_types[i]
- width = dst_type.size
+ dst_channel = format.channels[i]
+ width = dst_channel.size
if inv_swizzle[i] is not None:
value = 'src_pixel[%u]' % inv_swizzle[i]
- value = conversion_expr(src_type, dst_type, dst_native_type, value)
+ value = conversion_expr(src_channel, dst_channel, dst_native_type, value)
if shift:
value = '(%s << %u)' % (value, shift)
print ' pixel |= %s;' % value
print ' *dst_pixel++ = pixel;'
else:
for i in range(4):
- dst_type = format.in_types[i]
+ dst_channel = format.channels[i]
if inv_swizzle[i] is not None:
value = 'src_pixel[%u]' % inv_swizzle[i]
- value = conversion_expr(src_type, dst_type, dst_native_type, value)
+ value = conversion_expr(src_channel, dst_channel, dst_native_type, value)
print ' *dst_pixel++ = %s;' % value
else:
assert False
print
-def generate_read(formats, dst_type, dst_native_type, dst_suffix):
+def generate_read(formats, dst_channel, dst_native_type, dst_suffix):
'''Generate the dispatch function to read pixels from any format'''
for format in formats:
if is_format_supported(format):
- generate_format_read(format, dst_type, dst_native_type, dst_suffix)
+ generate_format_read(format, dst_channel, dst_native_type, dst_suffix)
print 'void'
print 'util_format_read_%s(enum pipe_format format, %s *dst, unsigned dst_stride, const void *src, unsigned src_stride, unsigned x, unsigned y, unsigned w, unsigned h)' % (dst_suffix, dst_native_type)
print
-def generate_write(formats, src_type, src_native_type, src_suffix):
+def generate_write(formats, src_channel, src_native_type, src_suffix):
'''Generate the dispatch function to write pixels to any format'''
for format in formats:
if is_format_supported(format):
- generate_format_write(format, src_type, src_native_type, src_suffix)
+ generate_format_write(format, src_channel, src_native_type, src_suffix)
print 'void'
print 'util_format_write_%s(enum pipe_format format, const %s *src, unsigned src_stride, void *dst, unsigned dst_stride, unsigned x, unsigned y, unsigned w, unsigned h)' % (src_suffix, src_native_type)
generate_clamp()
- type = Type(FLOAT, False, 32)
+ type = Channel(FLOAT, False, 32)
native_type = 'float'
suffix = '4f'
generate_read(formats, type, native_type, suffix)
generate_write(formats, type, native_type, suffix)
- type = Type(UNSIGNED, True, 8)
+ type = Channel(UNSIGNED, True, 8)
native_type = 'uint8_t'
suffix = '4ub'
return (x & (x - 1)) == 0;
-class Type:
- '''Describe the type of a color channel.'''
+class Channel:
+ '''Describe the channel of a color channel.'''
- def __init__(self, kind, norm, size):
- self.kind = kind
+ def __init__(self, type, norm, size):
+ self.type = type
self.norm = norm
self.size = size
- self.sign = kind in (SIGNED, FIXED, FLOAT)
+ self.sign = type in (SIGNED, FIXED, FLOAT)
def __str__(self):
- s = str(self.kind)
+ s = str(self.type)
if self.norm:
s += 'n'
s += str(self.size)
return s
def __eq__(self, other):
- return self.kind == other.kind and self.norm == other.norm and self.size == other.size
+ return self.type == other.type and self.norm == other.norm and self.size == other.size
class Format:
'''Describe a pixel format.'''
- def __init__(self, name, layout, block_width, block_height, in_types, out_swizzle, colorspace):
+ def __init__(self, name, layout, block_width, block_height, channels, swizzles, colorspace):
self.name = name
self.layout = layout
self.block_width = block_width
self.block_height = block_height
- self.in_types = in_types
- self.out_swizzle = out_swizzle
+ self.channels = channels
+ self.swizzles = swizzles
self.name = name
self.colorspace = colorspace
def block_size(self):
size = 0
- for type in self.in_types:
- size += type.size
+ for channel in self.channels:
+ size += channel.size
return size
def nr_channels(self):
nr_channels = 0
- for type in self.in_types:
- if type.size:
+ for channel in self.channels:
+ if channel.size:
nr_channels += 1
return nr_channels
def is_array(self):
- ref_type = self.in_types[0]
- for type in self.in_types[1:]:
- if type.size and (type.size != ref_type.size or type.size % 8):
+ ref_channel = self.channels[0]
+ for channel in self.channels[1:]:
+ if channel.size and (channel.size != ref_channel.size or channel.size % 8):
return False
return True
def is_mixed(self):
- ref_type = self.in_types[0]
- for type in self.in_types[1:]:
- if type.kind != VOID:
- if type.kind != ref_type.kind:
+ ref_channel = self.channels[0]
+ for channel in self.channels[1:]:
+ if channel.type != VOID:
+ if channel.type != ref_channel.type:
return True
- if type.norm != ref_type.norm:
+ if channel.norm != ref_channel.norm:
return True
return False
def is_pot(self):
return is_pot(self.block_size())
+ def is_int(self):
+ for channel in self.channels:
+ if channel.type not in (VOID, UNSIGNED, SIGNED):
+ return False
+ return True
+
+ def is_float(self):
+ for channel in self.channels:
+ if channel.type not in (VOID, FLOAT):
+ return False
+ return True
+
def stride(self):
return self.block_size()/8
-_kind_parse_map = {
+_type_parse_map = {
'': VOID,
'x': VOID,
'u': UNSIGNED,
def parse(filename):
'''Parse the format descrition in CSV format in terms of the
- Type and Format classes above.'''
+ Channel and Format classes above.'''
stream = open(filename)
formats = []
name = fields[0]
layout = fields[1]
block_width, block_height = map(int, fields[2:4])
- in_types = []
+ channels = []
for field in fields[4:8]:
if field:
- kind = _kind_parse_map[field[0]]
+ type = _type_parse_map[field[0]]
if field[1] == 'n':
norm = True
size = int(field[2:])
norm = False
size = int(field[1:])
else:
- kind = VOID
+ type = VOID
norm = False
size = 0
- in_type = Type(kind, norm, size)
- in_types.append(in_type)
- out_swizzle = [_swizzle_parse_map[swizzle] for swizzle in fields[8]]
+ channel = Channel(type, norm, size)
+ channels.append(channel)
+ swizzles = [_swizzle_parse_map[swizzle] for swizzle in fields[8]]
colorspace = fields[9]
- formats.append(Format(name, layout, block_width, block_height, in_types, out_swizzle, colorspace))
+ formats.append(Format(name, layout, block_width, block_height, channels, swizzles, colorspace))
return formats
}
-kind_map = {
+type_map = {
VOID: "UTIL_FORMAT_TYPE_VOID",
UNSIGNED: "UTIL_FORMAT_TYPE_UNSIGNED",
SIGNED: "UTIL_FORMAT_TYPE_SIGNED",
print " %s,\t/* is_mixed */" % (bool_map(format.is_mixed()),)
print " {"
for i in range(4):
- type = format.in_types[i]
+ channel = format.channels[i]
if i < 3:
sep = ","
else:
sep = ""
- print " {%s, %s, %u}%s\t/* %s */" % (kind_map[type.kind], bool_map(type.norm), type.size, sep, "xyzw"[i])
+ print " {%s, %s, %u}%s\t/* %s */" % (type_map[channel.type], bool_map(channel.norm), channel.size, sep, "xyzw"[i])
print " },"
print " {"
for i in range(4):
- swizzle = format.out_swizzle[i]
+ swizzle = format.swizzles[i]
if i < 3:
sep = ","
else:
from u_format_access import *
-def generate_format_read(format, dst_type, dst_native_type, dst_suffix):
+def generate_format_read(format, dst_channel, dst_native_type, dst_suffix):
'''Generate the function to read pixels from a particular format'''
name = format.short_name()
names = ['']*4
if format.colorspace == 'rgb':
for i in range(4):
- swizzle = format.out_swizzle[i]
+ swizzle = format.swizzles[i]
if swizzle < 4:
names[swizzle] += 'rgba'[i]
elif format.colorspace == 'zs':
- swizzle = format.out_swizzle[0]
+ swizzle = format.swizzles[0]
if swizzle < 4:
names[swizzle] = 'z'
else:
print ' %s pixel = *src_pixel++;' % src_native_type
shift = 0;
for i in range(4):
- src_type = format.in_types[i]
- width = src_type.size
+ src_channel = format.channels[i]
+ width = src_channel.size
if names[i]:
value = 'pixel'
mask = (1 << width) - 1
value = '(%s >> %u)' % (value, shift)
if shift + width < format.block_size():
value = '(%s & 0x%x)' % (value, mask)
- value = conversion_expr(src_type, dst_type, dst_native_type, value)
+ value = conversion_expr(src_channel, dst_channel, dst_native_type, value)
print ' %s %s = %s;' % (dst_native_type, names[i], value)
shift += width
else:
for i in range(4):
- src_type = format.in_types[i]
+ src_channel = format.channels[i]
if names[i]:
value = '(*src_pixel++)'
- value = conversion_expr(src_type, dst_type, dst_native_type, value)
+ value = conversion_expr(src_channel, dst_channel, dst_native_type, value)
print ' %s %s = %s;' % (dst_native_type, names[i], value)
else:
assert False
for i in range(4):
if format.colorspace == 'rgb':
- swizzle = format.out_swizzle[i]
+ swizzle = format.swizzles[i]
if swizzle < 4:
value = names[swizzle]
elif swizzle == SWIZZLE_0:
value = '0'
elif swizzle == SWIZZLE_1:
- value = get_one(dst_type)
+ value = get_one(dst_channel)
else:
assert False
elif format.colorspace == 'zs':
if i < 3:
value = 'z'
else:
- value = get_one(dst_type)
+ value = get_one(dst_channel)
else:
assert False
print ' TILE_PIXEL(dst, x, y, %u) = %s; /* %s */' % (i, value, 'rgba'[i])
print
-def pack_rgba(format, src_type, r, g, b, a):
+def pack_rgba(format, src_channel, r, g, b, a):
"""Return an expression for packing r, g, b, a into a pixel of the
given format. Ex: '(b << 24) | (g << 16) | (r << 8) | (a << 0)'
"""
value = None
if value:
- dst_type = format.in_types[i]
+ dst_channel = format.channels[i]
dst_native_type = native_type(format)
- value = conversion_expr(src_type, dst_type, dst_native_type, value)
+ value = conversion_expr(src_channel, dst_channel, dst_native_type, value)
term = "((%s) << %d)" % (value, shift)
if expr:
expr = expr + " | " + term
else:
expr = term
- width = format.in_types[i].size
+ width = format.channels[i].size
shift = shift + width
return expr
-def emit_unrolled_write_code(format, src_type):
+def emit_unrolled_write_code(format, src_channel):
'''Emit code for writing a block based on unrolled loops.
This is considerably faster than the TILE_PIXEL-based code below.
'''
print ' const uint8_t *a = src + 3 * TILE_C_STRIDE;'
print ' (void) r; (void) g; (void) b; (void) a; /* silence warnings */'
print ' for (i = 0; i < TILE_C_STRIDE; i += 2) {'
- print ' const uint32_t pixel0 = %s;' % pack_rgba(format, src_type, "r[i+0]", "g[i+0]", "b[i+0]", "a[i+0]")
- print ' const uint32_t pixel1 = %s;' % pack_rgba(format, src_type, "r[i+1]", "g[i+1]", "b[i+1]", "a[i+1]")
+ print ' const uint32_t pixel0 = %s;' % pack_rgba(format, src_channel, "r[i+0]", "g[i+0]", "b[i+0]", "a[i+0]")
+ print ' const uint32_t pixel1 = %s;' % pack_rgba(format, src_channel, "r[i+1]", "g[i+1]", "b[i+1]", "a[i+1]")
print ' const unsigned offset = (py + tile_y_offset[i]) * dstpix_stride + (px + tile_x_offset[i]);'
print ' dstpix[offset + 0] = pixel0;'
print ' dstpix[offset + 1] = pixel1;'
print ' }'
-def emit_tile_pixel_write_code(format, src_type):
+def emit_tile_pixel_write_code(format, src_channel):
'''Emit code for writing a block based on the TILE_PIXEL macro.'''
dst_native_type = native_type(format)
print ' %s pixel = 0;' % dst_native_type
shift = 0;
for i in range(4):
- dst_type = format.in_types[i]
- width = dst_type.size
+ dst_channel = format.channels[i]
+ width = dst_channel.size
if inv_swizzle[i] is not None:
value = 'TILE_PIXEL(src, x, y, %u)' % inv_swizzle[i]
- value = conversion_expr(src_type, dst_type, dst_native_type, value)
+ value = conversion_expr(src_channel, dst_channel, dst_native_type, value)
if shift:
value = '(%s << %u)' % (value, shift)
print ' pixel |= %s;' % value
print ' *dst_pixel++ = pixel;'
else:
for i in range(4):
- dst_type = format.in_types[i]
+ dst_channel = format.channels[i]
if inv_swizzle[i] is not None:
value = 'TILE_PIXEL(src, x, y, %u)' % inv_swizzle[i]
- value = conversion_expr(src_type, dst_type, dst_native_type, value)
+ value = conversion_expr(src_channel, dst_channel, dst_native_type, value)
print ' *dst_pixel++ = %s;' % value
else:
assert False
print ' }'
-def generate_format_write(format, src_type, src_native_type, src_suffix):
+def generate_format_write(format, src_channel, src_native_type, src_suffix):
'''Generate the function to write pixels to a particular format'''
name = format.short_name()
and format.block_size() <= 32 \
and format.is_pot() \
and not format.is_mixed() \
- and format.in_types[0].kind == UNSIGNED:
- emit_unrolled_write_code(format, src_type)
+ and format.channels[0].type == UNSIGNED:
+ emit_unrolled_write_code(format, src_channel)
else:
- emit_tile_pixel_write_code(format, src_type)
+ emit_tile_pixel_write_code(format, src_channel)
print '}'
print
-def generate_read(formats, dst_type, dst_native_type, dst_suffix):
+def generate_read(formats, dst_channel, dst_native_type, dst_suffix):
'''Generate the dispatch function to read pixels from any format'''
for format in formats:
if is_format_supported(format):
- generate_format_read(format, dst_type, dst_native_type, dst_suffix)
+ generate_format_read(format, dst_channel, dst_native_type, dst_suffix)
print 'void'
print 'lp_tile_read_%s(enum pipe_format format, %s *dst, const void *src, unsigned src_stride, unsigned x, unsigned y, unsigned w, unsigned h)' % (dst_suffix, dst_native_type)
print
-def generate_write(formats, src_type, src_native_type, src_suffix):
+def generate_write(formats, src_channel, src_native_type, src_suffix):
'''Generate the dispatch function to write pixels to any format'''
for format in formats:
if is_format_supported(format):
- generate_format_write(format, src_type, src_native_type, src_suffix)
+ generate_format_write(format, src_channel, src_native_type, src_suffix)
print 'void'
print 'lp_tile_write_%s(enum pipe_format format, const %s *src, void *dst, unsigned dst_stride, unsigned x, unsigned y, unsigned w, unsigned h)' % (src_suffix, src_native_type)
generate_clamp()
- type = Type(UNSIGNED, True, 8)
+ channel = Channel(UNSIGNED, True, 8)
native_type = 'uint8_t'
suffix = '4ub'
- generate_read(formats, type, native_type, suffix)
- generate_write(formats, type, native_type, suffix)
+ generate_read(formats, channel, native_type, suffix)
+ generate_write(formats, channel, native_type, suffix)
if __name__ == '__main__':