Add support for using the atomic-modesetting API to apply output state.
Unlike previous series, this commit does not unflip sprites_are_broken,
until further work has been done with assign_planes to make it reliable.

Signed-off-by: Daniel Stone <dani...@collabora.com>
Co-authored-by: Pekka Paalanen <pekka.paala...@collabora.co.uk>
Co-authored-by: Louis-Francis Ratté-Boulianne 
<louis-francis.ratte-boulia...@collabora.com>
Co-authored-by: Derek Foreman <derek.fore...@collabora.co.uk>
---
 configure.ac               |   2 +-
 libweston/compositor-drm.c | 504 ++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 431 insertions(+), 75 deletions(-)

diff --git a/configure.ac b/configure.ac
index 72b5d6f23..ba9247773 100644
--- a/configure.ac
+++ b/configure.ac
@@ -206,7 +206,7 @@ AM_CONDITIONAL(ENABLE_DRM_COMPOSITOR, test 
x$enable_drm_compositor = xyes)
 if test x$enable_drm_compositor = xyes; then
   AC_DEFINE([BUILD_DRM_COMPOSITOR], [1], [Build the DRM compositor])
   PKG_CHECK_MODULES(DRM_COMPOSITOR, [libudev >= 136 libdrm >= 2.4.30 gbm])
