diff --git a/cogl-pango/cogl-pango-display-list.c b/cogl-pango/cogl-pango-display-list.c index eda3c0722..bc781f988 100644 --- a/cogl-pango/cogl-pango-display-list.c +++ b/cogl-pango/cogl-pango-display-list.c @@ -342,7 +342,7 @@ emit_vertex_buffer_geometry (CoglPangoDisplayListNode *node) 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 a0f10a55e..4313ab9d5 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 fddff09b5..b00e5101e 100644 --- a/cogl/cogl-clutter.c +++ b/cogl/cogl-clutter.c @@ -29,6 +29,7 @@ #endif #include +#include #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 a28fe4f7d..7321455d3 100644 --- a/cogl/cogl-context-private.h +++ b/cogl/cogl-context-private.h @@ -356,7 +356,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 549569ad7..8bf443048 100644 --- a/cogl/cogl-context.c +++ b/cogl/cogl-context.c @@ -261,9 +261,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... */ @@ -368,8 +366,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 @@ -379,6 +376,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); @@ -430,13 +443,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)); @@ -610,38 +623,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; + + /* In GL 3, querying GL_EXTENSIONS is deprecated so we have to build + * the array using glGetStringi instead */ + if (context->driver == COGL_DRIVER_GL3) + { + int num_extensions, i; + + context->glGetIntegerv (GL_NUM_EXTENSIONS, &num_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); + + ret = g_strsplit (all_extensions, " ", 0 /* max tokens */); + } if ((env_disabled_extensions = g_getenv ("COGL_DISABLE_GL_EXTENSIONS")) || _cogl_config_disable_gl_extensions) { - 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; - - /* 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 */ - - enabled_extensions = - cogl_object_get_user_data (COGL_OBJECT (context), &extensions_key); - if (enabled_extensions) - return enabled_extensions; - - enabled_extensions = (const char *) context->glGetString (GL_EXTENSIONS); - - split_enabled_extensions = g_strsplit (enabled_extensions, - " ", - 0 /* no max tokens */); + char **src, **dst; if (env_disabled_extensions) split_env_disabled_extensions = @@ -659,46 +679,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 7883b3cbb..b8e400071 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 ad210a54d..e6f895d56 100644 --- a/cogl/cogl-feature-private.h +++ b/cogl/cogl-feature-private.h @@ -87,13 +87,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 5dc02f827..fd646b10c 100644 --- a/cogl/cogl-framebuffer.c +++ b/cogl/cogl-framebuffer.c @@ -1556,7 +1556,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)) @@ -1567,7 +1568,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 88fd18858..c2f387999 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_quark (void); diff --git a/cogl/cogl-journal.c b/cogl/cogl-journal.c index 25422a45e..e8eee7906 100644 --- a/cogl/cogl-journal.c +++ b/cogl/cogl-journal.c @@ -303,7 +303,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, @@ -615,7 +615,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 2d61a5eae..de3143d8e 100644 --- a/cogl/cogl-matrix-stack.c +++ b/cogl/cogl-matrix-stack.c @@ -795,8 +795,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) @@ -836,8 +835,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 c7f3bde88..bb00568d1 100644 --- a/cogl/cogl-pipeline-state.c +++ b/cogl/cogl-pipeline-state.c @@ -1037,7 +1037,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 2ad9e143b..6026ddbe3 100644 --- a/cogl/cogl-pipeline.c +++ b/cogl/cogl-pipeline.c @@ -2824,8 +2824,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; @@ -2838,7 +2840,7 @@ _cogl_pipeline_get_state_for_fragment_codegen (CoglContext *context) COGL_PIPELINE_STATE_USER_SHADER | 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 d167cb322..10eebacc9 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 30eb4ad7d..11f0ec392 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 b1ddb9fb2..383eeac1c 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-shader.c b/cogl/cogl-shader.c index 663661c14..3c2a0b77c 100644 --- a/cogl/cogl-shader.c +++ b/cogl/cogl-shader.c @@ -239,7 +239,8 @@ _cogl_shader_compile_real (CoglHandle handle, shader->gl_handle = ctx->glCreateShader (gl_type); - if (ctx->driver == COGL_DRIVER_GL && + if ((ctx->driver == COGL_DRIVER_GL || + ctx->driver == COGL_DRIVER_GL3 ) && ctx->glsl_major == 1 && ctx->glsl_minor >= 2) { diff --git a/cogl/cogl-texture.c b/cogl/cogl-texture.c index ebc137f07..95608c624 100644 --- a/cogl/cogl-texture.c +++ b/cogl/cogl-texture.c @@ -206,7 +206,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 998a47865..76ac7175a 100644 --- a/cogl/cogl.c +++ b/cogl/cogl.c @@ -51,6 +51,7 @@ #include "cogl1-context.h" #include "cogl-offscreen.h" #include "cogl-attribute-gl-private.h" +#include "cogl-clutter.h" #ifdef COGL_GL_DEBUG /* GL error to string conversion */ @@ -99,26 +100,13 @@ cogl_get_proc_address (const char* name) } 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; } @@ -127,7 +115,7 @@ _cogl_check_extension (const char *name, const gchar *ext) CoglBool cogl_check_extension (const char *name, const char *ext) { - return _cogl_check_extension (name, ext); + return cogl_clutter_check_extension (name, ext); } /* XXX: it's expected that we'll deprecated this with diff --git a/cogl/driver/gl/cogl-attribute-gl.c b/cogl/driver/gl/cogl-attribute-gl.c index 3d93f3f2c..312f0eaf2 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 eaf46bc21..db9fbd440 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 f2c22b262..4a6f62af6 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 4df719904..aeb50569c 100644 --- a/cogl/driver/gl/cogl-pipeline-fragend-glsl.c +++ b/cogl/driver/gl/cogl-pipeline-fragend-glsl.c @@ -913,10 +913,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, @@ -1046,8 +1046,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 @@ -1072,10 +1072,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 103ecdba3..899554180 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 */ @@ -675,7 +675,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 @@ -856,7 +857,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 b096bab05..78a8c8d3b 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 f38249289..f1b140741 100644 --- a/cogl/driver/gl/cogl-pipeline-vertend-glsl.c +++ b/cogl/driver/gl/cogl-pipeline-vertend-glsl.c @@ -261,7 +261,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, @@ -460,7 +461,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 5056544a1..1d64d5b2c 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_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 bb24106c6..7600db26a 100644 --- a/cogl/driver/gl/gl/cogl-driver-gl.c +++ b/cogl/driver/gl/gl/cogl-driver-gl.c @@ -291,10 +291,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)) { @@ -309,8 +309,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)) @@ -344,32 +342,49 @@ _cogl_driver_update_features (CoglContext *ctx, { CoglPrivateFeatureFlags private_flags = 0; CoglFeatureFlags 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); - if (!check_gl_version (ctx, error)) + gl_extensions = _cogl_context_get_gl_extensions (ctx); + + 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); @@ -395,8 +410,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, @@ -434,6 +447,7 @@ _cogl_driver_update_features (CoglContext *ctx, { flags |= COGL_FEATURE_OFFSCREEN; COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_OFFSCREEN, TRUE); + private_flags |= COGL_PRIVATE_FEATURE_QUERY_FRAMEBUFFER_BITS; } if (ctx->glBlitFramebuffer) @@ -457,6 +471,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) { flags |= COGL_FEATURE_SHADERS_ARBFP; @@ -546,10 +564,25 @@ _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; ctx->feature_flags |= 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 b105fa2e1..3975b8dd7 100644 --- a/cogl/driver/gl/gl/cogl-pipeline-progend-fixed-arbfp.c +++ b/cogl/driver/gl/gl/cogl-pipeline-progend-fixed-arbfp.c @@ -51,7 +51,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 6268b4d05..dd4955b33 100644 --- a/cogl/driver/gl/gles/cogl-driver-gles.c +++ b/cogl/driver/gl/gles/cogl-driver-gles.c @@ -192,7 +192,7 @@ _cogl_driver_update_features (CoglContext *context, { CoglPrivateFeatureFlags private_flags = 0; CoglFeatureFlags 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 @@ -203,23 +203,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 */, @@ -255,9 +262,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_VBOS; + 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 | + COGL_PRIVATE_FEATURE_ANY_GL); /* Both GLES 1.1 and GLES 2.0 support point sprites in core */ flags |= COGL_FEATURE_POINT_SPRITE; @@ -341,6 +355,8 @@ _cogl_driver_update_features (CoglContext *context, context->private_feature_flags |= private_flags; context->feature_flags |= 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 1fa475fb1..eeef4e7da 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 78dec260c..9c8102f13 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 f39bd2765..6130576d5 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 9c8dcca4a..9016f8d86 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 f1e5361bf..13ce9a4e4 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 df07f8100..f6fba0788 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 71fd827fa..f36e2ea9e 100644 --- a/cogl/winsys/cogl-winsys-glx-feature-functions.h +++ b/cogl/winsys/cogl-winsys-glx-feature-functions.h @@ -111,3 +111,17 @@ 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, + 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 6716c7c65..c9449ccf0 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; @@ -418,11 +420,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)) { context->feature_flags |= winsys_feature_data[i].feature_flags; @@ -432,6 +436,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) @@ -607,6 +613,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) { @@ -644,12 +680,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 f3a71d313..63abbd075 100644 --- a/cogl/winsys/cogl-winsys-sdl.c +++ b/cogl/winsys/cogl-winsys-sdl.c @@ -162,6 +162,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 fd9d7d5bb..8367324a7 100644 --- a/cogl/winsys/cogl-winsys-sdl2.c +++ b/cogl/winsys/cogl-winsys-sdl2.c @@ -157,6 +157,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 */ @@ -195,6 +197,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])) @@ -204,6 +207,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 7e2dc5d63..e6686d86b 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 fc476a8ec..266f1c63e 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 bbf9b05e9..84cb23bed 100644 --- a/tests/conform/test-utils.c +++ b/tests/conform/test-utils.c @@ -53,7 +53,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; }