mirror of
https://github.com/brl/mutter.git
synced 2024-11-12 17:27:03 -05:00
deform-effect: Use CoglPrimitives instead of CoglVertexBuffers
This changes ClutterDeformEffect to use a CoglAttributeBuffer with a CoglPrimitive instead of the old CoglVertexBuffer. The old vertex buffer code is now implemented in terms of the attribute buffer code and it will eventually be deprecated. Using CoglPrimitives should be slightly more efficient. This also changes the struct we store the vertices to be CoglVertexP3T2C4 instead of CoglTextureVertex. The latter is technically not compatible with neither vertex buffers nor attribute buffers because it contains a CoglColor and the internal members of that are private so it is not valid to assume it contains 4 bytes and use that as an attribute. Also it contains padding so it ends up redundantly creating a larger buffer. CoglTextureVertex is in the public API for the deform_vertex virtual so we still have to maintain that. Instead of directly manipulating the array to upload, the application is now passed a stack allocated temporary struct which gets converted to a CoglVertexP3T2C4. This also means that we can map the buffer as write only and still let the application read-write the vertex. The paint debug code to draw line strips for the deform mesh was previously trying to set a red source material. However this wasn't working because the material color was being overwritten by the color attribute in the vertex buffer. This patch fixes that by creating a seperate primitive for the lines and not adding the color attribute. The lines code was also drawing both the front and back indices. I don't think that entirely makes sense so I've just changed it to draw only the front indices. Maybe painting both would make more sense if backface culling was still enabled. https://bugzilla.gnome.org/show_bug.cgi?id=663636
This commit is contained in:
parent
b281f2090a
commit
8a752d674b
@ -74,13 +74,16 @@ struct _ClutterDeformEffectPrivate
|
||||
gint x_tiles;
|
||||
gint y_tiles;
|
||||
|
||||
CoglHandle vbo;
|
||||
CoglAttributeBuffer *buffer;
|
||||
|
||||
CoglHandle indices;
|
||||
CoglHandle back_indices;
|
||||
gint n_indices;
|
||||
/* These two primitives use the same attributes but with different
|
||||
indices */
|
||||
CoglPrimitive *front_primitive;
|
||||
CoglPrimitive *back_primitive;
|
||||
|
||||
CoglTextureVertex *vertices;
|
||||
CoglPrimitive *lines_primitive;
|
||||
|
||||
gint n_vertices;
|
||||
|
||||
gulong allocation_id;
|
||||
|
||||
@ -172,10 +175,11 @@ clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect)
|
||||
ClutterDeformEffectPrivate *priv = self->priv;
|
||||
gboolean is_depth_enabled, is_cull_enabled;
|
||||
CoglHandle material;
|
||||
gint n_tiles;
|
||||
|
||||
if (priv->is_dirty)
|
||||
{
|
||||
gboolean mapped_buffer;
|
||||
CoglVertexP3T2C4 *verts;
|
||||
ClutterActor *actor;
|
||||
gfloat width, height;
|
||||
guint opacity;
|
||||
@ -190,50 +194,79 @@ clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect)
|
||||
if (!clutter_offscreen_effect_get_target_size (effect, &width, &height))
|
||||
clutter_actor_get_size (actor, &width, &height);
|
||||
|
||||
/* XXX ideally, the sub-classes should tell us what they
|
||||
* changed in the texture vertices; we then would be able to
|
||||
* avoid resubmitting the same data, if it did not change. for
|
||||
* the time being, we resubmit everything
|
||||
*/
|
||||
verts = cogl_buffer_map (COGL_BUFFER (priv->buffer),
|
||||
COGL_BUFFER_ACCESS_WRITE,
|
||||
COGL_BUFFER_MAP_HINT_DISCARD);
|
||||
|
||||
/* If the map failed then we'll resort to allocating a temporary
|
||||
buffer */
|
||||
if (verts == NULL)
|
||||
{
|
||||
mapped_buffer = FALSE;
|
||||
verts = g_malloc (sizeof (*verts) * priv->n_vertices);
|
||||
}
|
||||
else
|
||||
mapped_buffer = TRUE;
|
||||
|
||||
for (i = 0; i < priv->y_tiles + 1; i++)
|
||||
{
|
||||
for (j = 0; j < priv->x_tiles + 1; j++)
|
||||
{
|
||||
CoglTextureVertex *vertex;
|
||||
CoglVertexP3T2C4 *vertex_out;
|
||||
CoglTextureVertex vertex;
|
||||
|
||||
vertex = &priv->vertices[(i * (priv->x_tiles + 1)) + j];
|
||||
/* CoglTextureVertex isn't an ideal structure to use for
|
||||
this because it contains a CoglColor. The internal
|
||||
layout of CoglColor is mean to be private so Clutter
|
||||
can not pass a pointer to it as a vertex
|
||||
attribute. Also it contains padding so we end up
|
||||
storing more data in the vertex buffer than we need
|
||||
to. Instead we let the application modify a dummy
|
||||
vertex and then copy the details back out to a more
|
||||
well-defined struct */
|
||||
|
||||
vertex->tx = (float) j / priv->x_tiles;
|
||||
vertex->ty = (float) i / priv->y_tiles;
|
||||
vertex.tx = (float) j / priv->x_tiles;
|
||||
vertex.ty = (float) i / priv->y_tiles;
|
||||
|
||||
vertex->x = width * vertex->tx;
|
||||
vertex->y = height * vertex->ty;
|
||||
vertex->z = 0.0f;
|
||||
vertex.x = width * vertex.tx;
|
||||
vertex.y = height * vertex.ty;
|
||||
vertex.z = 0.0f;
|
||||
|
||||
cogl_color_init_from_4ub (&vertex->color, 255, 255, 255, opacity);
|
||||
cogl_color_init_from_4ub (&vertex.color, 255, 255, 255, opacity);
|
||||
|
||||
_clutter_deform_effect_deform_vertex (self, width, height, vertex);
|
||||
_clutter_deform_effect_deform_vertex (self,
|
||||
width, height,
|
||||
&vertex);
|
||||
|
||||
vertex_out = verts + i * (priv->x_tiles + 1) + j;
|
||||
|
||||
vertex_out->x = vertex.x;
|
||||
vertex_out->y = vertex.y;
|
||||
vertex_out->z = vertex.z;
|
||||
vertex_out->s = vertex.tx;
|
||||
vertex_out->t = vertex.ty;
|
||||
vertex_out->r = cogl_color_get_red_byte (&vertex.color);
|
||||
vertex_out->g = cogl_color_get_green_byte (&vertex.color);
|
||||
vertex_out->b = cogl_color_get_blue_byte (&vertex.color);
|
||||
vertex_out->a = cogl_color_get_alpha_byte (&vertex.color);
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX in theory, the sub-classes should tell us what they changed
|
||||
* in the texture vertices; we then would be able to avoid resubmitting
|
||||
* the same data, if it did not change. for the time being, we resubmit
|
||||
* everything
|
||||
*/
|
||||
cogl_vertex_buffer_add (priv->vbo, "gl_Vertex",
|
||||
3,
|
||||
COGL_ATTRIBUTE_TYPE_FLOAT,
|
||||
FALSE,
|
||||
sizeof (CoglTextureVertex),
|
||||
&priv->vertices->x);
|
||||
cogl_vertex_buffer_add (priv->vbo, "gl_MultiTexCoord0",
|
||||
2,
|
||||
COGL_ATTRIBUTE_TYPE_FLOAT,
|
||||
FALSE,
|
||||
sizeof (CoglTextureVertex),
|
||||
&priv->vertices->tx);
|
||||
cogl_vertex_buffer_add (priv->vbo, "gl_Color",
|
||||
4,
|
||||
COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE,
|
||||
FALSE,
|
||||
sizeof (CoglTextureVertex),
|
||||
&priv->vertices->color);
|
||||
if (mapped_buffer)
|
||||
cogl_buffer_unmap (COGL_BUFFER (priv->buffer));
|
||||
else
|
||||
{
|
||||
cogl_buffer_set_data (COGL_BUFFER (priv->buffer),
|
||||
0, /* offset */
|
||||
verts,
|
||||
sizeof (*verts) * priv->n_vertices);
|
||||
g_free (verts);
|
||||
}
|
||||
|
||||
priv->is_dirty = FALSE;
|
||||
}
|
||||
@ -252,34 +285,22 @@ clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect)
|
||||
else if (priv->back_material == COGL_INVALID_HANDLE && is_cull_enabled)
|
||||
cogl_set_backface_culling_enabled (FALSE);
|
||||
|
||||
n_tiles = (priv->x_tiles + 1) * (priv->y_tiles + 1);
|
||||
|
||||
/* draw the front */
|
||||
material = clutter_offscreen_effect_get_target (effect);
|
||||
if (material != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cogl_set_source (material);
|
||||
cogl_vertex_buffer_draw_elements (priv->vbo,
|
||||
COGL_VERTICES_MODE_TRIANGLE_STRIP,
|
||||
priv->indices,
|
||||
0,
|
||||
n_tiles,
|
||||
0,
|
||||
priv->n_indices);
|
||||
cogl_push_source (material);
|
||||
cogl_primitive_draw (priv->front_primitive);
|
||||
cogl_pop_source ();
|
||||
}
|
||||
|
||||
/* draw the back */
|
||||
material = priv->back_material;
|
||||
if (material != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cogl_set_source (priv->back_material);
|
||||
cogl_vertex_buffer_draw_elements (priv->vbo,
|
||||
COGL_VERTICES_MODE_TRIANGLE_STRIP,
|
||||
priv->back_indices,
|
||||
0,
|
||||
n_tiles,
|
||||
0,
|
||||
priv->n_indices);
|
||||
cogl_push_source (material);
|
||||
cogl_primitive_draw (priv->back_primitive);
|
||||
cogl_pop_source ();
|
||||
}
|
||||
|
||||
/* restore the previous state */
|
||||
@ -291,24 +312,10 @@ clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect)
|
||||
else if (priv->back_material == COGL_INVALID_HANDLE && is_cull_enabled)
|
||||
cogl_set_backface_culling_enabled (TRUE);
|
||||
|
||||
if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_DEFORM_TILES))
|
||||
if (G_UNLIKELY (priv->lines_primitive != NULL))
|
||||
{
|
||||
cogl_set_source_color4f (1.0, 0, 0, 1.0);
|
||||
cogl_vertex_buffer_draw_elements (priv->vbo,
|
||||
COGL_VERTICES_MODE_LINE_STRIP,
|
||||
priv->indices,
|
||||
0,
|
||||
n_tiles,
|
||||
0,
|
||||
priv->n_indices);
|
||||
|
||||
cogl_vertex_buffer_draw_elements (priv->vbo,
|
||||
COGL_VERTICES_MODE_LINE_STRIP,
|
||||
priv->back_indices,
|
||||
0,
|
||||
n_tiles,
|
||||
0,
|
||||
priv->n_indices);
|
||||
cogl_primitive_draw (priv->lines_primitive);
|
||||
}
|
||||
}
|
||||
|
||||
@ -317,49 +324,60 @@ clutter_deform_effect_free_arrays (ClutterDeformEffect *self)
|
||||
{
|
||||
ClutterDeformEffectPrivate *priv = self->priv;
|
||||
|
||||
if (priv->vbo != COGL_INVALID_HANDLE)
|
||||
if (priv->buffer)
|
||||
{
|
||||
cogl_handle_unref (priv->vbo);
|
||||
priv->vbo = COGL_INVALID_HANDLE;
|
||||
cogl_object_unref (priv->buffer);
|
||||
priv->buffer = NULL;
|
||||
}
|
||||
|
||||
if (priv->indices != COGL_INVALID_HANDLE)
|
||||
if (priv->front_primitive)
|
||||
{
|
||||
cogl_handle_unref (priv->indices);
|
||||
priv->indices = COGL_INVALID_HANDLE;
|
||||
cogl_object_unref (priv->front_primitive);
|
||||
priv->front_primitive = NULL;
|
||||
}
|
||||
|
||||
g_free (priv->vertices);
|
||||
priv->vertices = NULL;
|
||||
if (priv->back_primitive)
|
||||
{
|
||||
cogl_object_unref (priv->back_primitive);
|
||||
priv->back_primitive = NULL;
|
||||
}
|
||||
|
||||
if (priv->lines_primitive)
|
||||
{
|
||||
cogl_object_unref (priv->lines_primitive);
|
||||
priv->lines_primitive = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_deform_effect_init_arrays (ClutterDeformEffect *self)
|
||||
{
|
||||
ClutterDeformEffectPrivate *priv = self->priv;
|
||||
GLushort *static_indices, *static_back_indices;
|
||||
GLushort *idx, *back_idx;
|
||||
gint x, y, direction;
|
||||
gint n_tiles;
|
||||
guint16 *static_front_indices, *static_back_indices;
|
||||
CoglIndices *front_indices, *back_indices;
|
||||
CoglAttribute *attributes[3];
|
||||
guint16 *front_idx, *back_idx;
|
||||
gint x, y, direction, n_indices;
|
||||
int i;
|
||||
|
||||
clutter_deform_effect_free_arrays (self);
|
||||
|
||||
priv->n_indices = (2 + 2 * priv->x_tiles)
|
||||
* priv->y_tiles
|
||||
+ (priv->y_tiles - 1);
|
||||
n_indices = ((2 + 2 * priv->x_tiles)
|
||||
* priv->y_tiles
|
||||
+ (priv->y_tiles - 1));
|
||||
|
||||
static_indices = g_new (GLushort, priv->n_indices);
|
||||
static_back_indices = g_new (GLushort, priv->n_indices);
|
||||
static_front_indices = g_new (guint16, n_indices);
|
||||
static_back_indices = g_new (guint16, n_indices);
|
||||
|
||||
#define MESH_INDEX(x,y) ((y) * (priv->x_tiles + 1) + (x))
|
||||
|
||||
/* compute all the triangles from the various tiles */
|
||||
direction = 1;
|
||||
|
||||
idx = static_indices;
|
||||
idx[0] = MESH_INDEX (0, 0);
|
||||
idx[1] = MESH_INDEX (0, 1);
|
||||
idx += 2;
|
||||
front_idx = static_front_indices;
|
||||
front_idx[0] = MESH_INDEX (0, 0);
|
||||
front_idx[1] = MESH_INDEX (0, 1);
|
||||
front_idx += 2;
|
||||
|
||||
back_idx = static_back_indices;
|
||||
back_idx[0] = MESH_INDEX (priv->x_tiles, 0);
|
||||
@ -372,22 +390,22 @@ clutter_deform_effect_init_arrays (ClutterDeformEffect *self)
|
||||
{
|
||||
if (direction)
|
||||
{
|
||||
idx[0] = MESH_INDEX (x + 1, y);
|
||||
idx[1] = MESH_INDEX (x + 1, y + 1);
|
||||
front_idx[0] = MESH_INDEX (x + 1, y);
|
||||
front_idx[1] = MESH_INDEX (x + 1, y + 1);
|
||||
|
||||
back_idx[0] = MESH_INDEX (priv->x_tiles - (x + 1), y);
|
||||
back_idx[1] = MESH_INDEX (priv->x_tiles - (x + 1), y + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
idx[0] = MESH_INDEX (priv->x_tiles - x - 1, y);
|
||||
idx[1] = MESH_INDEX (priv->x_tiles - x - 1, y + 1);
|
||||
front_idx[0] = MESH_INDEX (priv->x_tiles - x - 1, y);
|
||||
front_idx[1] = MESH_INDEX (priv->x_tiles - x - 1, y + 1);
|
||||
|
||||
back_idx[0] = MESH_INDEX (x + 1, y);
|
||||
back_idx[1] = MESH_INDEX (x + 1, y + 1);
|
||||
}
|
||||
|
||||
idx += 2;
|
||||
front_idx += 2;
|
||||
back_idx += 2;
|
||||
}
|
||||
|
||||
@ -396,9 +414,9 @@ clutter_deform_effect_init_arrays (ClutterDeformEffect *self)
|
||||
|
||||
if (direction)
|
||||
{
|
||||
idx[0] = MESH_INDEX (priv->x_tiles, y + 1);
|
||||
idx[1] = MESH_INDEX (priv->x_tiles, y + 1);
|
||||
idx[2] = MESH_INDEX (priv->x_tiles, y + 2);
|
||||
front_idx[0] = MESH_INDEX (priv->x_tiles, y + 1);
|
||||
front_idx[1] = MESH_INDEX (priv->x_tiles, y + 1);
|
||||
front_idx[2] = MESH_INDEX (priv->x_tiles, y + 2);
|
||||
|
||||
back_idx[0] = MESH_INDEX (0, y + 1);
|
||||
back_idx[1] = MESH_INDEX (0, y + 1);
|
||||
@ -406,16 +424,16 @@ clutter_deform_effect_init_arrays (ClutterDeformEffect *self)
|
||||
}
|
||||
else
|
||||
{
|
||||
idx[0] = MESH_INDEX (0, y + 1);
|
||||
idx[1] = MESH_INDEX (0, y + 1);
|
||||
idx[2] = MESH_INDEX (0, y + 2);
|
||||
front_idx[0] = MESH_INDEX (0, y + 1);
|
||||
front_idx[1] = MESH_INDEX (0, y + 1);
|
||||
front_idx[2] = MESH_INDEX (0, y + 2);
|
||||
|
||||
back_idx[0] = MESH_INDEX (priv->x_tiles, y + 1);
|
||||
back_idx[1] = MESH_INDEX (priv->x_tiles, y + 1);
|
||||
back_idx[2] = MESH_INDEX (priv->x_tiles, y + 2);
|
||||
}
|
||||
|
||||
idx += 3;
|
||||
front_idx += 3;
|
||||
back_idx += 3;
|
||||
|
||||
direction = !direction;
|
||||
@ -423,21 +441,82 @@ clutter_deform_effect_init_arrays (ClutterDeformEffect *self)
|
||||
|
||||
#undef MESH_INDEX
|
||||
|
||||
priv->indices =
|
||||
cogl_vertex_buffer_indices_new (COGL_INDICES_TYPE_UNSIGNED_SHORT,
|
||||
static_indices,
|
||||
priv->n_indices);
|
||||
priv->back_indices =
|
||||
cogl_vertex_buffer_indices_new (COGL_INDICES_TYPE_UNSIGNED_SHORT,
|
||||
static_back_indices,
|
||||
priv->n_indices);
|
||||
front_indices = cogl_indices_new (COGL_INDICES_TYPE_UNSIGNED_SHORT,
|
||||
static_front_indices,
|
||||
n_indices);
|
||||
back_indices = cogl_indices_new (COGL_INDICES_TYPE_UNSIGNED_SHORT,
|
||||
static_back_indices,
|
||||
n_indices);
|
||||
|
||||
g_free (static_indices);
|
||||
g_free (static_front_indices);
|
||||
g_free (static_back_indices);
|
||||
|
||||
n_tiles = (priv->x_tiles + 1) * (priv->y_tiles + 1);
|
||||
priv->vertices = g_new (CoglTextureVertex, n_tiles);
|
||||
priv->vbo = cogl_vertex_buffer_new (n_tiles);
|
||||
priv->n_vertices = (priv->x_tiles + 1) * (priv->y_tiles + 1);
|
||||
|
||||
priv->buffer =
|
||||
cogl_attribute_buffer_new (sizeof (CoglVertexP3T2C4) *
|
||||
priv->n_vertices,
|
||||
NULL);
|
||||
|
||||
/* The application is expected to continuously modify the vertices
|
||||
so we should give a hint to Cogl about that */
|
||||
cogl_buffer_set_update_hint (COGL_BUFFER (priv->buffer),
|
||||
COGL_BUFFER_UPDATE_HINT_DYNAMIC);
|
||||
|
||||
attributes[0] = cogl_attribute_new (priv->buffer,
|
||||
"cogl_position_in",
|
||||
sizeof (CoglVertexP3T2C4),
|
||||
G_STRUCT_OFFSET (CoglVertexP3T2C4, x),
|
||||
3, /* n_components */
|
||||
COGL_ATTRIBUTE_TYPE_FLOAT);
|
||||
attributes[1] = cogl_attribute_new (priv->buffer,
|
||||
"cogl_tex_coord0_in",
|
||||
sizeof (CoglVertexP3T2C4),
|
||||
G_STRUCT_OFFSET (CoglVertexP3T2C4, s),
|
||||
2, /* n_components */
|
||||
COGL_ATTRIBUTE_TYPE_FLOAT);
|
||||
attributes[2] = cogl_attribute_new (priv->buffer,
|
||||
"cogl_color_in",
|
||||
sizeof (CoglVertexP3T2C4),
|
||||
G_STRUCT_OFFSET (CoglVertexP3T2C4, r),
|
||||
4, /* n_components */
|
||||
COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE);
|
||||
|
||||
priv->front_primitive =
|
||||
cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLE_STRIP,
|
||||
priv->n_vertices,
|
||||
attributes,
|
||||
3 /* n_attributes */);
|
||||
cogl_primitive_set_indices (priv->front_primitive,
|
||||
front_indices,
|
||||
n_indices);
|
||||
|
||||
priv->back_primitive =
|
||||
cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLE_STRIP,
|
||||
priv->n_vertices,
|
||||
attributes,
|
||||
3 /* n_attributes */);
|
||||
cogl_primitive_set_indices (priv->back_primitive,
|
||||
back_indices,
|
||||
n_indices);
|
||||
|
||||
if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_DEFORM_TILES))
|
||||
{
|
||||
priv->lines_primitive =
|
||||
cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_LINE_STRIP,
|
||||
priv->n_vertices,
|
||||
attributes,
|
||||
2 /* n_attributes */);
|
||||
cogl_primitive_set_indices (priv->lines_primitive,
|
||||
front_indices,
|
||||
n_indices);
|
||||
}
|
||||
|
||||
cogl_object_unref (front_indices);
|
||||
cogl_object_unref (back_indices);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
cogl_object_unref (attributes[i]);
|
||||
|
||||
priv->is_dirty = TRUE;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user