3 /**************************************************************************
5 * Copyright 2009-2010 VMware, Inc.
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:
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial portions
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.
28 **************************************************************************/
32 * Pixel format packing and unpacking functions.
34 * @author Jose Fonseca <jfonseca@vmware.com>
39 from __future__
import division
, print_function
43 from u_format_parse
import *
46 if sys
.version_info
< (3, 0):
47 integer_types
= (int, long)
50 integer_types
= (int, )
52 def inv_swizzles(swizzles
):
53 '''Return an array[4] of inverse swizzle terms'''
54 '''Only pick the first matching value to avoid l8 getting blue and i8 getting alpha'''
55 inv_swizzle
= [None]*4
58 if swizzle
< 4 and inv_swizzle
[swizzle
] == None:
59 inv_swizzle
[swizzle
] = i
62 def print_channels(format
, func
):
63 if format
.nr_channels() <= 1:
64 func(format
.le_channels
, format
.le_swizzles
)
66 if (format
.le_channels
== format
.be_channels
and
67 [c
.shift
for c
in format
.le_channels
] ==
68 [c
.shift
for c
in format
.be_channels
] and
69 format
.le_swizzles
== format
.be_swizzles
):
70 func(format
.le_channels
, format
.le_swizzles
)
72 print('#if UTIL_ARCH_BIG_ENDIAN')
73 func(format
.be_channels
, format
.be_swizzles
)
75 func(format
.le_channels
, format
.le_swizzles
)
78 def generate_format_type(format
):
79 '''Generate a structure that describes the format.'''
81 assert format
.layout
== PLAIN
83 def generate_bitfields(channels
, swizzles
):
84 for channel
in channels
:
85 if channel
.type == VOID
:
87 print(' unsigned %s:%u;' % (channel
.name
, channel
.size
))
88 elif channel
.type == UNSIGNED
:
89 print(' unsigned %s:%u;' % (channel
.name
, channel
.size
))
90 elif channel
.type in (SIGNED
, FIXED
):
91 print(' int %s:%u;' % (channel
.name
, channel
.size
))
92 elif channel
.type == FLOAT
:
93 if channel
.size
== 64:
94 print(' double %s;' % (channel
.name
))
95 elif channel
.size
== 32:
96 print(' float %s;' % (channel
.name
))
98 print(' unsigned %s:%u;' % (channel
.name
, channel
.size
))
102 def generate_full_fields(channels
, swizzles
):
103 for channel
in channels
:
104 assert channel
.size
% 8 == 0 and is_pot(channel
.size
)
105 if channel
.type == VOID
:
107 print(' uint%u_t %s;' % (channel
.size
, channel
.name
))
108 elif channel
.type == UNSIGNED
:
109 print(' uint%u_t %s;' % (channel
.size
, channel
.name
))
110 elif channel
.type in (SIGNED
, FIXED
):
111 print(' int%u_t %s;' % (channel
.size
, channel
.name
))
112 elif channel
.type == FLOAT
:
113 if channel
.size
== 64:
114 print(' double %s;' % (channel
.name
))
115 elif channel
.size
== 32:
116 print(' float %s;' % (channel
.name
))
117 elif channel
.size
== 16:
118 print(' uint16_t %s;' % (channel
.name
))
124 use_bitfields
= False
125 for channel
in format
.le_channels
:
126 if channel
.size
% 8 or not is_pot(channel
.size
):
129 print('struct util_format_%s {' % format
.short_name())
131 print_channels(format
, generate_bitfields
)
133 print_channels(format
, generate_full_fields
)
138 def is_format_supported(format
):
139 '''Determines whether we actually have the plumbing necessary to generate the
140 to read/write to/from this format.'''
142 # FIXME: Ideally we would support any format combination here.
144 if format
.layout
!= PLAIN
:
148 channel
= format
.le_channels
[i
]
149 if channel
.type not in (VOID
, UNSIGNED
, SIGNED
, FLOAT
, FIXED
):
151 if channel
.type == FLOAT
and channel
.size
not in (16, 32, 64):
156 def native_type(format
):
157 '''Get the native appropriate for a format.'''
159 if format
.name
== 'PIPE_FORMAT_R11G11B10_FLOAT':
161 if format
.name
== 'PIPE_FORMAT_R9G9B9E5_FLOAT':
164 if format
.layout
== PLAIN
:
165 if not format
.is_array():
166 # For arithmetic pixel formats return the integer type that matches the whole pixel
167 return 'uint%u_t' % format
.block_size()
169 # For array pixel formats return the integer type that matches the color channel
170 channel
= format
.array_element()
171 if channel
.type in (UNSIGNED
, VOID
):
172 return 'uint%u_t' % channel
.size
173 elif channel
.type in (SIGNED
, FIXED
):
174 return 'int%u_t' % channel
.size
175 elif channel
.type == FLOAT
:
176 if channel
.size
== 16:
178 elif channel
.size
== 32:
180 elif channel
.size
== 64:
190 def intermediate_native_type(bits
, sign
):
191 '''Find a native type adequate to hold intermediate results of the request bit size.'''
193 bytes
= 4 # don't use anything smaller than 32bits
194 while bytes
* 8 < bits
:
199 return 'int%u_t' % bits
201 return 'uint%u_t' % bits
204 def get_one_shift(type):
205 '''Get the number of the bit that matches unity for this type.'''
206 if type.type == 'FLOAT':
210 if type.type == UNSIGNED
:
212 if type.type == SIGNED
:
214 if type.type == FIXED
:
219 def truncate_mantissa(x
, bits
):
220 '''Truncate an integer so it can be represented exactly with a floating
223 assert isinstance(x
, integer_types
)
230 # We can represent integers up to mantissa + 1 bits exactly
231 mask
= (1 << (bits
+ 1)) - 1
233 # Slide the mask until the MSB matches
235 while (x
>> shift
) & ~mask
:
243 def value_to_native(type, value
):
244 '''Get the value of unity for this type.'''
245 if type.type == FLOAT
:
247 and isinstance(value
, integer_types
):
248 return truncate_mantissa(value
, 23)
250 if type.type == FIXED
:
251 return int(value
* (1 << (type.size
// 2)))
254 if type.type == UNSIGNED
:
255 return int(value
* ((1 << type.size
) - 1))
256 if type.type == SIGNED
:
257 return int(value
* ((1 << (type.size
- 1)) - 1))
261 def native_to_constant(type, value
):
262 '''Get the value of unity for this type.'''
263 if type.type == FLOAT
:
265 return "%.1ff" % float(value
)
267 return "%.1f" % float(value
)
269 return str(int(value
))
273 '''Get the value of unity for this type.'''
274 return value_to_native(type, 1)
277 def clamp_expr(src_channel
, dst_channel
, dst_native_type
, value
):
278 '''Generate the expression to clamp the value in the source type to the
279 destination type range.'''
281 if src_channel
== dst_channel
:
284 src_min
= src_channel
.min()
285 src_max
= src_channel
.max()
286 dst_min
= dst_channel
.min()
287 dst_max
= dst_channel
.max()
289 # Translate the destination range to the src native value
290 dst_min_native
= native_to_constant(src_channel
, value_to_native(src_channel
, dst_min
))
291 dst_max_native
= native_to_constant(src_channel
, value_to_native(src_channel
, dst_max
))
293 if src_min
< dst_min
and src_max
> dst_max
:
294 return 'CLAMP(%s, %s, %s)' % (value
, dst_min_native
, dst_max_native
)
296 if src_max
> dst_max
:
297 return 'MIN2(%s, %s)' % (value
, dst_max_native
)
299 if src_min
< dst_min
:
300 return 'MAX2(%s, %s)' % (value
, dst_min_native
)
305 def conversion_expr(src_channel
,
306 dst_channel
, dst_native_type
,
309 src_colorspace
= RGB
,
310 dst_colorspace
= RGB
):
311 '''Generate the expression to convert a value between two types.'''
313 if src_colorspace
!= dst_colorspace
:
314 if src_colorspace
== SRGB
:
315 assert src_channel
.type == UNSIGNED
316 assert src_channel
.norm
317 assert src_channel
.size
<= 8
318 assert src_channel
.size
>= 4
319 assert dst_colorspace
== RGB
320 if src_channel
.size
< 8:
321 value
= '%s << %x | %s >> %x' % (value
, 8 - src_channel
.size
, value
, 2 * src_channel
.size
- 8)
322 if dst_channel
.type == FLOAT
:
323 return 'util_format_srgb_8unorm_to_linear_float(%s)' % value
325 assert dst_channel
.type == UNSIGNED
326 assert dst_channel
.norm
327 assert dst_channel
.size
== 8
328 return 'util_format_srgb_to_linear_8unorm(%s)' % value
329 elif dst_colorspace
== SRGB
:
330 assert dst_channel
.type == UNSIGNED
331 assert dst_channel
.norm
332 assert dst_channel
.size
<= 8
333 assert src_colorspace
== RGB
334 if src_channel
.type == FLOAT
:
335 value
= 'util_format_linear_float_to_srgb_8unorm(%s)' % value
337 assert src_channel
.type == UNSIGNED
338 assert src_channel
.norm
339 assert src_channel
.size
== 8
340 value
= 'util_format_linear_to_srgb_8unorm(%s)' % value
341 # XXX rounding is all wrong.
342 if dst_channel
.size
< 8:
343 return '%s >> %x' % (value
, 8 - dst_channel
.size
)
346 elif src_colorspace
== ZS
:
348 elif dst_colorspace
== ZS
:
353 if src_channel
== dst_channel
:
356 src_type
= src_channel
.type
357 src_size
= src_channel
.size
358 src_norm
= src_channel
.norm
359 src_pure
= src_channel
.pure
361 # Promote half to float
362 if src_type
== FLOAT
and src_size
== 16:
363 value
= 'util_half_to_float(%s)' % value
366 # Special case for float <-> ubytes for more accurate results
367 # Done before clamping since these functions already take care of that
368 if src_type
== UNSIGNED
and src_norm
and src_size
== 8 and dst_channel
.type == FLOAT
and dst_channel
.size
== 32:
369 return 'ubyte_to_float(%s)' % value
370 if src_type
== FLOAT
and src_size
== 32 and dst_channel
.type == UNSIGNED
and dst_channel
.norm
and dst_channel
.size
== 8:
371 return 'float_to_ubyte(%s)' % value
374 if dst_channel
.type != FLOAT
or src_type
!= FLOAT
:
375 value
= clamp_expr(src_channel
, dst_channel
, dst_native_type
, value
)
377 if src_type
in (SIGNED
, UNSIGNED
) and dst_channel
.type in (SIGNED
, UNSIGNED
):
378 if not src_norm
and not dst_channel
.norm
:
379 # neither is normalized -- just cast
380 return '(%s)%s' % (dst_native_type
, value
)
382 src_one
= get_one(src_channel
)
383 dst_one
= get_one(dst_channel
)
385 if src_one
> dst_one
and src_norm
and dst_channel
.norm
:
386 # We can just bitshift
387 src_shift
= get_one_shift(src_channel
)
388 dst_shift
= get_one_shift(dst_channel
)
389 value
= '(%s >> %s)' % (value
, src_shift
- dst_shift
)
391 # We need to rescale using an intermediate type big enough to hold the multiplication of both
392 tmp_native_type
= intermediate_native_type(src_size
+ dst_channel
.size
, src_channel
.sign
and dst_channel
.sign
)
393 value
= '((%s)%s)' % (tmp_native_type
, value
)
394 value
= '(%s * 0x%x / 0x%x)' % (value
, dst_one
, src_one
)
395 value
= '(%s)%s' % (dst_native_type
, value
)
398 # Promote to either float or double
399 if src_type
!= FLOAT
:
400 if src_norm
or src_type
== FIXED
:
401 one
= get_one(src_channel
)
403 value
= '(%s * (1.0f/0x%x))' % (value
, one
)
404 if dst_channel
.size
<= 32:
405 value
= '(float)%s' % value
408 # bigger than single precision mantissa, use double
409 value
= '(%s * (1.0/0x%x))' % (value
, one
)
413 if src_size
<= 23 or dst_channel
.size
<= 32:
414 value
= '(float)%s' % value
417 # bigger than single precision mantissa, use double
418 value
= '(double)%s' % value
422 # Convert double or float to non-float
423 if dst_channel
.type != FLOAT
:
424 if dst_channel
.norm
or dst_channel
.type == FIXED
:
425 dst_one
= get_one(dst_channel
)
426 if dst_channel
.size
<= 23:
427 value
= 'util_iround(%s * 0x%x)' % (value
, dst_one
)
429 # bigger than single precision mantissa, use double
430 value
= '(%s * (double)0x%x)' % (value
, dst_one
)
431 value
= '(%s)%s' % (dst_native_type
, value
)
433 # Cast double to float when converting to either half or float
434 if dst_channel
.size
<= 32 and src_size
> 32:
435 value
= '(float)%s' % value
438 if dst_channel
.size
== 16:
439 value
= 'util_float_to_half_rtz(%s)' % value
440 elif dst_channel
.size
== 64 and src_size
< 64:
441 value
= '(double)%s' % value
446 def generate_unpack_kernel(format
, dst_channel
, dst_native_type
):
448 if not is_format_supported(format
):
451 assert format
.layout
== PLAIN
453 def unpack_from_bitmask(channels
, swizzles
):
454 depth
= format
.block_size()
455 print(' uint%u_t value = *(const uint%u_t *)src;' % (depth
, depth
))
457 # Declare the intermediate variables
458 for i
in range(format
.nr_channels()):
459 src_channel
= channels
[i
]
460 if src_channel
.type == UNSIGNED
:
461 print(' uint%u_t %s;' % (depth
, src_channel
.name
))
462 elif src_channel
.type == SIGNED
:
463 print(' int%u_t %s;' % (depth
, src_channel
.name
))
465 # Compute the intermediate unshifted values
466 for i
in range(format
.nr_channels()):
467 src_channel
= channels
[i
]
469 shift
= src_channel
.shift
470 if src_channel
.type == UNSIGNED
:
472 value
= '%s >> %u' % (value
, shift
)
473 if shift
+ src_channel
.size
< depth
:
474 value
= '(%s) & 0x%x' % (value
, (1 << src_channel
.size
) - 1)
475 elif src_channel
.type == SIGNED
:
476 if shift
+ src_channel
.size
< depth
:
478 lshift
= depth
- (shift
+ src_channel
.size
)
479 value
= '%s << %u' % (value
, lshift
)
481 value
= '(int%u_t)(%s) ' % (depth
, value
)
482 if src_channel
.size
< depth
:
484 rshift
= depth
- src_channel
.size
485 value
= '(%s) >> %u' % (value
, rshift
)
489 if value
is not None:
490 print(' %s = %s;' % (src_channel
.name
, value
))
492 # Convert, swizzle, and store final values
494 swizzle
= swizzles
[i
]
496 src_channel
= channels
[swizzle
]
497 src_colorspace
= format
.colorspace
498 if src_colorspace
== SRGB
and i
== 3:
499 # Alpha channel is linear
501 value
= src_channel
.name
502 value
= conversion_expr(src_channel
,
503 dst_channel
, dst_native_type
,
505 src_colorspace
= src_colorspace
)
506 elif swizzle
== SWIZZLE_0
:
508 elif swizzle
== SWIZZLE_1
:
509 value
= get_one(dst_channel
)
510 elif swizzle
== SWIZZLE_NONE
:
514 print(' dst[%u] = %s; /* %s */' % (i
, value
, 'rgba'[i
]))
516 def unpack_from_struct(channels
, swizzles
):
517 print(' struct util_format_%s pixel;' % format
.short_name())
518 print(' memcpy(&pixel, src, sizeof pixel);')
521 swizzle
= swizzles
[i
]
523 src_channel
= channels
[swizzle
]
524 src_colorspace
= format
.colorspace
525 if src_colorspace
== SRGB
and i
== 3:
526 # Alpha channel is linear
528 value
= 'pixel.%s' % src_channel
.name
529 value
= conversion_expr(src_channel
,
530 dst_channel
, dst_native_type
,
532 src_colorspace
= src_colorspace
)
533 elif swizzle
== SWIZZLE_0
:
535 elif swizzle
== SWIZZLE_1
:
536 value
= get_one(dst_channel
)
537 elif swizzle
== SWIZZLE_NONE
:
541 print(' dst[%u] = %s; /* %s */' % (i
, value
, 'rgba'[i
]))
543 if format
.is_bitmask():
544 print_channels(format
, unpack_from_bitmask
)
546 print_channels(format
, unpack_from_struct
)
549 def generate_pack_kernel(format
, src_channel
, src_native_type
):
551 if not is_format_supported(format
):
554 dst_native_type
= native_type(format
)
556 assert format
.layout
== PLAIN
558 def pack_into_bitmask(channels
, swizzles
):
559 inv_swizzle
= inv_swizzles(swizzles
)
561 depth
= format
.block_size()
562 print(' uint%u_t value = 0;' % depth
)
565 dst_channel
= channels
[i
]
566 shift
= dst_channel
.shift
567 if inv_swizzle
[i
] is not None:
568 value
='src[%u]' % inv_swizzle
[i
]
569 dst_colorspace
= format
.colorspace
570 if dst_colorspace
== SRGB
and inv_swizzle
[i
] == 3:
571 # Alpha channel is linear
573 value
= conversion_expr(src_channel
,
574 dst_channel
, dst_native_type
,
576 dst_colorspace
= dst_colorspace
)
577 if dst_channel
.type in (UNSIGNED
, SIGNED
):
578 if shift
+ dst_channel
.size
< depth
:
579 value
= '(%s) & 0x%x' % (value
, (1 << dst_channel
.size
) - 1)
581 value
= '(uint32_t)(%s) << %u' % (value
, shift
)
582 if dst_channel
.type == SIGNED
:
584 value
= '(uint%u_t)(%s) ' % (depth
, value
)
587 if value
is not None:
588 print(' value |= %s;' % (value
))
590 print(' *(uint%u_t *)dst = value;' % depth
)
592 def pack_into_struct(channels
, swizzles
):
593 inv_swizzle
= inv_swizzles(swizzles
)
595 print(' struct util_format_%s pixel = {0};' % format
.short_name())
598 dst_channel
= channels
[i
]
599 width
= dst_channel
.size
600 if inv_swizzle
[i
] is None:
602 dst_colorspace
= format
.colorspace
603 if dst_colorspace
== SRGB
and inv_swizzle
[i
] == 3:
604 # Alpha channel is linear
606 value
='src[%u]' % inv_swizzle
[i
]
607 value
= conversion_expr(src_channel
,
608 dst_channel
, dst_native_type
,
610 dst_colorspace
= dst_colorspace
)
611 print(' pixel.%s = %s;' % (dst_channel
.name
, value
))
613 print(' memcpy(dst, &pixel, sizeof pixel);')
615 if format
.is_bitmask():
616 print_channels(format
, pack_into_bitmask
)
618 print_channels(format
, pack_into_struct
)
621 def generate_format_unpack(format
, dst_channel
, dst_native_type
, dst_suffix
):
622 '''Generate the function to unpack pixels from a particular format'''
624 name
= format
.short_name()
626 if "8unorm" in dst_suffix
:
627 dst_proto_type
= dst_native_type
629 dst_proto_type
= 'void'
631 print('static inline void')
632 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_proto_type
))
635 if is_format_supported(format
):
636 print(' unsigned x, y;')
637 print(' for(y = 0; y < height; y += %u) {' % (format
.block_height
,))
638 print(' %s *dst = dst_row;' % (dst_native_type
))
639 print(' const uint8_t *src = src_row;')
640 print(' for(x = 0; x < width; x += %u) {' % (format
.block_width
,))
642 generate_unpack_kernel(format
, dst_channel
, dst_native_type
)
644 print(' src += %u;' % (format
.block_size() / 8,))
647 print(' src_row += src_stride;')
648 print(' dst_row = (uint8_t *)dst_row + dst_stride;')
655 def generate_format_pack(format
, src_channel
, src_native_type
, src_suffix
):
656 '''Generate the function to pack pixels to a particular format'''
658 name
= format
.short_name()
661 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
))
664 print('void 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
), file=sys
.stdout2
)
666 if is_format_supported(format
):
667 print(' unsigned x, y;')
668 print(' for(y = 0; y < height; y += %u) {' % (format
.block_height
,))
669 print(' const %s *src = src_row;' % (src_native_type
))
670 print(' uint8_t *dst = dst_row;')
671 print(' for(x = 0; x < width; x += %u) {' % (format
.block_width
,))
673 generate_pack_kernel(format
, src_channel
, src_native_type
)
676 print(' dst += %u;' % (format
.block_size() / 8,))
678 print(' dst_row += dst_stride;')
679 print(' src_row += src_stride/sizeof(*src_row);')
686 def generate_format_fetch(format
, dst_channel
, dst_native_type
):
687 '''Generate the function to unpack pixels from a particular format'''
689 name
= format
.short_name()
691 print('static inline void')
692 print('util_format_%s_fetch_rgba(void *in_dst, const uint8_t *src, UNUSED unsigned i, UNUSED unsigned j)' % (name
))
694 print(' %s *dst = in_dst;' % dst_native_type
)
696 if is_format_supported(format
):
697 generate_unpack_kernel(format
, dst_channel
, dst_native_type
)
703 def is_format_hand_written(format
):
704 return format
.layout
!= PLAIN
or format
.colorspace
== ZS
707 def generate(formats
):
709 print('#include "pipe/p_compiler.h"')
710 print('#include "util/u_math.h"')
711 print('#include "util/u_half.h"')
712 print('#include "u_format.h"')
713 print('#include "u_format_other.h"')
714 print('#include "util/format_srgb.h"')
715 print('#include "u_format_yuv.h"')
716 print('#include "u_format_zs.h"')
717 print('#include "u_format_pack.h"')
720 for format
in formats
:
721 if not is_format_hand_written(format
):
723 if is_format_supported(format
) and not format
.is_bitmask():
724 generate_format_type(format
)
726 if format
.is_pure_unsigned():
727 native_type
= 'unsigned'
729 channel
= Channel(UNSIGNED
, False, True, 32)
731 generate_format_unpack(format
, channel
, native_type
, suffix
)
732 generate_format_pack(format
, channel
, native_type
, suffix
)
733 generate_format_fetch(format
, channel
, native_type
)
735 channel
= Channel(SIGNED
, False, True, 32)
738 generate_format_pack(format
, channel
, native_type
, suffix
)
739 elif format
.is_pure_signed():
742 channel
= Channel(SIGNED
, False, True, 32)
744 generate_format_unpack(format
, channel
, native_type
, suffix
)
745 generate_format_pack(format
, channel
, native_type
, suffix
)
746 generate_format_fetch(format
, channel
, native_type
)
748 native_type
= 'unsigned'
750 channel
= Channel(UNSIGNED
, False, True, 32)
751 generate_format_pack(format
, channel
, native_type
, suffix
)
753 channel
= Channel(FLOAT
, False, False, 32)
754 native_type
= 'float'
755 suffix
= 'rgba_float'
757 generate_format_unpack(format
, channel
, native_type
, suffix
)
758 generate_format_pack(format
, channel
, native_type
, suffix
)
759 generate_format_fetch(format
, channel
, native_type
)
761 channel
= Channel(UNSIGNED
, True, False, 8)
762 native_type
= 'uint8_t'
763 suffix
= 'rgba_8unorm'
765 generate_format_unpack(format
, channel
, native_type
, suffix
)
766 generate_format_pack(format
, channel
, native_type
, suffix
)