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.
This commit is contained in:
+23
-13
@@ -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,
|
||||||
|
|||||||
+3
-3
@@ -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);
|
||||||
|
|||||||
+1
-1
@@ -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;
|
||||||
|
|||||||
+1
-1
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user