[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