From bcdd579a589bef54881d5067d3d1619f6199d6d7 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Wed, 7 Nov 2012 12:25:13 +0200 Subject: [PATCH] gles2: update texture only if needed When a surface is on a non-primary plane (overlay), we do not need to keep the GL texture up-to-date, since we are not using it. Avoid calling glTex(Sub)Image2D in that case, and accumulate the texture damage separately. This is especially useful for backends, that can put wl_shm buffers into overlays. The empty damage check has to be moved from surface_accumulate_damage() into gles2_renderer_flush_damage(), because it really needs to check the accumulated damage, not only the current damage. Otherwise, if a surface migrates from a plane to the primary plane, and does not have new damage, the texture would not be updated even for accumulated damage. Signed-off-by: Pekka Paalanen --- src/compositor.c | 5 +++-- src/compositor.h | 1 + src/gles2-renderer.c | 20 ++++++++++++++++++-- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/compositor.c b/src/compositor.c index f8b9b960..83bd244b 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -239,6 +239,7 @@ weston_surface_create(struct weston_compositor *compositor) surface->num_textures = 0; surface->num_images = 0; + pixman_region32_init(&surface->texture_damage); surface->buffer = NULL; surface->output = NULL; @@ -782,6 +783,7 @@ destroy_surface(struct wl_resource *resource) if (surface->buffer) wl_list_remove(&surface->buffer_destroy_listener.link); + pixman_region32_fini(&surface->texture_damage); compositor->renderer->destroy_surface(surface); pixman_region32_fini(&surface->transform.boundingbox); @@ -905,8 +907,7 @@ static void surface_accumulate_damage(struct weston_surface *surface, pixman_region32_t *opaque) { - if (pixman_region32_not_empty(&surface->damage) && - surface->buffer && wl_buffer_is_shm(surface->buffer)) + if (surface->buffer && wl_buffer_is_shm(surface->buffer)) surface->compositor->renderer->flush_damage(surface); if (surface->transform.enabled) { diff --git a/src/compositor.h b/src/compositor.h index a0ccb727..d2e121b1 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -410,6 +410,7 @@ struct weston_surface { struct weston_compositor *compositor; GLuint textures[3]; int num_textures; + pixman_region32_t texture_damage; pixman_region32_t clip; pixman_region32_t damage; pixman_region32_t opaque; diff --git a/src/gles2-renderer.c b/src/gles2-renderer.c index 05647b7e..49fe7b04 100644 --- a/src/gles2-renderer.c +++ b/src/gles2-renderer.c @@ -775,6 +775,18 @@ gles2_renderer_flush_damage(struct weston_surface *surface) int i, n; #endif + pixman_region32_union(&surface->texture_damage, + &surface->texture_damage, &surface->damage); + + /* Avoid upload, if the texture won't be used this time. + * We still accumulate the damage in texture_damage. + */ + if (surface->plane != &surface->compositor->primary_plane) + return; + + if (!pixman_region32_not_empty(&surface->texture_damage)) + return; + glBindTexture(GL_TEXTURE_2D, surface->textures[0]); if (!surface->compositor->has_unpack_subimage) { @@ -783,14 +795,14 @@ gles2_renderer_flush_damage(struct weston_surface *surface) GL_BGRA_EXT, GL_UNSIGNED_BYTE, wl_shm_buffer_get_data(surface->buffer)); - return; + goto done; } #ifdef GL_UNPACK_ROW_LENGTH /* Mesa does not define GL_EXT_unpack_subimage */ glPixelStorei(GL_UNPACK_ROW_LENGTH, surface->pitch); data = wl_shm_buffer_get_data(surface->buffer); - rectangles = pixman_region32_rectangles(&surface->damage, &n); + rectangles = pixman_region32_rectangles(&surface->texture_damage, &n); for (i = 0; i < n; i++) { glPixelStorei(GL_UNPACK_SKIP_PIXELS, rectangles[i].x1); glPixelStorei(GL_UNPACK_SKIP_ROWS, rectangles[i].y1); @@ -801,6 +813,10 @@ gles2_renderer_flush_damage(struct weston_surface *surface) GL_BGRA_EXT, GL_UNSIGNED_BYTE, data); } #endif + +done: + pixman_region32_fini(&surface->texture_damage); + pixman_region32_init(&surface->texture_damage); } static void