drm: qxl: Atomic phase 1: convert cursor to universal plane
authorGabriel Krisman Bertazi <krisman@collabora.co.uk>
Mon, 27 Feb 2017 20:43:19 +0000 (17:43 -0300)
committerGerd Hoffmann <kraxel@redhat.com>
Tue, 28 Feb 2017 16:26:12 +0000 (17:26 +0100)
In preparation for atomic conversion, let's use the transitional atomic
helpers drm_plane_helper_update/disable.

Signed-off-by: Gabriel Krisman Bertazi <krisman@collabora.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/20170227204328.18761-6-krisman@collabora.co.uk
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
drivers/gpu/drm/qxl/qxl_display.c
drivers/gpu/drm/qxl/qxl_drv.h

index 04f021437c25df77828d19605876aeb9ff123a0d..fef464730c9b22c61d2d6331c3f10a4319fe54fd 100644 (file)
@@ -30,6 +30,7 @@
 #include "qxl_object.h"
 #include "drm_crtc_helper.h"
 #include <drm/drm_plane_helper.h>
+#include <drm/drm_atomic_helper.h>
 
 static bool qxl_head_enabled(struct qxl_head *head)
 {
@@ -256,7 +257,6 @@ static void qxl_crtc_destroy(struct drm_crtc *crtc)
        struct qxl_crtc *qxl_crtc = to_qxl_crtc(crtc);
 
        drm_crtc_cleanup(crtc);
-       qxl_bo_unref(&qxl_crtc->cursor_bo);
        kfree(qxl_crtc);
 }
 
@@ -304,234 +304,7 @@ static int qxl_crtc_page_flip(struct drm_crtc *crtc,
        return 0;
 }
 
