From 31b5beb2c00bfae83d6cd26e33242887f330e0bd Mon Sep 17 00:00:00 2001
From: Neil Roberts <neil@linux.intel.com>
Date: Wed, 2 Jun 2010 17:55:56 +0100
Subject: [PATCH] cogl: Add the infrastructure for checking for winsys
 extensions

This adds the framework needed to check for winsys specific extensions
(such as GLX extensions) using a similar mechanism to the
cogl-feature-functions header. There is a separate
cogl-winsys-feature-functions header which will contain macros to list
the extensions and functions. cogl_create_context_winsys now calls
_cogl_feature_check for each of these functions. _cogl_feature_check
has had to be changed to accept the driver prefix as the first
parameter so that it can prepend "GLX" rather than "GL" in this case.
---
 cogl/Makefile.am                            |  1 +
 cogl/cogl-feature-private.c                 |  7 ++-
 cogl/cogl-feature-private.h                 |  3 +-
 cogl/driver/gl/cogl.c                       |  2 +-
 cogl/driver/gles/cogl.c                     |  2 +-
 cogl/winsys/cogl-context-winsys.c           | 64 +++++++++++++++++++++
 cogl/winsys/cogl-context-winsys.h           | 21 ++++++-
 cogl/winsys/cogl-winsys-feature-functions.h | 25 ++++++++
 8 files changed, 118 insertions(+), 7 deletions(-)
 create mode 100644 cogl/winsys/cogl-winsys-feature-functions.h

diff --git a/cogl/Makefile.am b/cogl/Makefile.am
index 41f140827..0244dd403 100644
--- a/cogl/Makefile.am
+++ b/cogl/Makefile.am
@@ -77,6 +77,7 @@ cogl_sources_c = \
 	$(srcdir)/winsys/cogl-winsys.h			\
 	$(srcdir)/winsys/cogl-context-winsys.h          \
 	$(srcdir)/winsys/cogl-context-winsys.c          \
+	$(srcdir)/winsys/cogl-winsys-feature-functions.h \
 	$(srcdir)/cogl-handle.h 			\
 	$(srcdir)/cogl-context.h			\
 	$(srcdir)/cogl-context.c			\
diff --git a/cogl/cogl-feature-private.c b/cogl/cogl-feature-private.c
index d79bb7aa1..478c1f71e 100644
--- a/cogl/cogl-feature-private.c
+++ b/cogl/cogl-feature-private.c
@@ -33,7 +33,8 @@
 #include "cogl-feature-private.h"
 
 gboolean
