snippet: Add a hook for the layer texture coordinate transformation
This adds a hook called COGL_SNIPPET_HOOK_TEXTURE_COORD_TRANSFORM. This can be used to alter the application of the layer user matrix to a texture coordinate or it can bypass it altogether. This is the first per-layer hook that affects the vertex shader state so the patch includes the boilerplate needed to get that to work. Reviewed-by: Robert Bragg <robert@linux.intel.com>
This commit is contained in:
parent
b7e15929b6
commit
68b3643b25
@ -79,6 +79,7 @@ typedef enum
|
|||||||
COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT_INDEX,
|
COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT_INDEX,
|
||||||
COGL_PIPELINE_LAYER_STATE_USER_MATRIX_INDEX,
|
COGL_PIPELINE_LAYER_STATE_USER_MATRIX_INDEX,
|
||||||
COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS_INDEX,
|
COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS_INDEX,
|
||||||
|
COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS_INDEX,
|
||||||
COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS_INDEX,
|
COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS_INDEX,
|
||||||
|
|
||||||
/* note: layers don't currently have any non-sparse state */
|
/* note: layers don't currently have any non-sparse state */
|
||||||
@ -117,6 +118,8 @@ typedef enum
|
|||||||
COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS =
|
COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS =
|
||||||
1L<<COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS_INDEX,
|
1L<<COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS_INDEX,
|
||||||
|
|
||||||
|
COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS =
|
||||||
|
1L<<COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS_INDEX,
|
||||||
COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS =
|
COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS =
|
||||||
1L<<COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS_INDEX,
|
1L<<COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS_INDEX,
|
||||||
|
|
||||||
@ -139,15 +142,18 @@ typedef enum
|
|||||||
COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT | \
|
COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT | \
|
||||||
COGL_PIPELINE_LAYER_STATE_USER_MATRIX | \
|
COGL_PIPELINE_LAYER_STATE_USER_MATRIX | \
|
||||||
COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS | \
|
COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS | \
|
||||||
|
COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS | \
|
||||||
COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS)
|
COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS)
|
||||||
|
|
||||||
#define COGL_PIPELINE_LAYER_STATE_MULTI_PROPERTY \
|
#define COGL_PIPELINE_LAYER_STATE_MULTI_PROPERTY \
|
||||||
(COGL_PIPELINE_LAYER_STATE_FILTERS | \
|
(COGL_PIPELINE_LAYER_STATE_FILTERS | \
|
||||||
COGL_PIPELINE_LAYER_STATE_WRAP_MODES | \
|
COGL_PIPELINE_LAYER_STATE_WRAP_MODES | \
|
||||||
COGL_PIPELINE_LAYER_STATE_COMBINE | \
|
COGL_PIPELINE_LAYER_STATE_COMBINE | \
|
||||||
|
COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS | \
|
||||||
COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS)
|
COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS)
|
||||||
|
|
||||||
#define COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN 0
|
#define COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN \
|
||||||
|
COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
@ -200,6 +206,7 @@ typedef struct
|
|||||||
|
|
||||||
gboolean point_sprite_coords;
|
gboolean point_sprite_coords;
|
||||||
|
|
||||||
|
CoglPipelineSnippetList vertex_snippets;
|
||||||
CoglPipelineSnippetList fragment_snippets;
|
CoglPipelineSnippetList fragment_snippets;
|
||||||
} CoglPipelineLayerBigState;
|
} CoglPipelineLayerBigState;
|
||||||
|
|
||||||
|
@ -78,6 +78,10 @@ gboolean
|
|||||||
_cogl_pipeline_layer_point_sprite_coords_equal (CoglPipelineLayer *authority0,
|
_cogl_pipeline_layer_point_sprite_coords_equal (CoglPipelineLayer *authority0,
|
||||||
CoglPipelineLayer *authority1);
|
CoglPipelineLayer *authority1);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
_cogl_pipeline_layer_vertex_snippets_equal (CoglPipelineLayer *authority0,
|
||||||
|
CoglPipelineLayer *authority1);
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
_cogl_pipeline_layer_fragment_snippets_equal (CoglPipelineLayer *authority0,
|
_cogl_pipeline_layer_fragment_snippets_equal (CoglPipelineLayer *authority0,
|
||||||
CoglPipelineLayer *authority1);
|
CoglPipelineLayer *authority1);
|
||||||
@ -127,6 +131,11 @@ _cogl_pipeline_layer_hash_point_sprite_state (CoglPipelineLayer *authority,
|
|||||||
CoglPipelineLayer **authorities,
|
CoglPipelineLayer **authorities,
|
||||||
CoglPipelineHashState *state);
|
CoglPipelineHashState *state);
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_pipeline_layer_hash_vertex_snippets_state (CoglPipelineLayer *authority,
|
||||||
|
CoglPipelineLayer **authorities,
|
||||||
|
CoglPipelineHashState *state);
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_pipeline_layer_hash_fragment_snippets_state (CoglPipelineLayer *authority,
|
_cogl_pipeline_layer_hash_fragment_snippets_state (CoglPipelineLayer *authority,
|
||||||
CoglPipelineLayer **authorities,
|
CoglPipelineLayer **authorities,
|
||||||
|
@ -775,6 +775,42 @@ cogl_pipeline_get_layer_point_sprite_coords_enabled (CoglPipeline *pipeline,
|
|||||||
return authority->big_state->point_sprite_coords;
|
return authority->big_state->point_sprite_coords;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_cogl_pipeline_layer_add_vertex_snippet (CoglPipeline *pipeline,
|
||||||
|
int layer_index,
|
||||||
|
CoglSnippet *snippet)
|
||||||
|
{
|
||||||
|
CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS;
|
||||||
|
CoglPipelineLayer *layer, *authority;
|
||||||
|
|
||||||
|
/* Note: this will ensure that the layer exists, creating one if it
|
||||||
|
* doesn't already.
|
||||||
|
*
|
||||||
|
* Note: If the layer already existed it's possibly owned by another
|
||||||
|
* pipeline. If the layer is created then it will be owned by
|
||||||
|
* pipeline. */
|
||||||
|
layer = _cogl_pipeline_get_layer (pipeline, layer_index);
|
||||||
|
|
||||||
|
/* Now find the ancestor of the layer that is the authority for the
|
||||||
|
* state we want to change */
|
||||||
|
authority = _cogl_pipeline_layer_get_authority (layer, change);
|
||||||
|
|
||||||
|
layer = _cogl_pipeline_layer_pre_change_notify (pipeline, layer, change);
|
||||||
|
|
||||||
|
_cogl_pipeline_snippet_list_add (&layer->big_state->vertex_snippets,
|
||||||
|
snippet);
|
||||||
|
|
||||||
|
/* If we weren't previously the authority on this state then we need
|
||||||
|
* to extended our differences mask and so it's possible that some
|
||||||
|
* of our ancestry will now become redundant, so we aim to reparent
|
||||||
|
* ourselves if that's true... */
|
||||||
|
if (layer != authority)
|
||||||
|
{
|
||||||
|
layer->differences |= change;
|
||||||
|
_cogl_pipeline_layer_prune_redundant_ancestry (layer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cogl_pipeline_layer_add_fragment_snippet (CoglPipeline *pipeline,
|
_cogl_pipeline_layer_add_fragment_snippet (CoglPipeline *pipeline,
|
||||||
int layer_index,
|
int layer_index,
|
||||||
@ -821,8 +857,9 @@ cogl_pipeline_add_layer_snippet (CoglPipeline *pipeline,
|
|||||||
_COGL_RETURN_IF_FAIL (snippet->hook >= COGL_SNIPPET_FIRST_LAYER_HOOK);
|
_COGL_RETURN_IF_FAIL (snippet->hook >= COGL_SNIPPET_FIRST_LAYER_HOOK);
|
||||||
|
|
||||||
if (snippet->hook < COGL_SNIPPET_FIRST_LAYER_FRAGMENT_HOOK)
|
if (snippet->hook < COGL_SNIPPET_FIRST_LAYER_FRAGMENT_HOOK)
|
||||||
/* TODO */
|
_cogl_pipeline_layer_add_vertex_snippet (pipeline,
|
||||||
g_assert_not_reached ();
|
layer_index,
|
||||||
|
snippet);
|
||||||
else
|
else
|
||||||
_cogl_pipeline_layer_add_fragment_snippet (pipeline,
|
_cogl_pipeline_layer_add_fragment_snippet (pipeline,
|
||||||
layer_index,
|
layer_index,
|
||||||
@ -966,6 +1003,16 @@ _cogl_pipeline_layer_point_sprite_coords_equal (CoglPipelineLayer *authority0,
|
|||||||
return big_state0->point_sprite_coords == big_state1->point_sprite_coords;
|
return big_state0->point_sprite_coords == big_state1->point_sprite_coords;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
_cogl_pipeline_layer_vertex_snippets_equal (CoglPipelineLayer *authority0,
|
||||||
|
CoglPipelineLayer *authority1)
|
||||||
|
{
|
||||||
|
return _cogl_pipeline_snippet_list_equal (&authority0->big_state->
|
||||||
|
vertex_snippets,
|
||||||
|
&authority1->big_state->
|
||||||
|
vertex_snippets);
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
_cogl_pipeline_layer_fragment_snippets_equal (CoglPipelineLayer *authority0,
|
_cogl_pipeline_layer_fragment_snippets_equal (CoglPipelineLayer *authority0,
|
||||||
CoglPipelineLayer *authority1)
|
CoglPipelineLayer *authority1)
|
||||||
@ -1729,6 +1776,15 @@ _cogl_pipeline_layer_hash_point_sprite_state (CoglPipelineLayer *authority,
|
|||||||
sizeof (big_state->point_sprite_coords));
|
sizeof (big_state->point_sprite_coords));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_pipeline_layer_hash_vertex_snippets_state (CoglPipelineLayer *authority,
|
||||||
|
CoglPipelineLayer **authorities,
|
||||||
|
CoglPipelineHashState *state)
|
||||||
|
{
|
||||||
|
_cogl_pipeline_snippet_list_hash (&authority->big_state->vertex_snippets,
|
||||||
|
&state->hash);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_pipeline_layer_hash_fragment_snippets_state (CoglPipelineLayer *authority,
|
_cogl_pipeline_layer_hash_fragment_snippets_state (CoglPipelineLayer *authority,
|
||||||
CoglPipelineLayer **authorities,
|
CoglPipelineLayer **authorities,
|
||||||
|
@ -114,6 +114,10 @@ _cogl_pipeline_layer_has_alpha (CoglPipelineLayer *layer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* All bets are off if the layer contains any snippets */
|
/* All bets are off if the layer contains any snippets */
|
||||||
|
snippets_authority = _cogl_pipeline_layer_get_authority
|
||||||
|
(layer, COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS);
|
||||||
|
if (!COGL_LIST_EMPTY (&snippets_authority->big_state->vertex_snippets))
|
||||||
|
return TRUE;
|
||||||
snippets_authority = _cogl_pipeline_layer_get_authority
|
snippets_authority = _cogl_pipeline_layer_get_authority
|
||||||
(layer, COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS);
|
(layer, COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS);
|
||||||
if (!COGL_LIST_EMPTY (&snippets_authority->big_state->fragment_snippets))
|
if (!COGL_LIST_EMPTY (&snippets_authority->big_state->fragment_snippets))
|
||||||
@ -211,6 +215,11 @@ _cogl_pipeline_layer_init_multi_property_sparse_state (
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS:
|
||||||
|
_cogl_pipeline_snippet_list_copy (&layer->big_state->vertex_snippets,
|
||||||
|
&authority->big_state->
|
||||||
|
vertex_snippets);
|
||||||
|
break;
|
||||||
case COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS:
|
case COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS:
|
||||||
_cogl_pipeline_snippet_list_copy (&layer->big_state->fragment_snippets,
|
_cogl_pipeline_snippet_list_copy (&layer->big_state->fragment_snippets,
|
||||||
&authority->big_state->
|
&authority->big_state->
|
||||||
@ -591,6 +600,12 @@ _cogl_pipeline_layer_equal (CoglPipelineLayer *layer0,
|
|||||||
_cogl_pipeline_layer_point_sprite_coords_equal))
|
_cogl_pipeline_layer_point_sprite_coords_equal))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
if (layers_difference & COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS &&
|
||||||
|
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS_INDEX,
|
||||||
|
authorities0, authorities1,
|
||||||
|
_cogl_pipeline_layer_vertex_snippets_equal))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (layers_difference & COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS &&
|
if (layers_difference & COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS &&
|
||||||
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS_INDEX,
|
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS_INDEX,
|
||||||
authorities0, authorities1,
|
authorities0, authorities1,
|
||||||
@ -609,6 +624,9 @@ _cogl_pipeline_layer_free (CoglPipelineLayer *layer)
|
|||||||
layer->texture != NULL)
|
layer->texture != NULL)
|
||||||
cogl_object_unref (layer->texture);
|
cogl_object_unref (layer->texture);
|
||||||
|
|
||||||
|
if (layer->differences & COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS)
|
||||||
|
_cogl_pipeline_snippet_list_free (&layer->big_state->vertex_snippets);
|
||||||
|
|
||||||
if (layer->differences & COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS)
|
if (layer->differences & COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS)
|
||||||
_cogl_pipeline_snippet_list_free (&layer->big_state->fragment_snippets);
|
_cogl_pipeline_snippet_list_free (&layer->big_state->fragment_snippets);
|
||||||
|
|
||||||
|
@ -68,6 +68,12 @@ typedef struct
|
|||||||
NULL */
|
NULL */
|
||||||
const char *return_variable;
|
const char *return_variable;
|
||||||
|
|
||||||
|
/* If this is TRUE then it won't allocate a separate variable for
|
||||||
|
the return value. Instead it is expected that the snippet will
|
||||||
|
modify one of the argument variables directly and that will be
|
||||||
|
returned */
|
||||||
|
gboolean return_variable_is_argument;
|
||||||
|
|
||||||
/* The argument names or NULL if there are none */
|
/* The argument names or NULL if there are none */
|
||||||
const char *arguments;
|
const char *arguments;
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ _cogl_pipeline_snippet_generate_code (const CoglPipelineSnippetData *data)
|
|||||||
")\n"
|
")\n"
|
||||||
"{\n");
|
"{\n");
|
||||||
|
|
||||||
if (data->return_type)
|
if (data->return_type && !data->return_variable_is_argument)
|
||||||
g_string_append_printf (data->source_buf,
|
g_string_append_printf (data->source_buf,
|
||||||
" %s %s;\n"
|
" %s %s;\n"
|
||||||
"\n",
|
"\n",
|
||||||
|
@ -1627,10 +1627,37 @@ _cogl_pipeline_has_non_layer_vertex_snippets (CoglPipeline *pipeline)
|
|||||||
return !COGL_LIST_EMPTY (&authority->big_state->vertex_snippets);
|
return !COGL_LIST_EMPTY (&authority->big_state->vertex_snippets);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
check_layer_has_vertex_snippet (CoglPipelineLayer *layer,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
unsigned long state = COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS;
|
||||||
|
CoglPipelineLayer *authority =
|
||||||
|
_cogl_pipeline_layer_get_authority (layer, state);
|
||||||
|
gboolean *found_vertex_snippet = user_data;
|
||||||
|
|
||||||
|
if (!COGL_LIST_EMPTY (&authority->big_state->vertex_snippets))
|
||||||
|
{
|
||||||
|
*found_vertex_snippet = TRUE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
_cogl_pipeline_has_vertex_snippets (CoglPipeline *pipeline)
|
_cogl_pipeline_has_vertex_snippets (CoglPipeline *pipeline)
|
||||||
{
|
{
|
||||||
return _cogl_pipeline_has_non_layer_vertex_snippets (pipeline);
|
gboolean found_vertex_snippet = FALSE;
|
||||||
|
|
||||||
|
if (_cogl_pipeline_has_non_layer_vertex_snippets (pipeline))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
_cogl_pipeline_foreach_layer_internal (pipeline,
|
||||||
|
check_layer_has_vertex_snippet,
|
||||||
|
&found_vertex_snippet);
|
||||||
|
|
||||||
|
return found_vertex_snippet;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
|
@ -140,6 +140,15 @@ get_vertex_snippets (CoglPipeline *pipeline)
|
|||||||
return &pipeline->big_state->vertex_snippets;
|
return &pipeline->big_state->vertex_snippets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static CoglPipelineSnippetList *
|
||||||
|
get_layer_vertex_snippets (CoglPipelineLayer *layer)
|
||||||
|
{
|
||||||
|
unsigned long state = COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS;
|
||||||
|
layer = _cogl_pipeline_layer_get_authority (layer, state);
|
||||||
|
|
||||||
|
return &layer->big_state->vertex_snippets;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
_cogl_pipeline_vertend_glsl_start (CoglPipeline *pipeline,
|
_cogl_pipeline_vertend_glsl_start (CoglPipeline *pipeline,
|
||||||
int n_layers,
|
int n_layers,
|
||||||
@ -293,6 +302,7 @@ _cogl_pipeline_vertend_glsl_add_layer (CoglPipeline *pipeline,
|
|||||||
unsigned long layers_difference)
|
unsigned long layers_difference)
|
||||||
{
|
{
|
||||||
CoglPipelineShaderState *shader_state;
|
CoglPipelineShaderState *shader_state;
|
||||||
|
CoglPipelineSnippetData snippet_data;
|
||||||
int unit_index;
|
int unit_index;
|
||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, FALSE);
|
_COGL_GET_CONTEXT (ctx, FALSE);
|
||||||
@ -338,10 +348,47 @@ _cogl_pipeline_vertend_glsl_add_layer (CoglPipeline *pipeline,
|
|||||||
* avoid setting them if not
|
* avoid setting them if not
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
g_string_append_printf (shader_state->header,
|
||||||
|
"vec4\n"
|
||||||
|
"cogl_real_transform_layer%i (mat4 matrix, "
|
||||||
|
"vec4 tex_coord)\n"
|
||||||
|
"{\n"
|
||||||
|
" return matrix * tex_coord;\n"
|
||||||
|
"}\n",
|
||||||
|
unit_index);
|
||||||
|
|
||||||
|
/* Wrap the layer code in any snippets that have been hooked */
|
||||||
|
memset (&snippet_data, 0, sizeof (snippet_data));
|
||||||
|
snippet_data.snippets = get_layer_vertex_snippets (layer);
|
||||||
|
snippet_data.hook = COGL_SNIPPET_HOOK_TEXTURE_COORD_TRANSFORM;
|
||||||
|
snippet_data.chain_function = g_strdup_printf ("cogl_real_transform_layer%i",
|
||||||
|
unit_index);
|
||||||
|
snippet_data.final_name = g_strdup_printf ("cogl_transform_layer%i",
|
||||||
|
unit_index);
|
||||||
|
snippet_data.function_prefix = g_strdup_printf ("cogl_transform_layer%i",
|
||||||
|
unit_index);
|
||||||
|
snippet_data.return_type = "vec4";
|
||||||
|
snippet_data.return_variable = "cogl_tex_coord";
|
||||||
|
snippet_data.return_variable_is_argument = TRUE;
|
||||||
|
snippet_data.arguments = "cogl_matrix, cogl_tex_coord";
|
||||||
|
snippet_data.argument_declarations = "mat4 cogl_matrix, vec4 cogl_tex_coord";
|
||||||
|
snippet_data.source_buf = shader_state->header;
|
||||||
|
|
||||||
|
_cogl_pipeline_snippet_generate_code (&snippet_data);
|
||||||
|
|
||||||
|
g_free ((char *) snippet_data.chain_function);
|
||||||
|
g_free ((char *) snippet_data.final_name);
|
||||||
|
g_free ((char *) snippet_data.function_prefix);
|
||||||
|
|
||||||
g_string_append_printf (shader_state->source,
|
g_string_append_printf (shader_state->source,
|
||||||
" cogl_tex_coord_out[%i] = "
|
" cogl_tex_coord_out[%i] = "
|
||||||
"cogl_texture_matrix[%i] * cogl_tex_coord%i_in;\n",
|
"cogl_transform_layer%i (cogl_texture_matrix[%i],\n"
|
||||||
unit_index, unit_index, unit_index);
|
" "
|
||||||
|
" cogl_tex_coord%i_in);\n",
|
||||||
|
unit_index,
|
||||||
|
unit_index,
|
||||||
|
unit_index,
|
||||||
|
unit_index);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -2612,6 +2612,9 @@ _cogl_pipeline_init_layer_state_hash_functions (void)
|
|||||||
layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_USER_MATRIX_INDEX] =
|
layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_USER_MATRIX_INDEX] =
|
||||||
_cogl_pipeline_layer_hash_user_matrix_state;
|
_cogl_pipeline_layer_hash_user_matrix_state;
|
||||||
_index = COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS_INDEX;
|
_index = COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS_INDEX;
|
||||||
|
layer_state_hash_functions[_index] =
|
||||||
|
_cogl_pipeline_layer_hash_point_sprite_state;
|
||||||
|
_index = COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS_INDEX;
|
||||||
layer_state_hash_functions[_index] =
|
layer_state_hash_functions[_index] =
|
||||||
_cogl_pipeline_layer_hash_point_sprite_state;
|
_cogl_pipeline_layer_hash_point_sprite_state;
|
||||||
_index = COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS_INDEX;
|
_index = COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS_INDEX;
|
||||||
@ -2619,7 +2622,7 @@ _cogl_pipeline_init_layer_state_hash_functions (void)
|
|||||||
_cogl_pipeline_layer_hash_fragment_snippets_state;
|
_cogl_pipeline_layer_hash_fragment_snippets_state;
|
||||||
|
|
||||||
/* So we get a big error if we forget to update this code! */
|
/* So we get a big error if we forget to update this code! */
|
||||||
g_assert (COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT == 10);
|
g_assert (COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT == 11);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -54,6 +54,8 @@ typedef struct _CoglSnippet CoglSnippet;
|
|||||||
* stage of the pipeline.
|
* stage of the pipeline.
|
||||||
* @COGL_SNIPPET_HOOK_FRAGMENT: A hook for the entire fragment
|
* @COGL_SNIPPET_HOOK_FRAGMENT: A hook for the entire fragment
|
||||||
* processing stage of the pipeline.
|
* processing stage of the pipeline.
|
||||||
|
* @COGL_SNIPPET_HOOK_TEXTURE_COORD_TRANSFORM: A hook for applying the
|
||||||
|
* layer matrix to a texture coordinate for a layer.
|
||||||
* @COGL_SNIPPET_HOOK_LAYER_FRAGMENT: A hook for the fragment
|
* @COGL_SNIPPET_HOOK_LAYER_FRAGMENT: A hook for the fragment
|
||||||
* processing of a particular layer.
|
* processing of a particular layer.
|
||||||
* @COGL_SNIPPET_HOOK_TEXTURE_LOOKUP: A hook for the texture lookup
|
* @COGL_SNIPPET_HOOK_TEXTURE_LOOKUP: A hook for the texture lookup
|
||||||
@ -129,6 +131,46 @@ typedef struct _CoglSnippet CoglSnippet;
|
|||||||
* </glossdef>
|
* </glossdef>
|
||||||
* </glossentry>
|
* </glossentry>
|
||||||
* <glossentry>
|
* <glossentry>
|
||||||
|
* <glossterm>%COGL_SNIPPET_HOOK_TEXTURE_COORD_TRANSFORM</glossterm>
|
||||||
|
* Adds a shader snippet that will hook on to the texture coordinate
|
||||||
|
* transformation of a particular layer. This can be used to replace
|
||||||
|
* the processing for a layer or to modify the results.
|
||||||
|
* </para>
|
||||||
|
* <para>
|
||||||
|
* Within the snippet code for this hook there are two extra
|
||||||
|
* variables. The first is a mat4 called cogl_matrix which represents
|
||||||
|
* the user matrix for this layer. The second is called cogl_tex_coord
|
||||||
|
* and represents the incoming and outgoing texture coordinate. On
|
||||||
|
* entry to the hook, cogl_tex_coord contains the value of the
|
||||||
|
* corresponding texture coordinate attribute for this layer. The hook
|
||||||
|
* is expected to modify this variable. The output will be passed as a
|
||||||
|
* varying to the fragment processing stage. The default code will
|
||||||
|
* just multiply cogl_matrix by cogl_tex_coord and store the result in
|
||||||
|
* cogl_tex_coord.
|
||||||
|
* </para>
|
||||||
|
* <para>
|
||||||
|
* The ‘declarations’ string in @snippet will be inserted in the
|
||||||
|
* global scope of the shader. Use this to declare any uniforms,
|
||||||
|
* attributes or functions that the snippet requires.
|
||||||
|
* </para>
|
||||||
|
* <para>
|
||||||
|
* The ‘pre’ string in @snippet will be inserted just before the
|
||||||
|
* fragment processing for this layer. At this point cogl_tex_coord
|
||||||
|
* still contains the value of the texture coordinate attribute.
|
||||||
|
* </para>
|
||||||
|
* <para>
|
||||||
|
* If a ‘replace’ string is given then this will be used instead of
|
||||||
|
* the default fragment processing for this layer. The snippet can
|
||||||
|
* modify cogl_tex_coord or leave it as is to apply no transformation.
|
||||||
|
* </para>
|
||||||
|
* <para>
|
||||||
|
* The ‘post’ string in @snippet will be inserted just after the
|
||||||
|
* transformation. At this point cogl_tex_coord will contain the
|
||||||
|
* results of the transformation but it can be further modified by the
|
||||||
|
* snippet.
|
||||||
|
* </para>
|
||||||
|
* </glossentry>
|
||||||
|
* <glossentry>
|
||||||
* <glossterm>%COGL_SNIPPET_HOOK_LAYER_FRAGMENT</glossterm>
|
* <glossterm>%COGL_SNIPPET_HOOK_LAYER_FRAGMENT</glossterm>
|
||||||
* Adds a shader snippet that will hook on to the fragment processing
|
* Adds a shader snippet that will hook on to the fragment processing
|
||||||
* of a particular layer. This can be used to replace the processing
|
* of a particular layer. This can be used to replace the processing
|
||||||
@ -209,8 +251,7 @@ typedef enum {
|
|||||||
COGL_SNIPPET_HOOK_FRAGMENT = 2048,
|
COGL_SNIPPET_HOOK_FRAGMENT = 2048,
|
||||||
|
|
||||||
/* Per layer vertex hooks */
|
/* Per layer vertex hooks */
|
||||||
/* TODO */
|
COGL_SNIPPET_HOOK_TEXTURE_COORD_TRANSFORM = 4096,
|
||||||
/* ... = 4096 */
|
|
||||||
|
|
||||||
/* Per layer fragment hooks */
|
/* Per layer fragment hooks */
|
||||||
COGL_SNIPPET_HOOK_LAYER_FRAGMENT = 6144,
|
COGL_SNIPPET_HOOK_LAYER_FRAGMENT = 6144,
|
||||||
|
@ -45,6 +45,7 @@ paint (TestState *state)
|
|||||||
{
|
{
|
||||||
CoglPipeline *pipeline;
|
CoglPipeline *pipeline;
|
||||||
CoglSnippet *snippet;
|
CoglSnippet *snippet;
|
||||||
|
CoglMatrix matrix;
|
||||||
CoglColor color;
|
CoglColor color;
|
||||||
int location;
|
int location;
|
||||||
int i;
|
int i;
|
||||||
@ -268,7 +269,7 @@ paint (TestState *state)
|
|||||||
cogl_pop_source ();
|
cogl_pop_source ();
|
||||||
cogl_object_unref (pipeline);
|
cogl_object_unref (pipeline);
|
||||||
|
|
||||||
/* Test replacing the layer code */
|
/* Test replacing the fragment layer code */
|
||||||
pipeline = create_texture_pipeline ();
|
pipeline = create_texture_pipeline ();
|
||||||
|
|
||||||
snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_LAYER_FRAGMENT, NULL, NULL);
|
snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_LAYER_FRAGMENT, NULL, NULL);
|
||||||
@ -291,7 +292,7 @@ paint (TestState *state)
|
|||||||
cogl_pop_source ();
|
cogl_pop_source ();
|
||||||
cogl_object_unref (pipeline);
|
cogl_object_unref (pipeline);
|
||||||
|
|
||||||
/* Test modifying the layer code */
|
/* Test modifying the fragment layer code */
|
||||||
pipeline = cogl_pipeline_new ();
|
pipeline = cogl_pipeline_new ();
|
||||||
|
|
||||||
cogl_pipeline_set_uniform_1f (pipeline,
|
cogl_pipeline_set_uniform_1f (pipeline,
|
||||||
@ -311,6 +312,45 @@ paint (TestState *state)
|
|||||||
cogl_pop_source ();
|
cogl_pop_source ();
|
||||||
cogl_object_unref (pipeline);
|
cogl_object_unref (pipeline);
|
||||||
|
|
||||||
|
/* Test modifying the vertex layer code */
|
||||||
|
pipeline = create_texture_pipeline ();
|
||||||
|
|
||||||
|
cogl_matrix_init_identity (&matrix);
|
||||||
|
cogl_matrix_translate (&matrix, 0.0f, 1.0f, 0.0f);
|
||||||
|
cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix);
|
||||||
|
|
||||||
|
snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_TEXTURE_COORD_TRANSFORM,
|
||||||
|
NULL,
|
||||||
|
"cogl_tex_coord.x = 1.0;");
|
||||||
|
cogl_pipeline_add_layer_snippet (pipeline, 0, snippet);
|
||||||
|
cogl_object_unref (snippet);
|
||||||
|
|
||||||
|
cogl_push_source (pipeline);
|
||||||
|
cogl_rectangle_with_texture_coords (130, 0, 140, 10,
|
||||||
|
0, 0, 0, 0);
|
||||||
|
cogl_pop_source ();
|
||||||
|
cogl_object_unref (pipeline);
|
||||||
|
|
||||||
|
/* Test replacing the vertex layer code */
|
||||||
|
pipeline = create_texture_pipeline ();
|
||||||
|
|
||||||
|
cogl_matrix_init_identity (&matrix);
|
||||||
|
cogl_matrix_translate (&matrix, 0.0f, 1.0f, 0.0f);
|
||||||
|
cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix);
|
||||||
|
|
||||||
|
snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_TEXTURE_COORD_TRANSFORM,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
cogl_snippet_set_replace (snippet, "cogl_tex_coord.x = 1.0;\n");
|
||||||
|
cogl_pipeline_add_layer_snippet (pipeline, 0, snippet);
|
||||||
|
cogl_object_unref (snippet);
|
||||||
|
|
||||||
|
cogl_push_source (pipeline);
|
||||||
|
cogl_rectangle_with_texture_coords (140, 0, 150, 10,
|
||||||
|
0, 0, 0, 0);
|
||||||
|
cogl_pop_source ();
|
||||||
|
cogl_object_unref (pipeline);
|
||||||
|
|
||||||
/* Sanity check modifying the snippet */
|
/* Sanity check modifying the snippet */
|
||||||
snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, "foo", "bar");
|
snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, "foo", "bar");
|
||||||
g_assert_cmpstr (cogl_snippet_get_declarations (snippet), ==, "foo");
|
g_assert_cmpstr (cogl_snippet_get_declarations (snippet), ==, "foo");
|
||||||
@ -363,6 +403,8 @@ validate_result (void)
|
|||||||
test_utils_check_pixel (105, 5, 0xff0000ff);
|
test_utils_check_pixel (105, 5, 0xff0000ff);
|
||||||
test_utils_check_pixel (115, 5, 0xff00ffff);
|
test_utils_check_pixel (115, 5, 0xff00ffff);
|
||||||
test_utils_check_pixel (125, 5, 0xff80ffff);
|
test_utils_check_pixel (125, 5, 0xff80ffff);
|
||||||
|
test_utils_check_pixel (135, 5, 0xffff00ff);
|
||||||
|
test_utils_check_pixel (145, 5, 0x00ff00ff);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
Loading…
Reference in New Issue
Block a user