gles2: Have CoglProgram track uniforms per program

Previously custom uniforms were tracked in _CoglGles2Wrapper but as part
of a process to consolidate the gl/gles2 shader code it seems to make
sense for this state to be tracked in the CoglProgram object instead.

http://bugzilla.o-hand.com/show_bug.cgi?id=2179
This commit is contained in:
Robert Bragg 2010-06-08 23:06:50 +01:00
parent c26f4ffa22
commit 4a9321b60c
4 changed files with 61 additions and 40 deletions

View File

@ -930,8 +930,8 @@ cogl_gles2_wrapper_get_program (const CoglGles2WrapperSettings *settings)
/* We haven't tried to get a location for any of the custom uniforms
yet */
for (i = 0; i < COGL_GLES2_NUM_CUSTOM_UNIFORMS; i++)
program->custom_uniforms[i] = COGL_GLES2_UNBOUND_CUSTOM_UNIFORM;
for (i = 0; i < COGL_PROGRAM_NUM_CUSTOM_UNIFORMS; i++)
program->custom_gl_uniforms[i] = COGL_PROGRAM_UNBOUND_CUSTOM_UNIFORM;
w->compiled_programs = g_slist_append (w->compiled_programs, program);
@ -942,7 +942,6 @@ void
_cogl_gles2_wrapper_deinit (CoglGles2Wrapper *wrapper)
{
GSList *node, *next;
int i;
for (node = wrapper->compiled_programs; node; node = next)
{
@ -967,10 +966,6 @@ _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);
}
static void
@ -1180,6 +1175,7 @@ static void
_cogl_wrap_prepare_for_draw (void)
{
CoglGles2WrapperProgram *program;
guint32 dirty_custom_uniforms = 0;
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
@ -1200,12 +1196,18 @@ _cogl_wrap_prepare_for_draw (void)
w->current_program = program;
/* All of the uniforms are probably now out of date */
w->dirty_uniforms = COGL_GLES2_DIRTY_ALL;
w->dirty_custom_uniforms = (1 << COGL_GLES2_NUM_CUSTOM_UNIFORMS) - 1;
dirty_custom_uniforms = (1 << COGL_PROGRAM_NUM_CUSTOM_UNIFORMS) - 1;
}
w->settings_dirty = FALSE;
}
else
program = w->current_program;
{
CoglProgram *user_program =
_cogl_program_pointer_from_handle (w->settings.user_program);
if (user_program)
dirty_custom_uniforms = user_program->dirty_custom_uniforms;
program = w->current_program;
}
/* Make sure all of the uniforms are up to date */
if (w->dirty_uniforms)
@ -1284,7 +1286,7 @@ _cogl_wrap_prepare_for_draw (void)
w->dirty_uniforms = 0;
}
if (w->dirty_custom_uniforms)
if (dirty_custom_uniforms)
{
int i;
@ -1294,21 +1296,20 @@ _cogl_wrap_prepare_for_draw (void)
= _cogl_program_pointer_from_handle (w->settings.user_program);
const char *uniform_name;
for (i = 0; i < COGL_GLES2_NUM_CUSTOM_UNIFORMS; i++)
if ((w->dirty_custom_uniforms & (1 << i))
for (i = 0; i < COGL_PROGRAM_NUM_CUSTOM_UNIFORMS; i++)
if ((dirty_custom_uniforms & (1 << i))
&& (uniform_name = user_program->custom_uniform_names[i]))
{
if (program->custom_uniforms[i]
== COGL_GLES2_UNBOUND_CUSTOM_UNIFORM)
program->custom_uniforms[i]
if (program->custom_gl_uniforms[i]
== COGL_PROGRAM_UNBOUND_CUSTOM_UNIFORM)
program->custom_gl_uniforms[i]
= glGetUniformLocation (program->program, uniform_name);
if (program->custom_uniforms[i] >= 0)
cogl_gles2_do_set_uniform (program->custom_uniforms[i],
&w->custom_uniforms[i]);
if (program->custom_gl_uniforms[i] >= 0)
cogl_gles2_do_set_uniform (program->custom_gl_uniforms[i],
&user_program->custom_uniforms[i]);
}
user_program->dirty_custom_uniforms = 0;
}
w->dirty_custom_uniforms = 0;
}
if (w->dirty_attribute_pointers

View File

@ -26,6 +26,7 @@
#include "cogl.h" /* needed for gl header include */
#include "cogl-internal.h"
#include "cogl-program.h"
G_BEGIN_DECLS
@ -44,9 +45,6 @@ typedef struct _CoglGles2WrapperSettings CoglGles2WrapperSettings;
typedef struct _CoglGles2WrapperProgram CoglGles2WrapperProgram;
typedef struct _CoglGles2WrapperShader CoglGles2WrapperShader;
#define COGL_GLES2_NUM_CUSTOM_UNIFORMS 16
#define COGL_GLES2_UNBOUND_CUSTOM_UNIFORM -2
/* Must be a power of two */
#define COGL_GLES2_MODELVIEW_STACK_SIZE 32
#define COGL_GLES2_PROJECTION_STACK_SIZE 2
@ -190,7 +188,7 @@ struct _CoglGles2Wrapper
/* Whether the settings have changed since the last draw */
gboolean settings_dirty;
/* Uniforms that have changed since the last draw */
int dirty_uniforms, dirty_custom_uniforms;
int dirty_uniforms;
/* Attribute pointers that have changed since the last draw */
int dirty_attribute_pointers;
@ -214,13 +212,14 @@ struct _CoglGles2Wrapper
GLfloat fog_end;
GLfloat fog_color[4];
GLfloat point_size;
CoglBoxedValue custom_uniforms[COGL_GLES2_NUM_CUSTOM_UNIFORMS];
};
struct _CoglGles2WrapperProgram
{
GLuint program;
CoglProgram *user_program;
/* The settings that were used to generate this combination */
CoglGles2WrapperSettings settings;
@ -230,7 +229,7 @@ struct _CoglGles2WrapperProgram
/* The uniforms for this program */
CoglGles2WrapperUniforms uniforms;
GLint custom_uniforms[COGL_GLES2_NUM_CUSTOM_UNIFORMS];
GLint custom_gl_uniforms[COGL_PROGRAM_NUM_CUSTOM_UNIFORMS];
};
struct _CoglGles2WrapperShader

