compositor: q&d solution for surface drift

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.
dev
Pekka Paalanen 13 years ago
parent c7b45f68e6
commit ddae03cf9b
  1. 36
      src/compositor.c
  2. 6
      src/compositor.h
  3. 2
      src/shell.c
  4. 2
      src/tablet-shell.c

@ -311,12 +311,10 @@ weston_surface_update_transform(struct weston_surface *surface)
&surface->transform.boundingbox); &surface->transform.boundingbox);
} }
WL_EXPORT void static void
weston_surface_to_global(struct weston_surface *surface, surface_to_global_float(struct weston_surface *surface,
int32_t sx, int32_t sy, int32_t *x, int32_t *y) int32_t sx, int32_t sy, GLfloat *x, GLfloat *y)
{ {
weston_surface_update_transform(surface);
if (surface->transform.enabled) { if (surface->transform.enabled) {
struct weston_vector v = { { sx, sy, 0.0f, 1.0f } }; struct weston_vector v = { { sx, sy, 0.0f, 1.0f } };
@ -331,14 +329,27 @@ weston_surface_to_global(struct weston_surface *surface,
return; return;
} }
*x = floorf(v.f[0] / v.f[3]); *x = v.f[0] / v.f[3];
*y = floorf(v.f[1] / v.f[3]); *y = v.f[1] / v.f[3];
} else { } else {
*x = sx + surface->geometry.x; *x = sx + surface->geometry.x;
*y = sy + surface->geometry.y; *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 static void
surface_from_global_float(struct weston_surface *surface, surface_from_global_float(struct weston_surface *surface,
int32_t x, int32_t y, GLfloat *sx, GLfloat *sy) 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 WL_EXPORT void
weston_surface_configure(struct weston_surface *surface, 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); weston_surface_damage_below(surface);
@ -1100,12 +1111,11 @@ surface_attach(struct wl_client *client,
} else if (sx != 0 || sy != 0 || } else if (sx != 0 || sy != 0 ||
es->geometry.width != buffer->width || es->geometry.width != buffer->width ||
es->geometry.height != buffer->height) { es->geometry.height != buffer->height) {
int32_t from_x, from_y; GLfloat from_x, from_y;
int32_t to_x, to_y; GLfloat to_x, to_y;
/* FIXME: this has serious cumulating rounding errors */ surface_to_global_float(es, 0, 0, &from_x, &from_y);
weston_surface_to_global(es, 0, 0, &from_x, &from_y); surface_to_global_float(es, sx, sy, &to_x, &to_y);
weston_surface_to_global(es, sx, sy, &to_x, &to_y);
shell->configure(shell, es, shell->configure(shell, es,
es->geometry.x + to_x - from_x, es->geometry.x + to_x - from_x,
es->geometry.y + to_y - from_y, es->geometry.y + to_y - from_y,

@ -128,7 +128,7 @@ struct weston_shell {
int32_t width, int32_t height); int32_t width, int32_t height);
void (*configure)(struct weston_shell *shell, void (*configure)(struct weston_shell *shell,
struct weston_surface *surface, 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); void (*destroy)(struct weston_shell *shell);
}; };
@ -228,7 +228,7 @@ struct weston_surface {
* That includes the transformations referenced from the list. * That includes the transformations referenced from the list.
*/ */
struct { struct {
int32_t x, y; /* surface translation on display */ GLfloat x, y; /* surface translation on display */
int32_t width, height; int32_t width, height;
/* struct weston_transform */ /* struct weston_transform */
@ -372,7 +372,7 @@ weston_surface_create(struct weston_compositor *compositor);
void void
weston_surface_configure(struct weston_surface *surface, weston_surface_configure(struct weston_surface *surface,
int x, int y, int width, int height); GLfloat x, GLfloat y, int width, int height);
void void
weston_surface_assign_output(struct weston_surface *surface); weston_surface_assign_output(struct weston_surface *surface);

@ -1397,7 +1397,7 @@ map(struct weston_shell *base,
static void static void
configure(struct weston_shell *base, struct weston_surface *surface, 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); struct wl_shell *shell = container_of(base, struct wl_shell, shell);
int do_configure = !shell->locked; int do_configure = !shell->locked;

@ -141,7 +141,7 @@ tablet_shell_map(struct weston_shell *base, struct weston_surface *surface,
static void static void
tablet_shell_configure(struct weston_shell *base, tablet_shell_configure(struct weston_shell *base,
struct weston_surface *surface, struct weston_surface *surface,
int32_t x, int32_t y, GLfloat x, GLfloat y,
int32_t width, int32_t height) int32_t width, int32_t height)
{ {
weston_surface_configure(surface, x, y, width, height); weston_surface_configure(surface, x, y, width, height);

Loading…
Cancel
Save