mutter/cogl/cogl/cogl-util.c
Jonas Ådahl bf71cb2e3c Don't use config.h in clutter and cogl
In cogl use cogl-config.h and in clutter use clutter-build-config.h. We
can't use clutter-config.h in clutter because its already used and
installed.

https://bugzilla.gnome.org/show_bug.cgi?id=768976
2016-07-20 14:23:48 +08:00

287 lines
8.5 KiB
C

/*
* Cogl
*
* A Low Level GPU Graphics and Utilities API
*
* Copyright (C) 2007,2008,2009,2010 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
#ifdef HAVE_CONFIG_H
#include "cogl-config.h"
#endif
#include <string.h>
#include "cogl-util.h"
#include "cogl-private.h"
/*
* cogl_util_next_p2:
* @a: Value to get the next power of two
*
* Calculates the next power of two greater than or equal to @a.
*
* Return value: @a if @a is already a power of two, otherwise returns
* the next nearest power of two.
*/
int
_cogl_util_next_p2 (int a)
{
int rval = 1;
while (rval < a)
rval <<= 1;
return rval;
}
unsigned int
_cogl_util_one_at_a_time_mix (unsigned int hash)
{
hash += ( hash << 3 );
hash ^= ( hash >> 11 );
hash += ( hash << 15 );
return hash;
}
/* The 'ffs' function is part of C99 so it isn't always available */
#ifndef HAVE_FFS
int
_cogl_util_ffs (int num)
{
int i = 1;
if (num == 0)
return 0;
while ((num & 1) == 0)
{
num >>= 1;
i++;
}
return i;
}
#endif /* HAVE_FFS */
/* The 'ffsl' is non-standard but when building with GCC we'll use its
builtin instead */
#ifndef COGL_UTIL_HAVE_BUILTIN_FFSL
int
_cogl_util_ffsl_wrapper (long int num)
{
int i = 1;
if (num == 0)
return 0;
while ((num & 1) == 0)
{
num >>= 1;
i++;
}
return i;
}
#endif /* COGL_UTIL_HAVE_BUILTIN_FFSL */
#ifndef COGL_UTIL_HAVE_BUILTIN_POPCOUNTL
const unsigned char
_cogl_util_popcount_table[256] =
{
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4,
2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4,
2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6,
4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5,
3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6,
4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
};
#endif /* COGL_UTIL_HAVE_BUILTIN_POPCOUNTL */
/* tests/conform/test-bitmask.c tests some cogl internals and includes this
* file directly but since these functions depend on other internal Cogl
* symbols we hide them from test-bitmask.c
*
* XXX: maybe there's a better way for us to handle internal testing
* to avoid needing hacks like this.
*/
#ifndef _COGL_IN_TEST_BITMASK
/* Given a set of red, green and blue component masks, a depth and
* bits per pixel this function tries to determine a corresponding
* CoglPixelFormat.
*
* The depth is measured in bits not including padding for un-used
* alpha. The bits per pixel (bpp) does include padding for un-used
* alpha.
*
* This function firstly aims to match formats with RGB ordered
* components and only considers alpha coming first, in the most
* significant bits. If the function fails to match then it recurses
* by either switching the r and b masks around to check for BGR
* ordered formats or it recurses with the masks shifted to check for
* formats where the alpha component is the least significant bits.
*/
static CoglPixelFormat
_cogl_util_pixel_format_from_masks_real (unsigned long r_mask,
unsigned long g_mask,
unsigned long b_mask,
int depth, int bpp,
CoglBool check_bgr,
CoglBool check_afirst,
int recursion_depth)
{
CoglPixelFormat image_format;
if (depth == 24 && bpp == 24 &&
r_mask == 0xff0000 && g_mask == 0xff00 && b_mask == 0xff)
{
return COGL_PIXEL_FORMAT_RGB_888;
}
else if ((depth == 24 || depth == 32) && bpp == 32 &&
r_mask == 0xff0000 && g_mask == 0xff00 && b_mask == 0xff)
{
return COGL_PIXEL_FORMAT_ARGB_8888_PRE;
}
else if ((depth == 30 || depth == 32) &&
r_mask == 0x3ff00000 && g_mask == 0xffc00 && b_mask == 0x3ff)
{
return COGL_PIXEL_FORMAT_ARGB_2101010_PRE;
}
else if (depth == 16 && bpp == 16 &&
r_mask == 0xf800 && g_mask == 0x7e0 && b_mask == 0x1f)
{
return COGL_PIXEL_FORMAT_RGB_565;
}
if (recursion_depth == 2)
return 0;
/* Check for BGR ordering if we didn't find a match */
if (check_bgr)
{
image_format =
_cogl_util_pixel_format_from_masks_real (b_mask, g_mask, r_mask,
depth, bpp,
FALSE,
TRUE,
recursion_depth + 1);
if (image_format)
return image_format ^ COGL_BGR_BIT;
}
/* Check for alpha in the least significant bits if we still
* haven't found a match... */
if (check_afirst && depth != bpp)
{
int shift = bpp - depth;
image_format =
_cogl_util_pixel_format_from_masks_real (r_mask >> shift,
g_mask >> shift,
b_mask >> shift,
depth, bpp,
TRUE,
FALSE,
recursion_depth + 1);
if (image_format)
return image_format ^ COGL_AFIRST_BIT;
}
return 0;
}
CoglPixelFormat
_cogl_util_pixel_format_from_masks (unsigned long r_mask,
unsigned long g_mask,
unsigned long b_mask,
int depth, int bpp,
CoglBool byte_order_is_lsb_first)
{
CoglPixelFormat image_format =
_cogl_util_pixel_format_from_masks_real (r_mask, g_mask, b_mask,
depth, bpp,
TRUE,
TRUE,
0);
if (!image_format)
{
const char *byte_order[] = { "MSB first", "LSB first" };
g_warning ("Could not find a matching pixel format for red mask=0x%lx,"
"green mask=0x%lx, blue mask=0x%lx at depth=%d, bpp=%d "
"and byte order=%s\n", r_mask, g_mask, b_mask, depth, bpp,
byte_order[!!byte_order_is_lsb_first]);
return 0;
}
/* If the image is in little-endian then the order in memory is
reversed */
if (byte_order_is_lsb_first &&
_cogl_pixel_format_is_endian_dependant (image_format))
{
image_format ^= COGL_BGR_BIT;
if (image_format & COGL_A_BIT)
image_format ^= COGL_AFIRST_BIT;
}
return image_format;
}
#ifndef HAVE_MEMMEM
char *
_cogl_util_memmem (const void *haystack,
size_t haystack_len,
const void *needle,
size_t needle_len)
{
size_t i;
if (needle_len > haystack_len)
return NULL;
for (i = 0; i <= haystack_len - needle_len; i++)
if (!memcmp ((const char *) haystack + i, needle, needle_len))
return (char *) haystack + i;
return NULL;
}
#endif /* HAVE_MEMMEM */
#endif /* _COGL_IN_TEST_BITMASK */