Merge tag 'drm-misc-fixes-2017-11-02' of git://anongit.freedesktop.org/drm/drm-misc...
authorDave Airlie <airlied@redhat.com>
Mon, 13 Nov 2017 19:17:23 +0000 (05:17 +1000)
committerDave Airlie <airlied@redhat.com>
Mon, 13 Nov 2017 19:17:23 +0000 (05:17 +1000)
Driver Changes:
- qxl: Use a shadow bo as primary and blit to it to fix flicker (Gerd)

* tag 'drm-misc-fixes-2017-11-02' of git://anongit.freedesktop.org/drm/drm-misc:
  qxl: alloc & use shadow for dumb buffers
  drm/qxl: replace QXL_INFO with DRM_DEBUG_DRIVER

drivers/gpu/drm/qxl/qxl_cmd.c
drivers/gpu/drm/qxl/qxl_display.c
drivers/gpu/drm/qxl/qxl_drv.h
drivers/gpu/drm/qxl/qxl_dumb.c
drivers/gpu/drm/qxl/qxl_fb.c
drivers/gpu/drm/qxl/qxl_release.c
drivers/gpu/drm/qxl/qxl_ttm.c

index 74fc9362ecf98fb3efe8a0eb4b26d94aa2d94c41..c0fb52c6d4caaae43753a387f2fa5898019524db 100644 (file)
@@ -219,7 +219,7 @@ int qxl_garbage_collect(struct qxl_device *qdev)
        union qxl_release_info *info;
 
        while (qxl_ring_pop(qdev->release_ring, &id)) {
-               QXL_INFO(qdev, "popped %lld\n", id);
+               DRM_DEBUG_DRIVER("popped %lld\n", id);
                while (id) {
                        release = qxl_release_from_id_locked(qdev, id);
                        if (release == NULL)
@@ -229,8 +229,8 @@ int qxl_garbage_collect(struct qxl_device *qdev)
                        next_id = info->next;
                        qxl_release_unmap(qdev, release, info);
 
-                       QXL_INFO(qdev, "popped %lld, next %lld\n", id,
-                               next_id);
+                       DRM_DEBUG_DRIVER("popped %lld, next %lld\n", id,
+                                        next_id);
 
                        switch (release->type) {
                        case QXL_RELEASE_DRAWABLE:
@@ -248,7 +248,7 @@ int qxl_garbage_collect(struct qxl_device *qdev)
                }
        }
 
-       QXL_INFO(qdev, "%s: %d\n", __func__, i);
+       DRM_DEBUG_DRIVER("%d\n", i);
 
        return i;
 }
@@ -381,17 +381,19 @@ void qxl_io_create_primary(struct qxl_device *qdev,
 {
        struct qxl_surface_create *create;
 
-       QXL_INFO(qdev, "%s: qdev %p, ram_header %p\n", __func__, qdev,
-                qdev->ram_header);
+       DRM_DEBUG_DRIVER("qdev %p, ram_header %p\n", qdev, qdev->ram_header);
        create = &qdev->ram_header->create_surface;
        create->format = bo->surf.format;
        create->width = bo->surf.width;
        create->height = bo->surf.height;
        create->stride = bo->surf.stride;
-       create->mem = qxl_bo_physical_address(qdev, bo, offset);
+       if (bo->shadow) {
+               create->mem = qxl_bo_physical_address(qdev, bo->shadow, offset);
+       } else {
+               create->mem = qxl_bo_physical_address(qdev, bo, offset);
+       }
 
-       QXL_INFO(qdev, "%s: mem = %llx, from %p\n", __func__, create->mem,
-                bo->kptr);
+       DRM_DEBUG_DRIVER("mem = %llx, from %p\n", create->mem, bo->kptr);
 
        create->flags = QXL_SURF_FLAG_KEEP_DATA;
        create->type = QXL_SURF_TYPE_PRIMARY;
@@ -401,7 +403,7 @@ void qxl_io_create_primary(struct qxl_device *qdev,
 
 void qxl_io_memslot_add(struct qxl_device *qdev, uint8_t id)
 {
-       QXL_INFO(qdev, "qxl_memslot_add %d\n", id);
+       DRM_DEBUG_DRIVER("qxl_memslot_add %d\n", id);
        wait_for_io_cmd(qdev, id, QXL_IO_MEMSLOT_ADD_ASYNC);
 }
 
index afbf50d0c08fa1c89c49120717b7a51cb05d5b98..4756b3c9bf2cabadd7811accf1057e61c6426825 100644 (file)
@@ -305,7 +305,9 @@ static const struct drm_crtc_funcs qxl_crtc_funcs = {
 void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb)
 {
        struct qxl_framebuffer *qxl_fb = to_qxl_framebuffer(fb);
+       struct qxl_bo *bo = gem_to_qxl_bo(qxl_fb->obj);
 
+       WARN_ON(bo->shadow);
        drm_gem_object_unreference_unlocked(qxl_fb->obj);
        drm_framebuffer_cleanup(fb);
        kfree(qxl_fb);
@@ -508,6 +510,7 @@ static void qxl_primary_atomic_update(struct drm_plane *plane,
            .x2 = qfb->base.width,
            .y2 = qfb->base.height
        };
+       bool same_shadow = false;
 
        if (old_state->fb) {
                qfb_old = to_qxl_framebuffer(old_state->fb);
@@ -519,15 +522,23 @@ static void qxl_primary_atomic_update(struct drm_plane *plane,
        if (bo == bo_old)
                return;
 
+       if (bo_old && bo_old->shadow && bo->shadow &&
+           bo_old->shadow == bo->shadow) {
+               same_shadow = true;
+       }
+
        if (bo_old && bo_old->is_primary) {
-               qxl_io_destroy_primary(qdev);
+               if (!same_shadow)
+                       qxl_io_destroy_primary(qdev);
                bo_old->is_primary = false;
        }
 
        if (!bo->is_primary) {
-               qxl_io_create_primary(qdev, 0, bo);
+               if (!same_shadow)
+                       qxl_io_create_primary(qdev, 0, bo);
                bo->is_primary = true;
        }
+
        qxl_draw_dirty_fb(qdev, qfb, bo, 0, 0, &norect, 1, 1);
 }
 
@@ -679,8 +690,9 @@ static void qxl_cursor_atomic_disable(struct drm_plane *plane,
 static int qxl_plane_prepare_fb(struct drm_plane *plane,
                                struct drm_plane_state *new_state)
 {
+       struct qxl_device *qdev = plane->dev->dev_private;
        struct drm_gem_object *obj;
-       struct qxl_bo *user_bo;
+       struct qxl_bo *user_bo, *old_bo = NULL;
        int ret;
 
        if (!new_state->fb)
@@ -689,6 +701,32 @@ static int qxl_plane_prepare_fb(struct drm_plane *plane,
        obj = to_qxl_framebuffer(new_state->fb)->obj;
        user_bo = gem_to_qxl_bo(obj);
 
+       if (plane->type == DRM_PLANE_TYPE_PRIMARY &&
+           user_bo->is_dumb && !user_bo->shadow) {
+               if (plane->state->fb) {
+                       obj = to_qxl_framebuffer(plane->state->fb)->obj;
+                       old_bo = gem_to_qxl_bo(obj);
+               }
+               if (old_bo && old_bo->shadow &&
+                   user_bo->gem_base.size == old_bo->gem_base.size &&
+                   plane->state->crtc     == new_state->crtc &&
+                   plane->state->crtc_w   == new_state->crtc_w &&
+                   plane->state->crtc_h   == new_state->crtc_h &&
+                   plane->state->src_x    == new_state->src_x &&
+                   plane->state->src_y    == new_state->src_y &&
+                   plane->state->src_w    == new_state->src_w &&
+                   plane->state->src_h    == new_state->src_h &&
+                   plane->state->rotation == new_state->rotation &&
+                   plane->state->zpos     == new_state->zpos) {
+                       drm_gem_object_get(&old_bo->shadow->gem_base);
+                       user_bo->shadow = old_bo->shadow;
+               } else {
+                       qxl_bo_create(qdev, user_bo->gem_base.size,
+                                     true, true, QXL_GEM_DOMAIN_VRAM, NULL,
+                                     &user_bo->shadow);
+               }
+       }
+
        ret = qxl_bo_pin(user_bo, QXL_GEM_DOMAIN_CPU, NULL);
        if (ret)
                return ret;
@@ -713,6 +751,11 @@ static void qxl_plane_cleanup_fb(struct drm_plane *plane,
        obj = to_qxl_framebuffer(old_state->fb)->obj;
        user_bo = gem_to_qxl_bo(obj);
        qxl_bo_unpin(user_bo);
+
+       if (user_bo->shadow && !user_bo->is_primary) {
+               drm_gem_object_put_unlocked(&user_bo->shadow->gem_base);
+               user_bo->shadow = NULL;
+       }
 }
 
 static const uint32_t qxl_cursor_plane_formats[] = {
index 3397a190733693d649794649e35a7c725a251262..08752c0ffb35b21f1af70d84b9e03783b6aa2f61 100644 (file)
 
 #define QXL_DEBUGFS_MAX_COMPONENTS             32
 
-extern int qxl_log_level;
 extern int qxl_num_crtc;
 extern int qxl_max_ioctls;
 
-enum {
-       QXL_INFO_LEVEL = 1,
-       QXL_DEBUG_LEVEL = 2,
-};
-
-#define QXL_INFO(qdev, fmt, ...) do { \
-               if (qxl_log_level >= QXL_INFO_LEVEL) {  \
-                       qxl_io_log(qdev, fmt, __VA_ARGS__); \
-               }       \
-       } while (0)
-#define QXL_DEBUG(qdev, fmt, ...) do { \
-               if (qxl_log_level >= QXL_DEBUG_LEVEL) { \
-                       qxl_io_log(qdev, fmt, __VA_ARGS__); \
-               }       \
-       } while (0)
-#define QXL_INFO_ONCE(qdev, fmt, ...) do { \
-               static int done;                \
-               if (!done) {                    \
-                       done = 1;                       \
-                       QXL_INFO(qdev, fmt, __VA_ARGS__);       \
-               }                                               \
-       } while (0)
-
 #define DRM_FILE_OFFSET 0x100000000ULL
 #define DRM_FILE_PAGE_OFFSET (DRM_FILE_OFFSET >> PAGE_SHIFT)
 
@@ -113,6 +89,8 @@ struct qxl_bo {
        /* Constant after initialization */
        struct drm_gem_object           gem_base;
        bool is_primary; /* is this now a primary surface */
+       bool is_dumb;
+       struct qxl_bo *shadow;
        bool hw_surf_alloc;
        struct qxl_surface surf;
        uint32_t surface_id;
@@ -351,7 +329,7 @@ int qxl_check_idle(struct qxl_ring *ring);
 static inline void *
 qxl_fb_virtual_address(struct qxl_device *qdev, unsigned long physical)
 {
-       QXL_INFO(qdev, "not implemented (%lu)\n", physical);
+       DRM_DEBUG_DRIVER("not implemented (%lu)\n", physical);
        return 0;
 }
 
index 5e65d5d2d937d5f3db4be062dbf48eab5d116d29..11085ab0137425cae14eda185a4ce86df487e21e 100644 (file)
@@ -63,6 +63,7 @@ int qxl_mode_dumb_create(struct drm_file *file_priv,
                                              &handle);
        if (r)
                return r;
+       qobj->is_dumb = true;
        args->pitch = pitch;
        args->handle = handle;
        return 0;
index 844c4a31ca1305b131e13a158904b0f60e551178..23af3e352673e3b3e4712c68544e8c1d35fa9d00 100644 (file)
@@ -240,18 +240,15 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev,
                return ret;
 
        qbo = gem_to_qxl_bo(gobj);
-       QXL_INFO(qdev, "%s: %dx%d %d\n", __func__, mode_cmd.width,
-                mode_cmd.height, mode_cmd.pitches[0]);
+       DRM_DEBUG_DRIVER("%dx%d %d\n", mode_cmd.width,
+                        mode_cmd.height, mode_cmd.pitches[0]);
 
        shadow = vmalloc(mode_cmd.pitches[0] * mode_cmd.height);
        /* TODO: what's the usual response to memory allocation errors? */
        BUG_ON(!shadow);
-       QXL_INFO(qdev,
-       "surface0 at gpu offset %lld, mmap_offset %lld (virt %p, shadow %p)\n",
-                qxl_bo_gpu_offset(qbo),
-                qxl_bo_mmap_offset(qbo),
-                qbo->kptr,
-                shadow);
+       DRM_DEBUG_DRIVER("surface0 at gpu offset %lld, mmap_offset %lld (virt %p, shadow %p)\n",
+                        qxl_bo_gpu_offset(qbo), qxl_bo_mmap_offset(qbo),
+                        qbo->kptr, shadow);
        size = mode_cmd.pitches[0] * mode_cmd.height;
 
        info = drm_fb_helper_alloc_fbi(&qfbdev->helper);
index e6ec845b5be09a360877e475437872f47e6672c3..a6da6fa6ad5857f39df711731f962bff486f2dc6 100644 (file)
@@ -154,7 +154,7 @@ qxl_release_alloc(struct qxl_device *qdev, int type,
                return handle;
        }
        *ret = release;
-       QXL_INFO(qdev, "allocated release %d\n", handle);
+       DRM_DEBUG_DRIVER("allocated release %d\n", handle);
        release->id = handle;
        return handle;
 }
@@ -179,8 +179,7 @@ void
 qxl_release_free(struct qxl_device *qdev,
                 struct qxl_release *release)
 {
-       QXL_INFO(qdev, "release %d, type %d\n", release->id,
-                release->type);
+       DRM_DEBUG_DRIVER("release %d, type %d\n", release->id, release->type);
 
        if (release->surface_release_id)
                qxl_surface_id_dealloc(qdev, release->surface_release_id);
index 7ecf8a4b9fe6ab5bdbcec36035b05d0fa8441a4c..ab48238753118862e4d54d559404f93dc91c9eb1 100644 (file)
@@ -136,8 +136,8 @@ int qxl_mmap(struct file *filp, struct vm_area_struct *vma)
                 "filp->private_data->minor->dev->dev_private == NULL\n");
                return -EINVAL;
        }
-       QXL_INFO(qdev, "%s: filp->private_data = 0x%p, vma->vm_pgoff = %lx\n",
-                __func__, filp->private_data, vma->vm_pgoff);
+       DRM_DEBUG_DRIVER("filp->private_data = 0x%p, vma->vm_pgoff = %lx\n",
+                 filp->private_data, vma->vm_pgoff);
 
        r = ttm_bo_mmap(filp, vma, &qdev->mman.bdev);
        if (unlikely(r != 0))