diff --git a/cogl-pango/Makefile.am b/cogl-pango/Makefile.am index b57e14744..afd96d6b4 100644 --- a/cogl-pango/Makefile.am +++ b/cogl-pango/Makefile.am @@ -40,6 +40,8 @@ INCLUDES = \ -DG_DISABLE_SINGLE_INCLUDES \ -DCLUTTER_COMPILATION \ -DG_LOG_DOMAIN=\"CoglPango\" \ + -I$(top_srcdir)/cogl \ + -I$(top_srcdir)/cogl/winsys \ -I$(top_srcdir) \ -I$(top_builddir) diff --git a/cogl-pango/cogl-pango-display-list.c b/cogl-pango/cogl-pango-display-list.c index a79cf0f1c..844000667 100644 --- a/cogl-pango/cogl-pango-display-list.c +++ b/cogl-pango/cogl-pango-display-list.c @@ -30,6 +30,7 @@ #include #include "cogl-pango-display-list.h" +#include "cogl/cogl-context-private.h" typedef enum { @@ -265,6 +266,8 @@ emit_rectangles_through_journal (CoglPangoDisplayListNode *node) static void emit_vertex_buffer_geometry (CoglPangoDisplayListNode *node) { + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + /* It's expensive to go through the Cogl journal for large runs * of text in part because the journal transforms the quads in software * to avoid changing the modelview matrix. So for larger runs of text @@ -293,29 +296,27 @@ emit_vertex_buffer_geometry (CoglPangoDisplayListNode *node) node->d.texture.vertex_buffer = vb; } - #ifdef CLUTTER_COGL_HAS_GL + if (ctx->driver == COGL_DRIVER_GL) + cogl_vertex_buffer_draw (node->d.texture.vertex_buffer, + GL_QUADS, + 0, node->d.texture.verts->len); + else +#endif + { + /* GLES doesn't support GL_QUADS so instead we use a VBO with + indexed vertices to generate GL_TRIANGLES from the quads */ - cogl_vertex_buffer_draw (node->d.texture.vertex_buffer, - GL_QUADS, - 0, node->d.texture.verts->len); + int n_indices = node->d.texture.verts->len / 4 * 6; + CoglHandle indices_vbo + = cogl_vertex_buffer_indices_get_for_quads (n_indices); -#else /* CLUTTER_COGL_HAS_GL */ - { - /* GLES doesn't support GL_QUADS so instead we use a VBO with - indexed vertices to generate GL_TRIANGLES from the quads */ - - int n_indices = node->d.texture.verts->len / 4 * 6; - CoglHandle indices_vbo - = cogl_vertex_buffer_indices_get_for_quads (n_indices); - - cogl_vertex_buffer_draw_elements (node->d.texture.vertex_buffer, - COGL_VERTICES_MODE_TRIANGLES, - indices_vbo, - 0, node->d.texture.verts->len - 1, - 0, n_indices); - } -#endif /* CLUTTER_COGL_HAS_GL */ + cogl_vertex_buffer_draw_elements (node->d.texture.vertex_buffer, + COGL_VERTICES_MODE_TRIANGLES, + indices_vbo, + 0, node->d.texture.verts->len - 1, + 0, n_indices); + } } static void diff --git a/cogl/Makefile.am b/cogl/Makefile.am index 7e7469c3b..9d222642a 100644 --- a/cogl/Makefile.am +++ b/cogl/Makefile.am @@ -28,6 +28,9 @@ AM_CPPFLAGS = \ -DG_DISABLE_DEPRECATED \ -DG_LOG_DOMAIN=\"Cogl\" \ -DCLUTTER_COMPILATION \ + -DCOGL_GL_LIBNAME=\"$(COGL_GL_LIBNAME)\" \ + -DCOGL_GLES1_LIBNAME=\"$(COGL_GLES1_LIBNAME)\" \ + -DCOGL_GLES2_LIBNAME=\"$(COGL_GLES2_LIBNAME)\" \ $(NULL) AM_CFLAGS = $(COGL_DEP_CFLAGS) $(COGL_EXTRA_CFLAGS) $(MAINTAINER_CFLAGS) @@ -102,20 +105,19 @@ cogl_experimental_h = \ # driver sources cogl_driver_sources = -if COGL_DRIVER_GL +if COGL_DRIVER_GL_SUPPORTED cogl_driver_sources += \ $(srcdir)/driver/gl/cogl-gl.c \ $(srcdir)/driver/gl/cogl-texture-driver-gl.c \ $(NULL) endif -if COGL_DRIVER_GLES +if COGL_DRIVER_GLES_SUPPORTED cogl_driver_sources += \ $(srcdir)/driver/gles/cogl-gles.c \ $(srcdir)/driver/gles/cogl-texture-driver-gles.c \ $(NULL) - -endif # COGL_DRIVER_GLES +endif # winsys sources, common to all backends cogl_winsys_common_sources = \ @@ -387,7 +389,7 @@ libcogl_la_LDFLAGS = \ -no-undefined \ -version-info @COGL_LT_CURRENT@:@COGL_LT_REVISION@:@COGL_LT_AGE@ \ -export-dynamic \ - -export-symbols-regex "^(cogl|_cogl_debug_flags|_cogl_atlas_new|_cogl_atlas_add_reorganize_callback|_cogl_atlas_reserve_space|_cogl_callback|_cogl_util_get_eye_planes_for_screen_poly|_cogl_atlas_texture_remove_reorganize_callback|_cogl_atlas_texture_add_reorganize_callback|_cogl_texture_foreach_sub_texture_in_region|_cogl_atlas_texture_new_with_size|_cogl_profile_trace_message).*" + -export-symbols-regex "^(cogl|_cogl_debug_flags|_cogl_atlas_new|_cogl_atlas_add_reorganize_callback|_cogl_atlas_reserve_space|_cogl_callback|_cogl_util_get_eye_planes_for_screen_poly|_cogl_atlas_texture_remove_reorganize_callback|_cogl_atlas_texture_add_reorganize_callback|_cogl_texture_foreach_sub_texture_in_region|_cogl_atlas_texture_new_with_size|_cogl_profile_trace_message|_cogl_context_get_default).*" libcogl_la_SOURCES = $(cogl_sources_c) nodist_libcogl_la_SOURCES = $(BUILT_SOURCES) diff --git a/cogl/cogl-attribute.c b/cogl/cogl-attribute.c index 5970b79ed..b6e99576e 100644 --- a/cogl/cogl-attribute.c +++ b/cogl/cogl-attribute.c @@ -47,26 +47,11 @@ #include #include -#if ! defined (HAVE_COGL_GL) - -/* GLES doesn't have glDrawRangeElements, so we simply pretend it does - * but that it makes no use of the start, end constraints: */ -#define glDrawRangeElements(mode, start, end, count, type, indices) \ - glDrawElements (mode, count, type, indices) - /* This isn't defined in the GLES headers */ #ifndef GL_UNSIGNED_INT #define GL_UNSIGNED_INT 0x1405 #endif -#ifdef HAVE_COGL_GLES2 - -#define MAY_HAVE_PROGRAMABLE_GL - -#endif /* HAVE_COGL_GLES2 */ - -#endif - static void _cogl_attribute_free (CoglAttribute *attribute); COGL_OBJECT_DEFINE (Attribute, attribute); @@ -412,23 +397,24 @@ toggle_enabled_cb (int bit_num, void *user_data) _COGL_GET_CONTEXT (ctx, NO_RETVAL); -#ifdef HAVE_COGL_GLES2 - - if (enabled) - GE( ctx, glEnableVertexAttribArray (bit_num) ); + if (ctx->driver == COGL_DRIVER_GLES2) + { + if (enabled) + GE( ctx, glEnableVertexAttribArray (bit_num) ); + else + GE( ctx, glDisableVertexAttribArray (bit_num) ); + } +#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES) else - GE( ctx, glDisableVertexAttribArray (bit_num) ); + { + GE( ctx, glClientActiveTexture (GL_TEXTURE0 + bit_num) ); -#else /* HAVE_COGL_GLES2 */ - - GE( ctx, glClientActiveTexture (GL_TEXTURE0 + bit_num) ); - - if (enabled) - GE( ctx, glEnableClientState (GL_TEXTURE_COORD_ARRAY) ); - else - GE( ctx, glDisableClientState (GL_TEXTURE_COORD_ARRAY) ); - -#endif /* HAVE_COGL_GLES2 */ + if (enabled) + GE( ctx, glEnableClientState (GL_TEXTURE_COORD_ARRAY) ); + else + GE( ctx, glDisableClientState (GL_TEXTURE_COORD_ARRAY) ); + } +#endif } static void @@ -460,9 +446,7 @@ enable_gl_state (CoglDrawFlags flags, { CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer (); int i; -#ifdef MAY_HAVE_PROGRAMABLE_GL GLuint generic_index = 0; -#endif unsigned long enable_flags = 0; gboolean skip_gl_color = FALSE; CoglPipeline *source; @@ -591,134 +575,144 @@ enable_gl_state (CoglDrawFlags flags, { case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY: #ifdef HAVE_COGL_GLES2 - - attrib_location = - _cogl_pipeline_progend_glsl_get_color_attribute (source); - if (attrib_location != -1) + if (ctx->driver == COGL_DRIVER_GLES2) { - GE( ctx, - glVertexAttribPointer (attrib_location, - attribute->n_components, - attribute->type, - TRUE, /* normalize */ - attribute->stride, - base + attribute->offset) ); + attrib_location = + _cogl_pipeline_progend_glsl_get_color_attribute (source); + if (attrib_location != -1) + { + GE( ctx, + glVertexAttribPointer (attrib_location, + attribute->n_components, + attribute->type, + TRUE, /* normalize */ + attribute->stride, + base + attribute->offset) ); - _cogl_bitmask_set (&ctx->temp_bitmask, attrib_location, TRUE); + _cogl_bitmask_set (&ctx->temp_bitmask, attrib_location, TRUE); + } } - -#else - - enable_flags |= COGL_ENABLE_COLOR_ARRAY; - /* GE (ctx, glEnableClientState (GL_COLOR_ARRAY)); */ - GE (ctx, glColorPointer (attribute->n_components, - attribute->type, - attribute->stride, - base + attribute->offset)); - + else #endif + { + enable_flags |= COGL_ENABLE_COLOR_ARRAY; + /* GE (ctx, glEnableClientState (GL_COLOR_ARRAY)); */ + GE (ctx, glColorPointer (attribute->n_components, + attribute->type, + attribute->stride, + base + attribute->offset)); + + } break; case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY: #ifdef HAVE_COGL_GLES2 - - attrib_location = - _cogl_pipeline_progend_glsl_get_normal_attribute (source); - if (attrib_location != -1) + if (ctx->driver == COGL_DRIVER_GLES2) { - GE( ctx, - glVertexAttribPointer (attrib_location, - attribute->n_components, - attribute->type, - TRUE, /* normalize */ - attribute->stride, - base + attribute->offset) ); - _cogl_bitmask_set (&ctx->temp_bitmask, attrib_location, TRUE); + attrib_location = + _cogl_pipeline_progend_glsl_get_normal_attribute (source); + if (attrib_location != -1) + { + GE( ctx, + glVertexAttribPointer (attrib_location, + attribute->n_components, + attribute->type, + TRUE, /* normalize */ + attribute->stride, + base + attribute->offset) ); + _cogl_bitmask_set (&ctx->temp_bitmask, attrib_location, TRUE); + } } - -#else - - /* FIXME: go through cogl cache to enable normal array */ - GE (ctx, glEnableClientState (GL_NORMAL_ARRAY)); - GE (ctx, glNormalPointer (attribute->type, - attribute->stride, - base + attribute->offset)); - #endif +#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES) + if (ctx->driver != COGL_DRIVER_GLES2) + { + /* FIXME: go through cogl cache to enable normal array */ + GE (ctx, glEnableClientState (GL_NORMAL_ARRAY)); + GE (ctx, glNormalPointer (attribute->type, + attribute->stride, + base + attribute->offset)); + } +#endif break; case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY: #ifdef HAVE_COGL_GLES2 - - attrib_location = _cogl_pipeline_progend_glsl_get_tex_coord_attribute - (source, attribute->texture_unit); - if (attrib_location != -1) + if (ctx->driver == COGL_DRIVER_GLES2) { - GE( ctx, - glVertexAttribPointer (attrib_location, - attribute->n_components, - attribute->type, - FALSE, /* normalize */ - attribute->stride, - base + attribute->offset) ); - _cogl_bitmask_set (&ctx->temp_bitmask, attrib_location, TRUE); + attrib_location = + _cogl_pipeline_progend_glsl_get_tex_coord_attribute + (source, attribute->texture_unit); + if (attrib_location != -1) + { + GE( ctx, + glVertexAttribPointer (attrib_location, + attribute->n_components, + attribute->type, + FALSE, /* normalize */ + attribute->stride, + base + attribute->offset) ); + _cogl_bitmask_set (&ctx->temp_bitmask, attrib_location, TRUE); + } } -#else - - GE (ctx, glClientActiveTexture (GL_TEXTURE0 + - attribute->texture_unit)); - GE (ctx, glTexCoordPointer (attribute->n_components, - attribute->type, - attribute->stride, - base + attribute->offset)); - _cogl_bitmask_set (&ctx->temp_bitmask, - attribute->texture_unit, TRUE); - + else #endif + { + GE (ctx, glClientActiveTexture (GL_TEXTURE0 + + attribute->texture_unit)); + GE (ctx, glTexCoordPointer (attribute->n_components, + attribute->type, + attribute->stride, + base + attribute->offset)); + _cogl_bitmask_set (&ctx->temp_bitmask, + attribute->texture_unit, TRUE); + + } break; case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY: #ifdef HAVE_COGL_GLES2 - - attrib_location = - _cogl_pipeline_progend_glsl_get_position_attribute (source); - if (attrib_location != -1) + if (ctx->driver == COGL_DRIVER_GLES2) { - GE( ctx, - glVertexAttribPointer (attrib_location, - attribute->n_components, - attribute->type, - FALSE, /* normalize */ - attribute->stride, - base + attribute->offset) ); - _cogl_bitmask_set (&ctx->temp_bitmask, attrib_location, TRUE); + attrib_location = + _cogl_pipeline_progend_glsl_get_position_attribute (source); + if (attrib_location != -1) + { + GE( ctx, + glVertexAttribPointer (attrib_location, + attribute->n_components, + attribute->type, + FALSE, /* normalize */ + attribute->stride, + base + attribute->offset) ); + _cogl_bitmask_set (&ctx->temp_bitmask, attrib_location, TRUE); + } } - -#else - - enable_flags |= COGL_ENABLE_VERTEX_ARRAY; - /* GE (ctx, glEnableClientState (GL_VERTEX_ARRAY)); */ - GE (ctx, glVertexPointer (attribute->n_components, - attribute->type, - attribute->stride, - base + attribute->offset)); - + else #endif + { + enable_flags |= COGL_ENABLE_VERTEX_ARRAY; + /* GE (ctx, glEnableClientState (GL_VERTEX_ARRAY)); */ + GE (ctx, glVertexPointer (attribute->n_components, + attribute->type, + attribute->stride, + base + attribute->offset)); + + } break; case COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY: - { -#ifdef MAY_HAVE_PROGRAMABLE_GL - /* FIXME: go through cogl cache to enable generic array. */ - /* FIXME: this is going to end up just using the builtins - on GLES 2 */ - GE (ctx, glEnableVertexAttribArray (generic_index++)); - GE (ctx, glVertexAttribPointer (generic_index, - attribute->n_components, - attribute->type, - attribute->normalized, - attribute->stride, - base + attribute->offset)); -#endif - } + if (ctx->driver != COGL_DRIVER_GLES1) + { + /* FIXME: go through cogl cache to enable generic array. */ + /* FIXME: this is going to end up just using the builtins + on GLES 2 */ + GE (ctx, glEnableVertexAttribArray (generic_index++)); + GE (ctx, glVertexAttribPointer (generic_index, + attribute->n_components, + attribute->type, + attribute->normalized, + attribute->stride, + base + attribute->offset)); + } break; default: g_warning ("Unrecognised attribute type 0x%08x", attribute->type); @@ -752,9 +746,7 @@ disable_gl_state (CoglAttribute **attributes, int n_attributes, CoglPipeline *source) { -#ifdef MAY_HAVE_PROGRAMABLE_GL GLuint generic_index = 0; -#endif int i; _COGL_GET_CONTEXT (ctx, NO_RETVAL); @@ -773,8 +765,9 @@ disable_gl_state (CoglAttribute **attributes, break; case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY: /* FIXME: go through cogl cache to enable normal array */ -#ifndef HAVE_COGL_GLES2 - GE (ctx, glDisableClientState (GL_NORMAL_ARRAY)); +#if defined(HAVE_COGL_GLES) || defined(HAVE_COGL_GL) + if (ctx->driver != COGL_DRIVER_GLES2) + GE (ctx, glDisableClientState (GL_NORMAL_ARRAY)); #endif break; case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY: @@ -788,10 +781,9 @@ disable_gl_state (CoglAttribute **attributes, /* GE (ctx, glDisableClientState (GL_VERTEX_ARRAY)); */ break; case COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY: -#ifdef MAY_HAVE_PROGRAMABLE_GL - /* FIXME: go through cogl cache to enable generic array */ - GE (ctx, glDisableVertexAttribArray (generic_index++)); -#endif + if (ctx->driver != COGL_DRIVER_GLES1) + /* FIXME: go through cogl cache to enable generic array */ + GE (ctx, glDisableVertexAttribArray (generic_index++)); break; default: g_warning ("Unrecognised attribute type 0x%08x", attribute->type); diff --git a/cogl/cogl-blend-string.c b/cogl/cogl-blend-string.c index aaba5cf59..1eb2a8022 100644 --- a/cogl/cogl-blend-string.c +++ b/cogl/cogl-blend-string.c @@ -214,32 +214,33 @@ validate_blend_statements (CoglBlendStringStatement *statements, const char *error_string; CoglBlendStringError detail = COGL_BLEND_STRING_ERROR_INVALID_ERROR; -#ifdef HAVE_COGL_GL _COGL_GET_CONTEXT (ctx, 0); -#endif -#ifdef HAVE_COGL_GL - if (n_statements == 2) + if (ctx->driver == COGL_DRIVER_GL) { - /* glBlendEquationSeperate is GL 2.0 only */ - if (!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 driver"; + "channels isn't supported by the GLES 1"; detail = COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR; goto error; } } -#elif defined(HAVE_COGL_GLES) - 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; - } -#endif for (i = 0; i < n_statements; i++) for (j = 0; j < statements[i].function->argc; j++) @@ -261,15 +262,15 @@ validate_blend_statements (CoglBlendStringStatement *statements, goto error; } -#ifdef HAVE_COGL_GLES - if (arg->factor.is_color && - arg->factor.source.info->type == COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT) + if (ctx->driver == COGL_DRIVER_GLES1 && + arg->factor.is_color && + (arg->factor.source.info->type == + COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT)) { error_string = "GLES Doesn't support constant blend factors"; detail = COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR; goto error; } -#endif } return TRUE; diff --git a/cogl/cogl-buffer.c b/cogl/cogl-buffer.c index 207b1700a..7a6c77aaf 100644 --- a/cogl/cogl-buffer.c +++ b/cogl/cogl-buffer.c @@ -316,33 +316,25 @@ _cogl_buffer_access_to_gl_enum (CoglBufferAccess access) return GL_READ_ONLY; } -/* OpenGL ES 1.1 and 2 only know about STATIC_DRAW and DYNAMIC_DRAW */ -#if defined (COGL_HAS_GLES) -GLenum -_cogl_buffer_hints_to_gl_enum (CoglBufferUsageHint usage_hint, - CoglBufferUpdateHint update_hint) -{ - /* usage hint is always TEXTURE for now */ - if (update_hint == COGL_BUFFER_UPDATE_HINT_STATIC) - return GL_STATIC_DRAW; - return GL_DYNAMIC_DRAW; -} -#else GLenum _cogl_buffer_hints_to_gl_enum (CoglBufferUsageHint usage_hint, CoglBufferUpdateHint update_hint) { + _COGL_GET_CONTEXT (ctx, 0); + /* usage hint is always TEXTURE for now */ if (update_hint == COGL_BUFFER_UPDATE_HINT_STATIC) return GL_STATIC_DRAW; if (update_hint == COGL_BUFFER_UPDATE_HINT_DYNAMIC) return GL_DYNAMIC_DRAW; + /* OpenGL ES 1.1 and 2 only know about STATIC_DRAW and DYNAMIC_DRAW */ +#ifdef HAVE_COGL_GL if (update_hint == COGL_BUFFER_UPDATE_HINT_STREAM) return GL_STREAM_DRAW; +#endif return GL_STATIC_DRAW; } -#endif void * _cogl_buffer_bind (CoglBuffer *buffer, CoglBufferBindTarget target) diff --git a/cogl/cogl-clip-stack.c b/cogl/cogl-clip-stack.c index c599cfd27..7663bb407 100644 --- a/cogl/cogl-clip-stack.c +++ b/cogl/cogl-clip-stack.c @@ -71,11 +71,8 @@ set_clip_plane (GLint plane_num, const float *vertex_a, const float *vertex_b) { -#if defined (HAVE_COGL_GLES2) || defined (HAVE_COGL_GLES) - GLfloat plane[4]; -#else - GLdouble plane[4]; -#endif + GLfloat planef[4]; + double planed[4]; GLfloat angle; CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer (); CoglMatrixStack *modelview_stack = @@ -110,17 +107,29 @@ set_clip_plane (GLint plane_num, _cogl_matrix_stack_flush_to_gl (modelview_stack, COGL_MATRIX_MODELVIEW); - plane[0] = 0; - plane[1] = -1.0; - plane[2] = 0; - plane[3] = vertex_a[1]; -#if defined (HAVE_COGL_GLES2) - g_assert_not_reached (); -#elif defined (HAVE_COGL_GLES) - GE( ctx, glClipPlanef (plane_num, plane) ); -#else - GE( ctx, glClipPlane (plane_num, plane) ); -#endif + planef[0] = 0; + planef[1] = -1.0; + planef[2] = 0; + planef[3] = vertex_a[1]; + + switch (ctx->driver) + { + default: + g_assert_not_reached (); + break; + + case COGL_DRIVER_GLES1: + GE( ctx, glClipPlanef (plane_num, planef) ); + break; + + case COGL_DRIVER_GL: + planed[0] = planef[0]; + planed[1] = planef[1]; + planed[2] = planef[2]; + planed[3] = planef[3]; + GE( ctx, glClipPlane (plane_num, planed) ); + break; + } _cogl_matrix_stack_pop (modelview_stack); } diff --git a/cogl/cogl-context-private.h b/cogl/cogl-context-private.h index 87b0d6c3e..8ffcba19d 100644 --- a/cogl/cogl-context-private.h +++ b/cogl/cogl-context-private.h @@ -56,6 +56,8 @@ struct _CoglContext CoglDisplay *display; + CoglDriver driver; + /* vtable for the texture driver functions */ const CoglTextureDriver *texture_driver; @@ -86,10 +88,8 @@ struct _CoglContext API. We keep track of the matrix stack that Cogl is trying to flush so we can flush it later after the program is generated. A reference is taken on the stacks. */ -#ifdef HAVE_COGL_GLES2 CoglMatrixStack *flushed_modelview_stack; CoglMatrixStack *flushed_projection_stack; -#endif /* HAVE_COGL_GLES2 */ GArray *texture_units; int active_texture_unit; @@ -287,6 +287,18 @@ _cogl_context_get_default (); const CoglWinsysVtable * _cogl_context_get_winsys (CoglContext *context); +/* Check whether the current GL context is supported by Cogl */ +gboolean +_cogl_context_check_gl_version (CoglContext *context, + GError **error); + +/* Query the GL extensions and lookup the corresponding function + * pointers. Theoretically the list of extensions can change for + * different GL contexts so it is the winsys backend's responsiblity + * to know when to re-query the GL extensions. */ +void +_cogl_context_update_features (CoglContext *context); + /* Obtains the context and returns retval if NULL */ #define _COGL_GET_CONTEXT(ctxvar, retval) \ CoglContext *ctxvar = _cogl_context_get_default (); \ diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c index 7a7079731..0981e0d6b 100644 --- a/cogl/cogl-context.c +++ b/cogl/cogl-context.c @@ -54,8 +54,12 @@ #define GL_POINT_SPRITE 0x8861 #endif +#ifdef HAVE_COGL_GL extern const CoglTextureDriver _cogl_texture_driver_gl; +#endif +#if defined (HAVE_COGL_GLES) || defined (HAVE_COGL_GLES2) extern const CoglTextureDriver _cogl_texture_driver_gles; +#endif static void _cogl_context_free (CoglContext *context); @@ -168,6 +172,11 @@ cogl_context_new (CoglDisplay *display, context->display = display; + /* This is duplicated data, but it's much more convenient to have + the driver attached to the context and the value is accessed a + lot throughout Cogl */ + context->driver = display->renderer->driver; + winsys = _cogl_context_get_winsys (context); if (!winsys->context_init (context, error)) { @@ -176,12 +185,25 @@ cogl_context_new (CoglDisplay *display, return NULL; } + switch (context->driver) + { #ifdef HAVE_COGL_GL - context->texture_driver = &_cogl_texture_driver_gl; -#else - context->texture_driver = &_cogl_texture_driver_gles; + case COGL_DRIVER_GL: + context->texture_driver = &_cogl_texture_driver_gl; + break; #endif +#if defined (HAVE_COGL_GLES) || defined (HAVE_COGL_GLES2) + case COGL_DRIVER_GLES1: + case COGL_DRIVER_GLES2: + context->texture_driver = &_cogl_texture_driver_gles; + break; +#endif + + default: + g_assert_not_reached (); + } + /* Initialise the driver specific state */ _cogl_init_feature_overrides (context); @@ -308,14 +330,15 @@ cogl_context_new (CoglDisplay *display, context->texture_download_pipeline = COGL_INVALID_HANDLE; context->blit_texture_pipeline = COGL_INVALID_HANDLE; -#ifndef HAVE_COGL_GLES2 - /* 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 - * makes things a bit simpler for us. Under GLES2 the alpha test is - * implemented in the fragment shader so there is no enable for it - */ - GE (context, glEnable (GL_ALPHA_TEST)); +#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES) + if (context->driver != COGL_DRIVER_GLES2) + /* 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 + * makes things a bit simpler for us. Under GLES2 the alpha test is + * implemented in the fragment shader so there is no enable for it + */ + GE (context, glEnable (GL_ALPHA_TEST)); #endif #ifdef HAVE_COGL_GLES2 @@ -361,10 +384,9 @@ cogl_context_new (CoglDisplay *display, each pipeline to track whether any layers have point sprite coords enabled. We don't need to do this for GLES2 because point sprites are handled using a builtin varying in the shader. */ -#ifndef HAVE_COGL_GLES2 - if (cogl_features_available (COGL_FEATURE_POINT_SPRITE)) + if (_context->driver != COGL_DRIVER_GLES2 && + cogl_features_available (COGL_FEATURE_POINT_SPRITE)) GE (context, glEnable (GL_POINT_SPRITE)); -#endif return _cogl_context_object_new (context); } @@ -499,3 +521,37 @@ cogl_context_egl_get_egl_display (CoglContext *context) } #endif +gboolean +_cogl_context_check_gl_version (CoglContext *context, + GError **error) +{ +#ifdef HAVE_COGL_GL + if (context->driver == COGL_DRIVER_GL) + return _cogl_gl_check_gl_version (context, error); +#endif + +#if defined(HAVE_COGL_GLES) || defined(HAVE_COGL_GLES2) + return _cogl_gles_check_gl_version (context, error); +#endif + + g_assert_not_reached (); +} + +void +_cogl_context_update_features (CoglContext *context) +{ +#ifdef HAVE_COGL_GL + if (context->driver == COGL_DRIVER_GL) + { + _cogl_gl_update_features (context); + return; + } +#endif + +#if defined(HAVE_COGL_GLES) || defined(HAVE_COGL_GLES2) + _cogl_gles_update_features (context); + return; +#endif + + g_assert_not_reached (); +} diff --git a/cogl/cogl-display-private.h b/cogl/cogl-display-private.h index 24118550b..2db5d5563 100644 --- a/cogl/cogl-display-private.h +++ b/cogl/cogl-display-private.h @@ -29,6 +29,7 @@ #include "cogl-display.h" #include "cogl-renderer.h" #include "cogl-onscreen-template.h" +#include "cogl-internal.h" #if COGL_HAS_WAYLAND_EGL_SERVER_SUPPORT #include #endif diff --git a/cogl/cogl-display.c b/cogl/cogl-display.c index a0e37a25a..db0d7cd6c 100644 --- a/cogl/cogl-display.c +++ b/cogl/cogl-display.c @@ -28,9 +28,12 @@ #include "config.h" #endif +#include + #include "cogl.h" #include "cogl-private.h" #include "cogl-object.h" +#include "cogl-internal.h" #include "cogl-display-private.h" #include "cogl-renderer-private.h" diff --git a/cogl/cogl-ext-functions.h b/cogl/cogl-ext-functions.h index 2a85687df..45dc669e8 100644 --- a/cogl/cogl-ext-functions.h +++ b/cogl/cogl-ext-functions.h @@ -563,19 +563,6 @@ COGL_EXT_FUNCTION (GLboolean, glUnmapBuffer, (GLenum target)) COGL_EXT_END () -COGL_EXT_BEGIN (draw_range_elements, 1, 2, - 0, /* not in either GLES */ - "\0", - "\0") -COGL_EXT_FUNCTION (void, glDrawRangeElements, - (GLenum mode, - GLuint start, - GLuint end, - GLsizei count, - GLenum type, - const GLvoid *indices)) -COGL_EXT_END () - COGL_EXT_BEGIN (blending, 1, 2, COGL_EXT_IN_GLES2, "\0", diff --git a/cogl/cogl-feature-private.c b/cogl/cogl-feature-private.c index 27c806ca5..053bd0268 100644 --- a/cogl/cogl-feature-private.c +++ b/cogl/cogl-feature-private.c @@ -38,7 +38,7 @@ _cogl_feature_check (const CoglWinsysVtable *winsys, const CoglFeatureData *data, int gl_major, int gl_minor, - CoglExtGlesAvailability gles_version, + CoglDriver driver, const char *extensions_string, void *function_table) @@ -48,9 +48,13 @@ _cogl_feature_check (const CoglWinsysVtable *winsys, /* First check whether the functions should be directly provided by GL */ - if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, - data->min_gl_major, data->min_gl_minor) || - (gles_version & data->gles_availability)) + if ((driver == COGL_DRIVER_GL && + COGL_CHECK_GL_VERSION (gl_major, gl_minor, + data->min_gl_major, data->min_gl_minor)) || + (driver == COGL_DRIVER_GLES1 && + (data->gles_availability & COGL_EXT_IN_GLES)) || + (driver == COGL_DRIVER_GLES2 && + (data->gles_availability & COGL_EXT_IN_GLES2))) suffix = ""; else { @@ -180,15 +184,14 @@ void _cogl_feature_check_ext_functions (CoglContext *context, int gl_major, int gl_minor, - const char *gl_extensions, - CoglExtGlesAvailability gles_version) + const char *gl_extensions) { int i; for (i = 0; i < G_N_ELEMENTS (cogl_feature_ext_functions_data); i++) _cogl_feature_check (_cogl_context_get_winsys (context), "GL", cogl_feature_ext_functions_data + i, - gl_major, gl_minor, gles_version, + gl_major, gl_minor, context->driver, gl_extensions, context); } diff --git a/cogl/cogl-feature-private.h b/cogl/cogl-feature-private.h index b90897b9e..1cf3eed56 100644 --- a/cogl/cogl-feature-private.h +++ b/cogl/cogl-feature-private.h @@ -86,7 +86,7 @@ _cogl_feature_check (const CoglWinsysVtable *winsys, const CoglFeatureData *data, int gl_major, int gl_minor, - CoglExtGlesAvailability gles_version, + CoglDriver driver, const char *extensions_string, void *function_table); @@ -94,7 +94,6 @@ void _cogl_feature_check_ext_functions (CoglContext *context, int gl_major, int gl_minor, - const char *gl_extensions, - CoglExtGlesAvailability gles_version); + const char *gl_extensions); #endif /* __COGL_FEATURE_PRIVATE_H */ diff --git a/cogl/cogl-framebuffer.c b/cogl/cogl-framebuffer.c index d5b4ad439..7cf6048cf 100644 --- a/cogl/cogl-framebuffer.c +++ b/cogl/cogl-framebuffer.c @@ -615,8 +615,9 @@ _cogl_framebuffer_init_bits (CoglFramebuffer *framebuffer) return; #ifdef HAVE_COGL_GL - if (cogl_features_available (COGL_FEATURE_OFFSCREEN) - && framebuffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN) + if (ctx->driver == COGL_DRIVER_GL && + cogl_features_available (COGL_FEATURE_OFFSCREEN) && + framebuffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN) { GLenum attachment, pname; @@ -812,6 +813,8 @@ _cogl_offscreen_new_to_texture_full (CoglHandle texhandle, CoglFramebufferTryFBOData data; gboolean fbo_created; + _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE); + if (!cogl_features_available (COGL_FEATURE_OFFSCREEN)) return COGL_INVALID_HANDLE; @@ -866,7 +869,8 @@ _cogl_offscreen_new_to_texture_full (CoglHandle texhandle, if ((have_working_flags && try_creating_fbo (offscreen, flags, &data)) || #ifdef HAVE_COGL_GL - try_creating_fbo (offscreen, flags = _TRY_DEPTH_STENCIL, &data) || + (ctx->driver == COGL_DRIVER_GL && + try_creating_fbo (offscreen, flags = _TRY_DEPTH_STENCIL, &data)) || #endif try_creating_fbo (offscreen, flags = _TRY_DEPTH | _TRY_STENCIL, &data) || diff --git a/cogl/cogl-glx-renderer-private.h b/cogl/cogl-glx-renderer-private.h index 37dc452e3..101623518 100644 --- a/cogl/cogl-glx-renderer-private.h +++ b/cogl/cogl-glx-renderer-private.h @@ -25,6 +25,7 @@ #ifndef __COGL_RENDERER_GLX_PRIVATE_H #define __COGL_RENDERER_GLX_PRIVATE_H +#include #include "cogl-object-private.h" #include "cogl-xlib-renderer-private.h" @@ -43,6 +44,56 @@ typedef struct _CoglGLXRenderer /* Vblank stuff */ int dri_fd; + /* GModule pointing to libGL which we use to get glX functions out of */ + GModule *libgl_module; + + /* Function pointers for core GLX functionality. We can't just link + against these directly because we need to conditionally load + libGL when we are using GLX so that it won't conflict with a GLES + library if we are using EGL + GLES */ + void + (* glXDestroyContext) (Display *dpy, GLXContext ctx); + void + (* glXSwapBuffers) (Display *dpy, GLXDrawable drawable); + Bool + (* glXQueryExtension) (Display *dpy, int *errorb, int *event); + const char * + (* glXQueryExtensionsString) (Display *dpy, int screen); + Bool + (* glXQueryVersion) (Display *dpy, int *maj, int *min); + Bool + (* glXIsDirect) (Display *dpy, GLXContext ctx); + int + (* glXGetFBConfigAttrib) (Display *dpy, GLXFBConfig config, + int attribute, int *value); + GLXWindow + (* glXCreateWindow) (Display *dpy, GLXFBConfig config, + Window win, const int *attribList); + void + (* glXDestroyWindow) (Display *dpy, GLXWindow window); + GLXPixmap + (* glXCreatePixmap) (Display *dpy, GLXFBConfig config, + Pixmap pixmap, const int *attribList); + void + (* glXDestroyPixmap) (Display *dpy, GLXPixmap pixmap); + GLXContext + (* glXCreateNewContext) (Display *dpy, GLXFBConfig config, + int renderType, GLXContext shareList, + Bool direct); + Bool + (* glXMakeContextCurrent) (Display *dpy, GLXDrawable draw, + GLXDrawable read, GLXContext ctx); + void + (* glXSelectEvent) (Display *dpy, GLXDrawable drawable, + unsigned long mask); + GLXFBConfig * + (* glXGetFBConfigs) (Display *dpy, int screen, int *nelements); + GLXFBConfig * + (* glXChooseFBConfig) (Display *dpy, int screen, + const int *attrib_list, int *nelements); + XVisualInfo * + (* glXGetVisualFromFBConfig) (Display *dpy, GLXFBConfig config); + /* Function pointers for GLX specific extensions */ #define COGL_WINSYS_FEATURE_BEGIN(a, b, c, d, e, f) diff --git a/cogl/cogl-internal.h b/cogl/cogl-internal.h index 71e5766d0..022ea32a9 100644 --- a/cogl/cogl-internal.h +++ b/cogl/cogl-internal.h @@ -123,9 +123,18 @@ _cogl_transform_point (const CoglMatrix *matrix_mv, typedef enum { /*< prefix=COGL_DRIVER_ERROR >*/ COGL_DRIVER_ERROR_UNKNOWN_VERSION, - COGL_DRIVER_ERROR_INVALID_VERSION + COGL_DRIVER_ERROR_INVALID_VERSION, + COGL_DRIVER_ERROR_NO_SUITABLE_DRIVER_FOUND, + COGL_DRIVER_ERROR_FAILED_TO_LOAD_LIBRARY } CoglDriverError; +typedef enum +{ + COGL_DRIVER_GL, + COGL_DRIVER_GLES1, + COGL_DRIVER_GLES2 +} CoglDriver; + typedef enum { COGL_PRIVATE_FEATURE_TEXTURE_2D_FROM_EGL_IMAGE = 1L<<0, diff --git a/cogl/cogl-journal.c b/cogl/cogl-journal.c index 755584bc4..9f073d3ea 100644 --- a/cogl/cogl-journal.c +++ b/cogl/cogl-journal.c @@ -102,10 +102,10 @@ typedef struct _CoglJournalFlushState gsize stride; size_t array_offset; GLuint current_vertex; -#ifndef HAVE_COGL_GL + CoglIndices *indices; gsize indices_type_size; -#endif + CoglMatrixStack *modelview_stack; CoglMatrixStack *projection_stack; @@ -301,35 +301,38 @@ _cogl_journal_flush_modelview_and_entries (CoglJournalEntry *batch_start, draw_flags |= COGL_DRAW_COLOR_ATTRIBUTE_IS_OPAQUE; #ifdef HAVE_COGL_GL - - /* XXX: it's rather evil that we sneak in the GL_QUADS enum here... */ - _cogl_draw_attributes (GL_QUADS, - state->current_vertex, batch_len * 4, - attributes, - state->attributes->len, - draw_flags); - -#else /* HAVE_COGL_GL */ - if (batch_len > 1) + if (ctx->driver == COGL_DRIVER_GL) { - _cogl_draw_indexed_attributes (COGL_VERTICES_MODE_TRIANGLES, - state->current_vertex * 6 / 4, - batch_len * 6, - state->indices, - attributes, - state->attributes->len, - draw_flags); - - } - else - { - _cogl_draw_attributes (COGL_VERTICES_MODE_TRIANGLE_FAN, - state->current_vertex, 4, + /* XXX: it's rather evil that we sneak in the GL_QUADS enum here... */ + _cogl_draw_attributes (GL_QUADS, + state->current_vertex, batch_len * 4, attributes, state->attributes->len, draw_flags); } -#endif + else +#endif /* HAVE_COGL_GL */ + { + if (batch_len > 1) + { + _cogl_draw_indexed_attributes (COGL_VERTICES_MODE_TRIANGLES, + state->current_vertex * 6 / 4, + batch_len * 6, + state->indices, + attributes, + state->attributes->len, + draw_flags); + + } + else + { + _cogl_draw_attributes (COGL_VERTICES_MODE_TRIANGLE_FAN, + state->current_vertex, 4, + attributes, + state->attributes->len, + draw_flags); + } + } /* DEBUGGING CODE XXX: This path will cause all rectangles to be * drawn with a coloured outline. Each batch will be rendered with @@ -619,9 +622,8 @@ _cogl_journal_flush_vbo_offsets_and_entries (CoglJournalEntry *batch_start, 4, COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE); -#ifndef HAVE_COGL_GL - state->indices = cogl_get_rectangle_indices (batch_len); -#endif + if (ctx->driver != COGL_DRIVER_GL) + state->indices = cogl_get_rectangle_indices (batch_len); /* We only create new Attributes when the stride within the * AttributeBuffer changes. (due to a change in the number of pipeline diff --git a/cogl/cogl-matrix-stack.c b/cogl/cogl-matrix-stack.c index d761b5365..09aa0020d 100644 --- a/cogl/cogl-matrix-stack.c +++ b/cogl/cogl-matrix-stack.c @@ -393,7 +393,7 @@ _cogl_matrix_stack_set (CoglMatrixStack *stack, stack->age++; } -#ifndef HAVE_COGL_GLES2 +#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES) static void flush_to_fixed_api_gl (gboolean is_identity, @@ -417,7 +417,7 @@ flush_to_fixed_api_gl (gboolean is_identity, } } -#endif /* HAVE_COGL_GLES2 */ +#endif void _cogl_matrix_stack_prepare_for_flush (CoglMatrixStack *stack, @@ -462,72 +462,74 @@ _cogl_matrix_stack_flush_to_gl (CoglMatrixStack *stack, state = _cogl_matrix_stack_top (stack); -#ifdef HAVE_COGL_GLES2 - - /* Under GLES2 we need to flush the matrices differently because - they are stored in uniforms attached to the program instead of - the global GL context state. At this point we can't be sure that - the right program will be generated so instead we'll just store a - reference to the matrix stack that is intended to be flushed and - update the uniform once the program is ready. */ - - switch (mode) + if (ctx->driver == COGL_DRIVER_GLES2) { - case COGL_MATRIX_MODELVIEW: - cogl_object_ref (stack); - if (ctx->flushed_modelview_stack) - cogl_object_unref (ctx->flushed_modelview_stack); - ctx->flushed_modelview_stack = stack; - break; - - case COGL_MATRIX_PROJECTION: - cogl_object_ref (stack); - if (ctx->flushed_projection_stack) - cogl_object_unref (ctx->flushed_projection_stack); - ctx->flushed_projection_stack = stack; - break; - - case COGL_MATRIX_TEXTURE: - /* This shouldn't happen because the texture matrices are - handled by the GLSL pipeline backend */ - g_assert_not_reached (); - break; - } - -#else /* HAVE_COGL_GLES2 */ - - if (stack->flushed_state == state) - return; - - if (ctx->flushed_matrix_mode != mode) - { - GLenum gl_mode = 0; + /* Under GLES2 we need to flush the matrices differently because + they are stored in uniforms attached to the program instead of + the global GL context state. At this point we can't be sure that + the right program will be generated so instead we'll just store a + reference to the matrix stack that is intended to be flushed and + update the uniform once the program is ready. */ switch (mode) { case COGL_MATRIX_MODELVIEW: - gl_mode = GL_MODELVIEW; + cogl_object_ref (stack); + if (ctx->flushed_modelview_stack) + cogl_object_unref (ctx->flushed_modelview_stack); + ctx->flushed_modelview_stack = stack; break; case COGL_MATRIX_PROJECTION: - gl_mode = GL_PROJECTION; + cogl_object_ref (stack); + if (ctx->flushed_projection_stack) + cogl_object_unref (ctx->flushed_projection_stack); + ctx->flushed_projection_stack = stack; break; case COGL_MATRIX_TEXTURE: - gl_mode = GL_TEXTURE; + /* This shouldn't happen because the texture matrices are + handled by the GLSL pipeline backend */ + g_assert_not_reached (); break; } - - GE (ctx, glMatrixMode (gl_mode)); - ctx->flushed_matrix_mode = mode; } - _cogl_matrix_stack_prepare_for_flush (stack, - mode, - flush_to_fixed_api_gl, - stack); +#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES) + else + { + if (stack->flushed_state == state) + return; -#endif /* HAVE_COGL_GLES2 */ + if (ctx->flushed_matrix_mode != mode) + { + GLenum gl_mode = 0; + + switch (mode) + { + case COGL_MATRIX_MODELVIEW: + gl_mode = GL_MODELVIEW; + break; + + case COGL_MATRIX_PROJECTION: + gl_mode = GL_PROJECTION; + break; + + case COGL_MATRIX_TEXTURE: + gl_mode = GL_TEXTURE; + break; + } + + GE (ctx, glMatrixMode (gl_mode)); + ctx->flushed_matrix_mode = mode; + } + + _cogl_matrix_stack_prepare_for_flush (stack, + mode, + flush_to_fixed_api_gl, + stack); + } +#endif stack->flushed_state = state; } diff --git a/cogl/cogl-pipeline-fragend-arbfp.c b/cogl/cogl-pipeline-fragend-arbfp.c index ef0735779..3f24edb2c 100644 --- a/cogl/cogl-pipeline-fragend-arbfp.c +++ b/cogl/cogl-pipeline-fragend-arbfp.c @@ -225,9 +225,9 @@ _cogl_pipeline_fragend_arbfp_start (CoglPipeline *pipeline, */ authority = _cogl_pipeline_find_equivalent_parent (pipeline, - COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN & + _cogl_pipeline_get_state_for_fragment_codegen (ctx) & ~COGL_PIPELINE_STATE_LAYERS, - COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN); + _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx)); authority_priv = get_arbfp_priv (authority); if (authority_priv && authority_priv->arbfp_program_state) @@ -318,12 +318,18 @@ _cogl_pipeline_fragend_arbfp_start (CoglPipeline *pipeline, unsigned int _cogl_pipeline_fragend_arbfp_hash (const void *data) { - unsigned long fragment_state = - COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN; - unsigned long layer_fragment_state = - COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN; + unsigned int fragment_state; + unsigned int layer_fragment_state; + + _COGL_GET_CONTEXT (ctx, 0); + + fragment_state = + _cogl_pipeline_get_state_for_fragment_codegen (ctx); + layer_fragment_state = + _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx); return _cogl_pipeline_hash ((CoglPipeline *)data, + fragment_state, layer_fragment_state, 0); } @@ -331,10 +337,15 @@ _cogl_pipeline_fragend_arbfp_hash (const void *data) gboolean _cogl_pipeline_fragend_arbfp_equal (const void *a, const void *b) { - unsigned long fragment_state = - COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN; - unsigned long layer_fragment_state = - COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN; + unsigned int fragment_state; + unsigned int layer_fragment_state; + + _COGL_GET_CONTEXT (ctx, 0); + + fragment_state = + _cogl_pipeline_get_state_for_fragment_codegen (ctx); + layer_fragment_state = + _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx); return _cogl_pipeline_equal ((CoglPipeline *)a, (CoglPipeline *)b, fragment_state, layer_fragment_state, @@ -344,12 +355,9 @@ _cogl_pipeline_fragend_arbfp_equal (const void *a, const void *b) static const char * gl_target_to_arbfp_string (GLenum gl_target) { -#ifndef HAVE_COGL_GLES2 if (gl_target == GL_TEXTURE_1D) return "1D"; - else -#endif - if (gl_target == GL_TEXTURE_2D) + else if (gl_target == GL_TEXTURE_2D) return "2D"; #ifdef GL_ARB_texture_rectangle else if (gl_target == GL_TEXTURE_RECTANGLE_ARB) @@ -1028,7 +1036,9 @@ _cogl_pipeline_fragend_arbfp_pipeline_pre_change_notify ( CoglPipelineState change, const CoglColor *new_color) { - if ((change & COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN)) + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if ((change & _cogl_pipeline_get_state_for_fragment_codegen (ctx))) dirty_arbfp_program_state (pipeline); } @@ -1047,10 +1057,13 @@ _cogl_pipeline_fragend_arbfp_layer_pre_change_notify ( CoglPipelineLayerState change) { CoglPipelineFragendARBfpPrivate *priv = get_arbfp_priv (owner); + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + if (!priv) return; - if ((change & COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN)) + if ((change & _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx))) { dirty_arbfp_program_state (owner); return; diff --git a/cogl/cogl-pipeline-fragend-fixed.c b/cogl/cogl-pipeline-fragend-fixed.c index ebd2ec877..97fe04382 100644 --- a/cogl/cogl-pipeline-fragend-fixed.c +++ b/cogl/cogl-pipeline-fragend-fixed.c @@ -92,9 +92,14 @@ _cogl_pipeline_fragend_fixed_start (CoglPipeline *pipeline, { CoglHandle user_program; + _COGL_GET_CONTEXT (ctx, FALSE); + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_FIXED))) return FALSE; + if (ctx->driver == COGL_DRIVER_GLES2) + return FALSE; + /* If there is a user program with a fragment shader then the appropriate backend for that language should handle it. We can still use the fixed fragment backend if the program only contains @@ -319,20 +324,19 @@ _cogl_pipeline_fragend_fixed_end (CoglPipeline *pipeline, GE (ctx, glFogfv (GL_FOG_COLOR, fogColor)); -#if HAVE_COGL_GLES - switch (fog_state->mode) - { - case COGL_FOG_MODE_LINEAR: - gl_mode = GL_LINEAR; - break; - case COGL_FOG_MODE_EXPONENTIAL: - gl_mode = GL_EXP; - break; - case COGL_FOG_MODE_EXPONENTIAL_SQUARED: - gl_mode = GL_EXP2; - break; - } -#endif + if (ctx->driver == COGL_DRIVER_GLES1) + switch (fog_state->mode) + { + case COGL_FOG_MODE_LINEAR: + gl_mode = GL_LINEAR; + break; + case COGL_FOG_MODE_EXPONENTIAL: + gl_mode = GL_EXP; + break; + case COGL_FOG_MODE_EXPONENTIAL_SQUARED: + gl_mode = GL_EXP2; + break; + } /* TODO: support other modes for GLES2 */ /* NB: GLES doesn't have glFogi */ diff --git a/cogl/cogl-pipeline-fragend-glsl.c b/cogl/cogl-pipeline-fragend-glsl.c index a0787c404..32b355d17 100644 --- a/cogl/cogl-pipeline-fragend-glsl.c +++ b/cogl/cogl-pipeline-fragend-glsl.c @@ -227,9 +227,9 @@ _cogl_pipeline_fragend_glsl_start (CoglPipeline *pipeline, */ authority = _cogl_pipeline_find_equivalent_parent (pipeline, - COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN & + _cogl_pipeline_get_state_for_fragment_codegen (ctx) & ~COGL_PIPELINE_STATE_LAYERS, - COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN); + _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx)); authority_priv = get_glsl_priv (authority); if (!authority_priv) @@ -339,6 +339,8 @@ add_texture_lookup (GlslShaderState *glsl_shader_state, int unit_index = _cogl_pipeline_layer_get_unit_index (layer); const char *target_string, *tex_coord_swizzle; + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_TEXTURING))) { g_string_append (glsl_shader_state->source, @@ -362,7 +364,7 @@ add_texture_lookup (GlslShaderState *glsl_shader_state, cogl_texture_get_gl_texture (texture, NULL, &gl_target); switch (gl_target) { -#ifndef HAVE_COGL_GLES2 +#ifdef HAVE_COGL_GL case GL_TEXTURE_1D: target_string = "1D"; tex_coord_swizzle = "s"; @@ -413,14 +415,13 @@ add_texture_lookup (GlslShaderState *glsl_shader_state, supports the gl_PointCoord variable, it requires GLSL 1.2 which would mean we would have to declare the GLSL version and check for it */ -#ifdef HAVE_COGL_GLES2 - if (cogl_pipeline_get_layer_point_sprite_coords_enabled (pipeline, + if (ctx->driver == COGL_DRIVER_GLES2 && + cogl_pipeline_get_layer_point_sprite_coords_enabled (pipeline, layer->index)) g_string_append_printf (glsl_shader_state->source, "gl_PointCoord.%s", tex_coord_swizzle); else -#endif g_string_append_printf (glsl_shader_state->source, "cogl_tex_coord_in[%d].%s", unit_index, tex_coord_swizzle); @@ -782,7 +783,8 @@ _cogl_pipeline_fragend_glsl_end (CoglPipeline *pipeline, COGL_COUNTER_INC (_cogl_uprof_context, fragend_glsl_compile_counter); #ifdef HAVE_COGL_GLES2 - add_alpha_test_snippet (pipeline, glsl_shader_state); + if (ctx->driver == COGL_DRIVER_GLES2) + add_alpha_test_snippet (pipeline, glsl_shader_state); #endif g_string_append (glsl_shader_state->source, "}\n"); @@ -833,7 +835,9 @@ _cogl_pipeline_fragend_glsl_pre_change_notify (CoglPipeline *pipeline, CoglPipelineState change, const CoglColor *new_color) { - if ((change & COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN)) + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if ((change & _cogl_pipeline_get_state_for_fragment_codegen (ctx))) dirty_glsl_shader_state (pipeline); } @@ -853,11 +857,13 @@ _cogl_pipeline_fragend_glsl_layer_pre_change_notify ( { CoglPipelineFragendGlslPrivate *priv; + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + priv = get_glsl_priv (owner); if (!priv) return; - if ((change & COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN)) + if ((change & _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx))) { dirty_glsl_shader_state (owner); return; diff --git a/cogl/cogl-pipeline-opengl.c b/cogl/cogl-pipeline-opengl.c index 836a8017b..1b15b557a 100644 --- a/cogl/cogl-pipeline-opengl.c +++ b/cogl/cogl-pipeline-opengl.c @@ -240,12 +240,6 @@ _cogl_pipeline_texture_storage_change_notify (CoglHandle texture) static void set_glsl_program (GLuint gl_program) { -#ifdef HAVE_COGL_GLES - - g_return_if_reached (); - -#else /* HAVE_COGL_GLES */ - _COGL_GET_CONTEXT (ctx, NO_RETVAL); if (ctx->current_gl_program != gl_program) @@ -263,8 +257,6 @@ set_glsl_program (GLuint gl_program) ctx->current_gl_program = 0; } } - -#endif /* HAVE_COGL_GLES */ } void @@ -415,7 +407,7 @@ _cogl_get_max_texture_image_units (void) } #endif -#ifndef HAVE_COGL_GLES +#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL) static gboolean blend_factor_uses_constant (GLenum blend_factor) @@ -446,21 +438,20 @@ flush_depth_state (CoglDepthState *depth_state) ctx->depth_writing_enabled_cache = depth_state->write_enabled; } -#ifndef COGL_HAS_GLES - if (ctx->depth_range_near_cache != depth_state->range_near || - ctx->depth_range_far_cache != depth_state->range_far) + if (ctx->driver != COGL_DRIVER_GLES1 && + (ctx->depth_range_near_cache != depth_state->range_near || + ctx->depth_range_far_cache != depth_state->range_far)) { -#ifdef COGL_HAS_GLES2 - GE (ctx, glDepthRangef (depth_state->range_near, - depth_state->range_far)); -#else - GE (ctx, glDepthRange (depth_state->range_near, - depth_state->range_far)); -#endif + if (ctx->driver == COGL_DRIVER_GLES2) + GE (ctx, glDepthRangef (depth_state->range_near, + depth_state->range_far)); + else + GE (ctx, glDepthRange (depth_state->range_near, + depth_state->range_far)); + ctx->depth_range_near_cache = depth_state->range_near; ctx->depth_range_far_cache = depth_state->range_far; } -#endif /* COGL_HAS_GLES */ } static void @@ -472,8 +463,8 @@ _cogl_pipeline_flush_color_blend_alpha_depth_state ( _COGL_GET_CONTEXT (ctx, NO_RETVAL); /* On GLES2 we'll flush the color later */ -#ifndef HAVE_COGL_GLES2 - if (!skip_gl_color) + if (ctx->driver != COGL_DRIVER_GLES2 && + !skip_gl_color) { if ((pipelines_difference & COGL_PIPELINE_STATE_COLOR) || /* Assume if we were previously told to skip the color, then @@ -488,7 +479,6 @@ _cogl_pipeline_flush_color_blend_alpha_depth_state ( cogl_color_get_alpha_byte (&authority->color))); } } -#endif if (pipelines_difference & COGL_PIPELINE_STATE_BLEND) { @@ -497,97 +487,103 @@ _cogl_pipeline_flush_color_blend_alpha_depth_state ( CoglPipelineBlendState *blend_state = &authority->big_state->blend_state; -#if defined (HAVE_COGL_GLES2) - gboolean have_blend_equation_seperate = TRUE; - gboolean have_blend_func_separate = TRUE; -#elif defined (HAVE_COGL_GL) - gboolean have_blend_equation_seperate = FALSE; - gboolean have_blend_func_separate = FALSE; - if (ctx->glBlendEquationSeparate) /* Only GL 2.0 + */ - have_blend_equation_seperate = TRUE; - if (ctx->glBlendFuncSeparate) /* Only GL 1.4 + */ - have_blend_func_separate = TRUE; -#endif - -#ifndef HAVE_COGL_GLES /* GLES 1 only has glBlendFunc */ - if (blend_factor_uses_constant (blend_state->blend_src_factor_rgb) || - blend_factor_uses_constant (blend_state->blend_src_factor_alpha) || - blend_factor_uses_constant (blend_state->blend_dst_factor_rgb) || - blend_factor_uses_constant (blend_state->blend_dst_factor_alpha)) + /* GLES 1 only has glBlendFunc */ + if (ctx->driver == COGL_DRIVER_GLES1) { - float red = - cogl_color_get_red_float (&blend_state->blend_constant); - float green = - cogl_color_get_green_float (&blend_state->blend_constant); - float blue = - cogl_color_get_blue_float (&blend_state->blend_constant); - float alpha = - cogl_color_get_alpha_float (&blend_state->blend_constant); + GE (ctx, glBlendFunc (blend_state->blend_src_factor_rgb, + blend_state->blend_dst_factor_rgb)); + } +#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL) + else + { + if (blend_factor_uses_constant (blend_state->blend_src_factor_rgb) || + blend_factor_uses_constant (blend_state + ->blend_src_factor_alpha) || + blend_factor_uses_constant (blend_state->blend_dst_factor_rgb) || + blend_factor_uses_constant (blend_state->blend_dst_factor_alpha)) + { + float red = + cogl_color_get_red_float (&blend_state->blend_constant); + float green = + cogl_color_get_green_float (&blend_state->blend_constant); + float blue = + cogl_color_get_blue_float (&blend_state->blend_constant); + float alpha = + cogl_color_get_alpha_float (&blend_state->blend_constant); - GE (ctx, glBlendColor (red, green, blue, alpha)); + GE (ctx, glBlendColor (red, green, blue, alpha)); + } + + if (ctx->glBlendEquationSeparate && + blend_state->blend_equation_rgb != + blend_state->blend_equation_alpha) + GE (ctx, + glBlendEquationSeparate (blend_state->blend_equation_rgb, + blend_state->blend_equation_alpha)); + else + GE (ctx, glBlendEquation (blend_state->blend_equation_rgb)); + + if (ctx->glBlendFuncSeparate && + (blend_state->blend_src_factor_rgb != + blend_state->blend_src_factor_alpha || + (blend_state->blend_src_factor_rgb != + blend_state->blend_src_factor_alpha))) + GE (ctx, glBlendFuncSeparate (blend_state->blend_src_factor_rgb, + blend_state->blend_dst_factor_rgb, + blend_state->blend_src_factor_alpha, + blend_state->blend_dst_factor_alpha)); + else + GE (ctx, glBlendFunc (blend_state->blend_src_factor_rgb, + blend_state->blend_dst_factor_rgb)); + } +#endif + } + +#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES) + + if (ctx->driver != COGL_DRIVER_GLES2) + { + /* Under GLES2 the alpha function is implemented as part of the + fragment shader */ + if (pipelines_difference & (COGL_PIPELINE_STATE_ALPHA_FUNC | + COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE)) + { + CoglPipeline *authority = + _cogl_pipeline_get_authority (pipeline, + COGL_PIPELINE_STATE_ALPHA_FUNC); + CoglPipelineAlphaFuncState *alpha_state = + &authority->big_state->alpha_state; + + /* NB: Currently the Cogl defines are compatible with the GL ones: */ + GE (ctx, glAlphaFunc (alpha_state->alpha_func, + alpha_state->alpha_func_reference)); } - if (have_blend_equation_seperate && - blend_state->blend_equation_rgb != blend_state->blend_equation_alpha) - GE (ctx, glBlendEquationSeparate (blend_state->blend_equation_rgb, - blend_state->blend_equation_alpha)); - else - GE (ctx, glBlendEquation (blend_state->blend_equation_rgb)); + /* Under GLES2 the lighting parameters are implemented as uniforms + in the progend */ + if (pipelines_difference & COGL_PIPELINE_STATE_LIGHTING) + { + CoglPipeline *authority = + _cogl_pipeline_get_authority (pipeline, + COGL_PIPELINE_STATE_LIGHTING); + CoglPipelineLightingState *lighting_state = + &authority->big_state->lighting_state; + + GE (ctx, glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, + lighting_state->ambient)); + GE (ctx, glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, + lighting_state->diffuse)); + GE (ctx, glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, + lighting_state->specular)); + GE (ctx, glMaterialfv (GL_FRONT_AND_BACK, GL_EMISSION, + lighting_state->emission)); + GE (ctx, glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS, + &lighting_state->shininess)); + } + } - if (have_blend_func_separate && - (blend_state->blend_src_factor_rgb != blend_state->blend_src_factor_alpha || - (blend_state->blend_src_factor_rgb != - blend_state->blend_src_factor_alpha))) - GE (ctx, glBlendFuncSeparate (blend_state->blend_src_factor_rgb, - blend_state->blend_dst_factor_rgb, - blend_state->blend_src_factor_alpha, - blend_state->blend_dst_factor_alpha)); - else #endif - GE (ctx, glBlendFunc (blend_state->blend_src_factor_rgb, - blend_state->blend_dst_factor_rgb)); - } - -#ifndef HAVE_COGL_GLES2 - - /* Under GLES2 the alpha function is implemented as part of the - fragment shader */ - if (pipelines_difference & (COGL_PIPELINE_STATE_ALPHA_FUNC | - COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE)) - { - CoglPipeline *authority = - _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_ALPHA_FUNC); - CoglPipelineAlphaFuncState *alpha_state = - &authority->big_state->alpha_state; - - /* NB: Currently the Cogl defines are compatible with the GL ones: */ - GE (ctx, glAlphaFunc (alpha_state->alpha_func, - alpha_state->alpha_func_reference)); - } - - /* Under GLES2 the lighting parameters are implemented as uniforms - in the progend */ - if (pipelines_difference & COGL_PIPELINE_STATE_LIGHTING) - { - CoglPipeline *authority = - _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LIGHTING); - CoglPipelineLightingState *lighting_state = - &authority->big_state->lighting_state; - - GE (ctx, glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, - lighting_state->ambient)); - GE (ctx, glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, - lighting_state->diffuse)); - GE (ctx, glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, - lighting_state->specular)); - GE (ctx, glMaterialfv (GL_FRONT_AND_BACK, GL_EMISSION, - lighting_state->emission)); - GE (ctx, glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS, - &lighting_state->shininess)); - } - -#endif /* HAVE_COGL_GLES2 */ if (pipelines_difference & COGL_PIPELINE_STATE_DEPTH) { @@ -635,45 +631,54 @@ get_max_activateable_texture_units (void) int i; #ifdef HAVE_COGL_GL - /* GL_MAX_TEXTURE_COORDS is provided for both GLSL and ARBfp. It - defines the number of texture coordinates that can be - uploaded (but doesn't necessarily relate to how many texture - images can be sampled) */ - if (cogl_features_available (COGL_FEATURE_SHADERS_GLSL) || - cogl_features_available (COGL_FEATURE_SHADERS_ARBFP)) - /* Previously this code subtracted the value by one but there - was no explanation for why it did this and it doesn't seem - to make sense so it has been removed */ - GE (ctx, glGetIntegerv (GL_MAX_TEXTURE_COORDS, values + n_values++)); + if (ctx->driver == COGL_DRIVER_GL) + { + /* GL_MAX_TEXTURE_COORDS is provided for both GLSL and ARBfp. It + defines the number of texture coordinates that can be + uploaded (but doesn't necessarily relate to how many texture + images can be sampled) */ + if (cogl_features_available (COGL_FEATURE_SHADERS_GLSL) || + cogl_features_available (COGL_FEATURE_SHADERS_ARBFP)) + /* Previously this code subtracted the value by one but there + was no explanation for why it did this and it doesn't seem + to make sense so it has been removed */ + GE (ctx, glGetIntegerv (GL_MAX_TEXTURE_COORDS, + values + n_values++)); - /* GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS is defined for GLSL but - not ARBfp */ - if (cogl_features_available (COGL_FEATURE_SHADERS_GLSL)) - GE (ctx, glGetIntegerv (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, - values + n_values++)); + /* GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS is defined for GLSL but + not ARBfp */ + if (cogl_features_available (COGL_FEATURE_SHADERS_GLSL)) + GE (ctx, glGetIntegerv (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, + values + n_values++)); + } #endif /* HAVE_COGL_GL */ #ifdef HAVE_COGL_GLES2 + if (ctx->driver == COGL_DRIVER_GLES2) + { + GE (ctx, glGetIntegerv (GL_MAX_VERTEX_ATTRIBS, values + n_values)); + /* Two of the vertex attribs need to be used for the position + and color */ + values[n_values++] -= 2; - GE (ctx, glGetIntegerv (GL_MAX_VERTEX_ATTRIBS, values + n_values)); - /* Two of the vertex attribs need to be used for the position - and color */ - values[n_values++] -= 2; + GE (ctx, glGetIntegerv (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, + values + n_values++)); + } +#endif - GE (ctx, glGetIntegerv (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, - values + n_values++)); +#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES) /* not GLES2 */ + if (ctx->driver != COGL_DRIVER_GLES2) + { + /* GL_MAX_TEXTURE_UNITS defines the number of units that are + usable from the fixed function pipeline, therefore it isn't + available in GLES2. These are also tied to the number of + texture coordinates that can be uploaded so it should be less + than that available from the shader extensions */ + GE (ctx, glGetIntegerv (GL_MAX_TEXTURE_UNITS, + values + n_values++)); -#else /* HAVE_COGL_GLES2 */ - - /* GL_MAX_TEXTURE_UNITS defines the number of units that are - usable from the fixed function pipeline, therefore it isn't - available in GLES2. These are also tied to the number of - texture coordinates that can be uploaded so it should be less - than that available from the shader extensions */ - GE (ctx, glGetIntegerv (GL_MAX_TEXTURE_UNITS, - values + n_values++)); - -#endif /* HAVE_COGL_GLES2 */ + } +#endif g_assert (n_values <= G_N_ELEMENTS (values) && n_values > 0); @@ -786,8 +791,9 @@ flush_layers_common_gl_state_cb (CoglPipelineLayer *layer, void *user_data) /* Under GLES2 the fragment shader will use gl_PointCoord instead of replacing the texture coordinates */ -#ifndef HAVE_COGL_GLES2 - if (layers_difference & COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS) +#if defined (HAVE_COGL_GLES) || defined (HAVE_COGL_GL) + if (ctx->driver != COGL_DRIVER_GLES2 && + (layers_difference & COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS)) { CoglPipelineState change = COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS; CoglPipelineLayer *authority = @@ -799,7 +805,7 @@ flush_layers_common_gl_state_cb (CoglPipelineLayer *layer, void *user_data) GE (ctx, glTexEnvi (GL_POINT_SPRITE, GL_COORD_REPLACE, big_state->point_sprite_coords)); } -#endif /* HAVE_COGL_GLES2 */ +#endif cogl_handle_ref (layer); if (unit->layer != COGL_INVALID_HANDLE) @@ -1299,7 +1305,7 @@ done: of the program object so they could be overridden by any attribute changes in another program */ #ifdef HAVE_COGL_GLES2 - if (!skip_gl_color) + if (ctx->driver == COGL_DRIVER_GLES2 && !skip_gl_color) { int attribute; CoglPipeline *authority = diff --git a/cogl/cogl-pipeline-private.h b/cogl/cogl-pipeline-private.h index 897ae35b8..ba0fabf26 100644 --- a/cogl/cogl-pipeline-private.h +++ b/cogl/cogl-pipeline-private.h @@ -41,58 +41,97 @@ typedef struct _CoglPipelineLayer CoglPipelineLayer; #define COGL_PIPELINE_LAYER(OBJECT) ((CoglPipelineLayer *)OBJECT) -#if defined (HAVE_COGL_GL) +#ifdef HAVE_COGL_GL -/* NB: pipeline->fragend is currently a 3bit unsigned int bitfield */ -#define COGL_PIPELINE_FRAGEND_ARBFP 0 -#define COGL_PIPELINE_FRAGEND_ARBFP_MASK (1L<<0) -#define COGL_PIPELINE_FRAGEND_FIXED 1 -#define COGL_PIPELINE_FRAGEND_FIXED_MASK (1L<<1) -#define COGL_PIPELINE_FRAGEND_GLSL 2 -#define COGL_PIPELINE_FRAGEND_GLSL_MASK (1L<<2) +#define COGL_PIPELINE_FRAGEND_ARBFP 0 +#define COGL_PIPELINE_FRAGEND_FIXED 1 +#define COGL_PIPELINE_FRAGEND_GLSL 2 +#define COGL_PIPELINE_N_FRAGENDS 3 -#define COGL_PIPELINE_N_FRAGENDS 3 +#else /* HAVE_COGL_GL */ -#elif defined (HAVE_COGL_GLES2) +#ifdef HAVE_COGL_GLES2 -#define COGL_PIPELINE_FRAGEND_GLSL 0 -#define COGL_PIPELINE_FRAGEND_GLSL_MASK (1L<<0) +#define COGL_PIPELINE_FRAGEND_GLSL 0 +#ifdef HAVE_COGL_GLES +#define COGL_PIPELINE_FRAGEND_FIXED 1 +#define COGL_PIPELINE_N_FRAGENDS 2 +#else +#define COGL_PIPELINE_N_FRAGENDS 1 +#endif -#define COGL_PIPELINE_N_FRAGENDS 1 +#else /* HAVE_COGL_GLES2 */ -#else /* HAVE_COGL_GLES */ +#ifdef HAVE_COGL_GLES +#define COGL_PIPELINE_FRAGEND_FIXED 0 +#define COGL_PIPELINE_N_FRAGENDS 1 +#else +#error No drivers defined +#endif -#define COGL_PIPELINE_FRAGEND_FIXED 0 -#define COGL_PIPELINE_FRAGEND_FIXED_MASK (1L<<0) +#endif /* HAVE_COGL_GLES2 */ -#define COGL_PIPELINE_N_FRAGENDS 1 +#endif /* HAVE_COGL_GL */ +#ifdef COGL_PIPELINE_FRAGEND_ARBFP +#define COGL_PIPELINE_FRAGEND_ARBFP_MASK \ + (1 << COGL_PIPELINE_FRAGEND_ARBFP) +#endif +#ifdef COGL_PIPELINE_FRAGEND_FIXED +#define COGL_PIPELINE_FRAGEND_FIXED_MASK \ + (1 << COGL_PIPELINE_FRAGEND_FIXED) +#endif +#ifdef COGL_PIPELINE_FRAGEND_GLSL +#define COGL_PIPELINE_FRAGEND_GLSL_MASK \ + (1 << COGL_PIPELINE_FRAGEND_GLSL) #endif #define COGL_PIPELINE_FRAGEND_DEFAULT 0 #define COGL_PIPELINE_FRAGEND_UNDEFINED 3 -#if defined (HAVE_COGL_GL) +#ifdef HAVE_COGL_GL -#define COGL_PIPELINE_VERTEND_FIXED 0 -#define COGL_PIPELINE_VERTEND_GLSL 1 +#define COGL_PIPELINE_VERTEND_FIXED 0 +#define COGL_PIPELINE_VERTEND_GLSL 1 +#define COGL_PIPELINE_N_VERTENDS 2 -#define COGL_PIPELINE_N_VERTENDS 2 +#else /* HAVE_COGL_GL */ -#elif defined (HAVE_COGL_GLES2) - -#define COGL_PIPELINE_VERTEND_GLSL 0 - -#define COGL_PIPELINE_N_VERTENDS 1 - -#else /* HAVE_COGL_GLES */ - -#define COGL_PIPELINE_VERTEND_FIXED 0 - -#define COGL_PIPELINE_N_VERTENDS 1 +#ifdef HAVE_COGL_GLES2 +#define COGL_PIPELINE_VERTEND_GLSL 0 +#ifdef HAVE_COGL_GLES +#define COGL_PIPELINE_VERTEND_FIXED 1 +#define COGL_PIPELINE_N_VERTENDS 2 +#else +#define COGL_PIPELINE_N_VERTENDS 1 #endif +#else /* HAVE_COGL_GLES2 */ + +#ifdef HAVE_COGL_GLES +#define COGL_PIPELINE_VERTEND_FIXED 0 +#define COGL_PIPELINE_N_VERTENDS 1 +#else +#error No drivers defined +#endif /* HAVE_COGL_GLES */ + +#endif /* HAVE_COGL_GLES2 */ + +#endif /* HAVE_COGL_GL */ + +#ifdef COGL_PIPELINE_VERTEND_FIXED +#define COGL_PIPELINE_VERTEND_FIXED_MASK \ + (1 << COGL_PIPELINE_VERTEND_FIXED) +#endif +#ifdef COGL_PIPELINE_VERTEND_GLSL +#define COGL_PIPELINE_VERTEND_GLSL_MASK \ + (1 << COGL_PIPELINE_VERTEND_GLSL) +#endif + +#define COGL_PIPELINE_VERTEND_DEFAULT 0 +#define COGL_PIPELINE_VERTEND_UNDEFINED 3 + #define COGL_PIPELINE_VERTEND_DEFAULT 0 #define COGL_PIPELINE_VERTEND_UNDEFINED 3 @@ -187,23 +226,6 @@ typedef enum COGL_PIPELINE_LAYER_STATE_WRAP_MODES | \ COGL_PIPELINE_LAYER_STATE_COMBINE) -/* FIXME: Only texture target changes should really affect the - * codegen, but this is difficult to detect */ -#ifdef HAVE_COGL_GLES2 -/* On GLES2 we need to use a different varying for the texture lookups - * when point sprite coords are enabled */ -#define COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN \ - (COGL_PIPELINE_LAYER_STATE_COMBINE | \ - COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET | \ - COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS | \ - COGL_PIPELINE_LAYER_STATE_UNIT) -#else -#define COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN \ - (COGL_PIPELINE_LAYER_STATE_COMBINE | \ - COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET | \ - COGL_PIPELINE_LAYER_STATE_UNIT) -#endif - #define COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN 0 @@ -491,19 +513,6 @@ typedef enum _CoglPipelineState COGL_PIPELINE_STATE_DEPTH | \ COGL_PIPELINE_STATE_FOG) -#ifdef HAVE_COGL_GLES2 - /* Under GLES2 the alpha func becomes part of the fragment program - so we can't share programs there */ -#define COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN \ - (COGL_PIPELINE_STATE_LAYERS | \ - COGL_PIPELINE_STATE_ALPHA_FUNC | \ - COGL_PIPELINE_STATE_USER_SHADER) -#else -#define COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN \ - (COGL_PIPELINE_STATE_LAYERS | \ - COGL_PIPELINE_STATE_USER_SHADER) -#endif - #define COGL_PIPELINE_STATE_AFFECTS_VERTEX_CODEGEN \ (COGL_PIPELINE_STATE_LAYERS | \ COGL_PIPELINE_STATE_USER_SHADER) @@ -546,7 +555,7 @@ typedef enum _CoglPipelineBlendEnable typedef struct { /* Determines how this pipeline is blended with other primitives */ -#ifndef HAVE_COGL_GLES +#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL) GLenum blend_equation_rgb; GLenum blend_equation_alpha; GLint blend_src_factor_alpha; @@ -1240,5 +1249,11 @@ _cogl_pipeline_init_state_hash_functions (void); void _cogl_pipeline_init_layer_state_hash_functions (void); +CoglPipelineLayerState +_cogl_pipeline_get_layer_state_for_fragment_codegen (CoglContext *context); + +CoglPipelineState +_cogl_pipeline_get_state_for_fragment_codegen (CoglContext *context); + #endif /* __COGL_PIPELINE_PRIVATE_H */ diff --git a/cogl/cogl-pipeline-progend-glsl.c b/cogl/cogl-pipeline-progend-glsl.c index 51be8d128..ae8e0af66 100644 --- a/cogl/cogl-pipeline-progend-glsl.c +++ b/cogl/cogl-pipeline-progend-glsl.c @@ -301,8 +301,11 @@ destroy_glsl_priv (void *user_data) if (--priv->ref_count == 0) { #ifdef HAVE_COGL_GLES2 - clear_attribute_cache (priv); - clear_flushed_matrix_stacks (priv); + if (ctx->driver == COGL_DRIVER_GLES2) + { + clear_attribute_cache (priv); + clear_flushed_matrix_stacks (priv); + } #endif if (priv->program) @@ -411,17 +414,18 @@ get_uniform_cb (CoglPipeline *pipeline, unit_state->combine_constant_uniform = uniform_location; #ifdef HAVE_COGL_GLES2 + if (ctx->driver == COGL_DRIVER_GLES2) + { + g_string_set_size (ctx->codegen_source_buffer, 0); + g_string_append_printf (ctx->codegen_source_buffer, + "cogl_texture_matrix[%i]", state->unit); - g_string_set_size (ctx->codegen_source_buffer, 0); - g_string_append_printf (ctx->codegen_source_buffer, - "cogl_texture_matrix[%i]", state->unit); - - GE_RET( uniform_location, - ctx, glGetUniformLocation (state->gl_program, - ctx->codegen_source_buffer->str) ); - - unit_state->texture_matrix_uniform = uniform_location; + GE_RET( uniform_location, + ctx, glGetUniformLocation (state->gl_program, + ctx->codegen_source_buffer->str) ); + unit_state->texture_matrix_uniform = uniform_location; + } #endif state->unit++; @@ -454,7 +458,8 @@ update_constants_cb (CoglPipeline *pipeline, #ifdef HAVE_COGL_GLES2 - if (unit_state->texture_matrix_uniform != -1 && + if (ctx->driver == COGL_DRIVER_GLES2 && + unit_state->texture_matrix_uniform != -1 && (state->update_all || unit_state->dirty_texture_matrix)) { const CoglMatrix *matrix; @@ -529,9 +534,9 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline, authority = _cogl_pipeline_find_equivalent_parent (pipeline, (COGL_PIPELINE_STATE_AFFECTS_VERTEX_CODEGEN | - COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN) & + _cogl_pipeline_get_state_for_fragment_codegen (ctx)) & ~COGL_PIPELINE_STATE_LAYERS, - COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN | + _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx) | COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN); priv = get_glsl_priv (authority); @@ -591,7 +596,8 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline, /* Find the largest count of texture coordinate attributes * associated with each of the shaders so we can ensure a consistent * _cogl_tex_coord[] array declaration across all of the shaders.*/ - if (user_program) + if (ctx->driver == COGL_DRIVER_GLES2 && + user_program) for (l = user_program->attached_shaders; l; l = l->next) { CoglShader *shader = l->data; @@ -655,35 +661,40 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline, &state); #ifdef HAVE_COGL_GLES2 - if (program_changed) + if (ctx->driver == COGL_DRIVER_GLES2) { - int i; + if (program_changed) + { + int i; - clear_attribute_cache (priv); - clear_flushed_matrix_stacks (priv); + clear_attribute_cache (priv); + clear_flushed_matrix_stacks (priv); - for (i = 0; i < G_N_ELEMENTS (builtin_uniforms); i++) - GE_RET( priv->builtin_uniform_locations[i], - ctx, glGetUniformLocation (gl_program, - builtin_uniforms[i].uniform_name) ); + for (i = 0; i < G_N_ELEMENTS (builtin_uniforms); i++) + GE_RET( priv->builtin_uniform_locations[i], + ctx, + glGetUniformLocation (gl_program, + builtin_uniforms[i].uniform_name) ); - GE_RET( priv->modelview_uniform, - ctx, glGetUniformLocation (gl_program, - "cogl_modelview_matrix") ); + GE_RET( priv->modelview_uniform, + ctx, glGetUniformLocation (gl_program, + "cogl_modelview_matrix") ); - GE_RET( priv->projection_uniform, - ctx, glGetUniformLocation (gl_program, - "cogl_projection_matrix") ); + GE_RET( priv->projection_uniform, + ctx, glGetUniformLocation (gl_program, + "cogl_projection_matrix") ); - GE_RET( priv->mvp_uniform, - ctx, glGetUniformLocation (gl_program, - "cogl_modelview_projection_matrix") ); + GE_RET( priv->mvp_uniform, + ctx, + glGetUniformLocation (gl_program, + "cogl_modelview_projection_matrix") ); + } + if (program_changed || + priv->last_used_for_pipeline != pipeline) + priv->dirty_builtin_uniforms = ~(unsigned long) 0; + + update_builtin_uniforms (pipeline, gl_program, priv); } - if (program_changed || - priv->last_used_for_pipeline != pipeline) - priv->dirty_builtin_uniforms = ~(unsigned long) 0; - - update_builtin_uniforms (pipeline, gl_program, priv); #endif if (user_program) @@ -701,10 +712,12 @@ _cogl_pipeline_progend_glsl_pre_change_notify (CoglPipeline *pipeline, CoglPipelineState change, const CoglColor *new_color) { - if ((change & COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN)) + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if ((change & _cogl_pipeline_get_state_for_fragment_codegen (ctx))) dirty_glsl_program_state (pipeline); #ifdef HAVE_COGL_GLES2 - else + else if (ctx->driver == COGL_DRIVER_GLES2) { int i; @@ -734,7 +747,9 @@ _cogl_pipeline_progend_glsl_layer_pre_change_notify ( CoglPipelineLayer *layer, CoglPipelineLayerState change) { - if ((change & COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN)) + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if ((change & _cogl_pipeline_get_state_for_fragment_codegen (ctx))) { dirty_glsl_program_state (owner); return; @@ -850,6 +865,9 @@ _cogl_pipeline_progend_glsl_pre_paint (CoglPipeline *pipeline) _COGL_GET_CONTEXT (ctx, NO_RETVAL); + if (ctx->driver != COGL_DRIVER_GLES2) + return; + /* We only need to update the matrices if we're using the the GLSL vertend, but this is a requirement on GLES2 anyway */ g_return_if_fail (pipeline->vertend == COGL_PIPELINE_VERTEND_GLSL); diff --git a/cogl/cogl-pipeline-vertend-fixed.c b/cogl/cogl-pipeline-vertend-fixed.c index d6baf98f5..a3d3ae4f5 100644 --- a/cogl/cogl-pipeline-vertend-fixed.c +++ b/cogl/cogl-pipeline-vertend-fixed.c @@ -49,9 +49,14 @@ _cogl_pipeline_vertend_fixed_start (CoglPipeline *pipeline, { CoglProgram *user_program; + _COGL_GET_CONTEXT (ctx, FALSE); + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_FIXED))) return FALSE; + if (ctx->driver == COGL_DRIVER_GLES2) + return FALSE; + /* If there is a user program with a vertex shader then the appropriate backend for that language should handle it. We can still use the fixed vertex backend if the program only contains diff --git a/cogl/cogl-pipeline-vertend-glsl.c b/cogl/cogl-pipeline-vertend-glsl.c index ac98c8770..f13eceb3c 100644 --- a/cogl/cogl-pipeline-vertend-glsl.c +++ b/cogl/cogl-pipeline-vertend-glsl.c @@ -206,17 +206,13 @@ _cogl_pipeline_vertend_glsl_start (CoglPipeline *pipeline, "main ()\n" "{\n"); -#ifdef HAVE_COGL_GLES2 - - /* 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 (priv->source, - " cogl_point_size_out = cogl_point_size_in;\n"); - -#else /* HAVE_COGL_GLES2 */ - + if (ctx->driver == COGL_DRIVER_GLES2) + /* 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 (priv->source, + " cogl_point_size_out = cogl_point_size_in;\n"); /* On regular OpenGL we'll just flush the point size builtin */ - if (pipelines_difference & COGL_PIPELINE_STATE_POINT_SIZE) + else if (pipelines_difference & COGL_PIPELINE_STATE_POINT_SIZE) { CoglPipeline *authority = _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_POINT_SIZE); @@ -228,8 +224,6 @@ _cogl_pipeline_vertend_glsl_start (CoglPipeline *pipeline, } } -#endif /* HAVE_COGL_GLES2 */ - return TRUE; } @@ -241,32 +235,34 @@ _cogl_pipeline_vertend_glsl_add_layer (CoglPipeline *pipeline, CoglPipelineVertendPrivate *priv; int unit_index; + _COGL_GET_CONTEXT (ctx, FALSE); + priv = get_glsl_priv (pipeline); unit_index = _cogl_pipeline_layer_get_unit_index (layer); -#ifndef HAVE_COGL_GLES2 - - /* We are using the fixed function uniforms for the user matrices - and the only way to set them is with the fixed function API so we - still need to flush them here */ - if (layers_difference & COGL_PIPELINE_LAYER_STATE_USER_MATRIX) + if (ctx->driver != COGL_DRIVER_GLES2) { - CoglPipelineLayerState state = COGL_PIPELINE_LAYER_STATE_USER_MATRIX; - CoglPipelineLayer *authority = - _cogl_pipeline_layer_get_authority (layer, state); - CoglTextureUnit *unit = _cogl_get_texture_unit (unit_index); + /* We are using the fixed function uniforms for the user matrices + and the only way to set them is with the fixed function API so we + still need to flush them here */ + if (layers_difference & COGL_PIPELINE_LAYER_STATE_USER_MATRIX) + { + CoglPipelineLayerState state = COGL_PIPELINE_LAYER_STATE_USER_MATRIX; + CoglPipelineLayer *authority = + _cogl_pipeline_layer_get_authority (layer, state); + CoglTextureUnit *unit = _cogl_get_texture_unit (unit_index); - _cogl_matrix_stack_set (unit->matrix_stack, - &authority->big_state->matrix); + _cogl_matrix_stack_set (unit->matrix_stack, + &authority->big_state->matrix); - _cogl_set_active_texture_unit (unit_index); + _cogl_set_active_texture_unit (unit_index); - _cogl_matrix_stack_flush_to_gl (unit->matrix_stack, COGL_MATRIX_TEXTURE); + _cogl_matrix_stack_flush_to_gl (unit->matrix_stack, + COGL_MATRIX_TEXTURE); + } } -#endif /* HAVE_COGL_GLES2 */ - if (priv->source == NULL) return TRUE; diff --git a/cogl/cogl-pipeline.c b/cogl/cogl-pipeline.c index ce0820321..739036bd0 100644 --- a/cogl/cogl-pipeline.c +++ b/cogl/cogl-pipeline.c @@ -49,6 +49,10 @@ #include #include +#ifndef GL_FUNC_ADD +#define GL_FUNC_ADD 0x8006 +#endif + typedef gboolean (*CoglPipelineStateComparitor) (CoglPipeline *authority0, CoglPipeline *authority1); @@ -275,7 +279,7 @@ _cogl_pipeline_init_default_pipeline (void) alpha_state->alpha_func_reference = 0.0; /* Not the same as the GL default, but seems saner... */ -#ifndef HAVE_COGL_GLES +#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL) blend_state->blend_equation_rgb = GL_FUNC_ADD; blend_state->blend_equation_alpha = GL_FUNC_ADD; blend_state->blend_src_factor_alpha = GL_ONE; @@ -821,6 +825,8 @@ _cogl_pipeline_needs_blending_enabled (CoglPipeline *pipeline, CoglPipelineBlendEnable enabled; unsigned long other_state; + _COGL_GET_CONTEXT (ctx, FALSE); + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_BLENDING))) return FALSE; @@ -846,15 +852,18 @@ _cogl_pipeline_needs_blending_enabled (CoglPipeline *pipeline, * functions... */ -#ifndef HAVE_COGL_GLES - /* GLES 1 can't change the function or have separate alpha factors */ - if (blend_state->blend_equation_rgb != GL_FUNC_ADD || - blend_state->blend_equation_alpha != GL_FUNC_ADD) - return TRUE; +#if defined (HAVE_COGL_GLES2) || defined (HAVE_COGL_GL) + if (ctx->driver != COGL_DRIVER_GLES1) + { + /* GLES 1 can't change the function or have separate alpha factors */ + if (blend_state->blend_equation_rgb != GL_FUNC_ADD || + blend_state->blend_equation_alpha != GL_FUNC_ADD) + return TRUE; - if (blend_state->blend_src_factor_alpha != GL_ONE || - blend_state->blend_dst_factor_alpha != GL_ONE_MINUS_SRC_ALPHA) - return TRUE; + if (blend_state->blend_src_factor_alpha != GL_ONE || + blend_state->blend_dst_factor_alpha != GL_ONE_MINUS_SRC_ALPHA) + return TRUE; + } #endif if (blend_state->blend_src_factor_rgb != GL_ONE || @@ -3400,18 +3409,23 @@ _cogl_pipeline_blend_state_equal (CoglPipeline *authority0, CoglPipelineBlendState *blend_state0 = &authority0->big_state->blend_state; CoglPipelineBlendState *blend_state1 = &authority1->big_state->blend_state; -#ifndef HAVE_COGL_GLES - if (blend_state0->blend_equation_rgb != blend_state1->blend_equation_rgb) - return FALSE; - if (blend_state0->blend_equation_alpha != - blend_state1->blend_equation_alpha) - return FALSE; - if (blend_state0->blend_src_factor_alpha != - blend_state1->blend_src_factor_alpha) - return FALSE; - if (blend_state0->blend_dst_factor_alpha != - blend_state1->blend_dst_factor_alpha) - return FALSE; + _COGL_GET_CONTEXT (ctx, FALSE); + +#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL) + if (ctx->driver != COGL_DRIVER_GLES1) + { + if (blend_state0->blend_equation_rgb != blend_state1->blend_equation_rgb) + return FALSE; + if (blend_state0->blend_equation_alpha != + blend_state1->blend_equation_alpha) + return FALSE; + if (blend_state0->blend_src_factor_alpha != + blend_state1->blend_src_factor_alpha) + return FALSE; + if (blend_state0->blend_dst_factor_alpha != + blend_state1->blend_dst_factor_alpha) + return FALSE; + } #endif if (blend_state0->blend_src_factor_rgb != blend_state1->blend_src_factor_rgb) @@ -3419,11 +3433,12 @@ _cogl_pipeline_blend_state_equal (CoglPipeline *authority0, if (blend_state0->blend_dst_factor_rgb != blend_state1->blend_dst_factor_rgb) return FALSE; -#ifndef HAVE_COGL_GLES - if (blend_state0->blend_src_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR || - blend_state0->blend_src_factor_rgb == GL_CONSTANT_COLOR || - blend_state0->blend_dst_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR || - blend_state0->blend_dst_factor_rgb == GL_CONSTANT_COLOR) +#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL) + if (ctx->driver != COGL_DRIVER_GLES1 && + (blend_state0->blend_src_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR || + blend_state0->blend_src_factor_rgb == GL_CONSTANT_COLOR || + blend_state0->blend_dst_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR || + blend_state0->blend_dst_factor_rgb == GL_CONSTANT_COLOR)) { if (!cogl_color_equal (&blend_state0->blend_constant, &blend_state1->blend_constant)) @@ -4411,7 +4426,7 @@ arg_to_gl_blend_factor (CoglBlendStringArgument *arg) return GL_DST_ALPHA; } } -#ifndef HAVE_COGL_GLES +#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL) else if (arg->factor.source.info->type == COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT) { @@ -4442,7 +4457,6 @@ setup_blend_state (CoglBlendStringStatement *statement, GLint *blend_src_factor, GLint *blend_dst_factor) { -#ifndef HAVE_COGL_GLES switch (statement->function->type) { case COGL_BLEND_STRING_FUNCTION_ADD: @@ -4453,7 +4467,6 @@ setup_blend_state (CoglBlendStringStatement *statement, g_warning ("Unsupported blend function given"); *blend_equation = GL_FUNC_ADD; } -#endif *blend_src_factor = arg_to_gl_blend_factor (&statement->args[0]); *blend_dst_factor = arg_to_gl_blend_factor (&statement->args[1]); @@ -4473,6 +4486,8 @@ cogl_pipeline_set_blend (CoglPipeline *pipeline, int count; CoglPipelineBlendState *blend_state; + _COGL_GET_CONTEXT (ctx, FALSE); + g_return_val_if_fail (cogl_is_pipeline (pipeline), FALSE); count = @@ -4512,21 +4527,26 @@ cogl_pipeline_set_blend (CoglPipeline *pipeline, _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE); blend_state = &pipeline->big_state->blend_state; -#ifndef HAVE_COGL_GLES - setup_blend_state (rgb, - &blend_state->blend_equation_rgb, - &blend_state->blend_src_factor_rgb, - &blend_state->blend_dst_factor_rgb); - setup_blend_state (a, - &blend_state->blend_equation_alpha, - &blend_state->blend_src_factor_alpha, - &blend_state->blend_dst_factor_alpha); -#else - setup_blend_state (rgb, - NULL, - &blend_state->blend_src_factor_rgb, - &blend_state->blend_dst_factor_rgb); +#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES2) + if (ctx->driver != COGL_DRIVER_GLES1) + { + setup_blend_state (rgb, + &blend_state->blend_equation_rgb, + &blend_state->blend_src_factor_rgb, + &blend_state->blend_dst_factor_rgb); + setup_blend_state (a, + &blend_state->blend_equation_alpha, + &blend_state->blend_src_factor_alpha, + &blend_state->blend_dst_factor_alpha); + } + else #endif + { + setup_blend_state (rgb, + NULL, + &blend_state->blend_src_factor_rgb, + &blend_state->blend_dst_factor_rgb); + } /* If we are the current authority see if we can revert to one of our * ancestors being the authority */ @@ -4560,33 +4580,40 @@ void cogl_pipeline_set_blend_constant (CoglPipeline *pipeline, const CoglColor *constant_color) { -#ifndef HAVE_COGL_GLES - CoglPipelineState state = COGL_PIPELINE_STATE_BLEND; - CoglPipeline *authority; - CoglPipelineBlendState *blend_state; + _COGL_GET_CONTEXT (ctx, NO_RETVAL); g_return_if_fail (cogl_is_pipeline (pipeline)); - authority = _cogl_pipeline_get_authority (pipeline, state); - - blend_state = &authority->big_state->blend_state; - if (cogl_color_equal (constant_color, &blend_state->blend_constant)) + if (ctx->driver == COGL_DRIVER_GLES1) return; - /* - Flush journal primitives referencing the current state. - * - Make sure the pipeline has no dependants so it may be modified. - * - If the pipeline isn't currently an authority for the state being - * changed, then initialize that state from the current authority. - */ - _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE); +#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL) + { + CoglPipelineState state = COGL_PIPELINE_STATE_BLEND; + CoglPipeline *authority; + CoglPipelineBlendState *blend_state; - blend_state = &pipeline->big_state->blend_state; - blend_state->blend_constant = *constant_color; + authority = _cogl_pipeline_get_authority (pipeline, state); - _cogl_pipeline_update_authority (pipeline, authority, state, - _cogl_pipeline_blend_state_equal); + blend_state = &authority->big_state->blend_state; + if (cogl_color_equal (constant_color, &blend_state->blend_constant)) + return; - handle_automatic_blend_enable (pipeline, state); + /* - Flush journal primitives referencing the current state. + * - Make sure the pipeline has no dependants so it may be modified. + * - If the pipeline isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE); + + blend_state = &pipeline->big_state->blend_state; + blend_state->blend_constant = *constant_color; + + _cogl_pipeline_update_authority (pipeline, authority, state, + _cogl_pipeline_blend_state_equal); + + handle_automatic_blend_enable (pipeline, state); + } #endif } @@ -4677,6 +4704,8 @@ cogl_pipeline_set_depth_state (CoglPipeline *pipeline, CoglPipeline *authority; CoglDepthState *orig_state; + _COGL_GET_CONTEXT (ctx, FALSE); + g_return_val_if_fail (cogl_is_pipeline (pipeline), FALSE); g_return_val_if_fail (depth_state->magic == COGL_DEPTH_STATE_MAGIC, FALSE); @@ -4690,9 +4719,9 @@ cogl_pipeline_set_depth_state (CoglPipeline *pipeline, orig_state->range_far == depth_state->range_far) return TRUE; -#ifdef COGL_HAS_GLES - if (depth_state->range_near != 0 || - depth_state->range_far != 1) + if (ctx->driver == COGL_DRIVER_GLES1 && + (depth_state->range_near != 0 || + depth_state->range_far != 1)) { g_set_error (error, COGL_ERROR, @@ -4700,7 +4729,6 @@ cogl_pipeline_set_depth_state (CoglPipeline *pipeline, "glDepthRange not available on GLES 1"); return FALSE; } -#endif /* - Flush journal primitives referencing the current state. * - Make sure the pipeline has no dependants so it may be modified. @@ -6070,33 +6098,38 @@ _cogl_pipeline_hash_blend_state (CoglPipeline *authority, CoglPipelineBlendState *blend_state = &authority->big_state->blend_state; unsigned int hash; + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + if (!authority->real_blend_enable) return; hash = state->hash; -#ifndef HAVE_COGL_GLES - hash = - _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_equation_rgb, - sizeof (blend_state->blend_equation_rgb)); - hash = - _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_equation_alpha, - sizeof (blend_state->blend_equation_alpha)); - hash = - _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_src_factor_alpha, - sizeof (blend_state->blend_src_factor_alpha)); - hash = - _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_dst_factor_alpha, - sizeof (blend_state->blend_dst_factor_alpha)); - - if (blend_state->blend_src_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR || - blend_state->blend_src_factor_rgb == GL_CONSTANT_COLOR || - blend_state->blend_dst_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR || - blend_state->blend_dst_factor_rgb == GL_CONSTANT_COLOR) +#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL) + if (ctx->driver != COGL_DRIVER_GLES1) { hash = - _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_constant, - sizeof (blend_state->blend_constant)); + _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_equation_rgb, + sizeof (blend_state->blend_equation_rgb)); + hash = + _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_equation_alpha, + sizeof (blend_state->blend_equation_alpha)); + hash = + _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_src_factor_alpha, + sizeof (blend_state->blend_src_factor_alpha)); + hash = + _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_dst_factor_alpha, + sizeof (blend_state->blend_dst_factor_alpha)); + + if (blend_state->blend_src_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR || + blend_state->blend_src_factor_rgb == GL_CONSTANT_COLOR || + blend_state->blend_dst_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR || + blend_state->blend_dst_factor_rgb == GL_CONSTANT_COLOR) + { + hash = + _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_constant, + sizeof (blend_state->blend_constant)); + } } #endif @@ -6698,3 +6731,30 @@ _cogl_pipeline_find_equivalent_parent (CoglPipeline *pipeline, return authority1; } + +CoglPipelineLayerState +_cogl_pipeline_get_layer_state_for_fragment_codegen (CoglContext *context) +{ + CoglPipelineLayerState state = + (COGL_PIPELINE_LAYER_STATE_COMBINE | + COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET | + COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS | + COGL_PIPELINE_LAYER_STATE_UNIT); + + if (context->driver == COGL_DRIVER_GLES2) + state |= COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS; + + return state; +} + +CoglPipelineState +_cogl_pipeline_get_state_for_fragment_codegen (CoglContext *context) +{ + CoglPipelineState state = (COGL_PIPELINE_STATE_LAYERS | + COGL_PIPELINE_STATE_USER_SHADER); + + if (context->driver == COGL_DRIVER_GLES2) + state |= COGL_PIPELINE_STATE_ALPHA_FUNC; + + return state; +} diff --git a/cogl/cogl-private.h b/cogl/cogl-private.h index 8db76e1b2..465b267ce 100644 --- a/cogl/cogl-private.h +++ b/cogl/cogl-private.h @@ -27,11 +27,19 @@ G_BEGIN_DECLS gboolean -_cogl_gl_check_version (GError **error); +_cogl_gl_check_gl_version (CoglContext *context, + GError **error); void _cogl_gl_update_features (CoglContext *context); +gboolean +_cogl_gles_check_gl_version (CoglContext *context, + GError **error); + +void +_cogl_gles_update_features (CoglContext *context); + gboolean _cogl_check_extension (const char *name, const char *ext); diff --git a/cogl/cogl-program.c b/cogl/cogl-program.c index 8f00eadad..044c284c3 100644 --- a/cogl/cogl-program.c +++ b/cogl/cogl-program.c @@ -106,13 +106,11 @@ cogl_program_attach_shader (CoglHandle program_handle, shader = _cogl_shader_pointer_from_handle (shader_handle); /* Only one shader is allowed if the type is ARBfp */ -#ifdef HAVE_COGL_GL if (shader->language == COGL_SHADER_LANGUAGE_ARBFP) g_return_if_fail (program->attached_shaders == NULL); else if (shader->language == COGL_SHADER_LANGUAGE_GLSL) g_return_if_fail (_cogl_program_get_language (program) == COGL_SHADER_LANGUAGE_GLSL); -#endif program->attached_shaders = g_slist_prepend (program->attached_shaders, @@ -366,8 +364,6 @@ cogl_program_uniform_matrix (int uniform_no, uniform_no, size, count, transpose, value); } -#ifndef HAVE_COGL_GLES - /* ARBfp local parameters can be referenced like: * * "program.local[5]" @@ -478,8 +474,6 @@ _cogl_program_flush_uniform_glsl (GLint location, } } -#endif /* HAVE_COGL_GLES */ - #ifdef HAVE_COGL_GL static void @@ -506,17 +500,13 @@ _cogl_program_flush_uniforms (CoglProgram *program, GLuint gl_program, gboolean gl_program_changed) { -#ifdef HAVE_COGL_GLES - - g_return_if_reached (); - -#else /* HAVE_COGL_GLES */ - CoglProgramUniform *uniform; int i; _COGL_GET_CONTEXT (ctx, NO_RETVAL); + g_return_if_fail (ctx->driver != COGL_DRIVER_GLES1); + for (i = 0; i < program->custom_uniforms->len; i++) { uniform = &g_array_index (program->custom_uniforms, @@ -548,20 +538,18 @@ _cogl_program_flush_uniforms (CoglProgram *program, &uniform->value); break; -#ifdef HAVE_COGL_GL case COGL_SHADER_LANGUAGE_ARBFP: +#ifdef HAVE_COGL_GL _cogl_program_flush_uniform_arbfp (uniform->location, &uniform->value); - break; #endif + break; } } uniform->dirty = FALSE; } } - -#endif /* HAVE_COGL_GLES */ } CoglShaderLanguage diff --git a/cogl/cogl-renderer-private.h b/cogl/cogl-renderer-private.h index a6110d35c..dc279bac0 100644 --- a/cogl/cogl-renderer-private.h +++ b/cogl/cogl-renderer-private.h @@ -24,8 +24,11 @@ #ifndef __COGL_RENDERER_PRIVATE_H #define __COGL_RENDERER_PRIVATE_H +#include + #include "cogl-object-private.h" #include "cogl-winsys-private.h" +#include "cogl-internal.h" #ifdef COGL_HAS_XLIB_SUPPORT #include @@ -44,6 +47,12 @@ struct _CoglRenderer #ifdef COGL_HAS_XLIB_SUPPORT Display *foreign_xdpy; #endif + + CoglDriver driver; +#ifndef HAVE_DIRECTLY_LINKED_GL_LIBRARY + GModule *libgl_module; +#endif + #if COGL_HAS_EGL_PLATFORM_WAYLAND_SUPPORT struct wl_display *foreign_wayland_display; struct wl_compositor *foreign_wayland_compositor; diff --git a/cogl/cogl-renderer.c b/cogl/cogl-renderer.c index 026d4abb8..8b76a77e9 100644 --- a/cogl/cogl-renderer.c +++ b/cogl/cogl-renderer.c @@ -100,6 +100,11 @@ _cogl_renderer_free (CoglRenderer *renderer) const CoglWinsysVtable *winsys = _cogl_renderer_get_winsys (renderer); winsys->renderer_disconnect (renderer); +#ifndef HAVE_DIRECTLY_LINKED_GL_LIBRARY + if (renderer->libgl_module) + g_module_close (renderer->libgl_module); +#endif + g_slist_foreach (renderer->event_filters, (GFunc) native_filter_closure_free, NULL); @@ -166,6 +171,75 @@ cogl_renderer_check_onscreen_template (CoglRenderer *renderer, return TRUE; } +static gboolean +_cogl_renderer_choose_driver (CoglRenderer *renderer, + GError **error) +{ + const char *driver_name = g_getenv ("COGL_DRIVER"); + const char *libgl_name; +#ifndef HAVE_DIRECTLY_LINKED_GL_LIBRARY + char *libgl_module_path; +#endif + +#ifdef HAVE_COGL_GL + if (driver_name == NULL || !strcmp (driver_name, "gl")) + { + renderer->driver = COGL_DRIVER_GL; + libgl_name = COGL_GL_LIBNAME; + goto found; + } +#endif + +#ifdef HAVE_COGL_GLES2 + if (driver_name == NULL || !strcmp (driver_name, "gles2")) + { + renderer->driver = COGL_DRIVER_GLES2; + libgl_name = COGL_GLES2_LIBNAME; + goto found; + } +#endif + +#ifdef HAVE_COGL_GLES + if (driver_name == NULL || !strcmp (driver_name, "gles1")) + { + renderer->driver = COGL_DRIVER_GLES1; + libgl_name = COGL_GLES1_LIBNAME; + goto found; + } +#endif + + g_set_error (error, + COGL_DRIVER_ERROR, + COGL_DRIVER_ERROR_NO_SUITABLE_DRIVER_FOUND, + "No suitable driver found"); + return FALSE; + + found: + +#ifndef HAVE_DIRECTLY_LINKED_GL_LIBRARY + + libgl_module_path = g_module_build_path (NULL, /* standard lib search path */ + libgl_name); + + renderer->libgl_module = g_module_open (libgl_module_path, + G_MODULE_BIND_LAZY); + + g_free (libgl_module_path); + + if (renderer->libgl_module == NULL) + { + g_set_error (error, COGL_DRIVER_ERROR, + COGL_DRIVER_ERROR_FAILED_TO_LOAD_LIBRARY, + "Failed to dynamically open the GL library \"%s\"", + libgl_name); + return FALSE; + } + +#endif /* HAVE_DIRECTLY_LINKED_GL_LIBRARY */ + + return TRUE; +} + /* Final connection API */ gboolean @@ -177,6 +251,12 @@ cogl_renderer_connect (CoglRenderer *renderer, GError **error) if (renderer->connected) return TRUE; + /* The driver needs to be chosen before connecting the renderer + because eglInitialize requires the library containing the GL API + to be loaded before its called */ + if (!_cogl_renderer_choose_driver (renderer, error)) + return FALSE; + error_message = g_string_new (""); for (i = 0; i < G_N_ELEMENTS (_cogl_winsys_vtable_getters); i++) { diff --git a/cogl/cogl-shader-boilerplate.h b/cogl/cogl-shader-boilerplate.h index 3a23de1c9..b46b7b45e 100644 --- a/cogl/cogl-shader-boilerplate.h +++ b/cogl/cogl-shader-boilerplate.h @@ -29,10 +29,7 @@ #include "cogl.h" - -#ifndef HAVE_COGL_GLES2 - -#define _COGL_COMMON_SHADER_BOILERPLATE \ +#define _COGL_COMMON_SHADER_BOILERPLATE_GL \ "#define COGL_VERSION 100\n" \ "\n" \ "#define cogl_modelview_matrix gl_ModelViewMatrix\n" \ @@ -41,8 +38,8 @@ "#define cogl_texture_matrix gl_TextureMatrix\n" \ "\n" -#define _COGL_VERTEX_SHADER_BOILERPLATE \ - _COGL_COMMON_SHADER_BOILERPLATE \ +#define _COGL_VERTEX_SHADER_BOILERPLATE_GL \ + _COGL_COMMON_SHADER_BOILERPLATE_GL \ "#define cogl_position_in gl_Vertex\n" \ "#define cogl_color_in gl_Color\n" \ "#define cogl_tex_coord_in gl_MultiTexCoord0\n" \ @@ -61,8 +58,8 @@ "#define cogl_color_out gl_FrontColor\n" \ "#define cogl_tex_coord_out gl_TexCoord\n" -#define _COGL_FRAGMENT_SHADER_BOILERPLATE \ - _COGL_COMMON_SHADER_BOILERPLATE \ +#define _COGL_FRAGMENT_SHADER_BOILERPLATE_GL \ + _COGL_COMMON_SHADER_BOILERPLATE_GL \ "#define cogl_color_in gl_Color\n" \ "#define cogl_tex_coord_in gl_TexCoord\n" \ "\n" \ @@ -77,9 +74,7 @@ "#define coglFragCoord gl_FragCoord\n" #endif -#else /* HAVE_COGL_GLES2 */ - -#define _COGL_COMMON_SHADER_BOILERPLATE \ +#define _COGL_COMMON_SHADER_BOILERPLATE_GLES2 \ "#define COGL_VERSION 100\n" \ "\n" \ "uniform mat4 cogl_modelview_matrix;\n" \ @@ -92,8 +87,8 @@ if they are not actually used. The GLSL spec for GLES at least implies that this will happen for varyings but it doesn't explicitly so for attributes */ -#define _COGL_VERTEX_SHADER_BOILERPLATE \ - _COGL_COMMON_SHADER_BOILERPLATE \ +#define _COGL_VERTEX_SHADER_BOILERPLATE_GLES2 \ + _COGL_COMMON_SHADER_BOILERPLATE_GLES2 \ "#define cogl_color_out _cogl_color\n" \ "varying vec4 _cogl_color;\n" \ "#define cogl_tex_coord_out _cogl_tex_coord\n" \ @@ -105,11 +100,11 @@ "#define cogl_tex_coord_in cogl_tex_coord0_in;\n" \ "attribute vec3 cogl_normal_in;\n" -#define _COGL_FRAGMENT_SHADER_BOILERPLATE \ +#define _COGL_FRAGMENT_SHADER_BOILERPLATE_GLES2 \ "#if __VERSION__ == 100\n" \ "precision highp float;\n" \ "#endif\n" \ - _COGL_COMMON_SHADER_BOILERPLATE \ + _COGL_COMMON_SHADER_BOILERPLATE_GLES2 \ "\n" \ "varying vec4 _cogl_color;\n" \ "\n" \ @@ -121,7 +116,5 @@ "\n" \ "#define cogl_front_facing gl_FrontFacing\n" -#endif /* HAVE_COGL_GLES2 */ - #endif /* __COGL_SHADER_BOILERPLATE_H */ diff --git a/cogl/cogl-shader-private.h b/cogl/cogl-shader-private.h index 3b4b2325a..ee358167f 100644 --- a/cogl/cogl-shader-private.h +++ b/cogl/cogl-shader-private.h @@ -31,9 +31,7 @@ typedef struct _CoglShader CoglShader; typedef enum { COGL_SHADER_LANGUAGE_GLSL, -#ifdef HAVE_COGL_GL COGL_SHADER_LANGUAGE_ARBFP -#endif } CoglShaderLanguage; struct _CoglShader diff --git a/cogl/cogl-shader.c b/cogl/cogl-shader.c index 996676b8a..4d662ab37 100644 --- a/cogl/cogl-shader.c +++ b/cogl/cogl-shader.c @@ -41,11 +41,16 @@ static void _cogl_shader_free (CoglShader *shader); COGL_HANDLE_DEFINE (Shader, shader); COGL_OBJECT_DEFINE_DEPRECATED_REF_COUNTING (shader); +#ifndef GL_FRAGMENT_SHADER +#define GL_FRAGMENT_SHADER 0x8B30 +#endif +#ifndef GL_VERTEX_SHADER +#define GL_VERTEX_SHADER 0x8B31 +#endif + static void _cogl_shader_free (CoglShader *shader) { -#ifndef HAVE_COGL_GLES - /* Frees shader resources but its handle is not released! Do that separately before this! */ _COGL_GET_CONTEXT (ctx, NO_RETVAL); @@ -61,8 +66,6 @@ _cogl_shader_free (CoglShader *shader) if (shader->gl_handle) GE (ctx, glDeleteShader (shader->gl_handle)); -#endif /* HAVE_COGL_GLES */ - g_slice_free (CoglShader, shader); } @@ -98,8 +101,6 @@ cogl_create_shader (CoglShaderType type) static void delete_shader (CoglShader *shader) { -#ifndef HAVE_COGL_GLES - _COGL_GET_CONTEXT (ctx, NO_RETVAL); #ifdef HAVE_COGL_GL @@ -116,8 +117,6 @@ delete_shader (CoglShader *shader) } shader->gl_handle = 0; - -#endif /* HAVE_COGL_GLES */ } void @@ -154,16 +153,15 @@ cogl_shader_source (CoglHandle handle, void cogl_shader_compile (CoglHandle handle) { -#ifdef HAVE_COGL_GL CoglShader *shader = handle; -#endif + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); if (!cogl_is_shader (handle)) return; -#ifdef HAVE_COGL_GL - _cogl_shader_compile_real (shader, 0 /* ignored */); -#endif + if (ctx->driver == COGL_DRIVER_GL) + _cogl_shader_compile_real (shader, 0 /* ignored */); /* XXX: For GLES2 we don't actually compile anything until the * shader gets used so we have an opportunity to add some @@ -183,43 +181,49 @@ _cogl_shader_set_source_with_boilerplate (GLuint shader_gl_handle, const char **strings_in, const GLint *lengths_in) { -#ifndef HAVE_COGL_GLES - - static const char vertex_boilerplate[] = _COGL_VERTEX_SHADER_BOILERPLATE; - static const char fragment_boilerplate[] = _COGL_FRAGMENT_SHADER_BOILERPLATE; + const char *vertex_boilerplate; + const char *fragment_boilerplate; const char **strings = g_alloca (sizeof (char *) * (count_in + 3)); GLint *lengths = g_alloca (sizeof (GLint) * (count_in + 3)); int count = 0; -#ifdef HAVE_COGL_GLES2 char *tex_coord_declarations = NULL; -#endif _COGL_GET_CONTEXT (ctx, NO_RETVAL); -#ifdef HAVE_COGL_GLES2 - if (cogl_features_available (COGL_FEATURE_TEXTURE_3D)) + if (ctx->driver == COGL_DRIVER_GLES2) + { + vertex_boilerplate = _COGL_VERTEX_SHADER_BOILERPLATE_GLES2; + fragment_boilerplate = _COGL_FRAGMENT_SHADER_BOILERPLATE_GLES2; + } + else + { + vertex_boilerplate = _COGL_VERTEX_SHADER_BOILERPLATE_GL; + fragment_boilerplate = _COGL_FRAGMENT_SHADER_BOILERPLATE_GL; + } + + if (ctx->driver == COGL_DRIVER_GLES2 && + cogl_features_available (COGL_FEATURE_TEXTURE_3D)) { static const char texture_3d_extension[] = "#extension GL_OES_texture_3D : enable\n"; strings[count] = texture_3d_extension; lengths[count++] = sizeof (texture_3d_extension) - 1; } -#endif if (shader_gl_type == GL_VERTEX_SHADER) { strings[count] = vertex_boilerplate; - lengths[count++] = sizeof (vertex_boilerplate) - 1; + lengths[count++] = strlen (vertex_boilerplate); } else if (shader_gl_type == GL_FRAGMENT_SHADER) { strings[count] = fragment_boilerplate; - lengths[count++] = sizeof (fragment_boilerplate) - 1; + lengths[count++] = strlen (fragment_boilerplate); } -#ifdef HAVE_COGL_GLES2 - if (n_tex_coord_attribs) + if (ctx->driver == COGL_DRIVER_GLES2 && + n_tex_coord_attribs) { GString *declarations = g_string_new (NULL); @@ -245,7 +249,6 @@ _cogl_shader_set_source_with_boilerplate (GLuint shader_gl_handle, strings[count] = tex_coord_declarations; lengths[count++] = -1; /* null terminated */ } -#endif memcpy (strings + count, strings_in, sizeof (char *) * count_in); if (lengths_in) @@ -282,19 +285,13 @@ _cogl_shader_set_source_with_boilerplate (GLuint shader_gl_handle, GE( ctx, glShaderSource (shader_gl_handle, count, (const char **) strings, lengths) ); -#ifdef HAVE_COGL_GLES2 g_free (tex_coord_declarations); -#endif - -#endif /* HAVE_COGL_GLES */ } void _cogl_shader_compile_real (CoglHandle handle, int n_tex_coord_attribs) { -#ifndef HAVE_COGL_GLES - CoglShader *shader = handle; _COGL_GET_CONTEXT (ctx, NO_RETVAL); @@ -343,7 +340,9 @@ _cogl_shader_compile_real (CoglHandle handle, if (shader->gl_handle #ifdef HAVE_COGL_GLES2 - && shader->n_tex_coord_attribs >= n_tex_coord_attribs + && + (ctx->driver != COGL_DRIVER_GLES2 || + shader->n_tex_coord_attribs >= n_tex_coord_attribs) #endif ) return; @@ -389,19 +388,11 @@ _cogl_shader_compile_real (CoglHandle handle, } #endif } - -#endif /* HAVE_COGL_GLES */ } char * cogl_shader_get_info_log (CoglHandle handle) { -#ifdef HAVE_COGL_GLES - - return NULL; - -#else /* HAVE_COGL_GLES */ - CoglShader *shader; _COGL_GET_CONTEXT (ctx, NULL); @@ -443,8 +434,6 @@ cogl_shader_get_info_log (CoglHandle handle) buffer[len] = '\0'; return g_strdup (buffer); } - -#endif /* HAVE_COGL_GLES */ } CoglShaderType @@ -467,12 +456,7 @@ cogl_shader_get_type (CoglHandle handle) gboolean cogl_shader_is_compiled (CoglHandle handle) { -#ifdef HAVE_COGL_GLES - - return FALSE; - -#else /* HAVE_COGL_GLES */ - +#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES2) GLint status; CoglShader *shader; @@ -513,6 +497,7 @@ cogl_shader_is_compiled (CoglHandle handle) else return FALSE; } - -#endif /* HAVE_COGL_GLES */ +#else + return FALSE; +#endif } diff --git a/cogl/cogl-texture-2d.c b/cogl/cogl-texture-2d.c index 888720440..71ff44ad0 100644 --- a/cogl/cogl-texture-2d.c +++ b/cogl/cogl-texture-2d.c @@ -430,37 +430,38 @@ 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) + { + GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, + GL_TEXTURE_COMPRESSED, + &gl_compressed) ); - GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, - GL_TEXTURE_COMPRESSED, - &gl_compressed) ); + { + GLint val; - { - GLint val; + GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, + GL_TEXTURE_INTERNAL_FORMAT, + &val) ); - GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, - GL_TEXTURE_INTERNAL_FORMAT, - &val) ); - - gl_int_format = val; - } - - /* If we can query GL for the actual pixel format then we'll ignore - the passed in format and use that. */ - if (!ctx->texture_driver->pixel_format_from_gl_internal (gl_int_format, - &format)) - return COGL_INVALID_HANDLE; - -#else - - /* Otherwise we'll assume we can derive the GL format from the - passed in format */ - ctx->texture_driver->pixel_format_to_gl (format, - &gl_int_format, - NULL, - NULL); + gl_int_format = val; + } + /* If we can query GL for the actual pixel format then we'll ignore + the passed in format and use that. */ + if (!ctx->texture_driver->pixel_format_from_gl_internal (gl_int_format, + &format)) + return COGL_INVALID_HANDLE; + } + else #endif + { + /* Otherwise we'll assume we can derive the GL format from the + passed in format */ + ctx->texture_driver->pixel_format_to_gl (format, + &gl_int_format, + NULL, + NULL); + } /* Note: We always trust the given width and height without querying * the texture object because the user may be creating a Cogl @@ -772,7 +773,7 @@ _cogl_texture_2d_pre_paint (CoglTexture *tex, CoglTexturePrePaintFlags flags) GL_GENERATE_MIPMAP and reuploading the first pixel */ if (cogl_features_available (COGL_FEATURE_OFFSCREEN)) ctx->texture_driver->gl_generate_mipmaps (GL_TEXTURE_2D); -#ifndef HAVE_COGL_GLES2 +#if defined(HAVE_COGL_GLES) || defined(HAVE_COGL_GL) else { GE( ctx, glTexParameteri (GL_TEXTURE_2D, diff --git a/cogl/cogl-texture-3d.c b/cogl/cogl-texture-3d.c index 48e2e2d7d..a64c3d2ad 100644 --- a/cogl/cogl-texture-3d.c +++ b/cogl/cogl-texture-3d.c @@ -580,8 +580,8 @@ _cogl_texture_3d_pre_paint (CoglTexture *tex, CoglTexturePrePaintFlags flags) GL_GENERATE_MIPMAP and reuploading the first pixel */ if (cogl_features_available (COGL_FEATURE_OFFSCREEN)) ctx->texture_driver->gl_generate_mipmaps (GL_TEXTURE_3D); -#ifndef HAVE_COGL_GLES2 - else +#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES) + else if (ctx->driver != COGL_DRIVER_GLES2) { GE( ctx, glTexParameteri (GL_TEXTURE_3D, GL_GENERATE_MIPMAP, diff --git a/cogl/cogl-texture-rectangle.c b/cogl/cogl-texture-rectangle.c index 88cf5bcd4..e98be8d95 100644 --- a/cogl/cogl-texture-rectangle.c +++ b/cogl/cogl-texture-rectangle.c @@ -372,37 +372,36 @@ _cogl_texture_rectangle_new_from_foreign (GLuint gl_handle, /* Obtain texture parameters */ #if HAVE_COGL_GL + if (ctx->driver == COGL_DRIVER_GL) + { + GLint val; - GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_RECTANGLE_ARB, 0, - GL_TEXTURE_COMPRESSED, - &gl_compressed) ); + GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_RECTANGLE_ARB, 0, + GL_TEXTURE_COMPRESSED, + &gl_compressed) ); - { - GLint val; + GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_RECTANGLE_ARB, 0, + GL_TEXTURE_INTERNAL_FORMAT, + &val) ); - GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_RECTANGLE_ARB, 0, - GL_TEXTURE_INTERNAL_FORMAT, - &val) ); - - gl_int_format = val; - } - - /* If we can query GL for the actual pixel format then we'll ignore - the passed in format and use that. */ - if (!ctx->texture_driver->pixel_format_from_gl_internal (gl_int_format, - &format)) - return COGL_INVALID_HANDLE; - -#else - - /* Otherwise we'll assume we can derive the GL format from the - passed in format */ - ctx->texture_driver->pixel_format_to_gl (format, - &gl_int_format, - NULL, - NULL); + gl_int_format = val; + /* If we can query GL for the actual pixel format then we'll ignore + the passed in format and use that. */ + if (!ctx->texture_driver->pixel_format_from_gl_internal (gl_int_format, + &format)) + return COGL_INVALID_HANDLE; + } + else #endif + { + /* Otherwise we'll assume we can derive the GL format from the + passed in format */ + ctx->texture_driver->pixel_format_to_gl (format, + &gl_int_format, + NULL, + NULL); + } /* Note: We always trust the given width and height without querying * the texture object because the user may be creating a Cogl diff --git a/cogl/cogl-texture.c b/cogl/cogl-texture.c index ffd38b7ff..134e5f5b8 100644 --- a/cogl/cogl-texture.c +++ b/cogl/cogl-texture.c @@ -194,54 +194,54 @@ _cogl_texture_prepare_for_upload (CoglBitmap *src_bmp, limited number of formats so we must convert using the Cogl bitmap code instead */ -#ifdef HAVE_COGL_GL - - /* If the source format does not have the same premult flag as the - dst format then we need to copy and convert it */ - if (_cogl_texture_needs_premult_conversion (src_format, - dst_format)) + if (ctx->driver == COGL_DRIVER_GL) { - dst_bmp = _cogl_bitmap_copy (src_bmp); - - if (!_cogl_bitmap_convert_premult_status (dst_bmp, - src_format ^ - COGL_PREMULT_BIT)) + /* If the source format does not have the same premult flag as the + dst format then we need to copy and convert it */ + if (_cogl_texture_needs_premult_conversion (src_format, + dst_format)) { - cogl_object_unref (dst_bmp); - return NULL; + dst_bmp = _cogl_bitmap_copy (src_bmp); + + if (!_cogl_bitmap_convert_premult_status (dst_bmp, + src_format ^ + COGL_PREMULT_BIT)) + { + cogl_object_unref (dst_bmp); + return NULL; + } } + else + dst_bmp = cogl_object_ref (src_bmp); + + /* Use the source format from the src bitmap type and the internal + format from the dst format type so that GL can do the + conversion */ + ctx->texture_driver->pixel_format_to_gl (src_format, + NULL, /* internal format */ + out_glformat, + out_gltype); + ctx->texture_driver->pixel_format_to_gl (dst_format, + out_glintformat, + NULL, + NULL); + } else - dst_bmp = cogl_object_ref (src_bmp); + { + CoglPixelFormat closest_format; - /* Use the source format from the src bitmap type and the internal - format from the dst format type so that GL can do the - conversion */ - ctx->texture_driver->pixel_format_to_gl (src_format, - NULL, /* internal format */ - out_glformat, - out_gltype); - ctx->texture_driver->pixel_format_to_gl (dst_format, - out_glintformat, - NULL, - NULL); + closest_format = ctx->texture_driver->pixel_format_to_gl (dst_format, + out_glintformat, + out_glformat, + out_gltype); -#else /* HAVE_COGL_GL */ - { - CoglPixelFormat closest_format; - - closest_format = ctx->texture_driver->pixel_format_to_gl (dst_format, - out_glintformat, - out_glformat, - out_gltype); - - if (closest_format != src_format) - dst_bmp = _cogl_bitmap_convert_format_and_premult (src_bmp, - closest_format); - else - dst_bmp = cogl_object_ref (src_bmp); - } -#endif /* HAVE_COGL_GL */ + if (closest_format != src_format) + dst_bmp = _cogl_bitmap_convert_format_and_premult (src_bmp, + closest_format); + else + dst_bmp = cogl_object_ref (src_bmp); + } if (dst_format_out) *dst_format_out = dst_format; diff --git a/cogl/cogl.c b/cogl/cogl.c index b77a62309..7b2990ecc 100644 --- a/cogl/cogl.c +++ b/cogl/cogl.c @@ -164,15 +164,7 @@ toggle_flag (CoglContext *ctx, return FALSE; } -#ifdef HAVE_COGL_GLES2 - -/* Under GLES2 there are no builtin client flags so toggle_client_flag - should never be reached */ - -#define toggle_client_flag(ctx, new_flags, flag, gl_flag) \ - g_assert (((new_flags) & (flag)) == 0) - -#else /* HAVE_COGL_GLES2 */ +#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES) static gboolean toggle_client_flag (CoglContext *ctx, @@ -180,6 +172,8 @@ toggle_client_flag (CoglContext *ctx, unsigned long flag, GLenum gl_flag) { + g_return_val_if_fail (ctx->driver != COGL_DRIVER_GLES2, FALSE); + /* Toggles and caches a single client-side enable flag * on or off by comparing to current state */ @@ -201,7 +195,7 @@ toggle_client_flag (CoglContext *ctx, return FALSE; } -#endif /* HAVE_COGL_GLES2 */ +#endif void _cogl_enable (unsigned long flags) @@ -215,13 +209,18 @@ _cogl_enable (unsigned long flags) COGL_ENABLE_BACKFACE_CULLING, GL_CULL_FACE); - toggle_client_flag (ctx, flags, - COGL_ENABLE_VERTEX_ARRAY, - GL_VERTEX_ARRAY); +#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES) + if (ctx->driver != COGL_DRIVER_GLES2) + { + toggle_client_flag (ctx, flags, + COGL_ENABLE_VERTEX_ARRAY, + GL_VERTEX_ARRAY); - toggle_client_flag (ctx, flags, - COGL_ENABLE_COLOR_ARRAY, - GL_COLOR_ARRAY); + toggle_client_flag (ctx, flags, + COGL_ENABLE_COLOR_ARRAY, + GL_COLOR_ARRAY); + } +#endif } unsigned long @@ -557,9 +556,9 @@ _cogl_read_pixels_with_rowstride (int x, 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 */ -#ifndef COGL_HAS_GL - if (gl_format != GL_RGBA || gl_type != GL_UNSIGNED_BYTE || - rowstride != 4 * width) + if (ctx->driver != COGL_DRIVER_GL && + (gl_format != GL_RGBA || gl_type != GL_UNSIGNED_BYTE || + rowstride != 4 * width)) { CoglBitmap *tmp_bmp, *dst_bmp; guint8 *tmp_data = g_malloc (width * height * 4); @@ -599,7 +598,6 @@ _cogl_read_pixels_with_rowstride (int x, cogl_object_unref (tmp_bmp); } else -#endif { ctx->texture_driver->prep_gl_for_pixels_download (rowstride, bpp); diff --git a/cogl/driver/gl/cogl-gl.c b/cogl/driver/gl/cogl-gl.c index a701cb787..e2c1a3ce6 100644 --- a/cogl/driver/gl/cogl-gl.c +++ b/cogl/driver/gl/cogl-gl.c @@ -72,13 +72,12 @@ _cogl_get_gl_version (int *major_out, int *minor_out) } gboolean -_cogl_gl_check_version (GError **error) +_cogl_gl_check_gl_version (CoglContext *ctx, + GError **error) { int major, minor; const char *gl_extensions; - _COGL_GET_CONTEXT (ctx, FALSE); - if (!_cogl_get_gl_version (&major, &minor)) { g_set_error (error, @@ -166,8 +165,7 @@ _cogl_gl_update_features (CoglContext *context) _cogl_feature_check_ext_functions (context, gl_major, gl_minor, - gl_extensions, - 0 /* gles_version */); + gl_extensions); if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 2, 0) || _cogl_check_extension ("GL_ARB_texture_non_power_of_two", gl_extensions)) diff --git a/cogl/driver/gles/cogl-gles.c b/cogl/driver/gles/cogl-gles.c index 0d97d2b63..7035c691d 100644 --- a/cogl/driver/gles/cogl-gles.c +++ b/cogl/driver/gles/cogl-gles.c @@ -33,7 +33,7 @@ #include "cogl-feature-private.h" gboolean -_cogl_gl_check_version (GError **error) +_cogl_gles_check_gl_version (GError **error) { /* The GLES backend doesn't have any particular version requirements */ return TRUE; @@ -44,14 +44,11 @@ _cogl_gl_check_version (GError **error) * different GL contexts so it is the winsys backend's responsiblity * to know when to re-query the GL extensions. */ void -_cogl_gl_update_features (CoglContext *context) +_cogl_gles_update_features (CoglContext *context) { CoglPrivateFeatureFlags private_flags = 0; CoglFeatureFlags flags = 0; const char *gl_extensions; -#ifndef HAVE_COGL_GLES2 - int max_clip_planes = 0; -#endif int num_stencil_bits = 0; /* We have to special case getting the pointer to the glGetString @@ -77,32 +74,31 @@ _cogl_gl_update_features (CoglContext *context) _cogl_feature_check_ext_functions (context, -1 /* GL major version */, -1 /* GL minor version */, - gl_extensions, -#ifdef HAVE_COGL_GLES2 - COGL_EXT_IN_GLES2 -#else - COGL_EXT_IN_GLES -#endif - ); + gl_extensions); GE( context, glGetIntegerv (GL_STENCIL_BITS, &num_stencil_bits) ); /* We need at least three stencil bits to combine clips */ if (num_stencil_bits > 2) flags |= COGL_FEATURE_STENCIL_BUFFER; -#ifndef HAVE_COGL_GLES2 - GE( context, glGetIntegerv (GL_MAX_CLIP_PLANES, &max_clip_planes) ); - if (max_clip_planes >= 4) - flags |= COGL_FEATURE_FOUR_CLIP_PLANES; +#ifdef HAVE_COGL_GLES + if (context->driver == COGL_DRIVER_GLES1) + { + int max_clip_planes; + GE( context, glGetIntegerv (GL_MAX_CLIP_PLANES, &max_clip_planes) ); + if (max_clip_planes >= 4) + flags |= COGL_FEATURE_FOUR_CLIP_PLANES; + } #endif -#ifdef HAVE_COGL_GLES2 - flags |= COGL_FEATURE_SHADERS_GLSL | COGL_FEATURE_OFFSCREEN; - /* Note GLES 2 core doesn't support mipmaps for npot textures or - * repeat modes other than CLAMP_TO_EDGE. */ - flags |= COGL_FEATURE_TEXTURE_NPOT_BASIC; - flags |= COGL_FEATURE_DEPTH_RANGE; -#endif + if (context->driver == COGL_DRIVER_GLES2) + { + flags |= COGL_FEATURE_SHADERS_GLSL | COGL_FEATURE_OFFSCREEN; + /* Note GLES 2 core doesn't support mipmaps for npot textures or + * repeat modes other than CLAMP_TO_EDGE. */ + flags |= COGL_FEATURE_TEXTURE_NPOT_BASIC; + flags |= COGL_FEATURE_DEPTH_RANGE; + } flags |= COGL_FEATURE_VBOS; diff --git a/cogl/driver/gles/cogl-texture-driver-gles.c b/cogl/driver/gles/cogl-texture-driver-gles.c index 0571848c0..5123993b3 100644 --- a/cogl/driver/gles/cogl-texture-driver-gles.c +++ b/cogl/driver/gles/cogl-texture-driver-gles.c @@ -499,11 +499,10 @@ _cogl_texture_driver_allows_foreign_gl_target (GLenum gl_target) static void _cogl_texture_driver_gl_generate_mipmaps (GLenum gl_target) { -#ifdef HAVE_COGL_GLES2 _COGL_GET_CONTEXT (ctx, NO_RETVAL); - GE( ctx, glGenerateMipmap (gl_target) ); -#endif + if (ctx->driver == COGL_DRIVER_GLES2) + GE( ctx, glGenerateMipmap (gl_target) ); } static CoglPixelFormat diff --git a/cogl/winsys/cogl-winsys-egl.c b/cogl/winsys/cogl-winsys-egl.c index 5597cd127..971790676 100644 --- a/cogl/winsys/cogl-winsys-egl.c +++ b/cogl/winsys/cogl-winsys-egl.c @@ -353,7 +353,8 @@ check_egl_extensions (CoglRenderer *renderer) egl_renderer->private_features = 0; for (i = 0; i < G_N_ELEMENTS (winsys_feature_data); i++) if (_cogl_feature_check (winsys, - "EGL", winsys_feature_data + i, 0, 0, 0, + "EGL", winsys_feature_data + i, 0, 0, + COGL_DRIVER_GL, /* the driver isn't used */ egl_extensions, egl_renderer)) { @@ -514,7 +515,7 @@ update_winsys_features (CoglContext *context) check_egl_extensions (context->display->renderer); - _cogl_gl_update_features (context); + _cogl_context_update_features (context); #if defined (COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT) || \ defined (COGL_HAS_EGL_PLATFORM_WAYLAND_SUPPORT) @@ -619,23 +620,17 @@ try_create_context (CoglDisplay *display, EGL_BUFFER_SIZE, EGL_DONT_CARE, -#if defined (HAVE_COGL_GL) - EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, -#elif defined (HAVE_COGL_GLES2) - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, -#else - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT, -#endif + EGL_RENDERABLE_TYPE, (display->renderer->driver == COGL_DRIVER_GL ? + EGL_OPENGL_BIT : + display->renderer->driver == COGL_DRIVER_GLES1 ? + EGL_OPENGL_ES_BIT : + EGL_OPENGL_ES2_BIT), EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE }; -#if defined (HAVE_COGL_GLES2) - EGLint attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; -#else - EGLint *attribs = NULL; -#endif + EGLint attribs[3]; #ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT XVisualInfo *xvisinfo; @@ -646,11 +641,19 @@ try_create_context (CoglDisplay *display, #endif const char *error_message; + 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; + edpy = egl_renderer->edpy; -#ifdef HAVE_COGL_GL - eglBindAPI (EGL_OPENGL_API); -#endif + if (display->renderer->driver == COGL_DRIVER_GL) + eglBindAPI (EGL_OPENGL_API); /* Some GLES hardware can't support a stencil buffer: */ if (retry_cookie == 1) diff --git a/cogl/winsys/cogl-winsys-glx.c b/cogl/winsys/cogl-winsys-glx.c index 80c3767bb..b4ee25e65 100644 --- a/cogl/winsys/cogl-winsys-glx.c +++ b/cogl/winsys/cogl-winsys-glx.c @@ -265,17 +265,75 @@ glx_event_filter_cb (XEvent *xevent, void *data) static void _cogl_winsys_renderer_disconnect (CoglRenderer *renderer) { + CoglGLXRenderer *glx_renderer = renderer->winsys; + _cogl_xlib_renderer_disconnect (renderer); + if (glx_renderer->libgl_module) + g_module_close (glx_renderer->libgl_module); + g_slice_free (CoglGLXRenderer, renderer->winsys); } +static gboolean +resolve_core_glx_functions (CoglRenderer *renderer, + GError **error) +{ + CoglGLXRenderer *glx_renderer; + + glx_renderer = renderer->winsys; + + if (!g_module_symbol (glx_renderer->libgl_module, "glXCreatePixmap", + (void **) &glx_renderer->glXCreatePixmap) || + !g_module_symbol (glx_renderer->libgl_module, "glXDestroyPixmap", + (void **) &glx_renderer->glXDestroyPixmap) || + !g_module_symbol (glx_renderer->libgl_module, "glXChooseFBConfig", + (void **) &glx_renderer->glXChooseFBConfig) || + !g_module_symbol (glx_renderer->libgl_module, "glXCreateNewContext", + (void **) &glx_renderer->glXCreateNewContext) || + !g_module_symbol (glx_renderer->libgl_module, "glXGetFBConfigAttrib", + (void **) &glx_renderer->glXGetFBConfigAttrib) || + !g_module_symbol (glx_renderer->libgl_module, "glXQueryVersion", + (void **) &glx_renderer->glXQueryVersion) || + !g_module_symbol (glx_renderer->libgl_module, "glXDestroyContext", + (void **) &glx_renderer->glXDestroyContext) || + !g_module_symbol (glx_renderer->libgl_module, "glXMakeContextCurrent", + (void **) &glx_renderer->glXMakeContextCurrent) || + !g_module_symbol (glx_renderer->libgl_module, "glXSwapBuffers", + (void **) &glx_renderer->glXSwapBuffers) || + !g_module_symbol (glx_renderer->libgl_module, "glXQueryExtension", + (void **) &glx_renderer->glXQueryExtension) || + !g_module_symbol (glx_renderer->libgl_module, "glXIsDirect", + (void **) &glx_renderer->glXIsDirect) || + !g_module_symbol (glx_renderer->libgl_module, "glXGetVisualFromFBConfig", + (void **) &glx_renderer->glXGetVisualFromFBConfig) || + !g_module_symbol (glx_renderer->libgl_module, "glXSelectEvent", + (void **) &glx_renderer->glXSelectEvent) || + !g_module_symbol (glx_renderer->libgl_module, "glXCreateWindow", + (void **) &glx_renderer->glXCreateWindow) || + !g_module_symbol (glx_renderer->libgl_module, "glXGetFBConfigs", + (void **) &glx_renderer->glXGetFBConfigs) || + !g_module_symbol (glx_renderer->libgl_module, "glXDestroyWindow", + (void **) &glx_renderer->glXDestroyWindow) || + !g_module_symbol (glx_renderer->libgl_module, "glXQueryExtensionsString", + (void **) &glx_renderer->glXQueryExtensionsString)) + { + g_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_INIT, + "Failed to resolve required GLX symbol"); + return FALSE; + } + + return TRUE; +} + static gboolean _cogl_winsys_renderer_connect (CoglRenderer *renderer, GError **error) { CoglGLXRenderer *glx_renderer; CoglXlibRenderer *xlib_renderer; + char *libgl_module_path; renderer->winsys = g_slice_new0 (CoglGLXRenderer); @@ -285,9 +343,28 @@ _cogl_winsys_renderer_connect (CoglRenderer *renderer, if (!_cogl_xlib_renderer_connect (renderer, error)) goto error; - if (!glXQueryExtension (xlib_renderer->xdpy, - &glx_renderer->glx_error_base, - &glx_renderer->glx_event_base)) + libgl_module_path = g_module_build_path (NULL, /* standard lib search path */ + COGL_GL_LIBNAME); + + glx_renderer->libgl_module = g_module_open (libgl_module_path, + G_MODULE_BIND_LAZY); + + g_free (libgl_module_path); + + if (glx_renderer->libgl_module == NULL) + { + g_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_INIT, + "Failed to dynamically open the OpenGL library"); + goto error; + } + + if (!resolve_core_glx_functions (renderer, error)) + goto error; + + if (!glx_renderer->glXQueryExtension (xlib_renderer->xdpy, + &glx_renderer->glx_error_base, + &glx_renderer->glx_event_base)) { g_set_error (error, COGL_WINSYS_ERROR, COGL_WINSYS_ERROR_INIT, @@ -298,9 +375,9 @@ _cogl_winsys_renderer_connect (CoglRenderer *renderer, /* XXX: Note: For a long time Mesa exported a hybrid GLX, exporting * extensions specified to require GLX 1.3, but still reporting 1.2 * via glXQueryVersion. */ - if (!glXQueryVersion (xlib_renderer->xdpy, - &glx_renderer->glx_major, - &glx_renderer->glx_minor) + if (!glx_renderer->glXQueryVersion (xlib_renderer->xdpy, + &glx_renderer->glx_major, + &glx_renderer->glx_minor) || !(glx_renderer->glx_major == 1 && glx_renderer->glx_minor >= 2)) { g_set_error (error, COGL_WINSYS_ERROR, @@ -325,17 +402,19 @@ update_winsys_features (CoglContext *context) CoglXlibRenderer *xlib_renderer = context->display->renderer->winsys; CoglGLXRenderer *glx_renderer = context->display->renderer->winsys; const char *glx_extensions; + int default_screen; int i; g_return_if_fail (glx_display->glx_context); - _cogl_gl_update_features (context); + _cogl_context_update_features (context); memset (context->winsys_features, 0, sizeof (context->winsys_features)); + default_screen = DefaultScreen (xlib_renderer->xdpy); glx_extensions = - glXQueryExtensionsString (xlib_renderer->xdpy, - DefaultScreen (xlib_renderer->xdpy)); + glx_renderer->glXQueryExtensionsString (xlib_renderer->xdpy, + default_screen); COGL_NOTE (WINSYS, " GLX Extensions: %s", glx_extensions); @@ -346,7 +425,8 @@ update_winsys_features (CoglContext *context) for (i = 0; i < G_N_ELEMENTS (winsys_feature_data); i++) if (_cogl_feature_check (_cogl_context_get_winsys (context), - "GLX", winsys_feature_data + i, 0, 0, 0, + "GLX", winsys_feature_data + i, 0, 0, + COGL_DRIVER_GL, /* the driver isn't used */ glx_extensions, glx_renderer)) { @@ -407,6 +487,7 @@ find_fbconfig (CoglDisplay *display, GError **error) { CoglXlibRenderer *xlib_renderer = display->renderer->winsys; + CoglGLXRenderer *glx_renderer = display->renderer->winsys; GLXFBConfig *configs = NULL; int n_configs, i; static const int attributes[] = { @@ -424,10 +505,10 @@ find_fbconfig (CoglDisplay *display, gboolean ret = TRUE; int xscreen_num = DefaultScreen (xlib_renderer->xdpy); - configs = glXChooseFBConfig (xlib_renderer->xdpy, - xscreen_num, - attributes, - &n_configs); + configs = glx_renderer->glXChooseFBConfig (xlib_renderer->xdpy, + xscreen_num, + attributes, + &n_configs); if (!configs || n_configs == 0) { g_set_error (error, COGL_WINSYS_ERROR, @@ -443,7 +524,8 @@ find_fbconfig (CoglDisplay *display, { XVisualInfo *vinfo; - vinfo = glXGetVisualFromFBConfig (xlib_renderer->xdpy, configs[i]); + vinfo = glx_renderer->glXGetVisualFromFBConfig (xlib_renderer->xdpy, + configs[i]); if (vinfo == NULL) continue; @@ -519,11 +601,12 @@ create_context (CoglDisplay *display, GError **error) COGL_NOTE (WINSYS, "Creating GLX Context (display: %p)", xlib_renderer->xdpy); - glx_display->glx_context = glXCreateNewContext (xlib_renderer->xdpy, - config, - GLX_RGBA_TYPE, - NULL, - True); + glx_display->glx_context = + glx_renderer->glXCreateNewContext (xlib_renderer->xdpy, + config, + GLX_RGBA_TYPE, + NULL, + True); if (glx_display->glx_context == NULL) { g_set_error (error, COGL_WINSYS_ERROR, @@ -533,7 +616,7 @@ create_context (CoglDisplay *display, GError **error) } glx_renderer->is_direct = - glXIsDirect (xlib_renderer->xdpy, glx_display->glx_context); + glx_renderer->glXIsDirect (xlib_renderer->xdpy, glx_display->glx_context); COGL_NOTE (WINSYS, "Setting %s context", glx_renderer->is_direct ? "direct" : "indirect"); @@ -543,7 +626,8 @@ create_context (CoglDisplay *display, GError **error) * framebuffer is in use. */ - xvisinfo = glXGetVisualFromFBConfig (xlib_renderer->xdpy, config); + xvisinfo = glx_renderer->glXGetVisualFromFBConfig (xlib_renderer->xdpy, + config); if (xvisinfo == NULL) { g_set_error (error, COGL_WINSYS_ERROR, @@ -577,10 +661,11 @@ create_context (CoglDisplay *display, GError **error) * drawables. */ if (glx_renderer->glx_major == 1 && glx_renderer->glx_minor >= 3) { - glx_display->dummy_glxwin = glXCreateWindow (xlib_renderer->xdpy, - config, - xlib_display->dummy_xwin, - NULL); + glx_display->dummy_glxwin = + glx_renderer->glXCreateWindow (xlib_renderer->xdpy, + config, + xlib_display->dummy_xwin, + NULL); } if (glx_display->dummy_glxwin) @@ -591,10 +676,10 @@ create_context (CoglDisplay *display, GError **error) COGL_NOTE (WINSYS, "Selecting dummy 0x%x for the GLX context", (unsigned int) dummy_drawable); - glXMakeContextCurrent (xlib_renderer->xdpy, - dummy_drawable, - dummy_drawable, - glx_display->glx_context); + glx_renderer->glXMakeContextCurrent (xlib_renderer->xdpy, + dummy_drawable, + dummy_drawable, + glx_display->glx_context); XFree (xvisinfo); @@ -615,19 +700,23 @@ _cogl_winsys_display_destroy (CoglDisplay *display) CoglGLXDisplay *glx_display = display->winsys; CoglXlibDisplay *xlib_display = display->winsys; CoglXlibRenderer *xlib_renderer = display->renderer->winsys; + CoglGLXRenderer *glx_renderer = display->renderer->winsys; g_return_if_fail (glx_display != NULL); if (glx_display->glx_context) { - glXMakeContextCurrent (xlib_renderer->xdpy, None, None, NULL); - glXDestroyContext (xlib_renderer->xdpy, glx_display->glx_context); + glx_renderer->glXMakeContextCurrent (xlib_renderer->xdpy, + None, None, NULL); + glx_renderer->glXDestroyContext (xlib_renderer->xdpy, + glx_display->glx_context); glx_display->glx_context = NULL; } if (glx_display->dummy_glxwin) { - glXDestroyWindow (xlib_renderer->xdpy, glx_display->dummy_glxwin); + glx_renderer->glXDestroyWindow (xlib_renderer->xdpy, + glx_display->dummy_glxwin); glx_display->dummy_glxwin = None; } @@ -761,8 +850,8 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen, _cogl_xlib_renderer_trap_errors (display->renderer, &state); - xvisinfo = glXGetVisualFromFBConfig (xlib_renderer->xdpy, - glx_display->fbconfig); + xvisinfo = glx_renderer->glXGetVisualFromFBConfig (xlib_renderer->xdpy, + glx_display->fbconfig); if (xvisinfo == NULL) { g_set_error (error, COGL_WINSYS_ERROR, @@ -825,10 +914,10 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen, if (glx_renderer->glx_major == 1 && glx_renderer->glx_minor >= 3) { glx_onscreen->glxwin = - glXCreateWindow (xlib_renderer->xdpy, - glx_display->fbconfig, - xlib_onscreen->xwin, - NULL); + glx_renderer->glXCreateWindow (xlib_renderer->xdpy, + glx_display->fbconfig, + xlib_onscreen->xwin, + NULL); } #ifdef GLX_INTEL_swap_event @@ -841,9 +930,9 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen, * because we rely on it to advance the master clock, and * drive redraw/relayout, animations and event handling. */ - glXSelectEvent (xlib_renderer->xdpy, - drawable, - GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK); + glx_renderer->glXSelectEvent (xlib_renderer->xdpy, + drawable, + GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK); } #endif /* GLX_INTEL_swap_event */ @@ -856,6 +945,7 @@ _cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen) CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); CoglContext *context = framebuffer->context; CoglXlibRenderer *xlib_renderer = context->display->renderer->winsys; + CoglGLXRenderer *glx_renderer = context->display->renderer->winsys; CoglXlibTrapState old_state; CoglOnscreenXlib *xlib_onscreen = onscreen->winsys; CoglOnscreenGLX *glx_onscreen = onscreen->winsys; @@ -868,7 +958,8 @@ _cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen) if (glx_onscreen->glxwin != None) { - glXDestroyWindow (xlib_renderer->xdpy, glx_onscreen->glxwin); + glx_renderer->glXDestroyWindow (xlib_renderer->xdpy, + glx_onscreen->glxwin); glx_onscreen->glxwin = None; } @@ -913,9 +1004,9 @@ _cogl_winsys_onscreen_bind (CoglOnscreen *onscreen) _cogl_xlib_renderer_trap_errors (context->display->renderer, &old_state); - glXMakeContextCurrent (xlib_renderer->xdpy, - drawable, drawable, - glx_display->glx_context); + glx_renderer->glXMakeContextCurrent (xlib_renderer->xdpy, + drawable, drawable, + glx_display->glx_context); } else { @@ -934,10 +1025,10 @@ _cogl_winsys_onscreen_bind (CoglOnscreen *onscreen) xlib_onscreen->is_foreign_xwin ? "foreign" : "native", glx_display->glx_context); - glXMakeContextCurrent (xlib_renderer->xdpy, - drawable, - drawable, - glx_display->glx_context); + glx_renderer->glXMakeContextCurrent (xlib_renderer->xdpy, + drawable, + drawable, + glx_display->glx_context); /* In case we are using GLX_SGI_swap_control for vblank syncing * we need call glXSwapIntervalSGI here to make sure that it @@ -1252,7 +1343,7 @@ _cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen) else have_counter = FALSE; - glXSwapBuffers (xlib_renderer->xdpy, drawable); + glx_renderer->glXSwapBuffers (xlib_renderer->xdpy, drawable); if (have_counter) glx_onscreen->last_swap_vsync_counter = _cogl_winsys_get_vsync_counter (); @@ -1341,6 +1432,7 @@ _cogl_winsys_xlib_get_visual_info (void) { CoglGLXDisplay *glx_display; CoglXlibRenderer *xlib_renderer; + CoglGLXRenderer *glx_renderer; _COGL_GET_CONTEXT (ctx, NULL); @@ -1348,11 +1440,13 @@ _cogl_winsys_xlib_get_visual_info (void) glx_display = ctx->display->winsys; xlib_renderer = ctx->display->renderer->winsys; + glx_renderer = ctx->display->renderer->winsys; if (!glx_display->found_fbconfig) return NULL; - return glXGetVisualFromFBConfig (xlib_renderer->xdpy, glx_display->fbconfig); + return glx_renderer->glXGetVisualFromFBConfig (xlib_renderer->xdpy, + glx_display->fbconfig); } static gboolean @@ -1362,6 +1456,7 @@ get_fbconfig_for_depth (CoglContext *context, gboolean *can_mipmap_ret) { CoglXlibRenderer *xlib_renderer; + CoglGLXRenderer *glx_renderer; CoglGLXDisplay *glx_display; Display *dpy; GLXFBConfig *fbconfigs; @@ -1371,6 +1466,7 @@ get_fbconfig_for_depth (CoglContext *context, gboolean found = FALSE; xlib_renderer = context->display->renderer->winsys; + glx_renderer = context->display->renderer->winsys; glx_display = context->display->winsys; /* Check if we've already got a cached config for this depth */ @@ -1386,7 +1482,8 @@ get_fbconfig_for_depth (CoglContext *context, dpy = xlib_renderer->xdpy; - fbconfigs = glXGetFBConfigs (dpy, DefaultScreen (dpy), &n_elements); + fbconfigs = glx_renderer->glXGetFBConfigs (dpy, DefaultScreen (dpy), + &n_elements); db = G_MAXSHORT; stencil = G_MAXSHORT; @@ -1398,7 +1495,7 @@ get_fbconfig_for_depth (CoglContext *context, XVisualInfo *vi; int visual_depth; - vi = glXGetVisualFromFBConfig (dpy, fbconfigs[i]); + vi = glx_renderer->glXGetVisualFromFBConfig (dpy, fbconfigs[i]); if (vi == NULL) continue; @@ -1409,24 +1506,24 @@ get_fbconfig_for_depth (CoglContext *context, if (visual_depth != depth) continue; - glXGetFBConfigAttrib (dpy, - fbconfigs[i], - GLX_ALPHA_SIZE, - &alpha); - glXGetFBConfigAttrib (dpy, - fbconfigs[i], - GLX_BUFFER_SIZE, - &value); + glx_renderer->glXGetFBConfigAttrib (dpy, + fbconfigs[i], + GLX_ALPHA_SIZE, + &alpha); + glx_renderer->glXGetFBConfigAttrib (dpy, + fbconfigs[i], + GLX_BUFFER_SIZE, + &value); if (value != depth && (value - alpha) != depth) continue; value = 0; if (depth == 32) { - glXGetFBConfigAttrib (dpy, - fbconfigs[i], - GLX_BIND_TO_TEXTURE_RGBA_EXT, - &value); + glx_renderer->glXGetFBConfigAttrib (dpy, + fbconfigs[i], + GLX_BIND_TO_TEXTURE_RGBA_EXT, + &value); if (value) rgba = 1; } @@ -1436,27 +1533,27 @@ get_fbconfig_for_depth (CoglContext *context, if (rgba) continue; - glXGetFBConfigAttrib (dpy, - fbconfigs[i], - GLX_BIND_TO_TEXTURE_RGB_EXT, - &value); + glx_renderer->glXGetFBConfigAttrib (dpy, + fbconfigs[i], + GLX_BIND_TO_TEXTURE_RGB_EXT, + &value); if (!value) continue; } - glXGetFBConfigAttrib (dpy, - fbconfigs[i], - GLX_DOUBLEBUFFER, - &value); + glx_renderer->glXGetFBConfigAttrib (dpy, + fbconfigs[i], + GLX_DOUBLEBUFFER, + &value); if (value > db) continue; db = value; - glXGetFBConfigAttrib (dpy, - fbconfigs[i], - GLX_STENCIL_SIZE, - &value); + glx_renderer->glXGetFBConfigAttrib (dpy, + fbconfigs[i], + GLX_STENCIL_SIZE, + &value); if (value > stencil) continue; @@ -1465,10 +1562,10 @@ get_fbconfig_for_depth (CoglContext *context, /* glGenerateMipmap is defined in the offscreen extension */ if (cogl_features_available (COGL_FEATURE_OFFSCREEN)) { - glXGetFBConfigAttrib (dpy, - fbconfigs[i], - GLX_BIND_TO_MIPMAP_TEXTURE_EXT, - &value); + glx_renderer->glXGetFBConfigAttrib (dpy, + fbconfigs[i], + GLX_BIND_TO_MIPMAP_TEXTURE_EXT, + &value); if (value < mipmap) continue; @@ -1548,6 +1645,7 @@ try_create_glx_pixmap (CoglContext *context, CoglTexturePixmapGLX *glx_tex_pixmap = tex_pixmap->winsys; CoglRenderer *renderer; CoglXlibRenderer *xlib_renderer; + CoglGLXRenderer *glx_renderer; Display *dpy; /* We have to initialize this *opaque* variable because gcc tries to * be too smart for its own good and warns that the variable may be @@ -1560,6 +1658,7 @@ try_create_glx_pixmap (CoglContext *context, renderer = context->display->renderer; xlib_renderer = renderer->winsys; + glx_renderer = renderer->winsys; dpy = xlib_renderer->xdpy; if (!get_fbconfig_for_depth (context, @@ -1606,10 +1705,11 @@ try_create_glx_pixmap (CoglContext *context, _cogl_xlib_renderer_trap_errors (renderer, &trap_state); - glx_tex_pixmap->glx_pixmap = glXCreatePixmap (dpy, - fb_config, - tex_pixmap->pixmap, - attribs); + glx_tex_pixmap->glx_pixmap = + glx_renderer->glXCreatePixmap (dpy, + fb_config, + tex_pixmap->pixmap, + attribs); glx_tex_pixmap->has_mipmap_space = mipmap; XSync (dpy, False); @@ -1618,7 +1718,7 @@ try_create_glx_pixmap (CoglContext *context, { COGL_NOTE (TEXTURE_PIXMAP, "Failed to create pixmap for %p", tex_pixmap); _cogl_xlib_renderer_trap_errors (renderer, &trap_state); - glXDestroyPixmap (dpy, glx_tex_pixmap->glx_pixmap); + glx_renderer->glXDestroyPixmap (dpy, glx_tex_pixmap->glx_pixmap); XSync (dpy, False); _cogl_xlib_renderer_untrap_errors (renderer, &trap_state); @@ -1702,7 +1802,8 @@ free_glx_pixmap (CoglContext *context, * http://bugzilla.clutter-project.org/show_bug.cgi?id=2324 */ _cogl_xlib_renderer_trap_errors (renderer, &trap_state); - glXDestroyPixmap (xlib_renderer->xdpy, glx_tex_pixmap->glx_pixmap); + glx_renderer->glXDestroyPixmap (xlib_renderer->xdpy, + glx_tex_pixmap->glx_pixmap); XSync (xlib_renderer->xdpy, False); _cogl_xlib_renderer_untrap_errors (renderer, &trap_state); diff --git a/cogl/winsys/cogl-winsys-stub.c b/cogl/winsys/cogl-winsys-stub.c index 5db9918e8..f6a2b4113 100644 --- a/cogl/winsys/cogl-winsys-stub.c +++ b/cogl/winsys/cogl-winsys-stub.c @@ -83,10 +83,10 @@ _cogl_winsys_context_init (CoglContext *context, GError **error) { context->winsys = &_cogl_winsys_stub_dummy_ptr; - if (!_cogl_gl_check_version (error)) + if (!_cogl_context_check_gl_version (context, error)) return FALSE; - _cogl_gl_update_features (context); + _cogl_context_update_features (context); memset (context->winsys_features, 0, sizeof (context->winsys_features)); diff --git a/cogl/winsys/cogl-winsys-wgl.c b/cogl/winsys/cogl-winsys-wgl.c index fef731348..6596f7408 100644 --- a/cogl/winsys/cogl-winsys-wgl.c +++ b/cogl/winsys/cogl-winsys-wgl.c @@ -513,6 +513,8 @@ get_wgl_extensions_string (HDC dc) const char * (APIENTRY *pf_wglGetExtensionsStringARB) (HDC); const char * (APIENTRY *pf_wglGetExtensionsStringEXT) (void); + _COGL_GET_CONTEXT (ctx, NULL); + /* According to the docs for these two extensions, you are supposed to use wglGetProcAddress to detect their availability so presumably it will return NULL if they are not available */ @@ -550,7 +552,7 @@ update_winsys_features (CoglContext *context) g_return_if_fail (wgl_display->wgl_context); - _cogl_gl_update_features (context); + _cogl_context_update_features (context); memset (context->winsys_features, 0, sizeof (context->winsys_features)); @@ -567,7 +569,8 @@ update_winsys_features (CoglContext *context) for (i = 0; i < G_N_ELEMENTS (winsys_feature_data); i++) if (_cogl_feature_check (_cogl_context_get_winsys (context), - "WGL", winsys_feature_data + i, 0, 0, 0, + "WGL", winsys_feature_data + i, 0, 0, + COGL_DRIVER_GL, wgl_extensions, wgl_renderer)) { diff --git a/configure.ac b/configure.ac index ea7dea512..cba739cf2 100644 --- a/configure.ac +++ b/configure.ac @@ -356,9 +356,16 @@ dnl ============================================================ dnl ======================================================== dnl Drivers first... dnl ======================================================== -DRIVER_COUNT=0 EGL_CHECKED=no +dnl This gets set to yes if Cogl directly links to the GL library API +dnl so it doesn't need to be dlopened. This currently happens on OSX +dnl and WGL where it's not clear if window system API can be separated +dnl from the GL API. +GL_LIBRARY_DIRECTLY_LINKED=no + +enabled_drivers="" + AC_ARG_ENABLE( [gles1], [AC_HELP_STRING([--enable-gles1=@<:@no/yes@:>@], [Enable support for OpenGL-ES 1.1 @<:@default=no@:>@])], @@ -370,9 +377,7 @@ AS_IF([test "x$enable_gles1" = "xyes"], AS_IF([test "x$platform_win32" = "xyes"], [AC_MSG_ERROR([GLES 1 not available for win32])]) - DRIVER_COUNT=$((DRIVER_COUNT + 1)) - COGL_DRIVER=gles - glesversion=1.1 + enabled_drivers="$enabled_drivers gles1" cogl_gl_headers="GLES/gl.h GLES/glext.h" @@ -381,7 +386,8 @@ AS_IF([test "x$enable_gles1" = "xyes"], COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_GLES1" PKG_CHECK_EXISTS([glesv1_cm], - [COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES glesv1_cm" + [COGL_PKG_REQUIRES_GL="$COGL_PKG_REQUIRES_GL glesv1_cm" + COGL_GLES1_LIBNAME="GLESv1_CM" NEED_EGL=yes ], [ @@ -424,10 +430,10 @@ AS_IF([test "x$enable_gles1" = "xyes"], # bundles the GLES and EGL API together and -lGLESv1_CM # would be used for a standalone GLES API. AC_CHECK_LIB(GLES_CM, [eglInitialize], - [COGL_EXTRA_LDFLAGS="$COGL_EXTRA_LDFLAGS -lGLES_CM"], + [COGL_GLES1_LIBNAME="GLES_CM"], [ AC_CHECK_LIB(GLESv1_CM, [glFlush], - [COGL_EXTRA_LDFLAGS="$COGL_EXTRA_LDFLAGS -lGLESv1_CM" + [COGL_GLES1_LIBNAME="GLESv1_CM" NEED_SEPARATE_EGL=yes ], [AC_MSG_ERROR([Unable to locate required GLES 1.x Common Profile library])]) @@ -448,9 +454,7 @@ AS_IF([test "x$enable_gles2" = "xyes"], AS_IF([test "x$platform_win32" = "xyes"], [AC_MSG_ERROR([GLES 2 not available for win32])]) - DRIVER_COUNT=$((DRIVER_COUNT + 1)) - COGL_DRIVER=gles - glesversion=2.0 + enabled_drivers="$enabled_drivers gles2" cogl_gl_headers="GLES2/gl2.h GLES2/gl2ext.h" AC_DEFINE([HAVE_COGL_GLES2], 1, [Have GLES 2.0 for rendering]) @@ -458,7 +462,9 @@ AS_IF([test "x$enable_gles2" = "xyes"], COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_GLES2" PKG_CHECK_EXISTS([glesv2], - [COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES glesv2"], + [COGL_PKG_REQUIRES_GL="$COGL_PKG_REQUIRES_GL glesv2" + COGL_GLES2_LIBNAME="GLESv2" + ], [ # We have to check the two headers independently as GLES2/gl2ext.h # needs to include GLES2/gl2.h to have the GL types defined (eg. @@ -471,7 +477,7 @@ AS_IF([test "x$enable_gles2" = "xyes"], [AC_MSG_ERROR([Unable to locate GLES2/gl2ext.h])], [#include ]) - COGL_EXTRA_LDFLAGS="$COGL_EXTRA_LDFLAGS -lGLESv2" + COGL_GLES2_LIBNAME="GLESv2" ]) NEED_EGL=yes @@ -481,12 +487,11 @@ AC_ARG_ENABLE( [gl], [AC_HELP_STRING([--enable-gl=@<:@no/yes@:>@], [Enable support for OpenGL @<:@default=yes@:>@])], [], - [AS_IF([test $DRIVER_COUNT -gt 0], [enable_gl=no], [enable_gl=yes])] + [enable_gl=yes] ) AS_IF([test "x$enable_gl" = "xyes"], [ - DRIVER_COUNT=$((DRIVER_COUNT + 1)) - COGL_DRIVER=gl + enabled_drivers="$enabled_drivers gl" PKG_CHECK_EXISTS([x11], [ALLOW_GLX=yes]) @@ -496,6 +501,10 @@ AS_IF([test "x$enable_gl" = "xyes"], [ cogl_gl_headers="OpenGL/gl.h" COGL_EXTRA_LDFLAGS="$COGL_EXTRA_LDFLAGS -framework OpenGL" + dnl The GL API is being directly linked in so there is + dnl no need to dlopen it separately + GL_LIBRARY_DIRECTLY_LINKED=yes + COGL_GL_LIBNAME="" ], [test "x$platform_win32" = "xyes"], @@ -503,15 +512,22 @@ AS_IF([test "x$enable_gl" = "xyes"], COGL_EXTRA_LDFLAGS="$COGL_EXTRA_LDFLAGS -lopengl32 -lgdi32 -lwinmm" COGL_EXTRA_CFLAGS="$COGL_EXTRA_CFLAGS -D_WIN32_WINNT=0x0500" ALLOW_WGL=yes + dnl The GL API is being directly linked in so there is + dnl no need to dlopen it separately + GL_LIBRARY_DIRECTLY_LINKED=yes + COGL_GL_LIBNAME="" ], [ PKG_CHECK_EXISTS([gl], - [COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES gl"], + dnl We don't want to use COGL_PKG_REQUIRES here because we don't want to + dnl directly link against libGL + [COGL_PKG_REQUIRES_GL="$COGL_PKG_REQUIRES_GL gl"], [AC_CHECK_LIB(GL, [glGetString], - [COGL_EXTRA_LDFLAGS="$COGL_EXTRA_LDFLAGS -lGL"], + , [AC_MSG_ERROR([Unable to locate required GL library])]) ]) + COGL_GL_LIBNAME="GL" ]) AC_DEFINE([HAVE_COGL_GL], [1], [Have GL for rendering]) @@ -520,13 +536,18 @@ AS_IF([test "x$enable_gl" = "xyes"], COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS CLUTTER_COGL_HAS_GL" ]) -AS_IF([test $DRIVER_COUNT -gt 1], - [AC_MSG_ERROR(['The --enable-gl{es1,es2} options are currently mutually exclusive'])]) +AM_CONDITIONAL([COGL_DRIVER_GL_SUPPORTED], [test "x$enable_gl" = "xyes"]) +AM_CONDITIONAL([COGL_DRIVER_GLES_SUPPORTED], + [test "x$enable_gles1" = "xyes" || test "x$enable_gles2" = "xyes"]) -AC_SUBST([COGL_DRIVER]) +AC_SUBST([COGL_GL_LIBNAME]) +AC_SUBST([COGL_GLES1_LIBNAME]) +AC_SUBST([COGL_GLES2_LIBNAME]) -AM_CONDITIONAL([COGL_DRIVER_GL], [test "x$COGL_DRIVER" = "xgl"]) -AM_CONDITIONAL([COGL_DRIVER_GLES], [test "x$COGL_DRIVER" = "xgles"]) +if test "x$GL_LIBRARY_DIRECTLY_LINKED" = "xyes"; then + AC_DEFINE([HAVE_DIRECTLY_LINKED_GL_LIBRARY], [1], + [Defined if the GL library shouldn't be dlopened]) +fi dnl ======================================================== dnl Check window system integration libraries... @@ -541,7 +562,7 @@ AC_ARG_ENABLE( AS_IF([test "x$enable_glx" = "xyes"], [ AS_IF([test "x$ALLOW_GLX" != "xyes"], - [AC_MSG_ERROR([GLX not supported with $COGL_DRIVER driver])]) + [AC_MSG_ERROR([GLX not supported with this configuration])]) NEED_XLIB=yes SUPPORT_GLX=yes @@ -568,7 +589,7 @@ AC_ARG_ENABLE( AS_IF([test "x$enable_wgl" = "xyes"], [ AS_IF([test "x$ALLOW_WGL" != "xyes"], - [AC_MSG_ERROR([WGL not supported with $COGL_DRIVER driver])]) + [AC_MSG_ERROR([WGL not supported with this configuration])]) SUPPORT_WGL=yes GL_WINSYS_APIS="$GL_WINSYS_APIS wgl" @@ -691,7 +712,7 @@ AC_ARG_ENABLE( [xlib-egl-platform], [AC_HELP_STRING([--enable-xlib-egl-platform=@<:@no/yes@:>@], [Enable support for the Xlib egl platform @<:@default=auto@:>@])], [], - AS_IF([test "x$COGL_DRIVER" = "xgles" && test $EGL_PLATFORM_COUNT -eq 0], + AS_IF([test "x$enable_gles1" = "xyes" -o "x$enable_gles2" = "xyes" && test $EGL_PLATFORM_COUNT -eq 0], [enable_xlib_egl_platform=yes], [enable_xlib_egl_platform=no]) ) AS_IF([test "x$enable_xlib_egl_platform" = "xyes"], @@ -823,7 +844,22 @@ AS_IF([test "x$have_glib" = "xno"], AC_MSG_ERROR([glib-2.0 is required])) COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES glib-2.0" AC_SUBST(COGL_PKG_REQUIRES) PKG_CHECK_MODULES(COGL_DEP, [$COGL_PKG_REQUIRES]) +if test -n "$COGL_PKG_REQUIRES_GL"; then + PKG_CHECK_MODULES(COGL_DEP_GL, [$COGL_PKG_REQUIRES_GL]) + dnl Strip out the GL libraries from the GL pkg-config files so we can + dnl dynamically load them instead + gl_libs="" + for x in $COGL_DEP_GL_LIBS; do + AS_CASE([$x], + [-lGL], [], + [-lGLESv2], [], + [-lGLESv1_CM], [], + [*], [gl_libs="$gl_libs $x"]) + done + COGL_DEP_CFLAGS="$COGL_DEP_CFLAGS $COGL_DEP_CFLAGS_GL" + COGL_DEP_LIBS="$COGL_DEP_LIBS $gl_libs" +fi dnl ================================================================ dnl Misc program dependencies. @@ -920,7 +956,7 @@ echo " Prefix: ${prefix}" echo "" # Features echo " • Features:" -echo " Driver: ${COGL_DRIVER} ${glesversion}" +echo " Drivers: ${enabled_drivers}" echo " GL Window System APIs:${GL_WINSYS_APIS}" if test "x$SUPPORT_EGL" = "xyes"; then echo " EGL Platforms:${EGL_PLATFORMS}"