c5708d5
From 56cbcb6c41932b19ef0d838f1ff25a662a2e403d Mon Sep 17 00:00:00 2001
d779975
From: Gerd Hoffmann <kraxel@redhat.com>
c5708d5
Date: Thu, 19 Oct 2017 08:21:49 +0200
c5708d5
Subject: [PATCH] drm/qxl: replace QXL_INFO with DRM_DEBUG_DRIVER
d779975
c5708d5
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
c5708d5
Reviewed-by: Dave Airlie <airlied@redhat.com>
c5708d5
Link: http://patchwork.freedesktop.org/patch/msgid/20171019062150.28090-2-kraxel@redhat.com
c5708d5
---
c5708d5
 drivers/gpu/drm/qxl/qxl_cmd.c     | 16 +++++++---------
c5708d5
 drivers/gpu/drm/qxl/qxl_drv.h     | 26 +-------------------------
c5708d5
 drivers/gpu/drm/qxl/qxl_fb.c      | 13 +++++--------
c5708d5
 drivers/gpu/drm/qxl/qxl_release.c |  5 ++---
c5708d5
 drivers/gpu/drm/qxl/qxl_ttm.c     |  4 ++--
c5708d5
 5 files changed, 17 insertions(+), 47 deletions(-)
d779975
c5708d5
diff --git a/drivers/gpu/drm/qxl/qxl_cmd.c b/drivers/gpu/drm/qxl/qxl_cmd.c
c5708d5
index 74fc9362ecf9..8ec53d5abd62 100644
c5708d5
--- a/drivers/gpu/drm/qxl/qxl_cmd.c
c5708d5
+++ b/drivers/gpu/drm/qxl/qxl_cmd.c
c5708d5
@@ -219,7 +219,7 @@ int qxl_garbage_collect(struct qxl_device *qdev)
c5708d5
 	union qxl_release_info *info;
d779975
c5708d5
 	while (qxl_ring_pop(qdev->release_ring, &id)) {
c5708d5
-		QXL_INFO(qdev, "popped %lld\n", id);
c5708d5
+		DRM_DEBUG_DRIVER("popped %lld\n", id);
c5708d5
 		while (id) {
c5708d5
 			release = qxl_release_from_id_locked(qdev, id);
c5708d5
 			if (release == NULL)
c5708d5
@@ -229,8 +229,8 @@ int qxl_garbage_collect(struct qxl_device *qdev)
c5708d5
 			next_id = info->next;
c5708d5
 			qxl_release_unmap(qdev, release, info);
d779975
c5708d5
-			QXL_INFO(qdev, "popped %lld, next %lld\n", id,
c5708d5
-				next_id);
c5708d5
+			DRM_DEBUG_DRIVER("popped %lld, next %lld\n", id,
c5708d5
+					 next_id);
d779975
c5708d5
 			switch (release->type) {
c5708d5
 			case QXL_RELEASE_DRAWABLE:
c5708d5
@@ -248,7 +248,7 @@ int qxl_garbage_collect(struct qxl_device *qdev)
c5708d5
 		}
d779975
 	}
c5708d5
c5708d5
-	QXL_INFO(qdev, "%s: %d\n", __func__, i);
c5708d5
+	DRM_DEBUG_DRIVER("%d\n", i);
c5708d5
c5708d5
 	return i;
d779975
 }
