aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2017-11-13 14:17:23 -0500
committerDave Airlie <airlied@redhat.com>2017-11-13 14:17:23 -0500
commitfee25cb965f9e1360f845a7a3fb16bca1bbadc84 (patch)
treee80b01083c1a41379f62681b3cf00fd508d80c41 /drivers/gpu
parente7e62c7ef382f5db0de5e492e558efc9c3d60943 (diff)
parent62676d10b483a2ff6e8b08c5e7c7d63a831343f5 (diff)
Merge tag 'drm-misc-fixes-2017-11-02' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
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
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/qxl/qxl_cmd.c22
-rw-r--r--drivers/gpu/drm/qxl/qxl_display.c49
-rw-r--r--drivers/gpu/drm/qxl/qxl_drv.h28
-rw-r--r--drivers/gpu/drm/qxl/qxl_dumb.c1
-rw-r--r--drivers/gpu/drm/qxl/qxl_fb.c13
-rw-r--r--drivers/gpu/drm/qxl/qxl_release.c5
-rw-r--r--drivers/gpu/drm/qxl/qxl_ttm.c4
7 files changed, 71 insertions, 51 deletions
diff --git a/drivers/gpu/drm/qxl/qxl_cmd.c b/drivers/gpu/drm/qxl/qxl_cmd.c
index 74fc9362ecf9..c0fb52c6d4ca 100644
--- a/drivers/gpu/drm/qxl/qxl_cmd.c
+++ b/drivers/gpu/drm/qxl/qxl_cmd.c
@@ -219,7 +219,7 @@ int qxl_garbage_collect(struct qxl_device *qdev)
219 union qxl_release_info *info; 219 union qxl_release_info *info;
220 220
221 while (qxl_ring_pop(qdev->release_ring, &id)) { 221 while (qxl_ring_pop(qdev->release_ring, &id)) {
222 QXL_INFO(qdev, "popped %lld\n", id); 222 DRM_DEBUG_DRIVER("popped %lld\n", id);
223 while (id) { 223 while (id) {
224 release = qxl_release_from_id_locked(qdev, id); 224 release = qxl_release_from_id_locked(qdev, id);
225 if (release == NULL) 225 if (release == NULL)
@@ -229,8 +229,8 @@ int qxl_garbage_collect(struct qxl_device *qdev)
229 next_id = info->next; 229 next_id = info->next;
230 qxl_release_unmap(qdev, release, info); 230 qxl_release_unmap(qdev, release, info);
231 231
232 QXL_INFO(qdev, "popped %lld, next %lld\n", id, 232 DRM_DEBUG_DRIVER("popped %lld, next %lld\n", id,
233 next_id); 233 next_id);
234 234
235 switch (release->type) { 235 switch (release->type) {
236 case QXL_RELEASE_DRAWABLE: 236 case QXL_RELEASE_DRAWABLE:
@@ -248,7 +248,7 @@ int qxl_garbage_collect(struct qxl_device *qdev)
248 } 248 }
249 } 249 }
250 250
251 QXL_INFO(qdev, "%s: %d\n", __func__, i); 251 DRM_DEBUG_DRIVER("%d\n", i);
252 252
253 return i; 253 return i;
254} 254}
@@ -381,17 +381,19 @@ void qxl_io_create_primary(struct qxl_device *qdev,
381{ 381{
382 struct qxl_surface_create *create; 382 struct qxl_surface_create *create;
383 383
384 QXL_INFO(qdev, "%s: qdev %p, ram_header %p\n", __func__, qdev, 384 DRM_DEBUG_DRIVER("qdev %p, ram_header %p\n", qdev, qdev->ram_header);
385 qdev->ram_header);
386 create = &qdev->ram_header->create_surface; 385 create = &qdev->ram_header->create_surface;
387 create->format = bo->surf.format; 386 create->format = bo->surf.format;
388 create->width = bo->surf.width; 387 create->width = bo->surf.width;
389 create->height = bo->surf.height; 388 create->height = bo->surf.height;
390 create->stride = bo->surf.stride; 389 create->stride = bo->surf.stride;
391 create->mem = qxl_bo_physical_address(qdev, bo, offset); 390 if (bo->shadow) {
391 create->mem = qxl_bo_physical_address(qdev, bo->shadow, offset);
392 } else {
393 create->mem = qxl_bo_physical_address(qdev, bo, offset);
394 }
392 395
393 QXL_INFO(qdev, "%s: mem = %llx, from %p\n", __func__, create->mem, 396 DRM_DEBUG_DRIVER("mem = %llx, from %p\n", create->mem, bo->kptr);
394 bo->kptr);
395 397
396 create->flags = QXL_SURF_FLAG_KEEP_DATA; 398 create->flags = QXL_SURF_FLAG_KEEP_DATA;
397 create->type = QXL_SURF_TYPE_PRIMARY; 399 create->type = QXL_SURF_TYPE_PRIMARY;
@@ -401,7 +403,7 @@ void qxl_io_create_primary(struct qxl_device *qdev,
401 403
402void qxl_io_memslot_add(struct qxl_device *qdev, uint8_t id) 404void qxl_io_memslot_add(struct qxl_device *qdev, uint8_t id)
403{ 405{
404 QXL_INFO(qdev, "qxl_memslot_add %d\n", id); 406 DRM_DEBUG_DRIVER("qxl_memslot_add %d\n", id);
405 wait_for_io_cmd(qdev, id, QXL_IO_MEMSLOT_ADD_ASYNC); 407 wait_for_io_cmd(qdev, id, QXL_IO_MEMSLOT_ADD_ASYNC);
406} 408}
407 409
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index afbf50d0c08f..4756b3c9bf2c 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -305,7 +305,9 @@ static const struct drm_crtc_funcs qxl_crtc_funcs = {
305void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb) 305void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb)
306{ 306{
307 struct qxl_framebuffer *qxl_fb = to_qxl_framebuffer(fb); 307 struct qxl_framebuffer *qxl_fb = to_qxl_framebuffer(fb);
308 struct qxl_bo *bo = gem_to_qxl_bo(qxl_fb->obj);
308 309
310 WARN_ON(bo->shadow);
309 drm_gem_object_unreference_unlocked(qxl_fb->obj); 311 drm_gem_object_unreference_unlocked(qxl_fb->obj);
310 drm_framebuffer_cleanup(fb); 312 drm_framebuffer_cleanup(fb);
311 kfree(qxl_fb); 313 kfree(qxl_fb);
@@ -508,6 +510,7 @@ static void qxl_primary_atomic_update(struct drm_plane *plane,
508 .x2 = qfb->base.width, 510 .x2 = qfb->base.width,
509 .y2 = qfb->base.height 511 .y2 = qfb->base.height
510 }; 512 };
513 bool same_shadow = false;
511 514
512 if (old_state->fb) { 515 if (old_state->fb) {
513 qfb_old = to_qxl_framebuffer(old_state->fb); 516 qfb_old = to_qxl_framebuffer(old_state->fb);
@@ -519,15 +522,23 @@ static void qxl_primary_atomic_update(struct drm_plane *plane,
519 if (bo == bo_old) 522 if (bo == bo_old)
520 return; 523 return;
521 524
525 if (bo_old && bo_old->shadow && bo->shadow &&
526 bo_old->shadow == bo->shadow) {
527 same_shadow = true;
528 }
529
522 if (bo_old && bo_old->is_primary) { 530 if (bo_old && bo_old->is_primary) {
523 qxl_io_destroy_primary(qdev); 531 if (!same_shadow)
532 qxl_io_destroy_primary(qdev);
524 bo_old->is_primary = false; 533 bo_old->is_primary = false;
525 } 534 }
526 535
527 if (!bo->is_primary) { 536 if (!bo->is_primary) {
528 qxl_io_create_primary(qdev, 0, bo); 537 if (!same_shadow)
538 qxl_io_create_primary(qdev, 0, bo);
529 bo->is_primary = true; 539 bo->is_primary = true;
530 } 540 }
541
531 qxl_draw_dirty_fb(qdev, qfb, bo, 0, 0, &norect, 1, 1); 542 qxl_draw_dirty_fb(qdev, qfb, bo, 0, 0, &norect, 1, 1);
532} 543}
533 544
@@ -679,8 +690,9 @@ static void qxl_cursor_atomic_disable(struct drm_plane *plane,
679static int qxl_plane_prepare_fb(struct drm_plane *plane, 690static int qxl_plane_prepare_fb(struct drm_plane *plane,
680 struct drm_plane_state *new_state) 691 struct drm_plane_state *new_state)
681{ 692{
693 struct qxl_device *qdev = plane->dev->dev_private;
682 struct drm_gem_object *obj; 694 struct drm_gem_object *obj;
683 struct qxl_bo *user_bo; 695 struct qxl_bo *user_bo, *old_bo = NULL;
684 int ret; 696 int ret;
685 697
686 if (!new_state->fb) 698 if (!new_state->fb)
@@ -689,6 +701,32 @@ static int qxl_plane_prepare_fb(struct drm_plane *plane,
689 obj = to_qxl_framebuffer(new_state->fb)->obj; 701 obj = to_qxl_framebuffer(new_state->fb)->obj;
690 user_bo = gem_to_qxl_bo(obj); 702 user_bo = gem_to_qxl_bo(obj);
691 703
704 if (plane->type == DRM_PLANE_TYPE_PRIMARY &&
705 user_bo->is_dumb && !user_bo->shadow) {
706 if (plane->state->fb) {
707 obj = to_qxl_framebuffer(plane->state->fb)->obj;
708 old_bo = gem_to_qxl_bo(obj);
709 }
710 if (old_bo && old_bo->shadow &&
711 user_bo->gem_base.size == old_bo->gem_base.size &&
712 plane->state->crtc == new_state->crtc &&
713 plane->state->crtc_w == new_state->crtc_w &&
714 plane->state->crtc_h == new_state->crtc_h &&
715 plane->state->src_x == new_state->src_x &&
716 plane->state->src_y == new_state->src_y &&
717 plane->state->src_w == new_state->src_w &&
718 plane->state->src_h == new_state->src_h &&
719 plane->state->rotation == new_state->rotation &&
720 plane->state->zpos == new_state->zpos) {
721 drm_gem_object_get(&old_bo->shadow->gem_base);
722 user_bo->shadow = old_bo->shadow;
723 } else {
724 qxl_bo_create(qdev, user_bo->gem_base.size,
725 true, true, QXL_GEM_DOMAIN_VRAM, NULL,
726 &user_bo->shadow);
727 }
728 }
729
692 ret = qxl_bo_pin(user_bo, QXL_GEM_DOMAIN_CPU, NULL); 730 ret = qxl_bo_pin(user_bo, QXL_GEM_DOMAIN_CPU, NULL);
693 if (ret) 731 if (ret)
694 return ret; 732 return ret;
@@ -713,6 +751,11 @@ static void qxl_plane_cleanup_fb(struct drm_plane *plane,
713 obj = to_qxl_framebuffer(old_state->fb)->obj; 751 obj = to_qxl_framebuffer(old_state->fb)->obj;
714 user_bo = gem_to_qxl_bo(obj); 752 user_bo = gem_to_qxl_bo(obj);
715 qxl_bo_unpin(user_bo); 753 qxl_bo_unpin(user_bo);
754
755 if (user_bo->shadow && !user_bo->is_primary) {
756 drm_gem_object_put_unlocked(&user_bo->shadow->gem_base);
757 user_bo->shadow = NULL;
758 }
716} 759}
717 760
718static const uint32_t qxl_cursor_plane_formats[] = { 761static const uint32_t qxl_cursor_plane_formats[] = {
diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
index 3397a1907336..08752c0ffb35 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.h
+++ b/drivers/gpu/drm/qxl/qxl_drv.h
@@ -62,33 +62,9 @@
62 62
63#define QXL_DEBUGFS_MAX_COMPONENTS 32 63#define QXL_DEBUGFS_MAX_COMPONENTS 32
64 64
65extern int qxl_log_level;
66extern int qxl_num_crtc; 65extern int qxl_num_crtc;
67extern int qxl_max_ioctls; 66extern int qxl_max_ioctls;
68 67
69enum {
70 QXL_INFO_LEVEL = 1,
71 QXL_DEBUG_LEVEL = 2,
72};
73
74#define QXL_INFO(qdev, fmt, ...) do { \
75 if (qxl_log_level >= QXL_INFO_LEVEL) { \
76 qxl_io_log(qdev, fmt, __VA_ARGS__); \
77 } \
78 } while (0)
79#define QXL_DEBUG(qdev, fmt, ...) do { \
80 if (qxl_log_level >= QXL_DEBUG_LEVEL) { \
81 qxl_io_log(qdev, fmt, __VA_ARGS__); \
82 } \
83 } while (0)
84#define QXL_INFO_ONCE(qdev, fmt, ...) do { \
85 static int done; \
86 if (!done) { \
87 done = 1; \
88 QXL_INFO(qdev, fmt, __VA_ARGS__); \
89 } \
90 } while (0)
91
92#define DRM_FILE_OFFSET 0x100000000ULL 68#define DRM_FILE_OFFSET 0x100000000ULL
93#define DRM_FILE_PAGE_OFFSET (DRM_FILE_OFFSET >> PAGE_SHIFT) 69#define DRM_FILE_PAGE_OFFSET (DRM_FILE_OFFSET >> PAGE_SHIFT)
94 70
@@ -113,6 +89,8 @@ struct qxl_bo {
113 /* Constant after initialization */ 89 /* Constant after initialization */
114 struct drm_gem_object gem_base; 90 struct drm_gem_object gem_base;
115 bool is_primary; /* is this now a primary surface */ 91 bool is_primary; /* is this now a primary surface */
92 bool is_dumb;
93 struct qxl_bo *shadow;
116 bool hw_surf_alloc; 94 bool hw_surf_alloc;
117 struct qxl_surface surf; 95 struct qxl_surface surf;
118 uint32_t surface_id; 96 uint32_t surface_id;
@@ -351,7 +329,7 @@ int qxl_check_idle(struct qxl_ring *ring);
351static inline void * 329static inline void *
352qxl_fb_virtual_address(struct qxl_device *qdev, unsigned long physical) 330qxl_fb_virtual_address(struct qxl_device *qdev, unsigned long physical)
353{ 331{
354 QXL_INFO(qdev, "not implemented (%lu)\n", physical); 332 DRM_DEBUG_DRIVER("not implemented (%lu)\n", physical);
355 return 0; 333 return 0;
356} 334}
357 335
diff --git a/drivers/gpu/drm/qxl/qxl_dumb.c b/drivers/gpu/drm/qxl/qxl_dumb.c
index 5e65d5d2d937..11085ab01374 100644
--- a/drivers/gpu/drm/qxl/qxl_dumb.c
+++ b/drivers/gpu/drm/qxl/qxl_dumb.c
@@ -63,6 +63,7 @@ int qxl_mode_dumb_create(struct drm_file *file_priv,
63 &handle); 63 &handle);
64 if (r) 64 if (r)
65 return r; 65 return r;
66 qobj->is_dumb = true;
66 args->pitch = pitch; 67 args->pitch = pitch;
67 args->handle = handle; 68 args->handle = handle;
68 return 0; 69 return 0;
diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c
index 844c4a31ca13..23af3e352673 100644
--- a/drivers/gpu/drm/qxl/qxl_fb.c
+++ b/drivers/gpu/drm/qxl/qxl_fb.c
@@ -240,18 +240,15 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev,
240 return ret; 240 return ret;
241 241
242 qbo = gem_to_qxl_bo(gobj); 242 qbo = gem_to_qxl_bo(gobj);
243 QXL_INFO(qdev, "%s: %dx%d %d\n", __func__, mode_cmd.width, 243 DRM_DEBUG_DRIVER("%dx%d %d\n", mode_cmd.width,
244 mode_cmd.height, mode_cmd.pitches[0]); 244 mode_cmd.height, mode_cmd.pitches[0]);
245 245
246 shadow = vmalloc(mode_cmd.pitches[0] * mode_cmd.height); 246 shadow = vmalloc(mode_cmd.pitches[0] * mode_cmd.height);
247 /* TODO: what's the usual response to memory allocation errors? */ 247 /* TODO: what's the usual response to memory allocation errors? */
248 BUG_ON(!shadow); 248 BUG_ON(!shadow);
249 QXL_INFO(qdev, 249 DRM_DEBUG_DRIVER("surface0 at gpu offset %lld, mmap_offset %lld (virt %p, shadow %p)\n",
250 "surface0 at gpu offset %lld, mmap_offset %lld (virt %p, shadow %p)\n", 250 qxl_bo_gpu_offset(qbo), qxl_bo_mmap_offset(qbo),
251 qxl_bo_gpu_offset(qbo), 251 qbo->kptr, shadow);
252 qxl_bo_mmap_offset(qbo),
253 qbo->kptr,
254 shadow);
255 size = mode_cmd.pitches[0] * mode_cmd.height; 252 size = mode_cmd.pitches[0] * mode_cmd.height;
256 253
257 info = drm_fb_helper_alloc_fbi(&qfbdev->helper); 254 info = drm_fb_helper_alloc_fbi(&qfbdev->helper);
diff --git a/drivers/gpu/drm/qxl/qxl_release.c b/drivers/gpu/drm/qxl/qxl_release.c
index e6ec845b5be0..a6da6fa6ad58 100644
--- a/drivers/gpu/drm/qxl/qxl_release.c
+++ b/drivers/gpu/drm/qxl/qxl_release.c
@@ -154,7 +154,7 @@ qxl_release_alloc(struct qxl_device *qdev, int type,
154 return handle; 154 return handle;
155 } 155 }
156 *ret = release; 156 *ret = release;
157 QXL_INFO(qdev, "allocated release %d\n", handle); 157 DRM_DEBUG_DRIVER("allocated release %d\n", handle);
158 release->id = handle; 158 release->id = handle;
159 return handle; 159 return handle;
160} 160}
@@ -179,8 +179,7 @@ void
179qxl_release_free(struct qxl_device *qdev, 179qxl_release_free(struct qxl_device *qdev,
180 struct qxl_release *release) 180 struct qxl_release *release)
181{ 181{
182 QXL_INFO(qdev, "release %d, type %d\n", release->id, 182 DRM_DEBUG_DRIVER("release %d, type %d\n", release->id, release->type);
183 release->type);
184 183
185 if (release->surface_release_id) 184 if (release->surface_release_id)
186 qxl_surface_id_dealloc(qdev, release->surface_release_id); 185 qxl_surface_id_dealloc(qdev, release->surface_release_id);
diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c
index 7ecf8a4b9fe6..ab4823875311 100644
--- a/drivers/gpu/drm/qxl/qxl_ttm.c
+++ b/drivers/gpu/drm/qxl/qxl_ttm.c
@@ -136,8 +136,8 @@ int qxl_mmap(struct file *filp, struct vm_area_struct *vma)
136 "filp->private_data->minor->dev->dev_private == NULL\n"); 136 "filp->private_data->minor->dev->dev_private == NULL\n");
137 return -EINVAL; 137 return -EINVAL;
138 } 138 }
139 QXL_INFO(qdev, "%s: filp->private_data = 0x%p, vma->vm_pgoff = %lx\n", 139 DRM_DEBUG_DRIVER("filp->private_data = 0x%p, vma->vm_pgoff = %lx\n",
140 __func__, filp->private_data, vma->vm_pgoff); 140 filp->private_data, vma->vm_pgoff);
141 141
142 r = ttm_bo_mmap(filp, vma, &qdev->mman.bdev); 142 r = ttm_bo_mmap(filp, vma, &qdev->mman.bdev);
143 if (unlikely(r != 0)) 143 if (unlikely(r != 0))