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;
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)
{
}
}
+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)
{
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);
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,
surface_frame,
surface_set_opaque_region,
surface_set_input_region,
- surface_commit
+ surface_commit,
+ surface_set_buffer_transform
};
static void
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 {
/* wl_surface.frame */
struct wl_list frame_callback_list;
+
+ /* wl_surface.set_buffer_transform */
+ uint32_t buffer_transform;
} pending;
/*
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,
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)
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;
*(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;
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");
}
}
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);
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
{
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 &&
}
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;
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);
}
}
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. */
weston_surface_configure(surface,
surface->output->x + x,
surface->output->y + y,
- surface->buffer->width,
- surface->buffer->height);
+ width, height);
}
static void