-static int
-qxl_hide_cursor(struct qxl_device *qdev)
-{
-       struct qxl_release *release;
-       struct qxl_cursor_cmd *cmd;
-       int ret;
-
-       ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd), QXL_RELEASE_CURSOR_CMD,
-                                        &release, NULL);
-       if (ret)
-               return ret;
-
-       ret = qxl_release_reserve_list(release, true);
-       if (ret) {
-               qxl_release_free(qdev, release);
-               return ret;
-       }
-
-       cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release);
-       cmd->type = QXL_CURSOR_HIDE;
-       qxl_release_unmap(qdev, release, &cmd->release_info);
-
-       qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
-       qxl_release_fence_buffer_objects(release);
-       return 0;
-}
-
-static int qxl_crtc_apply_cursor(struct drm_crtc *crtc)
-{
-       struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
-       struct drm_device *dev = crtc->dev;
-       struct qxl_device *qdev = dev->dev_private;
-       struct qxl_cursor_cmd *cmd;
-       struct qxl_release *release;
-       int ret = 0;
-
-       if (!qcrtc->cursor_bo)
-               return 0;
-
-       ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd),
-                                        QXL_RELEASE_CURSOR_CMD,
-                                        &release, NULL);
-       if (ret)
-               return ret;
-
-       ret = qxl_release_list_add(release, qcrtc->cursor_bo);
-       if (ret)
-               goto out_free_release;
-
-       ret = qxl_release_reserve_list(release, false);
-       if (ret)
-               goto out_free_release;
-
-       cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release);
-       cmd->type = QXL_CURSOR_SET;
-       cmd->u.set.position.x = qcrtc->cur_x + qcrtc->hot_spot_x;
-       cmd->u.set.position.y = qcrtc->cur_y + qcrtc->hot_spot_y;
-
-       cmd->u.set.shape = qxl_bo_physical_address(qdev, qcrtc->cursor_bo, 0);
-
-       cmd->u.set.visible = 1;
-       qxl_release_unmap(qdev, release, &cmd->release_info);
-
-       qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
-       qxl_release_fence_buffer_objects(release);
-
-       return ret;
-
-out_free_release:
-       qxl_release_free(qdev, release);
-       return ret;
-}
-
-static int qxl_crtc_cursor_set2(struct drm_crtc *crtc,
-                               struct drm_file *file_priv,
-                               uint32_t handle,
-                               uint32_t width,
-                               uint32_t height, int32_t hot_x, int32_t hot_y)
-{
-       struct drm_device *dev = crtc->dev;
-       struct qxl_device *qdev = dev->dev_private;
-       struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
-       struct drm_gem_object *obj;
-       struct qxl_cursor *cursor;
-       struct qxl_cursor_cmd *cmd;
-       struct qxl_bo *cursor_bo, *user_bo;
-       struct qxl_release *release;
-       void *user_ptr;
-
-       int size = 64*64*4;
-       int ret = 0;
-       if (!handle)
-               return qxl_hide_cursor(qdev);
-
-       obj = drm_gem_object_lookup(file_priv, handle);
-       if (!obj) {
-               DRM_ERROR("cannot find cursor object\n");
-               return -ENOENT;
-       }
-
-       user_bo = gem_to_qxl_bo(obj);
-
-       ret = qxl_bo_pin(user_bo, QXL_GEM_DOMAIN_CPU, NULL);
-       if (ret)
-               goto out_unref;
-
-       ret = qxl_bo_kmap(user_bo, &user_ptr);
-       if (ret)
-               goto out_unpin;
-
-       ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd),
-                                        QXL_RELEASE_CURSOR_CMD,
-                                        &release, NULL);
-       if (ret)
-               goto out_kunmap;
-
-       ret = qxl_alloc_bo_reserved(qdev, release, sizeof(struct qxl_cursor) + size,
-                          &cursor_bo);
-       if (ret)
-               goto out_free_release;
-
-       ret = qxl_release_reserve_list(release, false);
-       if (ret)
-               goto out_free_bo;
-
-       ret = qxl_bo_kmap(cursor_bo, (void **)&cursor);
-       if (ret)
-               goto out_backoff;
-
-       cursor->header.unique = 0;
-       cursor->header.type = SPICE_CURSOR_TYPE_ALPHA;
-       cursor->header.width = 64;
-       cursor->header.height = 64;
-       cursor->header.hot_spot_x = hot_x;
-       cursor->header.hot_spot_y = hot_y;
-       cursor->data_size = size;
-       cursor->chunk.next_chunk = 0;
-       cursor->chunk.prev_chunk = 0;
-       cursor->chunk.data_size = size;
-
-       memcpy(cursor->chunk.data, user_ptr, size);
-
-       qxl_bo_kunmap(cursor_bo);
-
-       qxl_bo_kunmap(user_bo);
-
-       qcrtc->cur_x += qcrtc->hot_spot_x - hot_x;
-       qcrtc->cur_y += qcrtc->hot_spot_y - hot_y;
-       qcrtc->hot_spot_x = hot_x;
-       qcrtc->hot_spot_y = hot_y;
-
-       cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release);
-       cmd->type = QXL_CURSOR_SET;
-       cmd->u.set.position.x = qcrtc->cur_x + qcrtc->hot_spot_x;
-       cmd->u.set.position.y = qcrtc->cur_y + qcrtc->hot_spot_y;
-
-       cmd->u.set.shape = qxl_bo_physical_address(qdev, cursor_bo, 0);
-
-       cmd->u.set.visible = 1;
-       qxl_release_unmap(qdev, release, &cmd->release_info);
-
-       qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
-       qxl_release_fence_buffer_objects(release);
-
-       /* finish with the userspace bo */
-       qxl_bo_unpin(user_bo);
-
-       drm_gem_object_unreference_unlocked(obj);
-
-       qxl_bo_unref (&qcrtc->cursor_bo);
-       qcrtc->cursor_bo = cursor_bo;
-
-       return ret;
-
-out_backoff:
-       qxl_release_backoff_reserve_list(release);
-out_free_bo:
-       qxl_bo_unref(&cursor_bo);
-out_free_release:
-       qxl_release_free(qdev, release);
-out_kunmap:
-       qxl_bo_kunmap(user_bo);
-out_unpin:
-       qxl_bo_unpin(user_bo);
-out_unref:
-       drm_gem_object_unreference_unlocked(obj);
-       return ret;
-}
-
-static int qxl_crtc_cursor_move(struct drm_crtc *crtc,
-                               int x, int y)
-{
-       struct drm_device *dev = crtc->dev;
-       struct qxl_device *qdev = dev->dev_private;
-       struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
-       struct qxl_release *release;
-       struct qxl_cursor_cmd *cmd;
-       int ret;
-
-       ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd), QXL_RELEASE_CURSOR_CMD,
-                                  &release, NULL);
-       if (ret)
-               return ret;
-
-       ret = qxl_release_reserve_list(release, true);
-       if (ret) {
-               qxl_release_free(qdev, release);
-               return ret;
-       }
-
-       qcrtc->cur_x = x;
-       qcrtc->cur_y = y;
-
-       cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release);
-       cmd->type = QXL_CURSOR_MOVE;
-       cmd->u.position.x = qcrtc->cur_x + qcrtc->hot_spot_x;
-       cmd->u.position.y = qcrtc->cur_y + qcrtc->hot_spot_y;
-       qxl_release_unmap(qdev, release, &cmd->release_info);
-
-       qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
-       qxl_release_fence_buffer_objects(release);
-
-       return 0;
-}
-
 static const struct drm_crtc_funcs qxl_crtc_funcs = {
-       .cursor_set2 = qxl_crtc_cursor_set2,
-       .cursor_move = qxl_crtc_cursor_move,
        .set_config = drm_crtc_helper_set_config,
        .destroy = qxl_crtc_destroy,
        .page_flip = qxl_crtc_page_flip,
@@ -723,12 +496,6 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc,
                           bo->surf.stride, bo->surf.format);
                qxl_io_create_primary(qdev, 0, bo);
                bo->is_primary = true;
