From 747d4ee17e573766a0b46b60db9b2477b9286d27 Mon Sep 17 00:00:00 2001 From: Sinclair Yeh Date: Thu, 6 Jun 2013 16:41:30 -0700 Subject: [PATCH] Avoid unnecessarily re-allocating texture buffer when the size hasn't changed. v4: Incorporated krh and anderco's comments. Now adding newly allocated buffer's dimensions to texture_damage v3: * Removed unnecessary parentheses * Added check for switching from EGL image to SHM buffer * Moved shader assignment out of IF condition v2: Fixed the wrong comparison v1: Depending on specific DRI driver implementation, glTexImage2D() with data set to NULL may or may not re-allocate the texture buffer each time it is called. Unintended consequences happen if later glTexSubImage2D() is called to only update a sub-region of the texture buffer. I've explored moving glTexImage2D() from gl_renderer_attach() and simply mark the texture dirty, but the current implemention seems cleaner because I won't have to worry about calling ensure_textures() and re-assigning gs->shader unnecessarily. --- src/gl-renderer.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/gl-renderer.c b/src/gl-renderer.c index ea6631f15..f6c719489 100644 --- a/src/gl-renderer.c +++ b/src/gl-renderer.c @@ -66,6 +66,7 @@ struct gl_surface_state { int num_images; struct weston_buffer_reference buffer_ref; + int height; int pitch; /* in pixels */ }; @@ -1192,14 +1193,28 @@ gl_renderer_attach(struct weston_surface *es, struct wl_buffer *buffer) } if (wl_buffer_is_shm(buffer)) { - gs->pitch = wl_shm_buffer_get_stride(buffer) / 4; - gs->target = GL_TEXTURE_2D; + /* Only allocate a texture if it doesn't match existing one. + * If gs->num_images is not 0, then a switch from DRM allocated + * buffer to a SHM buffer is happening, and we need to allocate + * a new texture buffer. */ + if (wl_shm_buffer_get_stride(buffer) / 4 != gs->pitch || + wl_shm_buffer_get_height(buffer) != gs->height || + gs->num_images > 0) { + gs->pitch = wl_shm_buffer_get_stride(buffer) / 4; + gs->height = wl_shm_buffer_get_height(buffer); + gs->target = GL_TEXTURE_2D; + + ensure_textures(gs, 1); + glBindTexture(GL_TEXTURE_2D, gs->textures[0]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, + gs->pitch, buffer->height, 0, + GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL); + pixman_region32_union_rect(&gs->texture_damage, + &gs->texture_damage, + 0, 0, + gs->pitch, gs->height); + } - ensure_textures(gs, 1); - glBindTexture(GL_TEXTURE_2D, gs->textures[0]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, - gs->pitch, buffer->height, 0, - GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL); if (wl_shm_buffer_get_format(buffer) == WL_SHM_FORMAT_XRGB8888) gs->shader = &gr->texture_shader_rgbx; else @@ -1258,6 +1273,7 @@ gl_renderer_attach(struct weston_surface *es, struct wl_buffer *buffer) } gs->pitch = buffer->width; + gs->height = wl_shm_buffer_get_height(buffer); } else { weston_log("unhandled buffer type!\n"); weston_buffer_reference(&gs->buffer_ref, NULL);