summaryrefslogtreecommitdiff
path: root/ivi-shell
diff options
context:
space:
mode:
Diffstat (limited to 'ivi-shell')
-rw-r--r--ivi-shell/ivi-layout.c147
1 files changed, 141 insertions, 6 deletions
diff --git a/ivi-shell/ivi-layout.c b/ivi-shell/ivi-layout.c
index 827359ad..24bd8dd6 100644
--- a/ivi-shell/ivi-layout.c
+++ b/ivi-shell/ivi-layout.c
@@ -67,6 +67,8 @@
#include "shared/helpers.h"
#include "shared/os-compatibility.h"
+#define max(a, b) ((a) > (b) ? (a) : (b))
+
struct link_layer {
struct ivi_layout_layer *ivilayer;
struct wl_list link;
@@ -567,18 +569,127 @@ calc_transformation_matrix(struct ivi_rectangle *source_rect,
weston_matrix_translate(m, translate_x, translate_y, 0.0f);
}
+/*
+ * This computes intersected rect_output from two ivi_rectangles
+ */
+static void
+ivi_rectangle_intersect(const struct ivi_rectangle *rect1,
+ const struct ivi_rectangle *rect2,
+ struct ivi_rectangle *rect_output)
+{
+ int32_t rect1_right = rect1->x + rect1->width;
+ int32_t rect1_bottom = rect1->y + rect1->height;
+ int32_t rect2_right = rect2->x + rect2->width;
+ int32_t rect2_bottom = rect2->y + rect2->height;
+
+ rect_output->x = max(rect1->x, rect2->x);
+ rect_output->y = max(rect1->y, rect2->y);
+ rect_output->width = rect1_right < rect2_right ?
+ rect1_right - rect_output->x :
+ rect2_right - rect_output->x;
+ rect_output->height = rect1_bottom < rect2_bottom ?
+ rect1_bottom - rect_output->y :
+ rect2_bottom - rect_output->y;
+
+ if (rect_output->width < 0 || rect_output->height < 0) {
+ rect_output->width = 0;
+ rect_output->height = 0;
+ }
+}
+
+/*
+ * Transform rect_input by the inverse of matrix, intersect with boundingbox,
+ * and store the result in rect_output.
+ * The boundingbox must be given in the same coordinate space as rect_output.
+ * Additionally, there are the following restrictions on the matrix:
+ * - no projective transformations
+ * - no skew
+ * - only multiples of 90-degree rotations supported
+ *
+ * In failure case of weston_matrix_invert, rect_output is set to boundingbox
+ * as a fail-safe with log.
+ */
+static void
+calc_inverse_matrix_transform(const struct weston_matrix *matrix,
+ const struct ivi_rectangle *rect_input,
+ const struct ivi_rectangle *boundingbox,
+ struct ivi_rectangle *rect_output)
+{
+ struct weston_matrix m;
+ struct weston_vector top_left;
+ struct weston_vector bottom_right;
+
+ assert(boundingbox != rect_output);
+
+ if (weston_matrix_invert(&m, matrix) < 0) {
+ weston_log("ivi-shell: calc_inverse_matrix_transform fails to invert a matrix.\n");
+ weston_log("ivi-shell: boundingbox is set to the rect_output.\n");
+ rect_output->x = boundingbox->x;
+ rect_output->y = boundingbox->y;
+ rect_output->width = boundingbox->width;
+ rect_output->height = boundingbox->height;
+ }
+
+ /* The vectors and matrices involved will always produce f[3] == 1.0. */
+ top_left.f[0] = rect_input->x;
+ top_left.f[1] = rect_input->y;
+ top_left.f[2] = 0.0f;
+ top_left.f[3] = 1.0f;
+
+ bottom_right.f[0] = rect_input->x + rect_input->width;
+ bottom_right.f[1] = rect_input->y + rect_input->height;
+ bottom_right.f[2] = 0.0f;
+ bottom_right.f[3] = 1.0f;
+
+ weston_matrix_transform(&m, &top_left);
+ weston_matrix_transform(&m, &bottom_right);
+
+ if (top_left.f[0] < bottom_right.f[0]) {
+ rect_output->x = top_left.f[0];
+ rect_output->width = bottom_right.f[0] - rect_output->x;
+ } else {
+ rect_output->x = bottom_right.f[0];
+ rect_output->width = top_left.f[0] - rect_output->x;
+ }
+
+ if (top_left.f[1] < bottom_right.f[1]) {
+ rect_output->y = top_left.f[1];
+ rect_output->height = bottom_right.f[1] - rect_output->y;
+ } else {
+ rect_output->y = bottom_right.f[1];
+ rect_output->height = top_left.f[1] - rect_output->y;
+ }
+
+ ivi_rectangle_intersect(rect_output, boundingbox, rect_output);
+}
+
/**
- * This computes the whole transformation matrix from surface-local
+ * This computes the whole transformation matrix:m from surface-local
* coordinates to global coordinates. It is assumed that
* weston_view::geometry.{x,y} are zero.
+ *
+ * Additionally, this computes the mask on surface-local coordinates as a
+ * ivi_rectangle. This can be set to weston_view_set_mask.
+ *
+ * The mask is computed by following steps
+ * - destination rectangle of layer is inversed to surface-local cooodinates
+ * by inversed matrix:m.
+ * - the area is intersected by intersected area between weston_surface and
+ * source rectangle of ivi_surface.
*/
static void
-calc_surface_to_global_matrix(struct ivi_layout_layer *ivilayer,
- struct ivi_layout_surface *ivisurf,
- struct weston_matrix *m)
+calc_surface_to_global_matrix_and_mask_to_weston_surface(
+ struct ivi_layout_layer *ivilayer,
+ struct ivi_layout_surface *ivisurf,
+ struct weston_matrix *m,
+ struct ivi_rectangle *result)
{
const struct ivi_layout_surface_properties *sp = &ivisurf->prop;
const struct ivi_layout_layer_properties *lp = &ivilayer->prop;
+ struct ivi_rectangle weston_surface_rect = { 0,
+ 0,
+ ivisurf->surface->width,
+ ivisurf->surface->height };
struct ivi_rectangle surface_source_rect = { sp->source_x,
sp->source_y,
sp->source_width,
@@ -595,7 +706,15 @@ calc_surface_to_global_matrix(struct ivi_layout_layer *ivilayer,
lp->dest_y,
lp->dest_width,
lp->dest_height };
+ struct ivi_rectangle surface_result;
+ /*
+ * the whole transformation matrix:m from surface-local
+ * coordinates to global coordinates, which is computed by
+ * two steps,
+ * - surface-local coordinates to layer-local coordinates
+ * - layer-local coordinates to global coordinates
+ */
calc_transformation_matrix(&surface_source_rect,
&surface_dest_rect,
sp->orientation, m);
@@ -603,6 +722,18 @@ calc_surface_to_global_matrix(struct ivi_layout_layer *ivilayer,
calc_transformation_matrix(&layer_source_rect,
&layer_dest_rect,
lp->orientation, m);
+
+ /* this intersected ivi_rectangle would be used for masking
+ * weston_surface
+ */
+ ivi_rectangle_intersect(&surface_source_rect, &weston_surface_rect,
+ &surface_result);
+
+ /* calc masking area of weston_surface from m */
+ calc_inverse_matrix_transform(m,
+ &layer_dest_rect,
+ &surface_result,
+ result);
}
static void
@@ -610,6 +741,7 @@ update_prop(struct ivi_layout_layer *ivilayer,
struct ivi_layout_surface *ivisurf)
{
struct weston_view *tmpview;
+ struct ivi_rectangle r;
bool can_calc = true;
if (!ivilayer->event_mask && !ivisurf->event_mask) {
@@ -638,10 +770,13 @@ update_prop(struct ivi_layout_layer *ivilayer,
wl_list_remove(&ivisurf->transform.link);
weston_matrix_init(&ivisurf->transform.matrix);
- calc_surface_to_global_matrix(ivilayer, ivisurf, &ivisurf->transform.matrix);
+ calc_surface_to_global_matrix_and_mask_to_weston_surface(
+ ivilayer, ivisurf, &ivisurf->transform.matrix, &r);
if (tmpview != NULL) {
- wl_list_insert(&tmpview->geometry.transformation_list, &ivisurf->transform.link);
+ weston_view_set_mask(tmpview, r.x, r.y, r.width, r.height);
+ wl_list_insert(&tmpview->geometry.transformation_list,
+ &ivisurf->transform.link);
weston_view_set_transform_parent(tmpview, NULL);
}