From c61eca6002854b81ad8a418ae82a074423cea80b Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Fri, 6 Jan 2012 14:10:06 +0200 Subject: [PATCH] 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 Signed-off-by: Pekka Paalanen --- src/compositor.c | 44 ++++++++++++++++++++++++++++++++++++++------ src/compositor.h | 12 +++++++++++- src/util.c | 9 ++++++--- 3 files changed, 55 insertions(+), 10 deletions(-) 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 @@ weston_surface_create(struct weston_compositor *compositor, 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 @@ transform_vertex(struct weston_surface *surface, 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 @@ texture_transformed_surface(struct weston_surface *es) 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 @@ weston_surface_draw(struct weston_surface *es, struct weston_output *output) 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); diff --git a/src/compositor.h b/src/compositor.h index fe7176a..3ac6558 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -43,6 +43,8 @@ struct weston_vector { void weston_matrix_init(struct weston_matrix *matrix); void +weston_matrix_multiply(struct weston_matrix *m, const struct weston_matrix *n); +void weston_matrix_scale(struct weston_matrix *matrix, GLfloat x, GLfloat y, GLfloat z); void weston_matrix_translate(struct weston_matrix *matrix, @@ -53,6 +55,7 @@ weston_matrix_transform(struct weston_matrix *matrix, struct weston_vector *v); struct weston_transform { struct weston_matrix matrix; struct weston_matrix inverse; + struct wl_list link; }; struct weston_surface; @@ -234,13 +237,20 @@ struct weston_surface { int32_t pitch; struct wl_list link; struct wl_list buffer_link; - struct weston_transform *transform; struct weston_shader *shader; GLfloat color[4]; uint32_t alpha; uint32_t visual; int overlapped; + struct { + struct wl_list list; + int dirty; + + struct weston_transform cached; + int enabled; + } transform; + /* * Which output to vsync this surface to. * Used to determine, whether to send or queue frame events. diff --git a/src/util.c b/src/util.c index 99dc09e..4faa8b4 100644 --- a/src/util.c +++ b/src/util.c @@ -37,7 +37,7 @@ weston_matrix_init(struct weston_matrix *matrix) memcpy(matrix, &identity, sizeof identity); } -static void +WL_EXPORT void weston_matrix_multiply(struct weston_matrix *m, const struct weston_matrix *n) { struct weston_matrix tmp; @@ -162,7 +162,8 @@ weston_zoom_destroy(struct weston_zoom *zoom) { wl_list_remove(&zoom->animation.link); wl_list_remove(&zoom->listener.link); - zoom->surface->transform = NULL; + wl_list_remove(&zoom->transform.link); + zoom->surface->transform.dirty = 1; if (zoom->done) zoom->done(zoom, zoom->data); free(zoom); @@ -212,6 +213,8 @@ weston_zoom_frame(struct weston_animation *animation, weston_matrix_init(&zoom->transform.inverse); weston_matrix_scale(&zoom->transform.inverse, scale, scale, scale); + zoom->surface->transform.dirty = 1; + weston_compositor_damage_all(es->compositor); } @@ -230,7 +233,7 @@ weston_zoom_run(struct weston_surface *surface, GLfloat start, GLfloat stop, zoom->data = data; zoom->start = start; zoom->stop = stop; - surface->transform = &zoom->transform; + wl_list_insert(&surface->transform.list, &zoom->transform.link); weston_spring_init(&zoom->spring, 200.0, 0.0, 1.0); zoom->spring.friction = 700; zoom->spring.timestamp = weston_compositor_get_time(); -- 2.7.4