u_format.h revision e4069d07ddd8c2afa5378e54710e19e7517d43d6
1/**************************************************************************
2 *
3 * Copyright 2009 Vmware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28
29#ifndef U_FORMAT_H
30#define U_FORMAT_H
31
32
33#include "pipe/p_format.h"
34
35#ifdef __cplusplus
36extern "C" {
37#endif
38
39
40/**
41 * Describe how to best pack/unpack pixels into/from the prescribed format.
42 *
43 * These are used for automatic code generation of pixel packing and unpacking
44 * routines (in compile time, e.g., u_format_access.py, or in runtime, like
45 * llvmpipe does).
46 *
47 * Thumb rule is: if you're not code generating pixel packing/unpacking then
48 * these are irrelevant for you.
49 *
50 * Note that this can be deduced from other values in util_format_description
51 * structure. This is by design, to make code generation of pixel
52 * packing/unpacking/sampling routines simple and efficient.
53 *
54 * XXX: This should be renamed to something like util_format_pack.
55 */
56enum util_format_layout {
57   /**
58    * Single scalar component.
59    */
60   UTIL_FORMAT_LAYOUT_SCALAR = 0,
61
62   /**
63    * One or more components of mixed integer formats, arithmetically encoded
64    * in a word up to 32bits.
65    */
66   UTIL_FORMAT_LAYOUT_ARITH = 1,
67
68   /**
69    * One or more components, no mixed formats, each with equal power of two
70    * number of bytes.
71    */
72   UTIL_FORMAT_LAYOUT_ARRAY = 2,
73
74   /**
75    * XXX: Not used yet. These might go away and be replaced by a single entry,
76    * for formats where multiple pixels have to be
77    * read in order to determine a single pixel value (i.e., block.width > 1
78    * || block.height > 1)
79    */
80   UTIL_FORMAT_LAYOUT_YUV = 3,
81   UTIL_FORMAT_LAYOUT_DXT = 4
82};
83
84
85struct util_format_block
86{
87   /** Block width in pixels */
88   unsigned width;
89
90   /** Block height in pixels */
91   unsigned height;
92
93   /** Block size in bits */
94   unsigned bits;
95};
96
97
98enum util_format_type {
99   UTIL_FORMAT_TYPE_VOID = 0,
100   UTIL_FORMAT_TYPE_UNSIGNED = 1,
101   UTIL_FORMAT_TYPE_SIGNED = 2,
102   UTIL_FORMAT_TYPE_FIXED = 3,
103   UTIL_FORMAT_TYPE_FLOAT = 4
104};
105
106
107enum util_format_swizzle {
108   UTIL_FORMAT_SWIZZLE_X = 0,
109   UTIL_FORMAT_SWIZZLE_Y = 1,
110   UTIL_FORMAT_SWIZZLE_Z = 2,
111   UTIL_FORMAT_SWIZZLE_W = 3,
112   UTIL_FORMAT_SWIZZLE_0 = 4,
113   UTIL_FORMAT_SWIZZLE_1 = 5,
114   UTIL_FORMAT_SWIZZLE_NONE = 6
115};
116
117
118enum util_format_colorspace {
119   UTIL_FORMAT_COLORSPACE_RGB = 0,
120   UTIL_FORMAT_COLORSPACE_SRGB = 1,
121   UTIL_FORMAT_COLORSPACE_YUV = 2,
122   UTIL_FORMAT_COLORSPACE_ZS = 3
123};
124
125
126struct util_format_channel_description
127{
128   unsigned type:6;
129   unsigned normalized:1;
130   unsigned size:9;
131};
132
133
134struct util_format_description
135{
136   enum pipe_format format;
137   const char *name;
138   struct util_format_block block;
139   enum util_format_layout layout;
140   struct util_format_channel_description channel[4];
141   unsigned char swizzle[4];
142   enum util_format_colorspace colorspace;
143};
144
145
146extern const struct util_format_description
147util_format_description_table[];
148
149
150const struct util_format_description *
151util_format_description(enum pipe_format format);
152
153
154/*
155 * Format query functions.
156 */
157
158static INLINE boolean
159util_format_is_compressed(enum pipe_format format)
160{
161   const struct util_format_description *desc = util_format_description(format);
162
163   assert(format);
164   if (!format) {
165      return FALSE;
166   }
167
168   return desc->layout == UTIL_FORMAT_LAYOUT_DXT ? TRUE : FALSE;
169}
170
171static INLINE boolean
172util_format_is_depth_or_stencil(enum pipe_format format)
173{
174   const struct util_format_description *desc = util_format_description(format);
175
176   assert(format);
177   if (!format) {
178      return FALSE;
179   }
180
181   return desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS ? TRUE : FALSE;
182}
183
184static INLINE boolean
185util_format_is_depth_and_stencil(enum pipe_format format)
186{
187   const struct util_format_description *desc = util_format_description(format);
188
189   assert(format);
190   if (!format) {
191      return FALSE;
192   }
193
194   if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS) {
195      return FALSE;
196   }
197
198   return (desc->swizzle[0] != UTIL_FORMAT_SWIZZLE_NONE &&
199           desc->swizzle[1] != UTIL_FORMAT_SWIZZLE_NONE) ? TRUE : FALSE;
200}
201
202
203/**
204 * Return total bits needed for the pixel format per block.
205 */
206static INLINE uint
207util_format_get_blocksizebits(enum pipe_format format)
208{
209   const struct util_format_description *desc = util_format_description(format);
210
211   assert(format);
212   if (!format) {
213      return 0;
214   }
215
216   return desc->block.bits;
217}
218
219/**
220 * Return bytes per block (not pixel) for the given format.
221 */
222static INLINE uint
223util_format_get_blocksize(enum pipe_format format)
224{
225   uint bits = util_format_get_blocksizebits(format);
226
227   assert(bits % 8 == 0);
228
229   return bits / 8;
230}
231
232static INLINE uint
233util_format_get_blockwidth(enum pipe_format format)
234{
235   const struct util_format_description *desc = util_format_description(format);
236
237   assert(format);
238   if (!format) {
239      return 1;
240   }
241
242   switch (desc->layout) {
243   case UTIL_FORMAT_LAYOUT_YUV:
244      return 2;
245   case UTIL_FORMAT_LAYOUT_DXT:
246      return 4;
247   default:
248      return 1;
249   }
250}
251
252static INLINE uint
253util_format_get_blockheight(enum pipe_format format)
254{
255   const struct util_format_description *desc = util_format_description(format);
256
257   assert(format);
258   if (!format) {
259      return 1;
260   }
261
262   switch (desc->layout) {
263   case UTIL_FORMAT_LAYOUT_DXT:
264      return 4;
265   default:
266      return 1;
267   }
268}
269
270static INLINE unsigned
271util_format_get_nblocksx(enum pipe_format format,
272                         unsigned x)
273{
274   unsigned blockwidth = util_format_get_blockwidth(format);
275   return (x + blockwidth - 1) / blockwidth;
276}
277
278static INLINE unsigned
279util_format_get_nblocksy(enum pipe_format format,
280                         unsigned y)
281{
282   unsigned blockheight = util_format_get_blockheight(format);
283   return (y + blockheight - 1) / blockheight;
284}
285
286static INLINE unsigned
287util_format_get_nblocks(enum pipe_format format,
288                        unsigned width,
289                        unsigned height)
290{
291   return util_format_get_nblocksx(format, width) * util_format_get_nblocksy(format, height);
292}
293
294static INLINE size_t
295util_format_get_stride(enum pipe_format format,
296                       unsigned width)
297{
298   return util_format_get_nblocksx(format, width) * util_format_get_blocksize(format);
299}
300
301static INLINE size_t
302util_format_get_2d_size(enum pipe_format format,
303                        size_t stride,
304                        unsigned height)
305{
306   return util_format_get_nblocksy(format, height) * stride;
307}
308
309static INLINE uint
310util_format_get_component_bits(enum pipe_format format,
311                               enum util_format_colorspace colorspace,
312                               uint component)
313{
314   const struct util_format_description *desc = util_format_description(format);
315   enum util_format_colorspace desc_colorspace;
316
317   assert(format);
318   if (!format) {
319      return 0;
320   }
321
322   assert(component < 4);
323
324   /* Treat RGB and SRGB as equivalent. */
325   if (colorspace == UTIL_FORMAT_COLORSPACE_SRGB) {
326      colorspace = UTIL_FORMAT_COLORSPACE_RGB;
327   }
328   if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) {
329      desc_colorspace = UTIL_FORMAT_COLORSPACE_RGB;
330   } else {
331      desc_colorspace = desc->colorspace;
332   }
333
334   if (desc_colorspace != colorspace) {
335      return 0;
336   }
337
338   switch (desc->swizzle[component]) {
339   case UTIL_FORMAT_SWIZZLE_X:
340      return desc->channel[0].size;
341   case UTIL_FORMAT_SWIZZLE_Y:
342      return desc->channel[1].size;
343   case UTIL_FORMAT_SWIZZLE_Z:
344      return desc->channel[2].size;
345   case UTIL_FORMAT_SWIZZLE_W:
346      return desc->channel[3].size;
347   default:
348      return 0;
349   }
350}
351
352static INLINE boolean
353util_format_has_alpha(enum pipe_format format)
354{
355   const struct util_format_description *desc = util_format_description(format);
356
357   assert(format);
358   if (!format) {
359      return FALSE;
360   }
361
362   switch (desc->layout) {
363   case UTIL_FORMAT_LAYOUT_SCALAR:
364   case UTIL_FORMAT_LAYOUT_ARITH:
365   case UTIL_FORMAT_LAYOUT_ARRAY:
366      /* FIXME: pf_get_component_bits( PIPE_FORMAT_A8L8_UNORM, PIPE_FORMAT_COMP_A ) should not return 0 right? */
367      if (format == PIPE_FORMAT_A8_UNORM ||
368          format == PIPE_FORMAT_A8L8_UNORM ||
369          format == PIPE_FORMAT_A8L8_SRGB) {
370         return TRUE;
371      }
372      return util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 3) != 0;
373   case UTIL_FORMAT_LAYOUT_YUV:
374      return FALSE;
375   case UTIL_FORMAT_LAYOUT_DXT:
376      switch (format) {
377      case PIPE_FORMAT_DXT1_RGBA:
378      case PIPE_FORMAT_DXT3_RGBA:
379      case PIPE_FORMAT_DXT5_RGBA:
380      case PIPE_FORMAT_DXT1_SRGBA:
381      case PIPE_FORMAT_DXT3_SRGBA:
382      case PIPE_FORMAT_DXT5_SRGBA:
383         return TRUE;
384      default:
385         return FALSE;
386      }
387   default:
388      assert(0);
389      return FALSE;
390   }
391}
392
393
394/*
395 * Format access functions.
396 */
397
398void
399util_format_read_4f(enum pipe_format format,
400                    float *dst, unsigned dst_stride,
401                    const void *src, unsigned src_stride,
402                    unsigned x, unsigned y, unsigned w, unsigned h);
403
404void
405util_format_write_4f(enum pipe_format format,
406                     const float *src, unsigned src_stride,
407                     void *dst, unsigned dst_stride,
408                     unsigned x, unsigned y, unsigned w, unsigned h);
409
410void
411util_format_read_4ub(enum pipe_format format,
412                     uint8_t *dst, unsigned dst_stride,
413                     const void *src, unsigned src_stride,
414                     unsigned x, unsigned y, unsigned w, unsigned h);
415
416void
417util_format_write_4ub(enum pipe_format format,
418                      const uint8_t *src, unsigned src_stride,
419                      void *dst, unsigned dst_stride,
420                      unsigned x, unsigned y, unsigned w, unsigned h);
421
422#ifdef __cplusplus
423} // extern "C" {
424#endif
425
426#endif /* ! U_FORMAT_H */
427