summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Bragg <robert@linux.intel.com>2012-02-17 20:44:28 +0000
committerRobert Bragg <robert@linux.intel.com>2012-02-17 23:48:51 +0000
commit1c78c8d1ecc996de365fb9f4fdfaf007ec7d5fe4 (patch)
tree5854ac5f8d613cf918f3f404753f8ec6872cfce8
parent7cfef1f3cacdd44012f4678c410e2647d6dea80a (diff)
downloadcogl-1c78c8d1ecc996de365fb9f4fdfaf007ec7d5fe4.tar.gz
Adds a _cogl_util_pixel_format_from_masks API
This adds a utility function for inferring a CoglPixelFormat from a set of channel masks, a bits-per-pixel value, a pixel-depth value and pixel byte order. This plan is to use this to improve how we map X visuals to Cogl pixel formats. This patch was based on some ideas from Damien Leone <dleone@nvidia.com> https://bugzilla.gnome.org/show_bug.cgi?id=660188
-rw-r--r--cogl/cogl-util.c128
-rw-r--r--cogl/cogl-util.h15
-rw-r--r--tests/conform/test-bitmask.c1
3 files changed, 144 insertions, 0 deletions
diff --git a/cogl/cogl-util.c b/cogl/cogl-util.c
index 487a762c..ba84d94d 100644
--- a/cogl/cogl-util.c
+++ b/cogl/cogl-util.c
@@ -26,6 +26,7 @@
#endif
#include "cogl-util.h"
+#include "cogl-private.h"
/*
* cogl_util_next_p2:
@@ -120,3 +121,130 @@ _cogl_util_popcount_table[256] =
};
#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,
+ gboolean check_bgr,
+ gboolean 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 == 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,
+ gboolean 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;
+}
+
+#endif /* _COGL_IN_TEST_BITMASK */
diff --git a/cogl/cogl-util.h b/cogl/cogl-util.h
index 04e59d02..dfaa6a9a 100644
--- a/cogl/cogl-util.h
+++ b/cogl/cogl-util.h
@@ -27,6 +27,7 @@
#include <glib.h>
#include <math.h>
#include "cogl-defines.h"
+#include "cogl-types.h"
#ifndef COGL_HAS_GLIB_SUPPORT
#include <stdio.h>
@@ -190,4 +191,18 @@ _cogl_util_popcountl (unsigned long num)
} while(0)
#endif /* COGL_HAS_GLIB_SUPPORT */
+/* Match a CoglPixelFormat according to channel masks, color depth,
+ * bits per pixel and byte order. These information are provided by
+ * the Visual and XImage structures.
+ *
+ * If no specific pixel format could be found, COGL_PIXEL_FORMAT_ANY
+ * is returned.
+ */
+CoglPixelFormat
+_cogl_util_pixel_format_from_masks (unsigned long r_mask,
+ unsigned long g_mask,
+ unsigned long b_mask,
+ int depth, int bpp,
+ int byte_order);
+
#endif /* __COGL_UTIL_H */
diff --git a/tests/conform/test-bitmask.c b/tests/conform/test-bitmask.c
index 36369011..84d7027d 100644
--- a/tests/conform/test-bitmask.c
+++ b/tests/conform/test-bitmask.c
@@ -11,6 +11,7 @@
#include <cogl/cogl-bitmask.h>
#include <cogl/cogl-bitmask.c>
+#define _COGL_IN_TEST_BITMASK
#include <cogl/cogl-util.c>
typedef struct