From patchwork Mon Nov 7 08:01:02 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Fergeau X-Patchwork-Id: 9414413 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id C35E96022E for ; Mon, 7 Nov 2016 08:01:56 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B439828D5E for ; Mon, 7 Nov 2016 08:01:56 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A91C528D60; Mon, 7 Nov 2016 08:01:56 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 420F528D5E for ; Mon, 7 Nov 2016 08:01:56 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 068A46E318; Mon, 7 Nov 2016 08:01:14 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by gabe.freedesktop.org (Postfix) with ESMTPS id C00006E30D; Mon, 7 Nov 2016 08:01:11 +0000 (UTC) Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5BFC43D48A; Mon, 7 Nov 2016 08:01:11 +0000 (UTC) Received: from edamame.cdg.redhat.com (ovpn-116-52.ams2.redhat.com [10.36.116.52]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id uA78196V006535 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 7 Nov 2016 03:01:10 -0500 Received: by edamame.cdg.redhat.com (Postfix, from userid 1000) id 451E8146811; Mon, 7 Nov 2016 09:01:08 +0100 (CET) From: Christophe Fergeau To: spice-devel@lists.freedesktop.org Subject: [drm/qxl v3 6/7] qxl: Don't notify userspace when monitors config is unchanged Date: Mon, 7 Nov 2016 09:01:02 +0100 Message-Id: <20161107080103.22299-7-cfergeau@redhat.com> In-Reply-To: <20161107080103.22299-1-cfergeau@redhat.com> References: <20161107080103.22299-1-cfergeau@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Mon, 07 Nov 2016 08:01:11 +0000 (UTC) Cc: airlied@redhat.com, dri-devel@lists.freedesktop.org X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP When the QXL driver receives a QXL_INTERRUPT_CLIENT_MONITORS_CONFIG interrupt, we currently always notify userspace that there was some hotplug event. However, gnome-shell/mutter is reacting to this event by attempting a resolution change, which it does by issueing drmModeRmFB, drmModeAddFB, and then drmModeSetCrtc. This has the side-effect of causing qxl_crtc_mode_set() to tell the QXL virtual hardware that a primary surface was destroyed and created. After going through QEMU and then the remote SPICE client, a new identical monitors config message will be sent, resulting in a QXL_INTERRUPT_CLIENT_MONITORS_CONFIG interrupt to be emitted, and the same scenario occurring again. As destroying/creating the primary surface causes a visible screen flicker, this makes the guest hard to use ( https://bugzilla.redhat.com/show_bug.cgi?id=1266484 ). This commit checks if the screen configuration we received is the same one as the current one, and does not notify userspace about it if that's the case. Signed-off-by: Christophe Fergeau --- drivers/gpu/drm/qxl/qxl_display.c | 62 ++++++++++++++++++++++++++++++++------- 1 file changed, 52 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 8cf5177..518333c 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -57,11 +57,18 @@ static void qxl_alloc_client_monitors_config(struct qxl_device *qdev, unsigned c qdev->client_monitors_config->count = count; } +enum { + MONITORS_CONFIG_MODIFIED, + MONITORS_CONFIG_UNCHANGED, + MONITORS_CONFIG_BAD_CRC, +}; + static int qxl_display_copy_rom_client_monitors_config(struct qxl_device *qdev) { int i; int num_monitors; uint32_t crc; + int status = MONITORS_CONFIG_UNCHANGED; num_monitors = qdev->rom->client_monitors_config.count; crc = crc32(0, (const uint8_t *)&qdev->rom->client_monitors_config, @@ -70,7 +77,7 @@ static int qxl_display_copy_rom_client_monitors_config(struct qxl_device *qdev) qxl_io_log(qdev, "crc mismatch: have %X (%zd) != %X\n", crc, sizeof(qdev->rom->client_monitors_config), qdev->rom->client_monitors_config_crc); - return 1; + return MONITORS_CONFIG_BAD_CRC; } if (num_monitors > qdev->monitors_config->max_allowed) { DRM_DEBUG_KMS("client monitors list will be truncated: %d < %d\n", @@ -79,6 +86,10 @@ static int qxl_display_copy_rom_client_monitors_config(struct qxl_device *qdev) } else { num_monitors = qdev->rom->client_monitors_config.count; } + if (qdev->client_monitors_config + && (num_monitors != qdev->client_monitors_config->count)) { + status = MONITORS_CONFIG_MODIFIED; + } qxl_alloc_client_monitors_config(qdev, num_monitors); /* we copy max from the client but it isn't used */ qdev->client_monitors_config->max_allowed = @@ -88,17 +99,39 @@ static int qxl_display_copy_rom_client_monitors_config(struct qxl_device *qdev) &qdev->rom->client_monitors_config.heads[i]; struct qxl_head *client_head = &qdev->client_monitors_config->heads[i]; - client_head->x = c_rect->left; - client_head->y = c_rect->top; - client_head->width = c_rect->right - c_rect->left; - client_head->height = c_rect->bottom - c_rect->top; - client_head->surface_id = 0; - client_head->id = i; - client_head->flags = 0; + if (client_head->x != c_rect->left) { + client_head->x = c_rect->left; + status = MONITORS_CONFIG_MODIFIED; + } + if (client_head->y != c_rect->top) { + client_head->y = c_rect->top; + status = MONITORS_CONFIG_MODIFIED; + } + if (client_head->width != c_rect->right - c_rect->left) { + client_head->width = c_rect->right - c_rect->left; + status = MONITORS_CONFIG_MODIFIED; + } + if (client_head->height != c_rect->bottom - c_rect->top) { + client_head->height = c_rect->bottom - c_rect->top; + status = MONITORS_CONFIG_MODIFIED; + } + if (client_head->surface_id != 0) { + client_head->surface_id = 0; + status = MONITORS_CONFIG_MODIFIED; + } + if (client_head->id != i) { + client_head->id = i; + status = MONITORS_CONFIG_MODIFIED; + } + if (client_head->flags != 0) { + client_head->flags = 0; + status = MONITORS_CONFIG_MODIFIED; + } DRM_DEBUG_KMS("read %dx%d+%d+%d\n", client_head->width, client_head->height, client_head->x, client_head->y); } - return 0; + + return status; } static void qxl_update_offset_props(struct qxl_device *qdev) @@ -124,9 +157,18 @@ void qxl_display_read_client_monitors_config(struct qxl_device *qdev) { struct drm_device *dev = qdev->ddev; - while (qxl_display_copy_rom_client_monitors_config(qdev)) { + int status; + + status = qxl_display_copy_rom_client_monitors_config(qdev); + while (status == MONITORS_CONFIG_BAD_CRC) { qxl_io_log(qdev, "failed crc check for client_monitors_config," " retrying\n"); + status = qxl_display_copy_rom_client_monitors_config(qdev); + } + if (status == MONITORS_CONFIG_UNCHANGED) { + qxl_io_log(qdev, "config unchanged\n"); + DRM_DEBUG("ignoring unchanged client monitors config"); + return; } drm_modeset_lock_all(dev);