From 2142062ba1da5563c264946815fe00550c7679aa Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Tue, 18 Nov 2008 15:08:40 +0000 Subject: [PATCH] 2008-11-18 Emmanuele Bassi Bug 1049 - Clutter doesn't support most GLSL uniforms (patch by Chris Lord and Neil Roberts) * README: Update release notes. * clutter/Makefile.am: * clutter/clutter-shader-types.[ch]: Add GValue types for shader values. * clutter/clutter-actor.[ch]: Update the shader API to use the newly added GValue support for GLSL shader uniform setters. * clutter/clutter-shader.[ch]: Add float and integer convenience API for single value GLSL uniform setters. * clutter/cogl/cogl-shader.h: Add new uniform setters. * clutter/cogl/gl/cogl-context.c: * clutter/cogl/gl/cogl-context.h: * clutter/cogl/gl/cogl-defines.h.in: * clutter/cogl/gl/cogl-program.c: * clutter/cogl/gl/cogl.c: Update the GL implementation of COGL to handle the GLSL uniform setters. * clutter/cogl/gles/cogl-gles2-wrapper.c: * clutter/cogl/gles/cogl-gles2-wrapper.h: * clutter/cogl/gles/cogl-internal.h: * clutter/cogl/gles/cogl-program.c: Update the GLES 2.0 implementation of COGL to handle the GLSL uniform setters. * doc/reference/clutter/clutter-sections.txt: * doc/reference/cogl/cogl-sections.txt: Update the documentation. * tests/interactive/test-fbo.c: * tests/interactive/test-shader.c: Update the shader tests. --- cogl-shader.h | 66 ++++++++++++-- doc/reference/cogl/cogl-sections.txt | 3 + gl/cogl-context.c | 18 ++++ gl/cogl-context.h | 21 ++++- gl/cogl-defines.h.in | 126 +++++++++++++++++++++++++-- gl/cogl-program.c | 99 ++++++++++++++++++++- gl/cogl.c | 93 +++++++++++++++++++- gles/cogl-gles2-wrapper.c | 81 ++++++++++++++++- gles/cogl-gles2-wrapper.h | 4 +- gles/cogl-internal.h | 24 +++++ gles/cogl-program.c | 109 ++++++++++++++++++++++- 11 files changed, 621 insertions(+), 23 deletions(-) diff --git a/cogl-shader.h b/cogl-shader.h index 8438b69e9..4c06abe1c 100644 --- a/cogl-shader.h +++ b/cogl-shader.h @@ -188,10 +188,10 @@ void cogl_program_link (CoglHandle handle); /** * cogl_program_use: - * @handle: a #CoglHandle for a shader program or COGL_INVALID_HANDLE. + * @handle: a #CoglHandle for a shader program or %COGL_INVALID_HANDLE. * * Activate a specific shader program replacing that part of the GL - * rendering pipeline, if passed in COGL_INVALID_HANDLE the default + * rendering pipeline, if passed in %COGL_INVALID_HANDLE the default * behavior of GL is reinstated. */ void cogl_program_use (CoglHandle handle); @@ -201,29 +201,77 @@ void cogl_program_use (CoglHandle handle); * @handle: a #CoglHandle for a shader program. * @uniform_name: the name of a uniform. * - * Retrieve the location (offset) of a uniform variable in a shader program, a - * uniform is a variable that is constant for all vertices/fragments for a + * Retrieve the location (offset) of a uniform variable in a shader program, + * a uniform is a variable that is constant for all vertices/fragments for a * shader object and is possible to modify as an external parameter. * - * Returns: the offset of a uniform in a specified program, this uniform can be - * set using #cogl_program_uniform_1f when the program is in use. + * Return value: the offset of a uniform in a specified program. + * This uniform can be set using cogl_program_uniform_1f() when the + * program is in use. */ COGLint cogl_program_get_uniform_location (CoglHandle handle, const gchar *uniform_name); - /** * cogl_program_uniform_1f: * @uniform_no: the unform to set. * @value: the new value of the uniform. * - * Changes the value of a uniform in the currently used (see #cogl_program_use) - * shader program. + * Changes the value of a uniform in the currently used (see + * cogl_program_use()) shader program. */ void cogl_program_uniform_1f (COGLint uniform_no, gfloat value); + /** + * cogl_program_uniform_float: + * @uniform_no: the uniform to set. + * @size: Size of float vector. + * @count: Size of array of uniforms. + * @value: the new value of the uniform. + * + * Changes the value of a float vector uniform, or uniform array in the + * currently used (see #cogl_program_use) shader program. + */ +void cogl_program_uniform_float (COGLint uniform_no, + gint size, + gint count, + const GLfloat *value); + +/** + * cogl_program_uniform_int: + * @uniform_no: the uniform to set. + * @size: Size of int vector. + * @count: Size of array of uniforms. + * @value: the new value of the uniform. + * + * Changes the value of a int vector uniform, or uniform array in the + * currently used (see cogl_program_use()) shader program. + */ +void cogl_program_uniform_int (COGLint uniform_no, + gint size, + gint count, + const COGLint *value); + +/** + * cogl_program_uniform_matrix: + * @uniform_no: the uniform to set. + * @size: Size of matrix. + * @count: Size of array of uniforms. + * @transpose: Whether to transpose the matrix when setting the uniform. + * @value: the new value of the uniform. + * + * Changes the value of a matrix uniform, or uniform array in the + * currently used (see cogl_program_use()) shader program. The @size + * parameter is used to determine the square size of the matrix. + */ +void cogl_program_uniform_matrix (COGLint uniform_no, + gint size, + gint count, + gboolean transpose, + const GLfloat *value); + G_END_DECLS #endif /* __COGL_SHADER_H__ */ diff --git a/doc/reference/cogl/cogl-sections.txt b/doc/reference/cogl/cogl-sections.txt index ee5dbad5d..3ff906e90 100644 --- a/doc/reference/cogl/cogl-sections.txt +++ b/doc/reference/cogl/cogl-sections.txt @@ -138,6 +138,9 @@ cogl_program_link cogl_program_use cogl_program_get_uniform_location cogl_program_uniform_1f +cogl_program_uniform_float +cogl_program_uniform_int +cogl_program_uniform_matrix
diff --git a/gl/cogl-context.c b/gl/cogl-context.c index e4b7b0493..1cb41f85d 100644 --- a/gl/cogl-context.c +++ b/gl/cogl-context.c @@ -94,6 +94,24 @@ cogl_create_context () _context->pf_glGetInfoLogARB = NULL; _context->pf_glGetObjectParameterivARB = NULL; _context->pf_glUniform1fARB = NULL; + _context->pf_glUniform2fARB = NULL; + _context->pf_glUniform3fARB = NULL; + _context->pf_glUniform4fARB = NULL; + _context->pf_glUniform1fvARB = NULL; + _context->pf_glUniform2fvARB = NULL; + _context->pf_glUniform3fvARB = NULL; + _context->pf_glUniform4fvARB = NULL; + _context->pf_glUniform1iARB = NULL; + _context->pf_glUniform2iARB = NULL; + _context->pf_glUniform3iARB = NULL; + _context->pf_glUniform4iARB = NULL; + _context->pf_glUniform1ivARB = NULL; + _context->pf_glUniform2ivARB = NULL; + _context->pf_glUniform3ivARB = NULL; + _context->pf_glUniform4ivARB = NULL; + _context->pf_glUniformMatrix2fvARB = NULL; + _context->pf_glUniformMatrix3fvARB = NULL; + _context->pf_glUniformMatrix4fvARB = NULL; /* Init OpenGL state */ GE( glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE) ); diff --git a/gl/cogl-context.h b/gl/cogl-context.h index 62216dcbc..0bab8a2ff 100644 --- a/gl/cogl-context.h +++ b/gl/cogl-context.h @@ -96,7 +96,7 @@ typedef struct COGL_PFNGLDELETEOBJECTARBPROC pf_glDeleteObjectARB; COGL_PFNGLGETINFOLOGARBPROC pf_glGetInfoLogARB; COGL_PFNGLGETOBJECTPARAMETERIVARBPROC pf_glGetObjectParameterivARB; - COGL_PFNGLUNIFORM1FARBPROC pf_glUniform1fARB; + COGL_PFNGLVERTEXATTRIBPOINTERARBPROC pf_glVertexAttribPointerARB; COGL_PFNGLENABLEVERTEXATTRIBARRAYARBPROC pf_glEnableVertexAttribArrayARB; COGL_PFNGLDISABLEVERTEXATTRIBARRAYARBPROC pf_glDisableVertexAttribArrayARB; @@ -109,6 +109,25 @@ typedef struct COGL_PFNGLUNMAPBUFFERARBPROC pf_glUnmapBufferARB; COGL_PFNGLDELETEBUFFERSARBPROC pf_glDeleteBuffersARB; + COGL_PFNGLUNIFORM1FARBPROC pf_glUniform1fARB; + COGL_PFNGLUNIFORM2FARBPROC pf_glUniform2fARB; + COGL_PFNGLUNIFORM3FARBPROC pf_glUniform3fARB; + COGL_PFNGLUNIFORM4FARBPROC pf_glUniform4fARB; + COGL_PFNGLUNIFORM1FVARBPROC pf_glUniform1fvARB; + COGL_PFNGLUNIFORM2FVARBPROC pf_glUniform2fvARB; + COGL_PFNGLUNIFORM3FVARBPROC pf_glUniform3fvARB; + COGL_PFNGLUNIFORM4FVARBPROC pf_glUniform4fvARB; + COGL_PFNGLUNIFORM1IARBPROC pf_glUniform1iARB; + COGL_PFNGLUNIFORM2IARBPROC pf_glUniform2iARB; + COGL_PFNGLUNIFORM3IARBPROC pf_glUniform3iARB; + COGL_PFNGLUNIFORM4IARBPROC pf_glUniform4iARB; + COGL_PFNGLUNIFORM1IVARBPROC pf_glUniform1ivARB; + COGL_PFNGLUNIFORM2IVARBPROC pf_glUniform2ivARB; + COGL_PFNGLUNIFORM3IVARBPROC pf_glUniform3ivARB; + COGL_PFNGLUNIFORM4IVARBPROC pf_glUniform4ivARB; + COGL_PFNGLUNIFORMMATRIX2FVARBPROC pf_glUniformMatrix2fvARB; + COGL_PFNGLUNIFORMMATRIX3FVARBPROC pf_glUniformMatrix3fvARB; + COGL_PFNGLUNIFORMMATRIX4FVARBPROC pf_glUniformMatrix4fvARB; } CoglContext; CoglContext * diff --git a/gl/cogl-defines.h.in b/gl/cogl-defines.h.in index d33a8323b..31c75bbb2 100644 --- a/gl/cogl-defines.h.in +++ b/gl/cogl-defines.h.in @@ -837,11 +837,6 @@ typedef void GLenum pname, GLint *params); -typedef void - (APIENTRYP COGL_PFNGLUNIFORM1FARBPROC) - (GLint location, - GLfloat v0); - typedef void (APIENTRYP COGL_PFNGLVERTEXATTRIBPOINTERARBPROC) (GLuint index, @@ -897,6 +892,127 @@ typedef void (GLsizei n, const GLuint *buffers); +typedef void + (APIENTRYP COGL_PFNGLUNIFORM1FARBPROC) + (GLint location, + GLfloat v0); + +typedef void + (APIENTRYP COGL_PFNGLUNIFORM2FARBPROC) + (GLint location, + GLfloat v0, + GLfloat v1); + +typedef void + (APIENTRYP COGL_PFNGLUNIFORM3FARBPROC) + (GLint location, + GLfloat v0, + GLfloat v1, + GLfloat v2); + +typedef void + (APIENTRYP COGL_PFNGLUNIFORM4FARBPROC) + (GLint location, + GLfloat v0, + GLfloat v1, + GLfloat v2, + GLfloat v3); + +typedef void + (APIENTRYP COGL_PFNGLUNIFORM1FVARBPROC) + (GLint location, + GLsizei count, + const GLfloat * value); + +typedef void + (APIENTRYP COGL_PFNGLUNIFORM2FVARBPROC) + (GLint location, + GLsizei count, + const GLfloat * value); + +typedef void + (APIENTRYP COGL_PFNGLUNIFORM3FVARBPROC) + (GLint location, + GLsizei count, + const GLfloat * value); + +typedef void + (APIENTRYP COGL_PFNGLUNIFORM4FVARBPROC) + (GLint location, + GLsizei count, + const GLfloat * value); + +typedef void + (APIENTRYP COGL_PFNGLUNIFORM1IARBPROC) + (GLint location, + GLint v0); + +typedef void + (APIENTRYP COGL_PFNGLUNIFORM2IARBPROC) + (GLint location, + GLint v0, + GLint v1); + +typedef void + (APIENTRYP COGL_PFNGLUNIFORM3IARBPROC) + (GLint location, + GLint v0, + GLint v1, + GLint v2); + +typedef void + (APIENTRYP COGL_PFNGLUNIFORM4IARBPROC) + (GLint location, + GLint v0, + GLint v1, + GLint v2, + GLint v3); + +typedef void + (APIENTRYP COGL_PFNGLUNIFORM1IVARBPROC) + (GLint location, + GLsizei count, + const GLint * value); + +typedef void + (APIENTRYP COGL_PFNGLUNIFORM2IVARBPROC) + (GLint location, + GLsizei count, + const GLint * value); + +typedef void + (APIENTRYP COGL_PFNGLUNIFORM3IVARBPROC) + (GLint location, + GLsizei count, + const GLint * value); + +typedef void + (APIENTRYP COGL_PFNGLUNIFORM4IVARBPROC) + (GLint location, + GLsizei count, + const GLint * value); + +typedef void + (APIENTRYP COGL_PFNGLUNIFORMMATRIX2FVARBPROC) + (GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value); + +typedef void + (APIENTRYP COGL_PFNGLUNIFORMMATRIX3FVARBPROC) + (GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value); + +typedef void + (APIENTRYP COGL_PFNGLUNIFORMMATRIX4FVARBPROC) + (GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value); + G_END_DECLS #endif diff --git a/gl/cogl-program.c b/gl/cogl-program.c index 667137876..060e5bcd4 100644 --- a/gl/cogl-program.c +++ b/gl/cogl-program.c @@ -43,6 +43,24 @@ #define glLinkProgramARB ctx->pf_glLinkProgramARB #define glGetUniformLocationARB ctx->pf_glGetUniformLocationARB #define glUniform1fARB ctx->pf_glUniform1fARB +#define glUniform2fARB ctx->pf_glUniform2fARB +#define glUniform3fARB ctx->pf_glUniform3fARB +#define glUniform4fARB ctx->pf_glUniform4fARB +#define glUniform1fvARB ctx->pf_glUniform1fvARB +#define glUniform2fvARB ctx->pf_glUniform2fvARB +#define glUniform3fvARB ctx->pf_glUniform3fvARB +#define glUniform4fvARB ctx->pf_glUniform4fvARB +#define glUniform1iARB ctx->pf_glUniform1iARB +#define glUniform2iARB ctx->pf_glUniform2iARB +#define glUniform3iARB ctx->pf_glUniform3iARB +#define glUniform4iARB ctx->pf_glUniform4iARB +#define glUniform1ivARB ctx->pf_glUniform1ivARB +#define glUniform2ivARB ctx->pf_glUniform2ivARB +#define glUniform3ivARB ctx->pf_glUniform3ivARB +#define glUniform4ivARB ctx->pf_glUniform4ivARB +#define glUniformMatrix2fvARB ctx->pf_glUniformMatrix2fvARB +#define glUniformMatrix3fvARB ctx->pf_glUniformMatrix3fvARB +#define glUniformMatrix4fvARB ctx->pf_glUniformMatrix4fvARB #define glDeleteObjectARB ctx->pf_glDeleteObjectARB static void _cogl_program_free (CoglProgram *program); @@ -121,7 +139,7 @@ cogl_program_use (CoglHandle handle) { program = _cogl_program_pointer_from_handle (handle); gl_handle = program->gl_handle; - } + } glUseProgramObjectARB (gl_handle); } @@ -148,3 +166,82 @@ cogl_program_uniform_1f (COGLint uniform_no, _COGL_GET_CONTEXT (ctx, NO_RETVAL); glUniform1fARB (uniform_no, value); } + +void +cogl_program_uniform_float (COGLint uniform_no, + gint size, + gint count, + const GLfloat *value) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + switch (size) + { + case 1: + glUniform1fvARB (uniform_no, count, value); + break; + case 2: + glUniform2fvARB (uniform_no, count, value); + break; + case 3: + glUniform3fvARB (uniform_no, count, value); + break; + case 4: + glUniform4fvARB (uniform_no, count, value); + break; + default: + g_warning ("%s called with invalid size parameter", G_STRFUNC); + } +} + +void +cogl_program_uniform_int (COGLint uniform_no, + gint size, + gint count, + const COGLint *value) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + switch (size) + { + case 1: + glUniform1ivARB (uniform_no, count, value); + break; + case 2: + glUniform2ivARB (uniform_no, count, value); + break; + case 3: + glUniform3ivARB (uniform_no, count, value); + break; + case 4: + glUniform4ivARB (uniform_no, count, value); + break; + default: + g_warning ("%s called with invalid size parameter", G_STRFUNC); + } +} + +void +cogl_program_uniform_matrix (COGLint uniform_no, + gint size, + gint count, + gboolean transpose, + const GLfloat *value) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + switch (size) + { + case 2 : + glUniformMatrix2fvARB (uniform_no, count, transpose, value); + break; + case 3 : + glUniformMatrix3fvARB (uniform_no, count, transpose, value); + break; + case 4 : + glUniformMatrix4fvARB (uniform_no, count, transpose, value); + break; + default : + g_warning ("%s called with invalid size parameter", G_STRFUNC); + } +} diff --git a/gl/cogl.c b/gl/cogl.c index 8963e494e..a605c2e81 100644 --- a/gl/cogl.c +++ b/gl/cogl.c @@ -1028,6 +1028,78 @@ _cogl_features_init () (COGL_PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) cogl_get_proc_address ("glDisableVertexAttribArrayARB"); + ctx->pf_glUniform2fARB = + (COGL_PFNGLUNIFORM2FARBPROC) + cogl_get_proc_address ("glUniform2fARB"); + + ctx->pf_glUniform3fARB = + (COGL_PFNGLUNIFORM3FARBPROC) + cogl_get_proc_address ("glUniform3fARB"); + + ctx->pf_glUniform4fARB = + (COGL_PFNGLUNIFORM4FARBPROC) + cogl_get_proc_address ("glUniform4fARB"); + + ctx->pf_glUniform1fvARB = + (COGL_PFNGLUNIFORM1FVARBPROC) + cogl_get_proc_address ("glUniform1fvARB"); + + ctx->pf_glUniform2fvARB = + (COGL_PFNGLUNIFORM2FVARBPROC) + cogl_get_proc_address ("glUniform2fvARB"); + + ctx->pf_glUniform3fvARB = + (COGL_PFNGLUNIFORM3FVARBPROC) + cogl_get_proc_address ("glUniform3fvARB"); + + ctx->pf_glUniform4fvARB = + (COGL_PFNGLUNIFORM4FVARBPROC) + cogl_get_proc_address ("glUniform4fvARB"); + + ctx->pf_glUniform1iARB = + (COGL_PFNGLUNIFORM1IARBPROC) + cogl_get_proc_address ("glUniform1iARB"); + + ctx->pf_glUniform2iARB = + (COGL_PFNGLUNIFORM2IARBPROC) + cogl_get_proc_address ("glUniform2iARB"); + + ctx->pf_glUniform3iARB = + (COGL_PFNGLUNIFORM3IARBPROC) + cogl_get_proc_address ("glUniform3iARB"); + + ctx->pf_glUniform4iARB = + (COGL_PFNGLUNIFORM4IARBPROC) + cogl_get_proc_address ("glUniform4iARB"); + + ctx->pf_glUniform1ivARB = + (COGL_PFNGLUNIFORM1IVARBPROC) + cogl_get_proc_address ("glUniform1ivARB"); + + ctx->pf_glUniform2ivARB = + (COGL_PFNGLUNIFORM2IVARBPROC) + cogl_get_proc_address ("glUniform2ivARB"); + + ctx->pf_glUniform3ivARB = + (COGL_PFNGLUNIFORM3IVARBPROC) + cogl_get_proc_address ("glUniform3ivARB"); + + ctx->pf_glUniform4ivARB = + (COGL_PFNGLUNIFORM4IVARBPROC) + cogl_get_proc_address ("glUniform4ivARB"); + + ctx->pf_glUniformMatrix2fvARB = + (COGL_PFNGLUNIFORMMATRIX2FVARBPROC) + cogl_get_proc_address ("glUniformMatrix2fvARB"); + + ctx->pf_glUniformMatrix3fvARB = + (COGL_PFNGLUNIFORMMATRIX3FVARBPROC) + cogl_get_proc_address ("glUniformMatrix3fvARB"); + + ctx->pf_glUniformMatrix4fvARB = + (COGL_PFNGLUNIFORMMATRIX4FVARBPROC) + cogl_get_proc_address ("glUniformMatrix4fvARB"); + if (ctx->pf_glCreateProgramObjectARB && ctx->pf_glCreateShaderObjectARB && ctx->pf_glShaderSourceARB && @@ -1039,14 +1111,31 @@ _cogl_features_init () ctx->pf_glDeleteObjectARB && ctx->pf_glGetInfoLogARB && ctx->pf_glGetObjectParameterivARB && - ctx->pf_glUniform1fARB && + ctx->pf_glUniform1fARB && + ctx->pf_glUniform2fARB && + ctx->pf_glUniform3fARB && + ctx->pf_glUniform4fARB && + ctx->pf_glUniform1fvARB && + ctx->pf_glUniform2fvARB && + ctx->pf_glUniform3fvARB && + ctx->pf_glUniform4fvARB && + ctx->pf_glUniform1iARB && + ctx->pf_glUniform2iARB && + ctx->pf_glUniform3iARB && + ctx->pf_glUniform4iARB && + ctx->pf_glUniform1ivARB && + ctx->pf_glUniform2ivARB && + ctx->pf_glUniform3ivARB && + ctx->pf_glUniform4ivARB && + ctx->pf_glUniformMatrix2fvARB && + ctx->pf_glUniformMatrix3fvARB && + ctx->pf_glUniformMatrix4fvARB && ctx->pf_glVertexAttribPointerARB && ctx->pf_glEnableVertexAttribArrayARB && ctx->pf_glDisableVertexAttribArrayARB) flags |= COGL_FEATURE_SHADERS_GLSL; } - if (cogl_check_extension ("GL_EXT_framebuffer_object", gl_extensions) || cogl_check_extension ("GL_ARB_framebuffer_object", gl_extensions)) { diff --git a/gles/cogl-gles2-wrapper.c b/gles/cogl-gles2-wrapper.c index 25e3896a2..fea76500e 100644 --- a/gles/cogl-gles2-wrapper.c +++ b/gles/cogl-gles2-wrapper.c @@ -462,6 +462,7 @@ void cogl_gles2_wrapper_deinit (CoglGles2Wrapper *wrapper) { GSList *node, *next; + int i; for (node = wrapper->compiled_programs; node; node = next) { @@ -486,6 +487,10 @@ cogl_gles2_wrapper_deinit (CoglGles2Wrapper *wrapper) g_slist_free1 (node); } wrapper->compiled_fragment_shaders = NULL; + + for (i = 0; i < COGL_GLES2_NUM_CUSTOM_UNIFORMS; i++) + if (wrapper->custom_uniforms[i].count > 1) + g_free (wrapper->custom_uniforms[i].v.array); } void @@ -814,6 +819,78 @@ cogl_wrap_glNormalPointer (GLenum type, GLsizei stride, const GLvoid *pointer) GL_FALSE, stride, pointer); } +static void +cogl_gles2_do_set_uniform (GLint location, CoglBoxedValue *value) +{ + switch (value->type) + { + case COGL_BOXED_NONE: + break; + + case COGL_BOXED_INT: + { + gint *ptr; + + if (value->count == 1) + ptr = value->v.int_value; + else + ptr = value->v.int_array; + + switch (value->size) + { + case 1: glUniform1iv (location, value->count, ptr); break; + case 2: glUniform2iv (location, value->count, ptr); break; + case 3: glUniform3iv (location, value->count, ptr); break; + case 4: glUniform4iv (location, value->count, ptr); break; + } + } + break; + + case COGL_BOXED_FLOAT: + { + gfloat *ptr; + + if (value->count == 1) + ptr = value->v.float_value; + else + ptr = value->v.float_array; + + switch (value->size) + { + case 1: glUniform1fv (location, value->count, ptr); break; + case 2: glUniform2fv (location, value->count, ptr); break; + case 3: glUniform3fv (location, value->count, ptr); break; + case 4: glUniform4fv (location, value->count, ptr); break; + } + } + break; + + case COGL_BOXED_MATRIX: + { + gfloat *ptr; + + if (value->count == 1) + ptr = value->v.matrix; + else + ptr = value->v.float_array; + + switch (value->size) + { + case 2: + glUniformMatrix2fv (location, value->count, value->transpose, ptr); + break; + case 3: + glUniformMatrix3fv (location, value->count, value->transpose, ptr); + break; + case 4: + glUniformMatrix4fv (location, value->count, value->transpose, ptr); + break; + } + } + break; + } +} + void cogl_wrap_glDrawArrays (GLenum mode, GLint first, GLsizei count) { @@ -914,8 +991,8 @@ cogl_wrap_glDrawArrays (GLenum mode, GLint first, GLsizei count) program->custom_uniforms[i] = glGetUniformLocation (program->program, uniform_name); if (program->custom_uniforms[i] >= 0) - glUniform1f (program->custom_uniforms[i], - w->custom_uniforms[i]); + cogl_gles2_do_set_uniform (program->custom_uniforms[i], + &w->custom_uniforms[i]); } } diff --git a/gles/cogl-gles2-wrapper.h b/gles/cogl-gles2-wrapper.h index 19b062088..ddf181e92 100644 --- a/gles/cogl-gles2-wrapper.h +++ b/gles/cogl-gles2-wrapper.h @@ -26,6 +26,8 @@ #ifndef __COGL_GLES2_WRAPPER_H__ #define __COGL_GLES2_WRAPPER_H__ +#include "cogl-internal.h" + G_BEGIN_DECLS #ifdef HAVE_COGL_GLES2 @@ -131,7 +133,7 @@ struct _CoglGles2Wrapper GLfloat fog_start; GLfloat fog_end; GLfloat fog_color[4]; - GLfloat custom_uniforms[COGL_GLES2_NUM_CUSTOM_UNIFORMS]; + CoglBoxedValue custom_uniforms[COGL_GLES2_NUM_CUSTOM_UNIFORMS]; }; struct _CoglGles2WrapperProgram diff --git a/gles/cogl-internal.h b/gles/cogl-internal.h index 9275f4ba0..8ca926ece 100644 --- a/gles/cogl-internal.h +++ b/gles/cogl-internal.h @@ -26,6 +26,30 @@ #ifndef __COGL_INTERNAL_H #define __COGL_INTERNAL_H +typedef enum { + COGL_BOXED_NONE, + COGL_BOXED_INT, + COGL_BOXED_FLOAT, + COGL_BOXED_MATRIX +} CoglBoxedType; + +typedef struct _CoglBoxedValue +{ + CoglBoxedType type; + int size, count; + gboolean transpose; + + union { + gfloat float_value[4]; + gint int_value[4]; + gfloat matrix[16]; + gfloat *float_array; + gint *int_array; + gpointer array; + } v; +} CoglBoxedValue; + + #define COGL_DEBUG 0 #if COGL_DEBUG diff --git a/gles/cogl-program.c b/gles/cogl-program.c index 36ac6d509..c550df453 100644 --- a/gles/cogl-program.c +++ b/gles/cogl-program.c @@ -162,16 +162,95 @@ cogl_program_get_uniform_location (CoglHandle handle, void cogl_program_uniform_1f (COGLint uniform_no, gfloat value) +{ + cogl_program_uniform_float (uniform_no, 1, 1, &value); +} + +static void +cogl_program_uniform_x (COGLint uniform_no, + gint size, + gint count, + CoglBoxedType type, + size_t value_size, + gconstpointer value) { _COGL_GET_CONTEXT (ctx, NO_RETVAL); - if (uniform_no >= 0 && uniform_no < COGL_GLES2_NUM_CUSTOM_UNIFORMS) + if (uniform_no >= 0 && uniform_no < COGL_GLES2_NUM_CUSTOM_UNIFORMS + && size >= 1 && size <= 4 && count >= 1) { - ctx->gles2.custom_uniforms[uniform_no] = value; + CoglBoxedValue *bv = ctx->gles2.custom_uniforms + uniform_no; + + if (count == 1) + { + if (bv->count > 1) + g_free (bv->v.array); + + memcpy (bv->v.float_value, value, value_size); + } + else + { + if (bv->count > 1) + { + if (bv->count != count || bv->size != size || bv->type != type) + { + g_free (bv->v.array); + bv->v.array = g_malloc (count * value_size); + } + } + else + bv->v.array = g_malloc (count * value_size); + + memcpy (bv->v.array, value, count * value_size); + } + + bv->type = type; + bv->size = size; + bv->count = count; + ctx->gles2.dirty_custom_uniforms |= 1 << uniform_no; } } +void +cogl_program_uniform_float (COGLint uniform_no, + gint size, + gint count, + const GLfloat *value) +{ + cogl_program_uniform_x (uniform_no, size, count, COGL_BOXED_FLOAT, + sizeof (float) * size, value); +} + +void +cogl_program_uniform_int (COGLint uniform_no, + gint size, + gint count, + const GLint *value) +{ + cogl_program_uniform_x (uniform_no, size, count, COGL_BOXED_INT, + sizeof (gint) * size, value); +} + +void +cogl_program_uniform_matrix (COGLint uniform_no, + gint size, + gint count, + gboolean transpose, + const GLfloat *value) +{ + CoglBoxedValue *bv; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + bv = ctx->gles2.custom_uniforms + uniform_no; + + cogl_program_uniform_x (uniform_no, size, count, COGL_BOXED_MATRIX, + sizeof (float) * size * size, value); + + bv->transpose = transpose; +} + #else /* HAVE_COGL_GLES2 */ /* No support on regular OpenGL 1.1 */ @@ -228,4 +307,30 @@ cogl_program_uniform_1f (COGLint uniform_no, { } +void +cogl_program_uniform_float (COGLint uniform_no, + gint size, + gint count, + const GLfloat *value) +{ +} + +void +cogl_program_uniform_int (COGLint uniform_no, + gint size, + gint count, + const COGLint *value) +{ +} + +void +cogl_program_uniform_matrix (COGLint uniform_no, + gint size, + gint count, + gboolean transpose, + const GLfloat *value) +{ +} + + #endif /* HAVE_COGL_GLES2 */