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>
This commit is contained in:
parent
804e05185b
commit
c61eca6002
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user