[PATCH weston] compositor: Fix rendering with shm transformed buffers
Kristian Høgsberg
hoegsberg at gmail.com
Fri Nov 30 11:15:45 PST 2012
On Wed, Nov 28, 2012 at 05:10:26PM +0200, Ander Conselvan de Oliveira wrote:
> The implementation of buffer transformation didn't handle transformed
> shm buffers properly. The partial texture upload was broken since the
> damage is in surface coordinates that don't necessarily match the
> buffer's coordinates. It also wouldn't handle the buffer stride
> properly, resulting in incorrect rendering if it didn't match the
> buffer's width.
>
> The logic used for converting texture coordinates was generalized and
> moved out of the renderer, since this conversion may be useful in other
> places, such as the backends.
Thanks, committed.
Kristian
> ---
> src/compositor.c | 71 ++++++++++++++++++++++++++++++++++++++++++
> src/compositor.h | 7 +++++
> src/gl-renderer.c | 90 +++++++++++++++--------------------------------------
> 3 files changed, 103 insertions(+), 65 deletions(-)
>
> diff --git a/src/compositor.c b/src/compositor.c
> index a965fc2..565212d 100644
> --- a/src/compositor.c
> +++ b/src/compositor.c
> @@ -311,6 +311,77 @@ weston_surface_to_global_float(struct weston_surface *surface,
> }
>
> WL_EXPORT void
> +weston_surface_to_buffer_float(struct weston_surface *surface,
> + float sx, float sy, float *bx, float *by)
> +{
> + switch (surface->buffer_transform) {
> + case WL_OUTPUT_TRANSFORM_NORMAL:
> + default:
> + *bx = sx;
> + *by = sy;
> + break;
> + case WL_OUTPUT_TRANSFORM_FLIPPED:
> + *bx = surface->geometry.width - sx;
> + *by = sy;
> + break;
> + case WL_OUTPUT_TRANSFORM_90:
> + *bx = surface->geometry.height - sy;
> + *by = sx;
> + break;
> + case WL_OUTPUT_TRANSFORM_FLIPPED_90:
> + *bx = surface->geometry.height - sy;
> + *by = surface->geometry.width - sx;
> + break;
> + case WL_OUTPUT_TRANSFORM_180:
> + *bx = surface->geometry.width - sx;
> + *by = surface->geometry.height - sy;
> + break;
> + case WL_OUTPUT_TRANSFORM_FLIPPED_180:
> + *bx = sx;
> + *by = surface->geometry.height - sy;
> + break;
> + case WL_OUTPUT_TRANSFORM_270:
> + *bx = sy;
> + *by = surface->geometry.width - sx;
> + break;
> + case WL_OUTPUT_TRANSFORM_FLIPPED_270:
> + *bx = sy;
> + *by = sx;
> + break;
> + }
> +}
> +
> +WL_EXPORT pixman_box32_t
> +weston_surface_to_buffer_rect(struct weston_surface *surface,
> + pixman_box32_t rect)
> +{
> + float x1, x2, y1, y2;
> +
> + pixman_box32_t ret;
> +
> + weston_surface_to_buffer_float(surface, rect.x1, rect.y1, &x1, &y1);
> + weston_surface_to_buffer_float(surface, rect.x2, rect.y2, &x2, &y2);
> +
> + if (x1 <= x2) {
> + ret.x1 = x1;
> + ret.x2 = x2;
> + } else {
> + ret.x1 = x2;
> + ret.x2 = x1;
> + }
> +
> + if (y1 <= y2) {
> + ret.y1 = y1;
> + ret.y2 = y2;
> + } else {
> + ret.y1 = y2;
> + ret.y2 = y1;
> + }
> +
> + return ret;
> +}
> +
> +WL_EXPORT void
> weston_surface_move_to_plane(struct weston_surface *surface,
> struct weston_plane *plane)
> {
> diff --git a/src/compositor.h b/src/compositor.h
> index 48633d4..2547da1 100644
> --- a/src/compositor.h
> +++ b/src/compositor.h
> @@ -506,6 +506,13 @@ weston_surface_buffer_width(struct weston_surface *surface);
> int32_t
> weston_surface_buffer_height(struct weston_surface *surface);
>
> +WL_EXPORT void
> +weston_surface_to_buffer_float(struct weston_surface *surface,
> + float x, float y, float *bx, float *by);
> +pixman_box32_t
> +weston_surface_to_buffer_rect(struct weston_surface *surface,
> + pixman_box32_t rect);
> +
> void
> weston_spring_init(struct weston_spring *spring,
> double k, double current, double target);
> diff --git a/src/gl-renderer.c b/src/gl-renderer.c
> index c2fdaa3..664f395 100644
> --- a/src/gl-renderer.c
> +++ b/src/gl-renderer.c
> @@ -517,47 +517,6 @@ calculate_edges(struct weston_surface *es, pixman_box32_t *rect,
> return n;
> }
>
> -static void
> -transform_texcoord(struct weston_surface *es, GLfloat sx, GLfloat sy,
> - GLfloat *tx, GLfloat *ty)
> -{
> - switch(es->buffer_transform) {
> - case WL_OUTPUT_TRANSFORM_NORMAL:
> - default:
> - *tx = sx;
> - *ty = sy;
> - break;
> - case WL_OUTPUT_TRANSFORM_FLIPPED:
> - *tx = 1.0 - sx;
> - *ty = sy;
> - break;
> - case WL_OUTPUT_TRANSFORM_90:
> - *tx = 1.0 - sy;
> - *ty = sx;
> - break;
> - case WL_OUTPUT_TRANSFORM_FLIPPED_90:
> - *tx = 1.0 - sy;
> - *ty = 1.0 - sx;
> - break;
> - case WL_OUTPUT_TRANSFORM_180:
> - *tx = 1.0 - sx;
> - *ty = 1.0 - sy;
> - break;
> - case WL_OUTPUT_TRANSFORM_FLIPPED_180:
> - *tx = sx;
> - *ty = 1.0 - sy;
> - break;
> - case WL_OUTPUT_TRANSFORM_270:
> - *tx = sy;
> - *ty = 1.0 - sx;
> - break;
> - case WL_OUTPUT_TRANSFORM_FLIPPED_270:
> - *tx = sy;
> - *ty = sx;
> - break;
> - }
> -}
> -
> static int
> texture_region(struct weston_surface *es, pixman_region32_t *region,
> pixman_region32_t *surf_region)
> @@ -578,13 +537,23 @@ texture_region(struct weston_surface *es, pixman_region32_t *region,
> vtxcnt = wl_array_add(&ec->vtxcnt, nrects * nsurf * sizeof *vtxcnt);
>
> inv_width = 1.0 / es->pitch;
> - inv_height = 1.0 / es->geometry.height;
> +
> + switch (es->buffer_transform) {
> + case WL_OUTPUT_TRANSFORM_90:
> + case WL_OUTPUT_TRANSFORM_270:
> + case WL_OUTPUT_TRANSFORM_FLIPPED_90:
> + case WL_OUTPUT_TRANSFORM_FLIPPED_270:
> + inv_height = 1.0 / es->geometry.width;
> + break;
> + default:
> + inv_height = 1.0 / es->geometry.height;
> + }
>
> for (i = 0; i < nrects; i++) {
> pixman_box32_t *rect = &rects[i];
> for (j = 0; j < nsurf; j++) {
> pixman_box32_t *surf_rect = &surf_rects[j];
> - GLfloat sx, sy, tx, ty;
> + GLfloat sx, sy, bx, by;
> GLfloat ex[8], ey[8]; /* edge points in screen space */
> int n;
>
> @@ -613,12 +582,10 @@ texture_region(struct weston_surface *es, pixman_region32_t *region,
> *(v++) = ex[k];
> *(v++) = ey[k];
> /* texcoord: */
> - transform_texcoord(es,
> - sx * inv_width,
> - sy * inv_height,
> - &tx, &ty);
> - *(v++) = tx;
> - *(v++) = ty;
> + weston_surface_to_buffer_float(es, sx, sy,
> + &bx, &by);
> + *(v++) = bx * inv_width;
> + *(v++) = by * inv_height;
> }
>
> vtxcnt[nvtx++] = n;
> @@ -1107,12 +1074,14 @@ gl_renderer_flush_damage(struct weston_surface *surface)
> data = wl_shm_buffer_get_data(surface->buffer);
> 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);
> - glTexSubImage2D(GL_TEXTURE_2D, 0,
> - rectangles[i].x1, rectangles[i].y1,
> - rectangles[i].x2 - rectangles[i].x1,
> - rectangles[i].y2 - rectangles[i].y1,
> + pixman_box32_t r;
> +
> + r = weston_surface_to_buffer_rect(surface, rectangles[i]);
> +
> + glPixelStorei(GL_UNPACK_SKIP_PIXELS, r.x1);
> + glPixelStorei(GL_UNPACK_SKIP_ROWS, r.y1);
> + glTexSubImage2D(GL_TEXTURE_2D, 0, r.x1, r.y1,
> + r.x2 - r.x1, r.y2 - r.y1,
> GL_BGRA_EXT, GL_UNSIGNED_BYTE, data);
> }
> #endif
> @@ -1228,16 +1197,7 @@ gl_renderer_attach(struct weston_surface *es, struct wl_buffer *buffer)
> gs->images[i]);
> }
>
> - switch(es->buffer_transform) {
> - case WL_OUTPUT_TRANSFORM_90:
> - case WL_OUTPUT_TRANSFORM_270:
> - case WL_OUTPUT_TRANSFORM_FLIPPED_90:
> - case WL_OUTPUT_TRANSFORM_FLIPPED_270:
> - es->pitch = buffer->height;
> - break;
> - default:
> - es->pitch = buffer->width;
> - }
> + es->pitch = buffer->width;
> } else {
> weston_log("unhandled buffer type!\n");
> }
> --
> 1.7.10.4
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
More information about the wayland-devel
mailing list