From nobody Sat Nov 15 10:54:06 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1752494360; cv=none; d=zohomail.com; s=zohoarc; b=HXVTeF6v7hWtyMTUH/As9SY8Y3Z2pezLUzZhE1e9X5kuTpWqL87dt9oQEcjXpeYJ5/2+2+d0VO/AEf5NhdfCY55kqyAQuHGGwjyyoA8JM9D0zCgpcGNyLVgBZRno1DtGkawHzh9dXviryi4r+GVlbnAnb49jbU++O5GDI1OoJnU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752494360; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=uWyeEHTgdMwBOPbQAhP+8TeJjHS/avrQnveaFbPWxjQ=; b=J0X08M4ygcG3c2tQFoTUIbQvRDoWZvVE3M/Z1zJSPCR4dDWlCbb2/1sUqD7bkMY+tqcubnJM/+MoHnppq+THd/Ykp4giD1ti8pq+Angu94Gbv+oppkJYOvDhTowVOa0bFOdgWMbfQFDEJkQBMNA/3vWA4zY3u7iDFBBe2DFQtwc= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 17524943609081008.064400003286; Mon, 14 Jul 2025 04:59:20 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubHes-0001pC-Cu; Mon, 14 Jul 2025 07:47:46 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ubH5F-0005t1-EG for qemu-devel@nongnu.org; Mon, 14 Jul 2025 07:11:04 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ubH5C-00036r-GC for qemu-devel@nongnu.org; Mon, 14 Jul 2025 07:10:56 -0400 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-166-D7CdPuvgPDq_PsMdacDsWA-1; Mon, 14 Jul 2025 07:10:52 -0400 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 0C9881800290; Mon, 14 Jul 2025 11:10:51 +0000 (UTC) Received: from localhost (unknown [10.45.242.9]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 77FBF180035C; Mon, 14 Jul 2025 11:10:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752491453; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=uWyeEHTgdMwBOPbQAhP+8TeJjHS/avrQnveaFbPWxjQ=; b=BpbCspYd9MgQFO0lG+xQFPumt6ZkIOgGb7CIQiyqA8EYbP+qAs0jD22XOTfS1XYESBp3iK vdMhaPxbucKis3cID3oLsTN/OZkTWaTaqt6nKLaC4qppEB/c0jhyHJQRIjsr8xu/5/9KOH m7YINbTvtVwPv6tysU6CrdjqrrOUBWg= X-MC-Unique: D7CdPuvgPDq_PsMdacDsWA-1 X-Mimecast-MFC-AGG-ID: D7CdPuvgPDq_PsMdacDsWA_1752491451 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, Akihiko Odaki , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Subject: [PULL 01/13] ui/vnc: Do not copy z_stream Date: Mon, 14 Jul 2025 15:10:24 +0400 Message-ID: <20250714111039.4150419-2-marcandre.lureau@redhat.com> In-Reply-To: <20250714111039.4150419-1-marcandre.lureau@redhat.com> References: <20250714111039.4150419-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1752494363864116600 From: Akihiko Odaki vnc_worker_thread_loop() copies z_stream stored in its local VncState to the persistent VncState, and the copied one is freed with deflateEnd() later. However, deflateEnd() refuses to operate with a copied z_stream and returns Z_STREAM_ERROR, leaking the allocated memory. Avoid copying the zlib state to fix the memory leak. Fixes: bd023f953e5e ("vnc: threaded VNC server") Signed-off-by: Akihiko Odaki Reviewed-by: Marc-Andr=C3=A9 Lureau Reviewed-by: Philippe Mathieu-Daud=C3=A9 Message-Id: <20250603-zlib-v3-1-20b857bd8d05@rsg.ci.i.u-tokyo.ac.jp> --- ui/vnc.h | 2 +- ui/vnc-enc-zlib.c | 30 +++++++++++++++--------------- ui/vnc.c | 13 ++++++++++--- 3 files changed, 26 insertions(+), 19 deletions(-) diff --git a/ui/vnc.h b/ui/vnc.h index b3e07269bb..8df0cbab25 100644 --- a/ui/vnc.h +++ b/ui/vnc.h @@ -342,7 +342,7 @@ struct VncState * update vnc_async_encoding_start() */ VncTight *tight; - VncZlib zlib; + VncZlib *zlib; VncHextile hextile; VncZrle *zrle; VncZywrle zywrle; diff --git a/ui/vnc-enc-zlib.c b/ui/vnc-enc-zlib.c index 900ae5b30f..52e9193eab 100644 --- a/ui/vnc-enc-zlib.c +++ b/ui/vnc-enc-zlib.c @@ -48,21 +48,21 @@ void vnc_zlib_zfree(void *x, void *addr) =20 static void vnc_zlib_start(VncState *vs) { - buffer_reset(&vs->zlib.zlib); + buffer_reset(&vs->zlib->zlib); =20 // make the output buffer be the zlib buffer, so we can compress it la= ter - vs->zlib.tmp =3D vs->output; - vs->output =3D vs->zlib.zlib; + vs->zlib->tmp =3D vs->output; + vs->output =3D vs->zlib->zlib; } =20 static int vnc_zlib_stop(VncState *vs) { - z_streamp zstream =3D &vs->zlib.stream; + z_streamp zstream =3D &vs->zlib->stream; int previous_out; =20 // switch back to normal output/zlib buffers - vs->zlib.zlib =3D vs->output; - vs->output =3D vs->zlib.tmp; + vs->zlib->zlib =3D vs->output; + vs->output =3D vs->zlib->tmp; =20 // compress the zlib buffer =20 @@ -85,24 +85,24 @@ static int vnc_zlib_stop(VncState *vs) return -1; } =20 - vs->zlib.level =3D vs->tight->compression; + vs->zlib->level =3D vs->tight->compression; zstream->opaque =3D vs; } =20 - if (vs->tight->compression !=3D vs->zlib.level) { + if (vs->tight->compression !=3D vs->zlib->level) { if (deflateParams(zstream, vs->tight->compression, Z_DEFAULT_STRATEGY) !=3D Z_OK) { return -1; } - vs->zlib.level =3D vs->tight->compression; + vs->zlib->level =3D vs->tight->compression; } =20 // reserve memory in output buffer - buffer_reserve(&vs->output, vs->zlib.zlib.offset + 64); + buffer_reserve(&vs->output, vs->zlib->zlib.offset + 64); =20 // set pointers - zstream->next_in =3D vs->zlib.zlib.buffer; - zstream->avail_in =3D vs->zlib.zlib.offset; + zstream->next_in =3D vs->zlib->zlib.buffer; + zstream->avail_in =3D vs->zlib->zlib.offset; zstream->next_out =3D vs->output.buffer + vs->output.offset; zstream->avail_out =3D vs->output.capacity - vs->output.offset; previous_out =3D zstream->avail_out; @@ -147,8 +147,8 @@ int vnc_zlib_send_framebuffer_update(VncState *vs, int = x, int y, int w, int h) =20 void vnc_zlib_clear(VncState *vs) { - if (vs->zlib.stream.opaque) { - deflateEnd(&vs->zlib.stream); + if (vs->zlib->stream.opaque) { + deflateEnd(&vs->zlib->stream); } - buffer_free(&vs->zlib.zlib); + buffer_free(&vs->zlib->zlib); } diff --git a/ui/vnc.c b/ui/vnc.c index e9c30aad62..ab74154e4c 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -56,6 +56,11 @@ #include "io/dns-resolver.h" #include "monitor/monitor.h" =20 +typedef struct VncConnection { + VncState vs; + VncZlib zlib; +} VncConnection; + #define VNC_REFRESH_INTERVAL_BASE GUI_REFRESH_INTERVAL_DEFAULT #define VNC_REFRESH_INTERVAL_INC 50 #define VNC_REFRESH_INTERVAL_MAX GUI_REFRESH_INTERVAL_IDLE @@ -1362,7 +1367,7 @@ void vnc_disconnect_finish(VncState *vs) vs->magic =3D 0; g_free(vs->zrle); g_free(vs->tight); - g_free(vs); + g_free(container_of(vs, VncConnection, vs)); } =20 size_t vnc_client_io_error(VncState *vs, ssize_t ret, Error *err) @@ -3241,11 +3246,13 @@ static void vnc_refresh(DisplayChangeListener *dcl) static void vnc_connect(VncDisplay *vd, QIOChannelSocket *sioc, bool skipauth, bool websocket) { - VncState *vs =3D g_new0(VncState, 1); + VncConnection *vc =3D g_new0(VncConnection, 1); + VncState *vs =3D &vc->vs; bool first_client =3D QTAILQ_EMPTY(&vd->clients); int i; =20 trace_vnc_client_connect(vs, sioc); + vs->zlib =3D &vc->zlib; vs->zrle =3D g_new0(VncZrle, 1); vs->tight =3D g_new0(VncTight, 1); vs->magic =3D VNC_MAGIC; @@ -3268,7 +3275,7 @@ static void vnc_connect(VncDisplay *vd, QIOChannelSoc= ket *sioc, #ifdef CONFIG_PNG buffer_init(&vs->tight->png, "vnc-tight-png/%p", sioc); #endif - buffer_init(&vs->zlib.zlib, "vnc-zlib/%p", sioc); + buffer_init(&vc->zlib.zlib, "vnc-zlib/%p", sioc); buffer_init(&vs->zrle->zrle, "vnc-zrle/%p", sioc); buffer_init(&vs->zrle->fb, "vnc-zrle-fb/%p", sioc); buffer_init(&vs->zrle->zlib, "vnc-zrle-zlib/%p", sioc); --=20 2.50.0 From nobody Sat Nov 15 10:54:06 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1752494412; cv=none; d=zohomail.com; s=zohoarc; b=QuDQicDL6m8nkjd689F/z9K8ygFh9aQO9hZyVgwAkCSrYpFqlTNHsRt7J4/NN6zBBDKpmDgsMAlNjE290nR/z5VlNgfzHPmUZ6p7zEK5PLEmPxEe2POZXGCsvzXZP+mPq5goRRixxTqALYvWI+y5KuNz2QAFn3nKQuade1E43lE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752494412; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=TAbA28er3Wh+Wn24OIlK+6Gdf/fmAKSekDmuw4NbbEc=; b=B/gZ1AN5jzD3aYvG3STFMG4ydpygZ2mx6DQNtNjrIL6ck/1yeZ3xmmucHF4kJuFobnDl+5T29S7984HWo1+8Fuwofo+Znbhb7WCzmjw18rqsx8q9kJ61sopMmFchF5TccDmisMm794vs+bNaWIVQAMcI1GowV75GcICP3vaFzAw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 175249441188535.48566859448249; Mon, 14 Jul 2025 05:00:11 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubHek-0001Mf-DY; Mon, 14 Jul 2025 07:47:38 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ubH5P-000623-7O for qemu-devel@nongnu.org; Mon, 14 Jul 2025 07:11:11 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ubH5K-00038h-QG for qemu-devel@nongnu.org; Mon, 14 Jul 2025 07:11:06 -0400 Received: from mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-292-OCN4XwG1N4aHuyfcppVB1g-1; Mon, 14 Jul 2025 07:10:59 -0400 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id CAAEE19560AE; Mon, 14 Jul 2025 11:10:58 +0000 (UTC) Received: from localhost (unknown [10.45.242.9]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id D44EE180045B; Mon, 14 Jul 2025 11:10:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752491462; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=TAbA28er3Wh+Wn24OIlK+6Gdf/fmAKSekDmuw4NbbEc=; b=WQVcAaEMuIDL20RVj+l7GLe55BIFFWC8DnCSx4fm4vLiFo6XSn1+DBczoQdcmQrla6ZAAX e9pQ9PaIhk5ZxLZyTf9I419OOff0gvGGgxGA72IEmFvUtsc5h8sUI+cq4ZsU4bd53kv8Lq SzG3/4z5HuuXE1Rs1ufSPeYZKXiUmeM= X-MC-Unique: OCN4XwG1N4aHuyfcppVB1g-1 X-Mimecast-MFC-AGG-ID: OCN4XwG1N4aHuyfcppVB1g_1752491459 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, Akihiko Odaki , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Subject: [PULL 02/13] ui/vnc: Introduce the VncWorker type Date: Mon, 14 Jul 2025 15:10:25 +0400 Message-ID: <20250714111039.4150419-3-marcandre.lureau@redhat.com> In-Reply-To: <20250714111039.4150419-1-marcandre.lureau@redhat.com> References: <20250714111039.4150419-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: 0 X-Spam_score: -0.1 X-Spam_bar: / X-Spam_report: (-0.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, PDS_OTHER_BAD_TLD=1.999, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1752494415202116600 From: Akihiko Odaki The worker thread copies data in VncState to avoid race, but some data are too big to copy. Such data are held with pointers to avoid the overhead to copy, but it requires tedious memory management and makes them vulnerable to race. Introduce the VncWorker type to contain all data shared without copying. It allows allocating and freeing all shared data at once and shows that the race with the worker thread needs to be taken care of when accessing them. Signed-off-by: Akihiko Odaki Reviewed-by: Marc-Andr=C3=A9 Lureau Message-Id: <20250603-zlib-v3-2-20b857bd8d05@rsg.ci.i.u-tokyo.ac.jp> --- ui/vnc.h | 49 +++-- ui/vnc-enc-tight.c | 456 ++++++++++++++++++++++-------------------- ui/vnc-enc-zlib.c | 47 ++--- ui/vnc-enc-zrle.c | 122 +++++------ ui/vnc-jobs.c | 13 +- ui/vnc.c | 86 ++++---- ui/vnc-enc-zrle.c.inc | 20 +- 7 files changed, 405 insertions(+), 388 deletions(-) diff --git a/ui/vnc.h b/ui/vnc.h index 8df0cbab25..f2dab2f4d9 100644 --- a/ui/vnc.h +++ b/ui/vnc.h @@ -272,8 +272,6 @@ struct VncState gboolean disconnecting; =20 DECLARE_BITMAP(dirty[VNC_MAX_HEIGHT], VNC_DIRTY_BITS); - uint8_t **lossy_rect; /* Not an Array to avoid costly memcpy in - * vnc-jobs-async.c */ =20 VncDisplay *vd; VncStateUpdate update; /* Most recent pending request from client */ @@ -341,10 +339,7 @@ struct VncState /* Encoding specific, if you add something here, don't forget to * update vnc_async_encoding_start() */ - VncTight *tight; - VncZlib *zlib; VncHextile hextile; - VncZrle *zrle; VncZywrle zywrle; =20 Notifier mouse_mode_notifier; @@ -356,6 +351,19 @@ struct VncState QTAILQ_ENTRY(VncState) next; }; =20 +typedef struct VncWorker { + uint8_t lossy_rect[VNC_STAT_ROWS][VNC_STAT_COLS]; + + VncTight tight; + VncZlib zlib; + VncZrle zrle; +} VncWorker; + +typedef struct VncConnection { + VncState vs; + VncWorker worker; +} VncConnection; + =20 /*************************************************************************= **** * @@ -602,10 +610,11 @@ int vnc_server_fb_stride(VncDisplay *vd); =20 void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v); double vnc_update_freq(VncState *vs, int x, int y, int w, int h); -void vnc_sent_lossy_rect(VncState *vs, int x, int y, int w, int h); +void vnc_sent_lossy_rect(VncWorker *worker, int x, int y, int w, int h); =20 /* Encodings */ -int vnc_send_framebuffer_update(VncState *vs, int x, int y, int w, int h); +int vnc_send_framebuffer_update(VncState *vs, VncWorker *worker, + int x, int y, int w, int h); =20 int vnc_raw_send_framebuffer_update(VncState *vs, int x, int y, int w, int= h); =20 @@ -615,17 +624,21 @@ void vnc_hextile_set_pixel_conversion(VncState *vs, i= nt generic); =20 void *vnc_zlib_zalloc(void *x, unsigned items, unsigned size); void vnc_zlib_zfree(void *x, void *addr); -int vnc_zlib_send_framebuffer_update(VncState *vs, int x, int y, int w, in= t h); -void vnc_zlib_clear(VncState *vs); - -int vnc_tight_send_framebuffer_update(VncState *vs, int x, int y, int w, i= nt h); -int vnc_tight_png_send_framebuffer_update(VncState *vs, int x, int y, - int w, int h); -void vnc_tight_clear(VncState *vs); - -int vnc_zrle_send_framebuffer_update(VncState *vs, int x, int y, int w, in= t h); -int vnc_zywrle_send_framebuffer_update(VncState *vs, int x, int y, int w, = int h); -void vnc_zrle_clear(VncState *vs); +int vnc_zlib_send_framebuffer_update(VncState *vs, VncWorker *worker, + int x, int y, int w, int h); +void vnc_zlib_clear(VncWorker *worker); + +int vnc_tight_send_framebuffer_update(VncState *vs, VncWorker *worker, + int x, int y, int w, int h); +int vnc_tight_png_send_framebuffer_update(VncState *vs, VncWorker *worker, + int x, int y, int w, int h); +void vnc_tight_clear(VncWorker *worker); + +int vnc_zrle_send_framebuffer_update(VncState *vs, VncWorker *worker, + int x, int y, int w, int h); +int vnc_zywrle_send_framebuffer_update(VncState *vs, VncWorker *worker, + int x, int y, int w, int h); +void vnc_zrle_clear(VncWorker *worker); =20 /* vnc-clipboard.c */ void vnc_server_cut_text_caps(VncState *vs); diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c index 25c7b2c788..9dfe6ae5a2 100644 --- a/ui/vnc-enc-tight.c +++ b/ui/vnc-enc-tight.c @@ -72,8 +72,8 @@ static const struct { }; =20 =20 -static int tight_send_framebuffer_update(VncState *vs, int x, int y, - int w, int h); +static int tight_send_framebuffer_update(VncState *vs, VncWorker *worker, + int x, int y, int w, int h); =20 #ifdef CONFIG_VNC_JPEG static const struct { @@ -111,12 +111,12 @@ static const struct { { 9, PNG_ALL_FILTERS }, }; =20 -static int send_png_rect(VncState *vs, int x, int y, int w, int h, - VncPalette *palette); +static int send_png_rect(VncState *vs, VncWorker *worker, + int x, int y, int w, int h, VncPalette *palette); =20 -static bool tight_can_send_png_rect(VncState *vs, int w, int h) +static bool tight_can_send_png_rect(VncState *vs, VncTight *tight, int w, = int h) { - if (vs->tight->type !=3D VNC_ENCODING_TIGHT_PNG) { + if (tight->type !=3D VNC_ENCODING_TIGHT_PNG) { return false; } =20 @@ -135,7 +135,7 @@ static bool tight_can_send_png_rect(VncState *vs, int w= , int h) */ =20 static unsigned int -tight_detect_smooth_image24(VncState *vs, int w, int h) +tight_detect_smooth_image24(VncState *vs, VncTight *tight, int w, int h) { int off; int x, y, d, dx; @@ -144,7 +144,7 @@ tight_detect_smooth_image24(VncState *vs, int w, int h) int pixels =3D 0; int pix, left[3]; unsigned int errors; - unsigned char *buf =3D vs->tight->tight.buffer; + unsigned char *buf =3D tight->tight.buffer; =20 /* * If client is big-endian, color samples begin from the second @@ -205,7 +205,8 @@ tight_detect_smooth_image24(VncState *vs, int w, int h) #define DEFINE_DETECT_FUNCTION(bpp) \ \ static unsigned int \ - tight_detect_smooth_image##bpp(VncState *vs, int w, int h) { \ + tight_detect_smooth_image##bpp(VncState *vs, VncTight *tight, \ + int w, int h) { \ bool endian; \ uint##bpp##_t pix; \ int max[3], shift[3]; \ @@ -215,7 +216,7 @@ tight_detect_smooth_image24(VncState *vs, int w, int h) int pixels =3D 0; \ int sample, sum, left[3]; \ unsigned int errors; \ - unsigned char *buf =3D vs->tight->tight.buffer; = \ + unsigned char *buf =3D tight->tight.buffer; \ \ endian =3D 0; /* FIXME */ \ \ @@ -293,11 +294,11 @@ DEFINE_DETECT_FUNCTION(16) DEFINE_DETECT_FUNCTION(32) =20 static int -tight_detect_smooth_image(VncState *vs, int w, int h) +tight_detect_smooth_image(VncState *vs, VncTight *tight, int w, int h) { unsigned int errors; - int compression =3D vs->tight->compression; - int quality =3D vs->tight->quality; + int compression =3D tight->compression; + int quality =3D tight->quality; =20 if (!vs->vd->lossy) { return 0; @@ -309,7 +310,7 @@ tight_detect_smooth_image(VncState *vs, int w, int h) return 0; } =20 - if (vs->tight->quality !=3D (uint8_t)-1) { + if (tight->quality !=3D (uint8_t)-1) { if (w * h < VNC_TIGHT_JPEG_MIN_RECT_SIZE) { return 0; } @@ -320,17 +321,17 @@ tight_detect_smooth_image(VncState *vs, int w, int h) } =20 if (vs->client_pf.bytes_per_pixel =3D=3D 4) { - if (vs->tight->pixel24) { - errors =3D tight_detect_smooth_image24(vs, w, h); - if (vs->tight->quality !=3D (uint8_t)-1) { + if (tight->pixel24) { + errors =3D tight_detect_smooth_image24(vs, tight, w, h); + if (tight->quality !=3D (uint8_t)-1) { return (errors < tight_conf[quality].jpeg_threshold24); } return (errors < tight_conf[compression].gradient_threshold24); } else { - errors =3D tight_detect_smooth_image32(vs, w, h); + errors =3D tight_detect_smooth_image32(vs, tight, w, h); } } else { - errors =3D tight_detect_smooth_image16(vs, w, h); + errors =3D tight_detect_smooth_image16(vs, tight, w, h); } if (quality !=3D (uint8_t)-1) { return (errors < tight_conf[quality].jpeg_threshold); @@ -344,15 +345,15 @@ tight_detect_smooth_image(VncState *vs, int w, int h) #define DEFINE_FILL_PALETTE_FUNCTION(bpp) \ \ static int \ - tight_fill_palette##bpp(VncState *vs, int x, int y, \ - int max, size_t count, \ + tight_fill_palette##bpp(VncState *vs, VncTight *tight, \ + int x, int y, int max, size_t count, \ uint32_t *bg, uint32_t *fg, \ VncPalette *palette) { \ uint##bpp##_t *data; \ uint##bpp##_t c0, c1, ci; \ int i, n0, n1; \ \ - data =3D (uint##bpp##_t *)vs->tight->tight.buffer; \ + data =3D (uint##bpp##_t *)tight->tight.buffer; \ \ c0 =3D data[0]; \ i =3D 1; \ @@ -417,15 +418,15 @@ DEFINE_FILL_PALETTE_FUNCTION(8) DEFINE_FILL_PALETTE_FUNCTION(16) DEFINE_FILL_PALETTE_FUNCTION(32) =20 -static int tight_fill_palette(VncState *vs, int x, int y, +static int tight_fill_palette(VncState *vs, VncTight *tight, int x, int y, size_t count, uint32_t *bg, uint32_t *fg, VncPalette *palette) { int max; =20 - max =3D count / tight_conf[vs->tight->compression].idx_max_colors_divi= sor; + max =3D count / tight_conf[tight->compression].idx_max_colors_divisor; if (max < 2 && - count >=3D tight_conf[vs->tight->compression].mono_min_rect_size) { + count >=3D tight_conf[tight->compression].mono_min_rect_size) { max =3D 2; } if (max >=3D 256) { @@ -434,12 +435,15 @@ static int tight_fill_palette(VncState *vs, int x, in= t y, =20 switch (vs->client_pf.bytes_per_pixel) { case 4: - return tight_fill_palette32(vs, x, y, max, count, bg, fg, palette); + return tight_fill_palette32(vs, tight, x, y, max, count, bg, fg, + palette); case 2: - return tight_fill_palette16(vs, x, y, max, count, bg, fg, palette); + return tight_fill_palette16(vs, tight, x, y, max, count, bg, fg, + palette); default: max =3D 2; - return tight_fill_palette8(vs, x, y, max, count, bg, fg, palette); + return tight_fill_palette8(vs, tight, x, y, max, count, bg, fg, + palette); } return 0; } @@ -547,7 +551,8 @@ DEFINE_MONO_ENCODE_FUNCTION(32) */ =20 static void -tight_filter_gradient24(VncState *vs, uint8_t *buf, int w, int h) +tight_filter_gradient24(VncState *vs, VncTight *tight, uint8_t *buf, + int w, int h) { uint32_t *buf32; uint32_t pix32; @@ -558,7 +563,7 @@ tight_filter_gradient24(VncState *vs, uint8_t *buf, int= w, int h) int x, y, c; =20 buf32 =3D (uint32_t *)buf; - memset(vs->tight->gradient.buffer, 0, w * 3 * sizeof(int)); + memset(tight->gradient.buffer, 0, w * 3 * sizeof(int)); =20 if (1 /* FIXME */) { shift[0] =3D vs->client_pf.rshift; @@ -575,7 +580,7 @@ tight_filter_gradient24(VncState *vs, uint8_t *buf, int= w, int h) upper[c] =3D 0; here[c] =3D 0; } - prev =3D (int *)vs->tight->gradient.buffer; + prev =3D (int *)tight->gradient.buffer; for (x =3D 0; x < w; x++) { pix32 =3D *buf32++; for (c =3D 0; c < 3; c++) { @@ -605,8 +610,8 @@ tight_filter_gradient24(VncState *vs, uint8_t *buf, int= w, int h) #define DEFINE_GRADIENT_FILTER_FUNCTION(bpp) \ \ static void \ - tight_filter_gradient##bpp(VncState *vs, uint##bpp##_t *buf, \ - int w, int h) { \ + tight_filter_gradient##bpp(VncState *vs, VncTight *tight, \ + uint##bpp##_t *buf, int w, int h) { \ uint##bpp##_t pix, diff; \ bool endian; \ int *prev; \ @@ -615,7 +620,7 @@ tight_filter_gradient24(VncState *vs, uint8_t *buf, int= w, int h) int prediction; \ int x, y, c; \ \ - memset(vs->tight->gradient.buffer, 0, w * 3 * sizeof(int)); \ + memset(tight->gradient.buffer, 0, w * 3 * sizeof(int)); \ \ endian =3D 0; /* FIXME */ \ \ @@ -631,7 +636,7 @@ tight_filter_gradient24(VncState *vs, uint8_t *buf, int= w, int h) upper[c] =3D 0; \ here[c] =3D 0; \ } \ - prev =3D (int *)vs->tight->gradient.buffer; = \ + prev =3D (int *)tight->gradient.buffer; \ for (x =3D 0; x < w; x++) { \ pix =3D *buf; \ if (endian) { \ @@ -782,10 +787,10 @@ static void extend_solid_area(VncState *vs, int x, in= t y, int w, int h, *w_ptr +=3D cx - (*x_ptr + *w_ptr); } =20 -static int tight_init_stream(VncState *vs, int stream_id, +static int tight_init_stream(VncState *vs, VncTight *tight, int stream_id, int level, int strategy) { - z_streamp zstream =3D &vs->tight->stream[stream_id]; + z_streamp zstream =3D &tight->stream[stream_id]; =20 if (zstream->opaque =3D=3D NULL) { int err; @@ -803,15 +808,15 @@ static int tight_init_stream(VncState *vs, int stream= _id, return -1; } =20 - vs->tight->levels[stream_id] =3D level; + tight->levels[stream_id] =3D level; zstream->opaque =3D vs; } =20 - if (vs->tight->levels[stream_id] !=3D level) { + if (tight->levels[stream_id] !=3D level) { if (deflateParams(zstream, level, strategy) !=3D Z_OK) { return -1; } - vs->tight->levels[stream_id] =3D level; + tight->levels[stream_id] =3D level; } return 0; } @@ -836,29 +841,29 @@ static void tight_send_compact_size(VncState *vs, siz= e_t len) } } =20 -static int tight_compress_data(VncState *vs, int stream_id, size_t bytes, - int level, int strategy) +static int tight_compress_data(VncState *vs, VncTight *tight, int stream_i= d, + size_t bytes, int level, int strategy) { - z_streamp zstream =3D &vs->tight->stream[stream_id]; + z_streamp zstream =3D &tight->stream[stream_id]; int previous_out; =20 if (bytes < VNC_TIGHT_MIN_TO_COMPRESS) { - vnc_write(vs, vs->tight->tight.buffer, vs->tight->tight.offset); + vnc_write(vs, tight->tight.buffer, tight->tight.offset); return bytes; } =20 - if (tight_init_stream(vs, stream_id, level, strategy)) { + if (tight_init_stream(vs, tight, stream_id, level, strategy)) { return -1; } =20 /* reserve memory in output buffer */ - buffer_reserve(&vs->tight->zlib, bytes + 64); + buffer_reserve(&tight->zlib, bytes + 64); =20 /* set pointers */ - zstream->next_in =3D vs->tight->tight.buffer; - zstream->avail_in =3D vs->tight->tight.offset; - zstream->next_out =3D vs->tight->zlib.buffer + vs->tight->zlib.offset; - zstream->avail_out =3D vs->tight->zlib.capacity - vs->tight->zlib.offs= et; + zstream->next_in =3D tight->tight.buffer; + zstream->avail_in =3D tight->tight.offset; + zstream->next_out =3D tight->zlib.buffer + tight->zlib.offset; + zstream->avail_out =3D tight->zlib.capacity - tight->zlib.offset; previous_out =3D zstream->avail_out; zstream->data_type =3D Z_BINARY; =20 @@ -868,14 +873,14 @@ static int tight_compress_data(VncState *vs, int stre= am_id, size_t bytes, return -1; } =20 - vs->tight->zlib.offset =3D vs->tight->zlib.capacity - zstream->avail_o= ut; + tight->zlib.offset =3D tight->zlib.capacity - zstream->avail_out; /* ...how much data has actually been produced by deflate() */ bytes =3D previous_out - zstream->avail_out; =20 tight_send_compact_size(vs, bytes); - vnc_write(vs, vs->tight->zlib.buffer, bytes); + vnc_write(vs, tight->zlib.buffer, bytes); =20 - buffer_reset(&vs->tight->zlib); + buffer_reset(&tight->zlib); =20 return bytes; } @@ -914,67 +919,69 @@ static void tight_pack24(VncState *vs, uint8_t *buf, = size_t count, size_t *ret) } } =20 -static int send_full_color_rect(VncState *vs, int x, int y, int w, int h) +static int send_full_color_rect(VncState *vs, VncWorker *worker, + int x, int y, int w, int h) { + VncTight *tight =3D &worker->tight; + int level =3D tight_conf[tight->compression].raw_zlib_level; int stream =3D 0; ssize_t bytes; =20 #ifdef CONFIG_PNG - if (tight_can_send_png_rect(vs, w, h)) { - return send_png_rect(vs, x, y, w, h, NULL); + if (tight_can_send_png_rect(vs, tight, w, h)) { + return send_png_rect(vs, worker, x, y, w, h, NULL); } #endif =20 vnc_write_u8(vs, stream << 4); /* no flushing, no filter */ =20 - if (vs->tight->pixel24) { - tight_pack24(vs, vs->tight->tight.buffer, w * h, - &vs->tight->tight.offset); + if (tight->pixel24) { + tight_pack24(vs, tight->tight.buffer, w * h, &tight->tight.offset); bytes =3D 3; } else { bytes =3D vs->client_pf.bytes_per_pixel; } =20 - bytes =3D tight_compress_data(vs, stream, w * h * bytes, - tight_conf[vs->tight->compression].raw_zlib_le= vel, + bytes =3D tight_compress_data(vs, tight, stream, w * h * bytes, level, Z_DEFAULT_STRATEGY); =20 return (bytes >=3D 0); } =20 -static int send_solid_rect(VncState *vs) +static int send_solid_rect(VncState *vs, VncWorker *worker) { + VncTight *tight =3D &worker->tight; size_t bytes; =20 vnc_write_u8(vs, VNC_TIGHT_FILL << 4); /* no flushing, no filter */ =20 - if (vs->tight->pixel24) { - tight_pack24(vs, vs->tight->tight.buffer, 1, &vs->tight->tight.off= set); + if (tight->pixel24) { + tight_pack24(vs, tight->tight.buffer, 1, &tight->tight.offset); bytes =3D 3; } else { bytes =3D vs->client_pf.bytes_per_pixel; } =20 - vnc_write(vs, vs->tight->tight.buffer, bytes); + vnc_write(vs, tight->tight.buffer, bytes); return 1; } =20 -static int send_mono_rect(VncState *vs, int x, int y, +static int send_mono_rect(VncState *vs, VncWorker *worker, int x, int y, int w, int h, uint32_t bg, uint32_t fg) { ssize_t bytes; int stream =3D 1; - int level =3D tight_conf[vs->tight->compression].mono_zlib_level; + int level =3D tight_conf[worker->tight.compression].mono_zlib_level; =20 #ifdef CONFIG_PNG - if (tight_can_send_png_rect(vs, w, h)) { + if (tight_can_send_png_rect(vs, &worker->tight, w, h)) { int ret; int bpp =3D vs->client_pf.bytes_per_pixel * 8; VncPalette *palette =3D palette_new(2, bpp); =20 palette_put(palette, bg); palette_put(palette, fg); - ret =3D send_png_rect(vs, x, y, w, h, palette); + ret =3D send_png_rect(vs, worker, x, y, w, h, palette); palette_destroy(palette); return ret; } @@ -992,12 +999,12 @@ static int send_mono_rect(VncState *vs, int x, int y, uint32_t buf[2] =3D {bg, fg}; size_t ret =3D sizeof (buf); =20 - if (vs->tight->pixel24) { + if (worker->tight.pixel24) { tight_pack24(vs, (unsigned char*)buf, 2, &ret); } vnc_write(vs, buf, ret); =20 - tight_encode_mono_rect32(vs->tight->tight.buffer, w, h, bg, fg); + tight_encode_mono_rect32(worker->tight.tight.buffer, w, h, bg, fg); break; } case 2: @@ -1006,7 +1013,7 @@ static int send_mono_rect(VncState *vs, int x, int y, uint16_t fg16 =3D fg; vnc_write(vs, &bg16, 2); vnc_write(vs, &fg16, 2); - tight_encode_mono_rect16(vs->tight->tight.buffer, w, h, bg, fg); + tight_encode_mono_rect16(worker->tight.tight.buffer, w, h, bg, fg); break; } default: @@ -1015,18 +1022,20 @@ static int send_mono_rect(VncState *vs, int x, int = y, uint8_t fg8 =3D fg; vnc_write_u8(vs, bg8); vnc_write_u8(vs, fg8); - tight_encode_mono_rect8(vs->tight->tight.buffer, w, h, bg, fg); + tight_encode_mono_rect8(worker->tight.tight.buffer, w, h, bg, fg); break; } } - vs->tight->tight.offset =3D bytes; + worker->tight.tight.offset =3D bytes; =20 - bytes =3D tight_compress_data(vs, stream, bytes, level, Z_DEFAULT_STRA= TEGY); + bytes =3D tight_compress_data(vs, &worker->tight, stream, bytes, level, + Z_DEFAULT_STRATEGY); return (bytes >=3D 0); } =20 struct palette_cb_priv { VncState *vs; + VncTight *tight; uint8_t *header; #ifdef CONFIG_PNG png_colorp png_palette; @@ -1046,53 +1055,58 @@ static void write_palette(int idx, uint32_t color, = void *opaque) } } =20 -static bool send_gradient_rect(VncState *vs, int x, int y, int w, int h) +static bool send_gradient_rect(VncState *vs, VncWorker *worker, + int x, int y, int w, int h) { + VncTight *tight =3D &worker->tight; int stream =3D 3; - int level =3D tight_conf[vs->tight->compression].gradient_zlib_level; + int level =3D tight_conf[tight->compression].gradient_zlib_level; ssize_t bytes; =20 if (vs->client_pf.bytes_per_pixel =3D=3D 1) { - return send_full_color_rect(vs, x, y, w, h); + return send_full_color_rect(vs, worker, x, y, w, h); } =20 vnc_write_u8(vs, (stream | VNC_TIGHT_EXPLICIT_FILTER) << 4); vnc_write_u8(vs, VNC_TIGHT_FILTER_GRADIENT); =20 - buffer_reserve(&vs->tight->gradient, w * 3 * sizeof(int)); + buffer_reserve(&tight->gradient, w * 3 * sizeof(int)); =20 - if (vs->tight->pixel24) { - tight_filter_gradient24(vs, vs->tight->tight.buffer, w, h); + if (tight->pixel24) { + tight_filter_gradient24(vs, tight, tight->tight.buffer, w, h); bytes =3D 3; } else if (vs->client_pf.bytes_per_pixel =3D=3D 4) { - tight_filter_gradient32(vs, (uint32_t *)vs->tight->tight.buffer, w= , h); + tight_filter_gradient32(vs, tight, (uint32_t *)tight->tight.buffer, + w, h); bytes =3D 4; } else { - tight_filter_gradient16(vs, (uint16_t *)vs->tight->tight.buffer, w= , h); + tight_filter_gradient16(vs, tight, (uint16_t *)tight->tight.buffer, + w, h); bytes =3D 2; } =20 - buffer_reset(&vs->tight->gradient); + buffer_reset(&tight->gradient); =20 bytes =3D w * h * bytes; - vs->tight->tight.offset =3D bytes; + tight->tight.offset =3D bytes; =20 - bytes =3D tight_compress_data(vs, stream, bytes, + bytes =3D tight_compress_data(vs, tight, stream, bytes, level, Z_FILTERED); return (bytes >=3D 0); } =20 -static int send_palette_rect(VncState *vs, int x, int y, +static int send_palette_rect(VncState *vs, VncWorker *worker, int x, int y, int w, int h, VncPalette *palette) { + VncTight *tight =3D &worker->tight; int stream =3D 2; - int level =3D tight_conf[vs->tight->compression].idx_zlib_level; + int level =3D tight_conf[tight->compression].idx_zlib_level; int colors; ssize_t bytes; =20 #ifdef CONFIG_PNG - if (tight_can_send_png_rect(vs, w, h)) { - return send_png_rect(vs, x, y, w, h, palette); + if (tight_can_send_png_rect(vs, tight, w, h)) { + return send_png_rect(vs, worker, x, y, w, h, palette); } #endif =20 @@ -1107,38 +1121,38 @@ static int send_palette_rect(VncState *vs, int x, i= nt y, { size_t old_offset, offset, palette_sz =3D palette_size(palette); g_autofree uint32_t *header =3D g_new(uint32_t, palette_sz); - struct palette_cb_priv priv =3D { vs, (uint8_t *)header }; + struct palette_cb_priv priv =3D { vs, tight, (uint8_t *)header }; =20 old_offset =3D vs->output.offset; palette_iter(palette, write_palette, &priv); vnc_write(vs, header, palette_sz * sizeof(uint32_t)); =20 - if (vs->tight->pixel24) { + if (tight->pixel24) { tight_pack24(vs, vs->output.buffer + old_offset, colors, &offs= et); vs->output.offset =3D old_offset + offset; } =20 - tight_encode_indexed_rect32(vs->tight->tight.buffer, w * h, palett= e); + tight_encode_indexed_rect32(tight->tight.buffer, w * h, palette); break; } case 2: { size_t palette_sz =3D palette_size(palette); g_autofree uint16_t *header =3D g_new(uint16_t, palette_sz); - struct palette_cb_priv priv =3D { vs, (uint8_t *)header }; + struct palette_cb_priv priv =3D { vs, tight, (uint8_t *)header }; =20 palette_iter(palette, write_palette, &priv); vnc_write(vs, header, palette_sz * sizeof(uint16_t)); - tight_encode_indexed_rect16(vs->tight->tight.buffer, w * h, palett= e); + tight_encode_indexed_rect16(tight->tight.buffer, w * h, palette); break; } default: return -1; /* No palette for 8bits colors */ } bytes =3D w * h; - vs->tight->tight.offset =3D bytes; + tight->tight.offset =3D bytes; =20 - bytes =3D tight_compress_data(vs, stream, bytes, + bytes =3D tight_compress_data(vs, tight, stream, bytes, level, Z_DEFAULT_STRATEGY); return (bytes >=3D 0); } @@ -1154,8 +1168,8 @@ static int send_palette_rect(VncState *vs, int x, int= y, /* This is called once per encoding */ static void jpeg_init_destination(j_compress_ptr cinfo) { - VncState *vs =3D cinfo->client_data; - Buffer *buffer =3D &vs->tight->jpeg; + VncTight *tight =3D cinfo->client_data; + Buffer *buffer =3D &tight->jpeg; =20 cinfo->dest->next_output_byte =3D (JOCTET *)buffer->buffer + buffer->o= ffset; cinfo->dest->free_in_buffer =3D (size_t)(buffer->capacity - buffer->of= fset); @@ -1164,8 +1178,8 @@ static void jpeg_init_destination(j_compress_ptr cinf= o) /* This is called when we ran out of buffer (shouldn't happen!) */ static boolean jpeg_empty_output_buffer(j_compress_ptr cinfo) { - VncState *vs =3D cinfo->client_data; - Buffer *buffer =3D &vs->tight->jpeg; + VncTight *tight =3D cinfo->client_data; + Buffer *buffer =3D &tight->jpeg; =20 buffer->offset =3D buffer->capacity; buffer_reserve(buffer, 2048); @@ -1176,13 +1190,14 @@ static boolean jpeg_empty_output_buffer(j_compress_= ptr cinfo) /* This is called when we are done processing data */ static void jpeg_term_destination(j_compress_ptr cinfo) { - VncState *vs =3D cinfo->client_data; - Buffer *buffer =3D &vs->tight->jpeg; + VncTight *tight =3D cinfo->client_data; + Buffer *buffer =3D &tight->jpeg; =20 buffer->offset =3D buffer->capacity - cinfo->dest->free_in_buffer; } =20 -static int send_jpeg_rect(VncState *vs, int x, int y, int w, int h, int qu= ality) +static int send_jpeg_rect(VncState *vs, VncWorker *worker, + int x, int y, int w, int h, int quality) { struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; @@ -1193,15 +1208,15 @@ static int send_jpeg_rect(VncState *vs, int x, int = y, int w, int h, int quality) int dy; =20 if (surface_bytes_per_pixel(vs->vd->ds) =3D=3D 1) { - return send_full_color_rect(vs, x, y, w, h); + return send_full_color_rect(vs, worker, x, y, w, h); } =20 - buffer_reserve(&vs->tight->jpeg, 2048); + buffer_reserve(&worker->tight.jpeg, 2048); =20 cinfo.err =3D jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); =20 - cinfo.client_data =3D vs; + cinfo.client_data =3D &worker->tight; cinfo.image_width =3D w; cinfo.image_height =3D h; cinfo.input_components =3D 3; @@ -1231,9 +1246,9 @@ static int send_jpeg_rect(VncState *vs, int x, int y,= int w, int h, int quality) =20 vnc_write_u8(vs, VNC_TIGHT_JPEG << 4); =20 - tight_send_compact_size(vs, vs->tight->jpeg.offset); - vnc_write(vs, vs->tight->jpeg.buffer, vs->tight->jpeg.offset); - buffer_reset(&vs->tight->jpeg); + tight_send_compact_size(vs, worker->tight.jpeg.offset); + vnc_write(vs, worker->tight.jpeg.buffer, worker->tight.jpeg.offset); + buffer_reset(&worker->tight.jpeg); =20 return 1; } @@ -1249,7 +1264,7 @@ static void write_png_palette(int idx, uint32_t pix, = void *opaque) VncState *vs =3D priv->vs; png_colorp color =3D &priv->png_palette[idx]; =20 - if (vs->tight->pixel24) + if (priv->tight->pixel24) { color->red =3D (pix >> vs->client_pf.rshift) & vs->client_pf.rmax; color->green =3D (pix >> vs->client_pf.gshift) & vs->client_pf.gma= x; @@ -1274,12 +1289,12 @@ static void write_png_palette(int idx, uint32_t pix= , void *opaque) static void png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) { - VncState *vs =3D png_get_io_ptr(png_ptr); + VncWorker *worker =3D png_get_io_ptr(png_ptr); =20 - buffer_reserve(&vs->tight->png, vs->tight->png.offset + length); - memcpy(vs->tight->png.buffer + vs->tight->png.offset, data, length); + buffer_reserve(&worker->tight.png, worker->tight.png.offset + length); + memcpy(worker->tight.png.buffer + worker->tight.png.offset, data, leng= th); =20 - vs->tight->png.offset +=3D length; + worker->tight.png.offset +=3D length; } =20 static void png_flush_data(png_structp png_ptr) @@ -1296,16 +1311,16 @@ static void vnc_png_free(png_structp png_ptr, png_v= oidp ptr) g_free(ptr); } =20 -static int send_png_rect(VncState *vs, int x, int y, int w, int h, - VncPalette *palette) +static int send_png_rect(VncState *vs, VncWorker *worker, + int x, int y, int w, int h, VncPalette *palette) { png_byte color_type; png_structp png_ptr; png_infop info_ptr; png_colorp png_palette =3D NULL; pixman_image_t *linebuf; - int level =3D tight_png_conf[vs->tight->compression].png_zlib_level; - int filters =3D tight_png_conf[vs->tight->compression].png_filters; + int level =3D tight_png_conf[worker->tight.compression].png_zlib_level; + int filters =3D tight_png_conf[worker->tight.compression].png_filters; uint8_t *buf; int dy; =20 @@ -1322,7 +1337,7 @@ static int send_png_rect(VncState *vs, int x, int y, = int w, int h, return -1; } =20 - png_set_write_fn(png_ptr, (void *) vs, png_write_data, png_flush_data); + png_set_write_fn(png_ptr, worker, png_write_data, png_flush_data); png_set_compression_level(png_ptr, level); png_set_filter(png_ptr, PNG_FILTER_TYPE_DEFAULT, filters); =20 @@ -1343,29 +1358,30 @@ static int send_png_rect(VncState *vs, int x, int y= , int w, int h, palette_size(palette)); =20 priv.vs =3D vs; + priv.tight =3D &worker->tight; priv.png_palette =3D png_palette; palette_iter(palette, write_png_palette, &priv); =20 png_set_PLTE(png_ptr, info_ptr, png_palette, palette_size(palette)= ); =20 if (vs->client_pf.bytes_per_pixel =3D=3D 4) { - tight_encode_indexed_rect32(vs->tight->tight.buffer, w * h, + tight_encode_indexed_rect32(worker->tight.tight.buffer, w * h, palette); } else { - tight_encode_indexed_rect16(vs->tight->tight.buffer, w * h, + tight_encode_indexed_rect16(worker->tight.tight.buffer, w * h, palette); } } =20 png_write_info(png_ptr, info_ptr); =20 - buffer_reserve(&vs->tight->png, 2048); + buffer_reserve(&worker->tight.png, 2048); linebuf =3D qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, w); buf =3D (uint8_t *)pixman_image_get_data(linebuf); for (dy =3D 0; dy < h; dy++) { if (color_type =3D=3D PNG_COLOR_TYPE_PALETTE) { - memcpy(buf, vs->tight->tight.buffer + (dy * w), w); + memcpy(buf, worker->tight.tight.buffer + (dy * w), w); } else { qemu_pixman_linebuf_fill(linebuf, vs->vd->server, w, x, y + dy= ); } @@ -1383,46 +1399,47 @@ static int send_png_rect(VncState *vs, int x, int y= , int w, int h, =20 vnc_write_u8(vs, VNC_TIGHT_PNG << 4); =20 - tight_send_compact_size(vs, vs->tight->png.offset); - vnc_write(vs, vs->tight->png.buffer, vs->tight->png.offset); - buffer_reset(&vs->tight->png); + tight_send_compact_size(vs, worker->tight.png.offset); + vnc_write(vs, worker->tight.png.buffer, worker->tight.png.offset); + buffer_reset(&worker->tight.png); return 1; } #endif /* CONFIG_PNG */ =20 -static void vnc_tight_start(VncState *vs) +static void vnc_tight_start(VncState *vs, VncTight *tight) { - buffer_reset(&vs->tight->tight); + buffer_reset(&tight->tight); =20 // make the output buffer be the zlib buffer, so we can compress it la= ter - vs->tight->tmp =3D vs->output; - vs->output =3D vs->tight->tight; + tight->tmp =3D vs->output; + vs->output =3D tight->tight; } =20 -static void vnc_tight_stop(VncState *vs) +static void vnc_tight_stop(VncState *vs, VncTight *tight) { // switch back to normal output/zlib buffers - vs->tight->tight =3D vs->output; - vs->output =3D vs->tight->tmp; + tight->tight =3D vs->output; + vs->output =3D tight->tmp; } =20 -static int send_sub_rect_nojpeg(VncState *vs, int x, int y, int w, int h, +static int send_sub_rect_nojpeg(VncState *vs, VncWorker *worker, + int x, int y, int w, int h, int bg, int fg, int colors, VncPalette *pa= lette) { int ret; =20 if (colors =3D=3D 0) { - if (tight_detect_smooth_image(vs, w, h)) { - ret =3D send_gradient_rect(vs, x, y, w, h); + if (tight_detect_smooth_image(vs, &worker->tight, w, h)) { + ret =3D send_gradient_rect(vs, worker, x, y, w, h); } else { - ret =3D send_full_color_rect(vs, x, y, w, h); + ret =3D send_full_color_rect(vs, worker, x, y, w, h); } } else if (colors =3D=3D 1) { - ret =3D send_solid_rect(vs); + ret =3D send_solid_rect(vs, worker); } else if (colors =3D=3D 2) { - ret =3D send_mono_rect(vs, x, y, w, h, bg, fg); + ret =3D send_mono_rect(vs, worker, x, y, w, h, bg, fg); } else if (colors <=3D 256) { - ret =3D send_palette_rect(vs, x, y, w, h, palette); + ret =3D send_palette_rect(vs, worker, x, y, w, h, palette); } else { ret =3D 0; } @@ -1430,34 +1447,35 @@ static int send_sub_rect_nojpeg(VncState *vs, int x= , int y, int w, int h, } =20 #ifdef CONFIG_VNC_JPEG -static int send_sub_rect_jpeg(VncState *vs, int x, int y, int w, int h, +static int send_sub_rect_jpeg(VncState *vs, VncWorker *worker, + int x, int y, int w, int h, int bg, int fg, int colors, VncPalette *palette, bool force) { int ret; =20 if (colors =3D=3D 0) { - if (force || (tight_jpeg_conf[vs->tight->quality].jpeg_full && - tight_detect_smooth_image(vs, w, h))) { - int quality =3D tight_conf[vs->tight->quality].jpeg_quality; + if (force || (tight_jpeg_conf[worker->tight.quality].jpeg_full && + tight_detect_smooth_image(vs, &worker->tight, w, h))= ) { + int quality =3D tight_conf[worker->tight.quality].jpeg_quality; =20 - ret =3D send_jpeg_rect(vs, x, y, w, h, quality); + ret =3D send_jpeg_rect(vs, worker, x, y, w, h, quality); } else { - ret =3D send_full_color_rect(vs, x, y, w, h); + ret =3D send_full_color_rect(vs, worker, x, y, w, h); } } else if (colors =3D=3D 1) { - ret =3D send_solid_rect(vs); + ret =3D send_solid_rect(vs, worker); } else if (colors =3D=3D 2) { - ret =3D send_mono_rect(vs, x, y, w, h, bg, fg); + ret =3D send_mono_rect(vs, worker, x, y, w, h, bg, fg); } else if (colors <=3D 256) { if (force || (colors > 96 && - tight_jpeg_conf[vs->tight->quality].jpeg_idx && - tight_detect_smooth_image(vs, w, h))) { - int quality =3D tight_conf[vs->tight->quality].jpeg_quality; + tight_jpeg_conf[worker->tight.quality].jpeg_idx && + tight_detect_smooth_image(vs, &worker->tight, w, h))= ) { + int quality =3D tight_conf[worker->tight.quality].jpeg_quality; =20 - ret =3D send_jpeg_rect(vs, x, y, w, h, quality); + ret =3D send_jpeg_rect(vs, worker, x, y, w, h, quality); } else { - ret =3D send_palette_rect(vs, x, y, w, h, palette); + ret =3D send_palette_rect(vs, worker, x, y, w, h, palette); } } else { ret =3D 0; @@ -1475,8 +1493,10 @@ static void vnc_tight_cleanup(Notifier *n, void *val= ue) color_count_palette =3D NULL; } =20 -static int send_sub_rect(VncState *vs, int x, int y, int w, int h) +static int send_sub_rect(VncState *vs, VncWorker *worker, + int x, int y, int w, int h) { + VncTight *tight =3D &worker->tight; uint32_t bg =3D 0, fg =3D 0; int colors; int ret =3D 0; @@ -1491,57 +1511,59 @@ static int send_sub_rect(VncState *vs, int x, int y= , int w, int h) qemu_thread_atexit_add(&vnc_tight_cleanup_notifier); } =20 - vnc_framebuffer_update(vs, x, y, w, h, vs->tight->type); + vnc_framebuffer_update(vs, x, y, w, h, tight->type); =20 - vnc_tight_start(vs); + vnc_tight_start(vs, tight); vnc_raw_send_framebuffer_update(vs, x, y, w, h); - vnc_tight_stop(vs); + vnc_tight_stop(vs, tight); =20 #ifdef CONFIG_VNC_JPEG - if (!vs->vd->non_adaptive && vs->tight->quality !=3D (uint8_t)-1) { + if (!vs->vd->non_adaptive && tight->quality !=3D (uint8_t)-1) { double freq =3D vnc_update_freq(vs, x, y, w, h); =20 - if (freq < tight_jpeg_conf[vs->tight->quality].jpeg_freq_min) { + if (freq < tight_jpeg_conf[tight->quality].jpeg_freq_min) { allow_jpeg =3D false; } - if (freq >=3D tight_jpeg_conf[vs->tight->quality].jpeg_freq_thresh= old) { + if (freq >=3D tight_jpeg_conf[tight->quality].jpeg_freq_threshold)= { force_jpeg =3D true; - vnc_sent_lossy_rect(vs, x, y, w, h); + vnc_sent_lossy_rect(worker, x, y, w, h); } } #endif =20 - colors =3D tight_fill_palette(vs, x, y, w * h, &bg, &fg, color_count_p= alette); + colors =3D tight_fill_palette(vs, tight, x, y, w * h, &bg, &fg, + color_count_palette); =20 #ifdef CONFIG_VNC_JPEG - if (allow_jpeg && vs->tight->quality !=3D (uint8_t)-1) { - ret =3D send_sub_rect_jpeg(vs, x, y, w, h, bg, fg, colors, + if (allow_jpeg && tight->quality !=3D (uint8_t)-1) { + ret =3D send_sub_rect_jpeg(vs, worker, x, y, w, h, bg, fg, colors, color_count_palette, force_jpeg); } else { - ret =3D send_sub_rect_nojpeg(vs, x, y, w, h, bg, fg, colors, - color_count_palette); + ret =3D send_sub_rect_nojpeg(vs, worker, x, y, w, h, bg, fg, + colors, color_count_palette); } #else - ret =3D send_sub_rect_nojpeg(vs, x, y, w, h, bg, fg, colors, + ret =3D send_sub_rect_nojpeg(vs, worker, x, y, w, h, bg, fg, colors, color_count_palette); #endif =20 return ret; } =20 -static int send_sub_rect_solid(VncState *vs, int x, int y, int w, int h) +static int send_sub_rect_solid(VncState *vs, VncWorker *worker, + int x, int y, int w, int h) { - vnc_framebuffer_update(vs, x, y, w, h, vs->tight->type); + vnc_framebuffer_update(vs, x, y, w, h, worker->tight.type); =20 - vnc_tight_start(vs); + vnc_tight_start(vs, &worker->tight); vnc_raw_send_framebuffer_update(vs, x, y, w, h); - vnc_tight_stop(vs); + vnc_tight_stop(vs, &worker->tight); =20 - return send_solid_rect(vs); + return send_solid_rect(vs, worker); } =20 -static int send_rect_simple(VncState *vs, int x, int y, int w, int h, - bool split) +static int send_rect_simple(VncState *vs, VncWorker *worker, + int x, int y, int w, int h, bool split) { int max_size, max_width; int max_sub_width, max_sub_height; @@ -1549,8 +1571,8 @@ static int send_rect_simple(VncState *vs, int x, int = y, int w, int h, int rw, rh; int n =3D 0; =20 - max_size =3D tight_conf[vs->tight->compression].max_rect_size; - max_width =3D tight_conf[vs->tight->compression].max_rect_width; + max_size =3D tight_conf[worker->tight.compression].max_rect_size; + max_width =3D tight_conf[worker->tight.compression].max_rect_width; =20 if (split && (w > max_width || w * h > max_size)) { max_sub_width =3D (w > max_width) ? max_width : w; @@ -1560,18 +1582,18 @@ static int send_rect_simple(VncState *vs, int x, in= t y, int w, int h, for (dx =3D 0; dx < w; dx +=3D max_width) { rw =3D MIN(max_sub_width, w - dx); rh =3D MIN(max_sub_height, h - dy); - n +=3D send_sub_rect(vs, x+dx, y+dy, rw, rh); + n +=3D send_sub_rect(vs, worker, x + dx, y + dy, rw, rh); } } } else { - n +=3D send_sub_rect(vs, x, y, w, h); + n +=3D send_sub_rect(vs, worker, x, y, w, h); } =20 return n; } =20 -static int find_large_solid_color_rect(VncState *vs, int x, int y, - int w, int h, int max_rows) +static int find_large_solid_color_rect(VncState *vs, VncWorker *worker, + int x, int y, int w, int h, int max= _rows) { int dx, dy, dw, dh; int n =3D 0; @@ -1583,7 +1605,7 @@ static int find_large_solid_color_rect(VncState *vs, = int x, int y, /* If a rectangle becomes too large, send its upper part now. */ =20 if (dy - y >=3D max_rows) { - n +=3D send_rect_simple(vs, x, y, w, max_rows, true); + n +=3D send_rect_simple(vs, worker, x, y, w, max_rows, true); y +=3D max_rows; h -=3D max_rows; } @@ -1622,26 +1644,28 @@ static int find_large_solid_color_rect(VncState *vs= , int x, int y, /* Send rectangles at top and left to solid-color area. */ =20 if (y_best !=3D y) { - n +=3D send_rect_simple(vs, x, y, w, y_best-y, true); + n +=3D send_rect_simple(vs, worker, x, y, w, y_best - y, t= rue); } if (x_best !=3D x) { - n +=3D tight_send_framebuffer_update(vs, x, y_best, + n +=3D tight_send_framebuffer_update(vs, worker, x, y_best, x_best-x, h_best); } =20 /* Send solid-color rectangle. */ - n +=3D send_sub_rect_solid(vs, x_best, y_best, w_best, h_best); + n +=3D send_sub_rect_solid(vs, worker, + x_best, y_best, w_best, h_best); =20 /* Send remaining rectangles (at right and bottom). */ =20 if (x_best + w_best !=3D x + w) { - n +=3D tight_send_framebuffer_update(vs, x_best+w_best, + n +=3D tight_send_framebuffer_update(vs, worker, x_best + = w_best, y_best, w-(x_best-x)-w_best, h_best); } if (y_best + h_best !=3D y + h) { - n +=3D tight_send_framebuffer_update(vs, x, y_best+h_best, + n +=3D tight_send_framebuffer_update(vs, worker, + x, y_best + h_best, w, h-(y_best-y)-h_best); } =20 @@ -1649,73 +1673,73 @@ static int find_large_solid_color_rect(VncState *vs= , int x, int y, return n; } } - return n + send_rect_simple(vs, x, y, w, h, true); + return n + send_rect_simple(vs, worker, x, y, w, h, true); } =20 -static int tight_send_framebuffer_update(VncState *vs, int x, int y, - int w, int h) +static int tight_send_framebuffer_update(VncState *vs, VncWorker *worker, + int x, int y, int w, int h) { int max_rows; =20 if (vs->client_pf.bytes_per_pixel =3D=3D 4 && vs->client_pf.rmax =3D= =3D 0xFF && vs->client_pf.bmax =3D=3D 0xFF && vs->client_pf.gmax =3D=3D 0xFF) { - vs->tight->pixel24 =3D true; + worker->tight.pixel24 =3D true; } else { - vs->tight->pixel24 =3D false; + worker->tight.pixel24 =3D false; } =20 #ifdef CONFIG_VNC_JPEG - if (vs->tight->quality !=3D (uint8_t)-1) { + if (worker->tight.quality !=3D (uint8_t)-1) { double freq =3D vnc_update_freq(vs, x, y, w, h); =20 - if (freq > tight_jpeg_conf[vs->tight->quality].jpeg_freq_threshold= ) { - return send_rect_simple(vs, x, y, w, h, false); + if (freq > tight_jpeg_conf[worker->tight.quality].jpeg_freq_thresh= old) { + return send_rect_simple(vs, worker, x, y, w, h, false); } } #endif =20 if (w * h < VNC_TIGHT_MIN_SPLIT_RECT_SIZE) { - return send_rect_simple(vs, x, y, w, h, true); + return send_rect_simple(vs, worker, x, y, w, h, true); } =20 /* Calculate maximum number of rows in one non-solid rectangle. */ =20 - max_rows =3D tight_conf[vs->tight->compression].max_rect_size; - max_rows /=3D MIN(tight_conf[vs->tight->compression].max_rect_width, w= ); + max_rows =3D tight_conf[worker->tight.compression].max_rect_size; + max_rows /=3D MIN(tight_conf[worker->tight.compression].max_rect_width= , w); =20 - return find_large_solid_color_rect(vs, x, y, w, h, max_rows); + return find_large_solid_color_rect(vs, worker, x, y, w, h, max_rows); } =20 -int vnc_tight_send_framebuffer_update(VncState *vs, int x, int y, - int w, int h) +int vnc_tight_send_framebuffer_update(VncState *vs, VncWorker *worker, + int x, int y, int w, int h) { - vs->tight->type =3D VNC_ENCODING_TIGHT; - return tight_send_framebuffer_update(vs, x, y, w, h); + worker->tight.type =3D VNC_ENCODING_TIGHT; + return tight_send_framebuffer_update(vs, worker, x, y, w, h); } =20 -int vnc_tight_png_send_framebuffer_update(VncState *vs, int x, int y, - int w, int h) +int vnc_tight_png_send_framebuffer_update(VncState *vs, VncWorker *worker, + int x, int y, int w, int h) { - vs->tight->type =3D VNC_ENCODING_TIGHT_PNG; - return tight_send_framebuffer_update(vs, x, y, w, h); + worker->tight.type =3D VNC_ENCODING_TIGHT_PNG; + return tight_send_framebuffer_update(vs, worker, x, y, w, h); } =20 -void vnc_tight_clear(VncState *vs) +void vnc_tight_clear(VncWorker *worker) { int i; - for (i =3D 0; i < ARRAY_SIZE(vs->tight->stream); i++) { - if (vs->tight->stream[i].opaque) { - deflateEnd(&vs->tight->stream[i]); + for (i =3D 0; i < ARRAY_SIZE(worker->tight.stream); i++) { + if (worker->tight.stream[i].opaque) { + deflateEnd(&worker->tight.stream[i]); } } =20 - buffer_free(&vs->tight->tight); - buffer_free(&vs->tight->zlib); - buffer_free(&vs->tight->gradient); + buffer_free(&worker->tight.tight); + buffer_free(&worker->tight.zlib); + buffer_free(&worker->tight.gradient); #ifdef CONFIG_VNC_JPEG - buffer_free(&vs->tight->jpeg); + buffer_free(&worker->tight.jpeg); #endif #ifdef CONFIG_PNG - buffer_free(&vs->tight->png); + buffer_free(&worker->tight.png); #endif } diff --git a/ui/vnc-enc-zlib.c b/ui/vnc-enc-zlib.c index 52e9193eab..a6d287118a 100644 --- a/ui/vnc-enc-zlib.c +++ b/ui/vnc-enc-zlib.c @@ -46,23 +46,23 @@ void vnc_zlib_zfree(void *x, void *addr) g_free(addr); } =20 -static void vnc_zlib_start(VncState *vs) +static void vnc_zlib_start(VncState *vs, VncWorker *worker) { - buffer_reset(&vs->zlib->zlib); + buffer_reset(&worker->zlib.zlib); =20 // make the output buffer be the zlib buffer, so we can compress it la= ter - vs->zlib->tmp =3D vs->output; - vs->output =3D vs->zlib->zlib; + worker->zlib.tmp =3D vs->output; + vs->output =3D worker->zlib.zlib; } =20 -static int vnc_zlib_stop(VncState *vs) +static int vnc_zlib_stop(VncState *vs, VncWorker *worker) { - z_streamp zstream =3D &vs->zlib->stream; + z_streamp zstream =3D &worker->zlib.stream; int previous_out; =20 // switch back to normal output/zlib buffers - vs->zlib->zlib =3D vs->output; - vs->output =3D vs->zlib->tmp; + worker->zlib.zlib =3D vs->output; + vs->output =3D worker->zlib.tmp; =20 // compress the zlib buffer =20 @@ -76,7 +76,7 @@ static int vnc_zlib_stop(VncState *vs) zstream->zalloc =3D vnc_zlib_zalloc; zstream->zfree =3D vnc_zlib_zfree; =20 - err =3D deflateInit2(zstream, vs->tight->compression, Z_DEFLATED, + err =3D deflateInit2(zstream, worker->tight.compression, Z_DEFLATE= D, MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY); =20 @@ -85,24 +85,24 @@ static int vnc_zlib_stop(VncState *vs) return -1; } =20 - vs->zlib->level =3D vs->tight->compression; + worker->zlib.level =3D worker->tight.compression; zstream->opaque =3D vs; } =20 - if (vs->tight->compression !=3D vs->zlib->level) { - if (deflateParams(zstream, vs->tight->compression, + if (worker->tight.compression !=3D worker->zlib.level) { + if (deflateParams(zstream, worker->tight.compression, Z_DEFAULT_STRATEGY) !=3D Z_OK) { return -1; } - vs->zlib->level =3D vs->tight->compression; + worker->zlib.level =3D worker->tight.compression; } =20 // reserve memory in output buffer - buffer_reserve(&vs->output, vs->zlib->zlib.offset + 64); + buffer_reserve(&vs->output, worker->zlib.zlib.offset + 64); =20 // set pointers - zstream->next_in =3D vs->zlib->zlib.buffer; - zstream->avail_in =3D vs->zlib->zlib.offset; + zstream->next_in =3D worker->zlib.zlib.buffer; + zstream->avail_in =3D worker->zlib.zlib.offset; zstream->next_out =3D vs->output.buffer + vs->output.offset; zstream->avail_out =3D vs->output.capacity - vs->output.offset; previous_out =3D zstream->avail_out; @@ -118,7 +118,8 @@ static int vnc_zlib_stop(VncState *vs) return previous_out - zstream->avail_out; } =20 -int vnc_zlib_send_framebuffer_update(VncState *vs, int x, int y, int w, in= t h) +int vnc_zlib_send_framebuffer_update(VncState *vs, VncWorker *worker, + int x, int y, int w, int h) { int old_offset, new_offset, bytes_written; =20 @@ -129,9 +130,9 @@ int vnc_zlib_send_framebuffer_update(VncState *vs, int = x, int y, int w, int h) vnc_write_s32(vs, 0); =20 // compress the stream - vnc_zlib_start(vs); + vnc_zlib_start(vs, worker); vnc_raw_send_framebuffer_update(vs, x, y, w, h); - bytes_written =3D vnc_zlib_stop(vs); + bytes_written =3D vnc_zlib_stop(vs, worker); =20 if (bytes_written =3D=3D -1) return 0; @@ -145,10 +146,10 @@ int vnc_zlib_send_framebuffer_update(VncState *vs, in= t x, int y, int w, int h) return 1; } =20 -void vnc_zlib_clear(VncState *vs) +void vnc_zlib_clear(VncWorker *worker) { - if (vs->zlib->stream.opaque) { - deflateEnd(&vs->zlib->stream); + if (worker->zlib.stream.opaque) { + deflateEnd(&worker->zlib.stream); } - buffer_free(&vs->zlib->zlib); + buffer_free(&worker->zlib.zlib); } diff --git a/ui/vnc-enc-zrle.c b/ui/vnc-enc-zrle.c index 97ec6c7119..7679014c9e 100644 --- a/ui/vnc-enc-zrle.c +++ b/ui/vnc-enc-zrle.c @@ -35,45 +35,45 @@ static const int bits_per_packed_pixel[] =3D { }; =20 =20 -static void vnc_zrle_start(VncState *vs) +static void vnc_zrle_start(VncState *vs, VncZrle *zrle) { - buffer_reset(&vs->zrle->zrle); + buffer_reset(&zrle->zrle); =20 /* make the output buffer be the zlib buffer, so we can compress it la= ter */ - vs->zrle->tmp =3D vs->output; - vs->output =3D vs->zrle->zrle; + zrle->tmp =3D vs->output; + vs->output =3D zrle->zrle; } =20 -static void vnc_zrle_stop(VncState *vs) +static void vnc_zrle_stop(VncState *vs, VncZrle *zrle) { /* switch back to normal output/zlib buffers */ - vs->zrle->zrle =3D vs->output; - vs->output =3D vs->zrle->tmp; + zrle->zrle =3D vs->output; + vs->output =3D zrle->tmp; } =20 -static void *zrle_convert_fb(VncState *vs, int x, int y, int w, int h, - int bpp) +static void *zrle_convert_fb(VncState *vs, VncZrle *zrle, + int x, int y, int w, int h, int bpp) { Buffer tmp; =20 - buffer_reset(&vs->zrle->fb); - buffer_reserve(&vs->zrle->fb, w * h * bpp + bpp); + buffer_reset(&zrle->fb); + buffer_reserve(&zrle->fb, w * h * bpp + bpp); =20 tmp =3D vs->output; - vs->output =3D vs->zrle->fb; + vs->output =3D zrle->fb; =20 vnc_raw_send_framebuffer_update(vs, x, y, w, h); =20 - vs->zrle->fb =3D vs->output; + zrle->fb =3D vs->output; vs->output =3D tmp; - return vs->zrle->fb.buffer; + return zrle->fb.buffer; } =20 -static int zrle_compress_data(VncState *vs, int level) +static int zrle_compress_data(VncState *vs, VncZrle *zrle, int level) { - z_streamp zstream =3D &vs->zrle->stream; + z_streamp zstream =3D &zrle->stream; =20 - buffer_reset(&vs->zrle->zlib); + buffer_reset(&zrle->zlib); =20 if (zstream->opaque !=3D vs) { int err; @@ -93,13 +93,13 @@ static int zrle_compress_data(VncState *vs, int level) } =20 /* reserve memory in output buffer */ - buffer_reserve(&vs->zrle->zlib, vs->zrle->zrle.offset + 64); + buffer_reserve(&zrle->zlib, zrle->zrle.offset + 64); =20 /* set pointers */ - zstream->next_in =3D vs->zrle->zrle.buffer; - zstream->avail_in =3D vs->zrle->zrle.offset; - zstream->next_out =3D vs->zrle->zlib.buffer; - zstream->avail_out =3D vs->zrle->zlib.capacity; + zstream->next_in =3D zrle->zrle.buffer; + zstream->avail_in =3D zrle->zrle.offset; + zstream->next_out =3D zrle->zlib.buffer; + zstream->avail_out =3D zrle->zlib.capacity; zstream->data_type =3D Z_BINARY; =20 /* start encoding */ @@ -108,8 +108,8 @@ static int zrle_compress_data(VncState *vs, int level) return -1; } =20 - vs->zrle->zlib.offset =3D vs->zrle->zlib.capacity - zstream->avail_out; - return vs->zrle->zlib.offset; + zrle->zlib.offset =3D zrle->zlib.capacity - zstream->avail_out; + return zrle->zlib.offset; } =20 /* Try to work out whether to use RLE and/or a palette. We do this by @@ -252,21 +252,21 @@ static void zrle_write_u8(VncState *vs, uint8_t value) #undef ZRLE_COMPACT_PIXEL #undef ZRLE_BPP =20 -static int zrle_send_framebuffer_update(VncState *vs, int x, int y, - int w, int h) +static int zrle_send_framebuffer_update(VncState *vs, VncWorker *worker, + int x, int y, int w, int h) { bool be =3D vs->client_endian =3D=3D G_BIG_ENDIAN; size_t bytes; int zywrle_level; =20 - if (vs->zrle->type =3D=3D VNC_ENCODING_ZYWRLE) { - if (!vs->vd->lossy || vs->tight->quality =3D=3D (uint8_t)-1 - || vs->tight->quality =3D=3D 9) { + if (worker->zrle.type =3D=3D VNC_ENCODING_ZYWRLE) { + if (!vs->vd->lossy || worker->tight.quality =3D=3D (uint8_t)-1 + || worker->tight.quality =3D=3D 9) { zywrle_level =3D 0; - vs->zrle->type =3D VNC_ENCODING_ZRLE; - } else if (vs->tight->quality < 3) { + worker->zrle.type =3D VNC_ENCODING_ZRLE; + } else if (worker->tight.quality < 3) { zywrle_level =3D 3; - } else if (vs->tight->quality < 6) { + } else if (worker->tight.quality < 6) { zywrle_level =3D 2; } else { zywrle_level =3D 1; @@ -275,25 +275,25 @@ static int zrle_send_framebuffer_update(VncState *vs,= int x, int y, zywrle_level =3D 0; } =20 - vnc_zrle_start(vs); + vnc_zrle_start(vs, &worker->zrle); =20 switch (vs->client_pf.bytes_per_pixel) { case 1: - zrle_encode_8ne(vs, x, y, w, h, zywrle_level); + zrle_encode_8ne(vs, &worker->zrle, x, y, w, h, zywrle_level); break; =20 case 2: if (vs->client_pf.gmax > 0x1F) { if (be) { - zrle_encode_16be(vs, x, y, w, h, zywrle_level); + zrle_encode_16be(vs, &worker->zrle, x, y, w, h, zywrle_lev= el); } else { - zrle_encode_16le(vs, x, y, w, h, zywrle_level); + zrle_encode_16le(vs, &worker->zrle, x, y, w, h, zywrle_lev= el); } } else { if (be) { - zrle_encode_15be(vs, x, y, w, h, zywrle_level); + zrle_encode_15be(vs, &worker->zrle, x, y, w, h, zywrle_lev= el); } else { - zrle_encode_15le(vs, x, y, w, h, zywrle_level); + zrle_encode_15le(vs, &worker->zrle, x, y, w, h, zywrle_lev= el); } } break; @@ -314,53 +314,55 @@ static int zrle_send_framebuffer_update(VncState *vs,= int x, int y, =20 if ((fits_in_ls3bytes && !be) || (fits_in_ms3bytes && be)) { if (be) { - zrle_encode_24abe(vs, x, y, w, h, zywrle_level); + zrle_encode_24abe(vs, &worker->zrle, x, y, w, h, zywrle_le= vel); } else { - zrle_encode_24ale(vs, x, y, w, h, zywrle_level); + zrle_encode_24ale(vs, &worker->zrle, x, y, w, h, zywrle_le= vel); } } else if ((fits_in_ls3bytes && be) || (fits_in_ms3bytes && !be)) { if (be) { - zrle_encode_24bbe(vs, x, y, w, h, zywrle_level); + zrle_encode_24bbe(vs, &worker->zrle, x, y, w, h, zywrle_le= vel); } else { - zrle_encode_24ble(vs, x, y, w, h, zywrle_level); + zrle_encode_24ble(vs, &worker->zrle, x, y, w, h, zywrle_le= vel); } } else { if (be) { - zrle_encode_32be(vs, x, y, w, h, zywrle_level); + zrle_encode_32be(vs, &worker->zrle, x, y, w, h, zywrle_lev= el); } else { - zrle_encode_32le(vs, x, y, w, h, zywrle_level); + zrle_encode_32le(vs, &worker->zrle, x, y, w, h, zywrle_lev= el); } } } break; } =20 - vnc_zrle_stop(vs); - bytes =3D zrle_compress_data(vs, Z_DEFAULT_COMPRESSION); - vnc_framebuffer_update(vs, x, y, w, h, vs->zrle->type); + vnc_zrle_stop(vs, &worker->zrle); + bytes =3D zrle_compress_data(vs, &worker->zrle, Z_DEFAULT_COMPRESSION); + vnc_framebuffer_update(vs, x, y, w, h, worker->zrle.type); vnc_write_u32(vs, bytes); - vnc_write(vs, vs->zrle->zlib.buffer, vs->zrle->zlib.offset); + vnc_write(vs, worker->zrle.zlib.buffer, worker->zrle.zlib.offset); return 1; } =20 -int vnc_zrle_send_framebuffer_update(VncState *vs, int x, int y, int w, in= t h) +int vnc_zrle_send_framebuffer_update(VncState *vs, VncWorker *worker, + int x, int y, int w, int h) { - vs->zrle->type =3D VNC_ENCODING_ZRLE; - return zrle_send_framebuffer_update(vs, x, y, w, h); + worker->zrle.type =3D VNC_ENCODING_ZRLE; + return zrle_send_framebuffer_update(vs, worker, x, y, w, h); } =20 -int vnc_zywrle_send_framebuffer_update(VncState *vs, int x, int y, int w, = int h) +int vnc_zywrle_send_framebuffer_update(VncState *vs, VncWorker *worker, + int x, int y, int w, int h) { - vs->zrle->type =3D VNC_ENCODING_ZYWRLE; - return zrle_send_framebuffer_update(vs, x, y, w, h); + worker->zrle.type =3D VNC_ENCODING_ZYWRLE; + return zrle_send_framebuffer_update(vs, worker, x, y, w, h); } =20 -void vnc_zrle_clear(VncState *vs) +void vnc_zrle_clear(VncWorker *worker) { - if (vs->zrle->stream.opaque) { - deflateEnd(&vs->zrle->stream); + if (worker->zrle.stream.opaque) { + deflateEnd(&worker->zrle.stream); } - buffer_free(&vs->zrle->zrle); - buffer_free(&vs->zrle->fb); - buffer_free(&vs->zrle->zlib); + buffer_free(&worker->zrle.zrle); + buffer_free(&worker->zrle.fb); + buffer_free(&worker->zrle.zlib); } diff --git a/ui/vnc-jobs.c b/ui/vnc-jobs.c index d3486af9e2..bed33950a8 100644 --- a/ui/vnc-jobs.c +++ b/ui/vnc-jobs.c @@ -185,14 +185,10 @@ static void vnc_async_encoding_start(VncState *orig, = VncState *local) local->vnc_encoding =3D orig->vnc_encoding; local->features =3D orig->features; local->vd =3D orig->vd; - local->lossy_rect =3D orig->lossy_rect; local->write_pixels =3D orig->write_pixels; local->client_pf =3D orig->client_pf; local->client_endian =3D orig->client_endian; - local->tight =3D orig->tight; - local->zlib =3D orig->zlib; local->hextile =3D orig->hextile; - local->zrle =3D orig->zrle; local->client_width =3D orig->client_width; local->client_height =3D orig->client_height; } @@ -200,11 +196,7 @@ static void vnc_async_encoding_start(VncState *orig, V= ncState *local) static void vnc_async_encoding_end(VncState *orig, VncState *local) { buffer_free(&local->output); - orig->tight =3D local->tight; - orig->zlib =3D local->zlib; orig->hextile =3D local->hextile; - orig->zrle =3D local->zrle; - orig->lossy_rect =3D local->lossy_rect; } =20 static bool vnc_worker_clamp_rect(VncState *vs, VncJob *job, VncRect *rect) @@ -237,6 +229,7 @@ static bool vnc_worker_clamp_rect(VncState *vs, VncJob = *job, VncRect *rect) =20 static int vnc_worker_thread_loop(VncJobQueue *queue) { + VncConnection *vc; VncJob *job; VncRectEntry *entry, *tmp; VncState vs =3D {}; @@ -256,6 +249,7 @@ static int vnc_worker_thread_loop(VncJobQueue *queue) } =20 assert(job->vs->magic =3D=3D VNC_MAGIC); + vc =3D container_of(job->vs, VncConnection, vs); =20 vnc_lock_output(job->vs); if (job->vs->ioc =3D=3D NULL || job->vs->abort =3D=3D true) { @@ -295,7 +289,8 @@ static int vnc_worker_thread_loop(VncJobQueue *queue) } =20 if (vnc_worker_clamp_rect(&vs, job, &entry->rect)) { - n =3D vnc_send_framebuffer_update(&vs, entry->rect.x, entry->r= ect.y, + n =3D vnc_send_framebuffer_update(&vs, &vc->worker, + entry->rect.x, entry->rect.y, entry->rect.w, entry->rect.h); =20 if (n >=3D 0) { diff --git a/ui/vnc.c b/ui/vnc.c index ab74154e4c..1df35832d5 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -56,11 +56,6 @@ #include "io/dns-resolver.h" #include "monitor/monitor.h" =20 -typedef struct VncConnection { - VncState vs; - VncZlib zlib; -} VncConnection; - #define VNC_REFRESH_INTERVAL_BASE GUI_REFRESH_INTERVAL_DEFAULT #define VNC_REFRESH_INTERVAL_INC 50 #define VNC_REFRESH_INTERVAL_MAX GUI_REFRESH_INTERVAL_IDLE @@ -951,29 +946,30 @@ int vnc_raw_send_framebuffer_update(VncState *vs, int= x, int y, int w, int h) return 1; } =20 -int vnc_send_framebuffer_update(VncState *vs, int x, int y, int w, int h) +int vnc_send_framebuffer_update(VncState *vs, VncWorker *worker, + int x, int y, int w, int h) { int n =3D 0; =20 switch(vs->vnc_encoding) { case VNC_ENCODING_ZLIB: - n =3D vnc_zlib_send_framebuffer_update(vs, x, y, w, h); + n =3D vnc_zlib_send_framebuffer_update(vs, worker, x, y, w, h); break; case VNC_ENCODING_HEXTILE: vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_HEXTILE); n =3D vnc_hextile_send_framebuffer_update(vs, x, y, w, h); break; case VNC_ENCODING_TIGHT: - n =3D vnc_tight_send_framebuffer_update(vs, x, y, w, h); + n =3D vnc_tight_send_framebuffer_update(vs, worker, x, y, w, h= ); break; case VNC_ENCODING_TIGHT_PNG: - n =3D vnc_tight_png_send_framebuffer_update(vs, x, y, w, h); + n =3D vnc_tight_png_send_framebuffer_update(vs, worker, x, y, = w, h); break; case VNC_ENCODING_ZRLE: - n =3D vnc_zrle_send_framebuffer_update(vs, x, y, w, h); + n =3D vnc_zrle_send_framebuffer_update(vs, worker, x, y, w, h); break; case VNC_ENCODING_ZYWRLE: - n =3D vnc_zywrle_send_framebuffer_update(vs, x, y, w, h); + n =3D vnc_zywrle_send_framebuffer_update(vs, worker, x, y, w, = h); break; default: vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_RAW); @@ -1311,7 +1307,7 @@ static void vnc_disconnect_start(VncState *vs) =20 void vnc_disconnect_finish(VncState *vs) { - int i; + VncConnection *vc =3D container_of(vs, VncConnection, vs); =20 trace_vnc_client_disconnect_finish(vs, vs->ioc); =20 @@ -1325,9 +1321,9 @@ void vnc_disconnect_finish(VncState *vs) =20 qapi_free_VncClientInfo(vs->info); =20 - vnc_zlib_clear(vs); - vnc_tight_clear(vs); - vnc_zrle_clear(vs); + vnc_zlib_clear(&vc->worker); + vnc_tight_clear(&vc->worker); + vnc_zrle_clear(&vc->worker); =20 #ifdef CONFIG_VNC_SASL vnc_sasl_client_cleanup(vs); @@ -1355,19 +1351,12 @@ void vnc_disconnect_finish(VncState *vs) } buffer_free(&vs->jobs_buffer); =20 - for (i =3D 0; i < VNC_STAT_ROWS; ++i) { - g_free(vs->lossy_rect[i]); - } - g_free(vs->lossy_rect); - object_unref(OBJECT(vs->ioc)); vs->ioc =3D NULL; object_unref(OBJECT(vs->sioc)); vs->sioc =3D NULL; vs->magic =3D 0; - g_free(vs->zrle); - g_free(vs->tight); - g_free(container_of(vs, VncConnection, vs)); + g_free(vc); } =20 size_t vnc_client_io_error(VncState *vs, ssize_t ret, Error *err) @@ -2131,13 +2120,14 @@ static void send_xvp_message(VncState *vs, int code) =20 static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encod= ings) { + VncConnection *vc =3D container_of(vs, VncConnection, vs); int i; unsigned int enc =3D 0; =20 vs->features =3D 0; vs->vnc_encoding =3D 0; - vs->tight->compression =3D 9; - vs->tight->quality =3D -1; /* Lossless by default */ + vc->worker.tight.compression =3D 9; + vc->worker.tight.quality =3D -1; /* Lossless by default */ vs->absolute =3D -1; =20 /* @@ -2225,11 +2215,11 @@ static void set_encodings(VncState *vs, int32_t *en= codings, size_t n_encodings) vnc_server_cut_text_caps(vs); break; case VNC_ENCODING_COMPRESSLEVEL0 ... VNC_ENCODING_COMPRESSLEVEL0 += 9: - vs->tight->compression =3D (enc & 0x0F); + vc->worker.tight.compression =3D (enc & 0x0F); break; case VNC_ENCODING_QUALITYLEVEL0 ... VNC_ENCODING_QUALITYLEVEL0 + 9: if (vs->vd->lossy) { - vs->tight->quality =3D (enc & 0x0F); + vc->worker.tight.quality =3D (enc & 0x0F); } break; default: @@ -2958,7 +2948,7 @@ static VncRectStat *vnc_stat_rect(VncDisplay *vd, int= x, int y) return &vs->stats[y / VNC_STAT_RECT][x / VNC_STAT_RECT]; } =20 -void vnc_sent_lossy_rect(VncState *vs, int x, int y, int w, int h) +void vnc_sent_lossy_rect(VncWorker *worker, int x, int y, int w, int h) { int i, j; =20 @@ -2969,7 +2959,7 @@ void vnc_sent_lossy_rect(VncState *vs, int x, int y, = int w, int h) =20 for (j =3D y; j <=3D h; j++) { for (i =3D x; i <=3D w; i++) { - vs->lossy_rect[j][i] =3D 1; + worker->lossy_rect[j][i] =3D 1; } } } @@ -2985,6 +2975,7 @@ static int vnc_refresh_lossy_rect(VncDisplay *vd, int= x, int y) x =3D QEMU_ALIGN_DOWN(x, VNC_STAT_RECT); =20 QTAILQ_FOREACH(vs, &vd->clients, next) { + VncConnection *vc =3D container_of(vs, VncConnection, vs); int j; =20 /* kernel send buffers are full -> refresh later */ @@ -2992,11 +2983,11 @@ static int vnc_refresh_lossy_rect(VncDisplay *vd, i= nt x, int y) continue; } =20 - if (!vs->lossy_rect[sty][stx]) { + if (!vc->worker.lossy_rect[sty][stx]) { continue; } =20 - vs->lossy_rect[sty][stx] =3D 0; + vc->worker.lossy_rect[sty][stx] =3D 0; for (j =3D 0; j < VNC_STAT_RECT; ++j) { bitmap_set(vs->dirty[y + j], x / VNC_DIRTY_PIXELS_PER_BIT, @@ -3249,12 +3240,8 @@ static void vnc_connect(VncDisplay *vd, QIOChannelSo= cket *sioc, VncConnection *vc =3D g_new0(VncConnection, 1); VncState *vs =3D &vc->vs; bool first_client =3D QTAILQ_EMPTY(&vd->clients); - int i; =20 trace_vnc_client_connect(vs, sioc); - vs->zlib =3D &vc->zlib; - vs->zrle =3D g_new0(VncZrle, 1); - vs->tight =3D g_new0(VncTight, 1); vs->magic =3D VNC_MAGIC; vs->sioc =3D sioc; object_ref(OBJECT(vs->sioc)); @@ -3262,23 +3249,23 @@ static void vnc_connect(VncDisplay *vd, QIOChannelS= ocket *sioc, object_ref(OBJECT(vs->ioc)); vs->vd =3D vd; =20 - buffer_init(&vs->input, "vnc-input/%p", sioc); - buffer_init(&vs->output, "vnc-output/%p", sioc); - buffer_init(&vs->jobs_buffer, "vnc-jobs_buffer/%p", sioc); + buffer_init(&vs->input, "vnc-input/%p", sioc); + buffer_init(&vs->output, "vnc-output/%p", sioc); + buffer_init(&vs->jobs_buffer, "vnc-jobs_buffer/%p", sioc); =20 - buffer_init(&vs->tight->tight, "vnc-tight/%p", sioc); - buffer_init(&vs->tight->zlib, "vnc-tight-zlib/%p", sioc); - buffer_init(&vs->tight->gradient, "vnc-tight-gradient/%p", sioc); + buffer_init(&vc->worker.tight.tight, "vnc-tight/%p", sioc); + buffer_init(&vc->worker.tight.zlib, "vnc-tight-zlib/%p", sioc); + buffer_init(&vc->worker.tight.gradient, "vnc-tight-gradient/%p", sioc); #ifdef CONFIG_VNC_JPEG - buffer_init(&vs->tight->jpeg, "vnc-tight-jpeg/%p", sioc); + buffer_init(&vc->worker.tight.jpeg, "vnc-tight-jpeg/%p", sioc); #endif #ifdef CONFIG_PNG - buffer_init(&vs->tight->png, "vnc-tight-png/%p", sioc); + buffer_init(&vc->worker.tight.png, "vnc-tight-png/%p", sioc); #endif - buffer_init(&vc->zlib.zlib, "vnc-zlib/%p", sioc); - buffer_init(&vs->zrle->zrle, "vnc-zrle/%p", sioc); - buffer_init(&vs->zrle->fb, "vnc-zrle-fb/%p", sioc); - buffer_init(&vs->zrle->zlib, "vnc-zrle-zlib/%p", sioc); + buffer_init(&vc->worker.zlib.zlib, "vnc-zlib/%p", sioc); + buffer_init(&vc->worker.zrle.zrle, "vnc-zrle/%p", sioc); + buffer_init(&vc->worker.zrle.fb, "vnc-zrle-fb/%p", sioc); + buffer_init(&vc->worker.zrle.zlib, "vnc-zrle-zlib/%p", sioc); =20 if (skipauth) { vs->auth =3D VNC_AUTH_NONE; @@ -3295,11 +3282,6 @@ static void vnc_connect(VncDisplay *vd, QIOChannelSo= cket *sioc, VNC_DEBUG("Client sioc=3D%p ws=3D%d auth=3D%d subauth=3D%d\n", sioc, websocket, vs->auth, vs->subauth); =20 - vs->lossy_rect =3D g_malloc0(VNC_STAT_ROWS * sizeof (*vs->lossy_rect)); - for (i =3D 0; i < VNC_STAT_ROWS; ++i) { - vs->lossy_rect[i] =3D g_new0(uint8_t, VNC_STAT_COLS); - } - VNC_DEBUG("New client on socket %p\n", vs->sioc); update_displaychangelistener(&vd->dcl, VNC_REFRESH_INTERVAL_BASE); qio_channel_set_blocking(vs->ioc, false, NULL); diff --git a/ui/vnc-enc-zrle.c.inc b/ui/vnc-enc-zrle.c.inc index 2ef7501d52..68d28f58b7 100644 --- a/ui/vnc-enc-zrle.c.inc +++ b/ui/vnc-enc-zrle.c.inc @@ -62,16 +62,16 @@ #define ZRLE_ENCODE_TILE ZRLE_CONCAT2(zrle_encode_tile, ZRLE_ENCODE_S= UFFIX) #define ZRLE_WRITE_PALETTE ZRLE_CONCAT2(zrle_write_palette,ZRLE_ENCODE_S= UFFIX) =20 -static void ZRLE_ENCODE_TILE(VncState *vs, ZRLE_PIXEL *data, int w, int h, - int zywrle_level); +static void ZRLE_ENCODE_TILE(VncState *vs, VncZrle *zrle, ZRLE_PIXEL *data, + int w, int h, int zywrle_level); =20 #if ZRLE_BPP !=3D 8 #include "vnc-enc-zywrle-template.c" #endif =20 =20 -static void ZRLE_ENCODE(VncState *vs, int x, int y, int w, int h, - int zywrle_level) +static void ZRLE_ENCODE(VncState *vs, VncZrle *zrle, + int x, int y, int w, int h, int zywrle_level) { int ty; =20 @@ -87,16 +87,16 @@ static void ZRLE_ENCODE(VncState *vs, int x, int y, int= w, int h, =20 tw =3D MIN(VNC_ZRLE_TILE_WIDTH, x + w - tx); =20 - buf =3D zrle_convert_fb(vs, tx, ty, tw, th, ZRLE_BPP); - ZRLE_ENCODE_TILE(vs, buf, tw, th, zywrle_level); + buf =3D zrle_convert_fb(vs, zrle, tx, ty, tw, th, ZRLE_BPP); + ZRLE_ENCODE_TILE(vs, zrle, buf, tw, th, zywrle_level); } } } =20 -static void ZRLE_ENCODE_TILE(VncState *vs, ZRLE_PIXEL *data, int w, int h, - int zywrle_level) +static void ZRLE_ENCODE_TILE(VncState *vs, VncZrle *zrle, ZRLE_PIXEL *data, + int w, int h, int zywrle_level) { - VncPalette *palette =3D &vs->zrle->palette; + VncPalette *palette =3D &zrle->palette; =20 int runs =3D 0; int single_pixels =3D 0; @@ -236,7 +236,7 @@ static void ZRLE_ENCODE_TILE(VncState *vs, ZRLE_PIXEL *= data, int w, int h, #if ZRLE_BPP !=3D 8 if (zywrle_level > 0 && !(zywrle_level & 0x80)) { ZYWRLE_ANALYZE(data, data, w, h, w, zywrle_level, vs->zywrle.b= uf); - ZRLE_ENCODE_TILE(vs, data, w, h, zywrle_level | 0x80); + ZRLE_ENCODE_TILE(vs, zrle, data, w, h, zywrle_level | 0x80); } else #endif --=20 2.50.0 From nobody Sat Nov 15 10:54:06 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1752494423; cv=none; d=zohomail.com; s=zohoarc; b=eFyvnoGT9Ybl0/RWMmbNgfxCM7952wiyPp1pri3yCEy8/rB2SBBc9lpREdMdHMd1QbYOet6Jdq4PKWTvLIA4FpggWR3GQHnWt7+qEpbvk0DwwJ/EQuPiOMQKuPuZIP6CKAWNOSUVPBSXDzPhDV4SAvYGHVzeNBlh7/iP+wifcdg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752494423; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=KQNIH2ceD/6p8CyUoQ4Hhxi4tjgzkOrN9UmPsBwnATI=; b=ntwRJvKK0zF1uuoVyqGcJhGzRiBpYeE1+MBRRL5lzbgxl7pp1Gbn/DjEc3sKs2sThCtPJ1gmSFFhbSauq9AbxlLgAsAtS6/gRz5/TTs86Blex/+3OGfx5MThlwhQmHsr9gXrfmapHezKkY9cOA7Ntni9p6IC+pRJEhLJjnLYUKg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1752494423334233.38925024743423; Mon, 14 Jul 2025 05:00:23 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubHin-0004hH-Hp; Mon, 14 Jul 2025 07:51:50 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ubH5V-00066r-J8 for qemu-devel@nongnu.org; Mon, 14 Jul 2025 07:11:15 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ubH5T-0003AF-R3 for qemu-devel@nongnu.org; Mon, 14 Jul 2025 07:11:13 -0400 Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-240--hGca6SZM-SKJT8XYXX1og-1; Mon, 14 Jul 2025 07:11:07 -0400 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 6544F1800366; Mon, 14 Jul 2025 11:11:05 +0000 (UTC) Received: from localhost (unknown [10.45.242.9]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 661F919560A3; Mon, 14 Jul 2025 11:11:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752491471; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=KQNIH2ceD/6p8CyUoQ4Hhxi4tjgzkOrN9UmPsBwnATI=; b=LSQ3OdraHJcn3/OHiphZ6jYgm33Kx/O+FZyyWICFjQFQZXEfyzWrvDkKVpkM0MIcJVL+6H fTuq0Po5BIRqQIeYZitwdoXKO6x8cN8GWEyD8tbRN2W9LHafnPEEa8M0K4LH+1QjFLTlYM r25rpGeb4mSYZ9m5nVo6rSVN9TE1Gy8= X-MC-Unique: -hGca6SZM-SKJT8XYXX1og-1 X-Mimecast-MFC-AGG-ID: -hGca6SZM-SKJT8XYXX1og_1752491465 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, Vivek Kasireddy , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Dmitry Osipenko , Frediano Ziglio , Dongwon Kim , Michael Scherle Subject: [PULL 03/13] ui/egl-helpers: Error check the fds in egl_dmabuf_export_texture() Date: Mon, 14 Jul 2025 15:10:26 +0400 Message-ID: <20250714111039.4150419-4-marcandre.lureau@redhat.com> In-Reply-To: <20250714111039.4150419-1-marcandre.lureau@redhat.com> References: <20250714111039.4150419-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1752494424598116600 From: Vivek Kasireddy While trying to export and obtain fds associated with a texture, it is possible that the fds returned after eglExportDMABUFImageMESA() call have error values. Therefore, we need to evaluate the value of all fds and return false if any of them are negative. Cc: Gerd Hoffmann Cc: Marc-Andr=C3=A9 Lureau Cc: Dmitry Osipenko Cc: Frediano Ziglio Cc: Dongwon Kim Cc: Michael Scherle Reviewed-by: Marc-Andr=C3=A9 Lureau Signed-off-by: Vivek Kasireddy Message-Id: <20250617043546.1022779-2-vivek.kasireddy@intel.com> --- ui/egl-helpers.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index 5503a795e4..e3f2872cc1 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -295,6 +295,7 @@ bool egl_dmabuf_export_texture(uint32_t tex_id, int *fd= , EGLint *offset, { EGLImageKHR image; EGLuint64KHR modifiers[DMABUF_MAX_PLANES]; + int i; =20 image =3D eglCreateImageKHR(qemu_egl_display, eglGetCurrentContext(), EGL_GL_TEXTURE_2D_KHR, @@ -314,6 +315,11 @@ bool egl_dmabuf_export_texture(uint32_t tex_id, int *f= d, EGLint *offset, *modifier =3D modifiers[0]; } =20 + for (i =3D 0; i < *num_planes; i++) { + if (fd[i] < 0) { + return false; + } + } return true; } =20 --=20 2.50.0 From nobody Sat Nov 15 10:54:06 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1752494592; cv=none; d=zohomail.com; s=zohoarc; b=lF7dxZS0QL9XKsgjcTItN56awJLkFcMF1QnfWMCOeaVzvifna2M9F8GR9uEwyT+7cZ4dPQlzx+e2m9FjItz8Hbx4SA5gNsG2e6yaNh3eVXp5agnHDgtkpvqt3HbGg7cgAgzPsfbIepMZhVeaJLPhP3P2KSg5IUceqUNyeEAjSUg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752494592; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=I2u+YpVEc3NpHC4oX6/xekoaL5sePGqea71QsI6lILA=; b=KeR3APnLfqo7XZtY69TA1tmbRsH2qr0RP0akoF2VDilvkGbQCEMFwMXyo9t+9jsyWIZbuWSm31zIgqN7rWxtEGpv0H9KqHwHNR/8bNy02BB00fGywe9VdSyma4bXENLL/JtgS/qHuQcNSWNqKv/IfZrntFwWNJp21AKAJIFK7Q4= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1752494592394296.34414625215186; Mon, 14 Jul 2025 05:03:12 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubHd9-0006k6-3p; Mon, 14 Jul 2025 07:45:59 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ubH5d-0006CX-9U for qemu-devel@nongnu.org; Mon, 14 Jul 2025 07:11:30 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ubH5Z-0003Bf-QK for qemu-devel@nongnu.org; Mon, 14 Jul 2025 07:11:20 -0400 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-546-6RoHeMxeNo2SHp03mnPfXQ-1; Mon, 14 Jul 2025 07:11:13 -0400 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 8EAB01800287; Mon, 14 Jul 2025 11:11:11 +0000 (UTC) Received: from localhost (unknown [10.45.242.9]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id C76B419560A3; Mon, 14 Jul 2025 11:11:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752491477; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=I2u+YpVEc3NpHC4oX6/xekoaL5sePGqea71QsI6lILA=; b=Nm1/UR9Qjb/iDWqicVHNptKf0lJbCK0Fh9ddevb1V6vTT0XovE290iMKGz02jtr5HeErxc IsBHyuwFb921gEm6aov7iiRGrgWX3luNb/Da4IkwJfmeB8FnVIUSG82GDd8Ktxskclxc0W AgQa/ikN+6SdmJrLgb5QfnGzcbhtS4Q= X-MC-Unique: 6RoHeMxeNo2SHp03mnPfXQ-1 X-Mimecast-MFC-AGG-ID: 6RoHeMxeNo2SHp03mnPfXQ_1752491472 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, Vivek Kasireddy , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Dmitry Osipenko , Frediano Ziglio , Dongwon Kim , Michael Scherle Subject: [PULL 04/13] ui/spice: Enable gl=on option for non-local or remote clients Date: Mon, 14 Jul 2025 15:10:27 +0400 Message-ID: <20250714111039.4150419-5-marcandre.lureau@redhat.com> In-Reply-To: <20250714111039.4150419-1-marcandre.lureau@redhat.com> References: <20250714111039.4150419-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1752494593076116600 From: Vivek Kasireddy Newer versions of Spice server should be able to accept dmabuf fds from Qemu for clients that are connected via the network. In other words, when this option is enabled, Qemu would share a dmabuf fd with Spice which would encode and send the data associated with the fd to a client that could be located on a different machine. Cc: Gerd Hoffmann Cc: Marc-Andr=C3=A9 Lureau Cc: Dmitry Osipenko Cc: Frediano Ziglio Cc: Dongwon Kim Cc: Michael Scherle Reviewed-by: Marc-Andr=C3=A9 Lureau Signed-off-by: Vivek Kasireddy Message-Id: <20250617043546.1022779-3-vivek.kasireddy@intel.com> --- include/ui/spice-display.h | 1 + ui/spice-core.c | 4 ++++ ui/spice-display.c | 1 + 3 files changed, 6 insertions(+) diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h index e1a9b36185..6c55f38c8b 100644 --- a/include/ui/spice-display.h +++ b/include/ui/spice-display.h @@ -151,6 +151,7 @@ struct SimpleSpiceCursor { }; =20 extern bool spice_opengl; +extern bool spice_remote_client; =20 int qemu_spice_rect_is_empty(const QXLRect* r); void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r); diff --git a/ui/spice-core.c b/ui/spice-core.c index 0326c63bec..5acbdd3955 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -836,9 +836,13 @@ static void qemu_spice_init(void) #ifdef HAVE_SPICE_GL if (qemu_opt_get_bool(opts, "gl", 0)) { if ((port !=3D 0) || (tls_port !=3D 0)) { +#if SPICE_SERVER_VERSION >=3D 0x000f03 /* release 0.15.3 */ + spice_remote_client =3D 1; +#else error_report("SPICE GL support is local-only for now and " "incompatible with -spice port/tls-port"); exit(1); +#endif } egl_init(qemu_opt_get(opts, "rendernode"), DISPLAY_GL_MODE_ON, &er= ror_fatal); spice_opengl =3D 1; diff --git a/ui/spice-display.c b/ui/spice-display.c index 9c39d2c5c8..0fb72f6d6f 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -31,6 +31,7 @@ #include "standard-headers/drm/drm_fourcc.h" =20 bool spice_opengl; +bool spice_remote_client; =20 int qemu_spice_rect_is_empty(const QXLRect* r) { --=20 2.50.0 From nobody Sat Nov 15 10:54:06 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1752494574; cv=none; d=zohomail.com; s=zohoarc; b=aVJJIZnV5QPqdYLO1+9xcf7+pNu+zs8R0SdwYlA5eg+exkVdSDSq4I+MxhpfiLzx68EIZb6apsbg1HiRWDTKgbh7KFVZJ/7AouO4pNQoy49UNKhgo8I8WihIB5JJQvHGPDKtP7Nb7TxeZvwk5/r5rW3u28Fkk/AV7XxpRx2IRgM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752494574; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=VU3qOk5tSBxU8+d2num/+77BBR6EO3m9Ca6lEoeQNVU=; b=L4RYzvbWg4qfLGKUPi7hBxukhFIYNP++Kg/2XXcgIVw2Rd/iIOp+R7WGrEMMBJOAleriyx/RQCEfArKDnt52pkZs327eEh6rnDOVOm+BwCq6WED/b2G25qpTR1Odp60GQkOuV+CS39bNr4AsgCyCbDG2Fbtsq7D/opNDHjSIYX8= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1752494574391839.4869815188808; Mon, 14 Jul 2025 05:02:54 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubHhB-0002uN-EN; Mon, 14 Jul 2025 07:50:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ubH5i-0006IU-TY for qemu-devel@nongnu.org; Mon, 14 Jul 2025 07:11:34 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ubH5f-0003DN-4D for qemu-devel@nongnu.org; Mon, 14 Jul 2025 07:11:26 -0400 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-86-ichLWtTnO4y9ncK3sVTXeg-1; Mon, 14 Jul 2025 07:11:19 -0400 Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 6B58F180028A; Mon, 14 Jul 2025 11:11:17 +0000 (UTC) Received: from localhost (unknown [10.45.242.9]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id C76CB1956094; Mon, 14 Jul 2025 11:11:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752491482; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=VU3qOk5tSBxU8+d2num/+77BBR6EO3m9Ca6lEoeQNVU=; b=GW/hVXfSp+CON7/iVPA6i9d3EwA2s7Fn2rYgp9z1shOkA30t0M0ovVldCtiM58o/rpBipG 9xgM/5Bhp9hHi8GPxeLdyY6z+7RVaIMwi1A+QE3bgLgVWcDUVgJfmXtO3kzIVjULVpgN0f 4vLpcF0VZPo3vbYL87Hi6jw55o2PFOg= X-MC-Unique: ichLWtTnO4y9ncK3sVTXeg-1 X-Mimecast-MFC-AGG-ID: ichLWtTnO4y9ncK3sVTXeg_1752491477 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, Vivek Kasireddy , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Dmitry Osipenko , Frediano Ziglio , Dongwon Kim , Michael Scherle , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Subject: [PULL 05/13] ui/spice: Add an option for users to provide a preferred video codec Date: Mon, 14 Jul 2025 15:10:28 +0400 Message-ID: <20250714111039.4150419-6-marcandre.lureau@redhat.com> In-Reply-To: <20250714111039.4150419-1-marcandre.lureau@redhat.com> References: <20250714111039.4150419-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1752494577222116600 From: Vivek Kasireddy Giving users an option to choose a particular codec will enable them to make an appropriate decision based on their hardware and use-case. Note that, the Spice server would use this codec with Gstreamer encoder and only when gl=3Don is specified. If no codec is provided, then the codec gstreamer:h264 would be used as default. And, for the case where gl=3Doff, the default codec to be used is determined by the Spice server. Cc: Gerd Hoffmann Cc: Marc-Andr=C3=A9 Lureau Cc: Dmitry Osipenko Cc: Frediano Ziglio Cc: Dongwon Kim Cc: Michael Scherle Cc: Daniel P. Berrang=C3=A9 Reviewed-by: Marc-Andr=C3=A9 Lureau Signed-off-by: Vivek Kasireddy Message-Id: <20250617043546.1022779-4-vivek.kasireddy@intel.com> --- ui/spice-core.c | 15 +++++++++++++++ qemu-options.hx | 8 ++++++++ 2 files changed, 23 insertions(+) diff --git a/ui/spice-core.c b/ui/spice-core.c index 5acbdd3955..5e585ed958 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -488,6 +488,9 @@ static QemuOptsList qemu_spice_opts =3D { },{ .name =3D "streaming-video", .type =3D QEMU_OPT_STRING, + },{ + .name =3D "video-codec", + .type =3D QEMU_OPT_STRING, },{ .name =3D "agent-mouse", .type =3D QEMU_OPT_BOOL, @@ -662,6 +665,8 @@ static void qemu_spice_init(void) char *x509_key_file =3D NULL, *x509_cert_file =3D NULL, *x509_cacert_file =3D NULL; + const char *video_codec =3D NULL; + g_autofree char *enc_codec =3D NULL; int port, tls_port, addr_flags; spice_image_compression_t compression; spice_wan_compression_t wan_compr; @@ -838,6 +843,16 @@ static void qemu_spice_init(void) if ((port !=3D 0) || (tls_port !=3D 0)) { #if SPICE_SERVER_VERSION >=3D 0x000f03 /* release 0.15.3 */ spice_remote_client =3D 1; + + video_codec =3D qemu_opt_get(opts, "video-codec"); + if (video_codec) { + enc_codec =3D g_strconcat("gstreamer:", video_codec, NULL); + } + if (spice_server_set_video_codecs(spice_server, + enc_codec ?: "gstreamer:h264= ")) { + error_report("invalid video codec"); + exit(1); + } #else error_report("SPICE GL support is local-only for now and " "incompatible with -spice port/tls-port"); diff --git a/qemu-options.hx b/qemu-options.hx index 1f862b19a6..8f6a228a89 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2281,6 +2281,7 @@ DEF("spice", HAS_ARG, QEMU_OPTION_spice, " [,streaming-video=3D[off|all|filter]][,disable-copy-paste=3Don= |off]\n" " [,disable-agent-file-xfer=3Don|off][,agent-mouse=3D[on|off]]\n" " [,playback-compression=3D[on|off]][,seamless-migration=3D[on|o= ff]]\n" + " [,video-codec=3D\n" " [,gl=3D[on|off]][,rendernode=3D]\n" " enable spice\n" " at least one of {port, tls-port} is mandatory\n", @@ -2369,6 +2370,13 @@ SRST ``seamless-migration=3D[on|off]`` Enable/disable spice seamless migration. Default is off. =20 + ``video-codec=3D`` + Provide the preferred codec the Spice server should use with the + Gstreamer encoder. This option is only relevant when gl=3Don is + specified. If no codec is provided, then the codec gstreamer:h264 + would be used as default. And, for the case where gl=3Doff, the + default codec to be used is determined by the Spice server. + ``gl=3D[on|off]`` Enable/disable OpenGL context. Default is off. =20 --=20 2.50.0 From nobody Sat Nov 15 10:54:06 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1752494598; cv=none; d=zohomail.com; s=zohoarc; b=GbF5YWFJVN9xStUAaW3HVQMGkuqwSH1KTqM4URMSVHVfPbP36eZZP2FPomtQNLo8mAaColtpZFF6krhlMHqrOeY7YnKgimXa3KFpGuOPu+tZmgbgcj9DBnwUKA1zeVfDBXIAPZqLpgBkd9tf6cum6lEjFvCuGB3kkcFZ280JWH4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752494598; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=9vemcN2IltHES9sWVXSbrdPiFkkw6mhPtXJ2qDHWzdY=; b=PWSjI7lrqkZ9e7wCMrU1boblMnyZfkNA8eXxUD2eZBCSXIdDHSupOS4A8MstGtlvL4WlyDCPKUP1QHJVhQLWcnXNAWBPDXTFvkkJf3I365DGxkd8gCbmxG03Ih131Hmj9xAa6lEYiK9lXyDwu6tIreymGRPk5kApGCSjata8R5k= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1752494598684327.086366044437; Mon, 14 Jul 2025 05:03:18 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubHil-0004aw-Gp; Mon, 14 Jul 2025 07:51:47 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ubH5s-0006Jc-7E for qemu-devel@nongnu.org; Mon, 14 Jul 2025 07:11:40 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ubH5l-0003Eu-OZ for qemu-devel@nongnu.org; Mon, 14 Jul 2025 07:11:32 -0400 Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-97-ZYMHX0psMQibY5KGmGRtCg-1; Mon, 14 Jul 2025 07:11:25 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id E35E71956094; Mon, 14 Jul 2025 11:11:23 +0000 (UTC) Received: from localhost (unknown [10.45.242.9]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 9DFE71977000; Mon, 14 Jul 2025 11:11:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752491489; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=9vemcN2IltHES9sWVXSbrdPiFkkw6mhPtXJ2qDHWzdY=; b=DjUwYkXmMdd+jYKWcyReyIi6PIECUUjFmZePrGgvBqyl/q9kfAFZ6hm4LxZxKFy6wwpULJ g9E/Wzu9+++bDHIhhThBdkwyrNVsoALQk/nnnQfezRTivrTtoVzyH2u0gNjhaKc94299aL 7ubCrP5k5iE/ofJaOQpf2ph91YUTQoo= X-MC-Unique: ZYMHX0psMQibY5KGmGRtCg-1 X-Mimecast-MFC-AGG-ID: ZYMHX0psMQibY5KGmGRtCg_1752491484 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, Vivek Kasireddy , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Dmitry Osipenko , Frediano Ziglio , Dongwon Kim , Michael Scherle Subject: [PULL 06/13] ui/spice: Add an option to submit gl_draw requests at fixed rate Date: Mon, 14 Jul 2025 15:10:29 +0400 Message-ID: <20250714111039.4150419-7-marcandre.lureau@redhat.com> In-Reply-To: <20250714111039.4150419-1-marcandre.lureau@redhat.com> References: <20250714111039.4150419-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1752494601267116600 From: Vivek Kasireddy In the specific case where the display layer (virtio-gpu) is using dmabuf, and if remote clients are enabled (-spice gl=3Don,port=3Dxxxx), it makes sense to limit the maximum (streaming) rate (refresh rate) to a fixed value using the GUI refresh timer. Otherwise, the updates or gl_draw requests would be sent as soon as the Guest submits a new frame which is not optimal as it would lead to increased network traffic and wastage of GPU cycles if the frames get dropped. Cc: Gerd Hoffmann Cc: Marc-Andr=C3=A9 Lureau Cc: Dmitry Osipenko Cc: Frediano Ziglio Cc: Dongwon Kim Cc: Michael Scherle Reviewed-by: Marc-Andr=C3=A9 Lureau Signed-off-by: Vivek Kasireddy Message-Id: <20250617043546.1022779-5-vivek.kasireddy@intel.com> --- include/ui/spice-display.h | 1 + ui/spice-core.c | 12 ++++++++ ui/spice-display.c | 62 ++++++++++++++++++++++++++++++++------ qemu-options.hx | 5 +++ 4 files changed, 70 insertions(+), 10 deletions(-) diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h index 6c55f38c8b..9bdde78266 100644 --- a/include/ui/spice-display.h +++ b/include/ui/spice-display.h @@ -152,6 +152,7 @@ struct SimpleSpiceCursor { =20 extern bool spice_opengl; extern bool spice_remote_client; +extern int spice_max_refresh_rate; =20 int qemu_spice_rect_is_empty(const QXLRect* r); void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r); diff --git a/ui/spice-core.c b/ui/spice-core.c index 5e585ed958..5477950a5e 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -56,6 +56,8 @@ struct SpiceTimer { QEMUTimer *timer; }; =20 +#define DEFAULT_MAX_REFRESH_RATE 30 + static SpiceTimer *timer_add(SpiceTimerFunc func, void *opaque) { SpiceTimer *timer; @@ -491,6 +493,9 @@ static QemuOptsList qemu_spice_opts =3D { },{ .name =3D "video-codec", .type =3D QEMU_OPT_STRING, + },{ + .name =3D "max-refresh-rate", + .type =3D QEMU_OPT_NUMBER, },{ .name =3D "agent-mouse", .type =3D QEMU_OPT_BOOL, @@ -806,6 +811,13 @@ static void qemu_spice_init(void) spice_server_set_streaming_video(spice_server, SPICE_STREAM_VIDEO_= OFF); } =20 + spice_max_refresh_rate =3D qemu_opt_get_number(opts, "max-refresh-rate= ", + DEFAULT_MAX_REFRESH_RATE); + if (spice_max_refresh_rate <=3D 0) { + error_report("max refresh rate/fps is invalid"); + exit(1); + } + spice_server_set_agent_mouse (spice_server, qemu_opt_get_bool(opts, "agent-mouse", 1)); spice_server_set_playback_compression diff --git a/ui/spice-display.c b/ui/spice-display.c index 0fb72f6d6f..e409b6bdb2 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -32,6 +32,7 @@ =20 bool spice_opengl; bool spice_remote_client; +int spice_max_refresh_rate; =20 int qemu_spice_rect_is_empty(const QXLRect* r) { @@ -844,12 +845,32 @@ static void qemu_spice_gl_block_timer(void *opaque) warn_report("spice: no gl-draw-done within one second"); } =20 +static void spice_gl_draw(SimpleSpiceDisplay *ssd, + uint32_t x, uint32_t y, uint32_t w, uint32_t h) +{ + uint64_t cookie; + + cookie =3D (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_GL_DRAW_DONE, 0); + spice_qxl_gl_draw_async(&ssd->qxl, x, y, w, h, cookie); +} + static void spice_gl_refresh(DisplayChangeListener *dcl) { SimpleSpiceDisplay *ssd =3D container_of(dcl, SimpleSpiceDisplay, dcl); - uint64_t cookie; =20 - if (!ssd->ds || qemu_console_is_gl_blocked(ssd->dcl.con)) { + if (!ssd->ds) { + return; + } + + if (qemu_console_is_gl_blocked(ssd->dcl.con)) { + if (spice_remote_client && ssd->gl_updates && ssd->have_scanout) { + glFlush(); + spice_gl_draw(ssd, 0, 0, + surface_width(ssd->ds), surface_height(ssd->ds)); + ssd->gl_updates =3D 0; + /* E.g, to achieve 60 FPS, update_interval needs to be ~16.66 = ms */ + dcl->update_interval =3D 1000 / spice_max_refresh_rate; + } return; } =20 @@ -857,11 +878,8 @@ static void spice_gl_refresh(DisplayChangeListener *dc= l) if (ssd->gl_updates && ssd->have_surface) { qemu_spice_gl_block(ssd, true); glFlush(); - cookie =3D (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_GL_DRAW_DONE,= 0); - spice_qxl_gl_draw_async(&ssd->qxl, 0, 0, - surface_width(ssd->ds), - surface_height(ssd->ds), - cookie); + spice_gl_draw(ssd, 0, 0, + surface_width(ssd->ds), surface_height(ssd->ds)); ssd->gl_updates =3D 0; } } @@ -954,6 +972,20 @@ static void qemu_spice_gl_scanout_disable(DisplayChang= eListener *dcl) SimpleSpiceDisplay *ssd =3D container_of(dcl, SimpleSpiceDisplay, dcl); =20 trace_qemu_spice_gl_scanout_disable(ssd->qxl.id); + + /* + * We need to check for the case of "lost" updates, where a gl_draw + * was not submitted because the timer did not get a chance to run. + * One case where this happens is when the Guest VM is getting + * rebooted. If the console is blocked in this situation, we need + * to unblock it. Otherwise, newer updates would not take effect. + */ + if (qemu_console_is_gl_blocked(ssd->dcl.con)) { + if (spice_remote_client && ssd->gl_updates && ssd->have_scanout) { + ssd->gl_updates =3D 0; + qemu_spice_gl_block(ssd, false); + } + } spice_server_gl_scanout(&ssd->qxl, NULL, 0, 0, NULL, NULL, 0, DRM_FORM= AT_INVALID, DRM_FORMAT_MOD_INVALID, false); qemu_spice_gl_monitor_config(ssd, 0, 0, 0, 0); @@ -1061,7 +1093,6 @@ static void qemu_spice_gl_update(DisplayChangeListene= r *dcl, EGLint fourcc =3D 0; bool render_cursor =3D false; bool y_0_top =3D false; /* FIXME */ - uint64_t cookie; uint32_t width, height, texture; =20 if (!ssd->have_scanout) { @@ -1159,8 +1190,19 @@ static void qemu_spice_gl_update(DisplayChangeListen= er *dcl, trace_qemu_spice_gl_update(ssd->qxl.id, w, h, x, y); qemu_spice_gl_block(ssd, true); glFlush(); - cookie =3D (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_GL_DRAW_DONE, 0); - spice_qxl_gl_draw_async(&ssd->qxl, x, y, w, h, cookie); + + /* + * In the case of remote clients, the submission of gl_draw request is + * deferred here, so that it can be submitted later (to spice server) + * from spice_gl_refresh() timer callback. This is done to ensure that + * Guest updates are submitted at a steady rate (e.g. 60 FPS) instead + * of submitting them arbitrarily. + */ + if (spice_remote_client) { + ssd->gl_updates++; + } else { + spice_gl_draw(ssd, x, y, w, h); + } } =20 static const DisplayChangeListenerOps display_listener_gl_ops =3D { diff --git a/qemu-options.hx b/qemu-options.hx index 8f6a228a89..ac09abfd71 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2282,6 +2282,7 @@ DEF("spice", HAS_ARG, QEMU_OPTION_spice, " [,disable-agent-file-xfer=3Don|off][,agent-mouse=3D[on|off]]\n" " [,playback-compression=3D[on|off]][,seamless-migration=3D[on|o= ff]]\n" " [,video-codec=3D\n" + " [,max-refresh-rate=3Drate\n" " [,gl=3D[on|off]][,rendernode=3D]\n" " enable spice\n" " at least one of {port, tls-port} is mandatory\n", @@ -2377,6 +2378,10 @@ SRST would be used as default. And, for the case where gl=3Doff, the default codec to be used is determined by the Spice server. =20 + ``max-refresh-rate=3Drate`` + Provide the maximum refresh rate (or FPS) at which the encoding + requests should be sent to the Spice server. Default would be 30. + ``gl=3D[on|off]`` Enable/disable OpenGL context. Default is off. =20 --=20 2.50.0 From nobody Sat Nov 15 10:54:06 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1752493943; cv=none; d=zohomail.com; s=zohoarc; b=eOqywt9sbDkbCcMLWRAC5p0w7BVSwS/QpPs5lHWEuDnhqHJ755j5XJ+YQn4BONFmExJs3YGlR4hF6M4hxkuMZfTJ6kr9Bqv3wdUNWz1Be0cCt4wkV4/1EkVBnwIxWACi9oOlm4X3TuihnAJK3o2Zp2C1ZZ12w+Ru/BlqGo0/xro= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752493943; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=XGxC8pOOHdvNF80rDAG/0y/ryZPUHgUpZxYeZeyNMtI=; b=ieOg45eewiPG1kMRMBHi7xo4rlEaOCOVHdIumgHpJGgKjeLEdBrXJMd7z7lhXAIrm6KD8leESfmP3KfkRXVQ78KV9YXPpbSCRFdVfpgEtcGVyjveb+r92LASyQYHPYv4HrIVeOM8uCVzgnhnIH5R/gR4dVZATDvz0nx6bxkrBGw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1752493943973445.21775185437104; Mon, 14 Jul 2025 04:52:23 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubHiK-0003Kb-Gs; Mon, 14 Jul 2025 07:51:22 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ubH5r-0006Jn-Rj for qemu-devel@nongnu.org; Mon, 14 Jul 2025 07:11:38 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ubH5q-0003FS-4M for qemu-devel@nongnu.org; Mon, 14 Jul 2025 07:11:35 -0400 Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-90-z0va03VdNS2sZ2OSjYAeiA-1; Mon, 14 Jul 2025 07:11:30 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id E0595195608F; Mon, 14 Jul 2025 11:11:28 +0000 (UTC) Received: from localhost (unknown [10.45.242.9]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id DFB281977000; Mon, 14 Jul 2025 11:11:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752491493; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=XGxC8pOOHdvNF80rDAG/0y/ryZPUHgUpZxYeZeyNMtI=; b=LrnW84H7q1paUf4oT0dGn2+vUjZWr6G3/B5md0nIBZv8c4jzkH048vUrlbBzqxK0QjWkjS 5nN29JesFvKoQqmuaOy7oABZIYjB59FXeqJTGvngLn0SuKHCzTUsHiiW/cCur9kz0Mk4Yy H8XaYv54Nd/tyhK4ZWpqGTgX2/3QFc8= X-MC-Unique: z0va03VdNS2sZ2OSjYAeiA-1 X-Mimecast-MFC-AGG-ID: z0va03VdNS2sZ2OSjYAeiA_1752491489 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, Vivek Kasireddy , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Dmitry Osipenko , Frediano Ziglio , Dongwon Kim Subject: [PULL 07/13] ui/console-gl: Add a helper to create a texture with linear memory layout Date: Mon, 14 Jul 2025 15:10:30 +0400 Message-ID: <20250714111039.4150419-8-marcandre.lureau@redhat.com> In-Reply-To: <20250714111039.4150419-1-marcandre.lureau@redhat.com> References: <20250714111039.4150419-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1752493945241116600 From: Vivek Kasireddy There are cases where we do not want the memory layout of a texture to be tiled as the component processing the texture would not know how to de-tile either via software or hardware. Therefore, ensuring that the memory backing the texture has a linear layout is absolutely necessary in these situations. Cc: Gerd Hoffmann Cc: Marc-Andr=C3=A9 Lureau Cc: Dmitry Osipenko Cc: Frediano Ziglio Cc: Dongwon Kim Reviewed-by: Marc-Andr=C3=A9 Lureau Co-developed-by: Michael Scherle Signed-off-by: Vivek Kasireddy Reviewed-by: Dmitry Osipenko Message-Id: <20250617043546.1022779-6-vivek.kasireddy@intel.com> --- include/ui/console.h | 3 +++ ui/console-gl.c | 48 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/include/ui/console.h b/include/ui/console.h index 46b3128185..98feaa58bd 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -422,6 +422,9 @@ bool console_gl_check_format(DisplayChangeListener *dcl, pixman_format_code_t format); void surface_gl_create_texture(QemuGLShader *gls, DisplaySurface *surface); +bool surface_gl_create_texture_from_fd(DisplaySurface *surface, + int fd, GLuint *texture, + GLuint *mem_obj); void surface_gl_update_texture(QemuGLShader *gls, DisplaySurface *surface, int x, int y, int w, int h); diff --git a/ui/console-gl.c b/ui/console-gl.c index 103b954017..afb36dba64 100644 --- a/ui/console-gl.c +++ b/ui/console-gl.c @@ -25,6 +25,7 @@ * THE SOFTWARE. */ #include "qemu/osdep.h" +#include "qemu/error-report.h" #include "ui/console.h" #include "ui/shader.h" =20 @@ -96,6 +97,53 @@ void surface_gl_create_texture(QemuGLShader *gls, glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } =20 +bool surface_gl_create_texture_from_fd(DisplaySurface *surface, + int fd, GLuint *texture, + GLuint *mem_obj) +{ + unsigned long size =3D surface_stride(surface) * surface_height(surfac= e); + GLenum err =3D glGetError(); + *texture =3D 0; + *mem_obj =3D 0; + + if (!epoxy_has_gl_extension("GL_EXT_memory_object") || + !epoxy_has_gl_extension("GL_EXT_memory_object_fd")) { + error_report("spice: required OpenGL extensions not supported: " + "GL_EXT_memory_object and GL_EXT_memory_object_fd"); + return false; + } + +#ifdef GL_EXT_memory_object_fd + glCreateMemoryObjectsEXT(1, mem_obj); + glImportMemoryFdEXT(*mem_obj, size, GL_HANDLE_TYPE_OPAQUE_FD_EXT, fd); + + err =3D glGetError(); + if (err !=3D GL_NO_ERROR) { + error_report("spice: cannot import memory object from fd"); + goto cleanup_mem; + } + + glGenTextures(1, texture); + glBindTexture(GL_TEXTURE_2D, *texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_TILING_EXT, GL_LINEAR_TILING= _EXT); + glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, surface_width(surface= ), + surface_height(surface), *mem_obj, 0); + err =3D glGetError(); + if (err !=3D GL_NO_ERROR) { + error_report("spice: cannot create texture from memory object"); + goto cleanup_tex_and_mem; + } + return true; + +cleanup_tex_and_mem: + glDeleteTextures(1, texture); +cleanup_mem: + glDeleteMemoryObjectsEXT(1, mem_obj); + +#endif + return false; +} + void surface_gl_update_texture(QemuGLShader *gls, DisplaySurface *surface, int x, int y, int w, int h) --=20 2.50.0 From nobody Sat Nov 15 10:54:06 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1752496083; cv=none; d=zohomail.com; s=zohoarc; b=UJOY/CZ4dRLcbIZD/Y+6OSQE9x7kMmVEtQJXHOOEUEWRST68l+dLmtvHX6Y9Sh1+0wEZ1M48ZmE6E7Eifk59V5ysj9HUxmXTZwsusUvCq3lz3kRfMJimbfW9wQbJckmIRgSa0VFeRPYIL35hBTq1le44u7X0VZpaiwYLxXfLkFc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752496083; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=9PoE6bd35sOk0qJdIlAC+wu6emNS0c0T/QE+67h9qX4=; b=lc+6EgKv+N7XiJQfkdekcgaMX2oPq4I45jZXp3FYfN9DdWZk1+D5ODNp08YbPwoOBwaBt80dJT012Wc3+ZFm9TD+ZK9pAYO/ujpnhcBPR1xu9/CfYsaTsqG/s74wC/jgYU+CR+n1+0UwMpj6tjIQBYFohX6zIV0VPPvDChGBIbw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 17524960838421014.4621975712545; Mon, 14 Jul 2025 05:28:03 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubIGd-0004Pz-Ns; Mon, 14 Jul 2025 08:26:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ubHGx-0002I3-5k for qemu-devel@nongnu.org; Mon, 14 Jul 2025 07:23:04 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ubHGq-00065s-7U for qemu-devel@nongnu.org; Mon, 14 Jul 2025 07:23:02 -0400 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-539-_3bZWZWZMTiyyirt0tZxDw-1; Mon, 14 Jul 2025 07:11:36 -0400 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 316BE18011DF; Mon, 14 Jul 2025 11:11:35 +0000 (UTC) Received: from localhost (unknown [10.45.242.9]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 0441D1800285; Mon, 14 Jul 2025 11:11:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752492172; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=9PoE6bd35sOk0qJdIlAC+wu6emNS0c0T/QE+67h9qX4=; b=MBmIQa9wZF2uA5obfkpGzXgIirV57QRGxbPdmxPpeMBICPYA8eEbEtFomuft7mrRgb3nvu 7J9oJIrlD68v0JP4PuDNfA/+GLaay1+jKfcAW+EUjBZt/rf+U7SxiSybD5Ip7F2UArp34u g6MbtPq6eqmbat4d2PKwX1rGDFE43po= X-MC-Unique: _3bZWZWZMTiyyirt0tZxDw-1 X-Mimecast-MFC-AGG-ID: _3bZWZWZMTiyyirt0tZxDw_1752491495 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, Vivek Kasireddy , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Dmitry Osipenko , Frediano Ziglio , Dongwon Kim Subject: [PULL 08/13] ui/spice: Create a new texture with linear layout when gl=on is specified Date: Mon, 14 Jul 2025 15:10:31 +0400 Message-ID: <20250714111039.4150419-9-marcandre.lureau@redhat.com> In-Reply-To: <20250714111039.4150419-1-marcandre.lureau@redhat.com> References: <20250714111039.4150419-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1752496084922116600 From: Vivek Kasireddy Since most encoders/decoders (invoked by Spice) may not work properly with tiled memory associated with a texture, we need to create another texture that has linear memory layout and use that instead. Note that, there does not seem to be a direct way to indicate to the GL implementation that a texture's backing memory needs to be linear. Instead, we have to do it in a roundabout way where we need to first create a tiled texture and import that as a memory object to create a new texture that has a linear memory layout. Cc: Gerd Hoffmann Cc: Marc-Andr=C3=A9 Lureau Cc: Dmitry Osipenko Cc: Frediano Ziglio Cc: Dongwon Kim Reviewed-by: Marc-Andr=C3=A9 Lureau Co-developed-by: Michael Scherle Signed-off-by: Vivek Kasireddy Reviewed-by: Dmitry Osipenko Message-Id: <20250617043546.1022779-7-vivek.kasireddy@intel.com> --- include/ui/surface.h | 1 + ui/console-gl.c | 6 ++++ ui/spice-display.c | 82 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+) diff --git a/include/ui/surface.h b/include/ui/surface.h index f16f7be8be..006b1986bb 100644 --- a/include/ui/surface.h +++ b/include/ui/surface.h @@ -22,6 +22,7 @@ typedef struct DisplaySurface { GLenum glformat; GLenum gltype; GLuint texture; + GLuint mem_obj; #endif qemu_pixman_shareable share_handle; uint32_t share_handle_offset; diff --git a/ui/console-gl.c b/ui/console-gl.c index afb36dba64..403fc36fbd 100644 --- a/ui/console-gl.c +++ b/ui/console-gl.c @@ -184,6 +184,12 @@ void surface_gl_destroy_texture(QemuGLShader *gls, } glDeleteTextures(1, &surface->texture); surface->texture =3D 0; +#ifdef GL_EXT_memory_object_fd + if (surface->mem_obj) { + glDeleteMemoryObjectsEXT(1, &surface->mem_obj); + surface->mem_obj =3D 0; + } +#endif } =20 void surface_gl_setup_viewport(QemuGLShader *gls, diff --git a/ui/spice-display.c b/ui/spice-display.c index e409b6bdb2..854a97c198 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -893,6 +893,81 @@ static void spice_gl_update(DisplayChangeListener *dcl, ssd->gl_updates++; } =20 +static bool spice_gl_replace_fd_texture(SimpleSpiceDisplay *ssd, + int *fds, uint64_t *modifier, + int *num_planes) +{ + uint32_t offsets[DMABUF_MAX_PLANES], strides[DMABUF_MAX_PLANES]; + GLuint texture; + GLuint mem_obj; + int fourcc; + bool ret; + + if (!spice_remote_client) { + return true; + } + + if (*modifier =3D=3D DRM_FORMAT_MOD_LINEAR) { + return true; + } + + if (*num_planes > 1) { + error_report("spice: cannot replace texture with multiple planes"); + return false; + } + + /* + * We really want to ensure that the memory layout of the texture + * is linear; otherwise, the encoder's output may show corruption. + */ + if (!surface_gl_create_texture_from_fd(ssd->ds, fds[0], &texture, + &mem_obj)) { + error_report("spice: cannot create new texture from fd"); + return false; + } + + /* + * A successful return after glImportMemoryFdEXT() means that + * the ownership of fd has been passed to GL. In other words, + * the fd we got above should not be used anymore. + */ + ret =3D egl_dmabuf_export_texture(texture, + fds, + (EGLint *)offsets, + (EGLint *)strides, + &fourcc, + num_planes, + modifier); + if (!ret) { + glDeleteTextures(1, &texture); +#ifdef GL_EXT_memory_object_fd + glDeleteMemoryObjectsEXT(1, &mem_obj); +#endif + + /* + * Since we couldn't export our newly create texture (or create, + * an fd associated with it) we need to backtrack and try to + * recreate the fd associated with the original texture. + */ + ret =3D egl_dmabuf_export_texture(ssd->ds->texture, + fds, + (EGLint *)offsets, + (EGLint *)strides, + &fourcc, + num_planes, + modifier); + if (!ret) { + surface_gl_destroy_texture(ssd->gls, ssd->ds); + warn_report("spice: no texture available to display"); + } + } else { + surface_gl_destroy_texture(ssd->gls, ssd->ds); + ssd->ds->texture =3D texture; + ssd->ds->mem_obj =3D mem_obj; + } + return ret; +} + static void spice_server_gl_scanout(QXLInstance *qxl, const int *fd, uint32_t width, uint32_t height, @@ -917,6 +992,7 @@ static void spice_gl_switch(DisplayChangeListener *dcl, struct DisplaySurface *new_surface) { SimpleSpiceDisplay *ssd =3D container_of(dcl, SimpleSpiceDisplay, dcl); + bool ret; =20 if (ssd->ds) { surface_gl_destroy_texture(ssd->gls, ssd->ds); @@ -939,6 +1015,12 @@ static void spice_gl_switch(DisplayChangeListener *dc= l, return; } =20 + ret =3D spice_gl_replace_fd_texture(ssd, fd, &modifier, &num_plane= s); + if (!ret) { + surface_gl_destroy_texture(ssd->gls, ssd->ds); + return; + } + trace_qemu_spice_gl_surface(ssd->qxl.id, surface_width(ssd->ds), surface_height(ssd->ds), --=20 2.50.0 From nobody Sat Nov 15 10:54:06 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1752493929; cv=none; d=zohomail.com; s=zohoarc; b=IRY+fdUtuDtZs0uKkqfAIuJA9gzCEbmSTd0g2I9X2YlpOXQek0cHrvBdFIEo4LZTM3fCMIgAKTCxKwM22bAGS30//wvapJf7twECa5twbDgc2WDCnza3dbVkBSrxX/oy1GZ13gg9wMwJF0VGlFVdOu/pg4v1ybzFcxGOoESo+YA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752493929; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=/DKBN3+7PHd5LpCAXXeTGQanR81sYEgVkI6B9fYUCVQ=; b=hDtujY2g6K6txYbSKoO3AE2ZOWluj6mLi64lRgArHQLiRiJGTkbfaGWV18GAgAe1QUfr9XJhfXqkm7rH6HrUDrE62Ulmw04bjGJW478vniUrBsjF/6lZxpzTYUJd8ptwV6ZY6xbZZ77FnQjsFyfNiRvHiewnTVdosGkH4ueARpY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1752493929878155.91032347064072; Mon, 14 Jul 2025 04:52:09 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubHdF-000787-4G; Mon, 14 Jul 2025 07:46:05 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ubH67-0006Wr-1x for qemu-devel@nongnu.org; Mon, 14 Jul 2025 07:11:55 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ubH65-0003HT-6Q for qemu-devel@nongnu.org; Mon, 14 Jul 2025 07:11:50 -0400 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-611-W2ZyASOPOMa5pM16q6dCJw-1; Mon, 14 Jul 2025 07:11:42 -0400 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 5B82C1800268; Mon, 14 Jul 2025 11:11:41 +0000 (UTC) Received: from localhost (unknown [10.45.242.9]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 6689330001A1; Mon, 14 Jul 2025 11:11:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752491508; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/DKBN3+7PHd5LpCAXXeTGQanR81sYEgVkI6B9fYUCVQ=; b=igtnETdx4AXZEIoF6gcapg/8PrBRg+/DS60qyBpZJIMoRQqJZupKRVYWE/PbABpP/XznzP BPZ1akSks1PSe3O7P9jNv4wW8Jhc0my4eMyHI9reYT7OiFZJObgdhfkSGmJxLUbzA7EeIM E+xxOXMqG0LiipLEu+wTXD4a8Y4A5Qw= X-MC-Unique: W2ZyASOPOMa5pM16q6dCJw-1 X-Mimecast-MFC-AGG-ID: W2ZyASOPOMa5pM16q6dCJw_1752491501 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, Vivek Kasireddy , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Dmitry Osipenko , Frediano Ziglio , Dongwon Kim , Michael Scherle Subject: [PULL 09/13] ui/spice: Blit the scanout texture if its memory layout is not linear Date: Mon, 14 Jul 2025 15:10:32 +0400 Message-ID: <20250714111039.4150419-10-marcandre.lureau@redhat.com> In-Reply-To: <20250714111039.4150419-1-marcandre.lureau@redhat.com> References: <20250714111039.4150419-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1752493931274116600 From: Vivek Kasireddy In cases where the scanout buffer is provided as a texture (e.g. Virgl) we need to check to see if it has a linear memory layout or not. If it doesn't have a linear layout, then blitting it onto the texture associated with the display surface (which already has a linear layout) seems to ensure that there is no corruption seen regardless of which encoder or decoder is used. Cc: Gerd Hoffmann Cc: Marc-Andr=C3=A9 Lureau Cc: Dmitry Osipenko Cc: Frediano Ziglio Cc: Dongwon Kim Cc: Michael Scherle Reviewed-by: Marc-Andr=C3=A9 Lureau Signed-off-by: Vivek Kasireddy Message-Id: <20250617043546.1022779-8-vivek.kasireddy@intel.com> --- include/ui/spice-display.h | 3 ++ ui/spice-display.c | 81 +++++++++++++++++++++++++++++++++++--- 2 files changed, 78 insertions(+), 6 deletions(-) diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h index 9bdde78266..690ece7380 100644 --- a/include/ui/spice-display.h +++ b/include/ui/spice-display.h @@ -132,6 +132,9 @@ struct SimpleSpiceDisplay { egl_fb guest_fb; egl_fb blit_fb; egl_fb cursor_fb; + bool backing_y_0_top; + bool blit_scanout_texture; + bool new_scanout_texture; bool have_hot; #endif }; diff --git a/ui/spice-display.c b/ui/spice-display.c index 854a97c198..9ce622cefc 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -1086,7 +1086,7 @@ static void qemu_spice_gl_scanout_texture(DisplayChan= geListener *dcl, { SimpleSpiceDisplay *ssd =3D container_of(dcl, SimpleSpiceDisplay, dcl); EGLint offset[DMABUF_MAX_PLANES], stride[DMABUF_MAX_PLANES], fourcc = =3D 0; - int fd[DMABUF_MAX_PLANES], num_planes; + int fd[DMABUF_MAX_PLANES], num_planes, i; uint64_t modifier; =20 assert(tex_id); @@ -1098,11 +1098,26 @@ static void qemu_spice_gl_scanout_texture(DisplayCh= angeListener *dcl, =20 trace_qemu_spice_gl_scanout_texture(ssd->qxl.id, w, h, fourcc); =20 - /* note: spice server will close the fd */ - spice_server_gl_scanout(&ssd->qxl, fd, backing_width, backing_height, - (uint32_t *)offset, (uint32_t *)stride, num_pl= anes, - fourcc, modifier, y_0_top); - qemu_spice_gl_monitor_config(ssd, x, y, w, h); + if (spice_remote_client && modifier !=3D DRM_FORMAT_MOD_LINEAR) { + egl_fb_destroy(&ssd->guest_fb); + egl_fb_setup_for_tex(&ssd->guest_fb, + backing_width, backing_height, + tex_id, false); + ssd->backing_y_0_top =3D y_0_top; + ssd->blit_scanout_texture =3D true; + ssd->new_scanout_texture =3D true; + + for (i =3D 0; i < num_planes; i++) { + close(fd[i]); + } + } else { + /* note: spice server will close the fd */ + spice_server_gl_scanout(&ssd->qxl, fd, backing_width, backing_heig= ht, + (uint32_t *)offset, (uint32_t *)stride, + num_planes, fourcc, modifier, y_0_top); + qemu_spice_gl_monitor_config(ssd, x, y, w, h); + } + ssd->have_surface =3D false; ssd->have_scanout =3D true; } @@ -1168,6 +1183,50 @@ static void qemu_spice_gl_release_dmabuf(DisplayChan= geListener *dcl, egl_dmabuf_release_texture(dmabuf); } =20 +static bool spice_gl_blit_scanout_texture(SimpleSpiceDisplay *ssd, + egl_fb *scanout_tex_fb) +{ + uint32_t offsets[DMABUF_MAX_PLANES], strides[DMABUF_MAX_PLANES]; + int fds[DMABUF_MAX_PLANES], num_planes, fourcc; + uint64_t modifier; + bool ret; + + egl_fb_destroy(scanout_tex_fb); + egl_fb_setup_for_tex(scanout_tex_fb, + surface_width(ssd->ds), surface_height(ssd->ds), + ssd->ds->texture, false); + egl_fb_blit(scanout_tex_fb, &ssd->guest_fb, false); + glFlush(); + + if (!ssd->new_scanout_texture) { + return true; + } + + ret =3D egl_dmabuf_export_texture(ssd->ds->texture, + fds, + (EGLint *)offsets, + (EGLint *)strides, + &fourcc, + &num_planes, + &modifier); + if (!ret) { + error_report("spice: failed to get fd for texture"); + return false; + } + + spice_server_gl_scanout(&ssd->qxl, fds, + surface_width(ssd->ds), + surface_height(ssd->ds), + (uint32_t *)offsets, (uint32_t *)strides, + num_planes, fourcc, modifier, + ssd->backing_y_0_top); + qemu_spice_gl_monitor_config(ssd, 0, 0, + surface_width(ssd->ds), + surface_height(ssd->ds)); + ssd->new_scanout_texture =3D false; + return true; +} + static void qemu_spice_gl_update(DisplayChangeListener *dcl, uint32_t x, uint32_t y, uint32_t w, uint3= 2_t h) { @@ -1175,6 +1234,7 @@ static void qemu_spice_gl_update(DisplayChangeListene= r *dcl, EGLint fourcc =3D 0; bool render_cursor =3D false; bool y_0_top =3D false; /* FIXME */ + bool ret; uint32_t width, height, texture; =20 if (!ssd->have_scanout) { @@ -1269,6 +1329,15 @@ static void qemu_spice_gl_update(DisplayChangeListen= er *dcl, glFlush(); } =20 + if (spice_remote_client && ssd->blit_scanout_texture) { + egl_fb scanout_tex_fb; + + ret =3D spice_gl_blit_scanout_texture(ssd, &scanout_tex_fb); + if (!ret) { + return; + } + } + trace_qemu_spice_gl_update(ssd->qxl.id, w, h, x, y); qemu_spice_gl_block(ssd, true); glFlush(); --=20 2.50.0 From nobody Sat Nov 15 10:54:06 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1752494927; cv=none; d=zohomail.com; s=zohoarc; b=YKz5pYKkXOr7QEjgXJdQCC1jAav6paeqiSH/7CeXxKAN04Tk0UIHFvES/+isYrRCb7o8ZZOUbutgJVNHnYO5Ga4RbOG4IvcJzjMkqgC7k+BRFWDjTzB2AwW2nguMX75N0Bjq/zNQv0NdofD6alsRo5nf6NwX82/6K2cD3LI+cyA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752494927; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=s0DW657PuEuVKjB0hxciKKT0eQfi++HEcWHyzhRvOag=; b=YP6oMxikRGUFNCPqYY4Xe/qL2XngCXMBG8VWCcIbtZKW8YM38Mba1twKGPfLVCDrRbbwytlIy3Kq6LKe1iTjLhPW4Qix+ffOytNc2NNEqGBAhego8B5/OMsuJF/wCcXINi+1lwezoX0weKagtlx46x/QGSdeR64eszUSdEfmfqI= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1752494927619395.1654545856386; Mon, 14 Jul 2025 05:08:47 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubHj9-0004wh-A7; Mon, 14 Jul 2025 07:52:15 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ubH6D-0006a6-DD for qemu-devel@nongnu.org; Mon, 14 Jul 2025 07:11:57 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ubH6A-0003JY-Cb for qemu-devel@nongnu.org; Mon, 14 Jul 2025 07:11:57 -0400 Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-269-6YZXFW-1Pmm3AA4UjAhicA-1; Mon, 14 Jul 2025 07:11:49 -0400 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 2F3D118002ED; Mon, 14 Jul 2025 11:11:48 +0000 (UTC) Received: from localhost (unknown [10.45.242.9]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 427A219560A3; Mon, 14 Jul 2025 11:11:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752491513; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=s0DW657PuEuVKjB0hxciKKT0eQfi++HEcWHyzhRvOag=; b=Uzh0tEZNfHEOZm/ySI5GbjBUCxnKOu2oR8UeTayiKnXrWvyn1gVu56FWt4LAxY0lrCmqiE w6U/XDbn5gkNd/QJCGaqL+54nlfyDyl7XKUq/O84pEyUZSGCmZ6T/JprN9gK/pxSlO3gxh fAwvBhngyOhdIandpw6HEEm0K9sU8lI= X-MC-Unique: 6YZXFW-1Pmm3AA4UjAhicA-1 X-Mimecast-MFC-AGG-ID: 6YZXFW-1Pmm3AA4UjAhicA_1752491508 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, Andrew Keesler , Paolo Bonzini , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , Eduardo Habkost , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Akihiko Odaki , Dmitry Osipenko , "Michael S. Tsirkin" , Gerd Hoffmann , Eric Blake , Markus Armbruster Subject: [PULL 10/13] hw/display: Allow injection of virtio-gpu EDID name Date: Mon, 14 Jul 2025 15:10:33 +0400 Message-ID: <20250714111039.4150419-11-marcandre.lureau@redhat.com> In-Reply-To: <20250714111039.4150419-1-marcandre.lureau@redhat.com> References: <20250714111039.4150419-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1752494934660116600 From: Andrew Keesler Thanks to 72d277a7, 1ed2cb32, and others, EDID (Extended Display Identification Data) is propagated by QEMU such that a virtual display presents legitimate metadata (e.g., name, serial number, preferred resolutions, etc.) to its connected guest. This change adds the ability to specify the EDID name for a particular virtio-vga display. Previously, every virtual display would have the same name: "QEMU Monitor". Now, we can inject names of displays in order to test guest behavior that is specific to display names. We provide the ability to inject the display name from the frontend since this is guest visible data. Furthermore, this makes it clear where N potential display outputs would get their name from (which will be added in a future change). Note that we have elected to use a struct here for output data for extensibility - we intend to add per-output fields like resolution in a future change. It should be noted that EDID names longer than 12 bytes will be truncated per spec (I think?). Testing: verified that when I specified 2 outputs for a virtio-gpu with edid_name set, the names matched those that I configured with my vnc display. -display vnc=3Dlocalhost:0,id=3Daaa,display=3Dvga,head=3D0 \ -display vnc=3Dlocalhost:1,id=3Dbbb,display=3Dvga,head=3D1 \ -device '{"driver":"virtio-vga", "max_outputs":2, "id":"vga", "outputs":[ { "name":"AAA" }, { "name":"BBB" } ]}' Signed-off-by: Andrew Keesler Reviewed-by: Marc-Andr=C3=A9 Lureau Message-Id: <20250709121126.2946088-2-ankeesler@google.com> --- qapi/virtio.json | 18 ++++++++++-- include/hw/display/edid.h | 2 ++ include/hw/qdev-properties-system.h | 5 ++++ include/hw/virtio/virtio-gpu.h | 3 ++ hw/core/qdev-properties-system.c | 44 +++++++++++++++++++++++++++++ hw/display/virtio-gpu-base.c | 27 ++++++++++++++++++ 6 files changed, 97 insertions(+), 2 deletions(-) diff --git a/qapi/virtio.json b/qapi/virtio.json index 73df718a26..5e658a7033 100644 --- a/qapi/virtio.json +++ b/qapi/virtio.json @@ -963,17 +963,31 @@ { 'struct': 'IOThreadVirtQueueMapping', 'data': { 'iothread': 'str', '*vqs': ['uint16'] } } =20 +## +# @VirtIOGPUOutput: +# +# Describes configuration of a VirtIO GPU output. +# +# @name: the name of the output +# +# Since: 10.1 +## + +{ 'struct': 'VirtIOGPUOutput', + 'data': { 'name': 'str' } } + ## # @DummyVirtioForceArrays: # # Not used by QMP; hack to let us use IOThreadVirtQueueMappingList -# internally +# and VirtIOGPUOutputList internally # # Since: 9.0 ## =20 { 'struct': 'DummyVirtioForceArrays', - 'data': { 'unused-iothread-vq-mapping': ['IOThreadVirtQueueMapping'] } } + 'data': { 'unused-iothread-vq-mapping': ['IOThreadVirtQueueMapping'], + 'unused-virtio-gpu-output': ['VirtIOGPUOutput'] } } =20 ## # @GranuleMode: diff --git a/include/hw/display/edid.h b/include/hw/display/edid.h index 520f8ec202..91c0a428af 100644 --- a/include/hw/display/edid.h +++ b/include/hw/display/edid.h @@ -1,6 +1,8 @@ #ifndef EDID_H #define EDID_H =20 +#define EDID_NAME_MAX_LENGTH 12 + typedef struct qemu_edid_info { const char *vendor; /* http://www.uefi.org/pnp_id_list */ const char *name; diff --git a/include/hw/qdev-properties-system.h b/include/hw/qdev-properti= es-system.h index b921392c52..9601a11a09 100644 --- a/include/hw/qdev-properties-system.h +++ b/include/hw/qdev-properties-system.h @@ -32,6 +32,7 @@ extern const PropertyInfo qdev_prop_cpus390entitlement; extern const PropertyInfo qdev_prop_iothread_vq_mapping_list; extern const PropertyInfo qdev_prop_endian_mode; extern const PropertyInfo qdev_prop_vmapple_virtio_blk_variant; +extern const PropertyInfo qdev_prop_virtio_gpu_output_list; =20 #define DEFINE_PROP_PCI_DEVFN(_n, _s, _f, _d) \ DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_pci_devfn, int32_t) @@ -110,4 +111,8 @@ extern const PropertyInfo qdev_prop_vmapple_virtio_blk_= variant; qdev_prop_vmapple_virtio_blk_variant, \ VMAppleVirtioBlkVariant) =20 +#define DEFINE_PROP_VIRTIO_GPU_OUTPUT_LIST(_name, _state, _field) \ + DEFINE_PROP(_name, _state, _field, qdev_prop_virtio_gpu_output_list, \ + VirtIOGPUOutputList *) + #endif diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index a42957c4e2..9f16f89a36 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -20,6 +20,7 @@ #include "hw/virtio/virtio.h" #include "qemu/log.h" #include "system/vhost-user-backend.h" +#include "qapi/qapi-types-virtio.h" =20 #include "standard-headers/linux/virtio_gpu.h" #include "standard-headers/linux/virtio_ids.h" @@ -128,6 +129,7 @@ struct virtio_gpu_base_conf { uint32_t xres; uint32_t yres; uint64_t hostmem; + VirtIOGPUOutputList *outputs; }; =20 struct virtio_gpu_ctrl_command { @@ -167,6 +169,7 @@ struct VirtIOGPUBaseClass { =20 #define VIRTIO_GPU_BASE_PROPERTIES(_state, _conf) \ DEFINE_PROP_UINT32("max_outputs", _state, _conf.max_outputs, 1), \ + DEFINE_PROP_VIRTIO_GPU_OUTPUT_LIST("outputs", _state, _conf.outputs), \ DEFINE_PROP_BIT("edid", _state, _conf.flags, \ VIRTIO_GPU_FLAG_EDID_ENABLED, true), \ DEFINE_PROP_UINT32("xres", _state, _conf.xres, 1280), \ diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-sys= tem.c index 24e145d870..1f810b7ddf 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -1299,3 +1299,47 @@ const PropertyInfo qdev_prop_vmapple_virtio_blk_vari= ant =3D { .set =3D qdev_propinfo_set_enum, .set_default_value =3D qdev_propinfo_set_default_value_enum, }; + +/* --- VirtIOGPUOutputList --- */ + +static void get_virtio_gpu_output_list(Object *obj, Visitor *v, + const char *name, void *opaque, Error **errp) +{ + VirtIOGPUOutputList **prop_ptr =3D + object_field_prop_ptr(obj, opaque); + + visit_type_VirtIOGPUOutputList(v, name, prop_ptr, errp); +} + +static void set_virtio_gpu_output_list(Object *obj, Visitor *v, + const char *name, void *opaque, Error **errp) +{ + VirtIOGPUOutputList **prop_ptr =3D + object_field_prop_ptr(obj, opaque); + VirtIOGPUOutputList *list; + + if (!visit_type_VirtIOGPUOutputList(v, name, &list, errp)) { + return; + } + + qapi_free_VirtIOGPUOutputList(*prop_ptr); + *prop_ptr =3D list; +} + +static void release_virtio_gpu_output_list(Object *obj, + const char *name, void *opaque) +{ + VirtIOGPUOutputList **prop_ptr =3D + object_field_prop_ptr(obj, opaque); + + qapi_free_VirtIOGPUOutputList(*prop_ptr); + *prop_ptr =3D NULL; +} + +const PropertyInfo qdev_prop_virtio_gpu_output_list =3D { + .type =3D "VirtIOGPUOutputList", + .description =3D "VirtIO GPU output list [{\"name\":\"\"},...]", + .get =3D get_virtio_gpu_output_list, + .set =3D set_virtio_gpu_output_list, + .release =3D release_virtio_gpu_output_list, +}; diff --git a/hw/display/virtio-gpu-base.c b/hw/display/virtio-gpu-base.c index 9eb806b71f..7269477a1c 100644 --- a/hw/display/virtio-gpu-base.c +++ b/hw/display/virtio-gpu-base.c @@ -19,6 +19,7 @@ #include "qemu/error-report.h" #include "hw/display/edid.h" #include "trace.h" +#include "qapi/qapi-types-virtio.h" =20 void virtio_gpu_base_reset(VirtIOGPUBase *g) @@ -56,6 +57,8 @@ void virtio_gpu_base_generate_edid(VirtIOGPUBase *g, int scanout, struct virtio_gpu_resp_edid *edid) { + size_t output_idx; + VirtIOGPUOutputList *node; qemu_edid_info info =3D { .width_mm =3D g->req_state[scanout].width_mm, .height_mm =3D g->req_state[scanout].height_mm, @@ -64,6 +67,14 @@ virtio_gpu_base_generate_edid(VirtIOGPUBase *g, int scan= out, .refresh_rate =3D g->req_state[scanout].refresh_rate, }; =20 + for (output_idx =3D 0, node =3D g->conf.outputs; + output_idx <=3D scanout && node; output_idx++, node =3D node->nex= t) { + if (output_idx =3D=3D scanout && node->value && node->value->name)= { + info.name =3D node->value->name; + break; + } + } + edid->size =3D cpu_to_le32(sizeof(edid->edid)); qemu_edid_generate(edid->edid, sizeof(edid->edid), &info); } @@ -172,6 +183,8 @@ virtio_gpu_base_device_realize(DeviceState *qdev, VirtIOHandleOutput cursor_cb, Error **errp) { + size_t output_idx; + VirtIOGPUOutputList *node; VirtIODevice *vdev =3D VIRTIO_DEVICE(qdev); VirtIOGPUBase *g =3D VIRTIO_GPU_BASE(qdev); int i; @@ -181,6 +194,20 @@ virtio_gpu_base_device_realize(DeviceState *qdev, return false; } =20 + for (output_idx =3D 0, node =3D g->conf.outputs; + node; output_idx++, node =3D node->next) { + if (output_idx =3D=3D g->conf.max_outputs) { + error_setg(errp, "invalid outputs > %d", g->conf.max_outputs); + return false; + } + if (node->value && node->value->name && + strlen(node->value->name) > EDID_NAME_MAX_LENGTH) { + error_setg(errp, "invalid output name '%s' > %d", + node->value->name, EDID_NAME_MAX_LENGTH); + return false; + } + } + if (virtio_gpu_virgl_enabled(g->conf)) { error_setg(&g->migration_blocker, "virgl is not yet migratable"); if (migrate_add_blocker(&g->migration_blocker, errp) < 0) { --=20 2.50.0 From nobody Sat Nov 15 10:54:06 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1752494180; cv=none; d=zohomail.com; s=zohoarc; b=mmM0MCDKc8nLacI9eW19QzsAgfXm0alI8ecPr/jLoYQXPfJjPal1tmvYJn1FZYsTVJRzh6P9siB/wIgeZZ0kuq+h9aPVcdj3yBXyMvoiVKnhTijAuPyUG0KfpZ7I1t+hJtL7bzZfN1xG08SfouBsjYFPClruq8/6SznwaDWWRXQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752494180; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=aKPy83W1hiV5/W0xo6GAaKjDBMB+hmRcxLmXHAgpL6c=; b=g02+QtPUZ0Hhj/SJBWWBPlGa/SwhGCGnCOx6lQGRGSAT/lCCmik13rB18WB2Ybpd86adm5h5iJMsjbb1bHK4QaOx9Q/X1gyJa7r91PKKi6tpUUxfbKHach4GLaqYp5JpkNQVO5kjRO9I975gERgKueDOnlYlXALpA/SSum7GlxQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1752494180425658.8155607750448; Mon, 14 Jul 2025 04:56:20 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubHdI-0007RJ-TG; Mon, 14 Jul 2025 07:46:09 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ubH6F-0006gA-Az for qemu-devel@nongnu.org; Mon, 14 Jul 2025 07:12:00 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ubH6D-0003K8-Gm for qemu-devel@nongnu.org; Mon, 14 Jul 2025 07:11:59 -0400 Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-449-FRdI5mDmOf2N66rbl0TBTw-1; Mon, 14 Jul 2025 07:11:54 -0400 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 9F0001956088; Mon, 14 Jul 2025 11:11:53 +0000 (UTC) Received: from localhost (unknown [10.45.242.9]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 5581C19560A3; Mon, 14 Jul 2025 11:11:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752491516; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=aKPy83W1hiV5/W0xo6GAaKjDBMB+hmRcxLmXHAgpL6c=; b=dCc4E3Sd3ayJTayAuJX0TT66yVsoEWV46xT5fLOX7oyOClJ5Zsf2qBLg8a1pFyZ8yFeGPb peI0rsBQhehoQVf0BM58gaqzZk9Vk3WyCy/7esoBLsZCFHxi2su5no36GkhWuKfIlt39aL iUwo5TQTqZyq6dHl7AI5nXv3k0hD4io= X-MC-Unique: FRdI5mDmOf2N66rbl0TBTw-1 X-Mimecast-MFC-AGG-ID: FRdI5mDmOf2N66rbl0TBTw_1752491513 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, Weifeng Liu , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Eric Blake , Markus Armbruster Subject: [PULL 11/13] ui/gtk: Add keep-aspect-ratio option Date: Mon, 14 Jul 2025 15:10:34 +0400 Message-ID: <20250714111039.4150419-12-marcandre.lureau@redhat.com> In-Reply-To: <20250714111039.4150419-1-marcandre.lureau@redhat.com> References: <20250714111039.4150419-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1752494181840116600 From: Weifeng Liu When aspect ratio of host window and that of guest display are not aligned, we can either zoom the guest content to fill the whole host window or add padding to respect aspect ratio of the guest. Add an option keep-aspect-ratio to allow users to select their preferred behavior in this case. Suggested-by: BALATON Zoltan Suggested-by: Kim, Dongwon Signed-off-by: Weifeng Liu Reviewed-by: Marc-Andr=C3=A9 Lureau Tested-by: Marc-Andr=C3=A9 Lureau Message-Id: <20250601045245.36778-2-weifeng.liu.z@gmail.com> --- qapi/ui.json | 12 ++++++++---- include/ui/gtk.h | 1 + ui/gtk.c | 12 ++++++++++-- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/qapi/ui.json b/qapi/ui.json index 514fa159b1..9e496b4835 100644 --- a/qapi/ui.json +++ b/qapi/ui.json @@ -1335,13 +1335,17 @@ # @show-menubar: Display the main window menubar. Defaults to "on". # (Since 8.0) # +# @keep-aspect-ratio: Keep width/height aspect ratio of guest content when +# resizing host window. Defaults to "on". (Since 10.1) +# # Since: 2.12 ## { 'struct' : 'DisplayGTK', - 'data' : { '*grab-on-hover' : 'bool', - '*zoom-to-fit' : 'bool', - '*show-tabs' : 'bool', - '*show-menubar' : 'bool' } } + 'data' : { '*grab-on-hover' : 'bool', + '*zoom-to-fit' : 'bool', + '*show-tabs' : 'bool', + '*show-menubar' : 'bool', + '*keep-aspect-ratio' : 'bool' } } =20 ## # @DisplayEGLHeadless: diff --git a/include/ui/gtk.h b/include/ui/gtk.h index d3944046db..b7cfbf218e 100644 --- a/include/ui/gtk.h +++ b/include/ui/gtk.h @@ -140,6 +140,7 @@ struct GtkDisplayState { GdkCursor *null_cursor; Notifier mouse_mode_notifier; gboolean free_scale; + gboolean keep_aspect_ratio; =20 bool external_pause_update; =20 diff --git a/ui/gtk.c b/ui/gtk.c index 8c4a94c8f6..9104509ee1 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -828,8 +828,12 @@ void gd_update_scale(VirtualConsole *vc, int ww, int w= h, int fbw, int fbh) =20 sx =3D (double)ww / fbw; sy =3D (double)wh / fbh; - - vc->gfx.scale_x =3D vc->gfx.scale_y =3D MIN(sx, sy); + if (vc->s->keep_aspect_ratio) { + vc->gfx.scale_x =3D vc->gfx.scale_y =3D MIN(sx, sy); + } else { + vc->gfx.scale_x =3D sx; + vc->gfx.scale_y =3D sy; + } } } /** @@ -2328,6 +2332,10 @@ static GSList *gd_vc_gfx_init(GtkDisplayState *s, Vi= rtualConsole *vc, s->free_scale =3D true; } =20 + s->keep_aspect_ratio =3D true; + if (s->opts->u.gtk.has_keep_aspect_ratio) + s->keep_aspect_ratio =3D s->opts->u.gtk.keep_aspect_ratio; + for (i =3D 0; i < INPUT_EVENT_SLOTS_MAX; i++) { struct touch_slot *slot =3D &touch_slots[i]; slot->tracking_id =3D -1; --=20 2.50.0 From nobody Sat Nov 15 10:54:06 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1752494628; cv=none; d=zohomail.com; s=zohoarc; b=B2i8pAQPWhaN5YZ9NaQ2zz85tKGJ5ljSWtvAs354mymBYp2aYCKt0ZncdL1dXz/I1hMcaOYnVa5uHoaZfA0e85H4AwldULgdNppJZkavQhjG7DnTmEGBe5lSzTskNWj1TxG6sJXB3h/0nrI1cO+l9lq5dBgNCvFdYVpJy35i3tk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752494628; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=/4myqjH/Kdl7ZWCnYA3d+VdEmgMCkL9UEwDV1RI1+bc=; b=baDcx+XqvPV6lIgnxNIApfQVbPSNcvXHd4ubE9H2V5ojuxgCUJ9a+vEXPzyqQgbXVePERsAtLwhbX5cqDPZkyDH2BdQ/kFWJXZcCGmP0wyL0K9/3z4yTAv/JT+pm4SmLOL5DQ4Oc1iCP3dauZFkjax34O4AHNCOO4sivTvyc3HY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1752494627977255.11389582583683; Mon, 14 Jul 2025 05:03:47 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubHk0-0005jl-1Y; Mon, 14 Jul 2025 07:53:04 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ubH6M-0006xL-HD for qemu-devel@nongnu.org; Mon, 14 Jul 2025 07:12:07 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ubH6K-0003RD-CK for qemu-devel@nongnu.org; Mon, 14 Jul 2025 07:12:06 -0400 Received: from mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-644--CDi-feGM_KNAB9sB405tA-1; Mon, 14 Jul 2025 07:12:00 -0400 Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 2AF8119560B6; Mon, 14 Jul 2025 11:11:59 +0000 (UTC) Received: from localhost (unknown [10.45.242.9]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id D4E221956094; Mon, 14 Jul 2025 11:11:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752491523; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/4myqjH/Kdl7ZWCnYA3d+VdEmgMCkL9UEwDV1RI1+bc=; b=CJpYAaRTWfPlUfkeYcMwvLQh+gxcyZ9l+HvTabiDXPFEG7Rky3tUWy7H4dZ1QMy8FqowQW uDGHexBMDwJckUBqjlPiN2LZSBRaeo4oev073dak2YvrvP2+mM43f0KByApaPxox0KANnR borMbovzD2O43pto1DcPZJSEMbym9i8= X-MC-Unique: -CDi-feGM_KNAB9sB405tA-1 X-Mimecast-MFC-AGG-ID: -CDi-feGM_KNAB9sB405tA_1752491519 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, Weifeng Liu , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Eric Blake , Markus Armbruster Subject: [PULL 12/13] ui/gtk: Add scale option Date: Mon, 14 Jul 2025 15:10:35 +0400 Message-ID: <20250714111039.4150419-13-marcandre.lureau@redhat.com> In-Reply-To: <20250714111039.4150419-1-marcandre.lureau@redhat.com> References: <20250714111039.4150419-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1752494629680116600 From: Weifeng Liu Allow user to set a preferred scale (defaulting to 1) of the virtual display. Along with zoom-to-fix=3Dfalse, this would be helpful for users running QEMU on hi-dpi host desktop to achieve pixel to pixel display -- e.g., if the scale factor of a user's host desktop is set to 200%, then they can set a 0.5 scale for the virtual display to avoid magnification that might cause blurriness. Signed-off-by: Weifeng Liu Reviewed-by: Marc-Andr=C3=A9 Lureau Tested-by: Marc-Andr=C3=A9 Lureau Message-Id: <20250601045245.36778-3-weifeng.liu.z@gmail.com> --- qapi/ui.json | 5 ++++- include/ui/gtk.h | 1 + ui/gtk.c | 46 +++++++++++++++++++++++++++++----------------- 3 files changed, 34 insertions(+), 18 deletions(-) diff --git a/qapi/ui.json b/qapi/ui.json index 9e496b4835..a465d671c7 100644 --- a/qapi/ui.json +++ b/qapi/ui.json @@ -1338,6 +1338,8 @@ # @keep-aspect-ratio: Keep width/height aspect ratio of guest content when # resizing host window. Defaults to "on". (Since 10.1) # +# @scale: Set preferred scale of the display. Defaults to 1.0. (Since 10= .1) +# # Since: 2.12 ## { 'struct' : 'DisplayGTK', @@ -1345,7 +1347,8 @@ '*zoom-to-fit' : 'bool', '*show-tabs' : 'bool', '*show-menubar' : 'bool', - '*keep-aspect-ratio' : 'bool' } } + '*keep-aspect-ratio' : 'bool', + '*scale' : 'number' } } =20 ## # @DisplayEGLHeadless: diff --git a/include/ui/gtk.h b/include/ui/gtk.h index b7cfbf218e..3e6ce3cb48 100644 --- a/include/ui/gtk.h +++ b/include/ui/gtk.h @@ -41,6 +41,7 @@ typedef struct VirtualGfxConsole { DisplaySurface *ds; pixman_image_t *convert; cairo_surface_t *surface; + double preferred_scale; double scale_x; double scale_y; #if defined(CONFIG_OPENGL) diff --git a/ui/gtk.c b/ui/gtk.c index 9104509ee1..e91d093a49 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -67,6 +67,7 @@ #define VC_TERM_X_MIN 80 #define VC_TERM_Y_MIN 25 #define VC_SCALE_MIN 0.25 +#define VC_SCALE_MAX 4 #define VC_SCALE_STEP 0.25 =20 #ifdef GDK_WINDOWING_X11 @@ -272,15 +273,11 @@ static void gd_update_geometry_hints(VirtualConsole *= vc) if (!vc->gfx.ds) { return; } - if (s->free_scale) { - geo.min_width =3D surface_width(vc->gfx.ds) * VC_SCALE_MIN; - geo.min_height =3D surface_height(vc->gfx.ds) * VC_SCALE_MIN; - mask |=3D GDK_HINT_MIN_SIZE; - } else { - geo.min_width =3D surface_width(vc->gfx.ds) * vc->gfx.scale_x; - geo.min_height =3D surface_height(vc->gfx.ds) * vc->gfx.scale_= y; - mask |=3D GDK_HINT_MIN_SIZE; - } + double scale_x =3D s->free_scale ? VC_SCALE_MIN : vc->gfx.scale_x; + double scale_y =3D s->free_scale ? VC_SCALE_MIN : vc->gfx.scale_y; + geo.min_width =3D surface_width(vc->gfx.ds) * scale_x; + geo.min_height =3D surface_height(vc->gfx.ds) * scale_y; + mask |=3D GDK_HINT_MIN_SIZE; geo_widget =3D vc->gfx.drawing_area; gtk_widget_set_size_request(geo_widget, geo.min_width, geo.min_hei= ght); =20 @@ -1579,8 +1576,8 @@ static void gd_menu_full_screen(GtkMenuItem *item, vo= id *opaque) } s->full_screen =3D FALSE; if (vc->type =3D=3D GD_VC_GFX) { - vc->gfx.scale_x =3D 1.0; - vc->gfx.scale_y =3D 1.0; + vc->gfx.scale_x =3D vc->gfx.preferred_scale; + vc->gfx.scale_y =3D vc->gfx.preferred_scale; gd_update_windowsize(vc); } } @@ -1636,8 +1633,8 @@ static void gd_menu_zoom_fixed(GtkMenuItem *item, voi= d *opaque) GtkDisplayState *s =3D opaque; VirtualConsole *vc =3D gd_vc_find_current(s); =20 - vc->gfx.scale_x =3D 1.0; - vc->gfx.scale_y =3D 1.0; + vc->gfx.scale_x =3D vc->gfx.preferred_scale; + vc->gfx.scale_y =3D vc->gfx.preferred_scale; =20 gd_update_windowsize(vc); } @@ -1651,8 +1648,8 @@ static void gd_menu_zoom_fit(GtkMenuItem *item, void = *opaque) s->free_scale =3D TRUE; } else { s->free_scale =3D FALSE; - vc->gfx.scale_x =3D 1.0; - vc->gfx.scale_y =3D 1.0; + vc->gfx.scale_x =3D vc->gfx.preferred_scale; + vc->gfx.scale_y =3D vc->gfx.preferred_scale; } =20 gd_update_windowsize(vc); @@ -2243,6 +2240,11 @@ static void gl_area_realize(GtkGLArea *area, Virtual= Console *vc) } #endif =20 +static bool gd_scale_valid(double scale) +{ + return scale >=3D VC_SCALE_MIN && scale <=3D VC_SCALE_MAX; +} + static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc, QemuConsole *con, int idx, GSList *group, GtkWidget *view_menu) @@ -2252,8 +2254,18 @@ static GSList *gd_vc_gfx_init(GtkDisplayState *s, Vi= rtualConsole *vc, =20 vc->label =3D qemu_console_get_label(con); vc->s =3D s; - vc->gfx.scale_x =3D 1.0; - vc->gfx.scale_y =3D 1.0; + vc->gfx.preferred_scale =3D 1.0; + if (s->opts->u.gtk.has_scale) { + if (gd_scale_valid(s->opts->u.gtk.scale)) { + vc->gfx.preferred_scale =3D s->opts->u.gtk.scale; + } else { + error_report("Invalid scale value %lf given, being ignored", + s->opts->u.gtk.scale); + s->opts->u.gtk.has_scale =3D false; + } + } + vc->gfx.scale_x =3D vc->gfx.preferred_scale; + vc->gfx.scale_y =3D vc->gfx.preferred_scale; =20 #if defined(CONFIG_OPENGL) if (display_opengl) { --=20 2.50.0 From nobody Sat Nov 15 10:54:06 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1752494033; cv=none; d=zohomail.com; s=zohoarc; b=EQnrlMRav8lX9N0AvIxnPHTTtUWUZDbk5L+Ti2J/gYmQlnpAxlzX1qzekZK9XvymP6jNGyE5l0oIxXhVJmzZv/KPSGAxh5Vh3FwbcOFQuR0U80EsPRnABfnDvkJxDsYArncq+H+E8QJ04HO6h3whoaFnQEMdPbKbGgqSU2UZtKc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752494033; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=QHvlWL83L2yf+5AX4UtVjgNoCLqyCVDOO6MmbVr1kOM=; b=irRgN06iiXWtOVB1HY7gbUCHkJAkx02JYgMZc1QOU3Wkzncb6TmXcV0bLMByt9juwOhBqueyvNnv1qTiW/jY9yDN54S2zGuXzchaYqn3qpmkG6xsEbfyTvEHEI3LrpX2gdwZfw7M6ySrhmllzCYQb4pkZChb9rNkQWu0rRbZGjc= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1752494033797371.02166375541367; Mon, 14 Jul 2025 04:53:53 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubHan-0003Dd-Ge; Mon, 14 Jul 2025 07:43:33 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ubH6Q-0007BA-QH for qemu-devel@nongnu.org; Mon, 14 Jul 2025 07:12:11 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ubH6O-0003TY-UC for qemu-devel@nongnu.org; Mon, 14 Jul 2025 07:12:10 -0400 Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-495-YiW6FwPxMHKP99knZO_qvw-1; Mon, 14 Jul 2025 07:12:05 -0400 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 8DBA01956095; Mon, 14 Jul 2025 11:12:04 +0000 (UTC) Received: from localhost (unknown [10.45.242.9]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 448B518046C6; Mon, 14 Jul 2025 11:12:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752491527; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=QHvlWL83L2yf+5AX4UtVjgNoCLqyCVDOO6MmbVr1kOM=; b=Z0o+FD0XlTn6C+caNstw46KXnA5NIokoCk+kLhRV6GuD7p//FwkYZZIGS5W2+wBpxFHD/Q xy1X8DAUqnVLeu48OVNwzOXjEsn/SexfWUS5IcLy9BHzjgQURDhZCz5BgFyZtsbJ2pzgHl hTLWVJ0JVxhEvZXUYaE2cA8jJpiVTfU= X-MC-Unique: YiW6FwPxMHKP99knZO_qvw-1 X-Mimecast-MFC-AGG-ID: YiW6FwPxMHKP99knZO_qvw_1752491524 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Stefan Berger Subject: [PULL 13/13] tpm: "qemu -tpmdev help" should return success Date: Mon, 14 Jul 2025 15:10:36 +0400 Message-ID: <20250714111039.4150419-14-marcandre.lureau@redhat.com> In-Reply-To: <20250714111039.4150419-1-marcandre.lureau@redhat.com> References: <20250714111039.4150419-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1752494038230116600 From: Marc-Andr=C3=A9 Lureau Like other "-foo help" CLI, the qemu process should return 0 for "-tpmdev help". While touching this, switch to is_help_option() utility function as suggested by Peter Maydell. Signed-off-by: Marc-Andr=C3=A9 Lureau Reviewed-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daud=C3=A9 Message-Id: <20250707101412.2055581-1-marcandre.lureau@redhat.com> --- system/tpm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/system/tpm.c b/system/tpm.c index 8df0f6e72b..903b29c043 100644 --- a/system/tpm.c +++ b/system/tpm.c @@ -21,6 +21,7 @@ #include "system/tpm.h" #include "qemu/config-file.h" #include "qemu/error-report.h" +#include "qemu/help_option.h" =20 static QLIST_HEAD(, TPMBackend) tpm_backends =3D QLIST_HEAD_INITIALIZER(tpm_backends); @@ -179,9 +180,9 @@ int tpm_config_parse(QemuOptsList *opts_list, const cha= r *optstr) { QemuOpts *opts; =20 - if (!strcmp(optstr, "help")) { + if (is_help_option(optstr)) { tpm_display_backend_drivers(); - return -1; + exit(EXIT_SUCCESS); } opts =3D qemu_opts_parse_noisily(opts_list, optstr, true); if (!opts) { --=20 2.50.0