[PATCH weston 1/3] compositor: Implement buffer transformation
Ander Conselvan de Oliveira
ander.conselvan.de.oliveira at intel.com
Tue Nov 27 07:03:42 PST 2012
Implement the wl_surface.set_buffer_transform request. This includes
tracking the double-buffered buffer transformation parameter and making
the gl renderer able to handle transformed buffers.
---
src/compositor.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++---
src/compositor.h | 8 ++++++
src/gl-renderer.c | 62 ++++++++++++++++++++++++++++++++++++++++++---
src/shell.c | 34 +++++++++++++++----------
4 files changed, 156 insertions(+), 21 deletions(-)
diff --git a/src/compositor.c b/src/compositor.c
index 6eb0b8c..44cd4a8 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -245,6 +245,8 @@ weston_surface_create(struct weston_compositor *compositor)
pixman_region32_init(&surface->texture_damage);
surface->buffer = NULL;
+ surface->buffer_transform = WL_OUTPUT_TRANSFORM_NORMAL;
+ surface->pending.buffer_transform = surface->buffer_transform;
surface->output = NULL;
surface->plane = &compositor->primary_plane;
@@ -653,6 +655,34 @@ weston_surface_is_mapped(struct weston_surface *surface)
return 0;
}
+WL_EXPORT int32_t
+weston_surface_buffer_width(struct weston_surface *surface)
+{
+ 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:
+ return surface->buffer->height;
+ default:
+ return surface->buffer->width;
+ }
+}
+
+WL_EXPORT int32_t
+weston_surface_buffer_height(struct weston_surface *surface)
+{
+ 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:
+ return surface->buffer->width;
+ default:
+ return surface->buffer->height;
+ }
+}
+
WL_EXPORT uint32_t
weston_compositor_get_time(void)
{
@@ -1237,6 +1267,31 @@ surface_set_input_region(struct wl_client *client,
}
}
+static int
+surface_pending_buffer_has_different_size(struct weston_surface *surface)
+{
+ int width, height;
+
+ switch (surface->pending.buffer_transform) {
+ case WL_OUTPUT_TRANSFORM_90:
+ case WL_OUTPUT_TRANSFORM_270:
+ case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+ case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+ height = surface->pending.buffer->width;
+ width = surface->pending.buffer->height;
+ break;
+ default:
+ width = surface->pending.buffer->width;
+ height = surface->pending.buffer->height;
+ }
+
+ if (width == surface->geometry.width &&
+ height == surface->geometry.height)
+ return 0;
+ else
+ return 1;
+}
+
static void
surface_commit(struct wl_client *client, struct wl_resource *resource)
{
@@ -1245,10 +1300,12 @@ surface_commit(struct wl_client *client, struct wl_resource *resource)
if (surface->pending.sx || surface->pending.sy ||
(surface->pending.buffer &&
- (surface->pending.buffer->width != surface->geometry.width ||
- surface->pending.buffer->height != surface->geometry.height)))
+ surface_pending_buffer_has_different_size(surface)))
surface->geometry.dirty = 1;
+ /* wl_surface.set_buffer_rotation */
+ surface->buffer_transform = surface->pending.buffer_transform;
+
/* wl_surface.attach */
if (surface->pending.buffer || surface->pending.remove_contents)
weston_surface_attach(surface, surface->pending.buffer);
@@ -1298,6 +1355,15 @@ surface_commit(struct wl_client *client, struct wl_resource *resource)
weston_surface_schedule_repaint(surface);
}
+static void
+surface_set_buffer_transform(struct wl_client *client,
+ struct wl_resource *resource, int transform)
+{
+ struct weston_surface *surface = resource->data;
+
+ surface->pending.buffer_transform = transform;
+}
+
static const struct wl_surface_interface surface_interface = {
surface_destroy,
surface_attach,
@@ -1305,7 +1371,8 @@ static const struct wl_surface_interface surface_interface = {
surface_frame,
surface_set_opaque_region,
surface_set_input_region,
- surface_commit
+ surface_commit,
+ surface_set_buffer_transform
};
static void
diff --git a/src/compositor.h b/src/compositor.h
index e770664..9e6355d 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -437,6 +437,7 @@ struct weston_surface {
struct wl_buffer *buffer;
struct wl_listener buffer_destroy_listener;
+ uint32_t buffer_transform;
/* All the pending state, that wl_surface.commit will apply. */
struct {
@@ -458,6 +459,9 @@ struct weston_surface {
/* wl_surface.frame */
struct wl_list frame_callback_list;
+
+ /* wl_surface.set_buffer_transform */
+ uint32_t buffer_transform;
} pending;
/*
@@ -495,6 +499,10 @@ void
weston_surface_from_global_fixed(struct weston_surface *surface,
wl_fixed_t x, wl_fixed_t y,
wl_fixed_t *sx, wl_fixed_t *sy);
+int32_t
+weston_surface_buffer_width(struct weston_surface *surface);
+int32_t
+weston_surface_buffer_height(struct weston_surface *surface);
void
weston_spring_init(struct weston_spring *spring,
diff --git a/src/gl-renderer.c b/src/gl-renderer.c
index 249efbc..5824765 100644
--- a/src/gl-renderer.c
+++ b/src/gl-renderer.c
@@ -517,6 +517,47 @@ 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)
@@ -543,7 +584,7 @@ texture_region(struct weston_surface *es, pixman_region32_t *region,
pixman_box32_t *rect = &rects[i];
for (j = 0; j < nsurf; j++) {
pixman_box32_t *surf_rect = &surf_rects[j];
- GLfloat sx, sy;
+ GLfloat sx, sy, tx, ty;
GLfloat ex[8], ey[8]; /* edge points in screen space */
int n;
@@ -572,8 +613,12 @@ texture_region(struct weston_surface *es, pixman_region32_t *region,
*(v++) = ex[k];
*(v++) = ey[k];
/* texcoord: */
- *(v++) = sx * inv_width;
- *(v++) = sy * inv_height;
+ transform_texcoord(es,
+ sx * inv_width,
+ sy * inv_height,
+ &tx, &ty);
+ *(v++) = tx;
+ *(v++) = ty;
}
vtxcnt[nvtx++] = n;
@@ -1183,7 +1228,16 @@ gl_renderer_attach(struct weston_surface *es, struct wl_buffer *buffer)
gs->images[i]);
}
- es->pitch = buffer->width;
+ 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;
+ }
} else {
weston_log("unhandled buffer type!\n");
}
diff --git a/src/shell.c b/src/shell.c
index 6bd89ec..89d7627 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -2129,7 +2129,8 @@ configure_static_surface(struct weston_surface *es, struct weston_layer *layer)
}
weston_surface_configure(es, es->output->x, es->output->y,
- es->buffer->width, es->buffer->height);
+ weston_surface_buffer_width(es),
+ weston_surface_buffer_height(es));
if (wl_list_empty(&es->layer_link)) {
wl_list_insert(&layer->surface_list, &es->layer_link);
@@ -2815,12 +2816,14 @@ hide_input_panels(struct wl_listener *listener, void *data)
static void
center_on_output(struct weston_surface *surface, struct weston_output *output)
{
- float x = (output->width - surface->buffer->width) / 2;
- float y = (output->height - surface->buffer->height) / 2;
+ int32_t width = weston_surface_buffer_width(surface);
+ int32_t height = weston_surface_buffer_height(surface);
+ float x, y;
- weston_surface_configure(surface, output->x + x, output->y + y,
- surface->buffer->width,
- surface->buffer->height);
+ x = output->x + (output->width - width) / 2;
+ y = output->y + (output->height - height) / 2;
+
+ weston_surface_configure(surface, x, y, width, height);
}
static void
@@ -3029,6 +3032,8 @@ shell_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy)
{
struct shell_surface *shsurf = get_shell_surface(es);
struct desktop_shell *shell = shsurf->shell;
+ int32_t width = weston_surface_buffer_width(es);
+ int32_t height = weston_surface_buffer_height(es);
int type_changed = 0;
if (shsurf->next_type != SHELL_SURFACE_NONE &&
@@ -3038,10 +3043,10 @@ shell_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy)
}
if (!weston_surface_is_mapped(es)) {
- map(shell, es, es->buffer->width, es->buffer->height, sx, sy);
+ map(shell, es, width, height, sx, sy);
} else if (type_changed || sx != 0 || sy != 0 ||
- es->geometry.width != es->buffer->width ||
- es->geometry.height != es->buffer->height) {
+ es->geometry.width != width ||
+ es->geometry.height != height) {
float from_x, from_y;
float to_x, to_y;
@@ -3050,7 +3055,7 @@ shell_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy)
configure(shell, es,
es->geometry.x + to_x - from_x,
es->geometry.y + to_y - from_y,
- es->buffer->width, es->buffer->height);
+ width, height);
}
}
@@ -3216,8 +3221,10 @@ static void
input_panel_configure(struct weston_surface *surface, int32_t sx, int32_t sy)
{
struct weston_mode *mode = surface->output->current;
- float x = (mode->width - surface->buffer->width) / 2;
- float y = mode->height - surface->buffer->height;
+ int32_t width = weston_surface_buffer_width(surface);
+ int32_t height = weston_surface_buffer_height(surface);
+ float x = (mode->width - width) / 2;
+ float y = mode->height - height;
/* Don't map the input panel here, wait for
* show_input_panels signal. */
@@ -3225,8 +3232,7 @@ input_panel_configure(struct weston_surface *surface, int32_t sx, int32_t sy)
weston_surface_configure(surface,
surface->output->x + x,
surface->output->y + y,
- surface->buffer->width,
- surface->buffer->height);
+ width, height);
}
static void
--
1.7.10.4
More information about the wayland-devel
mailing list