[PATCH] pixman-backend: add support for zooming

Derek Foreman derekf at osg.samsung.com
Fri Aug 29 07:56:00 PDT 2014


Currently if you try to zoom with mod+scrollwheel the pixman
backend will stop rendering anything at all and will continuously
log "pixman renderer does not support zoom", giving the impression
that the server is hung.

Instead, this patch adds the missing zoom functionality.

This should close BUG 80258
---
 src/pixman-renderer.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 59 insertions(+), 6 deletions(-)

diff --git a/src/pixman-renderer.c b/src/pixman-renderer.c
index 4fdcb05..55e8824 100644
--- a/src/pixman-renderer.c
+++ b/src/pixman-renderer.c
@@ -168,6 +168,37 @@ transform_apply_viewport(pixman_transform_t *transform,
 }
 
 static void
+region_apply_zoom(struct weston_output *output,
+		  pixman_region32_t *region)
+{
+	pixman_box32_t *rects, *zoomed_rects;
+	int nrects, i;
+	double mag, tx, ty, zoomw, zoomh;
+
+	mag = 1.0 / (1.0 - output->zoom.spring_z.current);
+	zoomw = mag * output->width;
+	zoomh = mag * output->height;
+	tx = output->zoom.trans_x * output->width/2.0;
+	ty = output->zoom.trans_y * output->height/2.0;
+	rects = pixman_region32_rectangles(region, &nrects);
+	zoomed_rects = calloc(nrects, sizeof(pixman_box32_t));
+
+	for (i = 0; i < nrects; i++) {
+		zoomed_rects[i].x1 = (output->width / 2.0)
+				   + mag * (rects[i].x1 - tx) - zoomw / 2.0;
+		zoomed_rects[i].x2 = (output->width / 2.0)
+				   + mag * (rects[i].x2 - tx) - zoomw / 2.0;
+		zoomed_rects[i].y1 = (output->height / 2.0)
+				   + mag * (rects[i].y1 - ty) - zoomh / 2.0;
+		zoomed_rects[i].y2 = (output->height / 2.0)
+				   + mag * (rects[i].y2 - ty) - zoomh / 2.0;
+	}
+	pixman_region32_clear(region);
+	pixman_region32_init_rects(region, zoomed_rects, nrects);
+	free(zoomed_rects);
+}
+
+static void
 repaint_region(struct weston_view *ev, struct weston_output *output,
 	       pixman_region32_t *region, pixman_region32_t *surf_region,
 	       pixman_op_t pixman_op)
@@ -211,6 +242,10 @@ repaint_region(struct weston_view *ev, struct weston_output *output,
 	/* Convert from global to output coord */
 	region_global_to_output(output, &final_region);
 
+	/* Apply zoom if applicable */
+	if (output->zoom.active)
+		region_apply_zoom(output, &final_region);
+
 	/* And clip to it */
 	pixman_image_set_clip_region32 (po->shadow_image, &final_region);
 
@@ -218,6 +253,25 @@ repaint_region(struct weston_view *ev, struct weston_output *output,
 	   position, the output position/transform/scale and the client
 	   specified buffer transform/scale */
 	pixman_transform_init_identity(&transform);
+
+	if (output->zoom.active) {
+		double mag, zoomw, zoomh, tx, ty;
+
+		mag = 1.0f - output->zoom.spring_z.current;
+		zoomw = mag * output->width;
+		zoomh = mag * output->height;
+		tx = output->zoom.trans_x * output->width/2.0 - (zoomw - output->width) / 2.0;
+		ty = output->zoom.trans_y * output->height/2.0 - (zoomh - output->height) / 2.0;
+
+		pixman_transform_scale(&transform, NULL,
+				       pixman_double_to_fixed (mag),
+				       pixman_double_to_fixed (mag));
+
+		pixman_transform_translate(&transform, NULL,
+					   pixman_double_to_fixed(tx),
+					   pixman_double_to_fixed(ty));
+	}
+
 	pixman_transform_scale(&transform, NULL,
 			       pixman_double_to_fixed ((double)1.0/output->current_scale),
 			       pixman_double_to_fixed ((double)1.0/output->current_scale));
@@ -334,7 +388,8 @@ repaint_region(struct weston_view *ev, struct weston_output *output,
 
 	pixman_image_set_transform(ps->image, &transform);
 
-	if (ev->transform.enabled || output->current_scale != vp->buffer.scale)
+	if (ev->transform.enabled || output->current_scale != vp->buffer.scale
+	    || output->zoom.active)
 		pixman_image_set_filter(ps->image, PIXMAN_FILTER_BILINEAR, NULL, 0);
 	else
 		pixman_image_set_filter(ps->image, PIXMAN_FILTER_NEAREST, NULL, 0);
@@ -403,11 +458,6 @@ draw_view(struct weston_view *ev, struct weston_output *output,
 	if (!pixman_region32_not_empty(&repaint))
 		goto out;
 
-	if (output->zoom.active) {
-		weston_log("pixman renderer does not support zoom\n");
-		goto out;
-	}
-
 	/* TODO: Implement repaint_region_complex() using pixman_composite_trapezoids() */
 	if (ev->alpha != 1.0 ||
 	    (ev->transform.enabled &&
@@ -455,6 +505,9 @@ copy_to_hw_buffer(struct weston_output *output, pixman_region32_t *region)
 
 	region_global_to_output(output, &output_region);
 
+	if (output->zoom.active)
+		region_apply_zoom(output, &output_region);
+
 	pixman_image_set_clip_region32 (po->hw_buffer, &output_region);
 
 	pixman_image_composite32(PIXMAN_OP_SRC,
-- 
2.1.0.rc1



More information about the wayland-devel mailing list