diff --git a/configure.ac b/configure.ac index 7bc9881c..550bb3c8 100644 --- a/configure.ac +++ b/configure.ac @@ -117,7 +117,7 @@ AM_CONDITIONAL(BUILD_CLIENTS, test x$enable_clients == xyes) if test x$enable_clients == xyes; then AC_DEFINE([BUILD_CLIENTS], [1], [Build the Wayland clients]) - PKG_CHECK_MODULES(CLIENT, [wayland-client wayland-egl egl >= 7.10 cairo >= 1.10.0 gdk-pixbuf-2.0 glib-2.0 gobject-2.0 gio-2.0 xkbcommon]) + PKG_CHECK_MODULES(CLIENT, [wayland-client wayland-egl egl >= 7.10 cairo >= 1.10.0 gdk-pixbuf-2.0 glib-2.0 gobject-2.0 gio-2.0 xkbcommon libpng]) PKG_CHECK_MODULES(POPPLER, [poppler-glib], [have_poppler=yes], [have_poppler=no]) diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c index a0a23c79..5199622b 100644 --- a/src/compositor-wayland.c +++ b/src/compositor-wayland.c @@ -181,7 +181,6 @@ draw_border(struct wayland_output *output) glUniform1i(shader->tex_uniform, 0); glUniform1f(shader->alpha_uniform, 1); - c->base.current_alpha = 255; glUniform1f(shader->texwidth_uniform, 1); n = texture_border(output); diff --git a/src/compositor.c b/src/compositor.c index dd267424..18cbfccc 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -314,12 +314,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 } }; @@ -334,14 +332,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) @@ -452,7 +463,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); @@ -466,7 +477,8 @@ weston_surface_configure(struct weston_surface *surface, weston_surface_damage(surface); pixman_region32_fini(&surface->opaque); - if (surface->visual == WESTON_RGB_VISUAL) + if (surface->visual == WESTON_RGB_VISUAL && + surface->transform.enabled == 0) pixman_region32_init_rect(&surface->opaque, surface->geometry.x, surface->geometry.y, @@ -684,6 +696,9 @@ weston_surface_draw(struct weston_surface *es, struct weston_output *output) &output->region); pixman_region32_intersect(&repaint, &repaint, &es->damage); + /* Clear damage, assume outputs do not overlap. */ + pixman_region32_subtract(&es->damage, &es->damage, &output->region); + if (!pixman_region32_not_empty(&repaint)) goto out; @@ -707,21 +722,11 @@ weston_surface_draw(struct weston_surface *es, struct weston_output *output) glUniformMatrix4fv(es->shader->proj_uniform, 1, GL_FALSE, output->matrix.d); - - if (es->shader->tex_uniform != GL_NONE) - glUniform1i(es->shader->tex_uniform, 0); - - if (es->shader->color_uniform != GL_NONE) - glUniform4fv(es->shader->color_uniform,1, es->color); - - if (es->shader->alpha_uniform && es->alpha != ec->current_alpha) { - glUniform1f(es->shader->alpha_uniform, es->alpha / 255.0); - ec->current_alpha = es->alpha; - } - - if (es->shader->texwidth_uniform != GL_NONE) - glUniform1f(es->shader->texwidth_uniform, - (GLfloat)es->geometry.width / es->pitch); + glUniform1i(es->shader->tex_uniform, 0); + glUniform4fv(es->shader->color_uniform, 1, es->color); + glUniform1f(es->shader->alpha_uniform, es->alpha / 255.0); + glUniform1f(es->shader->texwidth_uniform, + (GLfloat)es->geometry.width / es->pitch); if (es->transform.enabled) filter = GL_LINEAR; @@ -1115,12 +1120,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, @@ -1857,43 +1861,13 @@ weston_shader_init(struct weston_shader *shader, shader->proj_uniform = glGetUniformLocation(shader->program, "proj"); shader->tex_uniform = glGetUniformLocation(shader->program, "tex"); shader->alpha_uniform = glGetUniformLocation(shader->program, "alpha"); + shader->color_uniform = glGetUniformLocation(shader->program, "color"); shader->texwidth_uniform = glGetUniformLocation(shader->program, "texwidth"); return 0; } -static int -init_solid_shader(struct weston_shader *shader, - GLuint vertex_shader, const char *fragment_source) -{ - GLint status; - char msg[512]; - - shader->vertex_shader = vertex_shader; - shader->fragment_shader = - compile_shader(GL_FRAGMENT_SHADER, fragment_source); - - shader->program = glCreateProgram(); - glAttachShader(shader->program, shader->vertex_shader); - glAttachShader(shader->program, shader->fragment_shader); - glBindAttribLocation(shader->program, 0, "position"); - glBindAttribLocation(shader->program, 1, "texcoord"); - - glLinkProgram(shader->program); - glGetProgramiv(shader->program, GL_LINK_STATUS, &status); - if (!status) { - glGetProgramInfoLog(shader->program, sizeof msg, NULL, msg); - fprintf(stderr, "link info: %s\n", msg); - return -1; - } - - shader->proj_uniform = glGetUniformLocation(shader->program, "proj"); - shader->color_uniform = glGetUniformLocation(shader->program, "color"); - - return 0; -} - WL_EXPORT void weston_output_destroy(struct weston_output *output) { @@ -2072,9 +2046,8 @@ weston_compositor_init(struct weston_compositor *ec, struct wl_display *display) if (weston_shader_init(&ec->texture_shader, vertex_shader, texture_fragment_shader) < 0) return -1; - if (init_solid_shader(&ec->solid_shader, - ec->texture_shader.vertex_shader, - solid_fragment_shader) < 0) + if (weston_shader_init(&ec->solid_shader, + vertex_shader, solid_fragment_shader) < 0) return -1; loop = wl_display_get_event_loop(ec->wl_display); diff --git a/src/compositor.h b/src/compositor.h index e350875f..80b848dc 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -104,11 +104,11 @@ enum weston_visual { struct weston_shader { GLuint program; GLuint vertex_shader, fragment_shader; - GLuint proj_uniform; - GLuint tex_uniform; - GLuint alpha_uniform; - GLuint color_uniform; - GLuint texwidth_uniform; + GLint proj_uniform; + GLint tex_uniform; + GLint alpha_uniform; + GLint color_uniform; + GLint texwidth_uniform; }; struct weston_animation { @@ -133,7 +133,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); }; @@ -153,7 +153,6 @@ struct weston_compositor { EGLContext context; EGLConfig config; GLuint fbo; - uint32_t current_alpha; struct weston_shader texture_shader; struct weston_shader solid_shader; struct weston_shader *current_shader; @@ -214,6 +213,31 @@ enum weston_output_flags { WL_OUTPUT_FLIPPED = 0x01 }; +/* Using weston_surface transformations + * + * To add a transformation to a surface, create a struct weston_transform, and + * add it to the list surface->geometry.transformation_list. Whenever you + * change the list, anything under surface->geometry, or anything in the + * weston_transforms linked into the list, you must set + * surface->geometry.dirty = 1. + * + * The order in the list defines the order of transformations. Let the list + * contain the transformation matrices M1, ..., Mn as head to tail. The + * transformation is applied to surface-local coordinate vector p as + * P = Mn * ... * M2 * M1 * p + * to produce the global coordinate vector P. The total transform + * Mn * ... * M2 * M1 + * is cached in surface->transform.matrix, and the inverse of it in + * surface->transform.inverse. + * + * The list always contains surface->transform.position transformation, which + * is the translation by surface->geometry.x and y. + * + * If you want to apply a transformation in local coordinates, add your + * weston_transform to the head of the list. If you want to apply a + * transformation in global coordinates, add it to the tail of the list. + */ + struct weston_surface { struct wl_surface surface; struct weston_compositor *compositor; @@ -234,7 +258,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 */ @@ -378,7 +402,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 d15c8e2d..53b192c2 100644 --- a/src/shell.c +++ b/src/shell.c @@ -103,6 +103,7 @@ struct shell_surface { struct wl_grab grab; uint32_t time; int32_t x, y; + struct weston_transform parent_transform; int32_t initial_up; } popup; @@ -521,8 +522,22 @@ shell_map_popup(struct shell_surface *shsurf, uint32_t time) shsurf->popup.grab.interface = &popup_grab_interface; device = es->compositor->input_device; - es->geometry.x = shsurf->parent->surface->geometry.x + shsurf->popup.x; - es->geometry.y = shsurf->parent->surface->geometry.y + shsurf->popup.y; + weston_surface_update_transform(parent); + if (parent->transform.enabled) { + shsurf->popup.parent_transform.matrix = + parent->transform.matrix; + } else { + /* construct x, y translation matrix */ + weston_matrix_init(&shsurf->popup.parent_transform.matrix); + shsurf->popup.parent_transform.matrix.d[12] = + parent->geometry.x; + shsurf->popup.parent_transform.matrix.d[13] = + parent->geometry.y; + } + wl_list_insert(es->geometry.transformation_list.prev, + &shsurf->popup.parent_transform.link); + es->geometry.x = shsurf->popup.x; + es->geometry.y = shsurf->popup.y; es->geometry.dirty = 1; shsurf->popup.grab.input_device = device; @@ -1397,7 +1412,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 14ac8895..bcaba161 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);