diff --git a/cogl/Makefile.am b/cogl/Makefile.am index ae02d86c0..8f3acfb45 100644 --- a/cogl/Makefile.am +++ b/cogl/Makefile.am @@ -327,6 +327,8 @@ cogl_sources_c = \ $(srcdir)/winsys/cogl-winsys-stub.c \ $(srcdir)/cogl-config-private.h \ $(srcdir)/cogl-config.c \ + $(srcdir)/cogl-boxed-value.h \ + $(srcdir)/cogl-boxed-value.c \ $(NULL) if SUPPORT_XLIB diff --git a/cogl/cogl-boxed-value.c b/cogl/cogl-boxed-value.c new file mode 100644 index 000000000..ec1d4d5fa --- /dev/null +++ b/cogl/cogl-boxed-value.c @@ -0,0 +1,286 @@ +/* + * Cogl + * + * An object oriented GL/GLES Abstraction/Utility Layer + * + * Copyright (C) 2011 Intel Corporation. + * + * 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, see . + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "cogl-boxed-value.h" +#include "cogl-context-private.h" + +gboolean +_cogl_boxed_value_equal (const CoglBoxedValue *bva, + const CoglBoxedValue *bvb) +{ + const void *pa, *pb; + + if (bva->type != bvb->type) + return FALSE; + + switch (bva->type) + { + case COGL_BOXED_NONE: + return TRUE; + + case COGL_BOXED_INT: + if (bva->size != bvb->size || bva->count != bvb->count) + return FALSE; + + if (bva->count == 1) + { + pa = bva->v.int_value; + pb = bvb->v.int_value; + } + else + { + pa = bva->v.int_array; + pb = bvb->v.int_array; + } + + return !memcmp (pa, pb, sizeof (int) * bva->size * bva->count); + + case COGL_BOXED_FLOAT: + if (bva->size != bvb->size || bva->count != bvb->count) + return FALSE; + + if (bva->count == 1) + { + pa = bva->v.float_value; + pb = bvb->v.float_value; + } + else + { + pa = bva->v.float_array; + pb = bvb->v.float_array; + } + + return !memcmp (pa, pb, sizeof (float) * bva->size * bva->count); + + case COGL_BOXED_MATRIX: + if (bva->size != bvb->size || + bva->count != bvb->count || + bva->transpose != bvb->transpose) + return FALSE; + + if (bva->count == 1) + { + pa = bva->v.matrix; + pb = bvb->v.matrix; + } + else + { + pa = bva->v.array; + pb = bvb->v.array; + } + + return !memcmp (pa, pb, + sizeof (float) * bva->size * bva->size * bva->count); + } + + g_warn_if_reached (); + + return FALSE; +} + +static void +_cogl_boxed_value_set_x (CoglBoxedValue *bv, + int size, + int count, + CoglBoxedType type, + gsize value_size, + gconstpointer value, + gboolean transpose) +{ + 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; + bv->transpose = transpose; +} + +void +_cogl_boxed_value_set_1f (CoglBoxedValue *bv, + float value) +{ + _cogl_boxed_value_set_x (bv, + 1, 1, COGL_BOXED_FLOAT, + sizeof (float), &value, FALSE); +} + +void +_cogl_boxed_value_set_1i (CoglBoxedValue *bv, + int value) +{ + _cogl_boxed_value_set_x (bv, + 1, 1, COGL_BOXED_INT, + sizeof (int), &value, FALSE); +} + +void +_cogl_boxed_value_set_float (CoglBoxedValue *bv, + int n_components, + int count, + const float *value) +{ + _cogl_boxed_value_set_x (bv, + n_components, count, + COGL_BOXED_FLOAT, + sizeof (float) * n_components, value, FALSE); +} + +void +_cogl_boxed_value_set_int (CoglBoxedValue *bv, + int n_components, + int count, + const int *value) +{ + _cogl_boxed_value_set_x (bv, + n_components, count, + COGL_BOXED_INT, + sizeof (int) * n_components, value, FALSE); +} + +void +_cogl_boxed_value_set_matrix (CoglBoxedValue *bv, + int dimensions, + int count, + gboolean transpose, + const float *value) +{ + _cogl_boxed_value_set_x (bv, + dimensions, count, + COGL_BOXED_MATRIX, + sizeof (float) * dimensions * dimensions, + value, + transpose); +} + +void +_cogl_boxed_value_destroy (CoglBoxedValue *bv) +{ + if (bv->count > 1) + g_free (bv->v.array); +} + +void +_cogl_boxed_value_set_uniform (CoglContext *ctx, + GLint location, + const CoglBoxedValue *value) +{ + switch (value->type) + { + case COGL_BOXED_NONE: + break; + + case COGL_BOXED_INT: + { + const int *ptr; + + if (value->count == 1) + ptr = value->v.int_value; + else + ptr = value->v.int_array; + + switch (value->size) + { + case 1: ctx->glUniform1iv (location, value->count, ptr); break; + case 2: ctx->glUniform2iv (location, value->count, ptr); break; + case 3: ctx->glUniform3iv (location, value->count, ptr); break; + case 4: ctx->glUniform4iv (location, value->count, ptr); break; + } + } + break; + + case COGL_BOXED_FLOAT: + { + const float *ptr; + + if (value->count == 1) + ptr = value->v.float_value; + else + ptr = value->v.float_array; + + switch (value->size) + { + case 1: ctx->glUniform1fv (location, value->count, ptr); break; + case 2: ctx->glUniform2fv (location, value->count, ptr); break; + case 3: ctx->glUniform3fv (location, value->count, ptr); break; + case 4: ctx->glUniform4fv (location, value->count, ptr); break; + } + } + break; + + case COGL_BOXED_MATRIX: + { + const float *ptr; + + if (value->count == 1) + ptr = value->v.matrix; + else + ptr = value->v.float_array; + + switch (value->size) + { + case 2: + ctx->glUniformMatrix2fv (location, value->count, + value->transpose, ptr); + break; + case 3: + ctx->glUniformMatrix3fv (location, value->count, + value->transpose, ptr); + break; + case 4: + ctx->glUniformMatrix4fv (location, value->count, + value->transpose, ptr); + break; + } + } + break; + } +} diff --git a/cogl/cogl-boxed-value.h b/cogl/cogl-boxed-value.h new file mode 100644 index 000000000..dada36f27 --- /dev/null +++ b/cogl/cogl-boxed-value.h @@ -0,0 +1,100 @@ +/* + * Cogl + * + * An object oriented GL/GLES Abstraction/Utility Layer + * + * Copyright (C) 2011 Intel Corporation. + * + * 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, see . + * + * + */ + +#ifndef __COGL_BOXED_VALUE_H +#define __COGL_BOXED_VALUE_H + +#include + +#include "cogl-context.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 { + float float_value[4]; + int int_value[4]; + float matrix[16]; + float *float_array; + int *int_array; + void *array; + } v; +} CoglBoxedValue; + +#define _cogl_boxed_value_init(bv) \ + G_STMT_START { \ + CoglBoxedValue *_bv = (bv); \ + _bv->type = COGL_BOXED_NONE; \ + _bv->count = 1; \ + } G_STMT_END + +gboolean +_cogl_boxed_value_equal (const CoglBoxedValue *bva, + const CoglBoxedValue *bvb); + +void +_cogl_boxed_value_set_1f (CoglBoxedValue *bv, + float value); + +void +_cogl_boxed_value_set_1i (CoglBoxedValue *bv, + int value); + +void +_cogl_boxed_value_set_float (CoglBoxedValue *bv, + int n_components, + int count, + const float *value); + +void +_cogl_boxed_value_set_int (CoglBoxedValue *bv, + int n_components, + int count, + const int *value); + +void +_cogl_boxed_value_set_matrix (CoglBoxedValue *bv, + int dimensions, + int count, + gboolean transpose, + const float *value); + +void +_cogl_boxed_value_destroy (CoglBoxedValue *bv); + +void +_cogl_boxed_value_set_uniform (CoglContext *ctx, + int location, + const CoglBoxedValue *value); + +#endif /* __COGL_BOXED_VALUE_H */ diff --git a/cogl/cogl-internal.h b/cogl/cogl-internal.h index 946f8bca7..6d0013756 100644 --- a/cogl/cogl-internal.h +++ b/cogl/cogl-internal.h @@ -32,29 +32,6 @@ #include #endif -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 { - float float_value[4]; - int int_value[4]; - float matrix[16]; - float *float_array; - int *int_array; - void *array; - } v; -} CoglBoxedValue; - #ifdef COGL_GL_DEBUG const char * diff --git a/cogl/cogl-pipeline-private.h b/cogl/cogl-pipeline-private.h index 4d0453644..5b07e5efe 100644 --- a/cogl/cogl-pipeline-private.h +++ b/cogl/cogl-pipeline-private.h @@ -36,6 +36,7 @@ #include "cogl-profile.h" #include "cogl-queue.h" #include "cogl-internal.h" +#include "cogl-boxed-value.h" #include diff --git a/cogl/cogl-program.c b/cogl/cogl-program.c index 316b16425..d0fb6f084 100644 --- a/cogl/cogl-program.c +++ b/cogl/cogl-program.c @@ -189,71 +189,34 @@ cogl_program_get_uniform_location (CoglHandle handle, return program->custom_uniforms->len - 1; } -static void -cogl_program_uniform_x (CoglHandle handle, - int uniform_no, - int size, - int count, - CoglBoxedType type, - gsize value_size, - gconstpointer value, - gboolean transpose) +static CoglProgramUniform * +cogl_program_modify_uniform (CoglProgram *program, + int uniform_no) { - CoglProgram *program = handle; + CoglProgramUniform *uniform; - _COGL_GET_CONTEXT (ctx, NO_RETVAL); + _COGL_RETURN_VAL_IF_FAIL (cogl_is_program (program), NULL); + _COGL_RETURN_VAL_IF_FAIL (uniform_no >= 0 && + uniform_no < program->custom_uniforms->len, + NULL); - _COGL_RETURN_IF_FAIL (cogl_is_program (handle)); - _COGL_RETURN_IF_FAIL (program != NULL); + uniform = &g_array_index (program->custom_uniforms, + CoglProgramUniform, uniform_no); + uniform->dirty = TRUE; - if (uniform_no >= 0 && uniform_no < program->custom_uniforms->len && - size >= 1 && size <= 4 && count >= 1) - { - CoglProgramUniform *uniform = - &g_array_index (program->custom_uniforms, - CoglProgramUniform, uniform_no); - - if (count == 1) - { - if (uniform->value.count > 1) - g_free (uniform->value.v.array); - - memcpy (uniform->value.v.float_value, value, value_size); - } - else - { - if (uniform->value.count > 1) - { - if (uniform->value.count != count || - uniform->value.size != size || - uniform->value.type != type) - { - g_free (uniform->value.v.array); - uniform->value.v.array = g_malloc (count * value_size); - } - } - else - uniform->value.v.array = g_malloc (count * value_size); - - memcpy (uniform->value.v.array, value, count * value_size); - } - - uniform->value.type = type; - uniform->value.size = size; - uniform->value.count = count; - uniform->value.transpose = transpose; - uniform->dirty = TRUE; - } + return uniform; } void cogl_program_uniform_1f (int uniform_no, float value) { + CoglProgramUniform *uniform; + _COGL_GET_CONTEXT (ctx, NO_RETVAL); - cogl_program_uniform_x (ctx->current_program, - uniform_no, 1, 1, COGL_BOXED_FLOAT, - sizeof (float), &value, FALSE); + + uniform = cogl_program_modify_uniform (ctx->current_program, uniform_no); + _cogl_boxed_value_set_1f (&uniform->value, value); } void @@ -261,19 +224,22 @@ cogl_program_set_uniform_1f (CoglHandle handle, int uniform_location, float value) { - cogl_program_uniform_x (handle, - uniform_location, 1, 1, COGL_BOXED_FLOAT, - sizeof (float), &value, FALSE); + CoglProgramUniform *uniform; + + uniform = cogl_program_modify_uniform (handle, uniform_location); + _cogl_boxed_value_set_1f (&uniform->value, value); } void cogl_program_uniform_1i (int uniform_no, int value) { + CoglProgramUniform *uniform; + _COGL_GET_CONTEXT (ctx, NO_RETVAL); - cogl_program_uniform_x (ctx->current_program, - uniform_no, 1, 1, COGL_BOXED_INT, - sizeof (int), &value, FALSE); + + uniform = cogl_program_modify_uniform (ctx->current_program, uniform_no); + _cogl_boxed_value_set_1i (&uniform->value, value); } void @@ -281,21 +247,24 @@ cogl_program_set_uniform_1i (CoglHandle handle, int uniform_location, int value) { - cogl_program_uniform_x (handle, - uniform_location, 1, 1, COGL_BOXED_INT, - sizeof (int), &value, FALSE); + CoglProgramUniform *uniform; + + uniform = cogl_program_modify_uniform (handle, uniform_location); + _cogl_boxed_value_set_1i (&uniform->value, value); } void cogl_program_uniform_float (int uniform_no, int size, int count, - const GLfloat *value) + const float *value) { + CoglProgramUniform *uniform; + _COGL_GET_CONTEXT (ctx, NO_RETVAL); - cogl_program_uniform_x (ctx->current_program, - uniform_no, size, count, COGL_BOXED_FLOAT, - sizeof (float) * size, value, FALSE); + + uniform = cogl_program_modify_uniform (ctx->current_program, uniform_no); + _cogl_boxed_value_set_float (&uniform->value, size, count, value); } void @@ -305,22 +274,24 @@ cogl_program_set_uniform_float (CoglHandle handle, int count, const float *value) { - cogl_program_uniform_x (handle, - uniform_location, n_components, count, - COGL_BOXED_FLOAT, - sizeof (float) * n_components, value, FALSE); + CoglProgramUniform *uniform; + + uniform = cogl_program_modify_uniform (handle, uniform_location); + _cogl_boxed_value_set_float (&uniform->value, n_components, count, value); } void cogl_program_uniform_int (int uniform_no, int size, int count, - const GLint *value) + const int *value) { + CoglProgramUniform *uniform; + _COGL_GET_CONTEXT (ctx, NO_RETVAL); - cogl_program_uniform_x (ctx->current_program, - uniform_no, size, count, COGL_BOXED_INT, - sizeof (int) * size, value, FALSE); + + uniform = cogl_program_modify_uniform (ctx->current_program, uniform_no); + _cogl_boxed_value_set_int (&uniform->value, size, count, value); } void @@ -330,10 +301,10 @@ cogl_program_set_uniform_int (CoglHandle handle, int count, const int *value) { - cogl_program_uniform_x (handle, - uniform_location, n_components, count, - COGL_BOXED_INT, - sizeof (int) * n_components, value, FALSE); + CoglProgramUniform *uniform; + + uniform = cogl_program_modify_uniform (handle, uniform_location); + _cogl_boxed_value_set_int (&uniform->value, n_components, count, value); } void @@ -344,14 +315,14 @@ cogl_program_set_uniform_matrix (CoglHandle handle, gboolean transpose, const float *value) { - _COGL_RETURN_IF_FAIL (cogl_is_program (handle)); + CoglProgramUniform *uniform; - cogl_program_uniform_x (handle, - uniform_location, dimensions, count, - COGL_BOXED_MATRIX, - sizeof (float) * dimensions * dimensions, - value, - transpose); + uniform = cogl_program_modify_uniform (handle, uniform_location); + _cogl_boxed_value_set_matrix (&uniform->value, + dimensions, + count, + transpose, + value); } void @@ -361,9 +332,12 @@ cogl_program_uniform_matrix (int uniform_no, gboolean transpose, const float *value) { + CoglProgramUniform *uniform; + _COGL_GET_CONTEXT (ctx, NO_RETVAL); - cogl_program_set_uniform_matrix (ctx->current_program, - uniform_no, size, count, transpose, value); + + uniform = cogl_program_modify_uniform (ctx->current_program, uniform_no); + _cogl_boxed_value_set_matrix (&uniform->value, size, count, transpose, value); } /* ARBfp local parameters can be referenced like: @@ -398,84 +372,6 @@ get_local_param_index (const char *uniform_name) return _index; } -static void -_cogl_program_flush_uniform_glsl (GLint location, - CoglBoxedValue *value) -{ - _COGL_GET_CONTEXT (ctx, NO_RETVAL); - - switch (value->type) - { - case COGL_BOXED_NONE: - break; - - case COGL_BOXED_INT: - { - int *ptr; - - if (value->count == 1) - ptr = value->v.int_value; - else - ptr = value->v.int_array; - - switch (value->size) - { - case 1: ctx->glUniform1iv (location, value->count, ptr); break; - case 2: ctx->glUniform2iv (location, value->count, ptr); break; - case 3: ctx->glUniform3iv (location, value->count, ptr); break; - case 4: ctx->glUniform4iv (location, value->count, ptr); break; - } - } - break; - - case COGL_BOXED_FLOAT: - { - float *ptr; - - if (value->count == 1) - ptr = value->v.float_value; - else - ptr = value->v.float_array; - - switch (value->size) - { - case 1: ctx->glUniform1fv (location, value->count, ptr); break; - case 2: ctx->glUniform2fv (location, value->count, ptr); break; - case 3: ctx->glUniform3fv (location, value->count, ptr); break; - case 4: ctx->glUniform4fv (location, value->count, ptr); break; - } - } - break; - - case COGL_BOXED_MATRIX: - { - float *ptr; - - if (value->count == 1) - ptr = value->v.matrix; - else - ptr = value->v.float_array; - - switch (value->size) - { - case 2: - ctx->glUniformMatrix2fv (location, value->count, - value->transpose, ptr); - break; - case 3: - ctx->glUniformMatrix3fv (location, value->count, - value->transpose, ptr); - break; - case 4: - ctx->glUniformMatrix4fv (location, value->count, - value->transpose, ptr); - break; - } - } - break; - } -} - #ifdef HAVE_COGL_GL static void @@ -536,8 +432,9 @@ _cogl_program_flush_uniforms (CoglProgram *program, switch (_cogl_program_get_language (program)) { case COGL_SHADER_LANGUAGE_GLSL: - _cogl_program_flush_uniform_glsl (uniform->location, - &uniform->value); + _cogl_boxed_value_set_uniform (ctx, + uniform->location, + &uniform->value); break; case COGL_SHADER_LANGUAGE_ARBFP: