aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2017-09-11 05:39:50 -0400
committerGerd Hoffmann <kraxel@redhat.com>2017-09-12 02:04:09 -0400
commitb0e07da3f5c8d069d186a7983ff64eaebf2ea230 (patch)
tree87841dc58f3c592fa29d79e11f97c12c1839c5d3
parent79964dbaf662229253b281c42e82e2675a9d3b80 (diff)
qxl: fix primary surface handling
The atomic conversion of the qxl driver didn't got the primary surface handling completely right. It works in the common simple cases, but fails for example when changing the display resolution using xrandr or in multihead setups. The rules are simple: There is one primary surface. Before defining a new one you have to destroy the old one. This patch makes qxl_primary_atomic_update() destroy the primary surface before defining a new one. It fixes is_primary flag updates. It adds is_primary checks so we don't try to update the primary surface in case it already has the state we want it being in. Fixes: 3538e80a869b ("drm: qxl: Atomic phase 1: Implement mode_set_nofb") Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=102338 Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=196777 Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Gabriel Krisman Bertazi <krisman@collabora.co.uk> Link: http://patchwork.freedesktop.org/patch/msgid/20170911093950.22401-1-kraxel@redhat.com
-rw-r--r--drivers/gpu/drm/qxl/qxl_display.c34
1 files changed, 19 insertions, 15 deletions
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index 03fe182203ce..7babdd8f20fd 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -512,23 +512,25 @@ static void qxl_primary_atomic_update(struct drm_plane *plane,
512 .y2 = qfb->base.height 512 .y2 = qfb->base.height
513 }; 513 };
514 514
515 if (!old_state->fb) { 515 if (old_state->fb) {
516 qxl_io_log(qdev, 516 qfb_old = to_qxl_framebuffer(old_state->fb);
517 "create primary fb: %dx%d,%d,%d\n", 517 bo_old = gem_to_qxl_bo(qfb_old->obj);
518 bo->surf.width, bo->surf.height, 518 } else {
519 bo->surf.stride, bo->surf.format); 519 bo_old = NULL;
520 }
520 521
521 qxl_io_create_primary(qdev, 0, bo); 522 if (bo == bo_old)
522 bo->is_primary = true;
523 return; 523 return;
524 524
525 } else { 525 if (bo_old && bo_old->is_primary) {
526 qfb_old = to_qxl_framebuffer(old_state->fb); 526 qxl_io_destroy_primary(qdev);
527 bo_old = gem_to_qxl_bo(qfb_old->obj);
528 bo_old->is_primary = false; 527 bo_old->is_primary = false;
529 } 528 }
530 529
531 bo->is_primary = true; 530 if (!bo->is_primary) {
531 qxl_io_create_primary(qdev, 0, bo);
532 bo->is_primary = true;
533 }
532 qxl_draw_dirty_fb(qdev, qfb, bo, 0, 0, &norect, 1, 1); 534 qxl_draw_dirty_fb(qdev, qfb, bo, 0, 0, &norect, 1, 1);
533} 535}
534 536
@@ -537,13 +539,15 @@ static void qxl_primary_atomic_disable(struct drm_plane *plane,
537{ 539{
538 struct qxl_device *qdev = plane->dev->dev_private; 540 struct qxl_device *qdev = plane->dev->dev_private;
539 541
540 if (old_state->fb) 542 if (old_state->fb) {
541 { struct qxl_framebuffer *qfb = 543 struct qxl_framebuffer *qfb =
542 to_qxl_framebuffer(old_state->fb); 544 to_qxl_framebuffer(old_state->fb);
543 struct qxl_bo *bo = gem_to_qxl_bo(qfb->obj); 545 struct qxl_bo *bo = gem_to_qxl_bo(qfb->obj);
544 546
545 qxl_io_destroy_primary(qdev); 547 if (bo->is_primary) {
546 bo->is_primary = false; 548 qxl_io_destroy_primary(qdev);
549 bo->is_primary = false;
550 }
547 } 551 }
548} 552}
549 553