c5708d5
@@ -381,8 +381,7 @@ void qxl_io_create_primary(struct qxl_device *qdev,
d779975
 {
c5708d5
 	struct qxl_surface_create *create;
c5708d5
c5708d5
-	QXL_INFO(qdev, "%s: qdev %p, ram_header %p\n", __func__, qdev,
c5708d5
-		 qdev->ram_header);
c5708d5
+	DRM_DEBUG_DRIVER("qdev %p, ram_header %p\n", qdev, qdev->ram_header);
c5708d5
 	create = &qdev->ram_header->create_surface;
c5708d5
 	create->format = bo->surf.format;
c5708d5
 	create->width = bo->surf.width;
c5708d5
@@ -390,8 +389,7 @@ void qxl_io_create_primary(struct qxl_device *qdev,
c5708d5
 	create->stride = bo->surf.stride;
c5708d5
 	create->mem = qxl_bo_physical_address(qdev, bo, offset);
c5708d5
c5708d5
-	QXL_INFO(qdev, "%s: mem = %llx, from %p\n", __func__, create->mem,
c5708d5
-		 bo->kptr);
c5708d5
+	DRM_DEBUG_DRIVER("mem = %llx, from %p\n", create->mem, bo->kptr);
c5708d5
c5708d5
 	create->flags = QXL_SURF_FLAG_KEEP_DATA;
c5708d5
 	create->type = QXL_SURF_TYPE_PRIMARY;
c5708d5
@@ -401,7 +399,7 @@ void qxl_io_create_primary(struct qxl_device *qdev,
c5708d5
c5708d5
 void qxl_io_memslot_add(struct qxl_device *qdev, uint8_t id)
c5708d5
 {
c5708d5
-	QXL_INFO(qdev, "qxl_memslot_add %d\n", id);
c5708d5
+	DRM_DEBUG_DRIVER("qxl_memslot_add %d\n", id);
c5708d5
 	wait_for_io_cmd(qdev, id, QXL_IO_MEMSLOT_ADD_ASYNC);
d779975
 }
d779975
c5708d5
diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
c5708d5
index 3397a1907336..d707b351875c 100644
c5708d5
--- a/drivers/gpu/drm/qxl/qxl_drv.h
c5708d5
+++ b/drivers/gpu/drm/qxl/qxl_drv.h
c5708d5
@@ -62,33 +62,9 @@
cbd54ab
c5708d5
 #define QXL_DEBUGFS_MAX_COMPONENTS		32
cbd54ab
c5708d5
-extern int qxl_log_level;
c5708d5
 extern int qxl_num_crtc;
c5708d5
 extern int qxl_max_ioctls;
cbd54ab
c5708d5
-enum {
c5708d5
-	QXL_INFO_LEVEL = 1,
c5708d5
-	QXL_DEBUG_LEVEL = 2,
c5708d5
-};
c5708d5
-
c5708d5
-#define QXL_INFO(qdev, fmt, ...) do { \
c5708d5
-		if (qxl_log_level >= QXL_INFO_LEVEL) {	\
c5708d5
-			qxl_io_log(qdev, fmt, __VA_ARGS__); \
c5708d5
-		}	\
c5708d5
-	} while (0)
c5708d5
-#define QXL_DEBUG(qdev, fmt, ...) do { \
c5708d5
-		if (qxl_log_level >= QXL_DEBUG_LEVEL) {	\
c5708d5
-			qxl_io_log(qdev, fmt, __VA_ARGS__); \
c5708d5
-		}	\
c5708d5
-	} while (0)
c5708d5
-#define QXL_INFO_ONCE(qdev, fmt, ...) do { \
c5708d5
-		static int done;		\
c5708d5
-		if (!done) {			\
c5708d5
-			done = 1;			\
c5708d5
-			QXL_INFO(qdev, fmt, __VA_ARGS__);	\
c5708d5
-		}						\
c5708d5
-	} while (0)
c5708d5
-
c5708d5
 #define DRM_FILE_OFFSET 0x100000000ULL
c5708d5
 #define DRM_FILE_PAGE_OFFSET (DRM_FILE_OFFSET >> PAGE_SHIFT)
c5708d5
c5708d5
@@ -351,7 +327,7 @@ int qxl_check_idle(struct qxl_ring *ring);
c5708d5
 static inline void *
c5708d5
 qxl_fb_virtual_address(struct qxl_device *qdev, unsigned long physical)
c5708d5
 {
c5708d5
-	QXL_INFO(qdev, "not implemented (%lu)\n", physical);
c5708d5
+	DRM_DEBUG_DRIVER("not implemented (%lu)\n", physical);
c5708d5
 	return 0;
c5708d5
 }
c5708d5
c5708d5
diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c
c5708d5
index 844c4a31ca13..23af3e352673 100644
c5708d5
--- a/drivers/gpu/drm/qxl/qxl_fb.c
c5708d5
+++ b/drivers/gpu/drm/qxl/qxl_fb.c
c5708d5
@@ -240,18 +240,15 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev,
c5708d5
 		return ret;
c5708d5
c5708d5
 	qbo = gem_to_qxl_bo(gobj);
c5708d5
-	QXL_INFO(qdev, "%s: %dx%d %d\n", __func__, mode_cmd.width,
c5708d5
-		 mode_cmd.height, mode_cmd.pitches[0]);
c5708d5
+	DRM_DEBUG_DRIVER("%dx%d %d\n", mode_cmd.width,
c5708d5
+			 mode_cmd.height, mode_cmd.pitches[0]);
c5708d5
c5708d5
 	shadow = vmalloc(mode_cmd.pitches[0] * mode_cmd.height);
c5708d5
 	/* TODO: what's the usual response to memory allocation errors? */
c5708d5
 	BUG_ON(!shadow);
c5708d5
-	QXL_INFO(qdev,
c5708d5
-	"surface0 at gpu offset %lld, mmap_offset %lld (virt %p, shadow %p)\n",
c5708d5
-		 qxl_bo_gpu_offset(qbo),
c5708d5
-		 qxl_bo_mmap_offset(qbo),
c5708d5
-		 qbo->kptr,
c5708d5
-		 shadow);
c5708d5
+	DRM_DEBUG_DRIVER("surface0 at gpu offset %lld, mmap_offset %lld (virt %p, shadow %p)\n",
c5708d5
+			 qxl_bo_gpu_offset(qbo), qxl_bo_mmap_offset(qbo),
c5708d5
+			 qbo->kptr, shadow);
c5708d5
 	size = mode_cmd.pitches[0] * mode_cmd.height;
c5708d5
c5708d5
 	info = drm_fb_helper_alloc_fbi(&qfbdev->helper);
c5708d5
diff --git a/drivers/gpu/drm/qxl/qxl_release.c b/drivers/gpu/drm/qxl/qxl_release.c
c5708d5
index e6ec845b5be0..a6da6fa6ad58 100644
c5708d5
--- a/drivers/gpu/drm/qxl/qxl_release.c
c5708d5
+++ b/drivers/gpu/drm/qxl/qxl_release.c
c5708d5
@@ -154,7 +154,7 @@ qxl_release_alloc(struct qxl_device *qdev, int type,
c5708d5
 		return handle;
cbd54ab
 	}
c5708d5
 	*ret = release;
c5708d5
-	QXL_INFO(qdev, "allocated release %d\n", handle);
c5708d5
+	DRM_DEBUG_DRIVER("allocated release %d\n", handle);
c5708d5
 	release->id = handle;
c5708d5
 	return handle;
cbd54ab
 }
