diff options
author | Dave Airlie <airlied@redhat.com> | 2017-11-13 14:17:23 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2017-11-13 14:17:23 -0500 |
commit | fee25cb965f9e1360f845a7a3fb16bca1bbadc84 (patch) | |
tree | e80b01083c1a41379f62681b3cf00fd508d80c41 /drivers/gpu | |
parent | e7e62c7ef382f5db0de5e492e558efc9c3d60943 (diff) | |
parent | 62676d10b483a2ff6e8b08c5e7c7d63a831343f5 (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.c | 22 | ||||
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_display.c | 49 | ||||
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_drv.h | 28 | ||||
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_dumb.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_fb.c | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_release.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_ttm.c | 4 |
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 | ||
402 | void qxl_io_memslot_add(struct qxl_device *qdev, uint8_t id) | 404 | void 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 = { | |||
305 | void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb) | 305 | void 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, | |||
679 | static int qxl_plane_prepare_fb(struct drm_plane *plane, | 690 | static 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 | ||
718 | static const uint32_t qxl_cursor_plane_formats[] = { | 761 | static 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 | ||
65 | extern int qxl_log_level; | ||
66 | extern int qxl_num_crtc; | 65 | extern int qxl_num_crtc; |
67 | extern int qxl_max_ioctls; | 66 | extern int qxl_max_ioctls; |
68 | 67 | ||
69 | enum { | ||
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); | |||
351 | static inline void * | 329 | static inline void * |
352 | qxl_fb_virtual_address(struct qxl_device *qdev, unsigned long physical) | 330 | qxl_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 | |||
179 | qxl_release_free(struct qxl_device *qdev, | 179 | qxl_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)) |