compositor: Implement buffer transformation

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.
This commit is contained in:
Ander Conselvan de Oliveira
2012-11-27 17:03:42 +02:00
committed by Kristian Høgsberg
parent 864c784b5c
commit 012b4c78c9
4 changed files with 156 additions and 21 deletions
+70 -3
View File
@@ -245,6 +245,8 @@ weston_surface_create(struct weston_compositor *compositor)
pixman_region32_init(&surface->texture_damage); pixman_region32_init(&surface->texture_damage);
surface->buffer = NULL; surface->buffer = NULL;
surface->buffer_transform = WL_OUTPUT_TRANSFORM_NORMAL;
surface->pending.buffer_transform = surface->buffer_transform;
surface->output = NULL; surface->output = NULL;
surface->plane = &compositor->primary_plane; surface->plane = &compositor->primary_plane;
@@ -653,6 +655,34 @@ weston_surface_is_mapped(struct weston_surface *surface)
return 0; 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 WL_EXPORT uint32_t
weston_compositor_get_time(void) 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 static void
surface_commit(struct wl_client *client, struct wl_resource *resource) 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 || if (surface->pending.sx || surface->pending.sy ||
(surface->pending.buffer && (surface->pending.buffer &&
(surface->pending.buffer->width != surface->geometry.width || surface_pending_buffer_has_different_size(surface)))
surface->pending.buffer->height != surface->geometry.height)))
surface->geometry.dirty = 1; surface->geometry.dirty = 1;
/* wl_surface.set_buffer_rotation */
surface->buffer_transform = surface->pending.buffer_transform;
/* wl_surface.attach */ /* wl_surface.attach */
if (surface->pending.buffer || surface->pending.remove_contents) if (surface->pending.buffer || surface->pending.remove_contents)
weston_surface_attach(surface, surface->pending.buffer); 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); 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 = { static const struct wl_surface_interface surface_interface = {
surface_destroy, surface_destroy,
surface_attach, surface_attach,
@@ -1305,7 +1371,8 @@ static const struct wl_surface_interface surface_interface = {
surface_frame, surface_frame,
surface_set_opaque_region, surface_set_opaque_region,
surface_set_input_region, surface_set_input_region,
surface_commit surface_commit,
surface_set_buffer_transform
}; };
static void static void
+8
View File
@@ -437,6 +437,7 @@ struct weston_surface {
struct wl_buffer *buffer; struct wl_buffer *buffer;
struct wl_listener buffer_destroy_listener; struct wl_listener buffer_destroy_listener;
uint32_t buffer_transform;
/* All the pending state, that wl_surface.commit will apply. */ /* All the pending state, that wl_surface.commit will apply. */
struct { struct {
@@ -458,6 +459,9 @@ struct weston_surface {
/* wl_surface.frame */ /* wl_surface.frame */
struct wl_list frame_callback_list; struct wl_list frame_callback_list;
/* wl_surface.set_buffer_transform */
uint32_t buffer_transform;
} pending; } pending;
/* /*
@@ -495,6 +499,10 @@ void
weston_surface_from_global_fixed(struct weston_surface *surface, weston_surface_from_global_fixed(struct weston_surface *surface,
wl_fixed_t x, wl_fixed_t y, wl_fixed_t x, wl_fixed_t y,
wl_fixed_t *sx, wl_fixed_t *sy); 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 void
weston_spring_init(struct weston_spring *spring, weston_spring_init(struct weston_spring *spring,
+58 -4
View File
@@ -517,6 +517,47 @@ calculate_edges(struct weston_surface *es, pixman_box32_t *rect,
return n; 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 static int
texture_region(struct weston_surface *es, pixman_region32_t *region, texture_region(struct weston_surface *es, pixman_region32_t *region,
pixman_region32_t *surf_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]; pixman_box32_t *rect = &rects[i];
for (j = 0; j < nsurf; j++) { for (j = 0; j < nsurf; j++) {
pixman_box32_t *surf_rect = &surf_rects[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 */ GLfloat ex[8], ey[8]; /* edge points in screen space */
int n; int n;
@@ -572,8 +613,12 @@ texture_region(struct weston_surface *es, pixman_region32_t *region,
*(v++) = ex[k]; *(v++) = ex[k];
*(v++) = ey[k]; *(v++) = ey[k];
/* texcoord: */ /* texcoord: */
*(v++) = sx * inv_width; transform_texcoord(es,
*(v++) = sy * inv_height; sx * inv_width,
sy * inv_height,
&tx, &ty);
*(v++) = tx;
*(v++) = ty;
} }
vtxcnt[nvtx++] = n; vtxcnt[nvtx++] = n;
@@ -1183,7 +1228,16 @@ gl_renderer_attach(struct weston_surface *es, struct wl_buffer *buffer)
gs->images[i]); 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 { } else {
weston_log("unhandled buffer type!\n"); weston_log("unhandled buffer type!\n");
} }
+20 -14
View File
@@ -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, 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)) { if (wl_list_empty(&es->layer_link)) {
wl_list_insert(&layer->surface_list, &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 static void
center_on_output(struct weston_surface *surface, struct weston_output *output) center_on_output(struct weston_surface *surface, struct weston_output *output)
{ {
float x = (output->width - surface->buffer->width) / 2; int32_t width = weston_surface_buffer_width(surface);
float y = (output->height - surface->buffer->height) / 2; int32_t height = weston_surface_buffer_height(surface);
float x, y;
weston_surface_configure(surface, output->x + x, output->y + y, x = output->x + (output->width - width) / 2;
surface->buffer->width, y = output->y + (output->height - height) / 2;
surface->buffer->height);
weston_surface_configure(surface, x, y, width, height);
} }
static void 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 shell_surface *shsurf = get_shell_surface(es);
struct desktop_shell *shell = shsurf->shell; 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; int type_changed = 0;
if (shsurf->next_type != SHELL_SURFACE_NONE && 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)) { 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 || } else if (type_changed || sx != 0 || sy != 0 ||
es->geometry.width != es->buffer->width || es->geometry.width != width ||
es->geometry.height != es->buffer->height) { es->geometry.height != height) {
float from_x, from_y; float from_x, from_y;
float to_x, to_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, configure(shell, es,
es->geometry.x + to_x - from_x, es->geometry.x + to_x - from_x,
es->geometry.y + to_y - from_y, 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) input_panel_configure(struct weston_surface *surface, int32_t sx, int32_t sy)
{ {
struct weston_mode *mode = surface->output->current; struct weston_mode *mode = surface->output->current;
float x = (mode->width - surface->buffer->width) / 2; int32_t width = weston_surface_buffer_width(surface);
float y = mode->height - surface->buffer->height; 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 /* Don't map the input panel here, wait for
* show_input_panels signal. */ * 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, weston_surface_configure(surface,
surface->output->x + x, surface->output->x + x,
surface->output->y + y, surface->output->y + y,
surface->buffer->width, width, height);
surface->buffer->height);
} }
static void static void