-_cogl_feature_check (const CoglFeatureData *data,
+_cogl_feature_check (const char *driver_prefix,
+                     const CoglFeatureData *data,
                      unsigned int gl_major,
                      unsigned int gl_minor,
                      const char *extensions_string)
@@ -79,8 +80,8 @@ _cogl_feature_check (const CoglFeatureData *data,
                *extension;
                extension += strlen (extension) + 1)
             {
-              g_string_set_size (full_extension_name, 0);
-              g_string_append (full_extension_name, "GL_");
+              g_string_assign (full_extension_name, driver_prefix);
+              g_string_append_c (full_extension_name, '_');
               g_string_append_len (full_extension_name,
                                    namespace, namespace_len);
               g_string_append_c (full_extension_name, '_');
diff --git a/cogl/cogl-feature-private.h b/cogl/cogl-feature-private.h
index 2221ec037..133d588ed 100644
--- a/cogl/cogl-feature-private.h
+++ b/cogl/cogl-feature-private.h
@@ -67,7 +67,8 @@ struct _CoglFeatureData
   const CoglFeatureFunction *functions;
 };
 
-gboolean _cogl_feature_check (const CoglFeatureData *data,
+gboolean _cogl_feature_check (const char *driver_prefix,
+                              const CoglFeatureData *data,
                               unsigned int gl_major, unsigned int gl_minor,
                               const char *extensions_string);
 
diff --git a/cogl/driver/gl/cogl.c b/cogl/driver/gl/cogl.c
index 08fae7d35..fd37f6d02 100644
--- a/cogl/driver/gl/cogl.c
+++ b/cogl/driver/gl/cogl.c
@@ -219,7 +219,7 @@ _cogl_features_init (void)
     flags |= COGL_FEATURE_FOUR_CLIP_PLANES;
 
   for (i = 0; i < G_N_ELEMENTS (cogl_feature_data); i++)
-    if (_cogl_feature_check (cogl_feature_data + i,
+    if (_cogl_feature_check ("GL", cogl_feature_data + i,
                              gl_major, gl_minor,
                              gl_extensions))
       {
diff --git a/cogl/driver/gles/cogl.c b/cogl/driver/gles/cogl.c
index fbf8e8b3a..f25a5fa6c 100644
--- a/cogl/driver/gles/cogl.c
+++ b/cogl/driver/gles/cogl.c
@@ -84,7 +84,7 @@ _cogl_features_init (void)
   gl_extensions = (const char*) glGetString (GL_EXTENSIONS);
 
   for (i = 0; i < G_N_ELEMENTS (cogl_feature_data); i++)
-    if (_cogl_feature_check (cogl_feature_data + i,
+    if (_cogl_feature_check ("GL", cogl_feature_data + i,
                              0, 0,
                              gl_extensions))
         flags |= cogl_feature_data[i].feature_flags;
diff --git a/cogl/winsys/cogl-context-winsys.c b/cogl/winsys/cogl-context-winsys.c
index e984f14bb..5d6437b05 100644
--- a/cogl/winsys/cogl-context-winsys.c
+++ b/cogl/winsys/cogl-context-winsys.c
@@ -25,7 +25,69 @@
 #include "config.h"
 #endif
 
+#ifdef COGL_HAS_GLX_SUPPORT
+#include <GL/glx.h>
+#endif
+
 #include "cogl-context.h"
+#include "cogl-feature-private.h"
+
+/* Define a set of arrays containing the functions required from GL
+   for each winsys feature */
+#define COGL_WINSYS_FEATURE_BEGIN(name, namespaces, extension_names,    \
+                                  feature_flags, feature_flags_private) \
+  static const CoglFeatureFunction                                      \
+  cogl_winsys_feature_ ## name ## _funcs[] = {
+#define COGL_WINSYS_FEATURE_FUNCTION(ret, name, args)                   \
+  { G_STRINGIFY (name), G_STRUCT_OFFSET (CoglContext, winsys.pf_ ## name) },
+#define COGL_WINSYS_FEATURE_END()               \
+  { NULL, 0 },                                  \
+    };
+#include "cogl-winsys-feature-functions.h"
+
+/* Define an array of features */
+#undef COGL_WINSYS_FEATURE_BEGIN
+#define COGL_WINSYS_FEATURE_BEGIN(name, namespaces, extension_names,    \
+                                  feature_flags, feature_flags_private) \
+  { 255, 255, namespaces, extension_names,                              \
+      feature_flags, feature_flags_private,                             \
+      cogl_winsys_feature_ ## name ## _funcs },
+#undef COGL_WINSYS_FEATURE_FUNCTION
+#define COGL_WINSYS_FEATURE_FUNCTION(ret, name, args)
+#undef COGL_WINSYS_FEATURE_END
+#define COGL_WINSYS_FEATURE_END()
+
+static const CoglFeatureData cogl_winsys_feature_data[] =
+  {
+#include "cogl-winsys-feature-functions.h"
+  };
+
+static const char *
+_cogl_get_winsys_extensions (void)
+{
+#ifdef COGL_HAS_GLX_SUPPORT
+  Display *display = _cogl_xlib_get_display ();
+
+  return glXQueryExtensionsString (display, DefaultScreen (display));
+#else
+  return "";
+#endif
+}
+
+static void
+_cogl_winsys_features_init (CoglContext *context)
+{
+  CoglWinsysFeatureFlags flags = 0;
+  const char *extensions = _cogl_get_winsys_extensions ();
+  int i;
+
+  for (i = 0; i < G_N_ELEMENTS (cogl_winsys_feature_data); i++)
+    if (_cogl_feature_check ("GLX", cogl_winsys_feature_data + i, 0, 0,
+                             extensions))
+      flags |= cogl_winsys_feature_data[i].feature_flags;
+
+  context->winsys.feature_flags = flags;
+}
 
 void
 _cogl_create_context_winsys (CoglContext *context)
@@ -33,6 +95,8 @@ _cogl_create_context_winsys (CoglContext *context)
 #ifdef COGL_HAS_XLIB_SUPPORT
   context->winsys.event_filters = NULL;
 #endif
+
+  _cogl_winsys_features_init (context);
 }
 
 #ifdef COGL_HAS_XLIB_SUPPORT
diff --git a/cogl/winsys/cogl-context-winsys.h b/cogl/winsys/cogl-context-winsys.h
index f0e28daed..aa6563a43 100644
--- a/cogl/winsys/cogl-context-winsys.h
+++ b/cogl/winsys/cogl-context-winsys.h
@@ -24,6 +24,11 @@
 #ifndef __COGL_CONTEXT_WINSYS_H
 #define __COGL_CONTEXT_WINSYS_H
 
+typedef enum
+{
+  COGL_WINSYS_FEATURE_STUB /* no features are defined yet */
+} CoglWinsysFeatureFlags;
+
 typedef struct
 {
   /* These are specific to winsys backends supporting Xlib. This
@@ -33,7 +38,21 @@ typedef struct
   GSList *event_filters;
 #endif
 
-  int stub;
+  /* Function pointers for winsys specific extensions */
+#define COGL_WINSYS_FEATURE_BEGIN(a, b, c, d, e)
+
+#define COGL_WINSYS_FEATURE_FUNCTION(ret, name, args) \
+  ret (APIENTRY * pf_ ## name) args;
+
+#define COGL_WINSYS_FEATURE_END()
+
+#include "cogl-winsys-feature-functions.h"
+
+#undef COGL_WINSYS_FEATURE_BEGIN
+#undef COGL_WINSYS_FEATURE_FUNCTION
+#undef COGL_WINSYS_FEATURE_END
+
+  CoglWinsysFeatureFlags feature_flags;
 } CoglContextWinsys;
 
 #endif /* __COGL_CONTEXT_WINSYS_H */
diff --git a/cogl/winsys/cogl-winsys-feature-functions.h b/cogl/winsys/cogl-winsys-feature-functions.h
new file mode 100644
index 000000000..e4f6de44a
--- /dev/null
+++ b/cogl/winsys/cogl-winsys-feature-functions.h
@@ -0,0 +1,25 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2010 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/>.
+ *
+ *
+ */
+
+/* This can be included multiple times with different definitions for
+   the COGL_WINSYS_FEATURE_* functions */