diff --git a/cogl.h.in b/cogl.h.in index 295cf0d4b..ffa5cce0b 100644 --- a/cogl.h.in +++ b/cogl.h.in @@ -752,6 +752,85 @@ void cogl_read_pixels (int x, */ void cogl_flush (void); +/** + * cogl_begin_gl: + * + * We do not advise nor reliably support the interleaving of raw GL drawing and + * Cogl drawing functions, but if you insist, cogl_begin_gl() and cogl_end_gl() + * provide a simple mechanism that may at least give you a fighting chance of + * succeeding. + * + * Note: this doesn't help you modify the behaviour of Cogl drawing functions + * through the modification of GL state; that will never be reliably supported, + * but if you are trying to do something like: + * + * { + * - setup some OpenGL state. + * - draw using OpenGL (e.g. glDrawArrays() ) + * - reset modified OpenGL state. + * - continue using Cogl to draw + * } + * + * You should surround blocks of drawing using raw GL with cogl_begin_gl() + * and cogl_end_gl(): + * + * { + * cogl_begin_gl (); + * - setup some OpenGL state. + * - draw using OpenGL (e.g. glDrawArrays() ) + * - reset modified OpenGL state. + * cogl_end_gl (); + * - continue using Cogl to draw + * } + * + * + * Don't ever try and do: + * + * { + * - setup some OpenGL state. + * - use Cogl to draw + * - reset modified OpenGL state. + * } + * + * When the internals of Cogl evolves, this is very liable to break. + * + * This function will flush all batched primitives, and subsequently flush + * all internal Cogl state to OpenGL as if it were going to draw something + * itself. + * + * The result is that the OpenGL modelview matrix will be setup; the state + * corresponding to the current source material will be set up and other world + * state such as backface culling, depth and fogging enabledness will be sent + * to OpenGL. + * + * Note: no special material state is flushed, so if you want Cogl to setup a + * simplified material state it is your responsibility to set a simple source + * material before calling cogl_begin_gl. E.g. by calling + * cogl_set_source_color4ub(). + * + * Note: It is your responsibility to restore any OpenGL state that you modify + * to how it was after calling cogl_begin_gl() if you don't do this then the + * result of further Cogl calls is undefined. + * + * Note: You can not nest begin/end blocks. + * + * Again we would like to stress, we do not advise the use of this API and if + * possible we would prefer to improve Cogl than have developers require raw + * OpenGL. + * + * Since: 1.0 + */ +void cogl_begin_gl (void); + +/** + * cogl_end_gl: + * + * This is the counterpart to cogl_begin_gl() used to delimit blocks of drawing + * code using raw OpenGL. Please refer to cogl_begin_gl() for full details. + * + * Since: 1.0 + */ +void cogl_end_gl (void); /* * Internal API available only to Clutter. diff --git a/common/cogl.c b/common/cogl.c index 81a0312ba..309e744d5 100644 --- a/common/cogl.c +++ b/common/cogl.c @@ -771,3 +771,78 @@ cogl_read_pixels (int x, } } +void +cogl_begin_gl (void) +{ + CoglMaterialFlushOptions options; + gulong enable_flags; + int i; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (ctx->in_begin_gl_block) + { + static gboolean shown = FALSE; + if (!shown) + g_warning ("You should not nest cogl_begin_gl/cogl_end_gl blocks"); + shown = TRUE; + return; + } + ctx->in_begin_gl_block = TRUE; + + /* Flush all batched primitives */ + cogl_flush (); + + /* Flush our clipping state to GL */ + cogl_clip_ensure (); + + /* Flush any client side matrix state */ + _cogl_current_matrix_state_flush (); + + + /* Setup the state for the current material */ + + /* We considered flushing a specific, minimal material here to try and + * simplify the GL state, but decided to avoid special cases and second + * guessing what would be actually helpful. + * + * A user should instead call cogl_set_source_color4ub() before + * cogl_begin_gl() to simplify the state flushed. + */ + options.flags = 0; + _cogl_material_flush_gl_state (ctx->source_material, &options); + + /* FIXME: This api is a bit yukky, ideally it will be removed if we + * re-work the cogl_enable mechanism */ + enable_flags |= _cogl_material_get_cogl_enable_flags (ctx->source_material); + + if (ctx->enable_backface_culling) + enable_flags |= COGL_ENABLE_BACKFACE_CULLING; + + cogl_enable (enable_flags); + + /* Disable all client texture coordinate arrays */ + for (i = 0; i < ctx->n_texcoord_arrays_enabled; i++) + { + GE (glClientActiveTexture (GL_TEXTURE0 + i)); + GE (glDisableClientState (GL_TEXTURE_COORD_ARRAY)); + } + ctx->n_texcoord_arrays_enabled = 0; +} + +void +cogl_end_gl (void) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (!ctx->in_begin_gl_block) + { + static gboolean shown = FALSE; + if (!shown) + g_warning ("cogl_end_gl is being called before cogl_begin_gl"); + shown = TRUE; + return; + } + ctx->in_begin_gl_block = FALSE; +} + diff --git a/doc/reference/cogl/cogl-sections.txt b/doc/reference/cogl/cogl-sections.txt index f383e2620..5a80895f2 100644 --- a/doc/reference/cogl/cogl-sections.txt +++ b/doc/reference/cogl/cogl-sections.txt @@ -74,6 +74,8 @@ cogl_read_pixels cogl_flush +cogl_begin_gl +cogl_end_gl COGL_TYPE_ATTRIBUTE_TYPE diff --git a/gl/cogl-context.c b/gl/cogl-context.c index 2266d9564..f587f8cd1 100644 --- a/gl/cogl-context.c +++ b/gl/cogl-context.c @@ -90,6 +90,8 @@ cogl_create_context () _context->last_path = 0; _context->stencil_material = cogl_material_new (); + _context->in_begin_gl_block = FALSE; + _context->pf_glGenRenderbuffersEXT = NULL; _context->pf_glBindRenderbufferEXT = NULL; _context->pf_glRenderbufferStorageEXT = NULL; diff --git a/gl/cogl-context.h b/gl/cogl-context.h index fa1ccb637..81d17c4fa 100644 --- a/gl/cogl-context.h +++ b/gl/cogl-context.h @@ -110,6 +110,8 @@ typedef struct guint quad_indices_short_len; CoglHandle quad_indices_short; + gboolean in_begin_gl_block; + /* Relying on glext.h to define these */ COGL_PFNGLGENRENDERBUFFERSEXTPROC pf_glGenRenderbuffersEXT; COGL_PFNGLDELETERENDERBUFFERSEXTPROC pf_glDeleteRenderbuffersEXT;