summaryrefslogtreecommitdiff
path: root/cogl/cogl-gles2-context.c
diff options
context:
space:
mode:
Diffstat (limited to 'cogl/cogl-gles2-context.c')
-rw-r--r--cogl/cogl-gles2-context.c752
1 files changed, 752 insertions, 0 deletions
diff --git a/cogl/cogl-gles2-context.c b/cogl/cogl-gles2-context.c
index deb889bf..c339ba1a 100644
--- a/cogl/cogl-gles2-context.c
+++ b/cogl/cogl-gles2-context.c
@@ -30,6 +30,8 @@
#include "config.h"
#endif
+#include <string.h>
+
#include "cogl-gles2.h"
#include "cogl-gles2-context-private.h"
@@ -49,6 +51,30 @@ static CoglGLES2Context *current_gles2_context;
static CoglUserDataKey offscreen_wrapper_key;
+/* The application's main function is renamed to this so that we can
+ * provide an alternative main function */
+#define MAIN_WRAPPER_REPLACEMENT_NAME "_c31"
+/* This uniform is used to flip the rendering or not depending on
+ * whether we are rendering to an offscreen buffer or not */
+#define MAIN_WRAPPER_FLIP_UNIFORM "_cogl_flip_vector"
+
+/* This wrapper function around 'main' is appended to every program in
+ * a separate shader so that we can add some extra code to flip the
+ * rendering when rendering to an offscreen buffer */
+static const char
+main_wrapper_function[] =
+ "uniform vec4 " MAIN_WRAPPER_FLIP_UNIFORM ";\n"
+ "\n"
+ "void\n"
+ MAIN_WRAPPER_REPLACEMENT_NAME " ();\n"
+ "\n"
+ "void\n"
+ "main ()\n"
+ "{\n"
+ " " MAIN_WRAPPER_REPLACEMENT_NAME " ();\n"
+ " gl_Position *= " MAIN_WRAPPER_FLIP_UNIFORM ";\n"
+ "}\n";
+
enum {
RESTORE_FB_NONE,
RESTORE_FB_FROM_OFFSCREEN,
@@ -98,6 +124,63 @@ detach_shader (CoglGLES2ProgramData *program_data,
}
}
+static CoglBool
+is_symbol_character (char ch)
+{
+ return g_ascii_isalnum (ch) || ch == '_';
+}
+
+static void
+replace_token (char *string,
+ const char *token,
+ const char *replacement,
+ int length)
+{
+ char *token_pos;
+ char *last_pos = string;
+ char *end = string + length;
+ int token_length = strlen (token);
+
+ /* NOTE: this assumes token and replacement are the same length */
+
+ while ((token_pos = _cogl_util_memmem (last_pos,
+ end - last_pos,
+ token,
+ token_length)))
+ {
+ /* Make sure this isn't in the middle of some longer token */
+ if ((token_pos <= string ||
+ !is_symbol_character (token_pos[-1])) &&
+ (token_pos + token_length == end ||
+ !is_symbol_character (token_pos[token_length])))
+ memcpy (token_pos, replacement, token_length);
+
+ last_pos = token_pos + token_length;
+ }
+}
+
+static void
+update_current_flip_state (CoglGLES2Context *gles2_ctx)
+{
+ CoglGLES2FlipState new_flip_state;
+
+ if (gles2_ctx->current_fbo_handle == 0 &&
+ cogl_is_offscreen (gles2_ctx->write_buffer))
+ new_flip_state = COGL_GLES2_FLIP_STATE_FLIPPED;
+ else
+ new_flip_state = COGL_GLES2_FLIP_STATE_NORMAL;
+
+ /* If the flip state has changed then we need to reflush all of the
+ * dependent state */
+ if (new_flip_state != gles2_ctx->current_flip_state)
+ {
+ gles2_ctx->viewport_dirty = TRUE;
+ gles2_ctx->scissor_dirty = TRUE;
+ gles2_ctx->front_face_dirty = TRUE;
+ gles2_ctx->current_flip_state = new_flip_state;
+ }
+}
+
/* We wrap glBindFramebuffer so that when framebuffer 0 is bound
* we can instead bind the write_framebuffer passed to
* cogl_push_gles2_context().
@@ -116,6 +199,8 @@ gl_bind_framebuffer_wrapper (GLenum target, GLuint framebuffer)
}
gles2_ctx->context->glBindFramebuffer (target, framebuffer);
+
+ update_current_flip_state (gles2_ctx);
}
static int
@@ -192,6 +277,93 @@ gl_read_pixels_wrapper (GLint x,
gles2_ctx->context->glReadPixels (x, y, width, height, format, type, pixels);
restore_write_buffer (gles2_ctx, restore_mode);
+
+ /* If the read buffer is a CoglOffscreen then the data will be
+ * upside down compared to what GL expects so we need to flip it */
+ if (gles2_ctx->current_fbo_handle == 0 &&
+ cogl_is_offscreen (gles2_ctx->read_buffer))
+ {
+ int bpp, bytes_per_row, stride, y;
+ uint8_t *bytes = pixels;
+ uint8_t *temprow;
+
+ /* Try to determine the bytes per pixel for the given
+ * format/type combination. If there's a format which doesn't
+ * make sense then we'll just give up because GL will probably
+ * have just thrown an error */
+ switch (format)
+ {
+ case GL_RGB:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ bpp = 3;
+ break;
+
+ case GL_UNSIGNED_SHORT_5_6_5:
+ bpp = 2;
+ break;
+
+ default:
+ return;
+ }
+ break;
+
+ case GL_RGBA:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ bpp = 4;
+ break;
+
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ bpp = 2;
+ break;
+
+ default:
+ return;
+ }
+ break;
+
+ case GL_ALPHA:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ bpp = 1;
+ break;
+
+ default:
+ return;
+ }
+ break;
+
+ default:
+ return;
+ }
+
+ bytes_per_row = bpp * width;
+ stride = ((bytes_per_row + gles2_ctx->pack_alignment - 1) &
+ ~(gles2_ctx->pack_alignment - 1));
+ temprow = g_alloca (bytes_per_row);
+
+ /* vertically flip the buffer in-place */
+ for (y = 0; y < height / 2; y++)
+ {
+ if (y != height - y - 1) /* skip center row */
+ {
+ memcpy (temprow,
+ bytes + y * stride,
+ bytes_per_row);
+ memcpy (bytes + y * stride,
+ bytes + (height - y - 1) * stride,
+ bytes_per_row);
+ memcpy (bytes + (height - y - 1) * stride,
+ temprow,
+ bytes_per_row);
+ }
+ }
+ }
}
static void
@@ -292,10 +464,14 @@ gl_create_program_wrapper (void)
data->ref_count = 1;
data->deleted = FALSE;
data->context = gles2_ctx;
+ data->flip_vector_location = 0;
+ data->flip_vector_state = COGL_GLES2_FLIP_STATE_UNKNOWN;
g_hash_table_insert (gles2_ctx->program_map,
GINT_TO_POINTER (id),
data);
+
+ gles2_ctx->context->glAttachShader (id, gles2_ctx->wrapper_shader);
}
return id;
@@ -378,6 +554,521 @@ gl_detach_shader_wrapper (GLuint program,
}
static void
+gl_shader_source_wrapper (GLuint shader,
+ GLsizei count,
+ const char *const *string,
+ const GLint *length)
+{
+ CoglGLES2Context *gles2_ctx = current_gles2_context;
+ CoglGLES2ShaderData *shader_data;
+
+ if ((shader_data = g_hash_table_lookup (gles2_ctx->shader_map,
+ GINT_TO_POINTER (shader))) &&
+ shader_data->type == GL_VERTEX_SHADER)
+ {
+ char **string_copy = g_alloca (count * sizeof (char *));
+ int i;
+
+ /* Replace any occurences of the symbol 'main' with a different
+ * symbol so that we can provide our own wrapper main
+ * function */
+
+ for (i = 0; i < count; i++)
+ {
+ int string_length = length ? length[i] : strlen (string[i]);
+
+ string_copy[i] = g_memdup (string[i], string_length);
+
+ replace_token (string_copy[i],
+ "main",
+ MAIN_WRAPPER_REPLACEMENT_NAME,
+ string_length);
+ }
+
+ gles2_ctx->context->glShaderSource (shader,
+ count,
+ (const char *const *) string_copy,
+ length);
+
+ for (i = 0; i < count; i++)
+ g_free (string_copy[i]);
+ }
+ else
+ gles2_ctx->context->glShaderSource (shader, count, string, length);
+}
+
+static void
+gl_get_shader_source_wrapper (GLuint shader,
+ GLsizei buf_size,
+ GLsizei *length_out,
+ GLchar *source)
+{
+ CoglGLES2Context *gles2_ctx = current_gles2_context;
+ CoglGLES2ShaderData *shader_data;
+ GLsizei length;
+
+ gles2_ctx->context->glGetShaderSource (shader,
+ buf_size,
+ &length,
+ source);
+
+ if ((shader_data = g_hash_table_lookup (gles2_ctx->shader_map,
+ GINT_TO_POINTER (shader))) &&
+ shader_data->type == GL_VERTEX_SHADER)
+ {
+ GLsizei copy_length = MIN (length, buf_size - 1);
+ replace_token (source,
+ MAIN_WRAPPER_REPLACEMENT_NAME,
+ "main",
+ copy_length);
+ }
+
+ if (length_out)
+ *length_out = length;
+}
+
+static void
+gl_link_program_wrapper (GLuint program)
+{
+ CoglGLES2Context *gles2_ctx = current_gles2_context;
+ CoglGLES2ProgramData *program_data;
+
+ gles2_ctx->context->glLinkProgram (program);
+
+ program_data = g_hash_table_lookup (gles2_ctx->program_map,
+ GINT_TO_POINTER (program));
+
+ if (program_data)
+ {
+ GLint status;
+
+ gles2_ctx->context->glGetProgramiv (program, GL_LINK_STATUS, &status);
+
+ if (status)
+ program_data->flip_vector_location =
+ gles2_ctx->context->glGetUniformLocation (program,
+ MAIN_WRAPPER_FLIP_UNIFORM);
+ }
+}
+
+static void
+gl_get_program_iv_wrapper (GLuint program,
+ GLenum pname,
+ GLint *params)
+{
+ CoglGLES2Context *gles2_ctx = current_gles2_context;
+
+ gles2_ctx->context->glGetProgramiv (program, pname, params);
+
+ switch (pname)
+ {
+ case GL_ATTACHED_SHADERS:
+ /* Decrease the number of shaders to try and hide the shader
+ * wrapper we added */
+ if (*params > 1)
+ (*params)--;
+ break;
+ }
+}
+
+static void
+gl_get_attached_shaders_wrapper (GLuint program,
+ GLsizei max_count,
+ GLsizei *count_ret,
+ GLuint *obj)
+{
+ CoglGLES2Context *gles2_ctx = current_gles2_context;
+ GLuint *tmp_buf;
+ GLsizei count, count_out;
+ int i;
+
+ /* We need to remove the wrapper shader we added from this list */
+
+ /* Allocate a temporary buffer that is one larger than the buffer
+ * passed in in case the application allocated exactly the size
+ * returned by GL_ATTACHED_SHADERS. */
+ tmp_buf = g_alloca (sizeof (GLuint) * (max_count + 1));
+
+ gles2_ctx->context->glGetAttachedShaders (program,
+ max_count + 1,
+ &count,
+ tmp_buf);
+
+ for (i = 0, count_out = 0; i < count; i++)
+ if (tmp_buf[i] != gles2_ctx->wrapper_shader)
+ obj[count_out++] = tmp_buf[i];
+
+ if (count_ret)
+ *count_ret = count_out;
+}
+
+static void
+flush_viewport_state (CoglGLES2Context *gles2_ctx)
+{
+ if (gles2_ctx->viewport_dirty)
+ {
+ int y;
+
+ if (gles2_ctx->current_flip_state == COGL_GLES2_FLIP_STATE_FLIPPED)
+ {
+ /* We need to know the height of the current framebuffer in
+ * order to flip the viewport. Fortunately we don't need to
+ * track the height of the FBOs created within the GLES2
+ * context because we would never be flipping if they are
+ * bound so we can just assume Cogl's framebuffer is bound
+ * when we are flipping */
+ int fb_height = cogl_framebuffer_get_height (gles2_ctx->write_buffer);
+ y = fb_height - (gles2_ctx->viewport[1] + gles2_ctx->viewport[3]);
+ }
+ else
+ y = gles2_ctx->viewport[1];
+
+ gles2_ctx->context->glViewport (gles2_ctx->viewport[0],
+ y,
+ gles2_ctx->viewport[2],
+ gles2_ctx->viewport[3]);
+
+ gles2_ctx->viewport_dirty = FALSE;
+ }
+}
+
+static void
+flush_scissor_state (CoglGLES2Context *gles2_ctx)
+{
+ if (gles2_ctx->scissor_dirty)
+ {
+ int y;
+
+ if (gles2_ctx->current_flip_state == COGL_GLES2_FLIP_STATE_FLIPPED)
+ {
+ /* See comment above about the viewport flipping */
+ int fb_height = cogl_framebuffer_get_height (gles2_ctx->write_buffer);
+ y = fb_height - (gles2_ctx->scissor[1] + gles2_ctx->scissor[3]);
+ }
+ else
+ y = gles2_ctx->scissor[1];
+
+ gles2_ctx->context->glScissor (gles2_ctx->scissor[0],
+ y,
+ gles2_ctx->scissor[2],
+ gles2_ctx->scissor[3]);
+
+ gles2_ctx->scissor_dirty = FALSE;
+ }
+}
+
+static void
+flush_front_face_state (CoglGLES2Context *gles2_ctx)
+{
+ if (gles2_ctx->front_face_dirty)
+ {
+ GLenum front_face;
+
+ if (gles2_ctx->current_flip_state == COGL_GLES2_FLIP_STATE_FLIPPED)
+ {
+ if (gles2_ctx->front_face == GL_CW)
+ front_face = GL_CCW;
+ else
+ front_face = GL_CW;
+ }
+ else
+ front_face = gles2_ctx->front_face;
+
+ gles2_ctx->context->glFrontFace (front_face);
+
+ gles2_ctx->front_face_dirty = FALSE;
+ }
+}
+
+static void
+pre_draw_wrapper (CoglGLES2Context *gles2_ctx)
+{
+ /* If there's no current program then we'll just let GL report an
+ * error */
+ if (gles2_ctx->current_program == NULL)
+ return;
+
+ flush_viewport_state (gles2_ctx);
+ flush_scissor_state (gles2_ctx);
+ flush_front_face_state (gles2_ctx);
+
+ /* We want to flip rendering when the application is rendering to a
+ * Cogl offscreen buffer in order to maintain the flipped texture
+ * coordinate origin */
+ if (gles2_ctx->current_flip_state !=
+ gles2_ctx->current_program->flip_vector_state)
+ {
+ GLuint location =
+ gles2_ctx->current_program->flip_vector_location;
+ float value[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
+
+ if (gles2_ctx->current_flip_state == COGL_GLES2_FLIP_STATE_FLIPPED)
+ value[1] = -1.0f;
+
+ gles2_ctx->context->glUniform4fv (location, 1, value);
+
+ gles2_ctx->current_program->flip_vector_state =
+ gles2_ctx->current_flip_state;
+ }
+}
+
+static void
+gl_clear_wrapper (GLbitfield mask)
+{
+ CoglGLES2Context *gles2_ctx = current_gles2_context;
+
+ /* Clearing is affected by the scissor state so we need to ensure
+ * that's flushed */
+ flush_scissor_state (gles2_ctx);
+
+ gles2_ctx->context->glClear (mask);
+}
+
+static void
+gl_draw_elements_wrapper (GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices)
+{
+ CoglGLES2Context *gles2_ctx = current_gles2_context;
+
+ pre_draw_wrapper (gles2_ctx);
+
+ gles2_ctx->context->glDrawElements (mode, count, type, indices);
+}
+
+static void
+gl_draw_arrays_wrapper (GLenum mode,
+ GLint first,
+ GLsizei count)
+{
+ CoglGLES2Context *gles2_ctx = current_gles2_context;
+
+ pre_draw_wrapper (gles2_ctx);
+
+ gles2_ctx->context->glDrawArrays (mode, first, count);
+}
+
+static void
+gl_get_program_info_log_wrapper (GLuint program,
+ GLsizei buf_size,
+ GLsizei *length_out,
+ GLchar *info_log)
+{
+ CoglGLES2Context *gles2_ctx = current_gles2_context;
+ GLsizei length;
+
+ gles2_ctx->context->glGetProgramInfoLog (program,
+ buf_size,
+ &length,
+ info_log);
+
+ replace_token (info_log,
+ MAIN_WRAPPER_REPLACEMENT_NAME,
+ "main",
+ MIN (length, buf_size));
+
+ if (length_out)
+ *length_out = length;
+}
+
+static void
+gl_get_shader_info_log_wrapper (GLuint shader,
+ GLsizei buf_size,
+ GLsizei *length_out,
+ GLchar *info_log)
+{
+ CoglGLES2Context *gles2_ctx = current_gles2_context;
+ GLsizei length;
+
+ gles2_ctx->context->glGetShaderInfoLog (shader,
+ buf_size,
+ &length,
+ info_log);
+
+ replace_token (info_log,
+ MAIN_WRAPPER_REPLACEMENT_NAME,
+ "main",
+ MIN (length, buf_size));
+
+ if (length_out)
+ *length_out = length;
+}
+
+static void
+gl_front_face_wrapper (GLenum mode)
+{
+ CoglGLES2Context *gles2_ctx = current_gles2_context;
+
+ /* If the mode doesn't make any sense then we'll just let the
+ * context deal with it directly so that it will throw an error */
+ if (mode != GL_CW && mode != GL_CCW)
+ gles2_ctx->context->glFrontFace (mode);
+ else
+ {
+ gles2_ctx->front_face = mode;
+ gles2_ctx->front_face_dirty = TRUE;
+ }
+}
+
+static void
+gl_viewport_wrapper (GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ CoglGLES2Context *gles2_ctx = current_gles2_context;
+
+ /* If the viewport is invalid then we'll just let the context deal
+ * with it directly so that it will throw an error */
+ if (width < 0 || height < 0)
+ gles2_ctx->context->glViewport (x, y, width, height);
+ else
+ {
+ gles2_ctx->viewport[0] = x;
+ gles2_ctx->viewport[1] = y;
+ gles2_ctx->viewport[2] = width;
+ gles2_ctx->viewport[3] = height;
+ gles2_ctx->viewport_dirty = TRUE;
+ }
+}
+
+static void
+gl_scissor_wrapper (GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ CoglGLES2Context *gles2_ctx = current_gles2_context;
+
+ /* If the scissor is invalid then we'll just let the context deal
+ * with it directly so that it will throw an error */
+ if (width < 0 || height < 0)
+ gles2_ctx->context->glScissor (x, y, width, height);
+ else
+ {
+ gles2_ctx->scissor[0] = x;
+ gles2_ctx->scissor[1] = y;
+ gles2_ctx->scissor[2] = width;
+ gles2_ctx->scissor[3] = height;
+ gles2_ctx->scissor_dirty = TRUE;
+ }
+}
+
+static void
+gl_get_boolean_v_wrapper (GLenum pname,
+ GLboolean *params)
+{
+ CoglGLES2Context *gles2_ctx = current_gles2_context;
+
+ switch (pname)
+ {
+ case GL_VIEWPORT:
+ {
+ int i;
+
+ for (i = 0; i < 4; i++)
+ params[i] = !!gles2_ctx->viewport[i];
+ }
+ break;
+
+ case GL_SCISSOR_BOX:
+ {
+ int i;
+
+ for (i = 0; i < 4; i++)
+ params[i] = !!gles2_ctx->scissor[i];
+ }
+ break;
+
+ default:
+ gles2_ctx->context->glGetBooleanv (pname, params);
+ }
+}
+
+static void
+gl_get_integer_v_wrapper (GLenum pname,
+ GLint *params)
+{
+ CoglGLES2Context *gles2_ctx = current_gles2_context;
+
+ switch (pname)
+ {
+ case GL_VIEWPORT:
+ {
+ int i;
+
+ for (i = 0; i < 4; i++)
+ params[i] = gles2_ctx->viewport[i];
+ }
+ break;
+
+ case GL_SCISSOR_BOX:
+ {
+ int i;
+
+ for (i = 0; i < 4; i++)
+ params[i] = gles2_ctx->scissor[i];
+ }
+ break;
+
+ case GL_FRONT_FACE:
+ params[0] = gles2_ctx->front_face;
+ break;
+
+ default:
+ gles2_ctx->context->glGetIntegerv (pname, params);
+ }
+}
+
+static void
+gl_get_float_v_wrapper (GLenum pname,
+ GLfloat *params)
+{
+ CoglGLES2Context *gles2_ctx = current_gles2_context;
+
+ switch (pname)
+ {
+ case GL_VIEWPORT:
+ {
+ int i;
+
+ for (i = 0; i < 4; i++)
+ params[i] = gles2_ctx->viewport[i];
+ }
+ break;
+
+ case GL_SCISSOR_BOX:
+ {
+ int i;
+
+ for (i = 0; i < 4; i++)
+ params[i] = gles2_ctx->scissor[i];
+ }
+ break;
+
+ case GL_FRONT_FACE:
+ params[0] = gles2_ctx->front_face;
+ break;
+
+ default:
+ gles2_ctx->context->glGetFloatv (pname, params);
+ }
+}
+
+static void
+gl_pixel_store_i_wrapper (GLenum pname, GLint param)
+{
+ CoglGLES2Context *gles2_ctx = current_gles2_context;
+
+ gles2_ctx->context->glPixelStorei (pname, param);
+
+ if (pname == GL_PACK_ALIGNMENT &&
+ (param == 1 || param == 2 || param == 4 || param == 8))
+ gles2_ctx->pack_alignment = param;
+}
+
+static void
_cogl_gles2_offscreen_free (CoglGLES2Offscreen *gles2_offscreen)
{
COGL_LIST_REMOVE (gles2_offscreen, list_node);
@@ -415,6 +1106,8 @@ _cogl_gles2_context_free (CoglGLES2Context *gles2_context)
const CoglWinsysVtable *winsys;
GList *objects, *l;
+ ctx->glDeleteShader (gles2_context->wrapper_shader);
+
if (gles2_context->current_program)
program_data_unref (gles2_context->current_program);
@@ -480,6 +1173,33 @@ free_program_data (CoglGLES2ProgramData *data)
g_slice_free (CoglGLES2ProgramData, data);
}
+static GLuint
+create_wrapper_shader (CoglContext *ctx)
+{
+ const char *strings = main_wrapper_function;
+ GLint length = sizeof (main_wrapper_function) - 1;
+ GLint status;
+ GLuint shader;
+
+ shader = ctx->glCreateShader (GL_VERTEX_SHADER);
+ ctx->glShaderSource (shader, 1, &strings, &length);
+ ctx->glCompileShader (shader);
+ ctx->glGetShaderiv (shader, GL_COMPILE_STATUS, &status);
+
+ if (!status)
+ {
+ char buf[512];
+
+ ctx->glGetShaderInfoLog (shader,
+ sizeof (buf),
+ NULL, /* length */
+ buf);
+ g_warning ("Compiling wrapper shader failed:\n%s", buf);
+ }
+
+ return shader;
+}
+
CoglGLES2Context *
cogl_gles2_context_new (CoglContext *ctx, GError **error)
{
@@ -511,6 +1231,13 @@ cogl_gles2_context_new (CoglContext *ctx, GError **error)
return NULL;
}
+ gles2_ctx->current_flip_state = COGL_GLES2_FLIP_STATE_UNKNOWN;
+ gles2_ctx->viewport_dirty = TRUE;
+ gles2_ctx->scissor_dirty = TRUE;
+ gles2_ctx->front_face_dirty = TRUE;
+ gles2_ctx->front_face = GL_CCW;
+ gles2_ctx->pack_alignment = 4;
+
gles2_ctx->vtable = g_malloc0 (sizeof (CoglGLES2Vtable));
#define COGL_EXT_BEGIN(name, \
min_gl_major, min_gl_minor, \
@@ -528,6 +1255,8 @@ cogl_gles2_context_new (CoglContext *ctx, GError **error)
#undef COGL_EXT_FUNCTION
#undef COGL_EXT_END
+ gles2_ctx->wrapper_shader = create_wrapper_shader (ctx);
+
gles2_ctx->vtable->glBindFramebuffer = gl_bind_framebuffer_wrapper;
gles2_ctx->vtable->glReadPixels = gl_read_pixels_wrapper;
gles2_ctx->vtable->glCopyTexImage2D = gl_copy_tex_image_2d_wrapper;
@@ -539,6 +1268,27 @@ cogl_gles2_context_new (CoglContext *ctx, GError **error)
gles2_ctx->vtable->glUseProgram = gl_use_program_wrapper;
gles2_ctx->vtable->glAttachShader = gl_attach_shader_wrapper;
gles2_ctx->vtable->glDetachShader = gl_detach_shader_wrapper;
+ gles2_ctx->vtable->glShaderSource = gl_shader_source_wrapper;
+ gles2_ctx->vtable->glGetShaderSource = gl_get_shader_source_wrapper;
+ gles2_ctx->vtable->glLinkProgram = gl_link_program_wrapper;
+ gles2_ctx->vtable->glGetProgramiv = gl_get_program_iv_wrapper;
+ gles2_ctx->vtable->glGetAttachedShaders = gl_get_attached_shaders_wrapper;
+ gles2_ctx->vtable->glGetProgramInfoLog = gl_get_program_info_log_wrapper;
+ gles2_ctx->vtable->glGetShaderInfoLog = gl_get_shader_info_log_wrapper;
+ gles2_ctx->vtable->glClear = gl_clear_wrapper;
+ gles2_ctx->vtable->glDrawElements = gl_draw_elements_wrapper;
+ gles2_ctx->vtable->glDrawArrays = gl_draw_arrays_wrapper;
+ gles2_ctx->vtable->glFrontFace = gl_front_face_wrapper;
+ gles2_ctx->vtable->glViewport = gl_viewport_wrapper;
+ gles2_ctx->vtable->glScissor = gl_scissor_wrapper;
+ gles2_ctx->vtable->glGetBooleanv = gl_get_boolean_v_wrapper;
+ gles2_ctx->vtable->glGetIntegerv = gl_get_integer_v_wrapper;
+ gles2_ctx->vtable->glGetFloatv = gl_get_float_v_wrapper;
+ gles2_ctx->vtable->glPixelStorei = gl_pixel_store_i_wrapper;
+
+ /* FIXME: we need to do something with glCopyTexImage2D and
+ * glCopySubTexImage2D so that it will flip the data if it is read
+ * from a CoglOffscreen */
gles2_ctx->shader_map =
g_hash_table_new_full (g_direct_hash,
@@ -719,6 +1469,8 @@ cogl_push_gles2_context (CoglContext *ctx,
if (gles2_ctx->write_buffer)
cogl_object_unref (gles2_ctx->write_buffer);
gles2_ctx->write_buffer = cogl_object_ref (write_buffer);
+
+ update_current_flip_state (gles2_ctx);
}
if (!winsys->set_gles2_context (gles2_ctx, &internal_error))