diff options
| -rw-r--r-- | drivers/gpu/drm/qxl/qxl_cmd.c | 6 | ||||
| -rw-r--r-- | drivers/gpu/drm/qxl/qxl_display.c | 49 | ||||
| -rw-r--r-- | drivers/gpu/drm/qxl/qxl_drv.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/qxl/qxl_dumb.c | 1 |
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 = { | |||
| 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 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; |
