drm/vkms: add overlay support
authorMelissa Wen <melissa.srw@gmail.com>
Sat, 24 Apr 2021 08:26:10 +0000 (05:26 -0300)
committerMelissa Wen <melissa.srw@gmail.com>
Thu, 29 Apr 2021 21:53:05 +0000 (18:53 -0300)
Add support to overlay plane, in addition to primary and cursor
planes. In this approach, the plane composition still requires an
active primary plane and planes are composed associatively in the
order: (primary <- overlay) <- cursor

It enables to run the following IGT tests successfully:
- kms_plane_cursor:
  - pipe-A-[overlay, primary, viewport]-size-[64, 128, 256]
- kms_atomic:
  - plane-overlay-legacy
and preserves the successful execution of kms_cursor_crc,
kms_writeback and kms_flip

Signed-off-by: Melissa Wen <melissa.srw@gmail.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: https://patchwork.freedesktop.org/patch/msgid/8261bf93d8a0e3ffaf81d8e7c9b3e9c229116be3.1619250933.git.melissa.srw@gmail.com
drivers/gpu/drm/vkms/vkms_composer.c
drivers/gpu/drm/vkms/vkms_drv.c
drivers/gpu/drm/vkms/vkms_drv.h
drivers/gpu/drm/vkms/vkms_output.c
drivers/gpu/drm/vkms/vkms_plane.c

index 48b1cf0f4ec8882f374606afa952b7ce0d319724..e49523866e1d4338cc047c0ab7ca95807dd45799 100644 (file)
@@ -176,11 +176,12 @@ static void compose_plane(struct vkms_composer *primary_composer,
 
 static int compose_active_planes(void **vaddr_out,
                                 struct vkms_composer *primary_composer,
-                                struct vkms_composer *cursor_composer)
+                                struct vkms_crtc_state *crtc_state)
 {
        struct drm_framebuffer *fb = &primary_composer->fb;
        struct drm_gem_object *gem_obj = drm_gem_fb_get_obj(fb, 0);
        struct drm_gem_shmem_object *shmem_obj = to_drm_gem_shmem_obj(gem_obj);
+       int i;
 
        if (!*vaddr_out) {
                *vaddr_out = kzalloc(shmem_obj->base.size, GFP_KERNEL);
@@ -195,8 +196,14 @@ static int compose_active_planes(void **vaddr_out,
 
        memcpy(*vaddr_out, shmem_obj->vaddr, shmem_obj->base.size);
 
-       if (cursor_composer)
-               compose_plane(primary_composer, cursor_composer, *vaddr_out);
+       /* If there are other planes besides primary, we consider the active
+        * planes should be in z-order and compose them associatively:
+        * ((primary <- overlay) <- cursor)
+        */
+       for (i = 1; i < crtc_state->num_active_planes; i++)
+               compose_plane(primary_composer,
+                             crtc_state->active_planes[i]->composer,
+                             *vaddr_out);
 
        return 0;
 }
@@ -218,7 +225,7 @@ void vkms_composer_worker(struct work_struct *work)
        struct drm_crtc *crtc = crtc_state->base.crtc;
        struct vkms_output *out = drm_crtc_to_vkms_output(crtc);
        struct vkms_composer *primary_composer = NULL;
-       struct vkms_composer *cursor_composer = NULL;
+       struct vkms_plane_state *act_plane = NULL;
        bool crc_pending, wb_pending;
        void *vaddr_out = NULL;
        u32 crc32 = 0;
@@ -242,11 +249,11 @@ void vkms_composer_worker(struct work_struct *work)
        if (!crc_pending)
                return;
 
-       if (crtc_state->num_active_planes >= 1)
-               primary_composer = crtc_state->active_planes[0]->composer;
-
-       if (crtc_state->num_active_planes == 2)
-               cursor_composer = crtc_state->active_planes[1]->composer;
+       if (crtc_state->num_active_planes >= 1) {
+               act_plane = crtc_state->active_planes[0];
+               if (act_plane->base.plane->type == DRM_PLANE_TYPE_PRIMARY)
+                       primary_composer = act_plane->composer;
+       }
 
        if (!primary_composer)
                return;
@@ -255,7 +262,7 @@ void vkms_composer_worker(struct work_struct *work)
                vaddr_out = crtc_state->active_writeback;
 
        ret = compose_active_planes(&vaddr_out, primary_composer,
-                                   cursor_composer);
+                                   crtc_state);
        if (ret) {
                if (ret == -EINVAL && !wb_pending)
                        kfree(vaddr_out);
index 2173b82606f661313870aa0643bb505ba79400d3..027ffe75944027d5552884a69d654c76dd4ed986 100644 (file)
@@ -44,6 +44,10 @@ static bool enable_writeback = true;
 module_param_named(enable_writeback, enable_writeback, bool, 0444);
 MODULE_PARM_DESC(enable_writeback, "Enable/Disable writeback connector support");
 
+static bool enable_overlay;
+module_param_named(enable_overlay, enable_overlay, bool, 0444);
+MODULE_PARM_DESC(enable_overlay, "Enable/Disable overlay support");
+
 DEFINE_DRM_GEM_FOPS(vkms_driver_fops);
 
 static void vkms_release(struct drm_device *dev)
@@ -198,6 +202,7 @@ static int __init vkms_init(void)
 
        config->cursor = enable_cursor;
        config->writeback = enable_writeback;
+       config->overlay = enable_overlay;
 
        return vkms_create(config);
 }
index 70fb7962161760bad2e714b1c37175dc5493290f..ac8c9c2fa4ed973a8e5586f351ca6a8823af8863 100644 (file)
@@ -89,6 +89,7 @@ struct vkms_device;
 struct vkms_config {
        bool writeback;
        bool cursor;
+       bool overlay;
        /* only set when instantiated */
        struct vkms_device *dev;
 };
index 6979fbc7f82127e0d2da296c2925168a97aec8ed..04406bd3ff02a003e672c3e63f2c1cf307085750 100644 (file)
@@ -39,7 +39,7 @@ int vkms_output_init(struct vkms_device *vkmsdev, int index)
        struct drm_connector *connector = &output->connector;
        struct drm_encoder *encoder = &output->encoder;
        struct drm_crtc *crtc = &output->crtc;
-       struct vkms_plane *primary, *cursor = NULL;
+       struct vkms_plane *primary, *cursor = NULL, *overlay = NULL;
        int ret;
        int writeback;
 
@@ -47,6 +47,15 @@ int vkms_output_init(struct vkms_device *vkmsdev, int index)
        if (IS_ERR(primary))
                return PTR_ERR(primary);
 
+       if (vkmsdev->config->overlay) {
+               overlay = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_OVERLAY, index);
+               if (IS_ERR(overlay))
+                       return PTR_ERR(overlay);
+
+               if (!overlay->base.possible_crtcs)
+                       overlay->base.possible_crtcs = drm_crtc_mask(crtc);
+       }
+
        if (vkmsdev->config->cursor) {
                cursor = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_CURSOR, index);
                if (IS_ERR(cursor))