c5708d5
@@ -179,8 +179,7 @@ void
c5708d5
 qxl_release_free(struct qxl_device *qdev,
c5708d5
 		 struct qxl_release *release)
c5708d5
 {
c5708d5
-	QXL_INFO(qdev, "release %d, type %d\n", release->id,
c5708d5
-		 release->type);
c5708d5
+	DRM_DEBUG_DRIVER("release %d, type %d\n", release->id, release->type);
c5708d5
c5708d5
 	if (release->surface_release_id)
c5708d5
 		qxl_surface_id_dealloc(qdev, release->surface_release_id);
c5708d5
diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c
c5708d5
index 7ecf8a4b9fe6..ab4823875311 100644
c5708d5
--- a/drivers/gpu/drm/qxl/qxl_ttm.c
c5708d5
+++ b/drivers/gpu/drm/qxl/qxl_ttm.c
c5708d5
@@ -136,8 +136,8 @@ int qxl_mmap(struct file *filp, struct vm_area_struct *vma)
c5708d5
 		 "filp->private_data->minor->dev->dev_private == NULL\n");
c5708d5
 		return -EINVAL;
c5708d5
 	}
c5708d5
-	QXL_INFO(qdev, "%s: filp->private_data = 0x%p, vma->vm_pgoff = %lx\n",
c5708d5
-		 __func__, filp->private_data, vma->vm_pgoff);
c5708d5
+	DRM_DEBUG_DRIVER("filp->private_data = 0x%p, vma->vm_pgoff = %lx\n",
c5708d5
+		  filp->private_data, vma->vm_pgoff);
c5708d5
c5708d5
 	r = ttm_bo_mmap(filp, vma, &qdev->mman.bdev);
