compositor: Add surface-to-buffer and buffer-to-surface matrices
authorJason Ekstrand <jason@jlekstrand.net>
Thu, 16 Oct 2014 15:55:19 +0000 (10:55 -0500)
committerPekka Paalanen <pekka.paalanen@collabora.co.uk>
Wed, 11 Mar 2015 10:26:45 +0000 (12:26 +0200)
Add matrix representations of these two transformations. Future patches
will leverage these to simplify the coordinate transformation code.

[Pekka: commit message]
Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
Reviewed-By: Derek Foreman <derekf@osg.samsung.com>
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
src/compositor.c
src/compositor.h

index 39ef838..47552f4 100644 (file)
@@ -642,6 +642,9 @@ weston_surface_create(struct weston_compositor *compositor)
        wl_list_init(&surface->subsurface_list);
        wl_list_init(&surface->subsurface_list_pending);
 
+       weston_matrix_init(&surface->buffer_to_surface_matrix);
+       weston_matrix_init(&surface->surface_to_buffer_matrix);
+
        return surface;
 }
 
@@ -2560,6 +2563,82 @@ weston_surface_commit_subsurface_order(struct weston_surface *surface)
 }
 
 static void
+weston_surface_build_buffer_matrix(struct weston_surface *surface,
+                                  struct weston_matrix *matrix)
+{
+       struct weston_buffer_viewport *vp = &surface->buffer_viewport;
+       double src_width, src_height, dest_width, dest_height;
+
+       weston_matrix_init(matrix);
+
+       if (vp->buffer.src_width == wl_fixed_from_int(-1)) {
+               src_width = surface->width_from_buffer;
+               src_height = surface->height_from_buffer;
+       } else {
+               src_width = wl_fixed_to_double(vp->buffer.src_width);
+               src_height = wl_fixed_to_double(vp->buffer.src_height);
+       }
+
+       if (vp->surface.width == -1) {
+               dest_width = src_width;
+               dest_height = src_height;
+       } else {
+               dest_width = vp->surface.width;
+               dest_height = vp->surface.height;
+       }
+
+       if (src_width != dest_width || src_height != dest_height)
+               weston_matrix_scale(matrix,
+                                   src_width / dest_width,
+                                   src_height / dest_height, 1);
+
+       if (vp->buffer.src_width != wl_fixed_from_int(-1))
+               weston_matrix_translate(matrix,
+                                       wl_fixed_to_double(vp->buffer.src_x),
+                                       wl_fixed_to_double(vp->buffer.src_y),
+                                       0);
+
+       switch (vp->buffer.transform) {
+       case WL_OUTPUT_TRANSFORM_FLIPPED:
+       case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+       case WL_OUTPUT_TRANSFORM_FLIPPED_180:
+       case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+               weston_matrix_scale(matrix, -1, 1, 1);
+               weston_matrix_translate(matrix,
+                                       surface->width_from_buffer, 0, 0);
+               break;
+       }
+
+       switch (vp->buffer.transform) {
+       default:
+       case WL_OUTPUT_TRANSFORM_NORMAL:
+       case WL_OUTPUT_TRANSFORM_FLIPPED:
+               break;
+       case WL_OUTPUT_TRANSFORM_90:
+       case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+               weston_matrix_rotate_xy(matrix, 0, 1);
+               weston_matrix_translate(matrix,
+                                       surface->height_from_buffer, 0, 0);
+               break;
+       case WL_OUTPUT_TRANSFORM_180:
+       case WL_OUTPUT_TRANSFORM_FLIPPED_180:
+               weston_matrix_rotate_xy(matrix, -1, 0);
+               weston_matrix_translate(matrix,
+                                       surface->width_from_buffer,
+                                       surface->height_from_buffer, 0);
+               break;
+       case WL_OUTPUT_TRANSFORM_270:
+       case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+               weston_matrix_rotate_xy(matrix, 0, -1);
+               weston_matrix_translate(matrix,
+                                       0, surface->width_from_buffer, 0);
+               break;
+       }
+
+       weston_matrix_scale(matrix, vp->buffer.scale, vp->buffer.scale, 1);
+}
+
+static void
 weston_surface_commit_state(struct weston_surface *surface,
                            struct weston_surface_state *state)
 {
@@ -2576,6 +2655,11 @@ weston_surface_commit_state(struct weston_surface *surface,
                weston_surface_attach(surface, state->buffer);
        weston_surface_state_set_buffer(state, NULL);
 
+       weston_surface_build_buffer_matrix(surface,
+                                          &surface->surface_to_buffer_matrix);
+       weston_matrix_invert(&surface->buffer_to_surface_matrix,
+                            &surface->surface_to_buffer_matrix);
+
        if (state->newly_attached || state->buffer_viewport.changed) {
                weston_surface_update_size(surface);
                if (surface->configure)
index 207767e..ead03ae 100644 (file)
@@ -926,6 +926,12 @@ struct weston_surface {
        /* All the pending state, that wl_surface.commit will apply. */
        struct weston_surface_state pending;
 
+       /* Matrices representating of the full transformation between
+        * buffer and surface coordinates.  These matrices are updated
+        * using the weston_surface_build_buffer_matrix function. */
+       struct weston_matrix buffer_to_surface_matrix;
+       struct weston_matrix surface_to_buffer_matrix;
+
        /*
         * If non-NULL, this function will be called on
         * wl_surface::commit after a new buffer has been set up for