aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/qxl/qxl_cmd.c6
-rw-r--r--drivers/gpu/drm/qxl/qxl_display.c49
-rw-r--r--drivers/gpu/drm/qxl/qxl_drv.h2
-rw-r--r--drivers/gpu/drm/qxl/qxl_dumb.c1
4 files changed, 54 insertions, 4 deletions
diff --git a/drivers/gpu/drm/qxl/qxl_cmd.c b/drivers/gpu/drm/qxl/qxl_cmd.c
index 8ec53d5abd62..c0fb52c6d4ca 100644
--- a/drivers/gpu/drm/qxl/qxl_cmd.c
+++ b/drivers/gpu/drm/qxl/qxl_cmd.c
@@ -387,7 +387,11 @@ void qxl_io_create_primary(struct qxl_device *qdev,
387 create->width = bo->surf.width; 387 create->width = bo->surf.width;
388 create->height = bo->surf.height; 388 create->height = bo->surf.height;
389 create->stride = bo->surf.stride; 389 create->stride = bo->surf.stride;
390 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 }
391 395
392 DRM_DEBUG_DRIVER("mem = %llx, from %p\n", create->mem, bo->kptr); 396 DRM_DEBUG_DRIVER("mem = %llx, from %p\n", create->mem, bo->kptr);
393 397
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 d707b351875c..08752c0ffb35 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.h
+++ b/drivers/gpu/drm/qxl/qxl_drv.h
@@ -89,6 +89,8 @@ struct qxl_bo {
89 /* Constant after initialization */ 89 /* Constant after initialization */
90 struct drm_gem_object gem_base; 90 struct drm_gem_object gem_base;
91 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;
92 bool hw_surf_alloc; 94 bool hw_surf_alloc;
93 struct qxl_surface surf; 95 struct qxl_surface surf;
94 uint32_t surface_id; 96 uint32_t surface_id;
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;