[PATCH v2 weston 14/16] compositor-drm: Track primary plane with a drm_plane
Daniel Stone
daniels at collabora.com
Mon Jun 22 09:25:19 PDT 2015
Use a real drm_plane to back the primary plane, displacing
output->current and output->next to their plane-tracked equivalents.
v2: Remove extra output->{current,next} members. Add primary plane to
plane_list so it gets cleaned up.
Signed-off-by: Daniel Stone <daniels at collabora.com>
---
src/compositor-drm.c | 118 +++++++++++++++++++++++++++++++++++++++------------
1 file changed, 90 insertions(+), 28 deletions(-)
diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 689b318..b52de4f 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -265,9 +265,9 @@ struct drm_output {
struct drm_fb *cursor_fb[2];
struct drm_plane *cursor_plane;
struct weston_plane fb_plane;
+ struct drm_plane *primary_plane;
struct weston_view *cursor_view;
int current_cursor;
- struct drm_fb *current, *next;
struct backlight *backlight;
struct drm_fb *dumb[2];
@@ -905,13 +905,13 @@ drm_output_prepare_scanout_view(struct drm_output *output,
return NULL;
}
- output->next = drm_fb_get_from_bo(bo, c, format);
- if (!output->next) {
+ output->primary_plane->next = drm_fb_get_from_bo(bo, c, format);
+ if (!output->primary_plane->next) {
gbm_bo_destroy(bo);
return NULL;
}
- drm_fb_set_buffer(output->next, buffer);
+ drm_fb_set_buffer(output->primary_plane->next, buffer);
return &output->fb_plane;
}
@@ -931,8 +931,8 @@ drm_output_render_gl(struct drm_output *output, pixman_region32_t *damage)
return;
}
- output->next = drm_fb_get_from_bo(bo, c, output->format);
- if (!output->next) {
+ output->primary_plane->next = drm_fb_get_from_bo(bo, c, output->format);
+ if (!output->primary_plane->next) {
weston_log("failed to get drm_fb for bo\n");
gbm_surface_release_buffer(output->surface, bo);
return;
@@ -955,7 +955,7 @@ drm_output_render_pixman(struct drm_output *output, pixman_region32_t *damage)
output->current_image ^= 1;
- output->next = output->dumb[output->current_image];
+ output->primary_plane->next = output->dumb[output->current_image];
pixman_renderer_output_set_buffer(&output->base,
output->image[output->current_image]);
@@ -1015,16 +1015,17 @@ drm_output_repaint(struct weston_output *output_base,
if (output->destroy_pending)
return -1;
- if (!output->next)
+ if (!output->primary_plane->next)
drm_output_render(output, damage);
- if (!output->next)
+ if (!output->primary_plane->next)
return -1;
mode = container_of(output->base.current_mode, struct drm_mode, base);
- if (!output->current ||
- output->current->stride != output->next->stride) {
+ if (!output->primary_plane->current ||
+ output->primary_plane->current->stride !=
+ output->primary_plane->next->stride) {
ret = drmModeSetCrtc(compositor->drm.fd, output->crtc_id,
- output->next->fb_id, 0, 0,
+ output->primary_plane->next->fb_id, 0, 0,
&output->connector_id, 1,
&mode->mode_info);
if (ret) {
@@ -1035,7 +1036,7 @@ drm_output_repaint(struct weston_output *output_base,
}
if (drmModePageFlip(compositor->drm.fd, output->crtc_id,
- output->next->fb_id,
+ output->primary_plane->next->fb_id,
DRM_MODE_PAGE_FLIP_EVENT, output) < 0) {
weston_log("queueing pageflip failed: %m\n");
goto err_pageflip;
@@ -1101,9 +1102,9 @@ drm_output_repaint(struct weston_output *output_base,
err_pageflip:
output->cursor_view = NULL;
- if (output->next) {
- drm_output_release_fb(output, output->next);
- output->next = NULL;
+ if (output->primary_plane->next) {
+ drm_output_release_fb(output, output->primary_plane->next);
+ output->primary_plane->next = NULL;
}
return -1;
@@ -1121,12 +1122,12 @@ drm_output_start_repaint_loop(struct weston_output *output_base)
if (output->destroy_pending)
return;
- if (!output->current) {
+ if (!output->primary_plane->current) {
/* We can't page flip if there's no mode set */
goto finish_frame;
}
- fb_id = output->current->fb_id;
+ fb_id = output->primary_plane->current->fb_id;
if (drmModePageFlip(compositor->drm.fd, output->crtc_id, fb_id,
DRM_MODE_PAGE_FLIP_EVENT, output) < 0) {
@@ -1197,9 +1198,9 @@ page_flip_handler(int fd, unsigned int frame,
* 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;
+ drm_output_release_fb(output, output->primary_plane->current);
+ output->primary_plane->current = output->primary_plane->next;
+ output->primary_plane->next = NULL;
}
output->page_flip_pending = 0;
@@ -1732,9 +1733,9 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo
WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
/* reset rendering stuff. */
- drm_output_release_fb(output, output->current);
- drm_output_release_fb(output, output->next);
- output->current = output->next = NULL;
+ drm_output_release_fb(output, output->primary_plane->current);
+ drm_output_release_fb(output, output->primary_plane->next);
+ output->primary_plane->current = output->primary_plane->next = NULL;
if (ec->use_pixman) {
drm_output_fini_pixman(output);
@@ -2599,6 +2600,60 @@ connector_get_current_mode(drmModeConnector *connector, int drm_fd,
}
static void
+drm_output_init_primary_plane(struct drm_output *output)
+{
+ struct drm_compositor *ec =
+ (struct drm_compositor *) output->base.compositor;
+ struct drm_plane *plane;
+
+ if (ec->universal_planes) {
+ wl_list_for_each(plane, &ec->plane_list, link) {
+ if (plane->type != WDRM_PLANE_TYPE_PRIMARY)
+ continue;
+ if (plane->output)
+ continue;
+ if (!drm_plane_crtc_supported(output,
+ plane->possible_crtcs))
+ continue;
+
+ plane->output = output;
+ output->primary_plane = plane;
+ break;
+ }
+ }
+ else {
+ /* XXX: Gross open-coding ... ? */
+ plane = zalloc(sizeof(*plane) + sizeof(uint32_t));
+ if (!plane) {
+ weston_log("%s: out of memory\n", __func__);
+ return;
+ }
+
+ weston_plane_init(&plane->base, &ec->base, 0, 0);
+ wl_list_insert(&ec->plane_list, &plane->link);
+
+ plane->plane_id = 0;
+ plane->possible_crtcs = 0;
+ plane->output = output;
+ plane->current = NULL;
+ plane->next = NULL;
+ plane->compositor = ec;
+ plane->count_formats = 1;
+ plane->formats[0] = output->format;
+ plane->type = WDRM_PLANE_TYPE_PRIMARY;
+
+ output->primary_plane = plane;
+ }
+
+ /* Unlike the cursor plane, we don't stack the primary plane into
+ * the base list, because it's implicitly placed at the bottom. The
+ * base compositor's primary_plane covers everything we construct
+ * with our renderer, with each output taking a chunk of the
+ * base primary_plane. So here we just internally treat this plane
+ * as a partial shadow of weston_compositor::primary_plane. */
+}
+
+static void
drm_output_init_cursor(struct drm_output *output)
{
struct drm_compositor *ec =
@@ -2758,6 +2813,12 @@ create_output_for_connector(struct drm_compositor *ec,
connector->mmWidth, connector->mmHeight,
transform, scale);
+ drm_output_init_primary_plane(output);
+ if (!output->primary_plane) {
+ weston_log("Failed to find primary plane for output %s\n",
+ output->base.name);
+ goto err_output;
+ }
drm_output_init_cursor(output);
if (ec->use_pixman) {
@@ -3172,7 +3233,7 @@ drm_compositor_set_modes(struct drm_compositor *compositor)
int ret;
wl_list_for_each(output, &compositor->base.output_list, base.link) {
- if (!output->current) {
+ if (!output->primary_plane->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,
@@ -3184,7 +3245,7 @@ drm_compositor_set_modes(struct drm_compositor *compositor)
drm_mode = (struct drm_mode *) output->base.current_mode;
ret = drmModeSetCrtc(compositor->drm.fd, output->crtc_id,
- output->current->fb_id, 0, 0,
+ output->primary_plane->current->fb_id, 0, 0,
&output->connector_id, 1,
&drm_mode->mode_info);
if (ret < 0) {
@@ -3358,7 +3419,8 @@ recorder_frame_notify(struct wl_listener *listener, void *data)
if (!output->recorder)
return;
- ret = drmPrimeHandleToFD(c->drm.fd, output->current->handle,
+ ret = drmPrimeHandleToFD(c->drm.fd,
+ output->primary_plane->current->handle,
DRM_CLOEXEC, &fd);
if (ret) {
weston_log("[libva recorder] "
@@ -3367,7 +3429,7 @@ recorder_frame_notify(struct wl_listener *listener, void *data)
}
ret = vaapi_recorder_frame(output->recorder, fd,
- output->current->stride);
+ output->primary_plane->current->stride);
if (ret < 0) {
weston_log("[libva recorder] aborted: %m\n");
recorder_destroy(output);
--
2.4.3
More information about the wayland-devel
mailing list