From 165531074bf76ad4a6b8f5d043b702dfa251cd97 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Mon, 2 Jun 2008 10:58:57 +0000 Subject: [PATCH] * clutter/cogl/gles/cogl-gles2-wrapper.h: The uniform numbers are now stored in a separate struct so they can be stored for application program objects as well. * clutter/cogl/gles/cogl.c: Moved stub shader functions into separate files. (_cogl_features_init): Report support for the shaders feature on GLES 2 * clutter/cogl/gles/cogl-shader.h: * clutter/cogl/gles/cogl-shader.c: * clutter/cogl/gles/cogl-program.h: * clutter/cogl/gles/cogl-program.c: Separate files to handle shaders on programs on GLES. If version 1.1 is being used then the stub functions which all fail are still used. * clutter/cogl/gles/cogl-gles2-wrapper.c (cogl_gles2_wrapper_init, cogl_gles2_wrapper_bind_attributes), (cogl_gles2_wrapper_get_uniforms): Move the uniforms and attribute bindings into a separate function so they can be used to bind on application shaders as well. (cogl_gles2_wrapper_update_matrix): Now takes a parameter and is no longer static so that it can be used to update all of the matrices when a new shader is bound. * clutter/cogl/gles/cogl-defines.h.in: Use GL_COMPILE_STATUS for CGL_OBJECT_COMPILE_STATUS if the latter isn't available (for example on GLES 2). * clutter/cogl/gles/cogl-context.h (CoglContext): Added handle arrays for programs and shaders. * clutter/cogl/gles/cogl-context.c (cogl_create_context) (cogl_destroy_context): Initialize and destroy program and shader handle array. * clutter/cogl/gles/Makefile.am (libclutter_cogl_la_SOURCES): Add cogl-{shader,program}.{c,h} --- gles/Makefile.am | 6 +- gles/cogl-context.c | 11 ++ gles/cogl-context.h | 4 + gles/cogl-defines.h.in | 6 +- gles/cogl-gles2-wrapper.c | 144 +++++++++++---------- gles/cogl-gles2-wrapper.h | 27 +++- gles/cogl-program.c | 257 ++++++++++++++++++++++++++++++++++++++ gles/cogl-program.h | 50 ++++++++ gles/cogl-shader.c | 184 +++++++++++++++++++++++++++ gles/cogl-shader.h | 40 ++++++ gles/cogl.c | 107 +--------------- 11 files changed, 661 insertions(+), 175 deletions(-) create mode 100644 gles/cogl-program.c create mode 100644 gles/cogl-program.h create mode 100644 gles/cogl-shader.c create mode 100644 gles/cogl-shader.h diff --git a/gles/Makefile.am b/gles/Makefile.am index dd26cecad..950888703 100644 --- a/gles/Makefile.am +++ b/gles/Makefile.am @@ -30,7 +30,11 @@ libclutter_cogl_la_SOURCES = \ cogl-texture.c \ cogl-fbo.c \ cogl-context.c \ - cogl-gles2-wrapper.h + cogl-gles2-wrapper.h \ + cogl-program.h \ + cogl-program.c \ + cogl-shader.h \ + cogl-shader.c if USE_GLES2_WRAPPER libclutter_cogl_la_SOURCES += \ diff --git a/gles/cogl-context.c b/gles/cogl-context.c index 60e2d80ce..5e061ecb0 100644 --- a/gles/cogl-context.c +++ b/gles/cogl-context.c @@ -64,6 +64,8 @@ cogl_create_context () _context->texture_vertices = NULL; _context->fbo_handles = NULL; + _context->program_handles = NULL; + _context->shader_handles = NULL; _context->draw_buffer = COGL_WINDOW_BUFFER; _context->blend_src_factor = CGL_SRC_ALPHA; @@ -96,6 +98,15 @@ cogl_destroy_context () if (_context->texture_vertices) g_free (_context->texture_vertices); + if (_context->texture_handles) + g_array_free (_context->texture_handles, TRUE); + if (_context->fbo_handles) + g_array_free (_context->fbo_handles, TRUE); + if (_context->shader_handles) + g_array_free (_context->shader_handles, TRUE); + if (_context->program_handles) + g_array_free (_context->program_handles, TRUE); + g_free (_context); } diff --git a/gles/cogl-context.h b/gles/cogl-context.h index 87f158220..4103620d5 100644 --- a/gles/cogl-context.h +++ b/gles/cogl-context.h @@ -67,6 +67,10 @@ typedef struct GArray *fbo_handles; CoglBufferTarget draw_buffer; + /* Shaders */ + GArray *program_handles; + GArray *shader_handles; + #ifdef HAVE_COGL_GLES2 CoglGles2Wrapper gles2; #endif diff --git a/gles/cogl-defines.h.in b/gles/cogl-defines.h.in index 574078a38..b3cd355d6 100644 --- a/gles/cogl-defines.h.in +++ b/gles/cogl-defines.h.in @@ -460,8 +460,10 @@ typedef GLuint COGLuint; #define CGL_VERTEX_SHADER 0 #endif -#ifdef GL_OBJECT_COMPILE_STATUS -#define CGL_OBJECT_COMPILE_STATUS GL_OBJECT_COMPILE_STATUS +#if defined(GL_OBJECT_COMPILE_STATUS) +#define CGL_OBJECT_COMPILE_STATUS GL_OBJECT_COMPILE_STATUS +#elif defined(GL_COMPILE_STATUS) +#define CGL_OBJECT_COMPILE_STATUS GL_COMPILE_STATUS #else #define CGL_OBJECT_COMPILE_STATUS 0 #endif diff --git a/gles/cogl-gles2-wrapper.c b/gles/cogl-gles2-wrapper.c index 47d11ffc5..3a2f2dca1 100644 --- a/gles/cogl-gles2-wrapper.c +++ b/gles/cogl-gles2-wrapper.c @@ -109,12 +109,7 @@ cogl_gles2_wrapper_init (CoglGles2Wrapper *wrapper) 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"); + cogl_gles2_wrapper_bind_attributes (wrapper->program); glLinkProgram (wrapper->program); glGetProgramiv (wrapper->program, GL_LINK_STATUS, &status); @@ -138,41 +133,11 @@ cogl_gles2_wrapper_init (CoglGles2Wrapper *wrapper) glUseProgram (wrapper->program); - wrapper->mvp_matrix_uniform - = glGetUniformLocation (wrapper->program, "mvp_matrix"); - wrapper->modelview_matrix_uniform - = glGetUniformLocation (wrapper->program, "modelview_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"); - - wrapper->fog_enabled_uniform - = glGetUniformLocation (wrapper->program, "fog_enabled"); - wrapper->fog_mode_uniform - = glGetUniformLocation (wrapper->program, "fog_mode"); - wrapper->fog_density_uniform - = glGetUniformLocation (wrapper->program, "fog_density"); - wrapper->fog_start_uniform - = glGetUniformLocation (wrapper->program, "fog_start"); - wrapper->fog_end_uniform - = glGetUniformLocation (wrapper->program, "fog_end"); - wrapper->fog_color_uniform - = glGetUniformLocation (wrapper->program, "fog_color"); - - wrapper->alpha_test_enabled_uniform - = glGetUniformLocation (wrapper->program, "alpha_test_enabled"); - wrapper->alpha_test_func_uniform - = glGetUniformLocation (wrapper->program, "alpha_test_func"); - wrapper->alpha_test_ref_uniform - = glGetUniformLocation (wrapper->program, "alpha_test_ref"); + wrapper->uniforms = &wrapper->fixed_uniforms; + cogl_gles2_wrapper_get_uniforms (wrapper->program, wrapper->uniforms); /* Always use the first texture unit */ - glUniform1i (wrapper->bound_texture_uniform, 0); + glUniform1i (wrapper->uniforms->bound_texture_uniform, 0); /* Initialize the stacks */ cogl_wrap_glMatrixMode (GL_TEXTURE); @@ -197,6 +162,55 @@ cogl_gles2_wrapper_init (CoglGles2Wrapper *wrapper) cogl_wrap_glAlphaFunc (GL_ALWAYS, 0.0f); } +void +cogl_gles2_wrapper_bind_attributes (GLuint program) +{ + glBindAttribLocation (program, COGL_GLES2_WRAPPER_VERTEX_ATTRIB, + "vertex_attrib"); + glBindAttribLocation (program, COGL_GLES2_WRAPPER_TEX_COORD_ATTRIB, + "tex_coord_attrib"); + glBindAttribLocation (program, COGL_GLES2_WRAPPER_COLOR_ATTRIB, + "color_attrib"); +} + +void +cogl_gles2_wrapper_get_uniforms (GLuint program, + CoglGles2WrapperUniforms *uniforms) +{ + uniforms->mvp_matrix_uniform + = glGetUniformLocation (program, "mvp_matrix"); + uniforms->modelview_matrix_uniform + = glGetUniformLocation (program, "modelview_matrix"); + uniforms->texture_matrix_uniform + = glGetUniformLocation (program, "texture_matrix"); + uniforms->texture_2d_enabled_uniform + = glGetUniformLocation (program, "texture_2d_enabled"); + uniforms->bound_texture_uniform + = glGetUniformLocation (program, "texture_unit"); + uniforms->alpha_only_uniform + = glGetUniformLocation (program, "alpha_only"); + + uniforms->fog_enabled_uniform + = glGetUniformLocation (program, "fog_enabled"); + uniforms->fog_mode_uniform + = glGetUniformLocation (program, "fog_mode"); + uniforms->fog_density_uniform + = glGetUniformLocation (program, "fog_density"); + uniforms->fog_start_uniform + = glGetUniformLocation (program, "fog_start"); + uniforms->fog_end_uniform + = glGetUniformLocation (program, "fog_end"); + uniforms->fog_color_uniform + = glGetUniformLocation (program, "fog_color"); + + uniforms->alpha_test_enabled_uniform + = glGetUniformLocation (program, "alpha_test_enabled"); + uniforms->alpha_test_func_uniform + = glGetUniformLocation (program, "alpha_test_func"); + uniforms->alpha_test_ref_uniform + = glGetUniformLocation (program, "alpha_test_ref"); +} + void cogl_gles2_wrapper_deinit (CoglGles2Wrapper *wrapper) { @@ -217,12 +231,12 @@ cogl_gles2_wrapper_deinit (CoglGles2Wrapper *wrapper) } } -static void -cogl_gles2_wrapper_update_matrix (CoglGles2Wrapper *wrapper) +void +cogl_gles2_wrapper_update_matrix (CoglGles2Wrapper *wrapper, GLenum matrix_num) { const float *matrix; - switch (wrapper->matrix_mode) + switch (matrix_num) { default: case GL_MODELVIEW: @@ -234,10 +248,10 @@ cogl_gles2_wrapper_update_matrix (CoglGles2Wrapper *wrapper) case GL_TEXTURE: matrix = wrapper->texture_stack + wrapper->texture_stack_pos * 16; - glUniformMatrix4fv (wrapper->texture_matrix_uniform, 1, GL_FALSE, matrix); + glUniformMatrix4fv (wrapper->uniforms->texture_matrix_uniform, + 1, GL_FALSE, matrix); break; } - } void @@ -314,7 +328,7 @@ cogl_wrap_glPopMatrix () } /* Update the matrix in the program object */ - cogl_gles2_wrapper_update_matrix (w); + cogl_gles2_wrapper_update_matrix (w, w->matrix_mode); } void @@ -356,7 +370,7 @@ cogl_wrap_glLoadIdentity () matrix[10] = 1.0f; matrix[15] = 1.0f; - cogl_gles2_wrapper_update_matrix (w); + cogl_gles2_wrapper_update_matrix (w, w->matrix_mode); } static void @@ -388,7 +402,7 @@ cogl_wrap_glMultMatrix (const float *m) memcpy (old_matrix, new_matrix, sizeof (float) * 16); - cogl_gles2_wrapper_update_matrix (w); + cogl_gles2_wrapper_update_matrix (w, w->matrix_mode); } void @@ -530,8 +544,9 @@ cogl_wrap_glDrawArrays (GLenum mode, GLint first, GLsizei count) + w->projection_stack_pos * 16, modelview_matrix); - glUniformMatrix4fv (w->mvp_matrix_uniform, 1, GL_FALSE, mvp_matrix); - glUniformMatrix4fv (w->modelview_matrix_uniform, 1, GL_FALSE, + glUniformMatrix4fv (w->uniforms->mvp_matrix_uniform, 1, + GL_FALSE, mvp_matrix); + glUniformMatrix4fv (w->uniforms->modelview_matrix_uniform, 1, GL_FALSE, modelview_matrix); w->mvp_uptodate = GL_TRUE; @@ -551,7 +566,7 @@ cogl_gles2_wrapper_bind_texture (GLenum target, GLuint 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, + glUniform1i (w->uniforms->alpha_only_uniform, internal_format == GL_ALPHA ? GL_TRUE : GL_FALSE); } @@ -571,15 +586,15 @@ cogl_wrap_glEnable (GLenum cap) switch (cap) { case GL_TEXTURE_2D: - glUniform1i (w->texture_2d_enabled_uniform, GL_TRUE); + glUniform1i (w->uniforms->texture_2d_enabled_uniform, GL_TRUE); break; case GL_FOG: - glUniform1i (w->fog_enabled_uniform, GL_TRUE); + glUniform1i (w->uniforms->fog_enabled_uniform, GL_TRUE); break; case GL_ALPHA_TEST: - glUniform1i (w->alpha_test_enabled_uniform, GL_TRUE); + glUniform1i (w->uniforms->alpha_test_enabled_uniform, GL_TRUE); break; default: @@ -595,15 +610,15 @@ cogl_wrap_glDisable (GLenum cap) switch (cap) { case GL_TEXTURE_2D: - glUniform1i (w->texture_2d_enabled_uniform, GL_FALSE); + glUniform1i (w->uniforms->texture_2d_enabled_uniform, GL_FALSE); break; case GL_FOG: - glUniform1i (w->fog_enabled_uniform, GL_FALSE); + glUniform1i (w->uniforms->fog_enabled_uniform, GL_FALSE); break; case GL_ALPHA_TEST: - glUniform1i (w->alpha_test_enabled_uniform, GL_FALSE); + glUniform1i (w->uniforms->alpha_test_enabled_uniform, GL_FALSE); break; default: @@ -655,8 +670,8 @@ cogl_wrap_glAlphaFunc (GLenum func, GLclampf ref) else if (ref > 1.0f) ref = 1.0f; - glUniform1i (w->alpha_test_func_uniform, func); - glUniform1f (w->alpha_test_ref_uniform, ref); + glUniform1i (w->uniforms->alpha_test_func_uniform, func); + glUniform1f (w->uniforms->alpha_test_ref_uniform, ref); } void @@ -738,19 +753,22 @@ cogl_wrap_glFogx (GLenum pname, GLfixed param) switch (pname) { case GL_FOG_MODE: - glUniform1i (w->fog_mode_uniform, param); + glUniform1i (w->uniforms->fog_mode_uniform, param); break; case GL_FOG_DENSITY: - glUniform1f (w->fog_density_uniform, CLUTTER_FIXED_TO_FLOAT (param)); + glUniform1f (w->uniforms->fog_density_uniform, + CLUTTER_FIXED_TO_FLOAT (param)); break; case GL_FOG_START: - glUniform1f (w->fog_start_uniform, CLUTTER_FIXED_TO_FLOAT (param)); + glUniform1f (w->uniforms->fog_start_uniform, + CLUTTER_FIXED_TO_FLOAT (param)); break; case GL_FOG_END: - glUniform1f (w->fog_end_uniform, CLUTTER_FIXED_TO_FLOAT (param)); + glUniform1f (w->uniforms->fog_end_uniform, + CLUTTER_FIXED_TO_FLOAT (param)); break; } } @@ -761,7 +779,7 @@ cogl_wrap_glFogxv (GLenum pname, const GLfixed *params) _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL); if (pname == GL_FOG_COLOR) - glUniform4f (w->fog_color_uniform, + glUniform4f (w->uniforms->fog_color_uniform, CLUTTER_FIXED_TO_FLOAT (params[0]), CLUTTER_FIXED_TO_FLOAT (params[1]), CLUTTER_FIXED_TO_FLOAT (params[2]), diff --git a/gles/cogl-gles2-wrapper.h b/gles/cogl-gles2-wrapper.h index b2c477e2c..fc2314004 100644 --- a/gles/cogl-gles2-wrapper.h +++ b/gles/cogl-gles2-wrapper.h @@ -30,19 +30,16 @@ G_BEGIN_DECLS #ifdef HAVE_COGL_GLES2 -typedef struct _CoglGles2Wrapper CoglGles2Wrapper; +typedef struct _CoglGles2Wrapper CoglGles2Wrapper; +typedef struct _CoglGles2WrapperUniforms CoglGles2WrapperUniforms; /* 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 +struct _CoglGles2WrapperUniforms { - GLuint program; - GLuint vertex_shader; - GLuint fragment_shader; - GLint mvp_matrix_uniform; GLint modelview_matrix_uniform; GLint texture_matrix_uniform; @@ -60,6 +57,13 @@ struct _CoglGles2Wrapper GLint alpha_test_enabled_uniform; GLint alpha_test_func_uniform; GLint alpha_test_ref_uniform; +}; + +struct _CoglGles2Wrapper +{ + GLuint program; + GLuint vertex_shader; + GLuint fragment_shader; GLuint matrix_mode; GLfloat modelview_stack[COGL_GLES2_MODELVIEW_STACK_SIZE * 16]; @@ -69,6 +73,11 @@ struct _CoglGles2Wrapper GLfloat texture_stack[COGL_GLES2_TEXTURE_STACK_SIZE * 16]; GLuint texture_stack_pos; + /* The uniforms for the fixed-functionality emulation program */ + CoglGles2WrapperUniforms fixed_uniforms; + /* The uniforms for the currently bound program */ + CoglGles2WrapperUniforms *uniforms; + /* 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 */ @@ -169,6 +178,12 @@ void cogl_gles2_wrapper_bind_texture (GLenum target, GLuint texture, /* This function is only available on GLES 2 */ #define cogl_wrap_glGenerateMipmap glGenerateMipmap +void cogl_gles2_wrapper_bind_attributes (GLuint program); +void cogl_gles2_wrapper_get_uniforms (GLuint program, + CoglGles2WrapperUniforms *uniforms); +void cogl_gles2_wrapper_update_matrix (CoglGles2Wrapper *wrapper, + GLenum matrix_num); + #else /* HAVE_COGL_GLES2 */ /* If we're not using GL ES 2 then just use the GL functions diff --git a/gles/cogl-program.c b/gles/cogl-program.c new file mode 100644 index 000000000..bca76584c --- /dev/null +++ b/gles/cogl-program.c @@ -0,0 +1,257 @@ +/* + * 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 "cogl.h" + +#include "cogl-internal.h" +#include "cogl-context.h" +#include "cogl-handle.h" + +#ifdef HAVE_COGL_GLES2 + +#include "cogl-shader.h" +#include "cogl-program.h" + +static void _cogl_program_free (CoglProgram *program); + +COGL_HANDLE_DEFINE (Program, program, program_handles); + +static void +_cogl_program_free (CoglProgram *program) +{ + /* Frees program resources but its handle is not + released! Do that separately before this! */ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + glDeleteProgram (program->gl_handle); +} + +CoglHandle +cogl_create_program (void) +{ + CoglProgram *program; + _COGL_GET_CONTEXT (ctx, 0); + + program = g_slice_new (CoglProgram); + program->ref_count = 1; + program->gl_handle = glCreateProgram (); + + program->attached_vertex_shader = FALSE; + program->attached_fragment_shader = FALSE; + program->attached_fixed_vertex_shader = FALSE; + program->attached_fixed_fragment_shader = FALSE; + + COGL_HANDLE_DEBUG_NEW (program, program); + + return _cogl_program_handle_new (program); +} + +void +cogl_program_attach_shader (CoglHandle program_handle, + CoglHandle shader_handle) +{ + CoglProgram *program; + CoglShader *shader; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (!cogl_is_program (program_handle) || !cogl_is_shader (shader_handle)) + return; + + program = _cogl_program_pointer_from_handle (program_handle); + shader = _cogl_shader_pointer_from_handle (shader_handle); + + if (shader->type == GL_VERTEX_SHADER) + { + if (program->attached_fixed_vertex_shader) + { + glDetachShader (program->gl_handle, ctx->gles2.vertex_shader); + program->attached_fixed_vertex_shader = FALSE; + } + program->attached_vertex_shader = TRUE; + } + else if (shader->type == GL_FRAGMENT_SHADER) + { + if (program->attached_fixed_fragment_shader) + { + glDetachShader (program->gl_handle, ctx->gles2.fragment_shader); + program->attached_fixed_fragment_shader = FALSE; + } + program->attached_fragment_shader = TRUE; + } + + glAttachShader (program->gl_handle, shader->gl_handle); +} + +void +cogl_program_link (CoglHandle handle) +{ + CoglProgram *program; + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (!cogl_is_program (handle)) + return; + + program = _cogl_program_pointer_from_handle (handle); + + if (!program->attached_vertex_shader + && !program->attached_fixed_vertex_shader) + { + glAttachShader (program->gl_handle, ctx->gles2.vertex_shader); + program->attached_fixed_vertex_shader = TRUE; + } + + if (!program->attached_fragment_shader + && !program->attached_fixed_fragment_shader) + { + glAttachShader (program->gl_handle, ctx->gles2.fragment_shader); + program->attached_fixed_fragment_shader = TRUE; + } + + /* Set the attributes so that the wrapper functions will still work */ + cogl_gles2_wrapper_bind_attributes (program->gl_handle); + + glLinkProgram (program->gl_handle); + + /* Retrieve the uniforms */ + cogl_gles2_wrapper_get_uniforms (program->gl_handle, + &program->uniforms); +} + +void +cogl_program_use (CoglHandle handle) +{ + CoglProgram *program; + GLuint gl_handle; + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (handle != COGL_INVALID_HANDLE && !cogl_is_program (handle)) + return; + + if (handle == COGL_INVALID_HANDLE) + { + /* Go back to the fixed-functionality emulator program */ + gl_handle = ctx->gles2.program; + ctx->gles2.uniforms = &ctx->gles2.fixed_uniforms; + } + else + { + program = _cogl_program_pointer_from_handle (handle); + gl_handle = program->gl_handle; + /* Use the uniforms in the program */ + ctx->gles2.uniforms = &program->uniforms; + } + + glUseProgram (gl_handle); + + /* Update all of the matrix attributes */ + cogl_gles2_wrapper_update_matrix (&ctx->gles2, GL_MODELVIEW); + cogl_gles2_wrapper_update_matrix (&ctx->gles2, GL_PROJECTION); + cogl_gles2_wrapper_update_matrix (&ctx->gles2, GL_TEXTURE); +} + +COGLint +cogl_program_get_uniform_location (CoglHandle handle, + const gchar *uniform_name) +{ + CoglProgram *program; + _COGL_GET_CONTEXT (ctx, 0); + + if (!cogl_is_program (handle)) + return 0; + + program = _cogl_program_pointer_from_handle (handle); + + return glGetUniformLocation (program->gl_handle, uniform_name); +} + +void +cogl_program_uniform_1f (COGLint uniform_no, + gfloat value) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + glUniform1f (uniform_no, value); +} + +#else /* HAVE_COGL_GLES2 */ + +/* No support on regular OpenGL 1.1 */ + +CoglHandle +cogl_create_program (void) +{ + return COGL_INVALID_HANDLE; +} + +gboolean +cogl_is_program (CoglHandle handle) +{ + return FALSE; +} + +CoglHandle +cogl_program_ref (CoglHandle handle) +{ + return COGL_INVALID_HANDLE; +} + +void +cogl_program_unref (CoglHandle handle) +{ +} + +void +cogl_program_attach_shader (CoglHandle program_handle, + CoglHandle shader_handle) +{ +} + +void +cogl_program_link (CoglHandle program_handle) +{ +} + +void +cogl_program_use (CoglHandle program_handle) +{ +} + +COGLint +cogl_program_get_uniform_location (CoglHandle program_handle, + const gchar *uniform_name) +{ + return 0; +} + +void +cogl_program_uniform_1f (COGLint uniform_no, + gfloat value) +{ +} + +#endif /* HAVE_COGL_GLES2 */ diff --git a/gles/cogl-program.h b/gles/cogl-program.h new file mode 100644 index 000000000..242d97062 --- /dev/null +++ b/gles/cogl-program.h @@ -0,0 +1,50 @@ +/* + * 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_PROGRAM_H +#define __COGL_PROGRAM_H + +#include "cogl-gles2-wrapper.h" + +typedef struct _CoglProgram CoglProgram; + +struct _CoglProgram +{ + guint ref_count; + GLuint gl_handle; + + /* Keep track of which types of shader we've attached so we can link + in our replacement fixed functionality shader */ + gboolean attached_vertex_shader; + gboolean attached_fragment_shader; + gboolean attached_fixed_vertex_shader; + gboolean attached_fixed_fragment_shader; + + CoglGles2WrapperUniforms uniforms; +}; + +CoglProgram *_cogl_program_pointer_from_handle (CoglHandle handle); + +#endif /* __COGL_PROGRAM_H */ diff --git a/gles/cogl-shader.c b/gles/cogl-shader.c new file mode 100644 index 000000000..2512f3ddc --- /dev/null +++ b/gles/cogl-shader.c @@ -0,0 +1,184 @@ +/* + * 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 "cogl.h" + +#include "cogl-shader.h" +#include "cogl-internal.h" +#include "cogl-context.h" +#include "cogl-handle.h" + +#ifdef HAVE_COGL_GLES2 + +static void _cogl_shader_free (CoglShader *shader); + +COGL_HANDLE_DEFINE (Shader, shader, shader_handles); + +static void +_cogl_shader_free (CoglShader *shader) +{ + /* Frees shader resources but its handle is not + released! Do that separately before this! */ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + glDeleteShader (shader->gl_handle); +} + +CoglHandle +cogl_create_shader (COGLenum shaderType) +{ + CoglShader *shader; + + _COGL_GET_CONTEXT (ctx, 0); + + shader = g_slice_new (CoglShader); + shader->ref_count = 1; + shader->gl_handle = glCreateShader (shaderType); + shader->type = shaderType; + + COGL_HANDLE_DEBUG_NEW (shader, shader); + + return _cogl_shader_handle_new (shader); +} + +void +cogl_shader_source (CoglHandle handle, + const gchar *source) +{ + CoglShader *shader; + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (!cogl_is_shader (handle)) + return; + + shader = _cogl_shader_pointer_from_handle (handle); + + glShaderSource (shader->gl_handle, 1, &source, NULL); +} + +void +cogl_shader_compile (CoglHandle handle) +{ + CoglShader *shader; + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (!cogl_is_shader (handle)) + return; + + shader = _cogl_shader_pointer_from_handle (handle); + + glCompileShader (shader->gl_handle); +} + +void +cogl_shader_get_info_log (CoglHandle handle, + guint size, + gchar *buffer) +{ + CoglShader *shader; + COGLint len = 0; + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (!cogl_is_shader (handle)) + return; + + shader = _cogl_shader_pointer_from_handle (handle); + + glGetShaderInfoLog (shader->gl_handle, size - 1, &len, buffer); + buffer[len] = '\0'; +} + +void +cogl_shader_get_parameteriv (CoglHandle handle, + COGLenum pname, + COGLint *dest) +{ + CoglShader *shader; + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (!cogl_is_shader (handle)) + return; + + shader = _cogl_shader_pointer_from_handle (handle); + + glGetShaderiv (shader->gl_handle, pname, dest); +} + +#else /* HAVE_COGL_GLES2 */ + +/* No support on regular OpenGL 1.1 */ + +CoglHandle +cogl_create_shader (COGLenum shaderType) +{ + return COGL_INVALID_HANDLE; +} + +gboolean +cogl_is_shader (CoglHandle handle) +{ + return FALSE; +} + +CoglHandle +cogl_shader_ref (CoglHandle handle) +{ + return COGL_INVALID_HANDLE; +} + +void +cogl_shader_unref (CoglHandle handle) +{ +} + +void +cogl_shader_source (CoglHandle shader, + const gchar *source) +{ +} + +void +cogl_shader_compile (CoglHandle shader_handle) +{ +} + +void +cogl_shader_get_info_log (CoglHandle handle, + guint size, + gchar *buffer) +{ +} + +void +cogl_shader_get_parameteriv (CoglHandle handle, + COGLenum pname, + COGLint *dest) +{ +} + +#endif /* HAVE_COGL_GLES2 */ diff --git a/gles/cogl-shader.h b/gles/cogl-shader.h new file mode 100644 index 000000000..04dff11f4 --- /dev/null +++ b/gles/cogl-shader.h @@ -0,0 +1,40 @@ +/* + * 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_SHADER_H +#define __COGL_SHADER_H + +typedef struct _CoglShader CoglShader; + +struct _CoglShader +{ + guint ref_count; + GLuint gl_handle; + GLenum type; +}; + +CoglShader *_cogl_shader_pointer_from_handle (CoglHandle handle); + +#endif /* __COGL_SHADER_H */ diff --git a/gles/cogl.c b/gles/cogl.c index 5e5cf76f6..6d070036b 100644 --- a/gles/cogl.c +++ b/gles/cogl.c @@ -490,6 +490,10 @@ _cogl_features_init () if (max_clip_planes >= 4) flags |= COGL_FEATURE_FOUR_CLIP_PLANES; +#ifdef HAVE_COGL_GLES2 + flags |= COGL_FEATURE_SHADERS_GLSL; +#endif + ctx->feature_flags = flags; ctx->features_cached = TRUE; } @@ -571,106 +575,3 @@ cogl_fog_set (const ClutterColor *fog_color, 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 */ - -CoglHandle -cogl_create_program (void) -{ - return COGL_INVALID_HANDLE; -} - -gboolean -cogl_is_program (CoglHandle handle) -{ - return FALSE; -} - -CoglHandle -cogl_program_ref (CoglHandle handle) -{ - return COGL_INVALID_HANDLE; -} - -void -cogl_program_unref (CoglHandle handle) -{ -} - -CoglHandle -cogl_create_shader (COGLenum shaderType) -{ - return COGL_INVALID_HANDLE; -} - -gboolean -cogl_is_shader (CoglHandle handle) -{ - return FALSE; -} - -CoglHandle -cogl_shader_ref (CoglHandle handle) -{ - return COGL_INVALID_HANDLE; -} - -void -cogl_shader_unref (CoglHandle handle) -{ -} - -void -cogl_shader_source (CoglHandle shader, - const gchar *source) -{ -} - -void -cogl_shader_compile (CoglHandle shader_handle) -{ -} - -void -cogl_program_attach_shader (CoglHandle program_handle, - CoglHandle shader_handle) -{ -} - -void -cogl_program_link (CoglHandle program_handle) -{ -} - -void -cogl_program_use (CoglHandle program_handle) -{ -} - -COGLint -cogl_program_get_uniform_location (CoglHandle program_handle, - const gchar *uniform_name) -{ - return 0; -} - -void -cogl_shader_get_info_log (CoglHandle handle, - guint size, - gchar *buffer) -{ -} - -void -cogl_shader_get_parameteriv (CoglHandle handle, - COGLenum pname, - COGLint *dest) -{ -} - - -void -cogl_program_uniform_1f (COGLint uniform_no, - gfloat value) -{ -}