View File

@ -63,9 +63,13 @@ _cogl_program_free (CoglProgram *program)
ctx->drv.gles2.settings_dirty = TRUE;
}
for (i = 0; i < COGL_GLES2_NUM_CUSTOM_UNIFORMS; i++)
if (program->custom_uniform_names[i])
g_free (program->custom_uniform_names[i]);
for (i = 0; i < COGL_PROGRAM_NUM_CUSTOM_UNIFORMS; i++)
{
if (program->custom_uniform_names[i])
g_free (program->custom_uniform_names[i]);
if (program->custom_uniforms[i].count > 1)
g_free (program->custom_uniforms[i].v.array);
}
g_slice_free (CoglProgram, program);
}
@ -75,10 +79,7 @@ cogl_create_program (void)
{
CoglProgram *program;
program = g_slice_new (CoglProgram);
program->attached_shaders = NULL;
memset (program->custom_uniform_names, 0,
COGL_GLES2_NUM_CUSTOM_UNIFORMS * sizeof (char *));
program = g_slice_new0 (CoglProgram);
return _cogl_program_handle_new (program);
}
@ -153,11 +154,11 @@ cogl_program_get_uniform_location (CoglHandle handle,
with a new fixed functionality shader. Instead we make our own
mapping of uniform numbers and cache the names */
for (i = 0; program->custom_uniform_names[i]
&& i < COGL_GLES2_NUM_CUSTOM_UNIFORMS; i++)
&& i < COGL_PROGRAM_NUM_CUSTOM_UNIFORMS; i++)
if (!strcmp (program->custom_uniform_names[i], uniform_name))
return i;
if (i < COGL_GLES2_NUM_CUSTOM_UNIFORMS)
if (i < COGL_PROGRAM_NUM_CUSTOM_UNIFORMS)
{
program->custom_uniform_names[i] = g_strdup (uniform_name);
return i;
@ -190,12 +191,18 @@ cogl_program_uniform_x (int uniform_no,
gsize value_size,
gconstpointer value)
{
CoglProgram *program;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
if (uniform_no >= 0 && uniform_no < COGL_GLES2_NUM_CUSTOM_UNIFORMS
program = ctx->current_program;
g_return_if_fail (program != NULL);
if (uniform_no >= 0 && uniform_no < COGL_PROGRAM_NUM_CUSTOM_UNIFORMS
&& size >= 1 && size <= 4 && count >= 1)
{
CoglBoxedValue *bv = ctx->drv.gles2.custom_uniforms + uniform_no;
CoglBoxedValue *bv = program->custom_uniforms + uniform_no;
if (count == 1)
{
@ -224,7 +231,7 @@ cogl_program_uniform_x (int uniform_no,
bv->size = size;
bv->count = count;
ctx->drv.gles2.dirty_custom_uniforms |= 1 << uniform_no;
program->dirty_custom_uniforms |= 1 << uniform_no;
}
}
@ -255,11 +262,16 @@ cogl_program_uniform_matrix (int uniform_no,
gboolean transpose,
const GLfloat *value)
{
CoglProgram *program;
CoglBoxedValue *bv;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
bv = ctx->drv.gles2.custom_uniforms + uniform_no;
program = ctx->current_program;
g_return_if_fail (program != NULL);
bv = program->custom_uniforms + uniform_no;
cogl_program_uniform_x (uniform_no, size, count, COGL_BOXED_MATRIX,
sizeof (float) * size * size, value);

View File

@ -27,6 +27,9 @@
#include "cogl-gles2-wrapper.h"
#include "cogl-handle.h"
#define COGL_PROGRAM_NUM_CUSTOM_UNIFORMS 16
#define COGL_PROGRAM_UNBOUND_CUSTOM_UNIFORM -2
typedef struct _CoglProgram CoglProgram;
struct _CoglProgram
@ -35,7 +38,13 @@ struct _CoglProgram
GSList *attached_shaders;
char *custom_uniform_names[COGL_GLES2_NUM_CUSTOM_UNIFORMS];
char *custom_uniform_names[COGL_PROGRAM_NUM_CUSTOM_UNIFORMS];
CoglBoxedValue custom_uniforms[COGL_PROGRAM_NUM_CUSTOM_UNIFORMS];
/* Uniforms that have changed since the last time this program was
* used. */
guint32 dirty_custom_uniforms;
};
CoglProgram *_cogl_program_pointer_from_handle (CoglHandle handle);