* 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}
This commit is contained in:
Neil Roberts 2008-06-02 10:58:57 +00:00
parent 46be48f8f6
commit 165531074b
11 changed files with 661 additions and 175 deletions

View File

@ -30,7 +30,11 @@ libclutter_cogl_la_SOURCES = \
cogl-texture.c \ cogl-texture.c \
cogl-fbo.c \ cogl-fbo.c \
cogl-context.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 if USE_GLES2_WRAPPER
libclutter_cogl_la_SOURCES += \ libclutter_cogl_la_SOURCES += \

View File

@ -64,6 +64,8 @@ cogl_create_context ()
_context->texture_vertices = NULL; _context->texture_vertices = NULL;
_context->fbo_handles = NULL; _context->fbo_handles = NULL;
_context->program_handles = NULL;
_context->shader_handles = NULL;
_context->draw_buffer = COGL_WINDOW_BUFFER; _context->draw_buffer = COGL_WINDOW_BUFFER;
_context->blend_src_factor = CGL_SRC_ALPHA; _context->blend_src_factor = CGL_SRC_ALPHA;
@ -96,6 +98,15 @@ cogl_destroy_context ()
if (_context->texture_vertices) if (_context->texture_vertices)
g_free (_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); g_free (_context);
} }

View File

@ -67,6 +67,10 @@ typedef struct
GArray *fbo_handles; GArray *fbo_handles;
CoglBufferTarget draw_buffer; CoglBufferTarget draw_buffer;
/* Shaders */
GArray *program_handles;
GArray *shader_handles;
#ifdef HAVE_COGL_GLES2 #ifdef HAVE_COGL_GLES2
CoglGles2Wrapper gles2; CoglGles2Wrapper gles2;
#endif #endif

View File

@ -460,8 +460,10 @@ typedef GLuint COGLuint;
#define CGL_VERTEX_SHADER 0 #define CGL_VERTEX_SHADER 0
#endif #endif
#ifdef GL_OBJECT_COMPILE_STATUS #if defined(GL_OBJECT_COMPILE_STATUS)
#define CGL_OBJECT_COMPILE_STATUS 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 #else
#define CGL_OBJECT_COMPILE_STATUS 0 #define CGL_OBJECT_COMPILE_STATUS 0
#endif #endif

View File

@ -109,12 +109,7 @@ cogl_gles2_wrapper_init (CoglGles2Wrapper *wrapper)
wrapper->program = glCreateProgram (); wrapper->program = glCreateProgram ();
glAttachShader (wrapper->program, wrapper->fragment_shader); glAttachShader (wrapper->program, wrapper->fragment_shader);
glAttachShader (wrapper->program, wrapper->vertex_shader); glAttachShader (wrapper->program, wrapper->vertex_shader);
glBindAttribLocation (wrapper->program, COGL_GLES2_WRAPPER_VERTEX_ATTRIB, cogl_gles2_wrapper_bind_attributes (wrapper->program);
"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); glLinkProgram (wrapper->program);
glGetProgramiv (wrapper->program, GL_LINK_STATUS, &status); glGetProgramiv (wrapper->program, GL_LINK_STATUS, &status);
@ -138,41 +133,11 @@ cogl_gles2_wrapper_init (CoglGles2Wrapper *wrapper)
glUseProgram (wrapper->program); glUseProgram (wrapper->program);
wrapper->mvp_matrix_uniform wrapper->uniforms = &wrapper->fixed_uniforms;
= glGetUniformLocation (wrapper->program, "mvp_matrix"); cogl_gles2_wrapper_get_uniforms (wrapper->program, wrapper->uniforms);
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");
/* Always use the first texture unit */ /* Always use the first texture unit */
glUniform1i (wrapper->bound_texture_uniform, 0); glUniform1i (wrapper->uniforms->bound_texture_uniform, 0);
/* Initialize the stacks */ /* Initialize the stacks */
cogl_wrap_glMatrixMode (GL_TEXTURE); cogl_wrap_glMatrixMode (GL_TEXTURE);
@ -197,6 +162,55 @@ cogl_gles2_wrapper_init (CoglGles2Wrapper *wrapper)
cogl_wrap_glAlphaFunc (GL_ALWAYS, 0.0f); 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 void
cogl_gles2_wrapper_deinit (CoglGles2Wrapper *wrapper) cogl_gles2_wrapper_deinit (CoglGles2Wrapper *wrapper)
{ {
@ -217,12 +231,12 @@ cogl_gles2_wrapper_deinit (CoglGles2Wrapper *wrapper)
} }
} }
static void void
cogl_gles2_wrapper_update_matrix (CoglGles2Wrapper *wrapper) cogl_gles2_wrapper_update_matrix (CoglGles2Wrapper *wrapper, GLenum matrix_num)
{ {
const float *matrix; const float *matrix;
switch (wrapper->matrix_mode) switch (matrix_num)
{ {
default: default:
case GL_MODELVIEW: case GL_MODELVIEW:
@ -234,10 +248,10 @@ cogl_gles2_wrapper_update_matrix (CoglGles2Wrapper *wrapper)
case GL_TEXTURE: case GL_TEXTURE:
matrix = wrapper->texture_stack + wrapper->texture_stack_pos * 16; 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; break;
} }
} }
void void
@ -314,7 +328,7 @@ cogl_wrap_glPopMatrix ()
} }
/* Update the matrix in the program object */ /* Update the matrix in the program object */
cogl_gles2_wrapper_update_matrix (w); cogl_gles2_wrapper_update_matrix (w, w->matrix_mode);
} }
void void
@ -356,7 +370,7 @@ cogl_wrap_glLoadIdentity ()
matrix[10] = 1.0f; matrix[10] = 1.0f;
matrix[15] = 1.0f; matrix[15] = 1.0f;
cogl_gles2_wrapper_update_matrix (w); cogl_gles2_wrapper_update_matrix (w, w->matrix_mode);
} }
static void static void
@ -388,7 +402,7 @@ cogl_wrap_glMultMatrix (const float *m)
memcpy (old_matrix, new_matrix, sizeof (float) * 16); memcpy (old_matrix, new_matrix, sizeof (float) * 16);
cogl_gles2_wrapper_update_matrix (w); cogl_gles2_wrapper_update_matrix (w, w->matrix_mode);
} }
void void
@ -530,8 +544,9 @@ cogl_wrap_glDrawArrays (GLenum mode, GLint first, GLsizei count)
+ w->projection_stack_pos * 16, + w->projection_stack_pos * 16,
modelview_matrix); modelview_matrix);
glUniformMatrix4fv (w->mvp_matrix_uniform, 1, GL_FALSE, mvp_matrix); glUniformMatrix4fv (w->uniforms->mvp_matrix_uniform, 1,
glUniformMatrix4fv (w->modelview_matrix_uniform, 1, GL_FALSE, GL_FALSE, mvp_matrix);
glUniformMatrix4fv (w->uniforms->modelview_matrix_uniform, 1, GL_FALSE,
modelview_matrix); modelview_matrix);
w->mvp_uptodate = GL_TRUE; 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 /* We need to keep track of whether the texture is alpha-only
because the emulation of GL_MODULATE needs to work differently in because the emulation of GL_MODULATE needs to work differently in
that case */ that case */
glUniform1i (w->alpha_only_uniform, glUniform1i (w->uniforms->alpha_only_uniform,
internal_format == GL_ALPHA ? GL_TRUE : GL_FALSE); internal_format == GL_ALPHA ? GL_TRUE : GL_FALSE);
} }
@ -571,15 +586,15 @@ cogl_wrap_glEnable (GLenum cap)
switch (cap) switch (cap)
{ {
case GL_TEXTURE_2D: case GL_TEXTURE_2D:
glUniform1i (w->texture_2d_enabled_uniform, GL_TRUE); glUniform1i (w->uniforms->texture_2d_enabled_uniform, GL_TRUE);
break; break;
case GL_FOG: case GL_FOG:
glUniform1i (w->fog_enabled_uniform, GL_TRUE); glUniform1i (w->uniforms->fog_enabled_uniform, GL_TRUE);
break; break;
case GL_ALPHA_TEST: case GL_ALPHA_TEST:
glUniform1i (w->alpha_test_enabled_uniform, GL_TRUE); glUniform1i (w->uniforms->alpha_test_enabled_uniform, GL_TRUE);
break; break;
default: default:
@ -595,15 +610,15 @@ cogl_wrap_glDisable (GLenum cap)
switch (cap) switch (cap)
{ {
case GL_TEXTURE_2D: case GL_TEXTURE_2D:
glUniform1i (w->texture_2d_enabled_uniform, GL_FALSE); glUniform1i (w->uniforms->texture_2d_enabled_uniform, GL_FALSE);
break; break;
case GL_FOG: case GL_FOG:
glUniform1i (w->fog_enabled_uniform, GL_FALSE); glUniform1i (w->uniforms->fog_enabled_uniform, GL_FALSE);
break; break;
case GL_ALPHA_TEST: case GL_ALPHA_TEST:
glUniform1i (w->alpha_test_enabled_uniform, GL_FALSE); glUniform1i (w->uniforms->alpha_test_enabled_uniform, GL_FALSE);
break; break;
default: default:
@ -655,8 +670,8 @@ cogl_wrap_glAlphaFunc (GLenum func, GLclampf ref)
else if (ref > 1.0f) else if (ref > 1.0f)
ref = 1.0f; ref = 1.0f;
glUniform1i (w->alpha_test_func_uniform, func); glUniform1i (w->uniforms->alpha_test_func_uniform, func);
glUniform1f (w->alpha_test_ref_uniform, ref); glUniform1f (w->uniforms->alpha_test_ref_uniform, ref);
} }
void void
@ -738,19 +753,22 @@ cogl_wrap_glFogx (GLenum pname, GLfixed param)
switch (pname) switch (pname)
{ {
case GL_FOG_MODE: case GL_FOG_MODE:
glUniform1i (w->fog_mode_uniform, param); glUniform1i (w->uniforms->fog_mode_uniform, param);
break; break;
case GL_FOG_DENSITY: 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; break;
case GL_FOG_START: 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; break;
case GL_FOG_END: 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; break;
} }
} }
@ -761,7 +779,7 @@ cogl_wrap_glFogxv (GLenum pname, const GLfixed *params)
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL); _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
if (pname == GL_FOG_COLOR) 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[0]),
CLUTTER_FIXED_TO_FLOAT (params[1]), CLUTTER_FIXED_TO_FLOAT (params[1]),
CLUTTER_FIXED_TO_FLOAT (params[2]), CLUTTER_FIXED_TO_FLOAT (params[2]),

