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 <dani...@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 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel