[PATCH] compositor: q&d solution for surface drift

Pekka Paalanen ppaalanen at gmail.com
Mon Feb 6 05:18:47 PST 2012


When a transformed (rotated) surface is continuously resized from its
top-left corner, its location will drift. This is due to accumulating
rounding errors in transforming an offset from surface-local to global
coordinates in surface_attach().

Diminish the drift down to unobservable level by changing the
weston_surface global position from integer to float.

The offset transformation is now done without rounding. To preserve the
precision, wl_shell::configure() interface must use floats, and so does
weston_surface_configure(), too.

The con of this patch is that it adds inconsistency to the surface
position coordinates: sometimes they are floats, sometimes integers.
---

I think this is the minimal fix, but is such an ugly change acceptable?

 src/compositor.c   |   36 +++++++++++++++++++++++-------------
 src/compositor.h   |    6 +++---
 src/shell.c        |    2 +-
 src/tablet-shell.c |    2 +-
 4 files changed, 28 insertions(+), 18 deletions(-)

diff --git a/src/compositor.c b/src/compositor.c
index 6b15a54..bd5d2e7 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -311,12 +311,10 @@ weston_surface_update_transform(struct weston_surface *surface)
 			     &surface->transform.boundingbox);
 }
 
-WL_EXPORT void
-weston_surface_to_global(struct weston_surface *surface,
-			 int32_t sx, int32_t sy, int32_t *x, int32_t *y)
+static void
+surface_to_global_float(struct weston_surface *surface,
+			int32_t sx, int32_t sy, GLfloat *x, GLfloat *y)
 {
-	weston_surface_update_transform(surface);
-
 	if (surface->transform.enabled) {
 		struct weston_vector v = { { sx, sy, 0.0f, 1.0f } };
 
@@ -331,14 +329,27 @@ weston_surface_to_global(struct weston_surface *surface,
 			return;
 		}
 
-		*x = floorf(v.f[0] / v.f[3]);
-		*y = floorf(v.f[1] / v.f[3]);
+		*x = v.f[0] / v.f[3];
+		*y = v.f[1] / v.f[3];
 	} else {
 		*x = sx + surface->geometry.x;
 		*y = sy + surface->geometry.y;
 	}
 }
 
+WL_EXPORT void
+weston_surface_to_global(struct weston_surface *surface,
+			 int32_t sx, int32_t sy, int32_t *x, int32_t *y)
+{
+	GLfloat xf, yf;
+
+	weston_surface_update_transform(surface);
+
+	surface_to_global_float(surface, sx, sy, &xf, &yf);
+	*x = floorf(xf);
+	*y = floorf(yf);
+}
+
 static void
 surface_from_global_float(struct weston_surface *surface,
 			  int32_t x, int32_t y, GLfloat *sx, GLfloat *sy)
@@ -449,7 +460,7 @@ weston_surface_flush_damage(struct weston_surface *surface)
 
 WL_EXPORT void
 weston_surface_configure(struct weston_surface *surface,
-			 int x, int y, int width, int height)
+			 GLfloat x, GLfloat y, int width, int height)
 {
 	weston_surface_damage_below(surface);
 
@@ -1100,12 +1111,11 @@ surface_attach(struct wl_client *client,
 	} else if (sx != 0 || sy != 0 ||
 		   es->geometry.width != buffer->width ||
 		   es->geometry.height != buffer->height) {
-		int32_t from_x, from_y;
-		int32_t to_x, to_y;
+		GLfloat from_x, from_y;
+		GLfloat to_x, to_y;
 
-		/* FIXME: this has serious cumulating rounding errors */
-		weston_surface_to_global(es, 0, 0, &from_x, &from_y);
-		weston_surface_to_global(es, sx, sy, &to_x, &to_y);
+		surface_to_global_float(es, 0, 0, &from_x, &from_y);
+		surface_to_global_float(es, sx, sy, &to_x, &to_y);
 		shell->configure(shell, es,
 				 es->geometry.x + to_x - from_x,
 				 es->geometry.y + to_y - from_y,
diff --git a/src/compositor.h b/src/compositor.h
index 5d12d43..4495412 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -128,7 +128,7 @@ struct weston_shell {
 		    int32_t width, int32_t height);
 	void (*configure)(struct weston_shell *shell,
 			  struct weston_surface *surface,
-			  int32_t x, int32_t y, int32_t width, int32_t height);
+			  GLfloat x, GLfloat y, int32_t width, int32_t height);
 	void (*destroy)(struct weston_shell *shell);
 };
 
@@ -228,7 +228,7 @@ struct weston_surface {
 	 * That includes the transformations referenced from the list.
 	 */
 	struct {
-		int32_t x, y; /* surface translation on display */
+		GLfloat x, y; /* surface translation on display */
 		int32_t width, height;
 
 		/* struct weston_transform */
@@ -372,7 +372,7 @@ weston_surface_create(struct weston_compositor *compositor);
 
 void
 weston_surface_configure(struct weston_surface *surface,
-			 int x, int y, int width, int height);
+			 GLfloat x, GLfloat y, int width, int height);
 
 void
 weston_surface_assign_output(struct weston_surface *surface);
diff --git a/src/shell.c b/src/shell.c
index d15c8e2..78120ef 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -1397,7 +1397,7 @@ map(struct weston_shell *base,
 
 static void
 configure(struct weston_shell *base, struct weston_surface *surface,
-	  int32_t x, int32_t y, int32_t width, int32_t height)
+	  GLfloat x, GLfloat y, int32_t width, int32_t height)
 {
 	struct wl_shell *shell = container_of(base, struct wl_shell, shell);
 	int do_configure = !shell->locked;
diff --git a/src/tablet-shell.c b/src/tablet-shell.c
index 14ac889..bcaba16 100644
--- a/src/tablet-shell.c
+++ b/src/tablet-shell.c
@@ -141,7 +141,7 @@ tablet_shell_map(struct weston_shell *base, struct weston_surface *surface,
 static void
 tablet_shell_configure(struct weston_shell *base,
 			     struct weston_surface *surface,
-			     int32_t x, int32_t y,
+			     GLfloat x, GLfloat y,
 			     int32_t width, int32_t height)
 {
 	weston_surface_configure(surface, x, y, width, height);
-- 
1.7.3.4



More information about the wayland-devel mailing list