compositor: Support output/buffer scaling
If you specify e.g. scale=2 in weston.ini an output section for the X11 backend we automatically upscale all normal surfaces by this amount. Additionally we respect a buffer_scale set on the buffer to mean that the buffer is already in a scaled form. This works with both the gl and the pixman renderer. The non-X backends compile and work, but don't support changing the output scale (they do downscale as needed due to buffer_scale though). This also sends the new "scale" and "done" events on wl_output, making clients aware of the scale.
This commit is contained in:
parent
1f206b4ce4
commit
4ea9552d05
@ -858,7 +858,8 @@ drm_output_prepare_overlay_surface(struct weston_output *output_base,
|
||||
box = pixman_region32_extents(&dest_rect);
|
||||
tbox = weston_transformed_rect(output_base->width,
|
||||
output_base->height,
|
||||
output_base->transform, *box);
|
||||
output_base->transform,
|
||||
1, *box);
|
||||
s->dest_x = tbox.x1;
|
||||
s->dest_y = tbox.y1;
|
||||
s->dest_w = tbox.x2 - tbox.x1;
|
||||
@ -895,7 +896,7 @@ drm_output_prepare_overlay_surface(struct weston_output *output_base,
|
||||
|
||||
tbox = weston_transformed_rect(wl_fixed_from_int(es->geometry.width),
|
||||
wl_fixed_from_int(es->geometry.height),
|
||||
es->buffer_transform, tbox);
|
||||
es->buffer_transform, 1, tbox);
|
||||
|
||||
s->src_x = tbox.x1 << 8;
|
||||
s->src_y = tbox.y1 << 8;
|
||||
@ -1813,7 +1814,7 @@ create_output_for_connector(struct drm_compositor *ec,
|
||||
|
||||
weston_output_init(&output->base, &ec->base, x, y,
|
||||
connector->mmWidth, connector->mmHeight,
|
||||
o ? o->transform : WL_OUTPUT_TRANSFORM_NORMAL);
|
||||
o ? o->transform : WL_OUTPUT_TRANSFORM_NORMAL, 1);
|
||||
|
||||
if (ec->use_pixman) {
|
||||
if (drm_output_init_pixman(output, ec) < 0) {
|
||||
|
@ -537,7 +537,8 @@ fbdev_output_create(struct fbdev_compositor *compositor,
|
||||
weston_output_init(&output->base, &compositor->base,
|
||||
0, 0, output->fb_info.width_mm,
|
||||
output->fb_info.height_mm,
|
||||
WL_OUTPUT_TRANSFORM_NORMAL);
|
||||
WL_OUTPUT_TRANSFORM_NORMAL,
|
||||
1);
|
||||
|
||||
width = output->fb_info.x_resolution;
|
||||
height = output->fb_info.y_resolution;
|
||||
|
@ -112,7 +112,7 @@ headless_compositor_create_output(struct headless_compositor *c,
|
||||
|
||||
output->base.current = &output->mode;
|
||||
weston_output_init(&output->base, &c->base, 0, 0, width, height,
|
||||
WL_OUTPUT_TRANSFORM_NORMAL);
|
||||
WL_OUTPUT_TRANSFORM_NORMAL, 1);
|
||||
|
||||
output->base.make = "weston";
|
||||
output->base.model = "headless";
|
||||
|
@ -1080,7 +1080,8 @@ rpi_output_create(struct rpi_compositor *compositor)
|
||||
|
||||
weston_output_init(&output->base, &compositor->base,
|
||||
0, 0, round(mm_width), round(mm_height),
|
||||
WL_OUTPUT_TRANSFORM_NORMAL);
|
||||
WL_OUTPUT_TRANSFORM_NORMAL,
|
||||
1);
|
||||
|
||||
if (gl_renderer_output_create(&output->base,
|
||||
(EGLNativeWindowType)&output->egl_window) < 0)
|
||||
|
@ -267,7 +267,7 @@ wayland_compositor_create_output(struct wayland_compositor *c,
|
||||
|
||||
output->base.current = &output->mode;
|
||||
weston_output_init(&output->base, &c->base, 0, 0, width, height,
|
||||
WL_OUTPUT_TRANSFORM_NORMAL);
|
||||
WL_OUTPUT_TRANSFORM_NORMAL, 1);
|
||||
|
||||
output->base.make = "waywayland";
|
||||
output->base.model = "none";
|
||||
|
@ -59,6 +59,7 @@
|
||||
static char *output_name;
|
||||
static char *output_mode;
|
||||
static char *output_transform;
|
||||
static char *output_scale;
|
||||
static int option_width;
|
||||
static int option_height;
|
||||
static int option_count;
|
||||
@ -68,6 +69,7 @@ struct x11_configured_output {
|
||||
char *name;
|
||||
int width, height;
|
||||
uint32_t transform;
|
||||
unsigned int scale;
|
||||
struct wl_list link;
|
||||
};
|
||||
|
||||
@ -125,6 +127,7 @@ struct x11_output {
|
||||
int shm_id;
|
||||
void *buf;
|
||||
uint8_t depth;
|
||||
uint32_t scale;
|
||||
};
|
||||
|
||||
static struct xkb_keymap *
|
||||
@ -534,8 +537,12 @@ x11_output_wait_for_map(struct x11_compositor *c, struct x11_output *output)
|
||||
configure_notify =
|
||||
(xcb_configure_notify_event_t *) event;
|
||||
|
||||
output->mode.width = configure_notify->width;
|
||||
output->mode.height = configure_notify->height;
|
||||
|
||||
if (configure_notify->width % output->scale != 0 ||
|
||||
configure_notify->height % output->scale != 0)
|
||||
weston_log("Resolution is not a multiple of screen size, rounding\n");
|
||||
output->mode.width = configure_notify->width / output->scale;
|
||||
output->mode.height = configure_notify->height / output->scale;
|
||||
configured = 1;
|
||||
break;
|
||||
}
|
||||
@ -677,7 +684,7 @@ static struct x11_output *
|
||||
x11_compositor_create_output(struct x11_compositor *c, int x, int y,
|
||||
int width, int height, int fullscreen,
|
||||
int no_input, char *configured_name,
|
||||
uint32_t transform)
|
||||
uint32_t transform, uint32_t scale)
|
||||
{
|
||||
static const char name[] = "Weston Compositor";
|
||||
static const char class[] = "weston-1\0Weston Compositor";
|
||||
@ -686,6 +693,7 @@ x11_compositor_create_output(struct x11_compositor *c, int x, int y,
|
||||
xcb_screen_iterator_t iter;
|
||||
struct wm_normal_hints normal_hints;
|
||||
struct wl_event_loop *loop;
|
||||
int output_width, output_height;
|
||||
uint32_t mask = XCB_CW_EVENT_MASK | XCB_CW_CURSOR;
|
||||
xcb_atom_t atom_list[1];
|
||||
uint32_t values[2] = {
|
||||
@ -694,6 +702,9 @@ x11_compositor_create_output(struct x11_compositor *c, int x, int y,
|
||||
0
|
||||
};
|
||||
|
||||
output_width = width * scale;
|
||||
output_height = height * scale;
|
||||
|
||||
if (configured_name)
|
||||
sprintf(title, "%s - %s", name, configured_name);
|
||||
else
|
||||
@ -719,9 +730,13 @@ x11_compositor_create_output(struct x11_compositor *c, int x, int y,
|
||||
|
||||
output->mode.flags =
|
||||
WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
|
||||
if (output->scale != 1)
|
||||
output->mode.flags |= WL_OUTPUT_MODE_SCALED;
|
||||
|
||||
output->mode.width = width;
|
||||
output->mode.height = height;
|
||||
output->mode.refresh = 60000;
|
||||
output->scale = scale;
|
||||
wl_list_init(&output->base.mode_list);
|
||||
wl_list_insert(&output->base.mode_list, &output->mode.link);
|
||||
|
||||
@ -733,7 +748,7 @@ x11_compositor_create_output(struct x11_compositor *c, int x, int y,
|
||||
output->window,
|
||||
iter.data->root,
|
||||
0, 0,
|
||||
width, height,
|
||||
output_width, output_height,
|
||||
0,
|
||||
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
||||
iter.data->root_visual,
|
||||
@ -751,10 +766,10 @@ x11_compositor_create_output(struct x11_compositor *c, int x, int y,
|
||||
memset(&normal_hints, 0, sizeof normal_hints);
|
||||
normal_hints.flags =
|
||||
WM_NORMAL_HINTS_MAX_SIZE | WM_NORMAL_HINTS_MIN_SIZE;
|
||||
normal_hints.min_width = width;
|
||||
normal_hints.min_height = height;
|
||||
normal_hints.max_width = width;
|
||||
normal_hints.max_height = height;
|
||||
normal_hints.min_width = output_width;
|
||||
normal_hints.min_height = output_height;
|
||||
normal_hints.max_width = output_width;
|
||||
normal_hints.max_height = output_height;
|
||||
xcb_change_property(c->conn, XCB_PROP_MODE_REPLACE, output->window,
|
||||
c->atom.wm_normal_hints,
|
||||
c->atom.wm_size_hints, 32,
|
||||
@ -794,10 +809,10 @@ x11_compositor_create_output(struct x11_compositor *c, int x, int y,
|
||||
output->base.make = "xwayland";
|
||||
output->base.model = "none";
|
||||
weston_output_init(&output->base, &c->base,
|
||||
x, y, width, height, transform);
|
||||
x, y, width, height, transform, scale);
|
||||
|
||||
if (c->use_pixman) {
|
||||
if (x11_output_init_shm(c, output, width, height) < 0)
|
||||
if (x11_output_init_shm(c, output, output_width, output_height) < 0)
|
||||
return NULL;
|
||||
if (pixman_renderer_output_create(&output->base) < 0) {
|
||||
x11_output_deinit_shm(c, output);
|
||||
@ -960,8 +975,8 @@ x11_output_transform_coordinate(struct x11_output *x11_output,
|
||||
{
|
||||
struct weston_output *output = &x11_output->base;
|
||||
wl_fixed_t tx, ty;
|
||||
wl_fixed_t width = wl_fixed_from_int(output->width - 1);
|
||||
wl_fixed_t height = wl_fixed_from_int(output->height - 1);
|
||||
wl_fixed_t width = wl_fixed_from_int(output->width * output->scale - 1);
|
||||
wl_fixed_t height = wl_fixed_from_int(output->height * output->scale - 1);
|
||||
|
||||
switch(output->transform) {
|
||||
case WL_OUTPUT_TRANSFORM_NORMAL:
|
||||
@ -999,6 +1014,9 @@ x11_output_transform_coordinate(struct x11_output *x11_output,
|
||||
break;
|
||||
}
|
||||
|
||||
tx /= output->scale;
|
||||
ty /= output->scale;
|
||||
|
||||
tx += wl_fixed_from_int(output->x);
|
||||
ty += wl_fixed_from_int(output->y);
|
||||
|
||||
@ -1457,7 +1475,7 @@ x11_compositor_create(struct wl_display *display,
|
||||
option_height ? height :
|
||||
o->height,
|
||||
fullscreen, no_input,
|
||||
o->name, o->transform);
|
||||
o->name, o->transform, o->scale);
|
||||
if (output == NULL)
|
||||
goto err_x11_input;
|
||||
|
||||
@ -1471,7 +1489,7 @@ x11_compositor_create(struct wl_display *display,
|
||||
for (i = output_count; i < count; i++) {
|
||||
output = x11_compositor_create_output(c, x, 0, width, height,
|
||||
fullscreen, no_input, NULL,
|
||||
WL_OUTPUT_TRANSFORM_NORMAL);
|
||||
WL_OUTPUT_TRANSFORM_NORMAL, wl_fixed_from_int(1));
|
||||
if (output == NULL)
|
||||
goto err_x11_input;
|
||||
x = pixman_region32_extents(&output->base.region)->x2;
|
||||
@ -1536,7 +1554,7 @@ output_section_done(void *data)
|
||||
output = malloc(sizeof *output);
|
||||
|
||||
if (!output || !output_name || (output_name[0] != 'X') ||
|
||||
(!output_mode && !output_transform)) {
|
||||
(!output_mode && !output_transform && !output_scale)) {
|
||||
if (output_name)
|
||||
free(output_name);
|
||||
output_name = NULL;
|
||||
@ -1559,6 +1577,16 @@ output_section_done(void *data)
|
||||
output->height = 640;
|
||||
}
|
||||
|
||||
output->scale = 1;
|
||||
if (output_scale) {
|
||||
if (sscanf(output_scale, "%d", &output->scale) != 1) {
|
||||
weston_log("Invalid scale \"%s\" for output %s\n",
|
||||
output_scale, output_name);
|
||||
x11_free_configured_output(output);
|
||||
goto err_free;
|
||||
}
|
||||
}
|
||||
|
||||
x11_output_set_transform(output);
|
||||
|
||||
wl_list_insert(configured_output_list.prev, &output->link);
|
||||
@ -1570,6 +1598,7 @@ err_free:
|
||||
free(output_transform);
|
||||
output_mode = NULL;
|
||||
output_transform = NULL;
|
||||
output_scale = NULL;
|
||||
}
|
||||
|
||||
WL_EXPORT struct weston_compositor *
|
||||
@ -1597,6 +1626,7 @@ backend_init(struct wl_display *display, int *argc, char *argv[],
|
||||
{ "name", CONFIG_KEY_STRING, &output_name },
|
||||
{ "mode", CONFIG_KEY_STRING, &output_mode },
|
||||
{ "transform", CONFIG_KEY_STRING, &output_transform },
|
||||
{ "scale", CONFIG_KEY_STRING, &output_scale },
|
||||
};
|
||||
|
||||
const struct config_section config_section[] = {
|
||||
|
110
src/compositor.c
110
src/compositor.c
@ -93,6 +93,8 @@ sigchld_handler(int signal_number, void *data)
|
||||
|
||||
static void
|
||||
weston_output_transform_init(struct weston_output *output, uint32_t transform);
|
||||
static void
|
||||
weston_output_scale_init(struct weston_output *output, uint32_t scale);
|
||||
|
||||
WL_EXPORT int
|
||||
weston_output_switch_mode(struct weston_output *output, struct weston_mode *mode)
|
||||
@ -113,6 +115,7 @@ weston_output_switch_mode(struct weston_output *output, struct weston_mode *mode
|
||||
|
||||
/* Update output region and transformation matrix */
|
||||
weston_output_transform_init(output, output->transform);
|
||||
weston_output_scale_init(output, output->scale);
|
||||
|
||||
pixman_region32_init(&output->previous_damage);
|
||||
pixman_region32_init_rect(&output->region, output->x, output->y,
|
||||
@ -291,7 +294,9 @@ weston_surface_create(struct weston_compositor *compositor)
|
||||
}
|
||||
|
||||
surface->buffer_transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
surface->buffer_scale = 1;
|
||||
surface->pending.buffer_transform = surface->buffer_transform;
|
||||
surface->pending.buffer_scale = surface->buffer_scale;
|
||||
surface->output = NULL;
|
||||
surface->plane = &compositor->primary_plane;
|
||||
surface->pending.newly_attached = 0;
|
||||
@ -360,6 +365,7 @@ weston_surface_to_global_float(struct weston_surface *surface,
|
||||
WL_EXPORT void
|
||||
weston_transformed_coord(int width, int height,
|
||||
enum wl_output_transform transform,
|
||||
uint32_t scale,
|
||||
float sx, float sy, float *bx, float *by)
|
||||
{
|
||||
switch (transform) {
|
||||
@ -397,20 +403,24 @@ weston_transformed_coord(int width, int height,
|
||||
*by = sx;
|
||||
break;
|
||||
}
|
||||
|
||||
*bx *= scale;
|
||||
*by *= scale;
|
||||
}
|
||||
|
||||
WL_EXPORT pixman_box32_t
|
||||
weston_transformed_rect(int width, int height,
|
||||
enum wl_output_transform transform,
|
||||
uint32_t scale,
|
||||
pixman_box32_t rect)
|
||||
{
|
||||
float x1, x2, y1, y2;
|
||||
|
||||
pixman_box32_t ret;
|
||||
|
||||
weston_transformed_coord(width, height, transform,
|
||||
weston_transformed_coord(width, height, transform, scale,
|
||||
rect.x1, rect.y1, &x1, &y1);
|
||||
weston_transformed_coord(width, height, transform,
|
||||
weston_transformed_coord(width, height, transform, scale,
|
||||
rect.x2, rect.y2, &x2, &y2);
|
||||
|
||||
if (x1 <= x2) {
|
||||
@ -439,16 +449,34 @@ weston_surface_to_buffer_float(struct weston_surface *surface,
|
||||
weston_transformed_coord(surface->geometry.width,
|
||||
surface->geometry.height,
|
||||
surface->buffer_transform,
|
||||
surface->buffer_scale,
|
||||
sx, sy, bx, by);
|
||||
}
|
||||
|
||||
WL_EXPORT void
|
||||
weston_surface_to_buffer(struct weston_surface *surface,
|
||||
int sx, int sy, int *bx, int *by)
|
||||
{
|
||||
float bxf, byf;
|
||||
|
||||
weston_transformed_coord(surface->geometry.width,
|
||||
surface->geometry.height,
|
||||
surface->buffer_transform,
|
||||
surface->buffer_scale,
|
||||
sx, sy, &bxf, &byf);
|
||||
*bx = floorf(bxf);
|
||||
*by = floorf(byf);
|
||||
}
|
||||
|
||||
WL_EXPORT pixman_box32_t
|
||||
weston_surface_to_buffer_rect(struct weston_surface *surface,
|
||||
pixman_box32_t rect)
|
||||
{
|
||||
return weston_transformed_rect(surface->geometry.width,
|
||||
surface->geometry.height,
|
||||
surface->buffer_transform, rect);
|
||||
surface->buffer_transform,
|
||||
surface->buffer_scale,
|
||||
rect);
|
||||
}
|
||||
|
||||
WL_EXPORT void
|
||||
@ -877,29 +905,37 @@ weston_surface_is_mapped(struct weston_surface *surface)
|
||||
WL_EXPORT int32_t
|
||||
weston_surface_buffer_width(struct weston_surface *surface)
|
||||
{
|
||||
int32_t width;
|
||||
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_ref.buffer->height;
|
||||
width = surface->buffer_ref.buffer->height;
|
||||
break;
|
||||
default:
|
||||
return surface->buffer_ref.buffer->width;
|
||||
width = surface->buffer_ref.buffer->width;
|
||||
break;
|
||||
}
|
||||
return width / surface->buffer_scale;
|
||||
}
|
||||
|
||||
WL_EXPORT int32_t
|
||||
weston_surface_buffer_height(struct weston_surface *surface)
|
||||
{
|
||||
int32_t height;
|
||||
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_ref.buffer->width;
|
||||
height = surface->buffer_ref.buffer->width;
|
||||
break;
|
||||
default:
|
||||
return surface->buffer_ref.buffer->height;
|
||||
height = surface->buffer_ref.buffer->height;
|
||||
break;
|
||||
}
|
||||
return height / surface->buffer_scale;
|
||||
}
|
||||
|
||||
WL_EXPORT uint32_t
|
||||
@ -1485,25 +1521,28 @@ static void
|
||||
weston_surface_commit(struct weston_surface *surface)
|
||||
{
|
||||
pixman_region32_t opaque;
|
||||
int buffer_width = 0;
|
||||
int buffer_height = 0;
|
||||
int surface_width = 0;
|
||||
int surface_height = 0;
|
||||
|
||||
/* wl_surface.set_buffer_rotation */
|
||||
/* wl_surface.set_buffer_transform */
|
||||
surface->buffer_transform = surface->pending.buffer_transform;
|
||||
|
||||
/* wl_surface.set_buffer_scale */
|
||||
surface->buffer_scale = surface->pending.buffer_scale;
|
||||
|
||||
/* wl_surface.attach */
|
||||
if (surface->pending.buffer || surface->pending.newly_attached)
|
||||
weston_surface_attach(surface, surface->pending.buffer);
|
||||
|
||||
if (surface->buffer_ref.buffer) {
|
||||
buffer_width = weston_surface_buffer_width(surface);
|
||||
buffer_height = weston_surface_buffer_height(surface);
|
||||
surface_width = weston_surface_buffer_width(surface);
|
||||
surface_height = weston_surface_buffer_height(surface);
|
||||
}
|
||||
|
||||
if (surface->configure && surface->pending.newly_attached)
|
||||
surface->configure(surface,
|
||||
surface->pending.sx, surface->pending.sy,
|
||||
buffer_width, buffer_height);
|
||||
surface_width, surface_height);
|
||||
|
||||
if (surface->pending.buffer)
|
||||
wl_list_remove(&surface->pending.buffer_destroy_listener.link);
|
||||
@ -1588,6 +1627,16 @@ surface_set_buffer_transform(struct wl_client *client,
|
||||
surface->pending.buffer_transform = transform;
|
||||
}
|
||||
|
||||
static void
|
||||
surface_set_buffer_scale(struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
uint32_t scale)
|
||||
{
|
||||
struct weston_surface *surface = resource->data;
|
||||
|
||||
surface->pending.buffer_scale = scale;
|
||||
}
|
||||
|
||||
static const struct wl_surface_interface surface_interface = {
|
||||
surface_destroy,
|
||||
surface_attach,
|
||||
@ -1596,7 +1645,8 @@ static const struct wl_surface_interface surface_interface = {
|
||||
surface_set_opaque_region,
|
||||
surface_set_input_region,
|
||||
surface_commit,
|
||||
surface_set_buffer_transform
|
||||
surface_set_buffer_transform,
|
||||
surface_set_buffer_scale
|
||||
};
|
||||
|
||||
static void
|
||||
@ -1702,25 +1752,28 @@ weston_subsurface_commit_from_cache(struct weston_subsurface *sub)
|
||||
{
|
||||
struct weston_surface *surface = sub->surface;
|
||||
pixman_region32_t opaque;
|
||||
int buffer_width = 0;
|
||||
int buffer_height = 0;
|
||||
int surface_width = 0;
|
||||
int surface_height = 0;
|
||||
|
||||
/* wl_surface.set_buffer_rotation */
|
||||
/* wl_surface.set_buffer_transform */
|
||||
surface->buffer_transform = sub->cached.buffer_transform;
|
||||
|
||||
/* wl_surface.set_buffer_scale */
|
||||
surface->buffer_scale = sub->cached.buffer_scale;
|
||||
|
||||
/* wl_surface.attach */
|
||||
if (sub->cached.buffer_ref.buffer || sub->cached.newly_attached)
|
||||
weston_surface_attach(surface, sub->cached.buffer_ref.buffer);
|
||||
weston_buffer_reference(&sub->cached.buffer_ref, NULL);
|
||||
|
||||
if (surface->buffer_ref.buffer) {
|
||||
buffer_width = weston_surface_buffer_width(surface);
|
||||
buffer_height = weston_surface_buffer_height(surface);
|
||||
surface_width = weston_surface_buffer_width(surface);
|
||||
surface_height = weston_surface_buffer_height(surface);
|
||||
}
|
||||
|
||||
if (surface->configure && sub->cached.newly_attached)
|
||||
surface->configure(surface, sub->cached.sx, sub->cached.sy,
|
||||
buffer_width, buffer_height);
|
||||
surface_width, surface_height);
|
||||
sub->cached.sx = 0;
|
||||
sub->cached.sy = 0;
|
||||
sub->cached.newly_attached = 0;
|
||||
@ -1797,6 +1850,7 @@ weston_subsurface_commit_to_cache(struct weston_subsurface *sub)
|
||||
surface->pending.newly_attached = 0;
|
||||
|
||||
sub->cached.buffer_transform = surface->pending.buffer_transform;
|
||||
sub->cached.buffer_scale = surface->pending.buffer_scale;
|
||||
|
||||
pixman_region32_copy(&sub->cached.opaque, &surface->pending.opaque);
|
||||
|
||||
@ -2466,6 +2520,9 @@ bind_output(struct wl_client *client,
|
||||
output->subpixel,
|
||||
output->make, output->model,
|
||||
output->transform);
|
||||
if (version >= 2)
|
||||
wl_output_send_scale(resource,
|
||||
output->scale);
|
||||
|
||||
wl_list_for_each (mode, &output->mode_list, link) {
|
||||
wl_output_send_mode(resource,
|
||||
@ -2474,6 +2531,9 @@ bind_output(struct wl_client *client,
|
||||
mode->height,
|
||||
mode->refresh);
|
||||
}
|
||||
|
||||
if (version >= 2)
|
||||
wl_output_send_done(resource);
|
||||
}
|
||||
|
||||
WL_EXPORT void
|
||||
@ -2608,6 +2668,12 @@ weston_output_transform_init(struct weston_output *output, uint32_t transform)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
weston_output_scale_init(struct weston_output *output, uint32_t scale)
|
||||
{
|
||||
output->scale = scale;
|
||||
}
|
||||
|
||||
WL_EXPORT void
|
||||
weston_output_move(struct weston_output *output, int x, int y)
|
||||
{
|
||||
@ -2622,7 +2688,8 @@ weston_output_move(struct weston_output *output, int x, int y)
|
||||
|
||||
WL_EXPORT void
|
||||
weston_output_init(struct weston_output *output, struct weston_compositor *c,
|
||||
int x, int y, int width, int height, uint32_t transform)
|
||||
int x, int y, int width, int height, uint32_t transform,
|
||||
uint32_t scale)
|
||||
{
|
||||
output->compositor = c;
|
||||
output->x = x;
|
||||
@ -2636,6 +2703,7 @@ weston_output_init(struct weston_output *output, struct weston_compositor *c,
|
||||
output->dirty = 1;
|
||||
|
||||
weston_output_transform_init(output, transform);
|
||||
weston_output_scale_init(output, scale);
|
||||
weston_output_init_zoom(output);
|
||||
|
||||
weston_output_move(output, x, y);
|
||||
|
@ -183,7 +183,8 @@ struct weston_output {
|
||||
char *make, *model, *serial_number;
|
||||
uint32_t subpixel;
|
||||
uint32_t transform;
|
||||
|
||||
uint32_t scale;
|
||||
|
||||
struct weston_mode *current;
|
||||
struct weston_mode *origin;
|
||||
struct wl_list mode_list;
|
||||
@ -601,6 +602,9 @@ struct weston_subsurface {
|
||||
|
||||
/* wl_surface.set_buffer_transform */
|
||||
uint32_t buffer_transform;
|
||||
|
||||
/* wl_surface.set_buffer_scale */
|
||||
uint32_t buffer_scale;
|
||||
} cached;
|
||||
|
||||
int synchronized;
|
||||
@ -704,6 +708,7 @@ struct weston_surface {
|
||||
|
||||
struct weston_buffer_reference buffer_ref;
|
||||
uint32_t buffer_transform;
|
||||
uint32_t buffer_scale;
|
||||
int keep_buffer; /* bool for backends to prevent early release */
|
||||
|
||||
/* All the pending state, that wl_surface.commit will apply. */
|
||||
@ -729,6 +734,9 @@ struct weston_surface {
|
||||
|
||||
/* wl_surface.set_buffer_transform */
|
||||
uint32_t buffer_transform;
|
||||
|
||||
/* wl_surface.set_scaling_factor */
|
||||
uint32_t buffer_scale;
|
||||
} pending;
|
||||
|
||||
/*
|
||||
@ -787,6 +795,10 @@ weston_surface_buffer_height(struct weston_surface *surface);
|
||||
WL_EXPORT void
|
||||
weston_surface_to_buffer_float(struct weston_surface *surface,
|
||||
float x, float y, float *bx, float *by);
|
||||
WL_EXPORT void
|
||||
weston_surface_to_buffer(struct weston_surface *surface,
|
||||
int sx, int sy, int *bx, int *by);
|
||||
|
||||
pixman_box32_t
|
||||
weston_surface_to_buffer_rect(struct weston_surface *surface,
|
||||
pixman_box32_t rect);
|
||||
@ -1005,7 +1017,7 @@ void
|
||||
weston_output_move(struct weston_output *output, int x, int y);
|
||||
void
|
||||
weston_output_init(struct weston_output *output, struct weston_compositor *c,
|
||||
int x, int y, int width, int height, uint32_t transform);
|
||||
int x, int y, int width, int height, uint32_t transform, uint32_t scale);
|
||||
void
|
||||
weston_output_destroy(struct weston_output *output);
|
||||
|
||||
@ -1136,10 +1148,12 @@ module_init(struct weston_compositor *compositor,
|
||||
void
|
||||
weston_transformed_coord(int width, int height,
|
||||
enum wl_output_transform transform,
|
||||
uint32_t scale,
|
||||
float sx, float sy, float *bx, float *by);
|
||||
pixman_box32_t
|
||||
weston_transformed_rect(int width, int height,
|
||||
enum wl_output_transform transform,
|
||||
uint32_t scale,
|
||||
pixman_box32_t rect);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -68,6 +68,7 @@ struct gl_surface_state {
|
||||
|
||||
struct weston_buffer_reference buffer_ref;
|
||||
int pitch; /* in pixels */
|
||||
int height; /* in pixels */
|
||||
};
|
||||
|
||||
struct gl_renderer {
|
||||
@ -552,17 +553,7 @@ texture_region(struct weston_surface *es, pixman_region32_t *region,
|
||||
vtxcnt = wl_array_add(&gr->vtxcnt, nrects * nsurf * sizeof *vtxcnt);
|
||||
|
||||
inv_width = 1.0 / gs->pitch;
|
||||
|
||||
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:
|
||||
inv_height = 1.0 / es->geometry.width;
|
||||
break;
|
||||
default:
|
||||
inv_height = 1.0 / es->geometry.height;
|
||||
}
|
||||
inv_height = 1.0 / gs->height;
|
||||
|
||||
for (i = 0; i < nrects; i++) {
|
||||
pixman_box32_t *rect = &rects[i];
|
||||
@ -791,7 +782,7 @@ draw_surface(struct weston_surface *es, struct weston_output *output,
|
||||
use_shader(gr, gs->shader);
|
||||
shader_uniforms(gs->shader, es, output);
|
||||
|
||||
if (es->transform.enabled || output->zoom.active)
|
||||
if (es->transform.enabled || output->zoom.active || output->scale != es->buffer_scale)
|
||||
filter = GL_LINEAR;
|
||||
else
|
||||
filter = GL_NEAREST;
|
||||
@ -1023,9 +1014,9 @@ gl_renderer_repaint_output(struct weston_output *output,
|
||||
int32_t width, height;
|
||||
pixman_region32_t buffer_damage, total_damage;
|
||||
|
||||
width = output->current->width +
|
||||
width = output->current->width * output->scale +
|
||||
output->border.left + output->border.right;
|
||||
height = output->current->height +
|
||||
height = output->current->height * output->scale +
|
||||
output->border.top + output->border.bottom;
|
||||
|
||||
glViewport(0, 0, width, height);
|
||||
@ -1214,6 +1205,7 @@ gl_renderer_attach(struct weston_surface *es, struct wl_buffer *buffer)
|
||||
|
||||
if (wl_buffer_is_shm(buffer)) {
|
||||
gs->pitch = wl_shm_buffer_get_stride(buffer) / 4;
|
||||
gs->height = wl_shm_buffer_get_height(buffer);
|
||||
gs->target = GL_TEXTURE_2D;
|
||||
|
||||
ensure_textures(gs, 1);
|
||||
@ -1279,6 +1271,7 @@ gl_renderer_attach(struct weston_surface *es, struct wl_buffer *buffer)
|
||||
}
|
||||
|
||||
gs->pitch = buffer->width;
|
||||
gs->height = buffer->height;
|
||||
} else {
|
||||
weston_log("unhandled buffer type!\n");
|
||||
weston_buffer_reference(&gs->buffer_ref, NULL);
|
||||
|
@ -104,6 +104,36 @@ pixman_renderer_read_pixels(struct weston_output *output,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
box_scale(pixman_box32_t *dst, int scale)
|
||||
{
|
||||
dst->x1 *= scale;
|
||||
dst->x2 *= scale;
|
||||
dst->y1 *= scale;
|
||||
dst->y2 *= scale;
|
||||
}
|
||||
|
||||
static void
|
||||
scale_region (pixman_region32_t *region, int scale)
|
||||
{
|
||||
pixman_box32_t *rects, *scaled_rects;
|
||||
int nrects, i;
|
||||
|
||||
if (scale != 1) {
|
||||
rects = pixman_region32_rectangles(region, &nrects);
|
||||
scaled_rects = calloc(nrects, sizeof(pixman_box32_t));
|
||||
|
||||
for (i = 0; i < nrects; i++) {
|
||||
scaled_rects[i] = rects[i];
|
||||
box_scale(&scaled_rects[i], scale);
|
||||
}
|
||||
pixman_region32_clear(region);
|
||||
|
||||
pixman_region32_init_rects (region, scaled_rects, nrects);
|
||||
free (scaled_rects);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
transform_region (pixman_region32_t *region, int width, int height, enum wl_output_transform transform)
|
||||
{
|
||||
@ -180,6 +210,7 @@ region_global_to_output(struct weston_output *output, pixman_region32_t *region)
|
||||
{
|
||||
pixman_region32_translate(region, -output->x, -output->y);
|
||||
transform_region (region, output->width, output->height, output->transform);
|
||||
scale_region (region, output->scale);
|
||||
}
|
||||
|
||||
#define D2F(v) pixman_double_to_fixed((double)v)
|
||||
@ -229,9 +260,12 @@ repaint_region(struct weston_surface *es, struct weston_output *output,
|
||||
pixman_image_set_clip_region32 (po->shadow_image, &final_region);
|
||||
|
||||
/* Set up the source transformation based on the surface
|
||||
position, the output position/transform and the client
|
||||
specified buffer transform */
|
||||
position, the output position/transform/scale and the client
|
||||
specified buffer transform/scale */
|
||||
pixman_transform_init_identity(&transform);
|
||||
pixman_transform_scale(&transform, NULL,
|
||||
pixman_double_to_fixed ((double)1.0/output->scale),
|
||||
pixman_double_to_fixed ((double)1.0/output->scale));
|
||||
|
||||
fw = pixman_int_to_fixed(output->width);
|
||||
fh = pixman_int_to_fixed(output->height);
|
||||
@ -338,9 +372,13 @@ repaint_region(struct weston_surface *es, struct weston_output *output,
|
||||
break;
|
||||
}
|
||||
|
||||
pixman_transform_scale(&transform, NULL,
|
||||
pixman_double_to_fixed ((double)es->buffer_scale),
|
||||
pixman_double_to_fixed ((double)es->buffer_scale));
|
||||
|
||||
pixman_image_set_transform(ps->image, &transform);
|
||||
|
||||
if (es->transform.enabled)
|
||||
if (es->transform.enabled || output->scale != es->buffer_scale)
|
||||
pixman_image_set_filter(ps->image, PIXMAN_FILTER_BILINEAR, NULL, 0);
|
||||
else
|
||||
pixman_image_set_filter(ps->image, PIXMAN_FILTER_NEAREST, NULL, 0);
|
||||
@ -651,8 +689,8 @@ pixman_renderer_output_create(struct weston_output *output)
|
||||
return -1;
|
||||
|
||||
/* set shadow image transformation */
|
||||
w = output->current->width;
|
||||
h = output->current->height;
|
||||
w = output->current->width * output->scale;
|
||||
h = output->current->height * output->scale;
|
||||
|
||||
po->shadow_buffer = malloc(w * h * 4);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user