summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cogl/Makefile.am2
-rw-r--r--cogl/cogl-context-private.h5
-rw-r--r--cogl/cogl-context.c3
-rw-r--r--cogl/cogl-gpu-info-private.h74
-rw-r--r--cogl/cogl-gpu-info.c254
-rw-r--r--cogl/cogl-util.h21
6 files changed, 359 insertions, 0 deletions
diff --git a/cogl/Makefile.am b/cogl/Makefile.am
index f6dbb0d6..a29155cc 100644
--- a/cogl/Makefile.am
+++ b/cogl/Makefile.am
@@ -180,6 +180,8 @@ cogl_sources_c = \
$(srcdir)/cogl-private.h \
$(srcdir)/cogl-debug.h \
$(srcdir)/cogl-debug-options.h \
+ $(srcdir)/cogl-gpu-info.c \
+ $(srcdir)/cogl-gpu-info-private.h \
$(srcdir)/cogl-handle.h \
$(srcdir)/cogl-context-private.h \
$(srcdir)/cogl-context.c \
diff --git a/cogl/cogl-context-private.h b/cogl/cogl-context-private.h
index 6d92faf3..347c2119 100644
--- a/cogl/cogl-context-private.h
+++ b/cogl/cogl-context-private.h
@@ -46,6 +46,7 @@
#include "cogl-texture-2d.h"
#include "cogl-texture-3d.h"
#include "cogl-texture-rectangle.h"
+#include "cogl-gpu-info-private.h"
typedef struct
{
@@ -62,6 +63,10 @@ struct _CoglContext
CoglDriver driver;
+ /* Information about the GPU and driver which we can use to
+ determine certain workarounds */
+ CoglGpuInfo gpu;
+
/* vtable for the texture driver functions */
const CoglTextureDriver *texture_driver;
diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c
index c68ff41b..09da40a4 100644
--- a/cogl/cogl-context.c
+++ b/cogl/cogl-context.c
@@ -47,6 +47,7 @@
#include "cogl2-path.h"
#include "cogl-attribute-private.h"
#include "cogl1-context.h"
+#include "cogl-gpu-info-private.h"
#include <string.h>
@@ -239,6 +240,8 @@ cogl_context_new (CoglDisplay *display,
g_assert_not_reached ();
}
+ _cogl_gpu_info_init (context, &context->gpu);
+
context->attribute_name_states_hash =
g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
context->attribute_name_index_map = NULL;
diff --git a/cogl/cogl-gpu-info-private.h b/cogl/cogl-gpu-info-private.h
new file mode 100644
index 00000000..2930d6bd
--- /dev/null
+++ b/cogl/cogl-gpu-info-private.h
@@ -0,0 +1,74 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ */
+
+#ifndef __COGL_GPU_INFO_PRIVATE_H
+#define __COGL_GPU_INFO_PRIVATE_H
+
+#include "cogl-context.h"
+
+typedef enum
+{
+ COGL_GPU_INFO_VENDOR_UNKNOWN,
+ COGL_GPU_INFO_VENDOR_INTEL
+} CoglGpuInfoVendor;
+
+typedef enum
+{
+ COGL_GPU_INFO_DRIVER_PACKAGE_UNKNOWN,
+ COGL_GPU_INFO_DRIVER_PACKAGE_MESA
+} CoglGpuInfoDriverPackage;
+
+typedef enum
+{
+ COGL_GPU_INFO_DRIVER_STUB
+} CoglGpuInfoDriverBug;
+
+typedef struct _CoglGpuInfoVersion CoglGpuInfoVersion;
+
+typedef struct _CoglGpuInfo CoglGpuInfo;
+
+struct _CoglGpuInfo
+{
+ CoglGpuInfoVendor vendor;
+ const char *vendor_name;
+
+ CoglGpuInfoDriverPackage driver_package;
+ const char *driver_package_name;
+ int driver_package_version;
+
+ CoglGpuInfoDriverBug driver_bugs;
+};
+
+/*
+ * _cogl_gpu_info_init:
+ * @ctx: A #CoglContext
+ * @gpu: A return location for the GPU information
+ *
+ * Determines information about the GPU and driver from the given
+ * context.
+ */
+void
+_cogl_gpu_info_init (CoglContext *ctx,
+ CoglGpuInfo *gpu);
+
+#endif /* __COGL_GPU_INFO_PRIVATE_H */
diff --git a/cogl/cogl-gpu-info.c b/cogl/cogl-gpu-info.c
new file mode 100644
index 00000000..f62bbc33
--- /dev/null
+++ b/cogl/cogl-gpu-info.c
@@ -0,0 +1,254 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <errno.h>
+
+#include "cogl-gpu-info-private.h"
+#include "cogl-context-private.h"
+#include "cogl-util.h"
+
+typedef struct
+{
+ const char *renderer_string;
+ const char *version_string;
+ const char *vendor_string;
+} CoglGpuInfoStrings;
+
+typedef struct
+{
+ CoglGpuInfoVendor vendor;
+ const char *name;
+ gboolean (* check_function) (const CoglGpuInfoStrings *strings);
+} CoglGpuInfoVendorDescription;
+
+typedef struct
+{
+ CoglGpuInfoDriverPackage driver_package;
+ const char *name;
+ gboolean (* check_function) (const CoglGpuInfoStrings *strings,
+ int *version_out);
+} CoglGpuInfoDriverPackageDescription;
+
+static gboolean
+_cogl_gpu_info_parse_version_string (const char *version_string,
+ int n_components,
+ const char **tail,
+ int *version_ret)
+{
+ int version = 0;
+ guint64 part;
+ int i;
+
+ for (i = 0; ; i++)
+ {
+ errno = 0;
+ part = g_ascii_strtoull (version_string,
+ (char **) &version_string,
+ 10);
+
+ if (errno || part > COGL_VERSION_MAX_COMPONENT_VALUE)
+ return FALSE;
+
+ version |= part << ((2 - i) * COGL_VERSION_COMPONENT_BITS);
+
+ if (i + 1 >= n_components)
+ break;
+
+ if (*version_string != '.')
+ return FALSE;
+
+ version_string++;
+ }
+
+ if (version_ret)
+ *version_ret = version;
+ if (tail)
+ *tail = version_string;
+
+ return TRUE;
+}
+
+static gboolean
+check_intel_vendor (const CoglGpuInfoStrings *strings)
+{
+ const char *intel_part = strstr (strings->renderer_string, "Intel(R)");
+
+ if (intel_part == NULL)
+ return FALSE;
+
+ /* The match must either be at the beginning of the string or
+ preceded by a space. Just in case there's a company called
+ IAmNotIntel (R) or something */
+ if (intel_part > strings->renderer_string && intel_part[-1] != ' ')
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+check_unknown_vendor (const CoglGpuInfoStrings *strings)
+{
+ /* This is a last resort so it always matches */
+ return TRUE;
+}
+
+static const CoglGpuInfoVendorDescription
+_cogl_gpu_info_vendors[] =
+ {
+ {
+ COGL_GPU_INFO_VENDOR_INTEL,
+ "Intel",
+ check_intel_vendor
+ },
+ /* Must be last */
+ {
+ COGL_GPU_INFO_VENDOR_UNKNOWN,
+ "Unknown",
+ check_unknown_vendor
+ }
+ };
+
+static gboolean
+check_mesa_driver_package (const CoglGpuInfoStrings *strings,
+ int *version_ret)
+{
+ guint64 micro_part;
+ const char *v;
+
+ /* The version string should always begin a two-part GL version
+ number */
+ if (!_cogl_gpu_info_parse_version_string (strings->version_string,
+ 2, /* n_components */
+ &v, /* tail */
+ NULL /* version_ret */))
+ return FALSE;
+
+ /* In mesa this will be followed by a space and the name "Mesa" */
+ if (!g_str_has_prefix (v, " Mesa "))
+ return FALSE;
+
+ v += 6;
+
+ /* Next there will be a version string that is at least two
+ components. On a git devel build the version will be something
+ like "-devel<git hash>" instead */
+ if (!_cogl_gpu_info_parse_version_string (v,
+ 2, /* n_components */
+ &v, /* tail */
+ version_ret))
+ return FALSE;
+
+ /* If it is a development build then we'll just leave the micro
+ number as 0 */
+ if (g_str_has_prefix (v, "-devel"))
+ return TRUE;
+
+ /* Otherwise there should be a micro version number */
+ if (*v != '.')
+ return FALSE;
+
+ errno = 0;
+ micro_part = g_ascii_strtoull (v + 1, NULL /* endptr */, 10 /* base */);
+ if (errno || micro_part > COGL_VERSION_MAX_COMPONENT_VALUE)
+ return FALSE;
+
+ *version_ret = COGL_VERSION_ENCODE (COGL_VERSION_GET_MAJOR (*version_ret),
+ COGL_VERSION_GET_MINOR (*version_ret),
+ micro_part);
+
+ return TRUE;
+}
+
+static gboolean
+check_unknown_driver_package (const CoglGpuInfoStrings *strings,
+ int *version_out)
+{
+ *version_out = 0;
+
+ /* This is a last resort so it always matches */
+ return TRUE;
+}
+
+static const CoglGpuInfoDriverPackageDescription
+_cogl_gpu_info_driver_packages[] =
+ {
+ {
+ COGL_GPU_INFO_DRIVER_PACKAGE_MESA,
+ "Mesa",
+ check_mesa_driver_package
+ },
+ /* Must be last */
+ {
+ COGL_GPU_INFO_DRIVER_PACKAGE_UNKNOWN,
+ "Unknown",
+ check_unknown_driver_package
+ }
+ };
+
+void
+_cogl_gpu_info_init (CoglContext *ctx,
+ CoglGpuInfo *gpu)
+{
+ CoglGpuInfoStrings strings;
+ int i;
+
+ strings.renderer_string = (const char *) ctx->glGetString (GL_RENDERER);
+ strings.version_string = (const char *) ctx->glGetString (GL_VERSION);
+ strings.vendor_string = (const char *) ctx->glGetString (GL_VENDOR);
+
+ /* Determine the driver package */
+ for (i = 0; ; i++)
+ {
+ const CoglGpuInfoDriverPackageDescription *description =
+ _cogl_gpu_info_driver_packages + i;
+
+ if (description->check_function (&strings, &gpu->driver_package_version))
+ {
+ gpu->driver_package = description->driver_package;
+ gpu->driver_package_name = description->name;
+ break;
+ }
+ }
+
+ /* Determine the GPU vendor */
+ for (i = 0; ; i++)
+ {
+ const CoglGpuInfoVendorDescription *description =
+ _cogl_gpu_info_vendors + i;
+
+ if (description->check_function (&strings))
+ {
+ gpu->vendor = description->vendor;
+ gpu->vendor_name = description->name;
+ break;
+ }
+ }
+
+ /* Determine the driver bugs */
+ gpu->driver_bugs = 0;
+}
diff --git a/cogl/cogl-util.h b/cogl/cogl-util.h
index 63723e9b..5734f2fc 100644
--- a/cogl/cogl-util.h
+++ b/cogl/cogl-util.h
@@ -47,6 +47,27 @@
#define COGL_EXPORT
#endif
+/* Macros to handle compacting a 3-component version number into an
+ int for quick comparison. This assumes all of the components are
+ <= 1023 */
+#define COGL_VERSION_COMPONENT_BITS 10
+#define COGL_VERSION_MAX_COMPONENT_VALUE \
+ ((1 << COGL_VERSION_COMPONENT_BITS) - 1)
+
+#define COGL_VERSION_ENCODE(major, minor, micro) \
+ (((major) << (COGL_VERSION_COMPONENT_BITS * 2)) | \
+ ((minor) << COGL_VERSION_COMPONENT_BITS) \
+ | (micro))
+
+#define COGL_VERSION_GET_MAJOR(version) \
+ (((version) >> 20) & COGL_VERSION_MAX_COMPONENT_VALUE)
+
+#define COGL_VERSION_GET_MINOR(version) \
+ (((version) >> 10) & COGL_VERSION_MAX_COMPONENT_VALUE)
+
+#define COGL_VERSION_GET_MICRO(version) \
+ ((version) & COGL_VERSION_MAX_COMPONENT_VALUE)
+
int
_cogl_util_next_p2 (int a);