-
-               ret = qxl_crtc_apply_cursor(crtc);
-               if (ret) {
-                       DRM_ERROR("could not set cursor after modeset");
-                       ret = 0;
-               }
        }
 
        if (bo->is_primary) {
@@ -788,6 +555,188 @@ static const struct drm_crtc_helper_funcs qxl_crtc_helper_funcs = {
        .commit = qxl_crtc_commit,
 };
 
+int qxl_plane_atomic_check(struct drm_plane *plane,
+                          struct drm_plane_state *state)
+{
+       return 0;
+}
+
+static void qxl_cursor_atomic_update(struct drm_plane *plane,
+                                    struct drm_plane_state *old_state)
+{
+       struct drm_device *dev = plane->dev;
+       struct qxl_device *qdev = dev->dev_private;
+       struct drm_framebuffer *fb = plane->state->fb;
+       struct qxl_release *release;
+       struct qxl_cursor_cmd *cmd;
+       struct qxl_cursor *cursor;
+       struct drm_gem_object *obj;
+       struct qxl_bo *cursor_bo, *user_bo = NULL;
+       int ret;
+       void *user_ptr;
+       int size = 64*64*4;
+
+       ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd),
+                                        QXL_RELEASE_CURSOR_CMD,
+                                        &release, NULL);
+
+       cmd = (struct qxl_cursor_cmd *) qxl_release_map(qdev, release);
+
+       if (fb != old_state->fb) {
+               obj = to_qxl_framebuffer(fb)->obj;
+               user_bo = gem_to_qxl_bo(obj);
+
+               /* pinning is done in the prepare/cleanup framevbuffer */
+               ret = qxl_bo_kmap(user_bo, &user_ptr);
+               if (ret)
+                       goto out_free_release;
+
+               ret = qxl_alloc_bo_reserved(qdev, release,
+                                           sizeof(struct qxl_cursor) + size,
+                                           &cursor_bo);
+               if (ret)
+                       goto out_kunmap;
+
+               ret = qxl_release_reserve_list(release, true);
+               if (ret)
+                       goto out_free_bo;
+
+               ret = qxl_bo_kmap(cursor_bo, (void **)&cursor);
+               if (ret)
+                       goto out_backoff;
+
+               cursor->header.unique = 0;
+               cursor->header.type = SPICE_CURSOR_TYPE_ALPHA;
+               cursor->header.width = 64;
+               cursor->header.height = 64;
+               cursor->header.hot_spot_x = fb->hot_x;
+               cursor->header.hot_spot_y = fb->hot_y;
+               cursor->data_size = size;
+               cursor->chunk.next_chunk = 0;
+               cursor->chunk.prev_chunk = 0;
+               cursor->chunk.data_size = size;
+               memcpy(cursor->chunk.data, user_ptr, size);
+               qxl_bo_kunmap(cursor_bo);
+               qxl_bo_kunmap(user_bo);
+
+               cmd->u.set.visible = 1;
+               cmd->u.set.shape = qxl_bo_physical_address(qdev,
+                                                          cursor_bo, 0);
+               cmd->type = QXL_CURSOR_SET;
+       } else {
+
+               ret = qxl_release_reserve_list(release, true);
+               if (ret)
+                       goto out_free_release;
+
+               cmd->type = QXL_CURSOR_MOVE;
+       }
+
+       cmd->u.position.x = plane->state->crtc_x + fb->hot_x;
+       cmd->u.position.y = plane->state->crtc_y + fb->hot_y;
+
+       qxl_release_unmap(qdev, release, &cmd->release_info);
+       qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
+       qxl_release_fence_buffer_objects(release);
+
+       return;
+
+out_backoff:
+       qxl_release_backoff_reserve_list(release);
+out_free_bo:
+       qxl_bo_unref(&cursor_bo);
+out_kunmap:
+       qxl_bo_kunmap(user_bo);
+out_free_release:
+       qxl_release_free(qdev, release);
+       return;
+
+}
+
+void qxl_cursor_atomic_disable(struct drm_plane *plane,
+                              struct drm_plane_state *old_state)
+{
+       struct qxl_device *qdev = plane->dev->dev_private;
+       struct qxl_release *release;
+       struct qxl_cursor_cmd *cmd;
+       int ret;
+
+       ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd),
+                                        QXL_RELEASE_CURSOR_CMD,
+                                        &release, NULL);
+       if (ret)
+               return;
+
+       ret = qxl_release_reserve_list(release, true);
+       if (ret) {
+               qxl_release_free(qdev, release);
+               return;
+       }
+
+       cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release);
+       cmd->type = QXL_CURSOR_HIDE;
+       qxl_release_unmap(qdev, release, &cmd->release_info);
+
+       qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
+       qxl_release_fence_buffer_objects(release);
+}
+
+int qxl_plane_prepare_fb(struct drm_plane *plane,
+                        struct drm_plane_state *new_state)
+{
+       struct drm_gem_object *obj;
+       struct qxl_bo *user_bo;
+       int ret;
+
+       if (!new_state->fb)
+               return 0;
+
+       obj = to_qxl_framebuffer(new_state->fb)->obj;
+       user_bo = gem_to_qxl_bo(obj);
+
+       ret = qxl_bo_pin(user_bo, QXL_GEM_DOMAIN_CPU, NULL);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static void qxl_plane_cleanup_fb(struct drm_plane *plane,
+                                struct drm_plane_state *old_state)
+{
+       struct drm_gem_object *obj;
+       struct qxl_bo *user_bo;
+
+       if (!plane->state->fb) {
+               /* we never executed prepare_fb, so there's nothing to
+                * unpin.
+                */
+               return;
+       }
+
+       obj = to_qxl_framebuffer(plane->state->fb)->obj;
+       user_bo = gem_to_qxl_bo(obj);
+       qxl_bo_unpin(user_bo);
+}
+
+static const uint32_t qxl_cursor_plane_formats[] = {
+       DRM_FORMAT_ARGB8888,
+};
+
+static const struct drm_plane_helper_funcs qxl_cursor_helper_funcs = {
+       .atomic_check = qxl_plane_atomic_check,
+       .atomic_update = qxl_cursor_atomic_update,
+       .atomic_disable = qxl_cursor_atomic_disable,
+       .prepare_fb = qxl_plane_prepare_fb,
+       .cleanup_fb = qxl_plane_cleanup_fb,
+};
+
+static const struct drm_plane_funcs qxl_cursor_plane_funcs = {
+       .update_plane   = drm_plane_helper_update,
+       .disable_plane  = drm_plane_helper_disable,
+       .destroy        = drm_primary_helper_destroy,
+};
+
 static const uint32_t qxl_primary_plane_formats[] = {
        DRM_FORMAT_XRGB8888,
        DRM_FORMAT_ARGB8888,
@@ -814,6 +763,11 @@ static struct drm_plane *qxl_create_plane(struct qxl_device *qdev,
                funcs = &qxl_primary_plane_funcs;
                formats = qxl_primary_plane_formats;
                num_formats = ARRAY_SIZE(qxl_primary_plane_formats);
+       } else if (type == DRM_PLANE_TYPE_CURSOR) {
+               funcs = &qxl_cursor_plane_funcs;
+               formats = qxl_cursor_plane_formats;
+               helper_funcs = &qxl_cursor_helper_funcs;
+               num_formats = ARRAY_SIZE(qxl_cursor_plane_formats);
        } else {
                return ERR_PTR(-EINVAL);
        }
@@ -840,7 +794,7 @@ free_plane:
 static int qdev_crtc_init(struct drm_device *dev, int crtc_id)
 {
        struct qxl_crtc *qxl_crtc;
-       struct drm_plane *primary;
+       struct drm_plane *primary, *cursor;
        struct qxl_device *qdev = dev->dev_private;
        int r;
 
@@ -854,15 +808,24 @@ static int qdev_crtc_init(struct drm_device *dev, int crtc_id)
                goto free_mem;
        }
 
-       r = drm_crtc_init_with_planes(dev, &qxl_crtc->base, primary, NULL,
+       cursor = qxl_create_plane(qdev, 1 << crtc_id, DRM_PLANE_TYPE_CURSOR);
+       if (IS_ERR(cursor)) {
+               r = -ENOMEM;
+               goto clean_primary;
+       }
+
+       r = drm_crtc_init_with_planes(dev, &qxl_crtc->base, primary, cursor,
                                      &qxl_crtc_funcs, NULL);
        if (r)
-               goto clean_primary;
+               goto clean_cursor;
 
        qxl_crtc->index = crtc_id;
        drm_crtc_helper_add(&qxl_crtc->base, &qxl_crtc_helper_funcs);
        return 0;
 
+clean_cursor:
+       drm_plane_cleanup(cursor);
+       kfree(cursor);
 clean_primary:
        drm_plane_cleanup(primary);
        kfree(primary);
@@ -1213,8 +1176,8 @@ int qxl_modeset_init(struct qxl_device *qdev)
        qdev->ddev.mode_config.funcs = (void *)&qxl_mode_funcs;
 
        /* modes will be validated against the framebuffer size */
-       qdev->ddev.mode_config.min_width = 320;
-       qdev->ddev.mode_config.min_height = 200;
+       qdev->ddev.mode_config.min_width = 0;
+       qdev->ddev.mode_config.min_height = 0;
        qdev->ddev.mode_config.max_width = 8192;
        qdev->ddev.mode_config.max_height = 8192;
 
index 647f0926cb508c6d43237d312da45445a7333701..0c313e5636322918a69b9891d65205f5aee99017 100644 (file)
@@ -134,11 +134,6 @@ struct qxl_bo_list {
 struct qxl_crtc {
        struct drm_crtc base;
        int index;
-       int cur_x;
-       int cur_y;
-       int hot_spot_x;
-       int hot_spot_y;
-       struct qxl_bo *cursor_bo;
 };
 
 struct qxl_output {