[Cogl] [PATCH] Add a GL 3 driver
Robert Bragg
robert at sixbynine.org
Mon Oct 1 05:34:49 PDT 2012
This is really cool, and looks good to land to me so we don't have to
worry about re-basing it. Once we have a glsl frontend in Cogl that
will hopefully let us address the inconsistencies between GL versions
in supporting single component textures.
Reviewed-by: Robert Bragg <robert at linux.intel.com>
thanks,
- Robert
On Sat, Sep 29, 2012 at 2:00 AM, Neil Roberts <neil at linux.intel.com> wrote:
> This adds a new CoglDriver for GL 3 called COGL_DRIVER_GL3. When
> requested, the GLX, EGL and SDL2 winsyss will set the necessary
> attributes to request a forward-compatible core profile 3.1 context.
> That means it will have no deprecated features.
>
> To simplify the explosion of checks for specific combinations of
> context->driver, many of these conditionals have now been replaced
> with private feature flags that are checked instead. The GL and GLES
> drivers now initialise these private feature flags depending on which
> driver is used.
>
> The fixed function backends now explicitly check whether the fixed
> function private feature is available which means the GL3 driver will
> fall back to always using the GLSL progend. Since Rob's latest patches
> the GLSL progend no longer uses any fixed function API anyway so it
> should just work.
>
> The driver is currently lower priority than COGL_DRIVER_GL so it will
> not be used unless it is specificly requested. We may want to change
> this priority at some point because apparently Mesa can make some
> memory savings if a core profile context is used.
>
> In GL 3, getting the combined extensions string with glGetString is
> deprecated so this patch changes it to use glGetStringi to build up an
> array of extensions instead. _cogl_context_get_gl_extensions now
> returns this array instead of trying to return a const string. The
> caller is expected to free the array.
>
> Some issues with this patch:
>
> • GL 3 does not support GL_ALPHA format textures. We should probably
> make this a feature flag or something. Cogl uses this to render text
> which currently just throws a GL error and breaks so it's pretty
> important to do something about this before considering the GL3
> driver to be stable.
>
> • GL 3 doesn't support client side vertex buffers. This probably
> doesn't matter because CoglBuffer won't normally use malloc'd
> buffers if VBOs are available, but it might but worth making
> malloc'd buffers a private feature and forcing it not to use them.
>
> • GL 3 doesn't support the default vertex array object. This patch
> just makes it create and bind a single non-default vertex array
> object which gets used just like the normal default object. Ideally
> it would be good to use vertex array objects properly and attach
> them to a CoglPrimitive to cache the state.
> ---
> cogl-pango/cogl-pango-display-list.c | 2 +-
> cogl/cogl-blend-string.c | 35 ++----
> cogl/cogl-clutter.c | 22 +++-
> cogl/cogl-context-private.h | 10 +-
> cogl/cogl-context.c | 118 ++++++++++++---------
> cogl/cogl-feature-private.c | 10 +-
> cogl/cogl-feature-private.h | 4 +-
> cogl/cogl-framebuffer.c | 6 +-
> cogl/cogl-internal.h | 15 ++-
> cogl/cogl-journal.c | 4 +-
> cogl/cogl-matrix-stack.c | 6 +-
> cogl/cogl-pipeline-state.c | 2 +-
> cogl/cogl-pipeline.c | 8 +-
> cogl/cogl-private.h | 2 +-
> cogl/cogl-renderer.c | 13 ++-
> cogl/cogl-renderer.h | 2 +
> cogl/cogl-texture.c | 2 +-
> cogl/cogl.c | 25 ++---
> cogl/driver/gl/cogl-attribute-gl.c | 8 +-
> cogl/driver/gl/cogl-clip-stack-gl.c | 1 +
> cogl/driver/gl/cogl-framebuffer-gl.c | 4 +-
> cogl/driver/gl/cogl-pipeline-fragend-glsl.c | 17 ++-
> cogl/driver/gl/cogl-pipeline-opengl.c | 9 +-
> cogl/driver/gl/cogl-pipeline-progend-fixed.c | 2 +-
> cogl/driver/gl/cogl-pipeline-vertend-glsl.c | 6 +-
> cogl/driver/gl/cogl-texture-2d-gl.c | 3 +-
> cogl/driver/gl/gl/cogl-driver-gl.c | 77 ++++++++++----
> .../gl/gl/cogl-pipeline-progend-fixed-arbfp.c | 2 +-
> cogl/driver/gl/gles/cogl-driver-gles.c | 44 +++++---
> cogl/gl-prototypes/cogl-all-functions.h | 26 ++++-
> cogl/gl-prototypes/cogl-in-gles-core-functions.h | 6 +-
> cogl/gl-prototypes/cogl-in-gles2-core-functions.h | 8 +-
> cogl/winsys/cogl-winsys-egl-feature-functions.h | 7 ++
> cogl/winsys/cogl-winsys-egl-private.h | 3 +-
> cogl/winsys/cogl-winsys-egl.c | 61 ++++++++---
> cogl/winsys/cogl-winsys-glx-feature-functions.h | 13 +++
> cogl/winsys/cogl-winsys-glx.c | 56 ++++++++--
> cogl/winsys/cogl-winsys-sdl.c | 6 ++
> cogl/winsys/cogl-winsys-sdl2.c | 26 +++++
> cogl/winsys/cogl-winsys-wgl.c | 17 ++-
> tests/conform/run-tests.sh | 11 +-
> tests/conform/test-utils.c | 3 +-
> 42 files changed, 475 insertions(+), 227 deletions(-)
>
> diff --git a/cogl-pango/cogl-pango-display-list.c b/cogl-pango/cogl-pango-display-list.c
> index 52b6b25..d77b6fb 100644
> --- a/cogl-pango/cogl-pango-display-list.c
> +++ b/cogl-pango/cogl-pango-display-list.c
> @@ -349,7 +349,7 @@ emit_vertex_buffer_geometry (CoglFramebuffer *fb,
> 2 /* n_attributes */);
>
> #ifdef CLUTTER_COGL_HAS_GL
> - if (ctx->driver == COGL_DRIVER_GL)
> + if ((ctx->private_feature_flags & COGL_PRIVATE_FEATURE_QUADS))
> cogl_primitive_set_mode (prim, GL_QUADS);
> else
> #endif
> diff --git a/cogl/cogl-blend-string.c b/cogl/cogl-blend-string.c
> index afb9f14..7d4c2e5 100644
> --- a/cogl/cogl-blend-string.c
> +++ b/cogl/cogl-blend-string.c
> @@ -216,30 +216,14 @@ validate_blend_statements (CoglBlendStringStatement *statements,
>
> _COGL_GET_CONTEXT (ctx, 0);
>
> - if (ctx->driver == COGL_DRIVER_GL)
> + if (n_statements == 2 &&
> + !ctx->glBlendEquationSeparate &&
> + statements[0].function->type != statements[1].function->type)
> {
> - if (n_statements == 2)
> - {
> - /* glBlendEquationSeperate is GL 2.0 only */
> - if (!ctx->glBlendEquationSeparate &&
> - statements[0].function->type != statements[1].function->type)
> - {
> - error_string = "Separate blend functions for the RGB an A "
> - "channels isn't supported by the driver";
> - detail = COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR;
> - goto error;
> - }
> - }
> - }
> - else if (ctx->driver == COGL_DRIVER_GLES1)
> - {
> - if (n_statements != 1)
> - {
> - error_string = "Separate blend functions for the RGB an A "
> - "channels isn't supported by the GLES 1";
> - detail = COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR;
> - goto error;
> - }
> + error_string = "Separate blend functions for the RGB an A "
> + "channels isn't supported by the driver";
> + detail = COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR;
> + goto error;
> }
>
> for (i = 0; i < n_statements; i++)
> @@ -262,12 +246,13 @@ validate_blend_statements (CoglBlendStringStatement *statements,
> goto error;
> }
>
> - if (ctx->driver == COGL_DRIVER_GLES1 &&
> + if (!(ctx->private_feature_flags &
> + COGL_PRIVATE_FEATURE_BLEND_CONSTANT) &&
> arg->factor.is_color &&
> (arg->factor.source.info->type ==
> COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT))
> {
> - error_string = "GLES Doesn't support constant blend factors";
> + error_string = "Driver doesn't support constant blend factors";
> detail = COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR;
> goto error;
> }
> diff --git a/cogl/cogl-clutter.c b/cogl/cogl-clutter.c
> index fddff09..b00e510 100644
> --- a/cogl/cogl-clutter.c
> +++ b/cogl/cogl-clutter.c
> @@ -29,6 +29,7 @@
> #endif
>
> #include <glib.h>
> +#include <string.h>
>
> #include "cogl-util.h"
> #include "cogl-types.h"
> @@ -46,7 +47,26 @@
> CoglBool
> cogl_clutter_check_extension (const char *name, const char *ext)
> {
> - return _cogl_check_extension (name, ext);
> + char *end;
> + int name_len, n;
> +
> + if (name == NULL || ext == NULL)
> + return FALSE;
> +
> + end = (char*)(ext + strlen(ext));
> +
> + name_len = strlen(name);
> +
> + while (ext < end)
> + {
> + n = strcspn(ext, " ");
> +
> + if ((name_len == n) && (!strncmp(name, ext, n)))
> + return TRUE;
> + ext += (n + 1);
> + }
> +
> + return FALSE;
> }
>
> CoglBool
> diff --git a/cogl/cogl-context-private.h b/cogl/cogl-context-private.h
> index 53239f4..4ea6687 100644
> --- a/cogl/cogl-context-private.h
> +++ b/cogl/cogl-context-private.h
> @@ -341,7 +341,15 @@ void
> _cogl_context_set_current_modelview_entry (CoglContext *context,
> CoglMatrixEntry *entry);
>
> -const char *
> +/*
> + * _cogl_context_get_gl_extensions:
> + * @context: A CoglContext
> + *
> + * Return value: a NULL-terminated array of strings representing the
> + * supported extensions by the current driver. This array is owned
> + * by the caller and should be freed with g_strfreev().
> + */
> +char **
> _cogl_context_get_gl_extensions (CoglContext *context);
>
> const char *
> diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c
> index 1d02f1f..325a58a 100644
> --- a/cogl/cogl-context.c
> +++ b/cogl/cogl-context.c
> @@ -248,9 +248,7 @@ cogl_context_new (CoglDisplay *display,
> context->texture_units =
> g_array_new (FALSE, FALSE, sizeof (CoglTextureUnit));
>
> - if (context->driver == COGL_DRIVER_GL ||
> - context->driver == COGL_DRIVER_GLES1 ||
> - context->driver == COGL_DRIVER_GLES2)
> + if ((context->private_feature_flags & COGL_PRIVATE_FEATURE_ANY_GL))
> {
> /* See cogl-pipeline.c for more details about why we leave texture unit 1
> * active by default... */
> @@ -347,8 +345,7 @@ cogl_context_new (CoglDisplay *display,
> context->blit_texture_pipeline = NULL;
>
> #if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES)
> - if (context->driver == COGL_DRIVER_GL ||
> - context->driver == COGL_DRIVER_GLES1)
> + if ((context->private_feature_flags & COGL_PRIVATE_FEATURE_ALPHA_TEST))
> /* The default for GL_ALPHA_TEST is to always pass which is equivalent to
> * the test being disabled therefore we assume that for all drivers there
> * will be no performance impact if we always leave the test enabled which
> @@ -358,6 +355,22 @@ cogl_context_new (CoglDisplay *display,
> GE (context, glEnable (GL_ALPHA_TEST));
> #endif
>
> +#if defined (HAVE_COGL_GL)
> + if ((context->driver == COGL_DRIVER_GL3))
> + {
> + GLuint vertex_array;
> +
> + /* In a forward compatible context, GL 3 doesn't support rendering
> + * using the default vertex array object. Cogl doesn't use vertex
> + * array objects yet so for now we just create a dummy array
> + * object that we will use as our own default object. Eventually
> + * it could be good to attach the vertex array objects to
> + * CoglPrimitives */
> + context->glGenVertexArrays (1, &vertex_array);
> + context->glBindVertexArray (vertex_array);
> + }
> +#endif
> +
> context->current_modelview_entry = NULL;
> context->current_projection_entry = NULL;
> _cogl_matrix_entry_identity_init (&context->identity_entry);
> @@ -407,13 +420,13 @@ cogl_context_new (CoglDisplay *display,
> context->buffer_map_fallback_in_use = FALSE;
>
> /* As far as I can tell, GL_POINT_SPRITE doesn't have any effect
> - unless GL_COORD_REPLACE is enabled for an individual
> - layer. Therefore it seems like it should be ok to just leave it
> - enabled all the time instead of having to have a set property on
> - each pipeline to track whether any layers have point sprite
> - coords enabled. We don't need to do this for GLES2 because point
> + unless GL_COORD_REPLACE is enabled for an individual layer.
> + Therefore it seems like it should be ok to just leave it enabled
> + all the time instead of having to have a set property on each
> + pipeline to track whether any layers have point sprite coords
> + enabled. We don't need to do this for GL3 or GLES2 because point
> sprites are handled using a builtin varying in the shader. */
> - if (context->driver != COGL_DRIVER_GLES2 &&
> + if ((context->private_feature_flags & COGL_PRIVATE_FEATURE_FIXED_FUNCTION) &&
> cogl_has_feature (context, COGL_FEATURE_ID_POINT_SPRITE))
> GE (context, glEnable (GL_POINT_SPRITE));
>
> @@ -572,38 +585,45 @@ _cogl_context_set_current_modelview_entry (CoglContext *context,
> context->current_modelview_entry = entry;
> }
>
> -const char *
> +char **
> _cogl_context_get_gl_extensions (CoglContext *context)
> {
> const char *env_disabled_extensions;
> + char **ret;
>
> - if ((env_disabled_extensions = g_getenv ("COGL_DISABLE_GL_EXTENSIONS"))
> - || _cogl_config_disable_gl_extensions)
> + /* In GL 3, querying GL_EXTENSIONS is deprecated so we have to build
> + * the array using glGetStringi instead */
> + if (context->driver == COGL_DRIVER_GL3)
> {
> - static CoglUserDataKey extensions_key;
> - const char *enabled_extensions;
> - char **split_enabled_extensions;
> - char **split_env_disabled_extensions;
> - char **split_conf_disabled_extensions;
> - char **e;
> - GString *result;
> + int num_extensions, i;
>
> - /* We need to return a const string so we'll attach the results
> - * to the CoglContext to avoid leaking the generated string.
> - * This string is only used rarely so we are using
> - * cogl_object_set_user_data instead of adding an explicit
> - * member to CoglContext to avoid making the struct bigger */
> + context->glGetIntegerv (GL_NUM_EXTENSIONS, &num_extensions);
>
> - enabled_extensions =
> - cogl_object_get_user_data (COGL_OBJECT (context), &extensions_key);
> - if (enabled_extensions)
> - return enabled_extensions;
> + ret = g_malloc (sizeof (char *) * (num_extensions + 1));
> +
> + for (i = 0; i < num_extensions; i++)
> + {
> + const char *ext =
> + (const char *) context->glGetStringi (GL_EXTENSIONS, i);
> + ret[i] = g_strdup (ext);
> + }
> +
> + ret[num_extensions] = NULL;
> + }
> + else
> + {
> + const char *all_extensions =
> + (const char *) context->glGetString (GL_EXTENSIONS);
>
> - enabled_extensions = (const char *) context->glGetString (GL_EXTENSIONS);
> + ret = g_strsplit (all_extensions, " ", 0 /* max tokens */);
> + }
>
> - split_enabled_extensions = g_strsplit (enabled_extensions,
> - " ",
> - 0 /* no max tokens */);
> + if ((env_disabled_extensions = g_getenv ("COGL_DISABLE_GL_EXTENSIONS"))
> + || _cogl_config_disable_gl_extensions)
> + {
> + char **split_env_disabled_extensions;
> + char **split_conf_disabled_extensions;
> + char **src, **dst;
>
> if (env_disabled_extensions)
> split_env_disabled_extensions =
> @@ -621,46 +641,38 @@ _cogl_context_get_gl_extensions (CoglContext *context)
> else
> split_conf_disabled_extensions = NULL;
>
> - result = g_string_new (NULL);
> -
> - for (e = split_enabled_extensions; *e; e++)
> + for (dst = ret, src = ret;
> + *src;
> + src++)
> {
> char **d;
>
> if (split_env_disabled_extensions)
> for (d = split_env_disabled_extensions; *d; d++)
> - if (!strcmp (*e, *d))
> + if (!strcmp (*src, *d))
> goto disabled;
> if (split_conf_disabled_extensions)
> for (d = split_conf_disabled_extensions; *d; d++)
> - if (!strcmp (*e, *d))
> + if (!strcmp (*src, *d))
> goto disabled;
>
> - if (result->len > 0)
> - g_string_append_c (result, ' ');
> - g_string_append (result, *e);
> + *(dst++) = *src;
> + continue;
>
> disabled:
> + g_free (*src);
> continue;
> }
>
> - enabled_extensions = g_string_free (result, FALSE);
> + *dst = NULL;
>
> - g_strfreev (split_enabled_extensions);
> if (split_env_disabled_extensions)
> g_strfreev (split_env_disabled_extensions);
> if (split_conf_disabled_extensions)
> g_strfreev (split_conf_disabled_extensions);
> -
> - cogl_object_set_user_data (COGL_OBJECT (context),
> - &extensions_key,
> - (void *) enabled_extensions,
> - (CoglUserDataDestroyCallback) g_free);
> -
> - return enabled_extensions;
> }
> - else
> - return (const char *) context->glGetString (GL_EXTENSIONS);
> +
> + return ret;
> }
>
> const char *
> diff --git a/cogl/cogl-feature-private.c b/cogl/cogl-feature-private.c
> index 10562cf..1f638a6 100644
> --- a/cogl/cogl-feature-private.c
> +++ b/cogl/cogl-feature-private.c
> @@ -31,6 +31,7 @@
>
> #include "cogl-feature-private.h"
> #include "cogl-renderer-private.h"
> +#include "cogl-private.h"
>
> CoglBool
> _cogl_feature_check (CoglRenderer *renderer,
> @@ -39,7 +40,7 @@ _cogl_feature_check (CoglRenderer *renderer,
> int gl_major,
> int gl_minor,
> CoglDriver driver,
> - const char *extensions_string,
> + char * const *extensions,
> void *function_table)
>
> {
> @@ -49,7 +50,8 @@ _cogl_feature_check (CoglRenderer *renderer,
>
> /* First check whether the functions should be directly provided by
> GL */
> - if ((driver == COGL_DRIVER_GL &&
> + if (((driver == COGL_DRIVER_GL ||
> + driver == COGL_DRIVER_GL3) &&
> COGL_CHECK_GL_VERSION (gl_major, gl_minor,
> data->min_gl_major, data->min_gl_minor)) ||
> (driver == COGL_DRIVER_GLES1 &&
> @@ -97,7 +99,7 @@ _cogl_feature_check (CoglRenderer *renderer,
> g_string_append_c (full_extension_name, '_');
> g_string_append (full_extension_name, extension);
> if (_cogl_check_extension (full_extension_name->str,
> - extensions_string))
> + extensions))
> break;
> }
>
> @@ -192,7 +194,7 @@ void
> _cogl_feature_check_ext_functions (CoglContext *context,
> int gl_major,
> int gl_minor,
> - const char *gl_extensions)
> + char * const *gl_extensions)
> {
> int i;
>
> diff --git a/cogl/cogl-feature-private.h b/cogl/cogl-feature-private.h
> index fd284e2..1207f9e 100644
> --- a/cogl/cogl-feature-private.h
> +++ b/cogl/cogl-feature-private.h
> @@ -85,13 +85,13 @@ _cogl_feature_check (CoglRenderer *renderer,
> int gl_major,
> int gl_minor,
> CoglDriver driver,
> - const char *extensions_string,
> + char * const *extensions,
> void *function_table);
>
> void
> _cogl_feature_check_ext_functions (CoglContext *context,
> int gl_major,
> int gl_minor,
> - const char *gl_extensions);
> + char * const *gl_extensions);
>
> #endif /* __COGL_FEATURE_PRIVATE_H */
> diff --git a/cogl/cogl-framebuffer.c b/cogl/cogl-framebuffer.c
> index 41f5d18..8e4f6f3 100644
> --- a/cogl/cogl-framebuffer.c
> +++ b/cogl/cogl-framebuffer.c
> @@ -1540,7 +1540,8 @@ cogl_framebuffer_read_pixels_into_bitmap (CoglFramebuffer *framebuffer,
> GL_RGBA/GL_UNSIGNED_BYTE and convert if necessary. We also need
> to use this intermediate buffer if the rowstride has padding
> because GLES does not support setting GL_ROW_LENGTH */
> - if ((ctx->driver != COGL_DRIVER_GL &&
> + if ((!(ctx->private_feature_flags &
> + COGL_PRIVATE_FEATURE_READ_PIXELS_ANY_FORMAT) &&
> (gl_format != GL_RGBA || gl_type != GL_UNSIGNED_BYTE ||
> cogl_bitmap_get_rowstride (bitmap) != 4 * width)) ||
> (required_format & ~COGL_PREMULT_BIT) != (format & ~COGL_PREMULT_BIT))
> @@ -1551,7 +1552,8 @@ cogl_framebuffer_read_pixels_into_bitmap (CoglFramebuffer *framebuffer,
> uint8_t *tmp_data;
> int succeeded;
>
> - if (ctx->driver == COGL_DRIVER_GL)
> + if ((ctx->private_feature_flags &
> + COGL_PRIVATE_FEATURE_READ_PIXELS_ANY_FORMAT))
> read_format = required_format;
> else
> {
> diff --git a/cogl/cogl-internal.h b/cogl/cogl-internal.h
> index 2d6e089..97f10d8 100644
> --- a/cogl/cogl-internal.h
> +++ b/cogl/cogl-internal.h
> @@ -104,7 +104,17 @@ typedef enum
> COGL_PRIVATE_FEATURE_OES_PACKED_DEPTH_STENCIL = 1L<<8,
> COGL_PRIVATE_FEATURE_TEXTURE_FORMAT_BGRA8888 = 1L<<9,
> COGL_PRIVATE_FEATURE_UNPACK_SUBIMAGE = 1L<<10,
> - COGL_PRIVATE_FEATURE_SAMPLER_OBJECTS = 1L<<11
> + COGL_PRIVATE_FEATURE_SAMPLER_OBJECTS = 1L<<11,
> + COGL_PRIVATE_FEATURE_FIXED_FUNCTION = 1L<<12,
> + COGL_PRIVATE_FEATURE_READ_PIXELS_ANY_FORMAT = 1L<<13,
> + COGL_PRIVATE_FEATURE_ANY_GL = 1L<<14,
> + COGL_PRIVATE_FEATURE_ALPHA_TEST = 1L<<15,
> + COGL_PRIVATE_FEATURE_FORMAT_CONVERSION = 1L<<16,
> + COGL_PRIVATE_FEATURE_QUADS = 1L<<17,
> + COGL_PRIVATE_FEATURE_BLEND_CONSTANT = 1L<<18,
> + COGL_PRIVATE_FEATURE_QUERY_FRAMEBUFFER_BITS = 1L<<19,
> + COGL_PRIVATE_FEATURE_BUILTIN_POINT_SIZE_UNIFORM = 1L<<20,
> + COGL_PRIVATE_FEATURE_QUERY_TEXTURE_PARAMETERS = 1L<<21
> } CoglPrivateFeatureFlags;
>
> /* Sometimes when evaluating pipelines, either during comparisons or
> @@ -115,9 +125,6 @@ typedef enum _CoglPipelineEvalFlags
> COGL_PIPELINE_EVAL_FLAG_NONE = 0
> } CoglPipelineEvalFlags;
>
> -CoglBool
> -_cogl_check_extension (const char *name, const char *ext);
> -
> uint32_t
> _cogl_driver_error_domain (void);
>
> diff --git a/cogl/cogl-journal.c b/cogl/cogl-journal.c
> index a467c33..4faed16 100644
> --- a/cogl/cogl-journal.c
> +++ b/cogl/cogl-journal.c
> @@ -302,7 +302,7 @@ _cogl_journal_flush_modelview_and_entries (CoglJournalEntry *batch_start,
> draw_flags |= COGL_DRAW_COLOR_ATTRIBUTE_IS_OPAQUE;
>
> #ifdef HAVE_COGL_GL
> - if (ctx->driver == COGL_DRIVER_GL)
> + if ((ctx->private_feature_flags & COGL_PRIVATE_FEATURE_QUADS))
> {
> /* XXX: it's rather evil that we sneak in the GL_QUADS enum here... */
> _cogl_framebuffer_draw_attributes (framebuffer,
> @@ -639,7 +639,7 @@ _cogl_journal_flush_vbo_offsets_and_entries (CoglJournalEntry *batch_start,
> 4,
> COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE);
>
> - if (ctx->driver != COGL_DRIVER_GL)
> + if (!(ctx->private_feature_flags & COGL_PRIVATE_FEATURE_QUADS))
> state->indices = cogl_get_rectangle_indices (ctx, batch_len);
>
> /* We only create new Attributes when the stride within the
> diff --git a/cogl/cogl-matrix-stack.c b/cogl/cogl-matrix-stack.c
> index 22afd7c..df1ec48 100644
> --- a/cogl/cogl-matrix-stack.c
> +++ b/cogl/cogl-matrix-stack.c
> @@ -794,8 +794,7 @@ _cogl_matrix_flush_to_gl_builtin (CoglContext *ctx,
> CoglMatrix *matrix,
> CoglMatrixMode mode)
> {
> - g_assert (ctx->driver == COGL_DRIVER_GL ||
> - ctx->driver == COGL_DRIVER_GLES1);
> + g_assert ((ctx->private_feature_flags & COGL_PRIVATE_FEATURE_FIXED_FUNCTION));
>
> #if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES)
> if (ctx->flushed_matrix_mode != mode)
> @@ -835,8 +834,7 @@ _cogl_matrix_entry_flush_to_gl_builtins (CoglContext *ctx,
> CoglFramebuffer *framebuffer,
> CoglBool disable_flip)
> {
> - g_assert (ctx->driver == COGL_DRIVER_GL ||
> - ctx->driver == COGL_DRIVER_GLES1);
> + g_assert ((ctx->private_feature_flags & COGL_PRIVATE_FEATURE_FIXED_FUNCTION));
>
> #if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES)
> {
> diff --git a/cogl/cogl-pipeline-state.c b/cogl/cogl-pipeline-state.c
> index fddc6c9..c4ec4ea 100644
> --- a/cogl/cogl-pipeline-state.c
> +++ b/cogl/cogl-pipeline-state.c
> @@ -708,7 +708,7 @@ cogl_pipeline_set_blend_constant (CoglPipeline *pipeline,
>
> _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline));
>
> - if (ctx->driver == COGL_DRIVER_GLES1)
> + if (!(ctx->private_feature_flags & COGL_PRIVATE_FEATURE_BLEND_CONSTANT))
> return;
>
> #if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL)
> diff --git a/cogl/cogl-pipeline.c b/cogl/cogl-pipeline.c
> index ac7b1cf..85264ab 100644
> --- a/cogl/cogl-pipeline.c
> +++ b/cogl/cogl-pipeline.c
> @@ -2641,8 +2641,10 @@ _cogl_pipeline_get_layer_state_for_fragment_codegen (CoglContext *context)
> COGL_PIPELINE_LAYER_STATE_UNIT |
> COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS);
>
> - if (context->driver == COGL_DRIVER_GL ||
> - context->driver == COGL_DRIVER_GLES2)
> + /* If the driver supports GLSL then we might be using gl_PointCoord
> + * to implement the sprite coords. In that case the generated code
> + * depends on the point sprite state */
> + if (cogl_has_feature (context, COGL_FEATURE_ID_GLSL))
> state |= COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS;
>
> return state;
> @@ -2654,7 +2656,7 @@ _cogl_pipeline_get_state_for_fragment_codegen (CoglContext *context)
> CoglPipelineState state = (COGL_PIPELINE_STATE_LAYERS |
> COGL_PIPELINE_STATE_FRAGMENT_SNIPPETS);
>
> - if (context->driver == COGL_DRIVER_GLES2)
> + if (!(context->private_feature_flags & COGL_PRIVATE_FEATURE_ALPHA_TEST))
> state |= COGL_PIPELINE_STATE_ALPHA_FUNC;
>
> return state;
> diff --git a/cogl/cogl-private.h b/cogl/cogl-private.h
> index 9006892..a78435b 100644
> --- a/cogl/cogl-private.h
> +++ b/cogl/cogl-private.h
> @@ -31,7 +31,7 @@
> G_BEGIN_DECLS
>
> CoglBool
> -_cogl_check_extension (const char *name, const char *ext);
> +_cogl_check_extension (const char *name, char * const *ext);
>
> void
> _cogl_clear (const CoglColor *color, unsigned long buffers);
> diff --git a/cogl/cogl-renderer.c b/cogl/cogl-renderer.c
> index 8b4413e..2e2a3df 100644
> --- a/cogl/cogl-renderer.c
> +++ b/cogl/cogl-renderer.c
> @@ -286,6 +286,15 @@ _cogl_renderer_choose_driver (CoglRenderer *renderer,
> libgl_name = COGL_GL_LIBNAME;
> goto found;
> }
> +
> + if (renderer->driver_override == COGL_DRIVER_GL3 ||
> + (renderer->driver_override == COGL_DRIVER_ANY &&
> + (driver_name == NULL || !g_ascii_strcasecmp (driver_name, "gl3"))))
> + {
> + renderer->driver = COGL_DRIVER_GL3;
> + libgl_name = COGL_GL_LIBNAME;
> + goto found;
> + }
> #endif
>
> #ifdef HAVE_COGL_GLES2
> @@ -340,6 +349,7 @@ found:
> #ifndef HAVE_DIRECTLY_LINKED_GL_LIBRARY
>
> if (renderer->driver == COGL_DRIVER_GL ||
> + renderer->driver == COGL_DRIVER_GL3 ||
> renderer->driver == COGL_DRIVER_GLES1 ||
> renderer->driver == COGL_DRIVER_GLES2)
> {
> @@ -362,6 +372,7 @@ found:
> {
> #ifdef HAVE_COGL_GL
> case COGL_DRIVER_GL:
> + case COGL_DRIVER_GL3:
> renderer->driver_vtable = &_cogl_driver_gl;
> renderer->texture_driver = &_cogl_texture_driver_gl;
> break;
> @@ -579,7 +590,7 @@ cogl_renderer_get_n_fragment_texture_units (CoglRenderer *renderer)
> _COGL_GET_CONTEXT (ctx, 0);
>
> #if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES2)
> - if (ctx->driver == COGL_DRIVER_GL || ctx->driver == COGL_DRIVER_GLES2)
> + if (cogl_has_feature (ctx, COGL_FEATURE_ID_GLSL))
> GE (ctx, glGetIntegerv (GL_MAX_TEXTURE_IMAGE_UNITS, &n));
> #endif
>
> diff --git a/cogl/cogl-renderer.h b/cogl/cogl-renderer.h
> index e00e682..ebb055e 100644
> --- a/cogl/cogl-renderer.h
> +++ b/cogl/cogl-renderer.h
> @@ -330,6 +330,7 @@ cogl_renderer_remove_constraint (CoglRenderer *renderer,
> * @COGL_DRIVER_ANY: Implies no preference for which driver is used
> * @COGL_DRIVER_NOP: A No-Op driver.
> * @COGL_DRIVER_GL: An OpenGL driver.
> + * @COGL_DRIVER_GL3: An OpenGL driver using the core GL 3.1 profile
> * @COGL_DRIVER_GLES1: An OpenGL ES 1.1 driver.
> * @COGL_DRIVER_GLES2: An OpenGL ES 2.0 driver.
> *
> @@ -344,6 +345,7 @@ typedef enum
> COGL_DRIVER_ANY,
> COGL_DRIVER_NOP,
> COGL_DRIVER_GL,
> + COGL_DRIVER_GL3,
> COGL_DRIVER_GLES1,
> COGL_DRIVER_GLES2
> } CoglDriver;
> diff --git a/cogl/cogl-texture.c b/cogl/cogl-texture.c
> index 2d54216..12be86e 100644
> --- a/cogl/cogl-texture.c
> +++ b/cogl/cogl-texture.c
> @@ -176,7 +176,7 @@ _cogl_texture_prepare_for_upload (CoglBitmap *src_bmp,
> limited number of formats so we must convert using the Cogl
> bitmap code instead */
>
> - if (ctx->driver == COGL_DRIVER_GL)
> + if ((ctx->private_feature_flags & COGL_PRIVATE_FEATURE_FORMAT_CONVERSION))
> {
> /* If the source format does not have the same premult flag as the
> dst format then we need to copy and convert it */
> diff --git a/cogl/cogl.c b/cogl/cogl.c
> index ff9f66f..62d511e 100644
> --- a/cogl/cogl.c
> +++ b/cogl/cogl.c
> @@ -90,26 +90,13 @@ _cogl_gl_error_to_string (GLenum error_code)
> #endif /* COGL_GL_DEBUG */
>
> CoglBool
> -_cogl_check_extension (const char *name, const gchar *ext)
> +_cogl_check_extension (const char *name, char * const *ext)
> {
> - char *end;
> - int name_len, n;
> -
> - if (name == NULL || ext == NULL)
> - return FALSE;
> -
> - end = (char*)(ext + strlen(ext));
> -
> - name_len = strlen(name);
> -
> - while (ext < end)
> - {
> - n = strcspn(ext, " ");
> -
> - if ((name_len == n) && (!strncmp(name, ext, n)))
> - return TRUE;
> - ext += (n + 1);
> - }
> + while (*ext)
> + if (!strcmp (name, *ext))
> + return TRUE;
> + else
> + ext++;
>
> return FALSE;
> }
> diff --git a/cogl/driver/gl/cogl-attribute-gl.c b/cogl/driver/gl/cogl-attribute-gl.c
> index c85b179..af89380 100644
> --- a/cogl/driver/gl/cogl-attribute-gl.c
> +++ b/cogl/driver/gl/cogl-attribute-gl.c
> @@ -54,8 +54,8 @@ toggle_builtin_attribute_enabled_cb (int bit_num, void *user_data)
> ForeachChangedBitState *state = user_data;
> CoglContext *context = state->context;
>
> - _COGL_RETURN_VAL_IF_FAIL (context->driver == COGL_DRIVER_GL ||
> - context->driver == COGL_DRIVER_GLES1,
> + _COGL_RETURN_VAL_IF_FAIL ((context->private_feature_flags &
> + COGL_PRIVATE_FEATURE_FIXED_FUNCTION),
> FALSE);
>
> #if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES)
> @@ -91,8 +91,8 @@ toggle_texcood_attribute_enabled_cb (int bit_num, void *user_data)
> ForeachChangedBitState *state = user_data;
> CoglContext *context = state->context;
>
> - _COGL_RETURN_VAL_IF_FAIL (context->driver == COGL_DRIVER_GL ||
> - context->driver == COGL_DRIVER_GLES1,
> + _COGL_RETURN_VAL_IF_FAIL ((context->private_feature_flags &
> + COGL_PRIVATE_FEATURE_FIXED_FUNCTION),
> FALSE);
>
> #if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES)
> diff --git a/cogl/driver/gl/cogl-clip-stack-gl.c b/cogl/driver/gl/cogl-clip-stack-gl.c
> index 933b943..9b9475e 100644
> --- a/cogl/driver/gl/cogl-clip-stack-gl.c
> +++ b/cogl/driver/gl/cogl-clip-stack-gl.c
> @@ -122,6 +122,7 @@ set_clip_plane (CoglFramebuffer *framebuffer,
> break;
>
> case COGL_DRIVER_GL:
> + case COGL_DRIVER_GL3:
> planed[0] = planef[0];
> planed[1] = planef[1];
> planed[2] = planef[2];
> diff --git a/cogl/driver/gl/cogl-framebuffer-gl.c b/cogl/driver/gl/cogl-framebuffer-gl.c
> index f2c22b2..4a6f62a 100644
> --- a/cogl/driver/gl/cogl-framebuffer-gl.c
> +++ b/cogl/driver/gl/cogl-framebuffer-gl.c
> @@ -896,8 +896,8 @@ _cogl_framebuffer_init_bits (CoglFramebuffer *framebuffer)
> return;
>
> #ifdef HAVE_COGL_GL
> - if (ctx->driver == COGL_DRIVER_GL &&
> - cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN) &&
> + if ((ctx->private_feature_flags &
> + COGL_PRIVATE_FEATURE_QUERY_FRAMEBUFFER_BITS) &&
> framebuffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN)
> {
> GLenum attachment, pname;
> diff --git a/cogl/driver/gl/cogl-pipeline-fragend-glsl.c b/cogl/driver/gl/cogl-pipeline-fragend-glsl.c
> index 6d743b1..622e4be 100644
> --- a/cogl/driver/gl/cogl-pipeline-fragend-glsl.c
> +++ b/cogl/driver/gl/cogl-pipeline-fragend-glsl.c
> @@ -873,10 +873,10 @@ _cogl_pipeline_fragend_glsl_add_layer (CoglPipeline *pipeline,
> return TRUE;
> }
>
> -/* GLES2 doesn't have alpha testing so we need to implement it in the
> - shader */
> +/* GLES2 and GL3 don't have alpha testing so we need to implement it
> + in the shader */
>
> -#ifdef HAVE_COGL_GLES2
> +#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL)
>
> static void
> add_alpha_test_snippet (CoglPipeline *pipeline,
> @@ -1011,8 +1011,8 @@ _cogl_pipeline_fragend_glsl_end (CoglPipeline *pipeline,
> g_string_append (shader_state->source,
> " cogl_color_out = cogl_color_in;\n");
>
> -#ifdef HAVE_COGL_GLES2
> - if (ctx->driver == COGL_DRIVER_GLES2)
> +#if defined(HAVE_COGL_GLES2) || defined (HAVE_COGL_GL)
> + if (!(ctx->private_feature_flags & COGL_PRIVATE_FEATURE_ALPHA_TEST))
> add_alpha_test_snippet (pipeline, shader_state);
> #endif
>
> @@ -1037,10 +1037,9 @@ _cogl_pipeline_fragend_glsl_end (CoglPipeline *pipeline,
> source_strings[1] = shader_state->source->str;
>
> if (shader_state->ref_point_coord &&
> - ctx->driver == COGL_DRIVER_GL)
> - {
> - version_string = "#version 120\n";
> - }
> + (ctx->driver == COGL_DRIVER_GL ||
> + ctx->driver == COGL_DRIVER_GL3))
> + version_string = "#version 120\n";
> else
> version_string = NULL;
>
> diff --git a/cogl/driver/gl/cogl-pipeline-opengl.c b/cogl/driver/gl/cogl-pipeline-opengl.c
> index 83dc197..fe4558b 100644
> --- a/cogl/driver/gl/cogl-pipeline-opengl.c
> +++ b/cogl/driver/gl/cogl-pipeline-opengl.c
> @@ -452,7 +452,7 @@ _cogl_pipeline_flush_color_blend_alpha_depth_state (
> _COGL_GET_CONTEXT (ctx, NO_RETVAL);
>
> /* On GLES2 we'll flush the color later */
> - if (ctx->driver != COGL_DRIVER_GLES2 &&
> + if ((ctx->private_feature_flags & COGL_PRIVATE_FEATURE_FIXED_FUNCTION) &&
> !skip_gl_color)
> {
> if ((pipelines_difference & COGL_PIPELINE_STATE_COLOR) ||
> @@ -531,7 +531,7 @@ _cogl_pipeline_flush_color_blend_alpha_depth_state (
>
> #if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES)
>
> - if (ctx->driver != COGL_DRIVER_GLES2)
> + if ((ctx->private_feature_flags & COGL_PRIVATE_FEATURE_ALPHA_TEST))
> {
> /* Under GLES2 the alpha function is implemented as part of the
> fragment shader */
> @@ -653,7 +653,8 @@ get_max_activateable_texture_units (void)
> int i;
>
> #ifdef HAVE_COGL_GL
> - if (ctx->driver == COGL_DRIVER_GL)
> + if (ctx->driver == COGL_DRIVER_GL ||
> + ctx->driver == COGL_DRIVER_GL3)
> {
> /* GL_MAX_TEXTURE_COORDS is provided for both GLSL and ARBfp. It
> defines the number of texture coordinates that can be
> @@ -834,7 +835,7 @@ flush_layers_common_gl_state_cb (CoglPipelineLayer *layer, void *user_data)
> * glsl progend.
> */
> #if defined (HAVE_COGL_GLES) || defined (HAVE_COGL_GL)
> - if (ctx->driver != COGL_DRIVER_GLES2 &&
> + if ((ctx->private_feature_flags & COGL_PRIVATE_FEATURE_FIXED_FUNCTION) &&
> (layers_difference & COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS))
> {
> CoglPipelineState change = COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS;
> diff --git a/cogl/driver/gl/cogl-pipeline-progend-fixed.c b/cogl/driver/gl/cogl-pipeline-progend-fixed.c
> index ee0d699..5a62a28 100644
> --- a/cogl/driver/gl/cogl-pipeline-progend-fixed.c
> +++ b/cogl/driver/gl/cogl-pipeline-progend-fixed.c
> @@ -48,7 +48,7 @@ _cogl_pipeline_progend_fixed_start (CoglPipeline *pipeline)
> if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_FIXED)))
> return FALSE;
>
> - if (ctx->driver == COGL_DRIVER_GLES2)
> + if (!(ctx->private_feature_flags & COGL_PRIVATE_FEATURE_FIXED_FUNCTION))
> return FALSE;
>
> /* Vertex snippets are only supported in the GLSL fragend */
> diff --git a/cogl/driver/gl/cogl-pipeline-vertend-glsl.c b/cogl/driver/gl/cogl-pipeline-vertend-glsl.c
> index e702e22..6387473 100644
> --- a/cogl/driver/gl/cogl-pipeline-vertend-glsl.c
> +++ b/cogl/driver/gl/cogl-pipeline-vertend-glsl.c
> @@ -223,7 +223,8 @@ _cogl_pipeline_vertend_glsl_start (CoglPipeline *pipeline,
> "cogl_generated_source ()\n"
> "{\n");
>
> - if (ctx->driver == COGL_DRIVER_GLES2)
> + if (!(ctx->private_feature_flags &
> + COGL_PRIVATE_FEATURE_BUILTIN_POINT_SIZE_UNIFORM))
> /* There is no builtin uniform for the pointsize on GLES2 so we need
> to copy it from the custom uniform in the vertex shader */
> g_string_append (shader_state->source,
> @@ -429,7 +430,8 @@ _cogl_pipeline_vertend_glsl_end (CoglPipeline *pipeline,
> shader_state->gl_shader = shader;
> }
>
> - if (ctx->driver == COGL_DRIVER_GL &&
> + if ((ctx->private_feature_flags &
> + COGL_PRIVATE_FEATURE_BUILTIN_POINT_SIZE_UNIFORM) &&
> (pipelines_difference & COGL_PIPELINE_STATE_POINT_SIZE))
> {
> CoglPipeline *authority =
> diff --git a/cogl/driver/gl/cogl-texture-2d-gl.c b/cogl/driver/gl/cogl-texture-2d-gl.c
> index 52169ec..ecb3d1e 100644
> --- a/cogl/driver/gl/cogl-texture-2d-gl.c
> +++ b/cogl/driver/gl/cogl-texture-2d-gl.c
> @@ -323,7 +323,8 @@ cogl_texture_2d_gl_new_from_foreign (CoglContext *ctx,
> (only level 0 we are interested in) */
>
> #if HAVE_COGL_GL
> - if (ctx->driver == COGL_DRIVER_GL)
> + if ((ctx->private_feature_flags &
> + COGL_PRIVATE_FEATURE_QUERY_TEXTURE_PARAMETERS))
> {
> GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_2D, 0,
> GL_TEXTURE_COMPRESSED,
> diff --git a/cogl/driver/gl/gl/cogl-driver-gl.c b/cogl/driver/gl/gl/cogl-driver-gl.c
> index d49040f..4b961b7 100644
> --- a/cogl/driver/gl/gl/cogl-driver-gl.c
> +++ b/cogl/driver/gl/gl/cogl-driver-gl.c
> @@ -290,10 +290,10 @@ _cogl_get_gl_version (CoglContext *ctx,
>
> static CoglBool
> check_gl_version (CoglContext *ctx,
> + char **gl_extensions,
> CoglError **error)
> {
> int major, minor;
> - const char *gl_extensions;
>
> if (!_cogl_get_gl_version (ctx, &major, &minor))
> {
> @@ -308,8 +308,6 @@ check_gl_version (CoglContext *ctx,
> if (COGL_CHECK_GL_VERSION (major, minor, 1, 3))
> return TRUE;
>
> - gl_extensions = _cogl_context_get_gl_extensions (ctx);
> -
> /* OpenGL 1.2 is only supported if we have the multitexturing
> extension */
> if (!_cogl_check_extension ("GL_ARB_multitexture", gl_extensions))
> @@ -342,32 +340,49 @@ _cogl_driver_update_features (CoglContext *ctx,
> CoglError **error)
> {
> CoglPrivateFeatureFlags private_flags = 0;
> - const char *gl_extensions;
> + char **gl_extensions;
> int max_clip_planes = 0;
> int num_stencil_bits = 0;
> int gl_major = 0, gl_minor = 0;
>
> - /* We have to special case getting the pointer to the glGetString
> - function because we need to use it to determine what functions we
> - can expect */
> + /* We have to special case getting the pointer to the glGetString*
> + functions because we need to use them to determine what functions
> + we can expect */
> ctx->glGetString =
> (void *) _cogl_renderer_get_proc_address (ctx->display->renderer,
> "glGetString",
> TRUE);
> + ctx->glGetStringi =
> + (void *) _cogl_renderer_get_proc_address (ctx->display->renderer,
> + "glGetStringi",
> + TRUE);
> + ctx->glGetIntegerv =
> + (void *) _cogl_renderer_get_proc_address (ctx->display->renderer,
> + "glGetIntegerv",
> + TRUE);
> +
> + gl_extensions = _cogl_context_get_gl_extensions (ctx);
>
> - if (!check_gl_version (ctx, error))
> + if (!check_gl_version (ctx, gl_extensions, error))
> return FALSE;
>
> - COGL_NOTE (WINSYS,
> - "Checking features\n"
> - " GL_VENDOR: %s\n"
> - " GL_RENDERER: %s\n"
> - " GL_VERSION: %s\n"
> - " GL_EXTENSIONS: %s",
> - ctx->glGetString (GL_VENDOR),
> - ctx->glGetString (GL_RENDERER),
> - _cogl_context_get_gl_version (ctx),
> - _cogl_context_get_gl_extensions (ctx));
> + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_WINSYS)))
> + {
> + char *all_extensions = g_strjoinv (" ", gl_extensions);
> +
> + COGL_NOTE (WINSYS,
> + "Checking features\n"
> + " GL_VENDOR: %s\n"
> + " GL_RENDERER: %s\n"
> + " GL_VERSION: %s\n"
> + " GL_EXTENSIONS: %s",
> + ctx->glGetString (GL_VENDOR),
> + ctx->glGetString (GL_RENDERER),
> + _cogl_context_get_gl_version (ctx),
> + all_extensions);
> +
> + g_free (all_extensions);
> + }
>
> _cogl_get_gl_version (ctx, &gl_major, &gl_minor);
>
> @@ -390,8 +405,6 @@ _cogl_driver_update_features (CoglContext *ctx,
> if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 1, 4))
> COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_MIRRORED_REPEAT, TRUE);
>
> - gl_extensions = _cogl_context_get_gl_extensions (ctx);
> -
> _cogl_feature_check_ext_functions (ctx,
> gl_major,
> gl_minor,
> @@ -422,7 +435,10 @@ _cogl_driver_update_features (CoglContext *ctx,
> private_flags |= COGL_PRIVATE_FEATURE_FOUR_CLIP_PLANES;
>
> if (ctx->glGenRenderbuffers)
> - COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_OFFSCREEN, TRUE);
> + {
> + COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_OFFSCREEN, TRUE);
> + private_flags |= COGL_PRIVATE_FEATURE_QUERY_FRAMEBUFFER_BITS;
> + }
>
> if (ctx->glBlitFramebuffer)
> private_flags |= COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT;
> @@ -439,6 +455,10 @@ _cogl_driver_update_features (CoglContext *ctx,
> _cogl_check_extension ("GL_EXT_pixel_buffer_object", gl_extensions))
> private_flags |= COGL_PRIVATE_FEATURE_PBOS;
>
> + if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 1, 4) ||
> + _cogl_check_extension ("GL_EXT_blend_color", gl_extensions))
> + private_flags |= COGL_PRIVATE_FEATURE_BLEND_CONSTANT;
> +
> if (ctx->glGenPrograms)
> COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_ARBFP, TRUE);
>
> @@ -512,9 +532,24 @@ _cogl_driver_update_features (CoglContext *ctx,
> if (ctx->glGenSamplers)
> private_flags |= COGL_PRIVATE_FEATURE_SAMPLER_OBJECTS;
>
> + if (ctx->driver == COGL_DRIVER_GL)
> + /* Features which are not available in GL 3 */
> + private_flags |= (COGL_PRIVATE_FEATURE_FIXED_FUNCTION |
> + COGL_PRIVATE_FEATURE_ALPHA_TEST |
> + COGL_PRIVATE_FEATURE_QUADS);
> +
> + private_flags |= (COGL_PRIVATE_FEATURE_READ_PIXELS_ANY_FORMAT |
> + COGL_PRIVATE_FEATURE_ANY_GL |
> + COGL_PRIVATE_FEATURE_FORMAT_CONVERSION |
> + COGL_PRIVATE_FEATURE_BLEND_CONSTANT |
> + COGL_PRIVATE_FEATURE_BUILTIN_POINT_SIZE_UNIFORM |
> + COGL_PRIVATE_FEATURE_QUERY_TEXTURE_PARAMETERS);
> +
> /* Cache features */
> ctx->private_feature_flags |= private_flags;
>
> + g_strfreev (gl_extensions);
> +
> return TRUE;
> }
>
> diff --git a/cogl/driver/gl/gl/cogl-pipeline-progend-fixed-arbfp.c b/cogl/driver/gl/gl/cogl-pipeline-progend-fixed-arbfp.c
> index 24782e7..31e715b 100644
> --- a/cogl/driver/gl/gl/cogl-pipeline-progend-fixed-arbfp.c
> +++ b/cogl/driver/gl/gl/cogl-pipeline-progend-fixed-arbfp.c
> @@ -48,7 +48,7 @@ _cogl_pipeline_progend_fixed_arbfp_start (CoglPipeline *pipeline)
> if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_FIXED)))
> return FALSE;
>
> - if (ctx->driver == COGL_DRIVER_GLES2)
> + if (!(ctx->private_feature_flags & COGL_PRIVATE_FEATURE_FIXED_FUNCTION))
> return FALSE;
>
> /* Vertex snippets are only supported in the GLSL fragend */
> diff --git a/cogl/driver/gl/gles/cogl-driver-gles.c b/cogl/driver/gl/gles/cogl-driver-gles.c
> index 08d1a79..c38f090 100644
> --- a/cogl/driver/gl/gles/cogl-driver-gles.c
> +++ b/cogl/driver/gl/gles/cogl-driver-gles.c
> @@ -190,7 +190,7 @@ _cogl_driver_update_features (CoglContext *context,
> CoglError **error)
> {
> CoglPrivateFeatureFlags private_flags = 0;
> - const char *gl_extensions;
> + char **gl_extensions;
> int num_stencil_bits = 0;
>
> /* We have to special case getting the pointer to the glGetString
> @@ -201,23 +201,30 @@ _cogl_driver_update_features (CoglContext *context,
> "glGetString",
> TRUE);
>
> - COGL_NOTE (WINSYS,
> - "Checking features\n"
> - " GL_VENDOR: %s\n"
> - " GL_RENDERER: %s\n"
> - " GL_VERSION: %s\n"
> - " GL_EXTENSIONS: %s",
> - context->glGetString (GL_VENDOR),
> - context->glGetString (GL_RENDERER),
> - _cogl_context_get_gl_version (context),
> - _cogl_context_get_gl_extensions (context));
> + gl_extensions = _cogl_context_get_gl_extensions (context);
>
> - _cogl_gpu_info_init (context, &context->gpu);
> + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_WINSYS)))
> + {
> + char *all_extensions = g_strjoinv (" ", gl_extensions);
> +
> + COGL_NOTE (WINSYS,
> + "Checking features\n"
> + " GL_VENDOR: %s\n"
> + " GL_RENDERER: %s\n"
> + " GL_VERSION: %s\n"
> + " GL_EXTENSIONS: %s",
> + context->glGetString (GL_VENDOR),
> + context->glGetString (GL_RENDERER),
> + _cogl_context_get_gl_version (context),
> + all_extensions);
> +
> + g_free (all_extensions);
> + }
>
> context->glsl_major = 1;
> context->glsl_minor = 0;
>
> - gl_extensions = _cogl_context_get_gl_extensions (context);
> + _cogl_gpu_info_init (context, &context->gpu);
>
> _cogl_feature_check_ext_functions (context,
> -1 /* GL major version */,
> @@ -250,9 +257,16 @@ _cogl_driver_update_features (CoglContext *context,
> COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_DEPTH_RANGE, TRUE);
> COGL_FLAGS_SET (context->features,
> COGL_FEATURE_ID_MIRRORED_REPEAT, TRUE);
> +
> + private_flags |= COGL_PRIVATE_FEATURE_BLEND_CONSTANT;
> }
> + else if (context->driver == COGL_DRIVER_GLES1)
> + private_flags |= (COGL_PRIVATE_FEATURE_FIXED_FUNCTION |
> + COGL_PRIVATE_FEATURE_ALPHA_TEST |
> + COGL_PRIVATE_FEATURE_BUILTIN_POINT_SIZE_UNIFORM);
>
> - private_flags |= COGL_PRIVATE_FEATURE_VBOS;
> + private_flags |= (COGL_PRIVATE_FEATURE_VBOS |
> + COGL_PRIVATE_FEATURE_ANY_GL);
>
> /* Both GLES 1.1 and GLES 2.0 support point sprites in core */
> COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_POINT_SPRITE, TRUE);
> @@ -313,6 +327,8 @@ _cogl_driver_update_features (CoglContext *context,
> /* Cache features */
> context->private_feature_flags |= private_flags;
>
> + g_strfreev (gl_extensions);
> +
> return TRUE;
> }
>
> diff --git a/cogl/gl-prototypes/cogl-all-functions.h b/cogl/gl-prototypes/cogl-all-functions.h
> index 1fa475f..eeef4e7 100644
> --- a/cogl/gl-prototypes/cogl-all-functions.h
> +++ b/cogl/gl-prototypes/cogl-all-functions.h
> @@ -128,7 +128,7 @@ COGL_EXT_END ()
>
>
>
> -COGL_EXT_BEGIN (offscreen_blit, 255, 255,
> +COGL_EXT_BEGIN (offscreen_blit, 3, 0,
> 0, /* not in either GLES */
> "EXT\0ANGLE\0",
> "framebuffer_blit\0")
> @@ -211,7 +211,7 @@ COGL_EXT_FUNCTION (void, glFramebufferTexture2DMultisampleIMG,
> GLsizei samples))
> COGL_EXT_END ()
>
> -COGL_EXT_BEGIN (ARB_sampler_objects, 255, 255,
> +COGL_EXT_BEGIN (ARB_sampler_objects, 3, 3,
> 0, /* not in either GLES */
> "ARB:\0",
> "sampler_objects\0")
> @@ -264,3 +264,25 @@ COGL_EXT_FUNCTION (void, glGetAttachedObjects,
> GLsizei* count,
> GLuint* shaders))
> COGL_EXT_END ()
> +
> +COGL_EXT_BEGIN (only_gl3, 3, 0,
> + 0, /* not in either GLES */
> + "\0",
> + "\0")
> +COGL_EXT_FUNCTION (const GLubyte *, glGetStringi,
> + (GLenum name, GLuint index))
> +COGL_EXT_END ()
> +
> +COGL_EXT_BEGIN (vertex_array_object, 3, 0,
> + 0, /* not in either GLES */
> + "ARB\0OES\0",
> + "vertex_array_object\0")
> +COGL_EXT_FUNCTION (void, glBindVertexArray,
> + (GLuint array))
> +COGL_EXT_FUNCTION (void, glDeleteVertexArrays,
> + (GLsizei n,
> + const GLuint *arrays))
> +COGL_EXT_FUNCTION (void, glGenVertexArrays,
> + (GLsizei n,
> + GLuint *arrays))
> +COGL_EXT_END ()
> diff --git a/cogl/gl-prototypes/cogl-in-gles-core-functions.h b/cogl/gl-prototypes/cogl-in-gles-core-functions.h
> index 78dec26..9c8102f 100644
> --- a/cogl/gl-prototypes/cogl-in-gles-core-functions.h
> +++ b/cogl/gl-prototypes/cogl-in-gles-core-functions.h
> @@ -50,11 +50,11 @@
> */
>
> COGL_EXT_BEGIN (only_in_both_gles,
> - 255, 255,
> + 4, 1,
> COGL_EXT_IN_GLES |
> COGL_EXT_IN_GLES2,
> - "\0",
> - "\0")
> + "ARB\0",
> + "ES2_compatibility\0")
> COGL_EXT_FUNCTION (void, glDepthRangef,
> (GLfloat near_val, GLfloat far_val))
> COGL_EXT_FUNCTION (void, glClearDepthf,
> diff --git a/cogl/gl-prototypes/cogl-in-gles2-core-functions.h b/cogl/gl-prototypes/cogl-in-gles2-core-functions.h
> index f39bd27..6130576 100644
> --- a/cogl/gl-prototypes/cogl-in-gles2-core-functions.h
> +++ b/cogl/gl-prototypes/cogl-in-gles2-core-functions.h
> @@ -50,7 +50,7 @@
> */
>
> COGL_EXT_BEGIN (offscreen,
> - 255, 255,
> + 3, 0,
> COGL_EXT_IN_GLES2,
> /* for some reason the ARB version of this
> extension doesn't have an ARB suffix for the
> @@ -146,10 +146,10 @@ COGL_EXT_FUNCTION (void, glBlendEquationSeparate,
> COGL_EXT_END ()
>
> COGL_EXT_BEGIN (gles2_only_api,
> - 255, 255,
> + 4, 1,
> COGL_EXT_IN_GLES2,
> - "\0",
> - "\0")
> + "ARB:\0",
> + "ES2_compatibility\0")
> COGL_EXT_FUNCTION (void, glReleaseShaderCompiler, (void))
> COGL_EXT_FUNCTION (void, glGetShaderPrecisionFormat,
> (GLenum shadertype,
> diff --git a/cogl/winsys/cogl-winsys-egl-feature-functions.h b/cogl/winsys/cogl-winsys-egl-feature-functions.h
> index 9c8dcca..9016f8d 100644
> --- a/cogl/winsys/cogl-winsys-egl-feature-functions.h
> +++ b/cogl/winsys/cogl-winsys-egl-feature-functions.h
> @@ -87,4 +87,11 @@ COGL_WINSYS_FEATURE_FUNCTION (EGLBoolean, eglUnbindWaylandDisplay,
> (EGLDisplay dpy,
> struct wl_display *wayland_display))
> COGL_WINSYS_FEATURE_END ()
> +
> +COGL_WINSYS_FEATURE_BEGIN (create_context,
> + "KHR\0",
> + "create_context\0",
> + COGL_EGL_WINSYS_FEATURE_CREATE_CONTEXT)
> +COGL_WINSYS_FEATURE_END ()
> +
> #endif
> diff --git a/cogl/winsys/cogl-winsys-egl-private.h b/cogl/winsys/cogl-winsys-egl-private.h
> index f1e5361..13ce9a4 100644
> --- a/cogl/winsys/cogl-winsys-egl-private.h
> +++ b/cogl/winsys/cogl-winsys-egl-private.h
> @@ -68,7 +68,8 @@ typedef enum _CoglEGLWinsysFeature
> {
> COGL_EGL_WINSYS_FEATURE_SWAP_REGION =1L<<0,
> COGL_EGL_WINSYS_FEATURE_EGL_IMAGE_FROM_X11_PIXMAP =1L<<1,
> - COGL_EGL_WINSYS_FEATURE_EGL_IMAGE_FROM_WAYLAND_BUFFER =1L<<2
> + COGL_EGL_WINSYS_FEATURE_EGL_IMAGE_FROM_WAYLAND_BUFFER =1L<<2,
> + COGL_EGL_WINSYS_FEATURE_CREATE_CONTEXT =1L<<3
> } CoglEGLWinsysFeature;
>
> typedef struct _CoglRendererEGL
> diff --git a/cogl/winsys/cogl-winsys-egl.c b/cogl/winsys/cogl-winsys-egl.c
> index ae46e61..2ff7687 100644
> --- a/cogl/winsys/cogl-winsys-egl.c
> +++ b/cogl/winsys/cogl-winsys-egl.c
> @@ -148,9 +148,11 @@ check_egl_extensions (CoglRenderer *renderer)
> {
> CoglRendererEGL *egl_renderer = renderer->winsys;
> const char *egl_extensions;
> + char **split_extensions;
> int i;
>
> egl_extensions = eglQueryString (egl_renderer->edpy, EGL_EXTENSIONS);
> + split_extensions = g_strsplit (egl_extensions, " ", 0 /* max_tokens */);
>
> COGL_NOTE (WINSYS, " EGL Extensions: %s", egl_extensions);
>
> @@ -159,12 +161,14 @@ check_egl_extensions (CoglRenderer *renderer)
> if (_cogl_feature_check (renderer,
> "EGL", winsys_feature_data + i, 0, 0,
> COGL_DRIVER_GL, /* the driver isn't used */
> - egl_extensions,
> + split_extensions,
> egl_renderer))
> {
> egl_renderer->private_features |=
> winsys_feature_data[i].feature_flags_private;
> }
> +
> + g_strfreev (split_extensions);
> }
>
> CoglBool
> @@ -234,11 +238,12 @@ egl_attributes_from_framebuffer_config (CoglDisplay *display,
> attributes[i++] = EGL_DONT_CARE;
>
> attributes[i++] = EGL_RENDERABLE_TYPE;
> - attributes[i++] = (renderer->driver == COGL_DRIVER_GL ?
> - EGL_OPENGL_BIT :
> - renderer->driver == COGL_DRIVER_GLES1 ?
> - EGL_OPENGL_ES_BIT :
> - EGL_OPENGL_ES2_BIT);
> + attributes[i++] = ((renderer->driver == COGL_DRIVER_GL ||
> + renderer->driver == COGL_DRIVER_GL3) ?
> + EGL_OPENGL_BIT :
> + renderer->driver == COGL_DRIVER_GLES1 ?
> + EGL_OPENGL_ES_BIT :
> + EGL_OPENGL_ES2_BIT);
>
> attributes[i++] = EGL_SURFACE_TYPE;
> attributes[i++] = EGL_WINDOW_BIT;
> @@ -314,24 +319,16 @@ try_create_context (CoglDisplay *display,
> EGLConfig config;
> EGLint config_count = 0;
> EGLBoolean status;
> - EGLint attribs[3];
> + EGLint attribs[9];
> EGLint cfg_attribs[MAX_EGL_CONFIG_ATTRIBS];
> const char *error_message;
>
> _COGL_RETURN_VAL_IF_FAIL (egl_display->egl_context == NULL, TRUE);
>
> - if (renderer->driver == COGL_DRIVER_GL)
> + if (renderer->driver == COGL_DRIVER_GL ||
> + renderer->driver == COGL_DRIVER_GL3)
> eglBindAPI (EGL_OPENGL_API);
>
> - if (display->renderer->driver == COGL_DRIVER_GLES2)
> - {
> - attribs[0] = EGL_CONTEXT_CLIENT_VERSION;
> - attribs[1] = 2;
> - attribs[2] = EGL_NONE;
> - }
> - else
> - attribs[0] = EGL_NONE;
> -
> egl_attributes_from_framebuffer_config (display,
> &display->onscreen_template->config,
> cfg_attribs);
> @@ -350,10 +347,40 @@ try_create_context (CoglDisplay *display,
>
> egl_display->egl_config = config;
>
> + if (display->renderer->driver == COGL_DRIVER_GL3)
> + {
> + if (!(egl_renderer->private_features &
> + COGL_EGL_WINSYS_FEATURE_CREATE_CONTEXT))
> + {
> + error_message = "Driver does not support GL 3 contexts";
> + goto fail;
> + }
> +
> + /* Try to get a core profile 3.1 context with no deprecated features */
> + attribs[0] = EGL_CONTEXT_MAJOR_VERSION_KHR;
> + attribs[1] = 3;
> + attribs[2] = EGL_CONTEXT_MINOR_VERSION_KHR;
> + attribs[3] = 1;
> + attribs[4] = EGL_CONTEXT_FLAGS_KHR;
> + attribs[5] = EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
> + attribs[6] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR;
> + attribs[7] = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
> + attribs[8] = EGL_NONE;
> + }
> + else if (display->renderer->driver == COGL_DRIVER_GLES2)
> + {
> + attribs[0] = EGL_CONTEXT_CLIENT_VERSION;
> + attribs[1] = 2;
> + attribs[2] = EGL_NONE;
> + }
> + else
> + attribs[0] = EGL_NONE;
> +
> egl_display->egl_context = eglCreateContext (edpy,
> config,
> EGL_NO_CONTEXT,
> attribs);
> +
> if (egl_display->egl_context == EGL_NO_CONTEXT)
> {
> error_message = "Unable to create a suitable EGL context";
> diff --git a/cogl/winsys/cogl-winsys-glx-feature-functions.h b/cogl/winsys/cogl-winsys-glx-feature-functions.h
> index c20f925..0450728 100644
> --- a/cogl/winsys/cogl-winsys-glx-feature-functions.h
> +++ b/cogl/winsys/cogl-winsys-glx-feature-functions.h
> @@ -105,3 +105,16 @@ COGL_WINSYS_FEATURE_BEGIN (swap_event,
> 0,
> COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT)
> COGL_WINSYS_FEATURE_END ()
> +
> +COGL_WINSYS_FEATURE_BEGIN (create_context,
> + "ARB\0",
> + "create_context",
> + 0,
> + 0)
> +COGL_WINSYS_FEATURE_FUNCTION (GLXContext, glXCreateContextAttribs,
> + (Display *dpy,
> + GLXFBConfig config,
> + GLXContext share_context,
> + Bool direct,
> + const int *attrib_list))
> +COGL_WINSYS_FEATURE_END ()
> diff --git a/cogl/winsys/cogl-winsys-glx.c b/cogl/winsys/cogl-winsys-glx.c
> index ff9b1fd..29d8cc9 100644
> --- a/cogl/winsys/cogl-winsys-glx.c
> +++ b/cogl/winsys/cogl-winsys-glx.c
> @@ -331,7 +331,8 @@ _cogl_winsys_renderer_connect (CoglRenderer *renderer,
> if (!_cogl_xlib_renderer_connect (renderer, error))
> goto error;
>
> - if (renderer->driver != COGL_DRIVER_GL)
> + if (renderer->driver != COGL_DRIVER_GL &&
> + renderer->driver != COGL_DRIVER_GL3)
> {
> _cogl_set_error (error, COGL_WINSYS_ERROR,
> COGL_WINSYS_ERROR_INIT,
> @@ -394,6 +395,7 @@ update_winsys_features (CoglContext *context, CoglError **error)
> _cogl_xlib_renderer_get_data (context->display->renderer);
> CoglGLXRenderer *glx_renderer = context->display->renderer->winsys;
> const char *glx_extensions;
> + char **split_extensions;
> int default_screen;
> int i;
>
> @@ -417,11 +419,13 @@ update_winsys_features (CoglContext *context, CoglError **error)
> COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN,
> TRUE);
>
> + split_extensions = g_strsplit (glx_extensions, " ", 0 /* max_tokens */);
> +
> for (i = 0; i < G_N_ELEMENTS (winsys_feature_data); i++)
> if (_cogl_feature_check (context->display->renderer,
> "GLX", winsys_feature_data + i, 0, 0,
> COGL_DRIVER_GL, /* the driver isn't used */
> - glx_extensions,
> + split_extensions,
> glx_renderer))
> {
> if (winsys_feature_data[i].winsys_feature)
> @@ -430,6 +434,8 @@ update_winsys_features (CoglContext *context, CoglError **error)
> TRUE);
> }
>
> + g_strfreev (split_extensions);
> +
> /* Note: the GLX_SGI_video_sync spec explicitly states this extension
> * only works for direct contexts. */
> if (!glx_renderer->is_direct)
> @@ -605,6 +611,36 @@ done:
> return ret;
> }
>
> +static GLXContext
> +create_gl3_context (CoglDisplay *display,
> + GLXFBConfig fb_config)
> +{
> + CoglXlibRenderer *xlib_renderer =
> + _cogl_xlib_renderer_get_data (display->renderer);
> + CoglGLXRenderer *glx_renderer = display->renderer->winsys;
> +
> + /* We want a core profile 3.1 context with no deprecated features */
> + static const int attrib_list[] =
> + {
> + GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
> + GLX_CONTEXT_MINOR_VERSION_ARB, 1,
> + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
> + GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
> + None
> + };
> +
> + /* Make sure that the display supports the GLX_ARB_create_context
> + extension */
> + if (glx_renderer->pf_glXCreateContextAttribs == NULL)
> + return NULL;
> +
> + return glx_renderer->pf_glXCreateContextAttribs (xlib_renderer->xdpy,
> + fb_config,
> + NULL /* share_context */,
> + True, /* direct */
> + attrib_list);
> +}
> +
> static CoglBool
> create_context (CoglDisplay *display, CoglError **error)
> {
> @@ -642,12 +678,16 @@ create_context (CoglDisplay *display, CoglError **error)
> COGL_NOTE (WINSYS, "Creating GLX Context (display: %p)",
> xlib_renderer->xdpy);
>
> - glx_display->glx_context =
> - glx_renderer->glXCreateNewContext (xlib_renderer->xdpy,
> - config,
> - GLX_RGBA_TYPE,
> - NULL,
> - True);
> + if (display->renderer->driver == COGL_DRIVER_GL3)
> + glx_display->glx_context = create_gl3_context (display, config);
> + else
> + glx_display->glx_context =
> + glx_renderer->glXCreateNewContext (xlib_renderer->xdpy,
> + config,
> + GLX_RGBA_TYPE,
> + NULL,
> + True);
> +
> if (glx_display->glx_context == NULL)
> {
> _cogl_set_error (error, COGL_WINSYS_ERROR,
> diff --git a/cogl/winsys/cogl-winsys-sdl.c b/cogl/winsys/cogl-winsys-sdl.c
> index 8def1a9..ccb0764 100644
> --- a/cogl/winsys/cogl-winsys-sdl.c
> +++ b/cogl/winsys/cogl-winsys-sdl.c
> @@ -161,6 +161,12 @@ _cogl_winsys_display_setup (CoglDisplay *display,
> sdl_display->video_mode_flags = SDL_OPENGL;
> break;
>
> + case COGL_DRIVER_GL3:
> + _cogl_set_error (error, COGL_WINSYS_ERROR,
> + COGL_WINSYS_ERROR_INIT,
> + "The SDL winsys does not support GL 3");
> + goto error;
> +
> #ifdef COGL_HAS_SDL_GLES_SUPPORT
> case COGL_DRIVER_GLES2:
> sdl_display->video_mode_flags = SDL_OPENGLES;
> diff --git a/cogl/winsys/cogl-winsys-sdl2.c b/cogl/winsys/cogl-winsys-sdl2.c
> index 390ab2b..3ebecf3 100644
> --- a/cogl/winsys/cogl-winsys-sdl2.c
> +++ b/cogl/winsys/cogl-winsys-sdl2.c
> @@ -156,6 +156,8 @@ _cogl_winsys_display_setup (CoglDisplay *display,
> SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 1);
> else if (display->renderer->driver == COGL_DRIVER_GLES2)
> SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 2);
> + else if (display->renderer->driver == COGL_DRIVER_GL3)
> + SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 3);
>
> /* Create a dummy 1x1 window that never gets display so that we can
> * create a GL context */
> @@ -194,6 +196,7 @@ _cogl_winsys_display_setup (CoglDisplay *display,
> switch (display->renderer->driver)
> {
> case COGL_DRIVER_GL:
> + case COGL_DRIVER_GL3:
> /* The first character of the version string will be a digit if
> * it's normal GL */
> if (!g_ascii_isdigit (gl_version[0]))
> @@ -203,6 +206,29 @@ _cogl_winsys_display_setup (CoglDisplay *display,
> "The GL driver was requested but SDL is using GLES");
> goto error;
> }
> +
> + if (gl_version[0] >= '3')
> + {
> + if (display->renderer->driver == COGL_DRIVER_GL)
> + {
> + _cogl_set_error (error, COGL_WINSYS_ERROR,
> + COGL_WINSYS_ERROR_INIT,
> + "The GL driver was requested but SDL is using "
> + "GL %c", gl_version[0]);
> + goto error;
> + }
> + }
> + else
> + {
> + if (display->renderer->driver == COGL_DRIVER_GL3)
> + {
> + _cogl_set_error (error, COGL_WINSYS_ERROR,
> + COGL_WINSYS_ERROR_INIT,
> + "The GL3 driver was requested but SDL is using "
> + "GL %c", gl_version[0]);
> + goto error;
> + }
> + }
> break;
>
> case COGL_DRIVER_GLES2:
> diff --git a/cogl/winsys/cogl-winsys-wgl.c b/cogl/winsys/cogl-winsys-wgl.c
> index 7e2dc5d..e6686d8 100644
> --- a/cogl/winsys/cogl-winsys-wgl.c
> +++ b/cogl/winsys/cogl-winsys-wgl.c
> @@ -579,9 +579,14 @@ get_wgl_extensions_string (HDC dc)
> GL_EXT_SWAP_CONTROL so if the extension to get the list of WGL
> extensions isn't supported then we can at least fake it to
> support the swap control extension */
> - if (_cogl_check_extension ("WGL_EXT_swap_control",
> - _cogl_context_get_gl_extensions (ctx)))
> - return "WGL_EXT_swap_control";
> + {
> + char **extensions = _cogl_context_get_gl_extensions (ctx);
> + CoglBool have_ext = _cogl_check_extension ("WGL_EXT_swap_control",
> + extensions);
> + g_strfreev (extensions);
> + if (have_ext)
> + return "WGL_EXT_swap_control";
> + }
>
> return NULL;
> }
> @@ -612,13 +617,15 @@ update_winsys_features (CoglContext *context, CoglError **error)
>
> if (wgl_extensions)
> {
> + char **split_extensions = g_strsplit (wgl_extensions);
> +
> COGL_NOTE (WINSYS, " WGL Extensions: %s", wgl_extensions);
>
> for (i = 0; i < G_N_ELEMENTS (winsys_feature_data); i++)
> if (_cogl_feature_check (context->display->renderer,
> "WGL", winsys_feature_data + i, 0, 0,
> COGL_DRIVER_GL,
> - wgl_extensions,
> + split_extensions,
> wgl_renderer))
> {
> context->feature_flags |= winsys_feature_data[i].feature_flags;
> @@ -627,6 +634,8 @@ update_winsys_features (CoglContext *context, CoglError **error)
> winsys_feature_data[i].winsys_feature,
> TRUE);
> }
> +
> + g_strfreev (split_extensions);
> }
>
> return TRUE;
> diff --git a/tests/conform/run-tests.sh b/tests/conform/run-tests.sh
> index fc476a8..266f1c6 100755
> --- a/tests/conform/run-tests.sh
> +++ b/tests/conform/run-tests.sh
> @@ -67,8 +67,8 @@ TITLE_FORMAT="%35s"
> printf $TITLE_FORMAT "Test"
>
> if test $HAVE_GL -eq 1; then
> - GL_FORMAT=" %6s %8s %7s %6s"
> - printf "$GL_FORMAT" "GL+FF" "GL+ARBFP" "GL+GLSL" "GL-NPT"
> + GL_FORMAT=" %6s %8s %7s %6s %6s"
> + printf "$GL_FORMAT" "GL+FF" "GL+ARBFP" "GL+GLSL" "GL-NPT" "GL3"
> fi
> if test $HAVE_GLES2 -eq 1; then
> GLES2_FORMAT=" %6s %7s"
> @@ -101,6 +101,10 @@ do
> export COGL_DRIVER=gl
> export COGL_DEBUG=disable-npot-textures
> run_test $test gl_npot
> +
> + export COGL_DRIVER=gl3
> + export COGL_DEBUG=
> + run_test $test gl3
> fi
>
> if test $HAVE_GLES2 -eq 1; then
> @@ -119,7 +123,8 @@ do
> "`get_status $gl_ff_result`" \
> "`get_status $gl_arbfp_result`" \
> "`get_status $gl_glsl_result`" \
> - "`get_status $gl_npot_result`"
> + "`get_status $gl_npot_result`" \
> + "`get_status $gl3_result`"
> fi
> if test $HAVE_GLES2 -eq 1; then
> printf "$GLES2_FORMAT" \
> diff --git a/tests/conform/test-utils.c b/tests/conform/test-utils.c
> index 6c55bf7..8ec7dc7 100644
> --- a/tests/conform/test-utils.c
> +++ b/tests/conform/test-utils.c
> @@ -52,7 +52,8 @@ test_utils_init (TestFlags flags)
> renderer = cogl_display_get_renderer (display);
>
> if (flags & TEST_REQUIREMENT_GL &&
> - cogl_renderer_get_driver (renderer) != COGL_DRIVER_GL)
> + cogl_renderer_get_driver (renderer) != COGL_DRIVER_GL &&
> + cogl_renderer_get_driver (renderer) != COGL_DRIVER_GL3)
> {
> missing_requirement = TRUE;
> }
> --
> 1.7.11.3.g3c3efa5
>
> _______________________________________________
> Cogl mailing list
> Cogl at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/cogl
More information about the Cogl
mailing list