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

Reply via email to