[Cogl] [PATCH 1/2] Add a mechanism for determining GPU driver details
Robert Bragg
robert at sixbynine.org
Thu Apr 5 06:00:14 PDT 2012
cool, thanks for the update, this all looks good to me now.
Reviewed-by: Robert Bragg <robert at linux.intel.com>
regards,
- Robert
On Thu, Apr 5, 2012 at 1:22 PM, Neil Roberts <neil at linux.intel.com> wrote:
> This adds a CoglGpuInfo struct to the CoglContext which contains some
> enums describing the GL driver in use. This currently includes the
> driver package (ie, is it Mesa) the version number of the package and
> the vendor of the GPU (ie, is it by Intel). There is also a bitmask
> which will contain the workarounds that we should do for that
> particular driver configuration. The struct is initialised on context
> creation by using a series of string comparisons on the strings
> returned from glGetString.
> ---
> cogl/Makefile.am | 2 +
> cogl/cogl-context-private.h | 5 +
> cogl/cogl-context.c | 3 +
> cogl/cogl-gpu-info-private.h | 74 ++++++++++++
> cogl/cogl-gpu-info.c | 254 ++++++++++++++++++++++++++++++++++++++++++
> cogl/cogl-util.h | 21 ++++
> 6 files changed, 359 insertions(+), 0 deletions(-)
> create mode 100644 cogl/cogl-gpu-info-private.h
> create mode 100644 cogl/cogl-gpu-info.c
>
> diff --git a/cogl/Makefile.am b/cogl/Makefile.am
> index 69cb5df..10c1e4a 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 a79672f..7c96a14 100644
> --- a/cogl/cogl-context-private.h
> +++ b/cogl/cogl-context-private.h
> @@ -47,6 +47,7 @@
> #include "cogl-texture-2d.h"
> #include "cogl-texture-3d.h"
> #include "cogl-texture-rectangle.h"
> +#include "cogl-gpu-info-private.h"
>
> typedef struct
> {
> @@ -63,6 +64,10 @@ struct _CoglContext
>
> CoglDriver driver;
>
> + /* Information about the GPU and driver which we can use to
> + determine certain workarounds */
> + CoglGpuInfo gpu;
> +
> /* vtables for the driver functions */
> const CoglDriverVtable *driver_vtable;
> const CoglTextureDriver *texture_driver;
> diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c
> index 8ed3103..d34450d 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>
>
> @@ -234,6 +235,8 @@ cogl_context_new (CoglDisplay *display,
> return NULL;
> }
>
> + _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 0000000..2930d6b
> --- /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 0000000..f62bbc3
> --- /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 d657c76..7681d33 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);
>
> --
> 1.7.3.16.g9464b
>
> _______________________________________________
> Cogl mailing list
> Cogl at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/cogl
More information about the Cogl
mailing list