index da4251aff67fa15e3cedfcf6e58205ba35f70c5a..107521ace597ad635b1cbbcc1ea151818a9d9c5a 100644 (file)
@@ -133,7 +133,7 @@ static int vkms_plane_atomic_check(struct drm_plane *plane,
        if (IS_ERR(crtc_state))
                return PTR_ERR(crtc_state);
 
-       if (plane->type == DRM_PLANE_TYPE_CURSOR)
+       if (plane->type != DRM_PLANE_TYPE_PRIMARY)
                can_position = true;
 
        ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
@@ -200,14 +200,23 @@ struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
        const u32 *formats;
        int nformats;
 
-       if (type == DRM_PLANE_TYPE_CURSOR) {
+       switch (type) {
+       case DRM_PLANE_TYPE_PRIMARY:
+               formats = vkms_formats;
+               nformats = ARRAY_SIZE(vkms_formats);
+               funcs = &vkms_primary_helper_funcs;
+               break;
+       case DRM_PLANE_TYPE_CURSOR:
+       case DRM_PLANE_TYPE_OVERLAY:
                formats = vkms_plane_formats;
                nformats = ARRAY_SIZE(vkms_plane_formats);
                funcs = &vkms_primary_helper_funcs;
-       } else {
+               break;
+       default:
                formats = vkms_formats;
                nformats = ARRAY_SIZE(vkms_formats);
                funcs = &vkms_primary_helper_funcs;
+               break;
        }
 
        plane = drmm_universal_plane_alloc(dev, struct vkms_plane, base, 1 << index,