mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 19:42:05 +00:00
rework enabling of attributes, removing _cogl_enable()
This removes the limited caching of enabled attributes done by _cogl_enable() and replaces it with a more generalized set of bitmasks associated with the context that allow us to efficiently compare the set of attribute locations that are currently enabled vs the new locations that need enabling so we only have to inform OpenGL of the changes in which locations are enabled/disabled. This also adds a per-context hash table for mapping attribute names to global name-state structs which includes a unique name-index for any name as well as pre-validated information about builtin "cogl_" attribute names including whether the attribute is normalized and what texture unit a texture attribute corresponds too. The name-state hash table means that cogl_attribute_new() now only needs to validate names the first time they are seen. CoglAttributes now reference a name-state structure instead of just the attribute name, so now we can efficiently get the name-index for any attribute and we can use that to index into a per-glsl-program cache that maps name indices to real GL attribute locations so when we get asked to draw a set of attributes we can very quickly determine what GL attributes need to be setup and enabled. If we don't have a cached location though we can still quickly access the string name so we can query OpenGL. Reviewed-by: Neil Roberts <neil@linux.intel.com>
This commit is contained in:
parent
2112af0bc5
commit
7283e0a49c
@ -40,19 +40,26 @@ typedef enum
|
||||
COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY
|
||||
} CoglAttributeNameID;
|
||||
|
||||
typedef struct _CoglAttributeNameState
|
||||
{
|
||||
char *name;
|
||||
CoglAttributeNameID name_id;
|
||||
int name_index;
|
||||
gboolean normalized_default;
|
||||
int texture_unit;
|
||||
} CoglAttributeNameState;
|
||||
|
||||
struct _CoglAttribute
|
||||
{
|
||||
CoglObject _parent;
|
||||
|
||||
CoglAttributeBuffer *attribute_buffer;
|
||||
const char *name;
|
||||
CoglAttributeNameID name_id;
|
||||
const CoglAttributeNameState *name_state;
|
||||
gsize stride;
|
||||
gsize offset;
|
||||
int n_components;
|
||||
CoglAttributeType type;
|
||||
gboolean normalized;
|
||||
unsigned int texture_unit;
|
||||
|
||||
int immutable_ref;
|
||||
};
|
||||
@ -71,6 +78,16 @@ typedef enum
|
||||
COGL_DRAW_COLOR_ATTRIBUTE_IS_OPAQUE = 1 << 3
|
||||
} CoglDrawFlags;
|
||||
|
||||
/* During CoglContext initialization we register the "cogl_color_in"
|
||||
* attribute name so it gets a global name_index of 0. We need to know
|
||||
* the name_index for "cogl_color_in" in
|
||||
* _cogl_pipeline_flush_gl_state() */
|
||||
#define COGL_ATTRIBUTE_COLOR_NAME_INDEX 0
|
||||
|
||||
CoglAttributeNameState *
|
||||
_cogl_attribute_register_attribute_name (CoglContext *context,
|
||||
const char *name);
|
||||
|
||||
CoglAttribute *
|
||||
_cogl_attribute_immutable_ref (CoglAttribute *attribute);
|
||||
|
||||
|
@ -59,80 +59,11 @@ static void _cogl_attribute_free (CoglAttribute *attribute);
|
||||
|
||||
COGL_OBJECT_DEFINE (Attribute, attribute);
|
||||
|
||||
#if 0
|
||||
gboolean
|
||||
validate_gl_attribute (const char *name,
|
||||
int n_components,
|
||||
CoglAttributeNameID *name_id,
|
||||
gboolean *normalized,
|
||||
unsigned int *texture_unit)
|
||||
{
|
||||
name = name + 3; /* skip past "gl_" */
|
||||
|
||||
*normalized = FALSE;
|
||||
*texture_unit = 0;
|
||||
|
||||
if (strcmp (name, "Vertex") == 0)
|
||||
{
|
||||
if (G_UNLIKELY (n_components == 1))
|
||||
{
|
||||
g_critical ("glVertexPointer doesn't allow 1 component vertex "
|
||||
"positions so we currently only support \"gl_Vertex\" "
|
||||
"attributes where n_components == 2, 3 or 4");
|
||||
return FALSE;
|
||||
}
|
||||
*name_id = COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY;
|
||||
}
|
||||
else if (strcmp (name, "Color") == 0)
|
||||
{
|
||||
if (G_UNLIKELY (n_components != 3 && n_components != 4))
|
||||
{
|
||||
g_critical ("glColorPointer expects 3 or 4 component colors so we "
|
||||
"currently only support \"gl_Color\" attributes where "
|
||||
"n_components == 3 or 4");
|
||||
return FALSE;
|
||||
}
|
||||
*name_id = COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY;
|
||||
*normalized = TRUE;
|
||||
}
|
||||
else if (strncmp (name, "MultiTexCoord", strlen ("MultiTexCoord")) == 0)
|
||||
{
|
||||
if (sscanf (gl_attribute, "MultiTexCoord%u", texture_unit) != 1)
|
||||
{
|
||||
g_warning ("gl_MultiTexCoord attributes should include a\n"
|
||||
"texture unit number, E.g. gl_MultiTexCoord0\n");
|
||||
unit = 0;
|
||||
}
|
||||
*name_id = COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY;
|
||||
}
|
||||
else if (strncmp (name, "Normal") == 0)
|
||||
{
|
||||
if (G_UNLIKELY (n_components != 3))
|
||||
{
|
||||
g_critical ("glNormalPointer expects 3 component normals so we "
|
||||
"currently only support \"gl_Normal\" attributes where "
|
||||
"n_components == 3");
|
||||
return FALSE;
|
||||
}
|
||||
*name_id = COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY;
|
||||
*normalized = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Unknown gl_* attribute name gl_%s\n", name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
gboolean
|
||||
validate_cogl_attribute (const char *name,
|
||||
int n_components,
|
||||
CoglAttributeNameID *name_id,
|
||||
gboolean *normalized,
|
||||
unsigned int *texture_unit)
|
||||
static gboolean
|
||||
validate_cogl_attribute_name (const char *name,
|
||||
CoglAttributeNameID *name_id,
|
||||
gboolean *normalized,
|
||||
int *texture_unit)
|
||||
{
|
||||
name = name + 5; /* skip "cogl_" */
|
||||
|
||||
@ -140,26 +71,11 @@ validate_cogl_attribute (const char *name,
|
||||
*texture_unit = 0;
|
||||
|
||||
if (strcmp (name, "position_in") == 0)
|
||||
{
|
||||
if (G_UNLIKELY (n_components == 1))
|
||||
{
|
||||
g_critical ("glVertexPointer doesn't allow 1 component vertex "
|
||||
"positions so we currently only support \"cogl_vertex\" "
|
||||
"attributes where n_components == 2, 3 or 4");
|
||||
return FALSE;
|
||||
}
|
||||
*name_id = COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY;
|
||||
}
|
||||
*name_id = COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY;
|
||||
else if (strcmp (name, "color_in") == 0)
|
||||
{
|
||||
if (G_UNLIKELY (n_components != 3 && n_components != 4))
|
||||
{
|
||||
g_critical ("glColorPointer expects 3 or 4 component colors so we "
|
||||
"currently only support \"cogl_color\" attributes where "
|
||||
"n_components == 3 or 4");
|
||||
return FALSE;
|
||||
}
|
||||
*name_id = COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY;
|
||||
*normalized = TRUE;
|
||||
}
|
||||
else if (strcmp (name, "tex_coord_in") == 0)
|
||||
*name_id = COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY;
|
||||
@ -178,13 +94,6 @@ validate_cogl_attribute (const char *name,
|
||||
}
|
||||
else if (strcmp (name, "normal_in") == 0)
|
||||
{
|
||||
if (G_UNLIKELY (n_components != 3))
|
||||
{
|
||||
g_critical ("glNormalPointer expects 3 component normals so we "
|
||||
"currently only support \"cogl_normal\" attributes "
|
||||
"where n_components == 3");
|
||||
return FALSE;
|
||||
}
|
||||
*name_id = COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY;
|
||||
*normalized = TRUE;
|
||||
}
|
||||
@ -197,6 +106,49 @@ validate_cogl_attribute (const char *name,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
CoglAttributeNameState *
|
||||
_cogl_attribute_register_attribute_name (CoglContext *context,
|
||||
const char *name)
|
||||
{
|
||||
CoglAttributeNameState *name_state = g_new (CoglAttributeNameState, 1);
|
||||
int name_index = context->n_attribute_names++;
|
||||
|
||||
name_state->name = g_strdup (name);
|
||||
name_state->name_index = name_index;
|
||||
if (strncmp (name, "cogl_", 5) == 0)
|
||||
{
|
||||
if (!validate_cogl_attribute_name (name,
|
||||
&name_state->name_id,
|
||||
&name_state->normalized_default,
|
||||
&name_state->texture_unit))
|
||||
goto error;
|
||||
}
|
||||
else
|
||||
{
|
||||
name_state->name_id = COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY;
|
||||
name_state->normalized_default = FALSE;
|
||||
name_state->texture_unit = 0;
|
||||
}
|
||||
|
||||
g_hash_table_insert (context->attribute_name_states_hash,
|
||||
name_state->name, name_state);
|
||||
|
||||
if (G_UNLIKELY (context->attribute_name_index_map == NULL))
|
||||
context->attribute_name_index_map =
|
||||
g_array_new (FALSE, FALSE, sizeof (void *));
|
||||
|
||||
g_array_set_size (context->attribute_name_index_map, name_index + 1);
|
||||
|
||||
g_array_index (context->attribute_name_index_map,
|
||||
CoglAttributeNameState *, name_index) = name_state;
|
||||
|
||||
return name_state;
|
||||
|
||||
error:
|
||||
g_free (name_state);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CoglAttribute *
|
||||
cogl_attribute_new (CoglAttributeBuffer *attribute_buffer,
|
||||
const char *name,
|
||||
@ -206,8 +158,20 @@ cogl_attribute_new (CoglAttributeBuffer *attribute_buffer,
|
||||
CoglAttributeType type)
|
||||
{
|
||||
CoglAttribute *attribute = g_slice_new (CoglAttribute);
|
||||
gboolean status;
|
||||
|
||||
/* FIXME: retrieve the context from the buffer */
|
||||
_COGL_GET_CONTEXT (ctx, NULL);
|
||||
|
||||
attribute->name_state =
|
||||
g_hash_table_lookup (ctx->attribute_name_states_hash, name);
|
||||
if (!attribute->name_state)
|
||||
{
|
||||
CoglAttributeNameState *name_state =
|
||||
_cogl_attribute_register_attribute_name (ctx, name);
|
||||
if (!name_state)
|
||||
goto error;
|
||||
attribute->name_state = name_state;
|
||||
}
|
||||
attribute->attribute_buffer = cogl_object_ref (attribute_buffer);
|
||||
attribute->stride = stride;
|
||||
attribute->offset = offset;
|
||||
@ -215,71 +179,52 @@ cogl_attribute_new (CoglAttributeBuffer *attribute_buffer,
|
||||
attribute->type = type;
|
||||
attribute->immutable_ref = 0;
|
||||
|
||||
if (strncmp (name, "cogl_", 5) == 0)
|
||||
if (attribute->name_state->name_id != COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY)
|
||||
{
|
||||
const char *common_tex_coord_names[8] = {
|
||||
"cogl_tex_coord0_in",
|
||||
"cogl_tex_coord1_in",
|
||||
"cogl_tex_coord2_in",
|
||||
"cogl_tex_coord3_in",
|
||||
"cogl_tex_coord4_in",
|
||||
"cogl_tex_coord5_in",
|
||||
"cogl_tex_coord6_in",
|
||||
"cogl_tex_coord7_in"
|
||||
};
|
||||
status = validate_cogl_attribute (name,
|
||||
n_components,
|
||||
&attribute->name_id,
|
||||
&attribute->normalized,
|
||||
&attribute->texture_unit);
|
||||
|
||||
/* Avoid even the cost of g_intern_string() for the very common case
|
||||
* attribute names...*/
|
||||
switch (attribute->name_id)
|
||||
switch (attribute->name_state->name_id)
|
||||
{
|
||||
case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY:
|
||||
attribute->name = "cogl_position_in";
|
||||
if (G_UNLIKELY (n_components == 1))
|
||||
{
|
||||
g_critical ("glVertexPointer doesn't allow 1 component vertex "
|
||||
"positions so we currently only support \"cogl_vertex\" "
|
||||
"attributes where n_components == 2, 3 or 4");
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY:
|
||||
attribute->name = "cogl_color_in";
|
||||
if (G_UNLIKELY (n_components != 3 && n_components != 4))
|
||||
{
|
||||
g_critical ("glColorPointer expects 3 or 4 component colors so we "
|
||||
"currently only support \"cogl_color\" attributes where "
|
||||
"n_components == 3 or 4");
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY:
|
||||
if (attribute->texture_unit < 8)
|
||||
attribute->name = common_tex_coord_names[attribute->texture_unit];
|
||||
else
|
||||
attribute->name = g_intern_string (name);
|
||||
break;
|
||||
case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY:
|
||||
attribute->name = "cogl_normal_in";
|
||||
if (G_UNLIKELY (n_components != 3))
|
||||
{
|
||||
g_critical ("glNormalPointer expects 3 component normals so we "
|
||||
"currently only support \"cogl_normal\" attributes "
|
||||
"where n_components == 3");
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_warn_if_reached ();
|
||||
}
|
||||
attribute->normalized = attribute->name_state->normalized_default;
|
||||
}
|
||||
#if 0
|
||||
else if (strncmp (name, "gl_", 3) == 0)
|
||||
status = validate_gl_attribute (attribute->name,
|
||||
n_components,
|
||||
&attribute->name_id,
|
||||
&attribute->normalized,
|
||||
&attribute->texture_unit);
|
||||
#endif
|
||||
else
|
||||
{
|
||||
attribute->name = g_intern_string (name);
|
||||
attribute->name_id = COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY;
|
||||
attribute->normalized = FALSE;
|
||||
attribute->texture_unit = 0;
|
||||
status = TRUE;
|
||||
}
|
||||
|
||||
if (!status)
|
||||
{
|
||||
_cogl_attribute_free (attribute);
|
||||
return NULL;
|
||||
}
|
||||
attribute->normalized = FALSE;
|
||||
|
||||
return _cogl_attribute_object_new (attribute);
|
||||
|
||||
error:
|
||||
_cogl_attribute_free (attribute);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
@ -428,87 +373,216 @@ validated:
|
||||
return status;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
toggle_enabled_cb (int bit_num, void *user_data)
|
||||
typedef struct _ForeachChangedBitState
|
||||
{
|
||||
const CoglBitmask *new_values = user_data;
|
||||
gboolean enabled = _cogl_bitmask_get (new_values, bit_num);
|
||||
CoglContext *context;
|
||||
const CoglBitmask *new_bits;
|
||||
CoglPipeline *pipeline;
|
||||
} ForeachChangedBitState;
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, FALSE);
|
||||
static gboolean
|
||||
toggle_builtin_attribute_enabled_cb (int bit_num, void *user_data)
|
||||
{
|
||||
ForeachChangedBitState *state = user_data;
|
||||
CoglContext *context = state->context;
|
||||
|
||||
_COGL_RETURN_VAL_IF_FAIL (context->driver == COGL_DRIVER_GL ||
|
||||
context->driver == COGL_DRIVER_GLES1,
|
||||
FALSE);
|
||||
|
||||
if (ctx->driver == COGL_DRIVER_GLES2)
|
||||
{
|
||||
if (enabled)
|
||||
GE( ctx, glEnableVertexAttribArray (bit_num) );
|
||||
else
|
||||
GE( ctx, glDisableVertexAttribArray (bit_num) );
|
||||
}
|
||||
#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES)
|
||||
else
|
||||
{
|
||||
GE( ctx, glClientActiveTexture (GL_TEXTURE0 + bit_num) );
|
||||
{
|
||||
gboolean enabled = _cogl_bitmask_get (state->new_bits, bit_num);
|
||||
GLenum cap;
|
||||
|
||||
if (enabled)
|
||||
GE( ctx, glEnableClientState (GL_TEXTURE_COORD_ARRAY) );
|
||||
else
|
||||
GE( ctx, glDisableClientState (GL_TEXTURE_COORD_ARRAY) );
|
||||
}
|
||||
switch (bit_num)
|
||||
{
|
||||
case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY:
|
||||
cap = GL_COLOR_ARRAY;
|
||||
break;
|
||||
case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY:
|
||||
cap = GL_VERTEX_ARRAY;
|
||||
break;
|
||||
case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY:
|
||||
cap = GL_NORMAL_ARRAY;
|
||||
break;
|
||||
}
|
||||
if (enabled)
|
||||
GE (context, glEnableClientState (cap));
|
||||
else
|
||||
GE (context, glDisableClientState (cap));
|
||||
}
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
set_enabled_arrays (CoglBitmask *value_cache,
|
||||
const CoglBitmask *new_values)
|
||||
static gboolean
|
||||
toggle_texcood_attribute_enabled_cb (int bit_num, void *user_data)
|
||||
{
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
ForeachChangedBitState *state = user_data;
|
||||
CoglContext *context = state->context;
|
||||
|
||||
/* Get the list of bits that are different */
|
||||
_cogl_bitmask_clear_all (&ctx->arrays_to_change);
|
||||
_cogl_bitmask_set_bits (&ctx->arrays_to_change, value_cache);
|
||||
_cogl_bitmask_xor_bits (&ctx->arrays_to_change, new_values);
|
||||
_COGL_RETURN_VAL_IF_FAIL (context->driver == COGL_DRIVER_GL ||
|
||||
context->driver == COGL_DRIVER_GLES1,
|
||||
FALSE);
|
||||
|
||||
/* Iterate over each bit to change */
|
||||
_cogl_bitmask_foreach (&ctx->arrays_to_change,
|
||||
toggle_enabled_cb,
|
||||
(void *) new_values);
|
||||
#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES)
|
||||
{
|
||||
gboolean enabled = _cogl_bitmask_get (state->new_bits, bit_num);
|
||||
|
||||
/* Store the new values */
|
||||
_cogl_bitmask_clear_all (value_cache);
|
||||
_cogl_bitmask_set_bits (value_cache, new_values);
|
||||
GE( context, glClientActiveTexture (GL_TEXTURE0 + bit_num) );
|
||||
|
||||
if (enabled)
|
||||
GE( context, glEnableClientState (GL_TEXTURE_COORD_ARRAY) );
|
||||
else
|
||||
GE( context, glDisableClientState (GL_TEXTURE_COORD_ARRAY) );
|
||||
}
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static CoglHandle
|
||||
enable_gl_state (CoglDrawFlags flags,
|
||||
CoglAttribute **attributes,
|
||||
int n_attributes,
|
||||
ValidateLayerState *state)
|
||||
static gboolean
|
||||
toggle_custom_attribute_enabled_cb (int bit_num, void *user_data)
|
||||
{
|
||||
ForeachChangedBitState *state = user_data;
|
||||
gboolean enabled = _cogl_bitmask_get (state->new_bits, bit_num);
|
||||
CoglContext *context = state->context;
|
||||
|
||||
if (enabled)
|
||||
GE( context, glEnableVertexAttribArray (bit_num) );
|
||||
else
|
||||
GE( context, glDisableVertexAttribArray (bit_num) );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
foreach_changed_bit_and_save (CoglContext *context,
|
||||
CoglBitmask *current_bits,
|
||||
const CoglBitmask *new_bits,
|
||||
CoglBitmaskForeachFunc callback,
|
||||
ForeachChangedBitState *state)
|
||||
{
|
||||
/* Get the list of bits that are different */
|
||||
_cogl_bitmask_clear_all (&context->changed_bits_tmp);
|
||||
_cogl_bitmask_set_bits (&context->changed_bits_tmp, current_bits);
|
||||
_cogl_bitmask_xor_bits (&context->changed_bits_tmp, new_bits);
|
||||
|
||||
/* Iterate over each bit to change */
|
||||
state->new_bits = new_bits;
|
||||
_cogl_bitmask_foreach (&context->changed_bits_tmp,
|
||||
callback,
|
||||
state);
|
||||
|
||||
/* Store the new values */
|
||||
_cogl_bitmask_clear_all (current_bits);
|
||||
_cogl_bitmask_set_bits (current_bits, new_bits);
|
||||
}
|
||||
|
||||
static void
|
||||
setup_generic_attribute (CoglContext *context,
|
||||
CoglPipeline *pipeline,
|
||||
CoglAttribute *attribute,
|
||||
guint8 *base)
|
||||
{
|
||||
int name_index = attribute->name_state->name_index;
|
||||
int attrib_location =
|
||||
_cogl_pipeline_progend_glsl_get_attrib_location (pipeline, name_index);
|
||||
if (attrib_location != -1)
|
||||
{
|
||||
GE( context, glVertexAttribPointer (attrib_location,
|
||||
attribute->n_components,
|
||||
attribute->type,
|
||||
attribute->normalized,
|
||||
attribute->stride,
|
||||
base + attribute->offset) );
|
||||
_cogl_bitmask_set (&context->enable_custom_attributes_tmp,
|
||||
attrib_location, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
apply_attribute_enable_updates (CoglContext *context,
|
||||
CoglPipeline *pipeline)
|
||||
{
|
||||
ForeachChangedBitState changed_bits_state;
|
||||
|
||||
changed_bits_state.context = context;
|
||||
changed_bits_state.new_bits = &context->enable_builtin_attributes_tmp;
|
||||
changed_bits_state.pipeline = pipeline;
|
||||
|
||||
foreach_changed_bit_and_save (context,
|
||||
&context->enabled_builtin_attributes,
|
||||
&context->enable_builtin_attributes_tmp,
|
||||
toggle_builtin_attribute_enabled_cb,
|
||||
&changed_bits_state);
|
||||
|
||||
changed_bits_state.new_bits = &context->enable_texcoord_attributes_tmp;
|
||||
foreach_changed_bit_and_save (context,
|
||||
&context->enabled_texcoord_attributes,
|
||||
&context->enable_texcoord_attributes_tmp,
|
||||
toggle_texcood_attribute_enabled_cb,
|
||||
&changed_bits_state);
|
||||
|
||||
changed_bits_state.new_bits = &context->enable_custom_attributes_tmp;
|
||||
foreach_changed_bit_and_save (context,
|
||||
&context->enabled_custom_attributes,
|
||||
&context->enable_custom_attributes_tmp,
|
||||
toggle_custom_attribute_enabled_cb,
|
||||
&changed_bits_state);
|
||||
}
|
||||
|
||||
static CoglPipeline *
|
||||
flush_state (CoglDrawFlags flags,
|
||||
CoglAttribute **attributes,
|
||||
int n_attributes,
|
||||
ValidateLayerState *state)
|
||||
{
|
||||
CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
|
||||
int i;
|
||||
GLuint generic_index = 0;
|
||||
unsigned long enable_flags = 0;
|
||||
gboolean skip_gl_color = FALSE;
|
||||
CoglPipeline *source;
|
||||
CoglPipeline *source = cogl_get_source ();
|
||||
CoglPipeline *copy = NULL;
|
||||
int n_tex_coord_attribs = 0;
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
|
||||
|
||||
if (!(flags & COGL_DRAW_SKIP_JOURNAL_FLUSH))
|
||||
_cogl_journal_flush (framebuffer->journal, framebuffer);
|
||||
|
||||
state->unit = 0;
|
||||
state->options.flags = 0;
|
||||
state->fallback_layers = 0;
|
||||
|
||||
if (!(flags & COGL_DRAW_SKIP_PIPELINE_VALIDATION))
|
||||
cogl_pipeline_foreach_layer (cogl_get_source (),
|
||||
validate_layer_cb,
|
||||
state);
|
||||
|
||||
/* NB: _cogl_framebuffer_flush_state may disrupt various state (such
|
||||
* as the pipeline state) when flushing the clip stack, so should
|
||||
* always be done first when preparing to draw. We need to do this
|
||||
* before setting up the array pointers because setting up the clip
|
||||
* stack can cause some drawing which would change the array
|
||||
* pointers. */
|
||||
if (!(flags & COGL_DRAW_SKIP_FRAMEBUFFER_FLUSH))
|
||||
_cogl_framebuffer_flush_state (cogl_get_draw_framebuffer (),
|
||||
_cogl_get_read_framebuffer (),
|
||||
COGL_FRAMEBUFFER_STATE_ALL);
|
||||
|
||||
/* In cogl_read_pixels we have a fast-path when reading a single
|
||||
* pixel and the scene is just comprised of simple rectangles still
|
||||
* in the journal. For this optimization to work we need to track
|
||||
* when the framebuffer really does get drawn to. */
|
||||
_cogl_framebuffer_dirty (framebuffer);
|
||||
|
||||
source = cogl_get_source ();
|
||||
|
||||
/* Iterate the attributes to work out whether blending needs to be
|
||||
enabled and how many texture coords there are. We need to do this
|
||||
before flushing the pipeline. */
|
||||
for (i = 0; i < n_attributes; i++)
|
||||
switch (attributes[i]->name_id)
|
||||
switch (attributes[i]->name_state->name_id)
|
||||
{
|
||||
case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY:
|
||||
if ((flags & COGL_DRAW_COLOR_ATTRIBUTE_IS_OPAQUE) == 0 &&
|
||||
@ -589,11 +663,13 @@ enable_gl_state (CoglDrawFlags flags,
|
||||
|
||||
_cogl_pipeline_flush_gl_state (source, skip_gl_color, n_tex_coord_attribs);
|
||||
|
||||
_cogl_bitmask_clear_all (&ctx->temp_bitmask);
|
||||
_cogl_bitmask_clear_all (&ctx->enable_builtin_attributes_tmp);
|
||||
_cogl_bitmask_clear_all (&ctx->enable_texcoord_attributes_tmp);
|
||||
_cogl_bitmask_clear_all (&ctx->enable_custom_attributes_tmp);
|
||||
|
||||
/* Bind the attribute pointers. We need to do this after the
|
||||
pipeline is flushed because on GLES2 that is the only point when
|
||||
we can determine the attribute locations */
|
||||
* pipeline is flushed because when using GLSL that is the only
|
||||
* point when we can determine the attribute locations */
|
||||
|
||||
for (i = 0; i < n_attributes; i++)
|
||||
{
|
||||
@ -601,156 +677,77 @@ enable_gl_state (CoglDrawFlags flags,
|
||||
CoglAttributeBuffer *attribute_buffer;
|
||||
CoglBuffer *buffer;
|
||||
guint8 *base;
|
||||
#ifdef HAVE_COGL_GLES2
|
||||
int attrib_location;
|
||||
#endif
|
||||
|
||||
attribute_buffer = cogl_attribute_get_buffer (attribute);
|
||||
buffer = COGL_BUFFER (attribute_buffer);
|
||||
base = _cogl_buffer_bind (buffer, COGL_BUFFER_BIND_TARGET_ATTRIBUTE_BUFFER);
|
||||
|
||||
switch (attribute->name_id)
|
||||
switch (attribute->name_state->name_id)
|
||||
{
|
||||
case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY:
|
||||
#ifdef HAVE_COGL_GLES2
|
||||
if (ctx->driver == COGL_DRIVER_GLES2)
|
||||
{
|
||||
attrib_location =
|
||||
_cogl_pipeline_progend_glsl_get_color_attribute (source);
|
||||
if (attrib_location != -1)
|
||||
{
|
||||
GE( ctx,
|
||||
glVertexAttribPointer (attrib_location,
|
||||
attribute->n_components,
|
||||
attribute->type,
|
||||
TRUE, /* normalize */
|
||||
attribute->stride,
|
||||
base + attribute->offset) );
|
||||
|
||||
_cogl_bitmask_set (&ctx->temp_bitmask, attrib_location, TRUE);
|
||||
}
|
||||
}
|
||||
setup_generic_attribute (ctx, source, attribute, base);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
enable_flags |= COGL_ENABLE_COLOR_ARRAY;
|
||||
/* GE (ctx, glEnableClientState (GL_COLOR_ARRAY)); */
|
||||
_cogl_bitmask_set (&ctx->enable_builtin_attributes_tmp,
|
||||
COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY, TRUE);
|
||||
GE (ctx, glColorPointer (attribute->n_components,
|
||||
attribute->type,
|
||||
attribute->stride,
|
||||
base + attribute->offset));
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY:
|
||||
#ifdef HAVE_COGL_GLES2
|
||||
if (ctx->driver == COGL_DRIVER_GLES2)
|
||||
{
|
||||
attrib_location =
|
||||
_cogl_pipeline_progend_glsl_get_normal_attribute (source);
|
||||
if (attrib_location != -1)
|
||||
{
|
||||
GE( ctx,
|
||||
glVertexAttribPointer (attrib_location,
|
||||
attribute->n_components,
|
||||
attribute->type,
|
||||
TRUE, /* normalize */
|
||||
attribute->stride,
|
||||
base + attribute->offset) );
|
||||
_cogl_bitmask_set (&ctx->temp_bitmask, attrib_location, TRUE);
|
||||
}
|
||||
}
|
||||
setup_generic_attribute (ctx, source, attribute, base);
|
||||
#endif
|
||||
#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES)
|
||||
if (ctx->driver != COGL_DRIVER_GLES2)
|
||||
{
|
||||
/* FIXME: go through cogl cache to enable normal array */
|
||||
GE (ctx, glEnableClientState (GL_NORMAL_ARRAY));
|
||||
_cogl_bitmask_set (&ctx->enable_builtin_attributes_tmp,
|
||||
COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY, TRUE);
|
||||
GE (ctx, glNormalPointer (attribute->type,
|
||||
attribute->stride,
|
||||
base + attribute->offset));
|
||||
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY:
|
||||
#ifdef HAVE_COGL_GLES2
|
||||
if (ctx->driver == COGL_DRIVER_GLES2)
|
||||
{
|
||||
attrib_location =
|
||||
_cogl_pipeline_progend_glsl_get_tex_coord_attribute
|
||||
(source, attribute->texture_unit);
|
||||
if (attrib_location != -1)
|
||||
{
|
||||
GE( ctx,
|
||||
glVertexAttribPointer (attrib_location,
|
||||
attribute->n_components,
|
||||
attribute->type,
|
||||
FALSE, /* normalize */
|
||||
attribute->stride,
|
||||
base + attribute->offset) );
|
||||
_cogl_bitmask_set (&ctx->temp_bitmask, attrib_location, TRUE);
|
||||
}
|
||||
}
|
||||
setup_generic_attribute (ctx, source, attribute, base);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
GE (ctx, glClientActiveTexture (GL_TEXTURE0 +
|
||||
attribute->texture_unit));
|
||||
_cogl_bitmask_set (&ctx->enable_texcoord_attributes_tmp,
|
||||
attribute->name_state->texture_unit, TRUE);
|
||||
GE (ctx,
|
||||
glClientActiveTexture (GL_TEXTURE0 +
|
||||
attribute->name_state->texture_unit));
|
||||
GE (ctx, glTexCoordPointer (attribute->n_components,
|
||||
attribute->type,
|
||||
attribute->stride,
|
||||
base + attribute->offset));
|
||||
_cogl_bitmask_set (&ctx->temp_bitmask,
|
||||
attribute->texture_unit, TRUE);
|
||||
|
||||
}
|
||||
break;
|
||||
case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY:
|
||||
#ifdef HAVE_COGL_GLES2
|
||||
if (ctx->driver == COGL_DRIVER_GLES2)
|
||||
{
|
||||
attrib_location =
|
||||
_cogl_pipeline_progend_glsl_get_position_attribute (source);
|
||||
if (attrib_location != -1)
|
||||
{
|
||||
GE( ctx,
|
||||
glVertexAttribPointer (attrib_location,
|
||||
attribute->n_components,
|
||||
attribute->type,
|
||||
FALSE, /* normalize */
|
||||
attribute->stride,
|
||||
base + attribute->offset) );
|
||||
_cogl_bitmask_set (&ctx->temp_bitmask, attrib_location, TRUE);
|
||||
}
|
||||
}
|
||||
setup_generic_attribute (ctx, source, attribute, base);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
enable_flags |= COGL_ENABLE_VERTEX_ARRAY;
|
||||
/* GE (ctx, glEnableClientState (GL_VERTEX_ARRAY)); */
|
||||
_cogl_bitmask_set (&ctx->enable_builtin_attributes_tmp,
|
||||
COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY, TRUE);
|
||||
GE (ctx, glVertexPointer (attribute->n_components,
|
||||
attribute->type,
|
||||
attribute->stride,
|
||||
base + attribute->offset));
|
||||
|
||||
}
|
||||
break;
|
||||
case COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY:
|
||||
if (ctx->driver != COGL_DRIVER_GLES1)
|
||||
{
|
||||
/* FIXME: go through cogl cache to enable generic array. */
|
||||
/* FIXME: this is going to end up just using the builtins
|
||||
on GLES 2 */
|
||||
GE (ctx, glEnableVertexAttribArray (generic_index++));
|
||||
GE (ctx, glVertexAttribPointer (generic_index,
|
||||
attribute->n_components,
|
||||
attribute->type,
|
||||
attribute->normalized,
|
||||
attribute->stride,
|
||||
base + attribute->offset));
|
||||
}
|
||||
setup_generic_attribute (ctx, source, attribute, base);
|
||||
break;
|
||||
default:
|
||||
g_warning ("Unrecognised attribute type 0x%08x", attribute->type);
|
||||
@ -759,10 +756,7 @@ enable_gl_state (CoglDrawFlags flags,
|
||||
_cogl_buffer_unbind (buffer);
|
||||
}
|
||||
|
||||
/* Flush the state of the attribute arrays */
|
||||
set_enabled_arrays (&ctx->arrays_enabled, &ctx->temp_bitmask);
|
||||
|
||||
_cogl_enable (enable_flags);
|
||||
apply_attribute_enable_updates (ctx, source);
|
||||
|
||||
return source;
|
||||
}
|
||||
@ -772,60 +766,14 @@ _cogl_attribute_disable_cached_arrays (void)
|
||||
{
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
_cogl_bitmask_clear_all (&ctx->temp_bitmask);
|
||||
set_enabled_arrays (&ctx->arrays_enabled, &ctx->temp_bitmask);
|
||||
}
|
||||
_cogl_bitmask_clear_all (&ctx->enable_builtin_attributes_tmp);
|
||||
_cogl_bitmask_clear_all (&ctx->enable_texcoord_attributes_tmp);
|
||||
_cogl_bitmask_clear_all (&ctx->enable_custom_attributes_tmp);
|
||||
|
||||
/* FIXME: we shouldn't be disabling state after drawing we should
|
||||
* just disable the things not needed after enabling state. */
|
||||
static void
|
||||
disable_gl_state (CoglAttribute **attributes,
|
||||
int n_attributes,
|
||||
CoglPipeline *source)
|
||||
{
|
||||
GLuint generic_index = 0;
|
||||
int i;
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
if (G_UNLIKELY (source != cogl_get_source ()))
|
||||
cogl_object_unref (source);
|
||||
|
||||
for (i = 0; i < n_attributes; i++)
|
||||
{
|
||||
CoglAttribute *attribute = attributes[i];
|
||||
|
||||
switch (attribute->name_id)
|
||||
{
|
||||
case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY:
|
||||
/* GE (ctx, glDisableClientState (GL_COLOR_ARRAY)); */
|
||||
break;
|
||||
case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY:
|
||||
/* FIXME: go through cogl cache to enable normal array */
|
||||
#if defined(HAVE_COGL_GLES) || defined(HAVE_COGL_GL)
|
||||
if (ctx->driver != COGL_DRIVER_GLES2)
|
||||
GE (ctx, glDisableClientState (GL_NORMAL_ARRAY));
|
||||
#endif
|
||||
break;
|
||||
case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY:
|
||||
/* The enabled state of the texture coord arrays is
|
||||
cached in ctx->enabled_texcoord_arrays so we don't
|
||||
need to do anything here. The array will be disabled
|
||||
by the next drawing primitive if it is not
|
||||
required */
|
||||
break;
|
||||
case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY:
|
||||
/* GE (ctx, glDisableClientState (GL_VERTEX_ARRAY)); */
|
||||
break;
|
||||
case COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY:
|
||||
if (ctx->driver != COGL_DRIVER_GLES1)
|
||||
/* FIXME: go through cogl cache to enable generic array */
|
||||
GE (ctx, glDisableVertexAttribArray (generic_index++));
|
||||
break;
|
||||
default:
|
||||
g_warning ("Unrecognised attribute type 0x%08x", attribute->type);
|
||||
}
|
||||
}
|
||||
/* XXX: we can pass a NULL source pipeline here because we know a
|
||||
* source pipeline only needs to be referenced when enabling
|
||||
* attributes. */
|
||||
apply_attribute_enable_updates (ctx, NULL);
|
||||
}
|
||||
|
||||
#ifdef COGL_ENABLE_DEBUG
|
||||
@ -1020,7 +968,8 @@ draw_wireframe (CoglVerticesMode mode,
|
||||
|
||||
for (i = 0; i < n_attributes; i++)
|
||||
{
|
||||
if (strcmp (attributes[i]->name, "cogl_position_in") == 0)
|
||||
if (attributes[i]->name_state->name_id ==
|
||||
COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY)
|
||||
{
|
||||
position = attributes[i];
|
||||
break;
|
||||
@ -1073,37 +1022,6 @@ draw_wireframe (CoglVerticesMode mode,
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
flush_state (CoglDrawFlags flags,
|
||||
ValidateLayerState *state)
|
||||
{
|
||||
if (!(flags & COGL_DRAW_SKIP_JOURNAL_FLUSH))
|
||||
{
|
||||
CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
|
||||
_cogl_journal_flush (framebuffer->journal, framebuffer);
|
||||
}
|
||||
|
||||
state->unit = 0;
|
||||
state->options.flags = 0;
|
||||
state->fallback_layers = 0;
|
||||
|
||||
if (!(flags & COGL_DRAW_SKIP_PIPELINE_VALIDATION))
|
||||
cogl_pipeline_foreach_layer (cogl_get_source (),
|
||||
validate_layer_cb,
|
||||
state);
|
||||
|
||||
/* NB: _cogl_framebuffer_flush_state may disrupt various state (such
|
||||
* as the pipeline state) when flushing the clip stack, so should
|
||||
* always be done first when preparing to draw. We need to do this
|
||||
* before setting up the array pointers because setting up the clip
|
||||
* stack can cause some drawing which would change the array
|
||||
* pointers. */
|
||||
if (!(flags & COGL_DRAW_SKIP_FRAMEBUFFER_FLUSH))
|
||||
_cogl_framebuffer_flush_state (cogl_get_draw_framebuffer (),
|
||||
_cogl_get_read_framebuffer (),
|
||||
COGL_FRAMEBUFFER_STATE_ALL);
|
||||
}
|
||||
|
||||
/* This can be called directly by the CoglJournal to draw attributes
|
||||
* skipping the implicit journal flush, the framebuffer flush and
|
||||
* pipeline validation. */
|
||||
@ -1120,15 +1038,12 @@ _cogl_draw_attributes (CoglVerticesMode mode,
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
flush_state (flags, &state);
|
||||
|
||||
source = enable_gl_state (flags, attributes, n_attributes, &state);
|
||||
source = flush_state (flags, attributes, n_attributes, &state);
|
||||
|
||||
GE (ctx, glDrawArrays ((GLenum)mode, first_vertex, n_vertices));
|
||||
|
||||
/* FIXME: we shouldn't be disabling state after drawing we should
|
||||
* just disable the things not needed after enabling state. */
|
||||
disable_gl_state (attributes, n_attributes, source);
|
||||
if (G_UNLIKELY (source != cogl_get_source ()))
|
||||
cogl_object_unref (source);
|
||||
|
||||
#ifdef COGL_ENABLE_DEBUG
|
||||
if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_WIREFRAME)))
|
||||
@ -1212,9 +1127,7 @@ _cogl_draw_indexed_attributes (CoglVerticesMode mode,
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
flush_state (flags, &state);
|
||||
|
||||
source = enable_gl_state (flags, attributes, n_attributes, &state);
|
||||
source = flush_state (flags, attributes, n_attributes, &state);
|
||||
|
||||
buffer = COGL_BUFFER (cogl_indices_get_buffer (indices));
|
||||
base = _cogl_buffer_bind (buffer, COGL_BUFFER_BIND_TARGET_INDEX_BUFFER);
|
||||
@ -1241,9 +1154,8 @@ _cogl_draw_indexed_attributes (CoglVerticesMode mode,
|
||||
|
||||
_cogl_buffer_unbind (buffer);
|
||||
|
||||
/* FIXME: we shouldn't be disabling state after drawing we should
|
||||
* just disable the things not needed after enabling state. */
|
||||
disable_gl_state (attributes, n_attributes, source);
|
||||
if (G_UNLIKELY (source != cogl_get_source ()))
|
||||
cogl_object_unref (source);
|
||||
|
||||
#ifdef COGL_ENABLE_DEBUG
|
||||
if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_WIREFRAME)))
|
||||
|
@ -72,8 +72,21 @@ struct _CoglContext
|
||||
CoglHandle default_layer_n;
|
||||
CoglHandle dummy_layer_dependant;
|
||||
|
||||
/* Enable cache */
|
||||
unsigned long enable_flags;
|
||||
GHashTable *attribute_name_states_hash;
|
||||
GArray *attribute_name_index_map;
|
||||
int n_attribute_names;
|
||||
|
||||
CoglBitmask enabled_builtin_attributes;
|
||||
CoglBitmask enabled_texcoord_attributes;
|
||||
CoglBitmask enabled_custom_attributes;
|
||||
|
||||
/* These are temporary bitmasks that are used when disabling
|
||||
* builtin,texcoord and custom attribute arrays. They are here just
|
||||
* to avoid allocating new ones each time */
|
||||
CoglBitmask enable_builtin_attributes_tmp;
|
||||
CoglBitmask enable_texcoord_attributes_tmp;
|
||||
CoglBitmask enable_custom_attributes_tmp;
|
||||
CoglBitmask changed_bits_tmp;
|
||||
|
||||
gboolean legacy_backface_culling_enabled;
|
||||
|
||||
@ -129,16 +142,6 @@ struct _CoglContext
|
||||
gboolean current_pipeline_skip_gl_color;
|
||||
unsigned long current_pipeline_age;
|
||||
|
||||
/* Bitmask of attributes enabled. On GLES2 these are the vertex
|
||||
attribute numbers and on regular GL these are only used for the
|
||||
texture coordinate arrays */
|
||||
CoglBitmask arrays_enabled;
|
||||
/* These are temporary bitmasks that are used when disabling
|
||||
texcoord arrays. They are here just to avoid allocating new ones
|
||||
each time */
|
||||
CoglBitmask arrays_to_change;
|
||||
CoglBitmask temp_bitmask;
|
||||
|
||||
gboolean gl_blend_enable_cache;
|
||||
|
||||
gboolean depth_test_enabled_cache;
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "cogl-framebuffer-private.h"
|
||||
#include "cogl-onscreen-private.h"
|
||||
#include "cogl2-path.h"
|
||||
#include "cogl-attribute-private.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@ -129,7 +130,6 @@ cogl_context_new (CoglDisplay *display,
|
||||
{
|
||||
CoglContext *context;
|
||||
GLubyte default_texture_data[] = { 0xff, 0xff, 0xff, 0x0 };
|
||||
unsigned long enable_flags = 0;
|
||||
const CoglWinsysVtable *winsys;
|
||||
int i;
|
||||
|
||||
@ -221,6 +221,16 @@ cogl_context_new (CoglDisplay *display,
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
context->attribute_name_states_hash =
|
||||
g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||
context->attribute_name_index_map = NULL;
|
||||
context->n_attribute_names = 0;
|
||||
|
||||
/* The "cogl_color_in" attribute needs a deterministic name_index
|
||||
* so we make sure it's the first attribute name we register */
|
||||
_cogl_attribute_register_attribute_name (context, "cogl_color_in");
|
||||
|
||||
|
||||
context->uniform_names =
|
||||
g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
|
||||
context->uniform_name_hash = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
@ -234,7 +244,6 @@ cogl_context_new (CoglDisplay *display,
|
||||
_cogl_pipeline_init_state_hash_functions ();
|
||||
_cogl_pipeline_init_layer_state_hash_functions ();
|
||||
|
||||
context->enable_flags = 0;
|
||||
context->current_clip_stack_valid = FALSE;
|
||||
context->current_clip_stack = NULL;
|
||||
|
||||
@ -284,9 +293,13 @@ cogl_context_new (CoglDisplay *display,
|
||||
context->current_pipeline_changes_since_flush = 0;
|
||||
context->current_pipeline_skip_gl_color = FALSE;
|
||||
|
||||
_cogl_bitmask_init (&context->arrays_enabled);
|
||||
_cogl_bitmask_init (&context->temp_bitmask);
|
||||
_cogl_bitmask_init (&context->arrays_to_change);
|
||||
_cogl_bitmask_init (&context->enabled_builtin_attributes);
|
||||
_cogl_bitmask_init (&context->enable_builtin_attributes_tmp);
|
||||
_cogl_bitmask_init (&context->enabled_texcoord_attributes);
|
||||
_cogl_bitmask_init (&context->enable_texcoord_attributes_tmp);
|
||||
_cogl_bitmask_init (&context->enabled_custom_attributes);
|
||||
_cogl_bitmask_init (&context->enable_custom_attributes_tmp);
|
||||
_cogl_bitmask_init (&context->changed_bits_tmp);
|
||||
|
||||
context->max_texture_units = -1;
|
||||
context->max_activateable_texture_units = -1;
|
||||
@ -385,7 +398,6 @@ cogl_context_new (CoglDisplay *display,
|
||||
|
||||
cogl_push_source (context->opaque_color_pipeline);
|
||||
_cogl_pipeline_flush_gl_state (context->opaque_color_pipeline, FALSE, 0);
|
||||
_cogl_enable (enable_flags);
|
||||
|
||||
context->atlases = NULL;
|
||||
g_hook_list_init (&context->atlas_reorganize_callbacks, sizeof (GHook));
|
||||
@ -468,9 +480,13 @@ _cogl_context_free (CoglContext *context)
|
||||
g_slist_free (context->atlases);
|
||||
g_hook_list_clear (&context->atlas_reorganize_callbacks);
|
||||
|
||||
_cogl_bitmask_destroy (&context->arrays_enabled);
|
||||
_cogl_bitmask_destroy (&context->temp_bitmask);
|
||||
_cogl_bitmask_destroy (&context->arrays_to_change);
|
||||
_cogl_bitmask_destroy (&context->enabled_builtin_attributes);
|
||||
_cogl_bitmask_destroy (&context->enable_builtin_attributes_tmp);
|
||||
_cogl_bitmask_destroy (&context->enabled_texcoord_attributes);
|
||||
_cogl_bitmask_destroy (&context->enable_texcoord_attributes_tmp);
|
||||
_cogl_bitmask_destroy (&context->enabled_custom_attributes);
|
||||
_cogl_bitmask_destroy (&context->enable_custom_attributes_tmp);
|
||||
_cogl_bitmask_destroy (&context->changed_bits_tmp);
|
||||
|
||||
g_slist_free (context->texture_types);
|
||||
g_slist_free (context->buffer_types);
|
||||
@ -490,6 +506,9 @@ _cogl_context_free (CoglContext *context)
|
||||
g_ptr_array_free (context->uniform_names, TRUE);
|
||||
g_hash_table_destroy (context->uniform_name_hash);
|
||||
|
||||
g_hash_table_destroy (context->attribute_name_states_hash);
|
||||
g_array_free (context->attribute_name_index_map, TRUE);
|
||||
|
||||
g_byte_array_free (context->buffer_map_fallback_array, TRUE);
|
||||
|
||||
cogl_object_unref (context->display);
|
||||
|
@ -1372,8 +1372,10 @@ done:
|
||||
int attribute;
|
||||
CoglPipeline *authority =
|
||||
_cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_COLOR);
|
||||
int name_index = COGL_ATTRIBUTE_COLOR_NAME_INDEX;
|
||||
|
||||
attribute = _cogl_pipeline_progend_glsl_get_color_attribute (pipeline);
|
||||
attribute =
|
||||
_cogl_pipeline_progend_glsl_get_attrib_location (pipeline, name_index);
|
||||
if (attribute != -1)
|
||||
GE (ctx,
|
||||
glVertexAttrib4f (attribute,
|
||||
|
@ -33,22 +33,9 @@
|
||||
|
||||
extern const CoglPipelineProgend _cogl_pipeline_glsl_progend;
|
||||
|
||||
#ifdef HAVE_COGL_GLES2
|
||||
|
||||
int
|
||||
_cogl_pipeline_progend_glsl_get_position_attribute (CoglPipeline *pipeline);
|
||||
|
||||
int
|
||||
_cogl_pipeline_progend_glsl_get_color_attribute (CoglPipeline *pipeline);
|
||||
|
||||
int
|
||||
_cogl_pipeline_progend_glsl_get_normal_attribute (CoglPipeline *pipeline);
|
||||
|
||||
int
|
||||
_cogl_pipeline_progend_glsl_get_tex_coord_attribute (CoglPipeline *pipeline,
|
||||
int unit);
|
||||
|
||||
#endif /* HAVE_COGL_GLES2 */
|
||||
_cogl_pipeline_progend_glsl_get_attrib_location (CoglPipeline *pipeline,
|
||||
int name_index);
|
||||
|
||||
#endif /* __COGL_PIPELINE_PROGEND_GLSL_PRIVATE_H */
|
||||
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "cogl-pipeline-vertend-glsl-private.h"
|
||||
#include "cogl-pipeline-cache.h"
|
||||
#include "cogl-pipeline-state-private.h"
|
||||
#include "cogl-attribute-private.h"
|
||||
|
||||
#ifdef HAVE_COGL_GLES2
|
||||
|
||||
@ -116,18 +117,6 @@ typedef struct
|
||||
unsigned long dirty_builtin_uniforms;
|
||||
GLint builtin_uniform_locations[G_N_ELEMENTS (builtin_uniforms)];
|
||||
|
||||
/* Under GLES2 we can't use the builtin functions to set attribute
|
||||
pointers such as the vertex position. Instead the vertex
|
||||
attribute code needs to query the attribute numbers from the
|
||||
progend backend */
|
||||
int position_attribute_location;
|
||||
int color_attribute_location;
|
||||
int normal_attribute_location;
|
||||
int tex_coord0_attribute_location;
|
||||
/* We only allocate this array if more than one tex coord attribute
|
||||
is requested because most pipelines will only use one layer */
|
||||
GArray *tex_coord_attribute_locations;
|
||||
|
||||
GLint modelview_uniform;
|
||||
GLint projection_uniform;
|
||||
GLint mvp_uniform;
|
||||
@ -148,6 +137,9 @@ typedef struct
|
||||
uniform is actually set */
|
||||
GArray *uniform_locations;
|
||||
|
||||
/* Array of attribute locations. */
|
||||
GArray *attribute_locations;
|
||||
|
||||
UnitState *unit_state;
|
||||
} CoglPipelineProgramState;
|
||||
|
||||
@ -161,8 +153,6 @@ get_program_state (CoglPipeline *pipeline)
|
||||
|
||||
#define UNIFORM_LOCATION_UNKNOWN -2
|
||||
|
||||
#ifdef HAVE_COGL_GLES2
|
||||
|
||||
#define ATTRIBUTE_LOCATION_UNKNOWN -2
|
||||
|
||||
/* Under GLES2 the vertex attribute API needs to query the attribute
|
||||
@ -172,125 +162,66 @@ get_program_state (CoglPipeline *pipeline)
|
||||
cache. This should always be called after the pipeline is flushed
|
||||
so they can assert that the gl program is valid */
|
||||
|
||||
/* All attributes names get internally mapped to a global set of
|
||||
* sequential indices when they are setup which we need to need to
|
||||
* then be able to map to a GL attribute location once we have
|
||||
* a linked GLSL program */
|
||||
|
||||
int
|
||||
_cogl_pipeline_progend_glsl_get_position_attribute (CoglPipeline *pipeline)
|
||||
_cogl_pipeline_progend_glsl_get_attrib_location (CoglPipeline *pipeline,
|
||||
int name_index)
|
||||
{
|
||||
CoglPipelineProgramState *program_state = get_program_state (pipeline);
|
||||
int *locations;
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, -1);
|
||||
|
||||
_COGL_RETURN_VAL_IF_FAIL (program_state != NULL, -1);
|
||||
_COGL_RETURN_VAL_IF_FAIL (program_state->program != 0, -1);
|
||||
|
||||
if (program_state->position_attribute_location == ATTRIBUTE_LOCATION_UNKNOWN)
|
||||
GE_RET( program_state->position_attribute_location,
|
||||
ctx, glGetAttribLocation (program_state->program,
|
||||
"cogl_position_in") );
|
||||
if (G_UNLIKELY (program_state->attribute_locations == NULL))
|
||||
program_state->attribute_locations =
|
||||
g_array_new (FALSE, FALSE, sizeof (int));
|
||||
|
||||
return program_state->position_attribute_location;
|
||||
}
|
||||
|
||||
int
|
||||
_cogl_pipeline_progend_glsl_get_color_attribute (CoglPipeline *pipeline)
|
||||
{
|
||||
CoglPipelineProgramState *program_state = get_program_state (pipeline);
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, -1);
|
||||
|
||||
_COGL_RETURN_VAL_IF_FAIL (program_state != NULL, -1);
|
||||
_COGL_RETURN_VAL_IF_FAIL (program_state->program != 0, -1);
|
||||
|
||||
if (program_state->color_attribute_location == ATTRIBUTE_LOCATION_UNKNOWN)
|
||||
GE_RET( program_state->color_attribute_location,
|
||||
ctx, glGetAttribLocation (program_state->program,
|
||||
"cogl_color_in") );
|
||||
|
||||
return program_state->color_attribute_location;
|
||||
}
|
||||
|
||||
int
|
||||
_cogl_pipeline_progend_glsl_get_normal_attribute (CoglPipeline *pipeline)
|
||||
{
|
||||
CoglPipelineProgramState *program_state = get_program_state (pipeline);
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, -1);
|
||||
|
||||
_COGL_RETURN_VAL_IF_FAIL (program_state != NULL, -1);
|
||||
_COGL_RETURN_VAL_IF_FAIL (program_state->program != 0, -1);
|
||||
|
||||
if (program_state->normal_attribute_location == ATTRIBUTE_LOCATION_UNKNOWN)
|
||||
GE_RET( program_state->normal_attribute_location,
|
||||
ctx, glGetAttribLocation (program_state->program,
|
||||
"cogl_normal_in") );
|
||||
|
||||
return program_state->normal_attribute_location;
|
||||
}
|
||||
|
||||
int
|
||||
_cogl_pipeline_progend_glsl_get_tex_coord_attribute (CoglPipeline *pipeline,
|
||||
int unit)
|
||||
{
|
||||
CoglPipelineProgramState *program_state = get_program_state (pipeline);
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, -1);
|
||||
|
||||
_COGL_RETURN_VAL_IF_FAIL (program_state != NULL, -1);
|
||||
_COGL_RETURN_VAL_IF_FAIL (program_state->program != 0, -1);
|
||||
|
||||
if (unit == 0)
|
||||
if (G_UNLIKELY (program_state->attribute_locations->len <= name_index))
|
||||
{
|
||||
if (program_state->tex_coord0_attribute_location ==
|
||||
ATTRIBUTE_LOCATION_UNKNOWN)
|
||||
GE_RET( program_state->tex_coord0_attribute_location,
|
||||
ctx, glGetAttribLocation (program_state->program,
|
||||
"cogl_tex_coord0_in") );
|
||||
|
||||
return program_state->tex_coord0_attribute_location;
|
||||
int i = program_state->attribute_locations->len;
|
||||
g_array_set_size (program_state->attribute_locations, name_index + 1);
|
||||
for (; i < program_state->attribute_locations->len; i++)
|
||||
g_array_index (program_state->attribute_locations, int, i)
|
||||
= ATTRIBUTE_LOCATION_UNKNOWN;
|
||||
}
|
||||
else
|
||||
|
||||
locations = &g_array_index (program_state->attribute_locations, int, 0);
|
||||
|
||||
if (locations[name_index] == ATTRIBUTE_LOCATION_UNKNOWN)
|
||||
{
|
||||
char *name = g_strdup_printf ("cogl_tex_coord%i_in", unit);
|
||||
int *locations;
|
||||
CoglAttributeNameState *name_state =
|
||||
g_array_index (ctx->attribute_name_index_map,
|
||||
CoglAttributeNameState *, name_index);
|
||||
|
||||
if (program_state->tex_coord_attribute_locations == NULL)
|
||||
program_state->tex_coord_attribute_locations =
|
||||
g_array_new (FALSE, FALSE, sizeof (int));
|
||||
if (program_state->tex_coord_attribute_locations->len <= unit - 1)
|
||||
{
|
||||
int i = program_state->tex_coord_attribute_locations->len;
|
||||
g_array_set_size (program_state->tex_coord_attribute_locations, unit);
|
||||
for (; i < unit; i++)
|
||||
g_array_index (program_state->tex_coord_attribute_locations, int, i)
|
||||
= ATTRIBUTE_LOCATION_UNKNOWN;
|
||||
}
|
||||
_COGL_RETURN_VAL_IF_FAIL (name_state != NULL, 0);
|
||||
|
||||
locations = &g_array_index (program_state->tex_coord_attribute_locations,
|
||||
int, 0);
|
||||
|
||||
if (locations[unit - 1] == ATTRIBUTE_LOCATION_UNKNOWN)
|
||||
GE_RET( locations[unit - 1],
|
||||
ctx, glGetAttribLocation (program_state->program, name) );
|
||||
|
||||
g_free (name);
|
||||
|
||||
return locations[unit - 1];
|
||||
GE_RET( locations[name_index],
|
||||
ctx, glGetAttribLocation (program_state->program,
|
||||
name_state->name) );
|
||||
}
|
||||
|
||||
return locations[name_index];
|
||||
}
|
||||
|
||||
static void
|
||||
clear_attribute_cache (CoglPipelineProgramState *program_state)
|
||||
{
|
||||
program_state->position_attribute_location = ATTRIBUTE_LOCATION_UNKNOWN;
|
||||
program_state->color_attribute_location = ATTRIBUTE_LOCATION_UNKNOWN;
|
||||
program_state->normal_attribute_location = ATTRIBUTE_LOCATION_UNKNOWN;
|
||||
program_state->tex_coord0_attribute_location = ATTRIBUTE_LOCATION_UNKNOWN;
|
||||
if (program_state->tex_coord_attribute_locations)
|
||||
if (program_state->attribute_locations)
|
||||
{
|
||||
g_array_free (program_state->tex_coord_attribute_locations, TRUE);
|
||||
program_state->tex_coord_attribute_locations = NULL;
|
||||
g_array_free (program_state->attribute_locations, TRUE);
|
||||
program_state->attribute_locations = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_COGL_GLES2
|
||||
|
||||
static void
|
||||
clear_flushed_matrix_stacks (CoglPipelineProgramState *program_state)
|
||||
{
|
||||
@ -320,8 +251,8 @@ program_state_new (int n_layers)
|
||||
program_state->n_tex_coord_attribs = 0;
|
||||
program_state->unit_state = g_new (UnitState, n_layers);
|
||||
program_state->uniform_locations = NULL;
|
||||
program_state->attribute_locations = NULL;
|
||||
#ifdef HAVE_COGL_GLES2
|
||||
program_state->tex_coord_attribute_locations = NULL;
|
||||
program_state->flushed_modelview_stack = NULL;
|
||||
program_state->flushed_modelview_is_identity = FALSE;
|
||||
program_state->flushed_projection_stack = NULL;
|
||||
@ -347,12 +278,11 @@ destroy_program_state (void *user_data,
|
||||
|
||||
if (--program_state->ref_count == 0)
|
||||
{
|
||||
clear_attribute_cache (program_state);
|
||||
|
||||
#ifdef HAVE_COGL_GLES2
|
||||
if (ctx->driver == COGL_DRIVER_GLES2)
|
||||
{
|
||||
clear_attribute_cache (program_state);
|
||||
clear_flushed_matrix_stacks (program_state);
|
||||
}
|
||||
clear_flushed_matrix_stacks (program_state);
|
||||
#endif
|
||||
|
||||
if (program_state->program)
|
||||
@ -858,9 +788,12 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline,
|
||||
state.program_state = program_state;
|
||||
|
||||
if (program_changed)
|
||||
cogl_pipeline_foreach_layer (pipeline,
|
||||
get_uniform_cb,
|
||||
&state);
|
||||
{
|
||||
cogl_pipeline_foreach_layer (pipeline,
|
||||
get_uniform_cb,
|
||||
&state);
|
||||
clear_attribute_cache (program_state);
|
||||
}
|
||||
|
||||
state.unit = 0;
|
||||
state.update_all = (program_changed ||
|
||||
@ -877,7 +810,6 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline,
|
||||
{
|
||||
int i;
|
||||
|
||||
clear_attribute_cache (program_state);
|
||||
clear_flushed_matrix_stacks (program_state);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (builtin_uniforms); i++)
|
||||
|
66
cogl/cogl.c
66
cogl/cogl.c
@ -141,69 +141,6 @@ cogl_clear (const CoglColor *color, unsigned long buffers)
|
||||
cogl_framebuffer_clear (cogl_get_draw_framebuffer (), buffers, color);
|
||||
}
|
||||
|
||||
#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES)
|
||||
|
||||
static gboolean
|
||||
toggle_client_flag (CoglContext *ctx,
|
||||
unsigned long new_flags,
|
||||
unsigned long flag,
|
||||
GLenum gl_flag)
|
||||
{
|
||||
_COGL_RETURN_VAL_IF_FAIL (ctx->driver != COGL_DRIVER_GLES2, FALSE);
|
||||
|
||||
/* Toggles and caches a single client-side enable flag
|
||||
* on or off by comparing to current state
|
||||
*/
|
||||
if (new_flags & flag)
|
||||
{
|
||||
if (!(ctx->enable_flags & flag))
|
||||
{
|
||||
GE( ctx, glEnableClientState (gl_flag) );
|
||||
ctx->enable_flags |= flag;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else if (ctx->enable_flags & flag)
|
||||
{
|
||||
GE( ctx, glDisableClientState (gl_flag) );
|
||||
ctx->enable_flags &= ~flag;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
_cogl_enable (unsigned long flags)
|
||||
{
|
||||
/* This function essentially caches glEnable state() in the
|
||||
* hope of lessening number GL traffic.
|
||||
*/
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES)
|
||||
if (ctx->driver != COGL_DRIVER_GLES2)
|
||||
{
|
||||
toggle_client_flag (ctx, flags,
|
||||
COGL_ENABLE_VERTEX_ARRAY,
|
||||
GL_VERTEX_ARRAY);
|
||||
|
||||
toggle_client_flag (ctx, flags,
|
||||
COGL_ENABLE_COLOR_ARRAY,
|
||||
GL_COLOR_ARRAY);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned long
|
||||
_cogl_get_enable (void)
|
||||
{
|
||||
_COGL_GET_CONTEXT (ctx, 0);
|
||||
|
||||
return ctx->enable_flags;
|
||||
}
|
||||
|
||||
/* XXX: This API has been deprecated */
|
||||
void
|
||||
cogl_set_depth_test_enabled (gboolean setting)
|
||||
@ -645,7 +582,6 @@ cogl_read_pixels (int x,
|
||||
void
|
||||
cogl_begin_gl (void)
|
||||
{
|
||||
unsigned long enable_flags = 0;
|
||||
CoglPipeline *pipeline;
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
@ -697,8 +633,6 @@ cogl_begin_gl (void)
|
||||
FALSE,
|
||||
cogl_pipeline_get_n_layers (pipeline));
|
||||
|
||||
_cogl_enable (enable_flags);
|
||||
|
||||
/* Disable any cached vertex arrays */
|
||||
_cogl_attribute_disable_cached_arrays ();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user