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:
parent
864c784b5c
commit
012b4c78c9
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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");
|
||||
}
|
||||
|
34
src/shell.c
34
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user