c5708d5
 	if (unlikely(r != 0))
cbd54ab
-- 
c5708d5
2.14.3
cbd54ab
c5708d5
From 62676d10b483a2ff6e8b08c5e7c7d63a831343f5 Mon Sep 17 00:00:00 2001
d779975
From: Gerd Hoffmann <kraxel@redhat.com>
c5708d5
Date: Thu, 19 Oct 2017 08:21:50 +0200
c5708d5
Subject: [PATCH] qxl: alloc & use shadow for dumb buffers
d779975
d779975
This patch changes the way the primary surface is used for dumb
d779975
framebuffers.  Instead of configuring the bo itself as primary surface
d779975
a shadow bo is created and used instead.  Framebuffers can share the
d779975
shadow bo in case they have the same format and resolution.
d779975
d779975
On atomic plane updates we don't have to update the primary surface in
d779975
case we pageflip from one framebuffer to another framebuffer which
d779975
shares the same shadow.  This in turn avoids the flicker caused by the
d779975
primary-destroy + primary-create cycle, which is very annonying when
d779975
running wayland on qxl.
d779975
d779975
The qxl driver never actually writes to the shadow bo.  It sends qxl
d779975
blit commands which update it though, and the spice server might
d779975
actually execute them (and thereby write to the shadow) in case the
d779975
local rendering is kicked for some reason.  This happens for example in
d779975
case qemu is asked to write out a dump of the guest display (screendump
d779975
monitor command).
d779975
d779975
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
c5708d5
Reviewed-by: Dave Airlie <airlied@redhat.com>
c5708d5
Link: http://patchwork.freedesktop.org/patch/msgid/20171019062150.28090-3-kraxel@redhat.com
d779975
---
d779975
 drivers/gpu/drm/qxl/qxl_cmd.c     |  6 ++++-
d779975
 drivers/gpu/drm/qxl/qxl_display.c | 49 ++++++++++++++++++++++++++++++++++++---
d779975
 drivers/gpu/drm/qxl/qxl_drv.h     |  2 ++
d779975
 drivers/gpu/drm/qxl/qxl_dumb.c    |  1 +
d779975
 4 files changed, 54 insertions(+), 4 deletions(-)
