diff --git a/.gitignore b/.gitignore index cd2235aed..9bbfd8c14 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,8 @@ clutter/stamp-* /clutter/cogl/cogl-defines-gl.h /clutter/cogl/cogl-defines-gles.h /clutter/cogl/cogl.h +/clutter/cogl/gles/cogl-fixed-vertex-shader.[ch] +/clutter/cogl/gles/cogl-fixed-fragment-shader.[ch] cogl-defines.h config.* configure diff --git a/ChangeLog b/ChangeLog index ae86a026e..487d08538 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,46 @@ +2008-05-27 Neil Roberts + + * clutter/eglx/clutter-stage-egl.h: + * clutter/eglx/clutter-egl-headers.h: + * clutter/eglx/clutter-backend-egl.h: + * clutter/eglx/Makefile.am: Include the GLES and EGL headers via + clutter-egl-headers.h so that the right version can be used + depending on whether the GLES 2 wrapper is being used. + + * configure.ac: Added an automake conditional for whether the GLES + 2 wrapper should be used. + + * clutter/eglx/clutter-stage-egl.c (clutter_stage_egl_realize): + Remove the call to glGetIntegerv to get the max texture size. It + was being called before the GL context was bound so it didn't work + anyway and it was causing trouble for the GLES 2 simulator. + + * clutter/cogl/gles/stringify.sh: Shell script to convert the + shaders into a C string. + + * clutter/cogl/gles/cogl-gles2-wrapper.h: + * clutter/cogl/gles/cogl-gles2-wrapper.c: Wrappers for most of the + missing GL functions in GLES 2. + + * clutter/cogl/gles/cogl-fixed-fragment-shader.glsl: + * clutter/cogl/gles/cogl-fixed-vertex-shader.glsl: New shaders for + GLES 2 + + * clutter/cogl/gles/cogl-defines.h.in: Use the @CLUTTER_GL_HEADER@ + macro instead of always using the GLES 1 header. + + * clutter/cogl/gles/cogl-context.h (CoglContext): Include a field + for the state of the GLES 2 wrapper. + + * clutter/cogl/gles/cogl-texture.c: + * clutter/cogl/gles/cogl-primitives.c: + * clutter/cogl/gles/cogl.c: Use wrapped versions of the GL + functions where neccessary. + + * clutter/cogl/gles/Makefile.am: Add sources for the GLES 2 + wrapper and an extra build step to put the GLSL files into a C + string whenever the files change. + 2008-05-26 Matthew Allum * clutter/x11/clutter-stage-x11.c: (clutter_stage_x11_request_coords): diff --git a/clutter/cogl/gles/Makefile.am b/clutter/cogl/gles/Makefile.am index 9f59e2ee3..1a35399c2 100644 --- a/clutter/cogl/gles/Makefile.am +++ b/clutter/cogl/gles/Makefile.am @@ -29,8 +29,29 @@ libclutter_cogl_la_SOURCES = \ cogl-primitives.c \ cogl-texture.c \ cogl-fbo.c \ - cogl-context.c + cogl-context.c \ + cogl-gles2-wrapper.h -EXTRA_DIST = cogl-defines.h.in +if USE_GLES2_WRAPPER +libclutter_cogl_la_SOURCES += \ + cogl-gles2-wrapper.c \ + cogl-fixed-vertex-shader.h \ + cogl-fixed-vertex-shader.c \ + cogl-fixed-fragment-shader.h \ + cogl-fixed-fragment-shader.c +endif + +EXTRA_DIST = cogl-defines.h.in \ + stringify.sh \ + cogl-fixed-vertex-shader.glsl \ + cogl-fixed-fragment-shader.glsl libclutter_cogl_la_LIBADD = $(top_builddir)/clutter/cogl/common/libclutter-cogl-common.la + +%.h : %.glsl + /bin/sh $(top_srcdir)/clutter/cogl/gles/stringify.sh -h $< + +%.c : %.glsl + /bin/sh $(top_srcdir)/clutter/cogl/gles/stringify.sh $< + +cogl-gles2-wrapper.lo : cogl-fixed-vertex-shader.h cogl-fixed-fragment-shader.h diff --git a/clutter/cogl/gles/cogl-context.c b/clutter/cogl/gles/cogl-context.c index a2e5c9ee6..60e2d80ce 100644 --- a/clutter/cogl/gles/cogl-context.c +++ b/clutter/cogl/gles/cogl-context.c @@ -29,13 +29,14 @@ #include "cogl.h" -#include #include #include "cogl-internal.h" #include "cogl-util.h" #include "cogl-context.h" +#include "cogl-gles2-wrapper.h" + static CoglContext *_context = NULL; gboolean @@ -67,9 +68,14 @@ cogl_create_context () _context->blend_src_factor = CGL_SRC_ALPHA; _context->blend_dst_factor = CGL_ONE_MINUS_SRC_ALPHA; + + /* Init the GLES2 wrapper */ +#ifdef HAVE_COGL_GLES2 + cogl_gles2_wrapper_init (&_context->gles2); +#endif /* Init OpenGL state */ - GE( glTexEnvx (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE) ); + GE( cogl_wrap_glTexEnvx (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE) ); GE( glColorMask (TRUE, TRUE, TRUE, FALSE) ); GE( glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ); cogl_enable (0); @@ -83,6 +89,10 @@ cogl_destroy_context () if (_context == NULL) return; +#ifdef HAVE_COGL_GLES2 + cogl_gles2_wrapper_deinit (&_context->gles2); +#endif + if (_context->texture_vertices) g_free (_context->texture_vertices); diff --git a/clutter/cogl/gles/cogl-context.h b/clutter/cogl/gles/cogl-context.h index f9654600c..87f158220 100644 --- a/clutter/cogl/gles/cogl-context.h +++ b/clutter/cogl/gles/cogl-context.h @@ -28,6 +28,8 @@ #include "cogl-primitives.h" +#include "cogl-gles2-wrapper.h" + typedef struct { GLfixed v[3]; @@ -64,6 +66,10 @@ typedef struct /* Framebuffer objects */ GArray *fbo_handles; CoglBufferTarget draw_buffer; + +#ifdef HAVE_COGL_GLES2 + CoglGles2Wrapper gles2; +#endif } CoglContext; diff --git a/clutter/cogl/gles/cogl-defines.h.in b/clutter/cogl/gles/cogl-defines.h.in index d97ab066c..574078a38 100644 --- a/clutter/cogl/gles/cogl-defines.h.in +++ b/clutter/cogl/gles/cogl-defines.h.in @@ -23,11 +23,11 @@ * Boston, MA 02111-1307, USA. */ -#include - #ifndef __COGL_DEFINES_H__ #define __COGL_DEFINES_H__ +#include <@CLUTTER_GL_HEADER@> + G_BEGIN_DECLS /* ClearBufferMask */ diff --git a/clutter/cogl/gles/cogl-fixed-fragment-shader.glsl b/clutter/cogl/gles/cogl-fixed-fragment-shader.glsl new file mode 100644 index 000000000..9dd22b8c4 --- /dev/null +++ b/clutter/cogl/gles/cogl-fixed-fragment-shader.glsl @@ -0,0 +1,29 @@ +/* Inputs from the vertex shader */ +varying vec4 frag_color; +varying vec2 tex_coord; + +/* Texturing options */ +uniform bool texture_2d_enabled; +uniform sampler2D texture_unit; +uniform bool alpha_only; + +void +main (void) +{ + if (texture_2d_enabled) + { + if (alpha_only) + { + /* If the texture only has an alpha channel (eg, with the + textures from the pango renderer) then the RGB components + will be black. We want to use the RGB from the current + color in that case */ + gl_FragColor = frag_color; + gl_FragColor.a *= texture2D (texture_unit, tex_coord).a; + } + else + gl_FragColor = frag_color * texture2D (texture_unit, tex_coord); + } + else + gl_FragColor = frag_color; +} diff --git a/clutter/cogl/gles/cogl-fixed-vertex-shader.glsl b/clutter/cogl/gles/cogl-fixed-vertex-shader.glsl new file mode 100644 index 000000000..ae6288c16 --- /dev/null +++ b/clutter/cogl/gles/cogl-fixed-vertex-shader.glsl @@ -0,0 +1,26 @@ +/* Per vertex attributes */ +attribute vec4 vertex_attrib; +attribute vec4 tex_coord_attrib; +attribute vec4 color_attrib; + +/* Transformation matrices */ +uniform mat4 mvp_matrix; /* combined modelview and projection matrix */ +uniform mat4 texture_matrix; + +/* Outputs to the fragment shader */ +varying vec4 frag_color; +varying vec2 tex_coord; + +void +main (void) +{ + /* Calculate the transformed position */ + gl_Position = mvp_matrix * vertex_attrib; + + /* Calculate the transformed texture coordinate */ + vec4 transformed_tex_coord = texture_matrix * tex_coord_attrib; + tex_coord = transformed_tex_coord.st / transformed_tex_coord.q; + + /* Pass the interpolated vertex color on to the fragment shader */ + frag_color = color_attrib; +} diff --git a/clutter/cogl/gles/cogl-gles2-wrapper.c b/clutter/cogl/gles/cogl-gles2-wrapper.c new file mode 100644 index 000000000..8151d961b --- /dev/null +++ b/clutter/cogl/gles/cogl-gles2-wrapper.c @@ -0,0 +1,632 @@ +/* + * Clutter COGL + * + * A basic GL/GLES Abstraction/Utility Layer + * + * Authored By Matthew Allum + * + * Copyright (C) 2008 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "cogl.h" +#include "cogl-gles2-wrapper.h" +#include "cogl-fixed-vertex-shader.h" +#include "cogl-fixed-fragment-shader.h" +#include "cogl-context.h" + +#define _COGL_GET_GLES2_WRAPPER(wvar, retval) \ + CoglGles2Wrapper *wvar; \ + { \ + CoglContext *__ctxvar = _cogl_context_get_default (); \ + if (__ctxvar == NULL) return retval; \ + wvar = &__ctxvar->gles2; \ + } + +#define COGL_GLES2_WRAPPER_VERTEX_ATTRIB 0 +#define COGL_GLES2_WRAPPER_TEX_COORD_ATTRIB 1 +#define COGL_GLES2_WRAPPER_COLOR_ATTRIB 2 + +static GLuint +cogl_gles2_wrapper_create_shader (GLenum type, const char *source) +{ + GLuint shader; + GLint source_len = strlen (source); + GLint status; + + shader = glCreateShader (type); + glShaderSource (shader, 1, &source, &source_len); + glCompileShader (shader); + + glGetShaderiv (shader, GL_COMPILE_STATUS, &status); + + if (!status) + { + char log[1024]; + GLint len; + + glGetShaderInfoLog (shader, sizeof (log) - 1, &len, log); + log[len] = '\0'; + + g_critical ("%s", log); + + glDeleteShader (shader); + + return 0; + } + + return shader; +} + +void +cogl_gles2_wrapper_init (CoglGles2Wrapper *wrapper) +{ + GLint status; + + memset (wrapper, 0, sizeof (CoglGles2Wrapper)); + + /* Create the shader program */ + wrapper->vertex_shader + = cogl_gles2_wrapper_create_shader (GL_VERTEX_SHADER, + cogl_fixed_vertex_shader); + + if (wrapper->vertex_shader == 0) + return; + + wrapper->fragment_shader + = cogl_gles2_wrapper_create_shader (GL_FRAGMENT_SHADER, + cogl_fixed_fragment_shader); + + if (wrapper->fragment_shader == 0) + { + glDeleteShader (wrapper->vertex_shader); + return; + } + + wrapper->program = glCreateProgram (); + glAttachShader (wrapper->program, wrapper->fragment_shader); + glAttachShader (wrapper->program, wrapper->vertex_shader); + glBindAttribLocation (wrapper->program, COGL_GLES2_WRAPPER_VERTEX_ATTRIB, + "vertex_attrib"); + glBindAttribLocation (wrapper->program, COGL_GLES2_WRAPPER_TEX_COORD_ATTRIB, + "tex_coord_attrib"); + glBindAttribLocation (wrapper->program, COGL_GLES2_WRAPPER_COLOR_ATTRIB, + "color_attrib"); + glLinkProgram (wrapper->program); + + glGetProgramiv (wrapper->program, GL_LINK_STATUS, &status); + + if (!status) + { + char log[1024]; + GLint len; + + glGetProgramInfoLog (wrapper->program, sizeof (log) - 1, &len, log); + log[len] = '\0'; + + g_critical ("%s", log); + + glDeleteProgram (wrapper->program); + glDeleteShader (wrapper->vertex_shader); + glDeleteShader (wrapper->fragment_shader); + + return; + } + + glUseProgram (wrapper->program); + + wrapper->mvp_matrix_uniform + = glGetUniformLocation (wrapper->program, "mvp_matrix"); + wrapper->texture_matrix_uniform + = glGetUniformLocation (wrapper->program, "texture_matrix"); + wrapper->texture_2d_enabled_uniform + = glGetUniformLocation (wrapper->program, "texture_2d_enabled"); + wrapper->bound_texture_uniform + = glGetUniformLocation (wrapper->program, "texture_unit"); + wrapper->alpha_only_uniform + = glGetUniformLocation (wrapper->program, "alpha_only"); + + /* Always use the first texture unit */ + glUniform1i (wrapper->bound_texture_uniform, 0); + + /* Initialize the stacks */ + cogl_wrap_glMatrixMode (GL_TEXTURE); + cogl_wrap_glLoadIdentity (); + cogl_wrap_glMatrixMode (GL_PROJECTION); + cogl_wrap_glLoadIdentity (); + cogl_wrap_glMatrixMode (GL_MODELVIEW); + cogl_wrap_glLoadIdentity (); + + wrapper->mvp_uptodate = GL_FALSE; +} + +void +cogl_gles2_wrapper_deinit (CoglGles2Wrapper *wrapper) +{ + if (wrapper->program) + { + glDeleteProgram (wrapper->program); + wrapper->program = 0; + } + if (wrapper->vertex_shader) + { + glDeleteShader (wrapper->vertex_shader); + wrapper->vertex_shader = 0; + } + if (wrapper->fragment_shader) + { + glDeleteShader (wrapper->fragment_shader); + wrapper->fragment_shader = 0; + } +} + +static void +cogl_gles2_wrapper_update_matrix (CoglGles2Wrapper *wrapper) +{ + const float *matrix; + + switch (wrapper->matrix_mode) + { + default: + case GL_MODELVIEW: + case GL_PROJECTION: + /* Queue a recalculation of the combined modelview and + projection matrix at the next draw */ + wrapper->mvp_uptodate = GL_FALSE; + break; + + case GL_TEXTURE: + matrix = wrapper->texture_stack + wrapper->texture_stack_pos * 16; + glUniformMatrix4fv (wrapper->texture_matrix_uniform, 1, GL_FALSE, matrix); + break; + } + +} + +void +cogl_wrap_glClearColorx (GLclampx r, GLclampx g, GLclampx b, GLclampx a) +{ + glClearColor (CLUTTER_FIXED_TO_FLOAT (r), + CLUTTER_FIXED_TO_FLOAT (g), + CLUTTER_FIXED_TO_FLOAT (b), + CLUTTER_FIXED_TO_FLOAT (a)); +} + +void +cogl_wrap_glPushMatrix () +{ + const float *src; + float *dst; + + _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL); + + /* Get a pointer to the old and new matrix position and increment + the stack pointer */ + switch (w->matrix_mode) + { + default: + case GL_MODELVIEW: + src = w->modelview_stack + w->modelview_stack_pos * 16; + w->modelview_stack_pos = (w->modelview_stack_pos + 1) + & (COGL_GLES2_MODELVIEW_STACK_SIZE - 1); + dst = w->modelview_stack + w->modelview_stack_pos * 16; + break; + + case GL_PROJECTION: + src = w->projection_stack + w->projection_stack_pos * 16; + w->projection_stack_pos = (w->projection_stack_pos + 1) + & (COGL_GLES2_PROJECTION_STACK_SIZE - 1); + dst = w->projection_stack + w->projection_stack_pos * 16; + break; + + case GL_TEXTURE: + src = w->texture_stack + w->texture_stack_pos * 16; + w->texture_stack_pos = (w->texture_stack_pos + 1) + & (COGL_GLES2_TEXTURE_STACK_SIZE - 1); + dst = w->texture_stack + w->texture_stack_pos * 16; + break; + } + + /* Copy the old matrix to the new position */ + memcpy (dst, src, sizeof (float) * 16); +} + +void +cogl_wrap_glPopMatrix () +{ + _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL); + + /* Decrement the stack pointer */ + switch (w->matrix_mode) + { + default: + case GL_MODELVIEW: + w->modelview_stack_pos = (w->modelview_stack_pos - 1) + & (COGL_GLES2_MODELVIEW_STACK_SIZE - 1); + break; + + case GL_PROJECTION: + w->projection_stack_pos = (w->projection_stack_pos - 1) + & (COGL_GLES2_PROJECTION_STACK_SIZE - 1); + break; + + case GL_TEXTURE: + w->texture_stack_pos = (w->texture_stack_pos - 1) + & (COGL_GLES2_TEXTURE_STACK_SIZE - 1); + break; + } + + /* Update the matrix in the program object */ + cogl_gles2_wrapper_update_matrix (w); +} + +void +cogl_wrap_glMatrixMode (GLenum mode) +{ + _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL); + + w->matrix_mode = mode; +} + +static float * +cogl_gles2_get_matrix_stack_top (CoglGles2Wrapper *wrapper) +{ + switch (wrapper->matrix_mode) + { + default: + case GL_MODELVIEW: + return wrapper->modelview_stack + wrapper->modelview_stack_pos * 16; + + case GL_PROJECTION: + return wrapper->projection_stack + wrapper->projection_stack_pos * 16; + + case GL_TEXTURE: + return wrapper->texture_stack + wrapper->texture_stack_pos * 16; + } +} + +void +cogl_wrap_glLoadIdentity () +{ + float *matrix; + + _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL); + + matrix = cogl_gles2_get_matrix_stack_top (w); + memset (matrix, 0, sizeof (float) * 16); + matrix[0] = 1.0f; + matrix[5] = 1.0f; + matrix[10] = 1.0f; + matrix[15] = 1.0f; + + cogl_gles2_wrapper_update_matrix (w); +} + +static void +cogl_gles2_wrapper_mult_matrix (float *dst, const float *a, const float *b) +{ + int i, j, k; + + for (i = 0; i < 4; i++) + for (j = 0; j < 4; j++) + { + float sum = 0.0f; + for (k = 0; k < 4; k++) + sum += a[k * 4 + j] * b[i * 4 + k]; + dst[i * 4 + j] = sum; + } +} + +static void +cogl_wrap_glMultMatrix (const float *m) +{ + float new_matrix[16]; + float *old_matrix; + + _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL); + + old_matrix = cogl_gles2_get_matrix_stack_top (w); + + cogl_gles2_wrapper_mult_matrix (new_matrix, old_matrix, m); + + memcpy (old_matrix, new_matrix, sizeof (float) * 16); + + cogl_gles2_wrapper_update_matrix (w); +} + +void +cogl_wrap_glMultMatrixx (const GLfixed *m) +{ + float new_matrix[16]; + int i; + + for (i = 0; i < 16; i++) + new_matrix[i] = CLUTTER_FIXED_TO_FLOAT (m[i]); + + cogl_wrap_glMultMatrix (new_matrix); +} + +void +cogl_wrap_glScalex (GLfixed x, GLfixed y, GLfixed z) +{ + float matrix[16]; + + memset (matrix, 0, sizeof (matrix)); + matrix[0] = CLUTTER_FIXED_TO_FLOAT (x); + matrix[5] = CLUTTER_FIXED_TO_FLOAT (y); + matrix[10] = CLUTTER_FIXED_TO_FLOAT (z); + matrix[15] = 1.0f; + + cogl_wrap_glMultMatrix (matrix); +} + +void +cogl_wrap_glTranslatex (GLfixed x, GLfixed y, GLfixed z) +{ + float matrix[16]; + + memset (matrix, 0, sizeof (matrix)); + matrix[0] = 1.0f; + matrix[5] = 1.0f; + matrix[10] = 1.0f; + matrix[12] = CLUTTER_FIXED_TO_FLOAT (x); + matrix[13] = CLUTTER_FIXED_TO_FLOAT (y); + matrix[14] = CLUTTER_FIXED_TO_FLOAT (z); + matrix[15] = 1.0f; + + cogl_wrap_glMultMatrix (matrix); +} + +void +cogl_wrap_glRotatex (GLfixed angle, GLfixed x, GLfixed y, GLfixed z) +{ + float matrix[16]; + float xf = CLUTTER_FIXED_TO_FLOAT (x); + float yf = CLUTTER_FIXED_TO_FLOAT (y); + float zf = CLUTTER_FIXED_TO_FLOAT (z); + float anglef = CLUTTER_FIXED_TO_FLOAT (angle) * G_PI / 180.0f; + float c = cosf (anglef); + float s = sinf (anglef); + + matrix[0] = xf * xf * (1.0f - c) + c; + matrix[1] = yf * xf * (1.0f - c) + zf * s; + matrix[2] = xf * zf * (1.0f - c) - yf * s; + matrix[3] = 0.0f; + + matrix[4] = xf * yf * (1.0f - c) - zf * s; + matrix[5] = yf * yf * (1.0f - c) + c; + matrix[6] = yf * zf * (1.0f - c) + xf * s; + matrix[7] = 0.0f; + + matrix[8] = xf * zf * (1.0f - c) + yf * s; + matrix[9] = yf * zf * (1.0f - c) - xf * s; + matrix[10] = zf * zf * (1.0f - c) + c; + matrix[11] = 0.0f; + + matrix[12] = 0.0f; + matrix[13] = 0.0f; + matrix[14] = 0.0f; + matrix[15] = 1.0f; + + cogl_wrap_glMultMatrix (matrix); +} + +void +cogl_wrap_glOrthox (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, + GLfixed near, GLfixed far) +{ + float matrix[16]; + float xrange = CLUTTER_FIXED_TO_FLOAT (right - left); + float yrange = CLUTTER_FIXED_TO_FLOAT (top - bottom); + float zrange = CLUTTER_FIXED_TO_FLOAT (far - near); + + memset (matrix, 0, sizeof (matrix)); + matrix[0] = 2.0f / xrange; + matrix[5] = 2.0f / yrange; + matrix[10] = 2.0f / zrange; + matrix[12] = CLUTTER_FIXED_TO_FLOAT (right + left) / xrange; + matrix[13] = CLUTTER_FIXED_TO_FLOAT (top + bottom) / yrange; + matrix[14] = CLUTTER_FIXED_TO_FLOAT (far + near) / zrange; + matrix[15] = 1.0f; + + cogl_wrap_glMultMatrix (matrix); +} + +void +cogl_wrap_glVertexPointer (GLint size, GLenum type, GLsizei stride, + const GLvoid *pointer) +{ + glVertexAttribPointer (COGL_GLES2_WRAPPER_VERTEX_ATTRIB, size, type, + GL_FALSE, stride, pointer); +} + +void +cogl_wrap_glTexCoordPointer (GLint size, GLenum type, GLsizei stride, + const GLvoid *pointer) +{ + glVertexAttribPointer (COGL_GLES2_WRAPPER_TEX_COORD_ATTRIB, size, type, + GL_FALSE, stride, pointer); +} + +void +cogl_wrap_glColorPointer (GLint size, GLenum type, GLsizei stride, + const GLvoid *pointer) +{ + glVertexAttribPointer (COGL_GLES2_WRAPPER_COLOR_ATTRIB, size, type, + GL_FALSE, stride, pointer); +} + +void +cogl_wrap_glDrawArrays (GLenum mode, GLint first, GLsizei count) +{ + _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL); + + /* Make sure the modelview+projection matrix is up to date */ + if (!w->mvp_uptodate) + { + float mvp_matrix[16]; + + cogl_gles2_wrapper_mult_matrix (mvp_matrix, + w->projection_stack + + w->projection_stack_pos * 16, + w->modelview_stack + + w->modelview_stack_pos * 16); + + glUniformMatrix4fv (w->mvp_matrix_uniform, 1, GL_FALSE, mvp_matrix); + + w->mvp_uptodate = GL_TRUE; + } + + glDrawArrays (mode, first, count); +} + +void +cogl_gles2_wrapper_bind_texture (GLenum target, GLuint texture, + GLenum internal_format) +{ + _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL); + + glBindTexture (target, texture); + + /* We need to keep track of whether the texture is alpha-only + because the emulation of GL_MODULATE needs to work differently in + that case */ + glUniform1i (w->alpha_only_uniform, + internal_format == GL_ALPHA ? GL_TRUE : GL_FALSE); +} + +void +cogl_wrap_glTexEnvx (GLenum target, GLenum pname, GLfixed param) +{ + /* This function is only used to set the texture mode once to + GL_MODULATE. The shader is hard-coded to modulate the texture so + nothing needs to be done here. */ +} + +void +cogl_wrap_glEnable (GLenum cap) +{ + _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL); + + switch (cap) + { + case GL_TEXTURE_2D: + glUniform1i (w->texture_2d_enabled_uniform, GL_TRUE); + break; + + default: + glEnable (cap); + } +} + +void +cogl_wrap_glDisable (GLenum cap) +{ + _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL); + + switch (cap) + { + case GL_TEXTURE_2D: + glUniform1i (w->texture_2d_enabled_uniform, GL_FALSE); + break; + + default: + glDisable (cap); + } +} + +void +cogl_wrap_glEnableClientState (GLenum array) +{ + switch (array) + { + case GL_VERTEX_ARRAY: + glEnableVertexAttribArray (COGL_GLES2_WRAPPER_VERTEX_ATTRIB); + break; + case GL_TEXTURE_COORD_ARRAY: + glEnableVertexAttribArray (COGL_GLES2_WRAPPER_TEX_COORD_ATTRIB); + break; + case GL_COLOR_ARRAY: + glEnableVertexAttribArray (COGL_GLES2_WRAPPER_COLOR_ATTRIB); + break; + } +} + +void +cogl_wrap_glDisableClientState (GLenum array) +{ + switch (array) + { + case GL_VERTEX_ARRAY: + glDisableVertexAttribArray (COGL_GLES2_WRAPPER_VERTEX_ATTRIB); + break; + case GL_TEXTURE_COORD_ARRAY: + glDisableVertexAttribArray (COGL_GLES2_WRAPPER_TEX_COORD_ATTRIB); + break; + case GL_COLOR_ARRAY: + glDisableVertexAttribArray (COGL_GLES2_WRAPPER_COLOR_ATTRIB); + break; + } +} + +void +cogl_wrap_glAlphaFunc (GLenum func, GLclampf ref) +{ + /* FIXME */ +} + +void +cogl_wrap_glColor4x (GLclampx r, GLclampx g, GLclampx b, GLclampx a) +{ + glVertexAttrib4f (COGL_GLES2_WRAPPER_COLOR_ATTRIB, + CLUTTER_FIXED_TO_FLOAT (r), + CLUTTER_FIXED_TO_FLOAT (g), + CLUTTER_FIXED_TO_FLOAT (b), + CLUTTER_FIXED_TO_FLOAT (a)); +} + +void +cogl_wrap_glClipPlanex (GLenum plane, GLfixed *equation) +{ + /* FIXME */ +} + +void +cogl_wrap_glGetFixedv (GLenum pname, GLfixed *params) +{ + /* FIXME */ +} + +void +cogl_wrap_glFogx (GLenum pname, GLfixed param) +{ + /* FIXME */ +} + +void +cogl_wrap_glFogxv (GLenum pname, const GLfixed *params) +{ + /* FIXME */ +} diff --git a/clutter/cogl/gles/cogl-gles2-wrapper.h b/clutter/cogl/gles/cogl-gles2-wrapper.h new file mode 100644 index 000000000..2e3f750f3 --- /dev/null +++ b/clutter/cogl/gles/cogl-gles2-wrapper.h @@ -0,0 +1,194 @@ +/* + * Clutter COGL + * + * A basic GL/GLES Abstraction/Utility Layer + * + * Authored By Matthew Allum + * + * Copyright (C) 2008 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __COGL_GLES2_WRAPPER_H__ +#define __COGL_GLES2_WRAPPER_H__ + +G_BEGIN_DECLS + +#ifdef HAVE_COGL_GLES2 + +typedef struct _CoglGles2Wrapper CoglGles2Wrapper; + +/* Must be a power of two */ +#define COGL_GLES2_MODELVIEW_STACK_SIZE 32 +#define COGL_GLES2_PROJECTION_STACK_SIZE 2 +#define COGL_GLES2_TEXTURE_STACK_SIZE 2 + +struct _CoglGles2Wrapper +{ + GLuint program; + GLuint vertex_shader; + GLuint fragment_shader; + + GLint mvp_matrix_uniform; + GLint texture_matrix_uniform; + GLint texture_2d_enabled_uniform; + GLint bound_texture_uniform; + GLint alpha_only_uniform; + + GLuint matrix_mode; + GLfloat modelview_stack[COGL_GLES2_MODELVIEW_STACK_SIZE * 16]; + GLuint modelview_stack_pos; + GLfloat projection_stack[COGL_GLES2_PROJECTION_STACK_SIZE * 16]; + GLuint projection_stack_pos; + GLfloat texture_stack[COGL_GLES2_TEXTURE_STACK_SIZE * 16]; + GLuint texture_stack_pos; + + /* The combined modelview and projection matrix is only updated at + the last minute in glDrawArrays to avoid recalculating it for + every change to the modelview matrix */ + GLboolean mvp_uptodate; +}; + +/* These defines are missing from GL ES 2 but we can still use them + with the wrapper funcions */ + +#ifndef GL_MODELVIEW + +#define GL_MODELVIEW 0x1700 +#define GL_PROJECTION 0x1701 + +#define GL_VERTEX_ARRAY 0x8074 +#define GL_TEXTURE_COORD_ARRAY 0x8078 +#define GL_COLOR_ARRAY 0x8076 + +#define GL_LIGHTING 0x0B50 +#define GL_ALPHA_TEST 0x0BC0 + +#define GL_FOG 0x0B60 +#define GL_FOG_COLOR 0x0B66 +#define GL_FOG_MODE 0x0B65 +#define GL_FOG_HINT 0x0C54 +#define GL_FOG_DENSITY 0x0B62 +#define GL_FOG_START 0x0B63 +#define GL_FOG_END 0x0B64 + +#define GL_CLIP_PLANE0 0x3000 +#define GL_CLIP_PLANE1 0x3001 +#define GL_CLIP_PLANE2 0x3002 +#define GL_CLIP_PLANE3 0x3003 +#define GL_MAX_CLIP_PLANES 0x0D32 + +#define GL_MODELVIEW_MATRIX 0x0BA6 +#define GL_PROJECTION_MATRIX 0x0BA7 + +#define GL_GENERATE_MIPMAP 0x8191 + +#define GL_TEXTURE_ENV 0x2300 +#define GL_TEXTURE_ENV_MODE 0x2200 +#define GL_MODULATE 0x2100 + +#endif /* GL_MODELVIEW */ + +void cogl_gles2_wrapper_init (CoglGles2Wrapper *wrapper); +void cogl_gles2_wrapper_deinit (CoglGles2Wrapper *wrapper); + +void cogl_wrap_glClearColorx (GLclampx r, GLclampx g, GLclampx b, GLclampx a); + +void cogl_wrap_glPushMatrix (); +void cogl_wrap_glPopMatrix (); +void cogl_wrap_glMatrixMode (GLenum mode); +void cogl_wrap_glLoadIdentity (); +void cogl_wrap_glMultMatrixx (const GLfixed *m); +void cogl_wrap_glScalex (GLfixed x, GLfixed y, GLfixed z); +void cogl_wrap_glTranslatex (GLfixed x, GLfixed y, GLfixed z); +void cogl_wrap_glRotatex (GLfixed angle, GLfixed x, GLfixed y, GLfixed z); +void cogl_wrap_glOrthox (GLfixed left, GLfixed right, + GLfixed bottom, GLfixed top, + GLfixed near, GLfixed far); + +void cogl_wrap_glEnable (GLenum cap); +void cogl_wrap_glDisable (GLenum cap); + +void cogl_wrap_glTexCoordPointer (GLint size, GLenum type, GLsizei stride, + const GLvoid *pointer); +void cogl_wrap_glVertexPointer (GLint size, GLenum type, GLsizei stride, + const GLvoid *pointer); +void cogl_wrap_glColorPointer (GLint size, GLenum type, GLsizei stride, + const GLvoid *pointer); + +void cogl_wrap_glTexEnvx (GLenum target, GLenum pname, GLfixed param); + +void cogl_wrap_glEnableClientState (GLenum array); +void cogl_wrap_glDisableClientState (GLenum array); + +void cogl_wrap_glAlphaFunc (GLenum func, GLclampf ref); + +void cogl_wrap_glColor4x (GLclampx r, GLclampx g, GLclampx b, GLclampx a); + +void cogl_wrap_glClipPlanex (GLenum plane, GLfixed *equation); + +void cogl_wrap_glGetFixedv (GLenum pname, GLfixed *params); + +void cogl_wrap_glFogx (GLenum pname, GLfixed param); +void cogl_wrap_glFogxv (GLenum pname, const GLfixed *params); + +void cogl_wrap_glDrawArrays (GLenum mode, GLint first, GLsizei count); + +void cogl_gles2_wrapper_bind_texture (GLenum target, GLuint texture, + GLenum internal_format); + +#else /* HAVE_COGL_GLES2 */ + +/* If we're not using GL ES 2 then just use the GL functions + directly */ + +#define cogl_wrap_glClearColorx glClearColorx +#define cogl_wrap_glDrawArrays glDrawArrays +#define cogl_wrap_glPushMatrix glPushMatrix +#define cogl_wrap_glPopMatrix glPopMatrix +#define cogl_wrap_glMatrixMode glMatrixMode +#define cogl_wrap_glLoadIdentity glLoadIdentity +#define cogl_wrap_glMultMatrixx glMultMatrixx +#define cogl_wrap_glScalex glScalex +#define cogl_wrap_glTranslatex glTranslatex +#define cogl_wrap_glRotatex glRotatex +#define cogl_wrap_glOrthox glOrthox +#define cogl_wrap_glEnable glEnable +#define cogl_wrap_glDisable glDisable +#define cogl_wrap_glTexCoordPointer glTexCoordPointer +#define cogl_wrap_glVertexPointer glVertexPointer +#define cogl_wrap_glColorPointer glColorPointer +#define cogl_wrap_glTexEnvx glTexEnvx +#define cogl_wrap_glEnableClientState glEnableClientState +#define cogl_wrap_glDisableClientState glDisableClientState +#define cogl_wrap_glAlphaFunc glAlphaFunc +#define cogl_wrap_glColor4x glColor4x +#define cogl_wrap_glClipPlanex glClipPlanex +#define cogl_wrap_glGetFixedv glGetFixedv +#define cogl_wrap_glFogx glFogx +#define cogl_wrap_glFogxv glFogxv + +/* The extra third parameter of the bind texture wrapper isn't needed + so we can just directly call glBindTexture */ +#define cogl_gles2_wrapper_bind_texture(target, texture, internal_format) \ + glBindTexture ((target), (texture)) + +#endif /* HAVE_COGL_GLES2 */ + +G_END_DECLS + +#endif /* __COGL_GLES2_WRAPPER_H__ */ diff --git a/clutter/cogl/gles/cogl-primitives.c b/clutter/cogl/gles/cogl-primitives.c index 08b79c2ee..bc7414670 100644 --- a/clutter/cogl/gles/cogl-primitives.c +++ b/clutter/cogl/gles/cogl-primitives.c @@ -57,8 +57,8 @@ _cogl_rectangle (gint x, cogl_enable (COGL_ENABLE_VERTEX_ARRAY | (ctx->color_alpha < 255 ? COGL_ENABLE_BLEND : 0)); - GE ( glVertexPointer (2, GL_SHORT, 0, rect_verts ) ); - GE ( glDrawArrays (GL_TRIANGLE_STRIP, 0, 4) ); + GE ( cogl_wrap_glVertexPointer (2, GL_SHORT, 0, rect_verts ) ); + GE ( cogl_wrap_glDrawArrays (GL_TRIANGLE_STRIP, 0, 4) ); } @@ -81,8 +81,8 @@ _cogl_rectanglex (ClutterFixed x, | (ctx->color_alpha < 255 ? COGL_ENABLE_BLEND : 0)); - GE( glVertexPointer (2, GL_FIXED, 0, rect_verts) ); - GE( glDrawArrays (GL_TRIANGLE_STRIP, 0, 4) ); + GE( cogl_wrap_glVertexPointer (2, GL_FIXED, 0, rect_verts) ); + GE( cogl_wrap_glDrawArrays (GL_TRIANGLE_STRIP, 0, 4) ); } @@ -147,8 +147,8 @@ _cogl_path_stroke_nodes () | (ctx->color_alpha < 255 ? COGL_ENABLE_BLEND : 0)); - GE( glVertexPointer (2, GL_FIXED, 0, ctx->path_nodes) ); - GE( glDrawArrays (GL_LINE_STRIP, 0, ctx->path_nodes_size) ); + GE( cogl_wrap_glVertexPointer (2, GL_FIXED, 0, ctx->path_nodes) ); + GE( cogl_wrap_glDrawArrays (GL_LINE_STRIP, 0, ctx->path_nodes_size) ); } static gint compare_ints (gconstpointer a, @@ -176,7 +176,7 @@ _cogl_path_fill_nodes () GE( glClear (GL_STENCIL_BUFFER_BIT) ); - GE( glEnable (GL_STENCIL_TEST) ); + GE( cogl_wrap_glEnable (GL_STENCIL_TEST) ); GE( glStencilFunc (GL_ALWAYS, 0x0, 0x0) ); GE( glStencilOp (GL_INVERT, GL_INVERT, GL_INVERT) ); GE( glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE) ); @@ -184,8 +184,8 @@ _cogl_path_fill_nodes () cogl_enable (COGL_ENABLE_VERTEX_ARRAY | (ctx->color_alpha < 255 ? COGL_ENABLE_BLEND : 0)); - GE( glVertexPointer (2, GL_FIXED, 0, ctx->path_nodes) ); - GE( glDrawArrays (GL_TRIANGLE_FAN, 0, ctx->path_nodes_size) ); + GE( cogl_wrap_glVertexPointer (2, GL_FIXED, 0, ctx->path_nodes) ); + GE( cogl_wrap_glDrawArrays (GL_TRIANGLE_FAN, 0, ctx->path_nodes_size) ); GE( glStencilFunc (GL_EQUAL, 0x1, 0x1) ); GE( glStencilOp (GL_ZERO, GL_ZERO, GL_ZERO) ); @@ -194,7 +194,7 @@ _cogl_path_fill_nodes () cogl_rectangle (bounds_x, bounds_y, bounds_w, bounds_h); - GE( glDisable (GL_STENCIL_TEST) ); + GE( cogl_wrap_glDisable (GL_STENCIL_TEST) ); #else { /* This is our edge list it stores intersections between our curve and @@ -347,8 +347,8 @@ fill_close: /* render triangles */ cogl_enable (COGL_ENABLE_VERTEX_ARRAY | (ctx->color_alpha < 255 ? COGL_ENABLE_BLEND : 0)); - GE ( glVertexPointer (2, GL_FIXED, 0, coords ) ); - GE ( glDrawArrays (GL_TRIANGLES, 0, spans * 2 * 3)); + GE ( cogl_wrap_glVertexPointer (2, GL_FIXED, 0, coords ) ); + GE ( cogl_wrap_glDrawArrays (GL_TRIANGLES, 0, spans * 2 * 3)); g_free (coords); } } diff --git a/clutter/cogl/gles/cogl-texture.c b/clutter/cogl/gles/cogl-texture.c index 133806e22..7b4ad2158 100644 --- a/clutter/cogl/gles/cogl-texture.c +++ b/clutter/cogl/gles/cogl-texture.c @@ -35,6 +35,8 @@ #include "cogl-context.h" #include "cogl-handle.h" +#include "cogl-gles2-wrapper.h" + #include #include /* @@ -220,7 +222,8 @@ _cogl_texture_upload_to_gl (CoglTexture *tex) slice_bmp.height); /* Upload new image data */ - GE( glBindTexture (tex->gl_target, gl_handle) ); + GE( cogl_gles2_wrapper_bind_texture (tex->gl_target, gl_handle, + tex->gl_intformat) ); GE( glPixelStorei (GL_UNPACK_ALIGNMENT, 1) ); @@ -385,18 +388,18 @@ _cogl_texture_download_from_gl (CoglTexture *tex, (0,0 in bottom-left corner to draw the texture upside-down so we match the way glReadPixels works) */ - GE( glMatrixMode (GL_PROJECTION) ); - GE( glPushMatrix () ); - GE( glLoadIdentity () ); + GE( cogl_wrap_glMatrixMode (GL_PROJECTION) ); + GE( cogl_wrap_glPushMatrix () ); + GE( cogl_wrap_glLoadIdentity () ); - GE( glOrthox (0, CLUTTER_INT_TO_FIXED (viewport[2]), - 0, CLUTTER_INT_TO_FIXED (viewport[3]), - CLUTTER_INT_TO_FIXED (0), - CLUTTER_INT_TO_FIXED (100)) ); + GE( cogl_wrap_glOrthox (0, CLUTTER_INT_TO_FIXED (viewport[2]), + 0, CLUTTER_INT_TO_FIXED (viewport[3]), + CLUTTER_INT_TO_FIXED (0), + CLUTTER_INT_TO_FIXED (100)) ); - GE( glMatrixMode (GL_MODELVIEW) ); - GE( glPushMatrix () ); - GE( glLoadIdentity () ); + GE( cogl_wrap_glMatrixMode (GL_MODELVIEW) ); + GE( cogl_wrap_glPushMatrix () ); + GE( cogl_wrap_glLoadIdentity () ); /* Draw to all channels */ cogl_draw_buffer (COGL_WINDOW_BUFFER | COGL_MASK_BUFFER, 0); @@ -465,10 +468,10 @@ _cogl_texture_download_from_gl (CoglTexture *tex, } /* Restore old state */ - glMatrixMode (GL_PROJECTION); - glPopMatrix (); - glMatrixMode (GL_MODELVIEW); - glPopMatrix (); + cogl_wrap_glMatrixMode (GL_PROJECTION); + cogl_wrap_glPopMatrix (); + cogl_wrap_glMatrixMode (GL_MODELVIEW); + cogl_wrap_glPopMatrix (); cogl_draw_buffer (COGL_WINDOW_BUFFER, 0); cogl_blend_func (old_src_factor, old_dst_factor); @@ -590,7 +593,8 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex, /* Upload new image data */ GE( glPixelStorei (GL_UNPACK_ALIGNMENT, 1) ); - GE( glBindTexture (tex->gl_target, gl_handle) ); + GE( cogl_gles2_wrapper_bind_texture (tex->gl_target, gl_handle, + tex->gl_intformat) ); GE( glTexSubImage2D (tex->gl_target, 0, local_x, local_y, @@ -808,7 +812,10 @@ _cogl_texture_slices_create (CoglTexture *tex) y_span->size - y_span->waste); #endif /* Setup texture parameters */ - GE( glBindTexture (tex->gl_target, gl_handles[y * n_x_slices + x]) ); + GE( cogl_gles2_wrapper_bind_texture (tex->gl_target, + gl_handles[y * n_x_slices + x], + tex->gl_intformat) ); + GE( glTexParameteri (tex->gl_target, GL_TEXTURE_MAG_FILTER, tex->mag_filter) ); GE( glTexParameteri (tex->gl_target, GL_TEXTURE_MIN_FILTER, tex->min_filter) ); GE( glTexParameteri (tex->gl_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) ); @@ -1546,7 +1553,7 @@ cogl_texture_set_filters (CoglHandle handle, for (i=0; islice_gl_handles->len; ++i) { gl_handle = g_array_index (tex->slice_gl_handles, GLuint, i); - GE( glBindTexture (tex->gl_target, gl_handle) ); + GE( glBindTexture (tex->gl_target, gl_handle) ); GE( glTexParameteri (tex->gl_target, GL_TEXTURE_MAG_FILTER, tex->mag_filter) ); GE( glTexParameteri (tex->gl_target, GL_TEXTURE_MIN_FILTER, tex->min_filter) ); } @@ -1772,8 +1779,8 @@ _cogl_texture_quad_sw (CoglTexture *tex, cogl_enable (enable_flags); - GE( glTexCoordPointer (2, GL_FIXED, 0, tex_coords) ); - GE( glVertexPointer (2, GL_FIXED, 0, quad_coords) ); + GE( cogl_wrap_glTexCoordPointer (2, GL_FIXED, 0, tex_coords) ); + GE( cogl_wrap_glVertexPointer (2, GL_FIXED, 0, quad_coords) ); /* Scale ratio from texture to quad widths */ tw = CLUTTER_INT_TO_FIXED (tex->bitmap.width); @@ -1865,7 +1872,8 @@ _cogl_texture_quad_sw (CoglTexture *tex, iter_y.index * iter_x.array->len + iter_x.index); - GE( glBindTexture (tex->gl_target, gl_handle) ); + GE( cogl_gles2_wrapper_bind_texture (tex->gl_target, gl_handle, + tex->gl_intformat) ); /* Draw textured quad */ tex_coords[0] = slice_tx1; tex_coords[1] = slice_ty1; @@ -1878,7 +1886,7 @@ _cogl_texture_quad_sw (CoglTexture *tex, quad_coords[4] = slice_qx1; quad_coords[5] = slice_qy2; quad_coords[6] = slice_qx2; quad_coords[7] = slice_qy2; - GE (glDrawArrays (GL_TRIANGLE_STRIP, 0, 4) ); + GE (cogl_wrap_glDrawArrays (GL_TRIANGLE_STRIP, 0, 4) ); } } } @@ -1919,12 +1927,13 @@ _cogl_texture_quad_hw (CoglTexture *tex, cogl_enable (enable_flags); - GE( glTexCoordPointer (2, GL_FIXED, 0, tex_coords) ); - GE( glVertexPointer (2, GL_FIXED, 0, quad_coords) ); + GE( cogl_wrap_glTexCoordPointer (2, GL_FIXED, 0, tex_coords) ); + GE( cogl_wrap_glVertexPointer (2, GL_FIXED, 0, quad_coords) ); /* Pick and bind opengl texture object */ gl_handle = g_array_index (tex->slice_gl_handles, GLuint, 0); - GE( glBindTexture (tex->gl_target, gl_handle) ); + GE( cogl_gles2_wrapper_bind_texture (tex->gl_target, gl_handle, + tex->gl_intformat) ); /* Don't include the waste in the texture coordinates */ x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan, 0); @@ -1945,7 +1954,7 @@ _cogl_texture_quad_hw (CoglTexture *tex, quad_coords[4] = x1; quad_coords[5] = y2; quad_coords[6] = x2; quad_coords[7] = y2; - GE (glDrawArrays (GL_TRIANGLE_STRIP, 0, 4) ); + GE (cogl_wrap_glDrawArrays (GL_TRIANGLE_STRIP, 0, 4) ); } void @@ -2106,14 +2115,14 @@ cogl_texture_polygon (CoglHandle handle, if (use_color) { enable_flags |= COGL_ENABLE_COLOR_ARRAY; - GE( glColorPointer (4, GL_FIXED, sizeof (CoglTextureGLVertex), - ctx->texture_vertices[0].c) ); + GE( cogl_wrap_glColorPointer (4, GL_FIXED, sizeof (CoglTextureGLVertex), + ctx->texture_vertices[0].c) ); } - GE( glVertexPointer (3, GL_FIXED, sizeof (CoglTextureGLVertex), - ctx->texture_vertices[0].v) ); - GE( glTexCoordPointer (2, GL_FIXED, sizeof (CoglTextureGLVertex), - ctx->texture_vertices[0].t) ); + GE( cogl_wrap_glVertexPointer (3, GL_FIXED, sizeof (CoglTextureGLVertex), + ctx->texture_vertices[0].v) ); + GE( cogl_wrap_glTexCoordPointer (2, GL_FIXED, sizeof (CoglTextureGLVertex), + ctx->texture_vertices[0].t) ); cogl_enable (enable_flags); @@ -2136,9 +2145,10 @@ cogl_texture_polygon (CoglHandle handle, p->c[3] = (vertices[i].color.alpha << 16) / 0xff; } - GE( glBindTexture (tex->gl_target, gl_handle) ); + GE( cogl_gles2_wrapper_bind_texture (tex->gl_target, gl_handle, + tex->gl_intformat) ); - GE( glDrawArrays (GL_TRIANGLE_FAN, 0, n_vertices) ); + GE( cogl_wrap_glDrawArrays (GL_TRIANGLE_FAN, 0, n_vertices) ); /* Set the last color so that the cache of the alpha value will work properly */ diff --git a/clutter/cogl/gles/cogl.c b/clutter/cogl/gles/cogl.c index b8fc8e1f8..303d49f9d 100644 --- a/clutter/cogl/gles/cogl.c +++ b/clutter/cogl/gles/cogl.c @@ -29,13 +29,13 @@ #include "cogl.h" -#include #include #include "cogl-internal.h" #include "cogl-util.h" #include "cogl-context.h" +#include "cogl-gles2-wrapper.h" /* GL error to string conversion */ #if COGL_DEBUG @@ -91,47 +91,47 @@ cogl_paint_init (const ClutterColor *color) fprintf(stderr, "\n ============== Paint Start ================ \n"); #endif - glClearColorx ((color->red << 16) / 0xff, - (color->green << 16) / 0xff, - (color->blue << 16) / 0xff, - 0xff); + cogl_wrap_glClearColorx ((color->red << 16) / 0xff, + (color->green << 16) / 0xff, + (color->blue << 16) / 0xff, + 0xff); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - glDisable (GL_LIGHTING); - glDisable (GL_FOG); + cogl_wrap_glDisable (GL_LIGHTING); + cogl_wrap_glDisable (GL_FOG); } /* FIXME: inline most of these */ void cogl_push_matrix (void) { - GE( glPushMatrix() ); + GE( cogl_wrap_glPushMatrix() ); } void cogl_pop_matrix (void) { - GE( glPopMatrix() ); + GE( cogl_wrap_glPopMatrix() ); } void cogl_scale (ClutterFixed x, ClutterFixed y) { - GE( glScalex (x, y, CFX_ONE) ); + GE( cogl_wrap_glScalex (x, y, CFX_ONE) ); } void cogl_translatex (ClutterFixed x, ClutterFixed y, ClutterFixed z) { - GE( glTranslatex (x, y, z) ); + GE( cogl_wrap_glTranslatex (x, y, z) ); } void cogl_translate (gint x, gint y, gint z) { - GE( glTranslatex (CLUTTER_INT_TO_FIXED(x), - CLUTTER_INT_TO_FIXED(y), - CLUTTER_INT_TO_FIXED(z)) ); + GE( cogl_wrap_glTranslatex (CLUTTER_INT_TO_FIXED(x), + CLUTTER_INT_TO_FIXED(y), + CLUTTER_INT_TO_FIXED(z)) ); } void @@ -140,13 +140,13 @@ cogl_rotatex (ClutterFixed angle, ClutterFixed y, ClutterFixed z) { - GE( glRotatex (angle,x,y,z) ); + GE( cogl_wrap_glRotatex (angle,x,y,z) ); } void cogl_rotate (gint angle, gint x, gint y, gint z) { - GE( glRotatex (CLUTTER_INT_TO_FIXED(angle), + GE( cogl_wrap_glRotatex (CLUTTER_INT_TO_FIXED(angle), CLUTTER_INT_TO_FIXED(x), CLUTTER_INT_TO_FIXED(y), CLUTTER_INT_TO_FIXED(z)) ); @@ -165,14 +165,14 @@ cogl_toggle_flag (CoglContext *ctx, { if (!(ctx->enable_flags & flag)) { - GE( glEnable (gl_flag) ); + GE( cogl_wrap_glEnable (gl_flag) ); ctx->enable_flags |= flag; return TRUE; } } else if (ctx->enable_flags & flag) { - GE( glDisable (gl_flag) ); + GE( cogl_wrap_glDisable (gl_flag) ); ctx->enable_flags &= ~flag; } @@ -192,14 +192,14 @@ cogl_toggle_client_flag (CoglContext *ctx, { if (!(ctx->enable_flags & flag)) { - GE( glEnableClientState (gl_flag) ); + GE( cogl_wrap_glEnableClientState (gl_flag) ); ctx->enable_flags |= flag; return TRUE; } } else if (ctx->enable_flags & flag) { - GE( glDisableClientState (gl_flag) ); + GE( cogl_wrap_glDisableClientState (gl_flag) ); ctx->enable_flags &= ~flag; } @@ -265,15 +265,15 @@ cogl_enable_depth_test (gboolean setting) { if (setting) { - glEnable (GL_DEPTH_TEST); - glEnable (GL_ALPHA_TEST); + cogl_wrap_glEnable (GL_DEPTH_TEST); + cogl_wrap_glEnable (GL_ALPHA_TEST); glDepthFunc (GL_LEQUAL); - glAlphaFunc (GL_GREATER, 0.1); + cogl_wrap_glAlphaFunc (GL_GREATER, 0.1); } else { - glDisable (GL_DEPTH_TEST); - glDisable (GL_ALPHA_TEST); + cogl_wrap_glDisable (GL_DEPTH_TEST); + cogl_wrap_glDisable (GL_ALPHA_TEST); } } @@ -302,10 +302,10 @@ cogl_color (const ClutterColor *color) #else /* conversion can cause issues with picking on some gles implementations */ - GE( glColor4x ((color->red << 16) / 0xff, - (color->green << 16) / 0xff, - (color->blue << 16) / 0xff, - (color->alpha << 16) / 0xff)); + GE( cogl_wrap_glColor4x ((color->red << 16) / 0xff, + (color->green << 16) / 0xff, + (color->blue << 16) / 0xff, + (color->alpha << 16) / 0xff)); #endif /* Store alpha for proper blending enables */ @@ -325,18 +325,18 @@ cogl_clip_set (ClutterFixed x_offset, GLfixed eqn_top[4] = { 0, CFX_ONE, 0, -y_offset }; GLfixed eqn_bottom[4] = { 0, -CFX_ONE, 0, y_offset + height }; - GE( glClipPlanex (GL_CLIP_PLANE0, eqn_left) ); - GE( glClipPlanex (GL_CLIP_PLANE1, eqn_right) ); - GE( glClipPlanex (GL_CLIP_PLANE2, eqn_top) ); - GE( glClipPlanex (GL_CLIP_PLANE3, eqn_bottom) ); - GE( glEnable (GL_CLIP_PLANE0) ); - GE( glEnable (GL_CLIP_PLANE1) ); - GE( glEnable (GL_CLIP_PLANE2) ); - GE( glEnable (GL_CLIP_PLANE3) ); + GE( cogl_wrap_glClipPlanex (GL_CLIP_PLANE0, eqn_left) ); + GE( cogl_wrap_glClipPlanex (GL_CLIP_PLANE1, eqn_right) ); + GE( cogl_wrap_glClipPlanex (GL_CLIP_PLANE2, eqn_top) ); + GE( cogl_wrap_glClipPlanex (GL_CLIP_PLANE3, eqn_bottom) ); + GE( cogl_wrap_glEnable (GL_CLIP_PLANE0) ); + GE( cogl_wrap_glEnable (GL_CLIP_PLANE1) ); + GE( cogl_wrap_glEnable (GL_CLIP_PLANE2) ); + GE( cogl_wrap_glEnable (GL_CLIP_PLANE3) ); } else if (cogl_features_available (COGL_FEATURE_STENCIL_BUFFER)) { - GE( glEnable (GL_STENCIL_TEST) ); + GE( cogl_wrap_glEnable (GL_STENCIL_TEST) ); GE( glClearStencil (0) ); GE( glClear (GL_STENCIL_BUFFER_BIT) ); @@ -344,7 +344,7 @@ cogl_clip_set (ClutterFixed x_offset, GE( glStencilFunc (GL_NEVER, 0x1, 0x1) ); GE( glStencilOp (GL_INCR, GL_INCR, GL_INCR) ); - GE( glColor4x (CFX_ONE, CFX_ONE, CFX_ONE, CFX_ONE ) ); + GE( cogl_wrap_glColor4x (CFX_ONE, CFX_ONE, CFX_ONE, CFX_ONE ) ); cogl_rectanglex (x_offset, y_offset, width, height); @@ -358,14 +358,14 @@ cogl_clip_unset (void) { if (cogl_features_available (COGL_FEATURE_FOUR_CLIP_PLANES)) { - GE( glDisable (GL_CLIP_PLANE3) ); - GE( glDisable (GL_CLIP_PLANE2) ); - GE( glDisable (GL_CLIP_PLANE1) ); - GE( glDisable (GL_CLIP_PLANE0) ); + GE( cogl_wrap_glDisable (GL_CLIP_PLANE3) ); + GE( cogl_wrap_glDisable (GL_CLIP_PLANE2) ); + GE( cogl_wrap_glDisable (GL_CLIP_PLANE1) ); + GE( cogl_wrap_glDisable (GL_CLIP_PLANE0) ); } else if (cogl_features_available (COGL_FEATURE_STENCIL_BUFFER)) { - GE( glDisable (GL_STENCIL_TEST) ); + GE( cogl_wrap_glDisable (GL_STENCIL_TEST) ); } } @@ -373,7 +373,7 @@ void cogl_alpha_func (COGLenum func, ClutterFixed ref) { - GE( glAlphaFunc (func, CLUTTER_FIXED_TO_FLOAT(ref)) ); + GE( cogl_wrap_glAlphaFunc (func, CLUTTER_FIXED_TO_FLOAT(ref)) ); } /* @@ -418,7 +418,7 @@ cogl_perspective (ClutterFixed fovy, M(2,3) = d; M(3,2) = 1 + ~CFX_ONE; - GE( glMultMatrixx (m) ); + GE( cogl_wrap_glMultMatrixx (m) ); #undef M } @@ -435,17 +435,17 @@ cogl_setup_viewport (guint w, ClutterFixed z_camera; GE( glViewport (0, 0, width, height) ); - GE( glMatrixMode (GL_PROJECTION) ); - GE( glLoadIdentity () ); + GE( cogl_wrap_glMatrixMode (GL_PROJECTION) ); + GE( cogl_wrap_glLoadIdentity () ); /* For Ortho projection. - * glOrthox (0, width << 16, 0, height << 16, -1 << 16, 1 << 16); + * cogl_wrap_glOrthox (0, width << 16, 0, height << 16, -1 << 16, 1 << 16); */ cogl_perspective (fovy, aspect, z_near, z_far); - GE( glMatrixMode (GL_MODELVIEW) ); - GE( glLoadIdentity () ); + GE( cogl_wrap_glMatrixMode (GL_MODELVIEW) ); + GE( cogl_wrap_glLoadIdentity () ); /* * camera distance from screen, 0.5 * tan (FOV) @@ -464,13 +464,13 @@ cogl_setup_viewport (guint w, } - GE( glTranslatex (-1 << 15, -1 << 15, -z_camera)); + GE( cogl_wrap_glTranslatex (-1 << 15, -1 << 15, -z_camera)); - GE( glScalex ( CFX_ONE / width, + GE( cogl_wrap_glScalex ( CFX_ONE / width, -CFX_ONE / height, CFX_ONE / width)); - GE( glTranslatex (0, -CFX_ONE * height, 0) ); + GE( cogl_wrap_glTranslatex (0, -CFX_ONE * height, 0) ); } static void @@ -519,19 +519,19 @@ cogl_features_available (CoglFeatureFlags features) void cogl_get_modelview_matrix (ClutterFixed m[16]) { - glGetFixedv(GL_MODELVIEW_MATRIX, &m[0]); + cogl_wrap_glGetFixedv(GL_MODELVIEW_MATRIX, &m[0]); } void cogl_get_projection_matrix (ClutterFixed m[16]) { - glGetFixedv(GL_PROJECTION_MATRIX, &m[0]); + cogl_wrap_glGetFixedv(GL_PROJECTION_MATRIX, &m[0]); } void cogl_get_viewport (ClutterFixed v[4]) { - glGetFixedv(GL_VIEWPORT, &v[0]); + cogl_wrap_glGetFixedv(GL_VIEWPORT, &v[0]); } void @@ -560,16 +560,16 @@ cogl_fog_set (const ClutterColor *fog_color, fogColor[2] = (fog_color->blue << 16) / 0xff; fogColor[3] = (fog_color->alpha << 16) / 0xff; - glEnable (GL_FOG); + cogl_wrap_glEnable (GL_FOG); - glFogxv (GL_FOG_COLOR, fogColor); + cogl_wrap_glFogxv (GL_FOG_COLOR, fogColor); - glFogx (GL_FOG_MODE, GL_LINEAR); + cogl_wrap_glFogx (GL_FOG_MODE, GL_LINEAR); glHint (GL_FOG_HINT, GL_NICEST); - glFogx (GL_FOG_DENSITY, (GLfixed) density); - glFogx (GL_FOG_START, (GLfixed) z_near); - glFogx (GL_FOG_END, (GLfixed) z_far); + cogl_wrap_glFogx (GL_FOG_DENSITY, (GLfixed) density); + cogl_wrap_glFogx (GL_FOG_START, (GLfixed) z_near); + cogl_wrap_glFogx (GL_FOG_END, (GLfixed) z_far); } /* Shaders, no support on regular OpenGL 1.1 */ diff --git a/clutter/cogl/gles/stringify.sh b/clutter/cogl/gles/stringify.sh new file mode 100644 index 000000000..c8b3cf8b4 --- /dev/null +++ b/clutter/cogl/gles/stringify.sh @@ -0,0 +1,65 @@ +#! /bin/sh + +output_copyright () +{ + cat < "$1"; +/* + * Clutter COGL + * + * A basic GL/GLES Abstraction/Utility Layer + * + * Authored By Matthew Allum + * + * Copyright (C) 2008 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +EOF +} + +# If two arguments are given then generate the header file instead +if test "$#" = 2; then + bfname="${2%.glsl}"; + bname=`basename "$bfname"`; + varname=`echo -n "${bname}" | tr -c a-z _`; + guardname=`echo -n "${varname}" | tr a-z A-Z`; + guardname="__${guardname}_H"; + headername="${bfname}.h"; + + output_copyright "${headername}"; + echo >> "${headername}"; + echo "#ifndef ${guardname}" >> "${headername}"; + echo "#define ${guardname}" >> "${headername}"; + echo >> "${headername}"; + echo "extern const char ${varname}[];" >> "${headername}"; + echo >> "${headername}"; + echo "#endif /* ${guardname} */" >> "${headername}"; + +else + + bfname="${1%.glsl}"; + bname=`basename "${bfname}"`; + cname="${bfname}.c"; + varname=`echo -n "${bname}" | tr -c a-z _`; + + output_copyright "${cname}"; + echo >> "${cname}"; + echo "const char ${varname}[] =" >> "${cname}"; + sed -e 's/"/\\"/' -e 's/^/ \"/' -e 's/$/\\n"/' \ + < "$1" >> "${cname}"; + echo " ;" >> "${cname}"; + +fi; diff --git a/clutter/eglx/Makefile.am b/clutter/eglx/Makefile.am index 82d91f3e3..8cd96738a 100644 --- a/clutter/eglx/Makefile.am +++ b/clutter/eglx/Makefile.am @@ -20,4 +20,5 @@ libclutter_eglx_la_SOURCES = \ clutter-backend-egl.c \ clutter-stage-egl.h \ clutter-stage-egl.c \ - clutter-eglx.h + clutter-eglx.h \ + clutter-egl-headers.h diff --git a/clutter/eglx/clutter-backend-egl.h b/clutter/eglx/clutter-backend-egl.h index 43894dd39..c5c3ae2a1 100644 --- a/clutter/eglx/clutter-backend-egl.h +++ b/clutter/eglx/clutter-backend-egl.h @@ -28,8 +28,7 @@ #include #include -#include -#include +#include "clutter-egl-headers.h" #include "../x11/clutter-backend-x11.h" #include "clutter-eglx.h" diff --git a/clutter/eglx/clutter-egl-headers.h b/clutter/eglx/clutter-egl-headers.h new file mode 100644 index 000000000..e7c33768a --- /dev/null +++ b/clutter/eglx/clutter-egl-headers.h @@ -0,0 +1,38 @@ +/* Clutter. + * An OpenGL based 'interactive canvas' library. + * Authored By Matthew Allum + * Copyright (C) 2006-2007 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __CLUTTER_EGL_HEADERS_H__ +#define __CLUTTER_EGL_HEADERS_H__ + +#ifdef HAVE_COGL_GLES2 +#include +#include +#else /* HAVE_COGL_GLES2 */ +#include +#include +#endif /* HAVE_COGL_GLES2 */ + +#ifdef HAVE_COGL_GLES2 +#define NativeDisplayType EGLNativeDisplayType +#define NativeWindowType EGLNativeWindowType +#endif /* HAVE_COGL_GLES2 */ + +#endif /* __CLUTTER_EGL_HEADERS_H__ */ diff --git a/clutter/eglx/clutter-eglx.h b/clutter/eglx/clutter-eglx.h index 0272ff3bb..74d4f971f 100644 --- a/clutter/eglx/clutter-eglx.h +++ b/clutter/eglx/clutter-eglx.h @@ -32,8 +32,7 @@ #include #include -#include -#include +#include "clutter-egl-headers.h" #include diff --git a/clutter/eglx/clutter-stage-egl.c b/clutter/eglx/clutter-stage-egl.c index 900fce898..e17551ce6 100644 --- a/clutter/eglx/clutter-stage-egl.c +++ b/clutter/eglx/clutter-stage-egl.c @@ -91,7 +91,6 @@ clutter_stage_egl_realize (ClutterActor *actor) { int c; int num_configs; - int max_tex_units; EGLConfig *all_configs; EGLint cfg_attribs[] = { @@ -138,10 +137,6 @@ clutter_stage_egl_realize (ClutterActor *actor) red, green, blue, alpha, stencil); } - max_tex_units = 0; - glGetIntegerv (GL_MAX_TEXTURE_SIZE, &max_tex_units); - CLUTTER_NOTE (BACKEND, "Texture units: %d\n", max_tex_units); - g_free (all_configs); if (status != EGL_TRUE) diff --git a/clutter/eglx/clutter-stage-egl.h b/clutter/eglx/clutter-stage-egl.h index 8e9896257..8d8e8da1a 100644 --- a/clutter/eglx/clutter-stage-egl.h +++ b/clutter/eglx/clutter-stage-egl.h @@ -8,8 +8,7 @@ #include #include -#include -#include +#include "clutter-egl-headers.h" #include "../x11/clutter-stage-x11.h" diff --git a/configure.ac b/configure.ac index 06f3198ef..51d6b2dfe 100644 --- a/configure.ac +++ b/configure.ac @@ -180,6 +180,7 @@ fi AM_CONDITIONAL(X11_TESTS, test "x$x11_tests" != "xno") clutter_gl_header="" +use_gles2_wrapper="no" if test "x$clutterbackend" = "xeglnative" || test "x$clutterbackend" = "xeglx" || test "x$clutterbackend" = "xfruity" then @@ -230,6 +231,8 @@ case $glesversion in [AC_MSG_ERROR([Unable to locate required GLES headers])]) GLES_LIBS="-lGLESv2 -lEGL" + + use_gles2_wrapper=yes ;; fruity) CLUTTER_COGL="gles" @@ -242,6 +245,8 @@ case $glesversion in esac fi +AM_CONDITIONAL(USE_GLES2_WRAPPER, test "x$use_gles2_wrapper" != "xno") + case $clutterbackend in sdl)