-  PKG_CHECK_MODULES(DRM_COMPOSITOR_ATOMIC, [libdrm >= 2.4.62],
+  PKG_CHECK_MODULES(DRM_COMPOSITOR_ATOMIC, [libdrm >= 2.4.78],
                    [AC_DEFINE([HAVE_DRM_ATOMIC], 1, [libdrm supports atomic 
API])],
                    [AC_MSG_WARN([libdrm does not support atomic modesetting, 
will omit that capability])])
   PKG_CHECK_MODULES(DRM_COMPOSITOR_GBM, [gbm >= 10.2],
diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
index cb8f00e95..d5955c9ca 100644
--- a/libweston/compositor-drm.c
+++ b/libweston/compositor-drm.c
@@ -83,6 +83,35 @@
 #define GBM_BO_USE_CURSOR GBM_BO_USE_CURSOR_64X64
 #endif
 
+/**
+ * Represents the values of an enum-type KMS property
+ */
+struct drm_property_enum_info {
+       const char *name; /**< name as string (static, not freed) */
+       bool valid; /**< true if value is supported; ignore if false */
+       uint64_t value; /**< raw value */
+};
+
+/**
+ * Holds information on a DRM property, including its ID and the enum
+ * values it holds.
+ *
+ * DRM properties are allocated dynamically, and maintained as DRM objects
+ * within the normal object ID space; they thus do not have a stable ID
+ * to refer to. This includes enum values, which must be referred to by
+ * integer values, but these are not stable.
+ *
+ * drm_property_info allows a cache to be maintained where Weston can use
+ * enum values internally to refer to properties, with the mapping to DRM
+ * ID values being maintained internally.
+ */
+struct drm_property_info {
+       const char *name; /**< name as string (static, not freed) */
+       uint32_t prop_id; /**< KMS property object ID */
+       unsigned int num_enum_values; /**< number of enum values */
+       struct drm_property_enum_info *enum_values; /**< array of enum values */
+};
+
 /**
  * List of properties attached to DRM planes
  */
@@ -111,6 +140,36 @@ enum wdrm_plane_type {
        WDRM_PLANE_TYPE__COUNT
 };
 
+static struct drm_property_enum_info plane_type_enums[] = {
+       [WDRM_PLANE_TYPE_PRIMARY] = {
+               .name = "Primary",
+       },
+       [WDRM_PLANE_TYPE_OVERLAY] = {
+               .name = "Overlay",
+       },
+       [WDRM_PLANE_TYPE_CURSOR] = {
+               .name = "Cursor",
+       },
+};
+
+static const struct drm_property_info plane_props[] = {
+       [WDRM_PLANE_TYPE] = {
+               .name = "type",
+               .enum_values = plane_type_enums,
+               .num_enum_values = WDRM_PLANE_TYPE__COUNT,
+       },
+       [WDRM_PLANE_SRC_X] = { .name = "SRC_X", },
+       [WDRM_PLANE_SRC_Y] = { .name = "SRC_Y", },
+       [WDRM_PLANE_SRC_W] = { .name = "SRC_W", },
+       [WDRM_PLANE_SRC_H] = { .name = "SRC_H", },
+       [WDRM_PLANE_CRTC_X] = { .name = "CRTC_X", },
+       [WDRM_PLANE_CRTC_Y] = { .name = "CRTC_Y", },
+       [WDRM_PLANE_CRTC_W] = { .name = "CRTC_W", },
+       [WDRM_PLANE_CRTC_H] = { .name = "CRTC_H", },
+       [WDRM_PLANE_FB_ID] = { .name = "FB_ID", },
+       [WDRM_PLANE_CRTC_ID] = { .name = "CRTC_ID", },
+};
+
 /**
  * List of properties attached to a DRM connector
  */
@@ -121,33 +180,10 @@ enum wdrm_connector_property {
        WDRM_CONNECTOR__COUNT
 };
 
-/**
- * Represents the values of an enum-type KMS property
- */
-struct drm_property_enum_info {
-       const char *name; /**< name as string (static, not freed) */
-       bool valid; /**< true if value is supported; ignore if false */
-       uint64_t value; /**< raw value */
-};
-
-/**
- * Holds information on a DRM property, including its ID and the enum
- * values it holds.
- *
- * DRM properties are allocated dynamically, and maintained as DRM objects
- * within the normal object ID space; they thus do not have a stable ID
- * to refer to. This includes enum values, which must be referred to by
- * integer values, but these are not stable.
- *
- * drm_property_info allows a cache to be maintained where Weston can use
- * enum values internally to refer to properties, with the mapping to DRM
- * ID values being maintained internally.
- */
-struct drm_property_info {
-       const char *name; /**< name as string (static, not freed) */
-       uint32_t prop_id; /**< KMS property object ID */
-       unsigned int num_enum_values; /**< number of enum values */
-       struct drm_property_enum_info *enum_values; /**< array of enum values */
+static const struct drm_property_info connector_props[] = {
+       [WDRM_CONNECTOR_EDID] = { .name = "EDID" },
+       [WDRM_CONNECTOR_DPMS] = { .name = "DPMS" },
+       [WDRM_CONNECTOR_CRTC_ID] = { .name = "CRTC_ID", },
 };
 
 /**
@@ -159,6 +195,11 @@ enum wdrm_crtc_property {
        WDRM_CRTC__COUNT
 };
 
+static const struct drm_property_info crtc_props[] = {
+       [WDRM_CRTC_MODE_ID] = { .name = "MODE_ID", },
+       [WDRM_CRTC_ACTIVE] = { .name = "ACTIVE", },
+};
+
 /**
  * Mode for drm_output_state_duplicate.
  */
@@ -376,6 +417,7 @@ struct drm_output {
 
        int vblank_pending;
        int page_flip_pending;
+       int atomic_complete_pending;
        int destroy_pending;
        int disable_pending;
        int dpms_off_pending;
@@ -1439,6 +1481,9 @@ drm_output_assign_state(struct drm_output_state *state,
 
        output->state_cur = state;
 
+       if (b->atomic_modeset && mode == DRM_STATE_APPLY_ASYNC)
+               output->atomic_complete_pending = 1;
+
        /* Replace state_cur on each affected plane with the new state, being
         * careful to dispose of orphaned (but only orphaned) previous state.
         * If the previous state is not orphaned (still has an output_state
@@ -1455,6 +1500,9 @@ drm_output_assign_state(struct drm_output_state *state,
                        continue;
                }
 
+               if (b->atomic_modeset)
+                       continue;
+
                if (plane->type == WDRM_PLANE_TYPE_OVERLAY)
                        output->vblank_pending++;
                else if (plane->type == WDRM_PLANE_TYPE_PRIMARY)
@@ -1758,7 +1806,7 @@ drm_waitvblank_pipe(struct drm_output *output)
 }
 
 static int
-drm_output_apply_state(struct drm_output_state *state)
+drm_output_apply_state_legacy(struct drm_output_state *state)
 {
        struct drm_output *output = state->output;
        struct drm_backend *backend = to_drm_backend(output->base.compositor);
@@ -1933,6 +1981,296 @@ err:
        return -1;
 }
 
+#ifdef HAVE_DRM_ATOMIC
+static int
+crtc_add_prop(drmModeAtomicReq *req, struct drm_output *output,
+             enum wdrm_crtc_property prop, uint64_t val)
+{
+       struct drm_property_info *info = &output->props_crtc[prop];
+       int ret;
+
+       if (info->prop_id == 0)
+               return -1;
+
+       ret = drmModeAtomicAddProperty(req, output->crtc_id, info->prop_id,
+                                      val);
+       return (ret <= 0) ? -1 : 0;
+}
+
+static int
+connector_add_prop(drmModeAtomicReq *req, struct drm_output *output,
+                  enum wdrm_connector_property prop, uint64_t val)
+{
+       struct drm_property_info *info = &output->props_conn[prop];
+       int ret;
+
+       if (info->prop_id == 0)
+               return -1;
+
+       ret = drmModeAtomicAddProperty(req, output->connector_id,
+                                      info->prop_id, val);
+       return (ret <= 0) ? -1 : 0;
+}
+
+static int
+plane_add_prop(drmModeAtomicReq *req, struct drm_plane *plane,
+              enum wdrm_plane_property prop, uint64_t val)
+{
+       struct drm_property_info *info = &plane->props[prop];
+       int ret;
+
+       if (info->prop_id == 0)
+               return -1;
+
+       ret = drmModeAtomicAddProperty(req, plane->plane_id, info->prop_id,
+                                      val);
+       return (ret <= 0) ? -1 : 0;
+}
+
+static int
+drm_mode_ensure_blob(struct drm_backend *backend, struct drm_mode *mode)
+{
+       int ret;
+
+       if (mode->blob_id)
+               return 0;
+
+       ret = drmModeCreatePropertyBlob(backend->drm.fd,
+                                       &mode->mode_info,
+                                       sizeof(mode->mode_info),
+                                       &mode->blob_id);
+       if (ret != 0)
+               weston_log("failed to create mode property blob: %m\n");
+
+       return ret;
+}
+
+static int
+drm_output_apply_state_atomic(struct drm_output_state *state,
+                             drmModeAtomicReq *req,
+                             uint32_t *flags)
+{
+       struct drm_output *output = state->output;
+       struct drm_backend *backend = to_drm_backend(output->base.compositor);
+       struct drm_plane_state *plane_state;
+       struct drm_mode *current_mode = to_drm_mode(output->base.current_mode);
+       int ret = 0;
+
+       if (state->dpms != output->state_cur->dpms)
+               *flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
+
+       if (state->dpms == WESTON_DPMS_ON) {
+               ret = drm_mode_ensure_blob(backend, current_mode);
+               if (ret != 0)
+                       goto err;
+
+               ret |= crtc_add_prop(req, output, WDRM_CRTC_MODE_ID,
+                                    current_mode->blob_id);
+               ret |= crtc_add_prop(req, output, WDRM_CRTC_ACTIVE, 1);
+               ret |= connector_add_prop(req, output, WDRM_CONNECTOR_CRTC_ID,
+                                         output->crtc_id);
+       } else {
+               ret |= crtc_add_prop(req, output, WDRM_CRTC_MODE_ID, 0);
+               ret |= crtc_add_prop(req, output, WDRM_CRTC_ACTIVE, 0);
+               ret |= connector_add_prop(req, output, WDRM_CONNECTOR_CRTC_ID,
+                                         0);
+       }
+
+       if (ret != 0) {
+               weston_log("couldn't set atomic CRTC/connector state\n");
+               goto err;
+       }
+
+       wl_list_for_each(plane_state, &state->plane_list, link) {
+               struct drm_plane *plane = plane_state->plane;
+
+               ret |= plane_add_prop(req, plane, WDRM_PLANE_FB_ID,
+                                     plane_state->fb ? plane_state->fb->fb_id 
: 0);
+               ret |= plane_add_prop(req, plane, WDRM_PLANE_CRTC_ID,
+                                     plane_state->fb ? output->crtc_id : 0);
+               ret |= plane_add_prop(req, plane, WDRM_PLANE_SRC_X,
+                                     plane_state->src_x);
+               ret |= plane_add_prop(req, plane, WDRM_PLANE_SRC_Y,
+                                     plane_state->src_y);
+               ret |= plane_add_prop(req, plane, WDRM_PLANE_SRC_W,
+                                     plane_state->src_w);
+               ret |= plane_add_prop(req, plane, WDRM_PLANE_SRC_H,
+                                     plane_state->src_h);
+               ret |= plane_add_prop(req, plane, WDRM_PLANE_CRTC_X,
+                                     plane_state->dest_x);
+               ret |= plane_add_prop(req, plane, WDRM_PLANE_CRTC_Y,
+                                     plane_state->dest_y);
+               ret |= plane_add_prop(req, plane, WDRM_PLANE_CRTC_W,
+                                     plane_state->dest_w);
+               ret |= plane_add_prop(req, plane, WDRM_PLANE_CRTC_H,
+                                     plane_state->dest_h);
+
+               if (ret != 0) {
+                       weston_log("couldn't set plane state\n");
+                       goto err;
+               }
+       }
+
+       return 0;
+
+err:
+       drm_output_state_free(state);
+       return -1;
+}
+
+static int
+drm_pending_state_apply_atomic(struct drm_pending_state *pending_state,
+                              enum drm_state_apply_mode mode)
+{
+       struct drm_backend *b = pending_state->backend;
+       struct drm_output_state *output_state, *tmp;
+       struct drm_plane *plane;
+       drmModeAtomicReq *req = drmModeAtomicAlloc();
+       uint32_t flags = 0;
+       int ret = 0;
+
+       if (!req)
+               return -1;
+
+       if (b->state_invalid) {
+               uint32_t *unused;
+               int err;
+
+               /* If we need to reset all our state (e.g. because we've
+                * just started, or just been VT-switched in), explicitly
+                * disable all the CRTCs and connectors we aren't using. */
+               wl_array_for_each(unused, &b->unused_connectors) {
+                       struct drm_property_info infos[WDRM_CONNECTOR__COUNT];
+                       struct drm_property_info *info;
+                       drmModeObjectProperties *props;
+
+                       memset(infos, 0, sizeof(infos));
+
+                       props = drmModeObjectGetProperties(b->drm.fd,
+                                                          *unused,
+                                                          
DRM_MODE_OBJECT_CONNECTOR);
+                       if (!props) {
+                               ret = -1;
+                               continue;
+                       }
+
+                       drm_property_info_populate(b, connector_props, infos,
+                                                  WDRM_CONNECTOR__COUNT,
+                                                  props);
+                       drmModeFreeObjectProperties(props);
+
+                       info = &infos[WDRM_CONNECTOR_CRTC_ID];
+                       err = drmModeAtomicAddProperty(req, *unused,
+                                                      info->prop_id, 0);
+                       if (err <= 0)
+                               ret = -1;
+
+                       info = &infos[WDRM_CONNECTOR_DPMS];
+                       if (info->prop_id > 0)
+                               err = drmModeAtomicAddProperty(req, *unused,
+                                                              info->prop_id,
+                                                              
DRM_MODE_DPMS_OFF);
+                       if (err <= 0)
+                               ret = -1;
+
+                       drm_property_info_free(infos, WDRM_CONNECTOR__COUNT);
+               }
+
+               wl_array_for_each(unused, &b->unused_crtcs) {
+                       struct drm_property_info infos[WDRM_CRTC__COUNT];
+                       struct drm_property_info *info;
+                       drmModeObjectProperties *props;
+                       uint64_t active;
+
+                       memset(infos, 0, sizeof(infos));
+
+                       /* We can't emit a disable on a CRTC that's already
+                        * off, as the kernel will refuse to generate an event
+                        * for an off->off state and fail the commit.
+                        */
+                       props = drmModeObjectGetProperties(b->drm.fd,
+                                                          *unused,
+                                                          
DRM_MODE_OBJECT_CRTC);
+                       if (!props) {
+                               ret = -1;
+                               continue;
+                       }
+
+                       drm_property_info_populate(b, crtc_props, infos,
+                                                  WDRM_CRTC__COUNT,
+                                                  props);
+
+                       info = &infos[WDRM_CRTC_ACTIVE];
+                       active = drm_property_get_value(info, props, 0);
+                       drmModeFreeObjectProperties(props);
+                       if (active == 0) {
+                               drm_property_info_free(infos, WDRM_CRTC__COUNT);
+                               continue;
+                       }
+
+                       err = drmModeAtomicAddProperty(req, *unused,
+                                                      info->prop_id, 0);
+                       if (err <= 0)
+                               ret = -1;
+
+                       info = &infos[WDRM_CRTC_MODE_ID];
+                       err = drmModeAtomicAddProperty(req, *unused,
+                                                      info->prop_id, 0);
+                       if (err <= 0)
+                               ret = -1;
+
+                       drm_property_info_free(infos, WDRM_CRTC__COUNT);
+               }
+
+               /* Disable all the planes; planes which are being used will
+                * override this state in the output-state application. */
+               wl_list_for_each(plane, &b->plane_list, link) {
+                       plane_add_prop(req, plane, WDRM_PLANE_CRTC_ID, 0);
+                       plane_add_prop(req, plane, WDRM_PLANE_FB_ID, 0);
+               }
+
+               flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
+       }
+
+       wl_list_for_each(output_state, &pending_state->output_list, link) {
+               if (mode == DRM_STATE_APPLY_SYNC)
+                       assert(output_state->dpms == WESTON_DPMS_OFF);
+               ret |= drm_output_apply_state_atomic(output_state, req, &flags);
+       }
+
+       if (ret != 0) {
+               weston_log("atomic: couldn't compile atomic state\n");
+               goto out;
+       }
+
+       switch (mode) {
+       case DRM_STATE_APPLY_SYNC:
+               break;
+       case DRM_STATE_APPLY_ASYNC:
+               flags |= DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK;
+               break;
+       }
+
+       ret = drmModeAtomicCommit(b->drm.fd, req, flags, b);
+       if (ret != 0) {
+               weston_log("atomic: couldn't commit new state: %m\n");
+               goto out;
+       }
+
+       wl_list_for_each_safe(output_state, tmp, &pending_state->output_list,
+                             link)
+               drm_output_assign_state(output_state, mode);
+
+       b->state_invalid = false;
+
+       assert(wl_list_empty(&pending_state->output_list));
+
+out:
+       drmModeAtomicFree(req);
+       return ret;
+}
+#endif
+
 static int
 drm_pending_state_apply(struct drm_pending_state *pending_state)
 {
@@ -1940,6 +2278,12 @@ drm_pending_state_apply(struct drm_pending_state 
*pending_state)
        struct drm_output_state *output_state, *tmp;
        uint32_t *unused;
 
+#ifdef HAVE_DRM_ATOMIC
+       if (b->atomic_modeset)
+               return drm_pending_state_apply_atomic(pending_state,
+                                                     DRM_STATE_APPLY_ASYNC);
+#endif
+
        if (b->state_invalid) {
                /* If we need to reset all our state (e.g. because we've
                 * just started, or just been VT-switched in), explicitly
@@ -1956,7 +2300,7 @@ drm_pending_state_apply(struct drm_pending_state 
*pending_state)
                struct drm_output *output = output_state->output;
                int ret;
 
-               ret = drm_output_apply_state(output_state);
+               ret = drm_output_apply_state_legacy(output_state);
                if (ret != 0) {
                        weston_log("Couldn't apply state for output %s\n",
                                   output->base.name);
@@ -1979,6 +2323,12 @@ drm_pending_state_apply_sync(struct drm_pending_state 
*pending_state)
        struct drm_output_state *output_state, *tmp;
        uint32_t *unused;
 
+#ifdef HAVE_DRM_ATOMIC
+       if (b->atomic_modeset)
+               return drm_pending_state_apply_atomic(pending_state,
+                                                     DRM_STATE_APPLY_SYNC);
+#endif
+
        if (b->state_invalid) {
                /* If we need to reset all our state (e.g. because we've
                 * just started, or just been VT-switched in), explicitly
@@ -1995,7 +2345,7 @@ drm_pending_state_apply_sync(struct drm_pending_state 
*pending_state)
                int ret;
 
                assert(output_state->dpms == WESTON_DPMS_OFF);
-               ret = drm_output_apply_state(output_state);
+               ret = drm_output_apply_state_legacy(output_state);
                if (ret != 0) {
                        weston_log("Couldn't apply state for output %s\n",
                                   output_state->output->base.name);
@@ -2155,9 +2505,12 @@ vblank_handler(int fd, unsigned int frame, unsigned int 
sec, unsigned int usec,
        struct drm_plane_state *ps = (struct drm_plane_state *) data;
        struct drm_output_state *os = ps->output_state;
        struct drm_output *output = os->output;
+       struct drm_backend *b = to_drm_backend(output->base.compositor);
        uint32_t flags = WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION |
                         WP_PRESENTATION_FEEDBACK_KIND_HW_CLOCK;
 
+       assert(!b->atomic_modeset);
+
        drm_output_update_msc(output, frame);
        output->vblank_pending--;
        assert(output->vblank_pending >= 0);
@@ -2175,12 +2528,14 @@ page_flip_handler(int fd, unsigned int frame,
                  unsigned int sec, unsigned int usec, void *data)
 {
        struct drm_output *output = data;
+       struct drm_backend *b = to_drm_backend(output->base.compositor);
        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, frame);
 
+       assert(!b->atomic_modeset);
        assert(output->page_flip_pending);
        output->page_flip_pending = 0;
 
@@ -2244,6 +2599,33 @@ drm_repaint_cancel(struct weston_compositor *compositor, 
void *repaint_data)
        b->repaint_data = NULL;
 }
 
+#ifdef HAVE_DRM_ATOMIC
+static void
+atomic_flip_handler(int fd, unsigned int frame, unsigned int sec,
+                   unsigned int usec, unsigned int crtc_id, void *data)
+{
+       struct drm_backend *b = data;
+       struct drm_output *output = drm_output_find_by_crtc(b, crtc_id);
+       uint32_t flags = WP_PRESENTATION_FEEDBACK_KIND_VSYNC |
+                        WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION |
+                        WP_PRESENTATION_FEEDBACK_KIND_HW_CLOCK;
+
+       /* During the initial modeset, we can disable CRTCs which we don't
+        * actually handle during normal operation; this will give us events
+        * for unknown outputs. Ignore them. */
+       if (!output)
+               return;
+
+       drm_output_update_msc(output, frame);
+
+       assert(b->atomic_modeset);
+       assert(output->atomic_complete_pending);
+       output->atomic_complete_pending = 0;
+
+       drm_output_update_complete(output, flags, sec, usec);
+}
+#endif
+
 static uint32_t
 drm_output_check_plane_format(struct drm_plane *p,
                               struct weston_view *ev, struct gbm_bo *bo)
@@ -2868,11 +3250,19 @@ drm_output_switch_mode(struct weston_output 
*output_base, struct weston_mode *mo
 static int
 on_drm_input(int fd, uint32_t mask, void *data)
 {
+#ifdef HAVE_DRM_ATOMIC
+       struct drm_backend *b = data;
+#endif
        drmEventContext evctx;
 
        memset(&evctx, 0, sizeof evctx);
-       evctx.version = 2;
-       evctx.page_flip_handler = page_flip_handler;
+       evctx.version = 3;
+#ifdef HAVE_DRM_ATOMIC
+       if (b->atomic_modeset)
+               evctx.page_flip_handler2 = atomic_flip_handler;
+       else
+#endif
+               evctx.page_flip_handler = page_flip_handler;
        evctx.vblank_handler = vblank_handler;
        drmHandleEvent(fd, &evctx);
 
@@ -2921,8 +3311,11 @@ init_kms_caps(struct drm_backend *b)
 
 #ifdef HAVE_DRM_ATOMIC
        if (b->universal_planes && !getenv("WESTON_DISABLE_ATOMIC")) {
+               ret = drmGetCap(b->drm.fd, DRM_CAP_CRTC_IN_VBLANK_EVENT, &cap);
+               if (ret != 0)
+                       cap = 0;
                ret = drmSetClientCap(b->drm.fd, DRM_CLIENT_CAP_ATOMIC, 1);
-               b->atomic_modeset = (ret == 0);
+               b->atomic_modeset = ((ret == 0) && (cap == 1));
        }
 #endif
        weston_log("DRM: %s atomic modesetting\n",
@@ -3054,35 +3447,6 @@ drm_plane_create(struct drm_backend *b, const 
drmModePlane *kplane,
        drmModeObjectProperties *props;
        int num_formats = (kplane) ? kplane->count_formats : 1;
 
-       static struct drm_property_enum_info plane_type_enums[] = {
-               [WDRM_PLANE_TYPE_PRIMARY] = {
-                       .name = "Primary",
-               },
-               [WDRM_PLANE_TYPE_OVERLAY] = {
-                       .name = "Overlay",
-               },
-               [WDRM_PLANE_TYPE_CURSOR] = {
-                       .name = "Cursor",
-               },
-       };
-       static const struct drm_property_info plane_props[] = {
-               [WDRM_PLANE_TYPE] = {
-                       .name = "type",
-                       .enum_values = plane_type_enums,
-                       .num_enum_values = WDRM_PLANE_TYPE__COUNT,
-               },
-               [WDRM_PLANE_SRC_X] = { .name = "SRC_X", },
-               [WDRM_PLANE_SRC_Y] = { .name = "SRC_Y", },
-               [WDRM_PLANE_SRC_W] = { .name = "SRC_W", },
-               [WDRM_PLANE_SRC_H] = { .name = "SRC_H", },
-               [WDRM_PLANE_CRTC_X] = { .name = "CRTC_X", },
-               [WDRM_PLANE_CRTC_Y] = { .name = "CRTC_Y", },
-               [WDRM_PLANE_CRTC_W] = { .name = "CRTC_W", },
-               [WDRM_PLANE_CRTC_H] = { .name = "CRTC_H", },
-               [WDRM_PLANE_FB_ID] = { .name = "FB_ID", },
-               [WDRM_PLANE_CRTC_ID] = { .name = "CRTC_ID", },
-       };
-
        plane = zalloc(sizeof(*plane) +
                       (sizeof(uint32_t) * num_formats));
        if (!plane) {
@@ -4306,7 +4670,8 @@ drm_output_destroy(struct weston_output *base)
        struct drm_backend *b = to_drm_backend(output->base.compositor);
        struct drm_mode *drm_mode, *next;
 
-       if (output->page_flip_pending || output->vblank_pending) {
+       if (output->page_flip_pending || output->vblank_pending ||
+           output->atomic_complete_pending) {
                output->destroy_pending = 1;
                weston_log("destroy output while page flip pending\n");
                return;
@@ -4364,7 +4729,8 @@ drm_output_disable(struct weston_output *base)
        struct drm_pending_state *pending_state;
        int ret;
 
-       if (output->page_flip_pending || output->vblank_pending) {
+       if (output->page_flip_pending || output->vblank_pending ||
+           output->atomic_complete_pending) {
                output->disable_pending = 1;
                return -1;
        }
@@ -4454,16 +4820,6 @@ create_output_for_connector(struct drm_backend *b,
        drmModeCrtcPtr origcrtc;
        int i;
 
-       static const struct drm_property_info connector_props[] = {
-               [WDRM_CONNECTOR_EDID] = { .name = "EDID" },
-               [WDRM_CONNECTOR_DPMS] = { .name = "DPMS" },
-               [WDRM_CONNECTOR_CRTC_ID] = { .name = "CRTC_ID", },
-       };
-       static const struct drm_property_info crtc_props[] = {
-               [WDRM_CRTC_MODE_ID] = { .name = "MODE_ID", },
-               [WDRM_CRTC_ACTIVE] = { .name = "ACTIVE", },
-       };
-
        i = find_crtc_for_connector(b, resources, connector);
        if (i < 0) {
                weston_log("No usable crtc/encoder pair for connector.\n");
-- 
2.14.3

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to