d779975
d779975
diff --git a/drivers/gpu/drm/qxl/qxl_cmd.c b/drivers/gpu/drm/qxl/qxl_cmd.c
c5708d5
index 8ec53d5abd62..c0fb52c6d4ca 100644
d779975
--- a/drivers/gpu/drm/qxl/qxl_cmd.c
d779975
+++ b/drivers/gpu/drm/qxl/qxl_cmd.c
c5708d5
@@ -387,7 +387,11 @@ void qxl_io_create_primary(struct qxl_device *qdev,
d779975
 	create->width = bo->surf.width;
d779975
 	create->height = bo->surf.height;
d779975
 	create->stride = bo->surf.stride;
d779975
-	create->mem = qxl_bo_physical_address(qdev, bo, offset);
d779975
+	if (bo->shadow) {
d779975
+		create->mem = qxl_bo_physical_address(qdev, bo->shadow, offset);
d779975
+	} else {
d779975
+		create->mem = qxl_bo_physical_address(qdev, bo, offset);
d779975
+	}
1fb65ff
c5708d5
 	DRM_DEBUG_DRIVER("mem = %llx, from %p\n", create->mem, bo->kptr);
c5708d5
d779975
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
c5708d5
index afbf50d0c08f..4756b3c9bf2c 100644
d779975
--- a/drivers/gpu/drm/qxl/qxl_display.c
d779975
+++ b/drivers/gpu/drm/qxl/qxl_display.c
d779975
@@ -305,7 +305,9 @@ static const struct drm_crtc_funcs qxl_crtc_funcs = {
d779975
 void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb)
d779975
 {
d779975
 	struct qxl_framebuffer *qxl_fb = to_qxl_framebuffer(fb);
d779975
+	struct qxl_bo *bo = gem_to_qxl_bo(qxl_fb->obj);
1fb65ff
d779975
+	WARN_ON(bo->shadow);
d779975
 	drm_gem_object_unreference_unlocked(qxl_fb->obj);
d779975
 	drm_framebuffer_cleanup(fb);
d779975
 	kfree(qxl_fb);
c5708d5
@@ -508,6 +510,7 @@ static void qxl_primary_atomic_update(struct drm_plane *plane,
d779975
 	    .x2 = qfb->base.width,
d779975
 	    .y2 = qfb->base.height
d779975
 	};
d779975
+	bool same_shadow = false;
1fb65ff
d779975
 	if (old_state->fb) {
d779975
 		qfb_old = to_qxl_framebuffer(old_state->fb);
c5708d5
@@ -519,15 +522,23 @@ static void qxl_primary_atomic_update(struct drm_plane *plane,
d779975
 	if (bo == bo_old)
d779975
 		return;
1fb65ff
d779975
+	if (bo_old && bo_old->shadow && bo->shadow &&
d779975
+	    bo_old->shadow == bo->shadow) {
d779975
+		same_shadow = true;
d779975
+	}
d779975
+
d779975
 	if (bo_old && bo_old->is_primary) {
d779975
-		qxl_io_destroy_primary(qdev);
d779975
+		if (!same_shadow)
d779975
+			qxl_io_destroy_primary(qdev);
d779975
 		bo_old->is_primary = false;
d779975
 	}
1fb65ff
d779975
 	if (!bo->is_primary) {
d779975
-		qxl_io_create_primary(qdev, 0, bo);
d779975
+		if (!same_shadow)
d779975
+			qxl_io_create_primary(qdev, 0, bo);
d779975
 		bo->is_primary = true;
d779975
 	}
d779975
+
d779975
 	qxl_draw_dirty_fb(qdev, qfb, bo, 0, 0, &norect, 1, 1);
d779975
 }
1fb65ff
c5708d5
@@ -679,8 +690,9 @@ static void qxl_cursor_atomic_disable(struct drm_plane *plane,
c5708d5
 static int qxl_plane_prepare_fb(struct drm_plane *plane,
c5708d5
 				struct drm_plane_state *new_state)
d779975
 {
d779975
+	struct qxl_device *qdev = plane->dev->dev_private;
d779975
 	struct drm_gem_object *obj;
d779975
-	struct qxl_bo *user_bo;
d779975
+	struct qxl_bo *user_bo, *old_bo = NULL;
d779975
 	int ret;
1fb65ff
d779975
 	if (!new_state->fb)
c5708d5
@@ -689,6 +701,32 @@ static int qxl_plane_prepare_fb(struct drm_plane *plane,
d779975
 	obj = to_qxl_framebuffer(new_state->fb)->obj;
d779975
 	user_bo = gem_to_qxl_bo(obj);
1fb65ff
d779975
+	if (plane->type == DRM_PLANE_TYPE_PRIMARY &&
d779975
+	    user_bo->is_dumb && !user_bo->shadow) {
d779975
+		if (plane->state->fb) {
d779975
+			obj = to_qxl_framebuffer(plane->state->fb)->obj;
d779975
+			old_bo = gem_to_qxl_bo(obj);
d779975
+		}
d779975
+		if (old_bo && old_bo->shadow &&
d779975
+		    user_bo->gem_base.size == old_bo->gem_base.size &&
d779975
+		    plane->state->crtc     == new_state->crtc &&
d779975
+		    plane->state->crtc_w   == new_state->crtc_w &&
d779975
+		    plane->state->crtc_h   == new_state->crtc_h &&
d779975
+		    plane->state->src_x    == new_state->src_x &&
d779975
+		    plane->state->src_y    == new_state->src_y &&
d779975
+		    plane->state->src_w    == new_state->src_w &&
d779975
+		    plane->state->src_h    == new_state->src_h &&
d779975
+		    plane->state->rotation == new_state->rotation &&
d779975
+		    plane->state->zpos     == new_state->zpos) {
d779975
+			drm_gem_object_get(&old_bo->shadow->gem_base);
d779975
+			user_bo->shadow = old_bo->shadow;
d779975
+		} else {
d779975
+			qxl_bo_create(qdev, user_bo->gem_base.size,
d779975
+				      true, true, QXL_GEM_DOMAIN_VRAM, NULL,
d779975
+				      &user_bo->shadow);
d779975
+		}
d779975
+	}
d779975
+
d779975
 	ret = qxl_bo_pin(user_bo, QXL_GEM_DOMAIN_CPU, NULL);
d779975
 	if (ret)
d779975
 		return ret;
c5708d5
@@ -713,6 +751,11 @@ static void qxl_plane_cleanup_fb(struct drm_plane *plane,
d779975
 	obj = to_qxl_framebuffer(old_state->fb)->obj;
d779975
 	user_bo = gem_to_qxl_bo(obj);
d779975
 	qxl_bo_unpin(user_bo);
d779975
+
d779975
+	if (user_bo->shadow && !user_bo->is_primary) {
d779975
+		drm_gem_object_put_unlocked(&user_bo->shadow->gem_base);
d779975
+		user_bo->shadow = NULL;
d779975
+	}
d779975
 }
1fb65ff
d779975
 static const uint32_t qxl_cursor_plane_formats[] = {
d779975
diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
c5708d5
index d707b351875c..08752c0ffb35 100644
d779975
--- a/drivers/gpu/drm/qxl/qxl_drv.h
d779975
+++ b/drivers/gpu/drm/qxl/qxl_drv.h
c5708d5
@@ -89,6 +89,8 @@ struct qxl_bo {
d779975
 	/* Constant after initialization */
d779975
 	struct drm_gem_object		gem_base;
d779975
 	bool is_primary; /* is this now a primary surface */
d779975
+	bool is_dumb;
d779975
+	struct qxl_bo *shadow;
d779975
 	bool hw_surf_alloc;
d779975
 	struct qxl_surface surf;
d779975
 	uint32_t surface_id;
d779975
diff --git a/drivers/gpu/drm/qxl/qxl_dumb.c b/drivers/gpu/drm/qxl/qxl_dumb.c
c5708d5
index 5e65d5d2d937..11085ab01374 100644
d779975
--- a/drivers/gpu/drm/qxl/qxl_dumb.c
d779975
+++ b/drivers/gpu/drm/qxl/qxl_dumb.c
d779975
@@ -63,6 +63,7 @@ int qxl_mode_dumb_create(struct drm_file *file_priv,
d779975
 					      &handle);
d779975
 	if (r)
d779975
 		return r;
d779975
+	qobj->is_dumb = true;
d779975
 	args->pitch = pitch;
d779975
 	args->handle = handle;
d779975
 	return 0;
d779975
-- 
c5708d5
2.14.3
d779975