[PATCH 07/15] window: Store server_allocation in surface size

alexl at redhat.com alexl at redhat.com
Wed May 22 05:41:31 PDT 2013


From: Alexander Larsson <alexl at redhat.com>

We used to just store the buffer size here which is not right if the
surface has a buffer_transform or a buffer_scale. To fix this we pass
the transform and scale into the toysurface prepare and swap calls and
move both the surface to buffer and the buffer to surface size
conversion there.

Without this interactive resize on the top or left sides of a transformed
or scaled surface will not work correctly.
---
 clients/window.c | 92 ++++++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 72 insertions(+), 20 deletions(-)

diff --git a/clients/window.c b/clients/window.c
index 00ffd27..6dd6533 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -158,7 +158,8 @@ struct toysurface {
 	 * Returns the Cairo surface to draw to.
 	 */
 	cairo_surface_t *(*prepare)(struct toysurface *base, int dx, int dy,
-				    int width, int height, uint32_t flags);
+				    int32_t width, int32_t height, uint32_t flags,
+				    enum wl_output_transform buffer_transform, uint32_t buffer_scale);
 
 	/*
 	 * Post the surface to the server, returning the server allocation
@@ -166,6 +167,7 @@ struct toysurface {
 	 * after calling this.
 	 */
 	void (*swap)(struct toysurface *base,
+		     enum wl_output_transform buffer_transform, uint32_t buffer_scale,
 		     struct rectangle *server_allocation);
 
 	/*
@@ -463,6 +465,50 @@ debug_print(void *proxy, int line, const char *func, const char *fmt, ...)
 
 #endif
 
+static void
+surface_to_buffer_size (enum wl_output_transform buffer_transform, uint32_t buffer_scale, int32_t *width, int32_t *height)
+{
+	int32_t tmp;
+
+	switch (buffer_transform) {
+	case WL_OUTPUT_TRANSFORM_90:
+	case WL_OUTPUT_TRANSFORM_270:
+	case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+	case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+		tmp = *width;
+		*width = *height;
+		*height = tmp;
+		break;
+	default:
+		break;
+	}
+
+	*width *= buffer_scale;
+	*height *= buffer_scale;
+}
+
+static void
+buffer_to_surface_size (enum wl_output_transform buffer_transform, uint32_t buffer_scale, int32_t *width, int32_t *height)
+{
+	int32_t tmp;
+
+	switch (buffer_transform) {
+	case WL_OUTPUT_TRANSFORM_90:
+	case WL_OUTPUT_TRANSFORM_270:
+	case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+	case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+		tmp = *width;
+		*width = *height;
+		*height = tmp;
+		break;
+	default:
+		break;
+	}
+
+	*width /= buffer_scale;
+	*height /= buffer_scale;
+}
+
 #ifdef HAVE_CAIRO_EGL
 
 struct egl_window_surface {
@@ -482,10 +528,13 @@ to_egl_window_surface(struct toysurface *base)
 
 static cairo_surface_t *
 egl_window_surface_prepare(struct toysurface *base, int dx, int dy,
-			   int width, int height, uint32_t flags)
+			   int32_t width, int32_t height, uint32_t flags,
+			   enum wl_output_transform buffer_transform, uint32_t buffer_scale)
 {
 	struct egl_window_surface *surface = to_egl_window_surface(base);
 
+	surface_to_buffer_size (buffer_transform, buffer_scale, &width, &height);
+
 	wl_egl_window_resize(surface->egl_window, width, height, dx, dy);
 	cairo_gl_surface_set_size(surface->cairo_surface, width, height);
 
@@ -494,6 +543,7 @@ egl_window_surface_prepare(struct toysurface *base, int dx, int dy,
 
 static void
 egl_window_surface_swap(struct toysurface *base,
+			enum wl_output_transform buffer_transform, uint32_t buffer_scale,
 			struct rectangle *server_allocation)
 {
 	struct egl_window_surface *surface = to_egl_window_surface(base);
@@ -502,6 +552,10 @@ egl_window_surface_swap(struct toysurface *base,
 	wl_egl_window_get_attached_size(surface->egl_window,
 					&server_allocation->width,
 					&server_allocation->height);
+
+	buffer_to_surface_size (buffer_transform, buffer_scale,
+				&server_allocation->width,
+				&server_allocation->height);
 }
 
 static int
@@ -948,11 +1002,12 @@ static const struct wl_buffer_listener shm_surface_buffer_listener = {
 
 static cairo_surface_t *
 shm_surface_prepare(struct toysurface *base, int dx, int dy,
-		    int width, int height, uint32_t flags)
+		    int32_t width, int32_t height, uint32_t flags,
+		    enum wl_output_transform buffer_transform, uint32_t buffer_scale)
 {
 	int resize_hint = !!(flags & SURFACE_HINT_RESIZE);
 	struct shm_surface *surface = to_shm_surface(base);
-	struct rectangle rect = { 0, 0, width, height };
+	struct rectangle rect = { 0};
 	struct shm_surface_leaf *leaf = NULL;
 	int i;
 
@@ -984,6 +1039,8 @@ shm_surface_prepare(struct toysurface *base, int dx, int dy,
 		leaf->resize_pool = NULL;
 	}
 
+	surface_to_buffer_size (buffer_transform, buffer_scale, &width, &height);
+
 	if (leaf->cairo_surface &&
 	    cairo_image_surface_get_width(leaf->cairo_surface) == width &&
 	    cairo_image_surface_get_height(leaf->cairo_surface) == height)
@@ -1003,6 +1060,9 @@ shm_surface_prepare(struct toysurface *base, int dx, int dy,
 						    6 * 1024 * 1024);
 	}
 
+	rect.width = width;
+	rect.height = height;
+
 	leaf->cairo_surface =
 		display_create_shm_surface(surface->display, &rect,
 					   surface->flags,
@@ -1019,6 +1079,7 @@ out:
 
 static void
 shm_surface_swap(struct toysurface *base,
+		 enum wl_output_transform buffer_transform, uint32_t buffer_scale,
 		 struct rectangle *server_allocation)
 {
 	struct shm_surface *surface = to_shm_surface(base);
@@ -1029,6 +1090,10 @@ shm_surface_swap(struct toysurface *base,
 	server_allocation->height =
 		cairo_image_surface_get_height(leaf->cairo_surface);
 
+	buffer_to_surface_size (buffer_transform, buffer_scale,
+				&server_allocation->width,
+				&server_allocation->height);
+
 	wl_surface_attach(surface->surface, leaf->data->buffer,
 			  surface->dx, surface->dy);
 	wl_surface_damage(surface->surface, 0, 0,
@@ -1269,6 +1334,7 @@ surface_flush(struct surface *surface)
 	}
 
 	surface->toysurface->swap(surface->toysurface,
+				  surface->buffer_transform, surface->buffer_scale,
 				  &surface->server_allocation);
 
 	cairo_surface_destroy(surface->cairo_surface);
@@ -1314,21 +1380,6 @@ surface_create_surface(struct surface *surface, int dx, int dy, uint32_t flags)
 	struct display *display = surface->window->display;
 	struct rectangle allocation = surface->allocation;
 
-	switch (surface->buffer_transform) {
-	case WL_OUTPUT_TRANSFORM_90:
-	case WL_OUTPUT_TRANSFORM_270:
-	case WL_OUTPUT_TRANSFORM_FLIPPED_90:
-	case WL_OUTPUT_TRANSFORM_FLIPPED_270:
-		allocation.width = surface->allocation.height;
-		allocation.height = surface->allocation.width;
-		break;
-	default:
-		break;
-	}
-
-	allocation.width *= surface->buffer_scale;
-	allocation.height *= surface->buffer_scale;
-
 	if (!surface->toysurface && display->dpy &&
 	    surface->buffer_type == WINDOW_BUFFER_TYPE_EGL_WINDOW) {
 		surface->toysurface =
@@ -1345,7 +1396,8 @@ surface_create_surface(struct surface *surface, int dx, int dy, uint32_t flags)
 
 	surface->cairo_surface = surface->toysurface->prepare(
 		surface->toysurface, dx, dy,
-		allocation.width, allocation.height, flags);
+		allocation.width, allocation.height, flags,
+		surface->buffer_transform, surface->buffer_scale);
 }
 
 static void
-- 
1.8.1.4



More information about the wayland-devel mailing list