[PATCH weston 7/8] compositor-drm: Implement clone mode, refactor output into logical ones
Emmanuel Gil Peyrot
emmanuel.peyrot at collabora.com
Mon May 2 21:40:16 UTC 2016
Introduces a “same-as” configuration option for each output, which
bypasses the rest of the output configuration (mode, scale, transform
and seat) and instead makes it a clone of the specified output.
This is implemented by splitting the drm_output struct into the
per-connector drm_output and the per-weston_output drm_logical_output,
with the latter containing one or more of the former in a wl_list.
I tested it on both i915 and etnaviv platforms, with various external
monitors and configurations, as well as hotplugging.
Signed-off-by: Emmanuel Gil Peyrot <emmanuel.peyrot at collabora.com>
---
src/compositor-drm.c | 794 +++++++++++++++++++++++++++++++--------------------
1 file changed, 477 insertions(+), 317 deletions(-)
diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 1edcaab..a0ed45f 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -157,8 +157,12 @@ struct drm_edid {
char serial_number[13];
};
+struct drm_logical_output;
+
struct drm_output {
- struct weston_output base;
+ struct wl_list link;
+ struct drm_logical_output *base;
+ char *name;
uint32_t crtc_id;
int pipe;
@@ -166,13 +170,21 @@ struct drm_output {
drmModeCrtcPtr original_crtc;
struct drm_edid edid;
drmModePropertyPtr dpms_prop;
- uint32_t gbm_format;
- enum dpms_enum dpms;
+ struct backlight *backlight;
int vblank_pending;
int page_flip_pending;
int destroy_pending;
+};
+
+struct drm_logical_output {
+ struct weston_output base;
+ struct wl_list output_list;
+
+ int page_flip_refcount;
+ uint32_t gbm_format;
+ enum dpms_enum dpms;
struct gbm_surface *gbm_surface;
struct gbm_bo *gbm_cursor_bo[2];
@@ -181,7 +193,6 @@ struct drm_output {
struct weston_view *cursor_view;
int current_cursor;
struct drm_fb *current, *next;
- struct backlight *backlight;
struct drm_fb *dumb[2];
pixman_image_t *image[2];
@@ -229,7 +240,7 @@ static struct gl_renderer_interface *gl_renderer;
static const char default_seat[] = "seat0";
static void
-drm_output_set_cursor(struct drm_output *output);
+drm_output_set_cursor(struct drm_logical_output *output);
static void
drm_output_update_msc(struct weston_output *output_base, unsigned int seq);
@@ -237,7 +248,7 @@ drm_output_update_msc(struct weston_output *output_base, unsigned int seq);
static int
drm_sprite_crtc_supported(struct drm_output *output, uint32_t supported)
{
- struct weston_compositor *ec = output->base.compositor;
+ struct weston_compositor *ec = output->base->base.compositor;
struct drm_backend *b =(struct drm_backend *)ec->backend;
int crtc;
@@ -423,7 +434,7 @@ drm_fb_set_buffer(struct drm_fb *fb, struct weston_buffer *buffer)
}
static void
-drm_output_release_fb(struct drm_output *output, struct drm_fb *fb)
+drm_output_release_fb(struct drm_logical_output *output, struct drm_fb *fb)
{
if (!fb)
return;
@@ -441,7 +452,7 @@ drm_output_release_fb(struct drm_output *output, struct drm_fb *fb)
}
static uint32_t
-drm_output_check_scanout_format(struct drm_output *output,
+drm_output_check_scanout_format(struct drm_logical_output *output,
struct weston_surface *es, struct gbm_bo *bo)
{
uint32_t format;
@@ -471,7 +482,7 @@ drm_output_check_scanout_format(struct drm_output *output,
}
static struct weston_plane *
-drm_output_prepare_scanout_view(struct drm_output *output,
+drm_output_prepare_scanout_view(struct drm_logical_output *output,
struct weston_view *ev)
{
struct weston_output *output_base = &output->base;
@@ -519,7 +530,8 @@ drm_output_prepare_scanout_view(struct drm_output *output,
}
static void
-drm_output_render_gl(struct drm_output *output, pixman_region32_t *damage)
+drm_output_render_gl(struct drm_logical_output *output,
+ pixman_region32_t *damage)
{
struct drm_backend *b =
(struct drm_backend *)output->base.compositor->backend;
@@ -543,7 +555,8 @@ drm_output_render_gl(struct drm_output *output, pixman_region32_t *damage)
}
static void
-drm_output_render_pixman(struct drm_output *output, pixman_region32_t *damage)
+drm_output_render_pixman(struct drm_logical_output *output,
+ pixman_region32_t *damage)
{
struct weston_compositor *ec = output->base.compositor;
pixman_region32_t total_damage, previous_damage;
@@ -569,7 +582,7 @@ drm_output_render_pixman(struct drm_output *output, pixman_region32_t *damage)
}
static void
-drm_output_render(struct drm_output *output, pixman_region32_t *damage)
+drm_output_render(struct drm_logical_output *output, pixman_region32_t *damage)
{
struct weston_compositor *c = output->base.compositor;
struct drm_backend *b = (struct drm_backend *)c->backend;
@@ -634,98 +647,117 @@ static int
drm_output_repaint(struct weston_output *output_base,
pixman_region32_t *damage)
{
- struct drm_output *output = (struct drm_output *) output_base;
+ struct drm_logical_output *logical_output =
+ (struct drm_logical_output *)output_base;
+ struct drm_output *output;
struct drm_backend *backend =
(struct drm_backend *)output_base->compositor->backend;
struct drm_sprite *s;
struct drm_mode *mode;
int ret = 0;
- if (output->destroy_pending)
- return -1;
+ wl_list_for_each(output, &logical_output->output_list, link) {
+ if (output->destroy_pending)
+ return -1;
+ }
- if (!output->next)
- drm_output_render(output, damage);
- if (!output->next)
+ if (!logical_output->next)
+ drm_output_render(logical_output, damage);
+ if (!logical_output->next)
return -1;
mode = container_of(output_base->current_mode, struct drm_mode, base);
- if (!output->current ||
- output->current->stride != output->next->stride) {
- ret = drmModeSetCrtc(backend->drm.fd, output->crtc_id,
- output->next->fb_id, 0, 0,
- &output->connector_id, 1,
- &mode->mode_info);
- if (ret) {
- weston_log("set mode failed: %m\n");
- goto err_pageflip;
+ if (!logical_output->current ||
+ logical_output->current->stride != logical_output->next->stride) {
+ wl_list_for_each(output, &logical_output->output_list, link) {
+ ret = drmModeSetCrtc(backend->drm.fd, output->crtc_id,
+ logical_output->next->fb_id, 0, 0,
+ &output->connector_id, 1,
+ &mode->mode_info);
+ if (ret) {
+ weston_log("set mode failed: %m\n");
+ goto err_pageflip;
+ }
}
output_base->set_dpms(output_base, WESTON_DPMS_ON);
}
- if (drmModePageFlip(backend->drm.fd, output->crtc_id,
- output->next->fb_id,
- DRM_MODE_PAGE_FLIP_EVENT, output) < 0) {
- weston_log("queueing pageflip failed: %m\n");
- goto err_pageflip;
- }
+ wl_list_for_each(output, &logical_output->output_list, link) {
+ if (output->page_flip_pending)
+ continue;
+ if (drmModePageFlip(backend->drm.fd, output->crtc_id,
+ logical_output->next->fb_id,
+ DRM_MODE_PAGE_FLIP_EVENT, output) < 0) {
+ weston_log("queueing pageflip failed: %m\n");
+ goto err_pageflip;
+ }
- output->page_flip_pending = 1;
+ output->page_flip_pending = 1;
+ ++logical_output->page_flip_refcount;
+ }
if (!backend->cursors_are_broken)
- drm_output_set_cursor(output);
+ drm_output_set_cursor(logical_output);
- /*
- * Now, update all the sprite surfaces
- */
- wl_list_for_each(s, &backend->sprite_list, link) {
- uint32_t flags = 0, fb_id = 0;
- drmVBlank vbl = {
- .request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT,
- .request.sequence = 1,
- };
+ /* Sprite support is disabled on clone mode for now. */
+ if (wl_list_length(&logical_output->output_list) == 1) {
+ /* Fetches the only output present from the list */
+ wl_list_for_each(output, &logical_output->output_list, link);
- if ((!s->current && !s->next) ||
- !drm_sprite_crtc_supported(output, s->possible_crtcs))
- continue;
+ /*
+ * Now, update all the sprite surfaces
+ */
+ wl_list_for_each(s, &backend->sprite_list, link) {
+ uint32_t flags = 0, fb_id = 0;
+ drmVBlank vbl = {
+ .request.type = DRM_VBLANK_RELATIVE |
+ DRM_VBLANK_EVENT,
+ .request.sequence = 1,
+ };
+
+ if ((!s->current && !s->next) ||
+ !drm_sprite_crtc_supported(output,
+ s->possible_crtcs))
+ continue;
- if (s->next && !backend->sprites_hidden)
- fb_id = s->next->fb_id;
+ if (s->next && !backend->sprites_hidden)
+ fb_id = s->next->fb_id;
- ret = drmModeSetPlane(backend->drm.fd, s->plane_id,
- output->crtc_id, fb_id, flags,
- s->dest_x, s->dest_y,
- s->dest_w, s->dest_h,
- s->src_x, s->src_y,
- s->src_w, s->src_h);
- if (ret)
- weston_log("setplane failed: %d: %s\n",
- ret, strerror(errno));
+ ret = drmModeSetPlane(backend->drm.fd, s->plane_id,
+ output->crtc_id, fb_id, flags,
+ s->dest_x, s->dest_y,
+ s->dest_w, s->dest_h,
+ s->src_x, s->src_y,
+ s->src_w, s->src_h);
+ if (ret)
+ weston_log("setplane failed: %d: %s\n",
+ ret, strerror(errno));
- vbl.request.type |= drm_waitvblank_pipe(output);
+ vbl.request.type |= drm_waitvblank_pipe(output);
- /*
- * Queue a vblank signal so we know when the surface
- * becomes active on the display or has been replaced.
- */
- vbl.request.signal = (unsigned long)s;
- ret = drmWaitVBlank(backend->drm.fd, &vbl);
- if (ret) {
- weston_log("vblank event request failed: %d: %s\n",
- ret, strerror(errno));
- }
+ /*
+ * Queue a vblank signal so we know when the surface
+ * becomes active on the display or has been replaced.
+ */
+ vbl.request.signal = (unsigned long)s;
+ ret = drmWaitVBlank(backend->drm.fd, &vbl);
+ if (ret) {
+ weston_log("vblank event request failed: %d:"
+ " %s\n", ret, strerror(errno));
+ }
- s->output = output;
- output->vblank_pending = 1;
+ s->output = output;
+ output->vblank_pending = 1;
+ }
}
return 0;
err_pageflip:
- output->cursor_view = NULL;
- if (output->next) {
- drm_output_release_fb(output, output->next);
- output->next = NULL;
+ logical_output->cursor_view = NULL;
+ if (logical_output->next) {
+ drm_output_release_fb(logical_output, logical_output->next);
+ logical_output->next = NULL;
}
return -1;
@@ -734,13 +766,16 @@ err_pageflip:
static void
drm_output_start_repaint_loop(struct weston_output *output_base)
{
- struct drm_output *output = (struct drm_output *) output_base;
+ struct drm_logical_output *logical_output =
+ (struct drm_logical_output *)output_base;
+ struct drm_output *output;
struct drm_backend *backend = (struct drm_backend *)
output_base->compositor->backend;
uint32_t fb_id;
struct timespec ts, tnow;
struct timespec vbl2now;
int64_t refresh_nsec;
+ long last_sec = 0, last_usec = 0;
int ret;
drmVBlank vbl = {
.request.type = DRM_VBLANK_RELATIVE,
@@ -748,20 +783,32 @@ drm_output_start_repaint_loop(struct weston_output *output_base)
.request.signal = 0,
};
- if (output->destroy_pending)
- return;
+ wl_list_for_each(output, &logical_output->output_list, link) {
+ if (output->destroy_pending)
+ return;
+ }
- if (!output->current) {
+ if (!logical_output->current) {
/* We can't page flip if there's no mode set */
goto finish_frame;
}
/* Try to get current msc and timestamp via instant query */
- vbl.request.type |= drm_waitvblank_pipe(output);
- ret = drmWaitVBlank(backend->drm.fd, &vbl);
+ wl_list_for_each(output, &logical_output->output_list, link) {
+ vbl.request.type |= drm_waitvblank_pipe(output);
+ ret = drmWaitVBlank(backend->drm.fd, &vbl);
+ if (ret != 0)
+ continue;
+ if (last_sec < vbl.reply.tval_sec ||
+ (last_sec == vbl.reply.tval_sec &&
+ last_usec < vbl.reply.tval_usec)) {
+ last_sec = vbl.reply.tval_sec;
+ last_usec = vbl.reply.tval_usec;
+ }
+ }
/* Error ret or zero timestamp means failure to get valid timestamp */
- if ((ret == 0) && (vbl.reply.tval_sec > 0 || vbl.reply.tval_usec > 0)) {
+ if (last_sec > 0 || last_usec > 0) {
ts.tv_sec = vbl.reply.tval_sec;
ts.tv_nsec = vbl.reply.tval_usec * 1000;
@@ -785,12 +832,15 @@ drm_output_start_repaint_loop(struct weston_output *output_base)
/* Immediate query didn't provide valid timestamp.
* Use pageflip fallback.
*/
- fb_id = output->current->fb_id;
+ fb_id = logical_output->current->fb_id;
- if (drmModePageFlip(backend->drm.fd, output->crtc_id, fb_id,
- DRM_MODE_PAGE_FLIP_EVENT, output) < 0) {
- weston_log("queueing pageflip failed: %m\n");
- goto finish_frame;
+ wl_list_for_each(output, &logical_output->output_list, link) {
+ if (drmModePageFlip(backend->drm.fd, output->crtc_id, fb_id,
+ DRM_MODE_PAGE_FLIP_EVENT, output) < 0) {
+ weston_log("queueing pageflip failed: %m\n");
+ goto finish_frame;
+ }
+ ++logical_output->page_flip_refcount;
}
return;
@@ -819,21 +869,22 @@ vblank_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec,
{
struct drm_sprite *s = (struct drm_sprite *)data;
struct drm_output *output = s->output;
+ struct drm_logical_output *logical_output = output->base;
struct timespec ts;
uint32_t flags = WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION |
WP_PRESENTATION_FEEDBACK_KIND_HW_CLOCK;
- drm_output_update_msc(&output->base, frame);
+ drm_output_update_msc(&logical_output->base, frame);
output->vblank_pending = 0;
- drm_output_release_fb(output, s->current);
+ drm_output_release_fb(logical_output, s->current);
s->current = s->next;
s->next = NULL;
if (!output->page_flip_pending) {
ts.tv_sec = sec;
ts.tv_nsec = usec * 1000;
- weston_output_finish_frame(&output->base, &ts, flags);
+ weston_output_finish_frame(&logical_output->base, &ts, flags);
}
}
@@ -845,35 +896,37 @@ page_flip_handler(int fd, unsigned int frame,
unsigned int sec, unsigned int usec, void *data)
{
struct drm_output *output = (struct drm_output *) data;
+ struct drm_logical_output *logical_output = output->base;
struct timespec ts;
uint32_t flags = WP_PRESENTATION_FEEDBACK_KIND_VSYNC |
WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION |
WP_PRESENTATION_FEEDBACK_KIND_HW_CLOCK;
- drm_output_update_msc(&output->base, frame);
+ drm_output_update_msc(&logical_output->base, frame);
/* We don't set page_flip_pending on start_repaint_loop, in that case
* we just want to page flip to the current buffer to get an accurate
* timestamp */
- if (output->page_flip_pending) {
- drm_output_release_fb(output, output->current);
- output->current = output->next;
- output->next = NULL;
+ if (output->page_flip_pending &&
+ --logical_output->page_flip_refcount == 0) {
+ drm_output_release_fb(logical_output, logical_output->current);
+ logical_output->current = logical_output->next;
+ logical_output->next = NULL;
}
output->page_flip_pending = 0;
if (output->destroy_pending)
- drm_output_destroy(&output->base);
+ drm_output_destroy(&logical_output->base);
else if (!output->vblank_pending) {
ts.tv_sec = sec;
ts.tv_nsec = usec * 1000;
- weston_output_finish_frame(&output->base, &ts, flags);
+ weston_output_finish_frame(&logical_output->base, &ts, flags);
/* We can't call this from frame_notify, because the output's
* repaint needed flag is cleared just after that */
- if (output->recorder)
- weston_output_schedule_repaint(&output->base);
+ if (logical_output->recorder)
+ weston_output_schedule_repaint(&logical_output->base);
}
}
@@ -914,14 +967,15 @@ drm_view_transform_supported(struct weston_view *ev)
}
static struct weston_plane *
-drm_output_prepare_overlay_view(struct drm_output *output,
+drm_output_prepare_overlay_view(struct drm_logical_output *logical_output,
struct weston_view *ev)
{
- struct weston_output *output_base = &output->base;
+ struct weston_output *output_base = &logical_output->base;
struct weston_compositor *ec = output_base->compositor;
struct drm_backend *b = (struct drm_backend *)ec->backend;
struct weston_buffer_viewport *viewport = &ev->surface->buffer_viewport;
struct wl_resource *buffer_resource;
+ struct drm_output *output;
struct drm_sprite *s;
struct linux_dmabuf_buffer *dmabuf;
int found = 0;
@@ -959,8 +1013,14 @@ drm_output_prepare_overlay_view(struct drm_output *output,
if (!drm_view_transform_supported(ev))
return NULL;
+ if (wl_list_length(&logical_output->output_list) != 1)
+ return NULL;
+ /* Fetches the only output present from the list */
+ wl_list_for_each(output, &logical_output->output_list, link);
+
wl_list_for_each(s, &b->sprite_list, link) {
- if (!drm_sprite_crtc_supported(output, s->possible_crtcs))
+ if (!drm_sprite_crtc_supported(output,
+ s->possible_crtcs))
continue;
if (!s->next) {
@@ -1088,7 +1148,7 @@ drm_output_prepare_overlay_view(struct drm_output *output,
}
static struct weston_plane *
-drm_output_prepare_cursor_view(struct drm_output *output,
+drm_output_prepare_cursor_view(struct drm_logical_output *output,
struct weston_view *ev)
{
struct drm_backend *b =
@@ -1167,39 +1227,46 @@ cursor_bo_update(struct drm_backend *b, struct gbm_bo *bo,
}
static void
-drm_output_set_cursor(struct drm_output *output)
+drm_output_set_cursor(struct drm_logical_output *logical_output)
{
- struct weston_view *ev = output->cursor_view;
+ struct drm_output *output;
+ struct weston_plane *cursor_plane = &logical_output->cursor_plane;
+ struct weston_view *ev = logical_output->cursor_view;
struct weston_buffer *buffer;
struct drm_backend *b =
- (struct drm_backend *) output->base.compositor->backend;
+ (struct drm_backend *) logical_output->base.compositor->backend;
EGLint handle;
struct gbm_bo *bo;
float x, y;
- output->cursor_view = NULL;
+ logical_output->cursor_view = NULL;
if (ev == NULL) {
- drmModeSetCursor(b->drm.fd, output->crtc_id, 0, 0, 0);
- output->cursor_plane.x = INT32_MIN;
- output->cursor_plane.y = INT32_MIN;
+ wl_list_for_each(output, &logical_output->output_list, link)
+ drmModeSetCursor(b->drm.fd, output->crtc_id, 0, 0, 0);
+ cursor_plane->x = INT32_MIN;
+ cursor_plane->y = INT32_MIN;
return;
}
buffer = ev->surface->buffer_ref.buffer;
if (buffer &&
- pixman_region32_not_empty(&output->cursor_plane.damage)) {
- pixman_region32_fini(&output->cursor_plane.damage);
- pixman_region32_init(&output->cursor_plane.damage);
- output->current_cursor ^= 1;
- bo = output->gbm_cursor_bo[output->current_cursor];
+ pixman_region32_not_empty(&cursor_plane->damage)) {
+ pixman_region32_fini(&cursor_plane->damage);
+ pixman_region32_init(&cursor_plane->damage);
+ logical_output->current_cursor ^= 1;
+ bo = logical_output->gbm_cursor_bo[
+ logical_output->current_cursor];
cursor_bo_update(b, bo, ev);
handle = gbm_bo_get_handle(bo).s32;
- if (drmModeSetCursor(b->drm.fd, output->crtc_id, handle,
- b->cursor_width, b->cursor_height)) {
- weston_log("failed to set cursor: %m\n");
- b->cursors_are_broken = 1;
+ wl_list_for_each(output, &logical_output->output_list, link) {
+ if (drmModeSetCursor(b->drm.fd, output->crtc_id, handle,
+ b->cursor_width,
+ b->cursor_height)) {
+ weston_log("failed to set cursor: %m\n");
+ b->cursors_are_broken = 1;
+ }
}
}
@@ -1208,17 +1275,20 @@ drm_output_set_cursor(struct drm_output *output)
/* From global to output space, output transform is guaranteed to be
* NORMAL by drm_output_prepare_cursor_view().
*/
- x = (x - output->base.x) * output->base.current_scale;
- y = (y - output->base.y) * output->base.current_scale;
-
- if (output->cursor_plane.x != x || output->cursor_plane.y != y) {
- if (drmModeMoveCursor(b->drm.fd, output->crtc_id, x, y)) {
- weston_log("failed to move cursor: %m\n");
- b->cursors_are_broken = 1;
+ x = (x - logical_output->base.x) * logical_output->base.current_scale;
+ y = (y - logical_output->base.y) * logical_output->base.current_scale;
+
+ if (cursor_plane->x != x || cursor_plane->y != y) {
+ wl_list_for_each(output, &logical_output->output_list, link) {
+ if (drmModeMoveCursor(b->drm.fd, output->crtc_id,
+ x, y)) {
+ weston_log("failed to move cursor: %m\n");
+ b->cursors_are_broken = 1;
+ }
}
- output->cursor_plane.x = x;
- output->cursor_plane.y = y;
+ cursor_plane->x = x;
+ cursor_plane->y = y;
}
}
@@ -1227,7 +1297,8 @@ drm_assign_planes(struct weston_output *output_base)
{
struct drm_backend *b =
(struct drm_backend *)output_base->compositor->backend;
- struct drm_output *output = (struct drm_output *)output_base;
+ struct drm_logical_output *output =
+ (struct drm_logical_output *)output_base;
struct weston_view *ev, *next;
pixman_region32_t overlap, surface_overlap;
struct weston_plane *primary, *next_plane;
@@ -1307,52 +1378,58 @@ drm_assign_planes(struct weston_output *output_base)
}
static void
-drm_output_fini_pixman(struct drm_output *output);
+drm_output_fini_pixman(struct drm_logical_output *output);
static void
drm_output_destroy(struct weston_output *output_base)
{
- struct drm_output *output = (struct drm_output *) output_base;
+ struct drm_logical_output *logical_output =
+ (struct drm_logical_output *)output_base;
+ struct drm_output *output;
struct drm_backend *b =
(struct drm_backend *)output_base->compositor->backend;
- drmModeCrtcPtr origcrtc = output->original_crtc;
+ drmModeCrtcPtr origcrtc;
- if (output->page_flip_pending) {
- output->destroy_pending = 1;
- weston_log("destroy output while page flip pending\n");
- return;
- }
+ wl_list_for_each(output, &logical_output->output_list, link) {
+ if (output->page_flip_pending) {
+ output->destroy_pending = 1;
+ weston_log("destroy output while page flip pending\n");
+ return;
+ }
- if (output->backlight)
- backlight_destroy(output->backlight);
+ if (output->backlight)
+ backlight_destroy(output->backlight);
- drmModeFreeProperty(output->dpms_prop);
+ drmModeFreeProperty(output->dpms_prop);
- /* Turn off hardware cursor */
- drmModeSetCursor(b->drm.fd, output->crtc_id, 0, 0, 0);
+ /* Turn off hardware cursor */
+ drmModeSetCursor(b->drm.fd, output->crtc_id, 0, 0, 0);
- /* Restore original CRTC state */
- drmModeSetCrtc(b->drm.fd, origcrtc->crtc_id, origcrtc->buffer_id,
- origcrtc->x, origcrtc->y,
- &output->connector_id, 1, &origcrtc->mode);
- drmModeFreeCrtc(origcrtc);
+ /* Restore original CRTC state */
+ origcrtc = output->original_crtc;
+ drmModeSetCrtc(b->drm.fd, origcrtc->crtc_id,
+ origcrtc->buffer_id,
+ origcrtc->x, origcrtc->y,
+ &output->connector_id, 1, &origcrtc->mode);
+ drmModeFreeCrtc(origcrtc);
- b->crtc_allocator &= ~(1 << output->crtc_id);
- b->connector_allocator &= ~(1 << output->connector_id);
+ b->crtc_allocator &= ~(1 << output->crtc_id);
+ b->connector_allocator &= ~(1 << output->connector_id);
+ }
if (b->use_pixman) {
- drm_output_fini_pixman(output);
+ drm_output_fini_pixman(logical_output);
} else {
gl_renderer->output_destroy(output_base);
- gbm_surface_destroy(output->gbm_surface);
+ gbm_surface_destroy(logical_output->gbm_surface);
}
- weston_plane_release(&output->fb_plane);
- weston_plane_release(&output->cursor_plane);
+ weston_plane_release(&logical_output->fb_plane);
+ weston_plane_release(&logical_output->cursor_plane);
- weston_output_destroy(&output->base);
+ weston_output_destroy(output_base);
- free(output);
+ free(logical_output);
}
/**
@@ -1367,7 +1444,7 @@ drm_output_destroy(struct weston_output *output_base)
* @returns Pointer to a mode from the output's mode list
*/
static struct drm_mode *
-choose_mode (struct weston_output *output_base, struct weston_mode *target_mode)
+choose_mode(struct weston_output *output_base, struct weston_mode *target_mode)
{
struct drm_mode *tmp_mode = NULL, *mode;
@@ -1392,14 +1469,17 @@ choose_mode (struct weston_output *output_base, struct weston_mode *target_mode)
}
static int
-drm_output_init_egl(struct drm_output *output, struct drm_backend *b);
+drm_output_init_egl(struct drm_logical_output *output, struct drm_backend *b);
static int
-drm_output_init_pixman(struct drm_output *output, struct drm_backend *b);
+drm_output_init_pixman(struct drm_logical_output *output,
+ struct drm_backend *b);
static int
-drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mode)
+drm_output_switch_mode(struct weston_output *output_base,
+ struct weston_mode *mode)
{
- struct drm_output *output;
+ struct drm_logical_output *output =
+ (struct drm_logical_output *)output_base;
struct drm_mode *drm_mode;
struct drm_backend *b;
@@ -1414,8 +1494,7 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo
}
b = (struct drm_backend *)output_base->compositor->backend;
- output = (struct drm_output *)output_base;
- drm_mode = choose_mode(&output->base, mode);
+ drm_mode = choose_mode(output_base, mode);
if (!drm_mode) {
weston_log("%s, invalid resolution:%dx%d\n", __func__, mode->width, mode->height);
@@ -1444,7 +1523,7 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo
return -1;
}
} else {
- gl_renderer->output_destroy(&output->base);
+ gl_renderer->output_destroy(output_base);
gbm_surface_destroy(output->gbm_surface);
if (drm_output_init_egl(output, b) < 0) {
@@ -1704,21 +1783,25 @@ drm_get_backlight(struct drm_output *output)
static void
drm_set_backlight(struct weston_output *output_base, uint32_t value)
{
- struct drm_output *output = (struct drm_output *) output_base;
+ struct drm_logical_output *logical_output =
+ (struct drm_logical_output *)output_base;
+ struct drm_output *output;
long max_brightness, new_brightness;
- if (!output->backlight)
- return;
+ wl_list_for_each(output, &logical_output->output_list, link) {
+ if (!output->backlight)
+ return;
- if (value > 255)
- return;
+ if (value > 255)
+ return;
- max_brightness = backlight_get_max_brightness(output->backlight);
+ max_brightness = backlight_get_max_brightness(output->backlight);
- /* get denormalized value */
- new_brightness = (value * max_brightness) / 255;
+ /* get denormalized value */
+ new_brightness = (value * max_brightness) / 255;
- backlight_set_brightness(output->backlight, new_brightness);
+ backlight_set_brightness(output->backlight, new_brightness);
+ }
}
static drmModePropertyPtr
@@ -1744,23 +1827,28 @@ drm_get_prop(int fd, drmModeConnectorPtr connector, const char *name)
static void
drm_set_dpms(struct weston_output *output_base, enum dpms_enum level)
{
- struct drm_output *output = (struct drm_output *) output_base;
+ struct drm_logical_output *logical_output =
+ (struct drm_logical_output *)output_base;
struct weston_compositor *ec = output_base->compositor;
struct drm_backend *b = (struct drm_backend *)ec->backend;
+ struct drm_output *output;
int ret;
- if (!output->dpms_prop)
- return;
+ wl_list_for_each(output, &logical_output->output_list, link) {
+ if (!output->dpms_prop)
+ continue;
- ret = drmModeConnectorSetProperty(b->drm.fd, output->connector_id,
- output->dpms_prop->prop_id, level);
- if (ret) {
- weston_log("DRM: DPMS: failed property set for %s\n",
- output_base->name);
- return;
+ ret = drmModeConnectorSetProperty(b->drm.fd,
+ output->connector_id,
+ output->dpms_prop->prop_id,
+ level);
+ if (ret) {
+ weston_log("DRM: DPMS: failed property set for %s\n",
+ output->name);
+ continue;
+ }
}
-
- output->dpms = level;
+ logical_output->dpms = level;
}
static const char * const connector_type_names[] = {
@@ -1831,7 +1919,7 @@ find_crtc_for_connector(struct drm_backend *b,
/* Init output state that depends on gl or gbm */
static int
-drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
+drm_output_init_egl(struct drm_logical_output *output, struct drm_backend *b)
{
EGLint format[2] = {
output->gbm_format,
@@ -1883,7 +1971,8 @@ drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
}
static int
-drm_output_init_pixman(struct drm_output *output, struct drm_backend *b)
+drm_output_init_pixman(struct drm_logical_output *output,
+ struct drm_backend *b)
{
int w = output->base.current_mode->width;
int h = output->base.current_mode->height;
@@ -1927,7 +2016,7 @@ err:
}
static void
-drm_output_fini_pixman(struct drm_output *output)
+drm_output_fini_pixman(struct drm_logical_output *output)
{
unsigned int i;
@@ -2073,11 +2162,11 @@ find_and_parse_output_edid(struct drm_backend *b,
output->edid.monitor_name,
output->edid.serial_number);
if (output->edid.pnp_id[0] != '\0')
- output->base.make = output->edid.pnp_id;
+ output->base->base.make = output->edid.pnp_id;
if (output->edid.monitor_name[0] != '\0')
- output->base.model = output->edid.monitor_name;
+ output->base->base.model = output->edid.monitor_name;
if (output->edid.serial_number[0] != '\0')
- output->base.serial_number = output->edid.serial_number;
+ output->base->base.serial_number = output->edid.serial_number;
}
drmModeFreePropertyBlob(edid_blob);
}
@@ -2302,6 +2391,7 @@ create_output_for_connector(struct drm_backend *b,
drmModeConnector *connector,
int x, int y, struct udev_device *drm_device)
{
+ struct drm_logical_output *logical_output = NULL;
struct drm_output *output;
struct drm_mode *drm_mode, *next, *current;
struct weston_output *output_base;
@@ -2312,6 +2402,7 @@ create_output_for_connector(struct drm_backend *b,
char *s, *name;
enum output_config config;
uint32_t transform;
+ bool is_clone = false;
i = find_crtc_for_connector(b, resources, connector);
if (i < 0) {
@@ -2321,20 +2412,32 @@ create_output_for_connector(struct drm_backend *b,
name = make_connector_name(connector);
- output = zalloc(sizeof *output);
- if (output == NULL)
- return -1;
-
- output_base = &output->base;
- output_base->subpixel = drm_subpixel_to_wayland(connector->subpixel);
- output_base->name = name;
- output_base->make = "unknown";
- output_base->model = "unknown";
- output_base->serial_number = "unknown";
- wl_list_init(&output_base->mode_list);
-
section = weston_config_get_section(b->compositor->config, "output", "name",
name);
+
+ weston_config_section_get_string(section, "same-as", &s, "");
+ if (strcmp(s, "") != 0) {
+ struct drm_logical_output *temporary_logical_output = NULL;
+ wl_list_for_each(temporary_logical_output,
+ &b->compositor->output_list, base.link) {
+ if (strcmp(temporary_logical_output->base.name, s) == 0) {
+ logical_output = temporary_logical_output;
+ break;
+ }
+ }
+ if (logical_output == NULL)
+ return -1;
+ is_clone = true;
+ } else {
+ logical_output = zalloc(sizeof *logical_output);
+ if (logical_output == NULL)
+ return -1;
+ is_clone = false;
+ }
+ free(s);
+
+ output_base = &logical_output->base;
+
weston_config_section_get_string(section, "mode", &s, "preferred");
if (strcmp(s, "off") == 0)
config = OUTPUT_CONFIG_OFF;
@@ -2352,21 +2455,42 @@ create_output_for_connector(struct drm_backend *b,
}
free(s);
- weston_config_section_get_int(section, "scale", &scale, 1);
- weston_config_section_get_string(section, "transform", &s, "normal");
- if (weston_parse_transform(s, &transform) < 0)
- weston_log("Invalid transform \"%s\" for output %s\n", s, name);
+ if (!is_clone) {
+ output_base->subpixel =
+ drm_subpixel_to_wayland(connector->subpixel);
+ output_base->name = name;
+ output_base->make = "unknown";
+ output_base->model = "unknown";
+ output_base->serial_number = "unknown";
+ wl_list_init(&output_base->mode_list);
- free(s);
+ weston_config_section_get_int(section, "scale", &scale, 1);
+ weston_config_section_get_string(section, "transform", &s,
+ "normal");
+ if (weston_parse_transform(s, &transform) < 0)
+ weston_log("Invalid transform \"%s\" for output %s\n",
+ s, name);
- if (get_gbm_format_from_section(section,
- b->gbm_format,
- &output->gbm_format) == -1)
- output->gbm_format = b->gbm_format;
+ free(s);
- weston_config_section_get_string(section, "seat", &s, "");
- setup_output_seat_constraint(b, output_base, s);
- free(s);
+ if (get_gbm_format_from_section(section,
+ b->gbm_format,
+ &logical_output->gbm_format) == -1)
+ logical_output->gbm_format = b->gbm_format;
+
+ weston_config_section_get_string(section, "seat", &s, "");
+ setup_output_seat_constraint(b, output_base, s);
+ free(s);
+
+ wl_list_init(&logical_output->output_list);
+ }
+
+ output = zalloc(sizeof *output);
+ if (output == NULL)
+ return -1;
+
+ wl_list_insert(&logical_output->output_list, &output->link);
+ output->base = logical_output;
output->crtc_id = resources->crtcs[i];
output->pipe = i;
@@ -2377,15 +2501,6 @@ create_output_for_connector(struct drm_backend *b,
output->original_crtc = drmModeGetCrtc(b->drm.fd, output->crtc_id);
output->dpms_prop = drm_get_prop(b->drm.fd, connector, "DPMS");
- if (connector_get_current_mode(connector, b->drm.fd, &crtc_mode) < 0)
- goto err_free;
-
- for (i = 0; i < connector->count_modes; i++) {
- drm_mode = drm_output_add_mode(output_base, &connector->modes[i]);
- if (!drm_mode)
- goto err_free;
- }
-
if (config == OUTPUT_CONFIG_OFF) {
weston_log("Disabling output %s\n", name);
drmModeSetCrtc(b->drm.fd, output->crtc_id,
@@ -2393,62 +2508,80 @@ create_output_for_connector(struct drm_backend *b,
goto err_free;
}
- current = drm_output_choose_initial_mode(output_base, config,
- width, height,
- &crtc_mode, &modeline);
- if (!current)
- goto err_free;
- output_base->current_mode = ¤t->base;
- output_base->current_mode->flags |= WL_OUTPUT_MODE_CURRENT;
+ find_and_parse_output_edid(b, output, connector);
+ if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
+ output_base->connection_internal = 1;
- weston_output_init(output_base, b->compositor, x, y,
- connector->mmWidth, connector->mmHeight,
- transform, scale);
+ if (!is_clone) {
+ if (connector_get_current_mode(connector, b->drm.fd, &crtc_mode) < 0)
+ goto err_free;
- if (b->use_pixman) {
- if (drm_output_init_pixman(output, b) < 0) {
- weston_log("Failed to init output pixman state\n");
+ for (i = 0; i < connector->count_modes; i++) {
+ drm_mode = drm_output_add_mode(output_base,
+ &connector->modes[i]);
+ if (!drm_mode)
+ goto err_free;
+ }
+
+ current = drm_output_choose_initial_mode(output_base, config,
+ width, height,
+ &crtc_mode,
+ &modeline);
+ if (!current)
+ goto err_free;
+ output_base->current_mode = ¤t->base;
+ output_base->current_mode->flags |= WL_OUTPUT_MODE_CURRENT;
+
+ weston_output_init(output_base, b->compositor, x, y,
+ connector->mmWidth, connector->mmHeight,
+ transform, scale);
+
+ if (b->use_pixman) {
+ if (drm_output_init_pixman(logical_output, b) < 0) {
+ weston_log("Failed to init output pixman state\n");
+ goto err_output;
+ }
+ } else if (drm_output_init_egl(logical_output, b) < 0) {
+ weston_log("Failed to init output gl state\n");
goto err_output;
}
- } else if (drm_output_init_egl(output, b) < 0) {
- weston_log("Failed to init output gl state\n");
- goto err_output;
- }
-
- output->backlight = backlight_init(drm_device,
- connector->connector_type);
- if (output->backlight) {
- weston_log("Initialized backlight, device %s\n",
- output->backlight->path);
- output_base->set_backlight = drm_set_backlight;
- output_base->backlight_current = drm_get_backlight(output);
- } else {
- weston_log("Failed to initialize backlight\n");
- }
- weston_compositor_add_output(b->compositor, output_base);
+ output->backlight = backlight_init(drm_device,
+ connector->connector_type);
+ if (output->backlight) {
+ weston_log("Initialized backlight, device %s\n",
+ output->backlight->path);
+ output_base->set_backlight = drm_set_backlight;
+ output_base->backlight_current =
+ drm_get_backlight(output);
+ } else {
+ weston_log("Failed to initialize backlight\n");
+ }
- find_and_parse_output_edid(b, output, connector);
- if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
- output_base->connection_internal = 1;
+ weston_compositor_add_output(b->compositor, output_base);
- output_base->start_repaint_loop = drm_output_start_repaint_loop;
- output_base->repaint = drm_output_repaint;
- output_base->destroy = drm_output_destroy;
- output_base->assign_planes = drm_assign_planes;
- output_base->set_dpms = drm_set_dpms;
- output_base->switch_mode = drm_output_switch_mode;
+ output_base->start_repaint_loop = drm_output_start_repaint_loop;
+ output_base->repaint = drm_output_repaint;
+ output_base->destroy = drm_output_destroy;
+ output_base->assign_planes = drm_assign_planes;
+ output_base->set_dpms = drm_set_dpms;
+ output_base->switch_mode = drm_output_switch_mode;
- output_base->gamma_size = output->original_crtc->gamma_size;
- output_base->set_gamma = drm_output_set_gamma;
+ output_base->gamma_size = output->original_crtc->gamma_size;
+ output_base->set_gamma = drm_output_set_gamma;
- weston_plane_init(&output->cursor_plane, b->compositor,
- INT32_MIN, INT32_MIN);
- weston_plane_init(&output->fb_plane, b->compositor, 0, 0);
+ weston_plane_init(&logical_output->cursor_plane, b->compositor,
+ INT32_MIN, INT32_MIN);
+ weston_plane_init(&logical_output->fb_plane, b->compositor,
+ 0, 0);
- weston_compositor_stack_plane(b->compositor, &output->cursor_plane, NULL);
- weston_compositor_stack_plane(b->compositor, &output->fb_plane,
- &b->compositor->primary_plane);
+ weston_compositor_stack_plane(b->compositor,
+ &logical_output->cursor_plane,
+ NULL);
+ weston_compositor_stack_plane(b->compositor,
+ &logical_output->fb_plane,
+ &b->compositor->primary_plane);
+ }
weston_log("Output %s, (connector %d, crtc %d)\n", name,
output->connector_id, output->crtc_id);
@@ -2472,16 +2605,20 @@ err_output:
weston_output_destroy(output_base);
err_free:
wl_list_for_each_safe(drm_mode, next, &output_base->mode_list,
- base.link) {
+ base.link) {
wl_list_remove(&drm_mode->base.link);
free(drm_mode);
}
+ wl_list_remove(&output->link);
drmModeFreeCrtc(output->original_crtc);
b->crtc_allocator &= ~(1 << output->crtc_id);
b->connector_allocator &= ~(1 << output->connector_id);
free(output);
+ if (!is_clone)
+ free(logical_output);
+
return -1;
}
@@ -2537,20 +2674,27 @@ static void
destroy_sprites(struct drm_backend *backend)
{
struct drm_sprite *sprite, *next;
+ struct drm_logical_output *logical_output;
struct drm_output *output;
- output = container_of(backend->compositor->output_list.next,
- struct drm_output, base.link);
+ logical_output = container_of(backend->compositor->output_list.next,
+ struct drm_logical_output, base.link);
- wl_list_for_each_safe(sprite, next, &backend->sprite_list, link) {
- drmModeSetPlane(backend->drm.fd,
- sprite->plane_id,
- output->crtc_id, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0);
- drm_output_release_fb(output, sprite->current);
- drm_output_release_fb(output, sprite->next);
- weston_plane_release(&sprite->plane);
- free(sprite);
+ /* Sprite support is disabled on clone mode for now. */
+ if (wl_list_length(&logical_output->output_list) == 1) {
+ /* Fetches the only output present from the list */
+ wl_list_for_each(output, &logical_output->output_list, link);
+
+ wl_list_for_each_safe(sprite, next, &backend->sprite_list, link) {
+ drmModeSetPlane(backend->drm.fd,
+ sprite->plane_id,
+ output->crtc_id, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0);
+ drm_output_release_fb(logical_output, sprite->current);
+ drm_output_release_fb(logical_output, sprite->next);
+ weston_plane_release(&sprite->plane);
+ free(sprite);
+ }
}
}
@@ -2623,7 +2767,8 @@ update_outputs(struct drm_backend *b, struct udev_device *drm_device)
{
drmModeConnector *connector;
drmModeRes *resources;
- struct drm_output *output, *next;
+ struct drm_logical_output *logical_output, *next_logical_output;
+ struct drm_output *output, *next_output;
int x = 0, y = 0;
uint32_t connected = 0, disconnects = 0;
int i;
@@ -2672,13 +2817,17 @@ update_outputs(struct drm_backend *b, struct udev_device *drm_device)
disconnects = b->connector_allocator & ~connected;
if (disconnects) {
- wl_list_for_each_safe(output, next, &b->compositor->output_list,
- base.link) {
- if (disconnects & (1 << output->connector_id)) {
- disconnects &= ~(1 << output->connector_id);
- weston_log("connector %d disconnected\n",
- output->connector_id);
- drm_output_destroy(&output->base);
+ wl_list_for_each_safe(logical_output, next_logical_output,
+ &b->compositor->output_list, base.link) {
+ wl_list_for_each_safe(output, next_output, &logical_output->output_list, link) {
+ if (disconnects & (1 << output->connector_id)) {
+ disconnects &= ~(1 << output->connector_id);
+ weston_log("connector %d disconnected\n",
+ output->connector_id);
+ wl_list_remove(&output->link);
+ if (wl_list_empty(&logical_output->output_list))
+ drm_output_destroy(&logical_output->base);
+ }
}
}
}
@@ -2754,31 +2903,34 @@ drm_destroy(struct weston_compositor *ec)
static void
drm_backend_set_modes(struct drm_backend *backend)
{
+ struct drm_logical_output *logical_output;
struct drm_output *output;
struct drm_mode *drm_mode;
int ret;
- wl_list_for_each(output, &backend->compositor->output_list, base.link) {
- if (!output->current) {
+ wl_list_for_each(logical_output, &backend->compositor->output_list, base.link) {
+ if (!logical_output->current) {
/* If something that would cause the output to
* switch mode happened while in another vt, we
* might not have a current drm_fb. In that case,
* schedule a repaint and let drm_output_repaint
* handle setting the mode. */
- weston_output_schedule_repaint(&output->base);
+ weston_output_schedule_repaint(&logical_output->base);
continue;
}
- drm_mode = (struct drm_mode *) output->base.current_mode;
- ret = drmModeSetCrtc(backend->drm.fd, output->crtc_id,
- output->current->fb_id, 0, 0,
- &output->connector_id, 1,
- &drm_mode->mode_info);
- if (ret < 0) {
- weston_log(
- "failed to set mode %dx%d for output at %d,%d: %m\n",
- drm_mode->base.width, drm_mode->base.height,
- output->base.x, output->base.y);
+ drm_mode = (struct drm_mode *)logical_output->base.current_mode;
+ wl_list_for_each(output, &logical_output->output_list, link) {
+ ret = drmModeSetCrtc(backend->drm.fd, output->crtc_id,
+ logical_output->current->fb_id, 0, 0,
+ &output->connector_id, 1,
+ &drm_mode->mode_info);
+ if (ret < 0) {
+ weston_log(
+ "failed to set mode %dx%d for output at %d,%d: %m\n",
+ drm_mode->base.width, drm_mode->base.height,
+ logical_output->base.x, logical_output->base.y);
+ }
}
}
}
@@ -2789,6 +2941,7 @@ session_notify(struct wl_listener *listener, void *data)
struct weston_compositor *compositor = data;
struct drm_backend *b = (struct drm_backend *)compositor->backend;
struct drm_sprite *sprite;
+ struct drm_logical_output *logical_output;
struct drm_output *output;
if (compositor->session_active) {
@@ -2812,19 +2965,26 @@ session_notify(struct wl_listener *listener, void *data)
* back, we schedule a repaint, which will process
* pending frame callbacks. */
- wl_list_for_each(output, &compositor->output_list, base.link) {
- output->base.repaint_needed = 0;
- drmModeSetCursor(b->drm.fd, output->crtc_id, 0, 0, 0);
+ wl_list_for_each(logical_output, &compositor->output_list, base.link) {
+ logical_output->base.repaint_needed = 0;
+ wl_list_for_each(output, &logical_output->output_list, link)
+ drmModeSetCursor(b->drm.fd, output->crtc_id, 0, 0, 0);
}
- output = container_of(compositor->output_list.next,
- struct drm_output, base.link);
+ logical_output = container_of(compositor->output_list.next,
+ struct drm_logical_output, base.link);
- wl_list_for_each(sprite, &b->sprite_list, link)
- drmModeSetPlane(b->drm.fd,
- sprite->plane_id,
- output->crtc_id, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0);
+ /* Sprite support is disabled on clone mode for now. */
+ if (wl_list_length(&logical_output->output_list) == 1) {
+ /* Fetches the only output present from the list */
+ wl_list_for_each(output, &logical_output->output_list, link);
+
+ wl_list_for_each(sprite, &b->sprite_list, link)
+ drmModeSetPlane(b->drm.fd,
+ sprite->plane_id,
+ output->crtc_id, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0);
+ }
};
}
@@ -2907,7 +3067,7 @@ planes_binding(struct weston_keyboard *keyboard, uint32_t time, uint32_t key,
#ifdef BUILD_VAAPI_RECORDER
static void
-recorder_destroy(struct drm_output *output)
+recorder_destroy(struct drm_logical_output *output)
{
vaapi_recorder_destroy(output->recorder);
output->recorder = NULL;
@@ -2921,11 +3081,11 @@ recorder_destroy(struct drm_output *output)
static void
recorder_frame_notify(struct wl_listener *listener, void *data)
{
- struct drm_output *output;
+ struct drm_logical_output *output;
struct drm_backend *b;
int fd, ret;
- output = container_of(listener, struct drm_output,
+ output = container_of(listener, struct drm_logical_output,
recorder_frame_listener);
b = (struct drm_backend *)output->base.compositor->backend;
@@ -2970,11 +3130,11 @@ recorder_binding(struct weston_keyboard *keyboard, uint32_t time, uint32_t key,
void *data)
{
struct drm_backend *b = data;
- struct drm_output *output;
+ struct drm_logical_output *output;
int width, height;
output = container_of(b->compositor->output_list.next,
- struct drm_output, base.link);
+ struct drm_logical_output, base.link);
if (!output->recorder) {
if (output->gbm_format != GBM_FORMAT_XRGB8888) {
@@ -3018,7 +3178,7 @@ recorder_binding(struct weston_keyboard *keyboard, uint32_t time, uint32_t key,
static void
switch_to_gl_renderer(struct drm_backend *b)
{
- struct drm_output *output;
+ struct drm_logical_output *output;
bool dmabuf_support_inited;
if (!b->use_pixman)
--
2.8.2
More information about the wayland-devel
mailing list