[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