4 * An object oriented GL/GLES Abstraction/Utility Layer
6 * Copyright (C) 2007,2008,2009,2010 Intel Corporation.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
28 #include "cogl-util.h"
29 #include "cogl-private.h"
33 * @a: Value to get the next power of two
35 * Calculates the next power of two greater than or equal to @a.
37 * Return value: @a if @a is already a power of two, otherwise returns
38 * the next nearest power of two.
41 _cogl_util_next_p2 (int a)
52 _cogl_util_one_at_a_time_mix (unsigned int hash)
54 hash += ( hash << 3 );
55 hash ^= ( hash >> 11 );
56 hash += ( hash << 15 );
61 /* The 'ffs' function is part of C99 so it isn't always available */
65 _cogl_util_ffs (int num)
72 while ((num & 1) == 0)
82 /* The 'ffsl' is non-standard but when building with GCC we'll use its
84 #ifndef COGL_UTIL_HAVE_BUILTIN_FFSL
87 _cogl_util_ffsl_wrapper (long int num)
94 while ((num & 1) == 0)
103 #endif /* COGL_UTIL_HAVE_BUILTIN_FFSL */
105 #ifndef COGL_UTIL_HAVE_BUILTIN_POPCOUNTL
108 _cogl_util_popcount_table[256] =
110 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4,
111 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
112 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4,
113 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
114 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6,
115 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
116 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5,
117 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
118 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6,
119 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
120 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
123 #endif /* COGL_UTIL_HAVE_BUILTIN_POPCOUNTL */
125 /* tests/conform/test-bitmask.c tests some cogl internals and includes this
126 * file directly but since these functions depend on other internal Cogl
127 * symbols we hide them from test-bitmask.c
129 * XXX: maybe there's a better way for us to handle internal testing
130 * to avoid needing hacks like this.
132 #ifndef _COGL_IN_TEST_BITMASK
134 /* Given a set of red, green and blue component masks, a depth and
135 * bits per pixel this function tries to determine a corresponding
138 * The depth is measured in bits not including padding for un-used
139 * alpha. The bits per pixel (bpp) does include padding for un-used
142 * This function firstly aims to match formats with RGB ordered
143 * components and only considers alpha coming first, in the most
144 * significant bits. If the function fails to match then it recurses
145 * by either switching the r and b masks around to check for BGR
146 * ordered formats or it recurses with the masks shifted to check for
147 * formats where the alpha component is the least significant bits.
149 static CoglPixelFormat
150 _cogl_util_pixel_format_from_masks_real (unsigned long r_mask,
151 unsigned long g_mask,
152 unsigned long b_mask,
155 gboolean check_afirst,
158 CoglPixelFormat image_format;
160 if (depth == 24 && bpp == 24 &&
161 r_mask == 0xff0000 && g_mask == 0xff00 && b_mask == 0xff)
163 return COGL_PIXEL_FORMAT_RGB_888;
165 else if ((depth == 24 || depth == 32) && bpp == 32 &&
166 r_mask == 0xff0000 && g_mask == 0xff00 && b_mask == 0xff)
168 return COGL_PIXEL_FORMAT_ARGB_8888_PRE;
170 else if ((depth == 30 || depth == 32) &&
171 r_mask == 0x3ff00000 && g_mask == 0xffc00 && b_mask == 0x3ff)
173 return COGL_PIXEL_FORMAT_ARGB_2101010_PRE;
175 else if (depth == 16 && bpp == 16 &&
176 r_mask == 0xf800 && g_mask == 0x7e0 && b_mask == 0x1f)
178 return COGL_PIXEL_FORMAT_RGB_565;
181 if (recursion_depth == 2)
184 /* Check for BGR ordering if we didn't find a match */
188 _cogl_util_pixel_format_from_masks_real (b_mask, g_mask, r_mask,
192 recursion_depth + 1);
194 return image_format ^ COGL_BGR_BIT;
197 /* Check for alpha in the least significant bits if we still
198 * haven't found a match... */
199 if (check_afirst && depth != bpp)
201 int shift = bpp - depth;
204 _cogl_util_pixel_format_from_masks_real (r_mask >> shift,
210 recursion_depth + 1);
212 return image_format ^ COGL_AFIRST_BIT;
219 _cogl_util_pixel_format_from_masks (unsigned long r_mask,
220 unsigned long g_mask,
221 unsigned long b_mask,
223 gboolean byte_order_is_lsb_first)
225 CoglPixelFormat image_format =
226 _cogl_util_pixel_format_from_masks_real (r_mask, g_mask, b_mask,
234 const char *byte_order[] = { "MSB first", "LSB first" };
235 g_warning ("Could not find a matching pixel format for red mask=0x%lx,"
236 "green mask=0x%lx, blue mask=0x%lx at depth=%d, bpp=%d "
237 "and byte order=%s\n", r_mask, g_mask, b_mask, depth, bpp,
238 byte_order[!!byte_order_is_lsb_first]);
242 /* If the image is in little-endian then the order in memory is
244 if (byte_order_is_lsb_first &&
245 _cogl_pixel_format_is_endian_dependant (image_format))
247 image_format ^= COGL_BGR_BIT;
248 if (image_format & COGL_A_BIT)
249 image_format ^= COGL_AFIRST_BIT;
255 #endif /* _COGL_IN_TEST_BITMASK */