4 /**************************************************************************
6 * Copyright 2009 VMware, Inc.
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:
17 * The above copyright notice and this permission notice (including the
18 * next paragraph) shall be included in all copies or substantial portions
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.
29 **************************************************************************/
33 * Pixel format accessor functions.
35 * @author Jose Fonseca <jfonseca@vmware.com>
42 from u_format_parse
import *
45 def short_name(format
):
46 '''Make up a short norm for a format, suitable to be used as suffix in
50 if name
.startswith('PIPE_FORMAT_'):
51 name
= name
[len('PIPE_FORMAT_'):]
56 def is_format_supported(format
):
57 '''Determines whether we actually have the plumbing necessary to generate the
58 to read/write to/from this format.'''
60 # FIXME: Ideally we would support any format combination here.
62 # XXX: It should be straightforward to support srgb
63 if format
.colorspace
not in ('rgb', 'zs'):
66 if format
.layout
not in (ARITH
, ARRAY
):
70 type = format
.in_types
[i
]
71 if type.kind
not in (VOID
, UNSIGNED
, FLOAT
):
74 # We can only read a color from a depth/stencil format if the depth channel is present
75 if format
.colorspace
== 'zs' and format
.out_swizzle
[0] == SWIZZLE_NONE
:
81 def native_type(format
):
82 '''Get the native appropriate for a format.'''
84 if format
.layout
== ARITH
:
85 # For arithmetic pixel formats return the integer type that matches the whole pixel
86 return 'uint%u_t' % format
.block_size()
87 elif format
.layout
== ARRAY
:
88 # For array pixel formats return the integer type that matches the color channel
89 type = format
.in_types
[0]
90 if type.kind
== UNSIGNED
:
91 return 'uint%u_t' % type.size
92 elif type.kind
== SIGNED
:
93 return 'int%u_t' % type.size
94 elif type.kind
== FLOAT
:
107 def intermediate_native_type(bits
, sign
):
108 '''Find a native type adequate to hold intermediate results of the request bit size.'''
110 bytes
= 4 # don't use anything smaller than 32bits
111 while bytes
* 8 < bits
:
116 return 'int%u_t' % bits
118 return 'uint%u_t' % bits
121 def get_one_shift(type):
122 '''Get the number of the bit that matches unity for this type.'''
123 if type.kind
== 'FLOAT':
127 if type.kind
== UNSIGNED
:
129 if type.kind
== SIGNED
:
131 if type.kind
== FIXED
:
137 '''Get the value of unity for this type.'''
138 if type.kind
== 'FLOAT' or not type.norm
:
141 return (1 << get_one_shift(type)) - 1
144 def generate_clamp():
145 '''Code generate the clamping functions for each type.
147 We don't use a macro so that arguments with side effects,
148 like *src_pixel++ are correctly handled.
151 for suffix
, native_type
in [
154 ('ui', 'unsigned int'),
157 print 'static INLINE %s' % native_type
158 print 'clamp%s(%s value, %s lbound, %s ubound)' % (suffix
, native_type
, native_type
, native_type
)
160 print ' if(value < lbound)'
161 print ' return lbound;'
162 print ' if(value > ubound)'
163 print ' return ubound;'
164 print ' return value;'
169 def clamp_expr(src_type
, dst_type
, dst_native_type
, value
):
170 '''Generate the expression to clamp the value in the source type to the
171 destination type range.'''
173 if src_type
== dst_type
:
176 # Pick the approriate clamp function
177 if src_type
.kind
== FLOAT
:
178 if src_type
.size
== 32:
180 elif src_type
.size
== 64:
184 elif src_type
.kind
== UNSIGNED
:
186 elif src_type
.kind
== SIGNED
:
191 # Clamp floats to [-1, 1] or [0, 1] range
192 if src_type
.kind
== FLOAT
and dst_type
.norm
:
194 if src_type
.sign
and dst_type
.sign
:
198 return '%s(%s, %s, %s)' % (func
, value
, min, max)
200 # FIXME: Also clamp scaled values
205 def conversion_expr(src_type
, dst_type
, dst_native_type
, value
):
206 '''Generate the expression to convert a value between two types.'''
208 if src_type
== dst_type
:
211 if src_type
.kind
== FLOAT
and dst_type
.kind
== FLOAT
:
212 return '(%s)%s' % (dst_native_type
, value
)
214 if not src_type
.norm
and not dst_type
.norm
:
215 return '(%s)%s' % (dst_native_type
, value
)
217 value
= clamp_expr(src_type
, dst_type
, dst_native_type
, value
)
219 if dst_type
.kind
== FLOAT
:
221 one
= get_one(src_type
)
222 if src_type
.size
<= 23:
223 scale
= '(1.0f/0x%x)' % one
225 # bigger than single precision mantissa, use double
226 scale
= '(1.0/0x%x)' % one
227 value
= '(%s * %s)' % (value
, scale
)
228 return '(%s)%s' % (dst_native_type
, value
)
230 if src_type
.kind
== FLOAT
:
232 dst_one
= get_one(dst_type
)
233 if dst_type
.size
<= 23:
234 scale
= '0x%x' % dst_one
236 # bigger than single precision mantissa, use double
237 scale
= '(double)0x%x' % dst_one
238 value
= '(%s * %s)' % (value
, scale
)
239 return '(%s)%s' % (dst_native_type
, value
)
241 if src_type
.kind
== dst_type
.kind
:
242 src_one
= get_one(src_type
)
243 dst_one
= get_one(dst_type
)
245 if src_one
> dst_one
and src_type
.norm
and dst_type
.norm
:
246 # We can just bitshift
247 src_shift
= get_one_shift(src_type
)
248 dst_shift
= get_one_shift(dst_type
)
249 value
= '(%s >> %s)' % (value
, src_shift
- dst_shift
)
251 # We need to rescale using an intermediate type big enough to hold the multiplication of both
252 tmp_native_type
= intermediate_native_type(src_type
.size
+ dst_type
.size
, src_type
.sign
and dst_type
.sign
)
253 value
= '(%s)%s' % (tmp_native_type
, value
)
254 value
= '%s * 0x%x / 0x%x' % (value
, dst_one
, src_one
)
255 value
= '(%s)%s' % (dst_native_type
, value
)
261 def generate_format_read(format
, dst_type
, dst_native_type
, dst_suffix
):
262 '''Generate the function to read pixels from a particular format'''
264 name
= short_name(format
)
266 src_native_type
= native_type(format
)
269 print 'util_format_%s_read_%s(%s *dst, unsigned dst_stride, const uint8_t *src, unsigned src_stride, unsigned x0, unsigned y0, unsigned w, unsigned h)' % (name
, dst_suffix
, dst_native_type
)
271 print ' unsigned x, y;'
272 print ' const uint8_t *src_row = src + y0*src_stride;'
273 print ' %s *dst_row = dst;' % dst_native_type
274 print ' for (y = 0; y < h; ++y) {'
275 print ' const %s *src_pixel = (const %s *)(src_row + x0*%u);' % (src_native_type
, src_native_type
, format
.stride())
276 print ' %s *dst_pixel = dst_row;' %dst
_native
_type
277 print ' for (x = 0; x < w; ++x) {'
280 if format
.colorspace
== 'rgb':
282 swizzle
= format
.out_swizzle
[i
]
284 names
[swizzle
] += 'rgba'[i
]
285 elif format
.colorspace
== 'zs':
286 swizzle
= format
.out_swizzle
[0]
294 if format
.layout
== ARITH
:
295 print ' %s pixel = *src_pixel++;' % src_native_type
298 src_type
= format
.in_types
[i
]
299 width
= src_type
.size
302 mask
= (1 << width
) - 1
304 value
= '(%s >> %u)' % (value
, shift
)
305 if shift
+ width
< format
.block_size():
306 value
= '(%s & 0x%x)' % (value
, mask
)
307 value
= conversion_expr(src_type
, dst_type
, dst_native_type
, value
)
308 print ' %s %s = %s;' % (dst_native_type
, names
[i
], value
)
310 elif format
.layout
== ARRAY
:
312 src_type
= format
.in_types
[i
]
314 value
= '(*src_pixel++)'
315 value
= conversion_expr(src_type
, dst_type
, dst_native_type
, value
)
316 print ' %s %s = %s;' % (dst_native_type
, names
[i
], value
)
321 if format
.colorspace
== 'rgb':
322 swizzle
= format
.out_swizzle
[i
]
324 value
= names
[swizzle
]
325 elif swizzle
== SWIZZLE_0
:
327 elif swizzle
== SWIZZLE_1
:
328 value
= get_one(dst_type
)
331 elif format
.colorspace
== 'zs':
335 value
= get_one(dst_type
)
338 print ' *dst_pixel++ = %s; /* %s */' % (value
, 'rgba'[i
])
341 print ' src_row += src_stride;'
342 print ' dst_row += dst_stride/sizeof(%s);' % dst_native_type
348 def generate_format_write(format
, src_type
, src_native_type
, src_suffix
):
349 '''Generate the function to write pixels to a particular format'''
351 name
= short_name(format
)
353 dst_native_type
= native_type(format
)
356 print 'util_format_%s_write_%s(const %s *src, unsigned src_stride, uint8_t *dst, unsigned dst_stride, unsigned x0, unsigned y0, unsigned w, unsigned h)' % (name
, src_suffix
, src_native_type
)
358 print ' unsigned x, y;'
359 print ' uint8_t *dst_row = dst + y0*dst_stride;'
360 print ' const %s *src_row = src;' % src_native_type
361 print ' for (y = 0; y < h; ++y) {'
362 print ' %s *dst_pixel = (%s *)(dst_row + x0*%u);' % (dst_native_type
, dst_native_type
, format
.stride())
363 print ' const %s *src_pixel = src_row;' %src_native
_type
364 print ' for (x = 0; x < w; ++x) {'
366 inv_swizzle
= [None]*4
367 if format
.colorspace
== 'rgb':
369 swizzle
= format
.out_swizzle
[i
]
371 inv_swizzle
[swizzle
] = i
372 elif format
.colorspace
== 'zs':
373 swizzle
= format
.out_swizzle
[0]
375 inv_swizzle
[swizzle
] = 0
379 if format
.layout
== ARITH
:
380 print ' %s pixel = 0;' % dst_native_type
383 dst_type
= format
.in_types
[i
]
384 width
= dst_type
.size
385 if inv_swizzle
[i
] is not None:
386 value
= 'src_pixel[%u]' % inv_swizzle
[i
]
387 value
= conversion_expr(src_type
, dst_type
, dst_native_type
, value
)
389 value
= '(%s << %u)' % (value
, shift
)
390 print ' pixel |= %s;' % value
392 print ' *dst_pixel++ = pixel;'
393 elif format
.layout
== ARRAY
:
395 dst_type
= format
.in_types
[i
]
396 if inv_swizzle
[i
] is not None:
397 value
= 'src_pixel[%u]' % inv_swizzle
[i
]
398 value
= conversion_expr(src_type
, dst_type
, dst_native_type
, value
)
399 print ' *dst_pixel++ = %s;' % value
402 print ' src_pixel += 4;'
405 print ' dst_row += dst_stride;'
406 print ' src_row += src_stride/sizeof(%s);' % src_native_type
412 def generate_read(formats
, dst_type
, dst_native_type
, dst_suffix
):
413 '''Generate the dispatch function to read pixels from any format'''
415 for format
in formats
:
416 if is_format_supported(format
):
417 generate_format_read(format
, dst_type
, dst_native_type
, dst_suffix
)
420 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
)
422 print ' void (*func)(%s *dst, unsigned dst_stride, const uint8_t *src, unsigned src_stride, unsigned x0, unsigned y0, unsigned w, unsigned h);' % dst_native_type
423 print ' switch(format) {'
424 for format
in formats
:
425 if is_format_supported(format
):
426 print ' case %s:' % format
.name
427 print ' func = &util_format_%s_read_%s;' % (short_name(format
), dst_suffix
)
430 print ' debug_printf("unsupported format\\n");'
433 print ' func(dst, dst_stride, (const uint8_t *)src, src_stride, x, y, w, h);'
438 def generate_write(formats
, src_type
, src_native_type
, src_suffix
):
439 '''Generate the dispatch function to write pixels to any format'''
441 for format
in formats
:
442 if is_format_supported(format
):
443 generate_format_write(format
, src_type
, src_native_type
, src_suffix
)
446 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
)
449 print ' void (*func)(const %s *src, unsigned src_stride, uint8_t *dst, unsigned dst_stride, unsigned x0, unsigned y0, unsigned w, unsigned h);' % src_native_type
450 print ' switch(format) {'
451 for format
in formats
:
452 if is_format_supported(format
):
453 print ' case %s:' % format
.name
454 print ' func = &util_format_%s_write_%s;' % (short_name(format
), src_suffix
)
457 print ' debug_printf("unsupported format\\n");'
460 print ' func(src, src_stride, (uint8_t *)dst, dst_stride, x, y, w, h);'
467 for arg
in sys
.argv
[1:]:
468 formats
.extend(parse(arg
))
470 print '/* This file is autogenerated by u_format_access.py from u_format.csv. Do not edit directly. */'
472 # This will print the copyright message on the top of this file
473 print __doc__
.strip()
475 print '#include "pipe/p_compiler.h"'
476 print '#include "u_format.h"'
477 print '#include "u_math.h"'
482 type = Type(FLOAT
, False, 32)
483 native_type
= 'float'
486 generate_read(formats
, type, native_type
, suffix
)
487 generate_write(formats
, type, native_type
, suffix
)
489 type = Type(UNSIGNED
, True, 8)
490 native_type
= 'uint8_t'
493 generate_read(formats
, type, native_type
, suffix
)
494 generate_write(formats
, type, native_type
, suffix
)
497 if __name__
== '__main__':