compositor: implement a stack of surface transformations
Having at most one transformation object attached to a surface is not
enough anymore. If we have a surface that needs to be scaled to
fullscreen, and then we have the zoom animation, we already need two
transformations combined.
Implement support for multiple transformations by adding a transformation
list. The final transformation is the ordered composite of those in the
list. To avoid traversing the list every single time, add a dirty flag,
and cache the final transformation.
The existing transformation users (only zoom) are converted.
Note: surface drawing should honour all kinds of transformations, but
not damage region code nor input event translating code take
transformations into account, AFAICT. Therefore anything but translation
will probably behave badly until they are fixed.
Cc: Juan Zhao <juan.j.zhao@linux.intel.com>
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
diff --git a/src/compositor.c b/src/compositor.c
index 9eb643c..0a7dea3 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -205,7 +205,8 @@
surface->buffer_destroy_listener.func = surface_handle_buffer_destroy;
- surface->transform = NULL;
+ wl_list_init(&surface->transform.list);
+ surface->transform.dirty = 1;
return surface;
}
@@ -504,7 +505,9 @@
t.f[2] = 0.0;
t.f[3] = 1.0;
- weston_matrix_transform(&surface->transform->matrix, &t);
+ weston_matrix_transform(&surface->transform.cached.matrix, &t);
+
+ /* XXX: assumes last row of matrix is [0 0 * 1] */
r[ 0] = t.f[0];
r[ 1] = t.f[1];
@@ -538,6 +541,34 @@
return 1;
}
+static void
+weston_surface_update_transform(struct weston_surface *surface)
+{
+ struct weston_matrix *matrix = &surface->transform.cached.matrix;
+ struct weston_matrix *inverse = &surface->transform.cached.inverse;
+ struct weston_transform *tform;
+
+ if (!surface->transform.dirty)
+ return;
+
+ surface->transform.dirty = 0;
+
+ if (wl_list_empty(&surface->transform.list)) {
+ surface->transform.enabled = 0;
+ return;
+ }
+
+ surface->transform.enabled = 1;
+
+ weston_matrix_init(matrix);
+ wl_list_for_each(tform, &surface->transform.list, link)
+ weston_matrix_multiply(matrix, &tform->matrix);
+
+ weston_matrix_init(inverse);
+ wl_list_for_each_reverse(tform, &surface->transform.list, link)
+ weston_matrix_multiply(inverse, &tform->inverse);
+}
+
WL_EXPORT void
weston_surface_draw(struct weston_surface *es, struct weston_output *output)
{
@@ -584,12 +615,13 @@
ec->current_alpha = es->alpha;
}
- if (es->transform == NULL) {
- filter = GL_NEAREST;
- n = texture_region(es, &repaint);
- } else {
+ weston_surface_update_transform(es);
+ if (es->transform.enabled) {
filter = GL_LINEAR;
n = texture_transformed_surface(es);
+ } else {
+ filter = GL_NEAREST;
+ n = texture_region(es, &repaint);
}
glBindTexture(GL_TEXTURE_2D, es->texture);