[RFC weston 08/16] compositor: add weston_matrix_transform_rect() and use it for where appropriate

Derek Foreman derekf at osg.samsung.com
Fri Sep 26 14:10:19 PDT 2014


New function that transforms a pixman_box32_t rectangle by a matrix.

Since pixman rectangles are represented by 2 corners, non-90 degree
rotations can't be properly represented.  This function gives the
axis aligned rectangle that encloses the rotated rectangle.

We use this for matrix_transform_region() and weston_matrix_transform_rect(),
simplifying them and allowing them to work for non 90 degree rotations.
---
 src/compositor.c | 96 ++++++++++++++++++++++++++++----------------------------
 src/compositor.h |  4 +++
 2 files changed, 52 insertions(+), 48 deletions(-)

diff --git a/src/compositor.c b/src/compositor.c
index 205397b..ca7c938 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -581,6 +581,50 @@ weston_view_to_global_float(struct weston_view *view,
 	}
 }
 
+WL_EXPORT pixman_box32_t
+weston_matrix_transform_rect(struct weston_matrix *matrix,
+			     pixman_box32_t rect)
+{
+	int i;
+	pixman_box32_t out;
+
+	/* since pixman regions are defined by two corners we have
+	 * to be careful with rotations that aren't multiples of 90.
+	 * We need to take all four corners of the region and rotate
+	 * them, then construct the largest possible two corner
+	 * rectangle from the result.
+	 */
+	struct weston_vector corners[4] = {
+		{{rect.x1, rect.y1, 0, 1}},
+		{{rect.x2, rect.y1, 0, 1}},
+		{{rect.x1, rect.y2, 0, 1}},
+		{{rect.x2, rect.y2, 0, 1}},
+	};
+
+	for (i = 0; i < 4; i++) {
+		weston_matrix_transform(matrix, &corners[i]);
+		corners[i].f[0] /= corners[i].f[3];
+		corners[i].f[1] /= corners[i].f[3];
+	}
+
+	out.x1 = floor(corners[0].f[0]);
+	out.y1 = floor(corners[0].f[1]);
+	out.x2 = ceil(corners[0].f[0]);
+	out.y2 = ceil(corners[0].f[1]);
+
+	for (i = 1; i < 4; i++) {
+		if (floor(corners[i].f[0]) < out.x1)
+			out.x1 = floor(corners[i].f[0]);
+		if (floor(corners[i].f[1]) < out.y1)
+			out.y1 = floor(corners[i].f[1]);
+		if (ceil(corners[i].f[0]) > out.x2)
+			out.x2 = ceil(corners[i].f[0]);
+		if (ceil(corners[i].f[1]) > out.y2)
+			out.y2 = ceil(corners[i].f[1]);
+	}
+	return out;
+}
+
 WL_EXPORT void
 weston_transformed_coord(int width, int height,
 			 enum wl_output_transform transform,
@@ -674,38 +718,8 @@ weston_matrix_transform_region(pixman_region32_t *dest,
 	if (!dest_rects)
 		return;
 
-	for (i = 0; i < nrects; i++) {
-		struct weston_vector vec1 = {{
-			src_rects[i].x1, src_rects[i].y1, 0, 1
-		}};
-		weston_matrix_transform(matrix, &vec1);
-		vec1.f[0] /= vec1.f[3];
-		vec1.f[1] /= vec1.f[3];
-
-		struct weston_vector vec2 = {{
-			src_rects[i].x2, src_rects[i].y2, 0, 1
-		}};
-		weston_matrix_transform(matrix, &vec2);
-		vec2.f[0] /= vec2.f[3];
-		vec2.f[1] /= vec2.f[3];
-
-		if (vec1.f[0] < vec2.f[0]) {
-			dest_rects[i].x1 = floor(vec1.f[0]);
-			dest_rects[i].x2 = ceil(vec2.f[0]);
-		} else {
-			dest_rects[i].x1 = floor(vec2.f[0]);
-			dest_rects[i].x2 = ceil(vec1.f[0]);
-		}
-
-
-		if (vec1.f[1] < vec2.f[1]) {
-			dest_rects[i].y1 = floor(vec1.f[1]);
-			dest_rects[i].y2 = ceil(vec2.f[1]);
-		} else {
-			dest_rects[i].y1 = floor(vec2.f[1]);
-			dest_rects[i].y2 = ceil(vec1.f[1]);
-		}
-	}
+	for (i = 0; i < nrects; i++)
+		dest_rects[i] = weston_matrix_transform_rect(matrix, src_rects[i]);
 
 	pixman_region32_clear(dest);
 	pixman_region32_init_rects(dest, dest_rects, nrects);
@@ -866,22 +880,8 @@ WL_EXPORT pixman_box32_t
 weston_surface_to_buffer_rect(struct weston_surface *surface,
 			      pixman_box32_t rect)
 {
-	struct weston_buffer_viewport *vp = &surface->buffer_viewport;
-	float xf, yf;
-
-	/* first transform box coordinates if the scaler is set */
-	scaler_surface_to_buffer(surface, rect.x1, rect.y1, &xf, &yf);
-	rect.x1 = floorf(xf);
-	rect.y1 = floorf(yf);
-
-	scaler_surface_to_buffer(surface, rect.x2, rect.y2, &xf, &yf);
-	rect.x2 = floorf(xf);
-	rect.y2 = floorf(yf);
-
-	return weston_transformed_rect(surface->width_from_buffer,
-				       surface->height_from_buffer,
-				       vp->buffer.transform, vp->buffer.scale,
-				       rect);
+	return weston_matrix_transform_rect(&surface->surface_to_buffer_matrix,
+					    rect);
 }
 
 WL_EXPORT void
diff --git a/src/compositor.h b/src/compositor.h
index 1f1d33d..6c1c174 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -1422,6 +1422,10 @@ int
 module_init(struct weston_compositor *compositor,
 	    int *argc, char *argv[]);
 
+pixman_box32_t
+weston_matrix_transform_rect(struct weston_matrix *matrix,
+			     pixman_box32_t rect);
+
 void
 weston_transformed_coord(int width, int height,
 			 enum wl_output_transform transform,
-- 
2.1.0



More information about the wayland-devel mailing list