View File

@ -30,19 +30,16 @@ G_BEGIN_DECLS
#ifdef HAVE_COGL_GLES2 #ifdef HAVE_COGL_GLES2
typedef struct _CoglGles2Wrapper CoglGles2Wrapper; typedef struct _CoglGles2Wrapper CoglGles2Wrapper;
typedef struct _CoglGles2WrapperUniforms CoglGles2WrapperUniforms;
/* Must be a power of two */ /* Must be a power of two */
#define COGL_GLES2_MODELVIEW_STACK_SIZE 32 #define COGL_GLES2_MODELVIEW_STACK_SIZE 32
#define COGL_GLES2_PROJECTION_STACK_SIZE 2 #define COGL_GLES2_PROJECTION_STACK_SIZE 2
#define COGL_GLES2_TEXTURE_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 mvp_matrix_uniform;
GLint modelview_matrix_uniform; GLint modelview_matrix_uniform;
GLint texture_matrix_uniform; GLint texture_matrix_uniform;
@ -60,6 +57,13 @@ struct _CoglGles2Wrapper
GLint alpha_test_enabled_uniform; GLint alpha_test_enabled_uniform;
GLint alpha_test_func_uniform; GLint alpha_test_func_uniform;
GLint alpha_test_ref_uniform; GLint alpha_test_ref_uniform;
};
struct _CoglGles2Wrapper
{
GLuint program;
GLuint vertex_shader;
GLuint fragment_shader;
GLuint matrix_mode; GLuint matrix_mode;
GLfloat modelview_stack[COGL_GLES2_MODELVIEW_STACK_SIZE * 16]; GLfloat modelview_stack[COGL_GLES2_MODELVIEW_STACK_SIZE * 16];
@ -69,6 +73,11 @@ struct _CoglGles2Wrapper
GLfloat texture_stack[COGL_GLES2_TEXTURE_STACK_SIZE * 16]; GLfloat texture_stack[COGL_GLES2_TEXTURE_STACK_SIZE * 16];
GLuint texture_stack_pos; 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 combined modelview and projection matrix is only updated at
the last minute in glDrawArrays to avoid recalculating it for the last minute in glDrawArrays to avoid recalculating it for
every change to the modelview matrix */ 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 */ /* This function is only available on GLES 2 */
#define cogl_wrap_glGenerateMipmap glGenerateMipmap #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 */ #else /* HAVE_COGL_GLES2 */
/* If we're not using GL ES 2 then just use the GL functions /* If we're not using GL ES 2 then just use the GL functions

257
gles/cogl-program.c Normal file
View File

@ -0,0 +1,257 @@
/*
* Clutter COGL
*
* A basic GL/GLES Abstraction/Utility Layer
*
* Authored By Matthew Allum <mallum@openedhand.com>
*
* 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 */

50
gles/cogl-program.h Normal file
View File

@ -0,0 +1,50 @@
/*
* Clutter COGL
*
* A basic GL/GLES Abstraction/Utility Layer
*
* Authored By Matthew Allum <mallum@openedhand.com>
*
* 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 */

184
gles/cogl-shader.c Normal file
View File

@ -0,0 +1,184 @@
/*
* Clutter COGL
*
* A basic GL/GLES Abstraction/Utility Layer
*
* Authored By Matthew Allum <mallum@openedhand.com>
*
* 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 */

40
gles/cogl-shader.h Normal file
View File

@ -0,0 +1,40 @@
/*
* Clutter COGL
*
* A basic GL/GLES Abstraction/Utility Layer
*
* Authored By Matthew Allum <mallum@openedhand.com>
*
* 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 */

View File

@ -490,6 +490,10 @@ _cogl_features_init ()
if (max_clip_planes >= 4) if (max_clip_planes >= 4)
flags |= COGL_FEATURE_FOUR_CLIP_PLANES; flags |= COGL_FEATURE_FOUR_CLIP_PLANES;
#ifdef HAVE_COGL_GLES2
flags |= COGL_FEATURE_SHADERS_GLSL;
#endif
ctx->feature_flags = flags; ctx->feature_flags = flags;
ctx->features_cached = TRUE; 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_START, (GLfixed) z_near);
cogl_wrap_glFogx (GL_FOG_END, (GLfixed) z_far); 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)
{
}