1142ca628SMarc-André Lureau /*
2142ca628SMarc-André Lureau * QEMU DBus display console
3142ca628SMarc-André Lureau *
4142ca628SMarc-André Lureau * Copyright (c) 2021 Marc-André Lureau <marcandre.lureau@redhat.com>
5142ca628SMarc-André Lureau *
6142ca628SMarc-André Lureau * Permission is hereby granted, free of charge, to any person obtaining a copy
7142ca628SMarc-André Lureau * of this software and associated documentation files (the "Software"), to deal
8142ca628SMarc-André Lureau * in the Software without restriction, including without limitation the rights
9142ca628SMarc-André Lureau * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10142ca628SMarc-André Lureau * copies of the Software, and to permit persons to whom the Software is
11142ca628SMarc-André Lureau * furnished to do so, subject to the following conditions:
12142ca628SMarc-André Lureau *
13142ca628SMarc-André Lureau * The above copyright notice and this permission notice shall be included in
14142ca628SMarc-André Lureau * all copies or substantial portions of the Software.
15142ca628SMarc-André Lureau *
16142ca628SMarc-André Lureau * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17142ca628SMarc-André Lureau * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18142ca628SMarc-André Lureau * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19142ca628SMarc-André Lureau * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20142ca628SMarc-André Lureau * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21142ca628SMarc-André Lureau * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22142ca628SMarc-André Lureau * THE SOFTWARE.
23142ca628SMarc-André Lureau */
24142ca628SMarc-André Lureau #include "qemu/osdep.h"
255feed38cSThomas Huth #include "qemu/error-report.h"
26de1f8ce0SMarc-André Lureau #include "qapi/error.h"
27142ca628SMarc-André Lureau #include "sysemu/sysemu.h"
28142ca628SMarc-André Lureau #include "dbus.h"
29*01fff506SMarc-André Lureau #include "glib.h"
3029c5c7e5SMarc-André Lureau #ifdef G_OS_UNIX
31142ca628SMarc-André Lureau #include <gio/gunixfdlist.h>
3229c5c7e5SMarc-André Lureau #endif
33de1f8ce0SMarc-André Lureau #ifdef WIN32
34de1f8ce0SMarc-André Lureau #include <d3d11.h>
35de1f8ce0SMarc-André Lureau #include <dxgi1_2.h>
36de1f8ce0SMarc-André Lureau #endif
37142ca628SMarc-André Lureau
3884a0a2efSMarc-André Lureau #ifdef CONFIG_OPENGL
39142ca628SMarc-André Lureau #include "ui/shader.h"
40142ca628SMarc-André Lureau #include "ui/egl-helpers.h"
41142ca628SMarc-André Lureau #include "ui/egl-context.h"
42949c084aSMarc-André Lureau #include "ui/qemu-pixman.h"
4384a0a2efSMarc-André Lureau #endif
44142ca628SMarc-André Lureau #include "trace.h"
45142ca628SMarc-André Lureau
46f43bf0a7SMarc-André Lureau static void dbus_gfx_switch(DisplayChangeListener *dcl,
47f43bf0a7SMarc-André Lureau struct DisplaySurface *new_surface);
48f43bf0a7SMarc-André Lureau
49de1f8ce0SMarc-André Lureau enum share_kind {
50de1f8ce0SMarc-André Lureau SHARE_KIND_NONE,
51de1f8ce0SMarc-André Lureau SHARE_KIND_MAPPED,
52de1f8ce0SMarc-André Lureau SHARE_KIND_D3DTEX,
53de1f8ce0SMarc-André Lureau };
54de1f8ce0SMarc-André Lureau
55142ca628SMarc-André Lureau struct _DBusDisplayListener {
56142ca628SMarc-André Lureau GObject parent;
57142ca628SMarc-André Lureau
58142ca628SMarc-André Lureau char *bus_name;
59142ca628SMarc-André Lureau DBusDisplayConsole *console;
60142ca628SMarc-André Lureau GDBusConnection *conn;
61142ca628SMarc-André Lureau
62142ca628SMarc-André Lureau QemuDBusDisplay1Listener *proxy;
63142ca628SMarc-André Lureau
64949c084aSMarc-André Lureau #ifdef CONFIG_PIXMAN
657007e98cSBilal Elmoussaoui /* Keep track of the damage region */
667007e98cSBilal Elmoussaoui pixman_region32_t gl_damage;
67949c084aSMarc-André Lureau #else
68949c084aSMarc-André Lureau int gl_damage;
697007e98cSBilal Elmoussaoui #endif
707007e98cSBilal Elmoussaoui
71142ca628SMarc-André Lureau DisplayChangeListener dcl;
72142ca628SMarc-André Lureau DisplaySurface *ds;
73de1f8ce0SMarc-André Lureau enum share_kind ds_share;
74de1f8ce0SMarc-André Lureau
7548dddba1SMarc-André Lureau bool ds_mapped;
7648dddba1SMarc-André Lureau bool can_share_map;
7748dddba1SMarc-André Lureau
7848dddba1SMarc-André Lureau #ifdef WIN32
7948dddba1SMarc-André Lureau QemuDBusDisplay1ListenerWin32Map *map_proxy;
80de1f8ce0SMarc-André Lureau QemuDBusDisplay1ListenerWin32D3d11 *d3d11_proxy;
8148dddba1SMarc-André Lureau HANDLE peer_process;
82de1f8ce0SMarc-André Lureau ID3D11Texture2D *d3d_texture;
83f43bf0a7SMarc-André Lureau #ifdef CONFIG_OPENGL
84f43bf0a7SMarc-André Lureau egl_fb fb;
85f43bf0a7SMarc-André Lureau #endif
8648dddba1SMarc-André Lureau #else /* !WIN32 */
87fa88b85dSMarc-André Lureau QemuDBusDisplay1ListenerUnixMap *map_proxy;
88fa88b85dSMarc-André Lureau #endif
89*01fff506SMarc-André Lureau
90142ca628SMarc-André Lureau guint dbus_filter;
91142ca628SMarc-André Lureau guint32 display_serial_to_discard;
92142ca628SMarc-André Lureau guint32 cursor_serial_to_discard;
93142ca628SMarc-André Lureau };
94f43bf0a7SMarc-André Lureau
95f43bf0a7SMarc-André Lureau G_DEFINE_TYPE(DBusDisplayListener, dbus_display_listener, G_TYPE_OBJECT)
96f43bf0a7SMarc-André Lureau
97*01fff506SMarc-André Lureau static void dbus_gfx_update(DisplayChangeListener *dcl,
98fa88b85dSMarc-André Lureau int x, int y, int w, int h);
99*01fff506SMarc-André Lureau
ddl_discard_display_messages(DBusDisplayListener * ddl)100fa88b85dSMarc-André Lureau static void ddl_discard_display_messages(DBusDisplayListener *ddl)
101*01fff506SMarc-André Lureau {
102*01fff506SMarc-André Lureau guint32 serial = g_dbus_connection_get_last_serial(
103fa88b85dSMarc-André Lureau g_dbus_proxy_get_connection(G_DBUS_PROXY(ddl->proxy)));
104fa88b85dSMarc-André Lureau
105f43bf0a7SMarc-André Lureau g_atomic_int_set(&ddl->display_serial_to_discard, serial);
106f43bf0a7SMarc-André Lureau }
107f43bf0a7SMarc-André Lureau
ddl_discard_cursor_messages(DBusDisplayListener * ddl)108f43bf0a7SMarc-André Lureau static void ddl_discard_cursor_messages(DBusDisplayListener *ddl)
109f43bf0a7SMarc-André Lureau {
110f43bf0a7SMarc-André Lureau guint32 serial = g_dbus_connection_get_last_serial(
111f43bf0a7SMarc-André Lureau g_dbus_proxy_get_connection(G_DBUS_PROXY(ddl->proxy)));
112f43bf0a7SMarc-André Lureau
113f43bf0a7SMarc-André Lureau g_atomic_int_set(&ddl->cursor_serial_to_discard, serial);
114de1f8ce0SMarc-André Lureau }
115de1f8ce0SMarc-André Lureau
116de1f8ce0SMarc-André Lureau #ifdef CONFIG_OPENGL
dbus_scanout_disable(DisplayChangeListener * dcl)117de1f8ce0SMarc-André Lureau static void dbus_scanout_disable(DisplayChangeListener *dcl)
118de1f8ce0SMarc-André Lureau {
119de1f8ce0SMarc-André Lureau DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl);
120de1f8ce0SMarc-André Lureau
121de1f8ce0SMarc-André Lureau ddl_discard_display_messages(ddl);
122de1f8ce0SMarc-André Lureau
123de1f8ce0SMarc-André Lureau qemu_dbus_display1_listener_call_disable(
124de1f8ce0SMarc-André Lureau ddl->proxy, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
125de1f8ce0SMarc-André Lureau }
126de1f8ce0SMarc-André Lureau
127de1f8ce0SMarc-André Lureau #ifdef WIN32
d3d_texture2d_share(ID3D11Texture2D * d3d_texture,HANDLE * handle,Error ** errp)128de1f8ce0SMarc-André Lureau static bool d3d_texture2d_share(ID3D11Texture2D *d3d_texture,
129de1f8ce0SMarc-André Lureau HANDLE *handle, Error **errp)
130de1f8ce0SMarc-André Lureau {
131de1f8ce0SMarc-André Lureau IDXGIResource1 *dxgiResource = NULL;
132de1f8ce0SMarc-André Lureau HRESULT hr;
133de1f8ce0SMarc-André Lureau
134de1f8ce0SMarc-André Lureau hr = d3d_texture->lpVtbl->QueryInterface(d3d_texture,
135de1f8ce0SMarc-André Lureau &IID_IDXGIResource1,
136de1f8ce0SMarc-André Lureau (void **)&dxgiResource);
137de1f8ce0SMarc-André Lureau if (FAILED(hr)) {
138de1f8ce0SMarc-André Lureau goto fail;
139de1f8ce0SMarc-André Lureau }
140de1f8ce0SMarc-André Lureau
141de1f8ce0SMarc-André Lureau hr = dxgiResource->lpVtbl->CreateSharedHandle(
142de1f8ce0SMarc-André Lureau dxgiResource,
143de1f8ce0SMarc-André Lureau NULL,
144de1f8ce0SMarc-André Lureau DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
145de1f8ce0SMarc-André Lureau NULL,
146de1f8ce0SMarc-André Lureau handle
147de1f8ce0SMarc-André Lureau );
148de1f8ce0SMarc-André Lureau
149de1f8ce0SMarc-André Lureau dxgiResource->lpVtbl->Release(dxgiResource);
150de1f8ce0SMarc-André Lureau
151de1f8ce0SMarc-André Lureau if (SUCCEEDED(hr)) {
152de1f8ce0SMarc-André Lureau return true;
153de1f8ce0SMarc-André Lureau }
154de1f8ce0SMarc-André Lureau
155de1f8ce0SMarc-André Lureau fail:
156de1f8ce0SMarc-André Lureau error_setg_win32(errp, GetLastError(), "failed to create shared handle");
157de1f8ce0SMarc-André Lureau return false;
158de1f8ce0SMarc-André Lureau }
159de1f8ce0SMarc-André Lureau
d3d_texture2d_acquire0(ID3D11Texture2D * d3d_texture,Error ** errp)160de1f8ce0SMarc-André Lureau static bool d3d_texture2d_acquire0(ID3D11Texture2D *d3d_texture, Error **errp)
161de1f8ce0SMarc-André Lureau {
162de1f8ce0SMarc-André Lureau IDXGIKeyedMutex *dxgiMutex = NULL;
163de1f8ce0SMarc-André Lureau HRESULT hr;
164de1f8ce0SMarc-André Lureau
165de1f8ce0SMarc-André Lureau hr = d3d_texture->lpVtbl->QueryInterface(d3d_texture,
166de1f8ce0SMarc-André Lureau &IID_IDXGIKeyedMutex,
167de1f8ce0SMarc-André Lureau (void **)&dxgiMutex);
168de1f8ce0SMarc-André Lureau if (FAILED(hr)) {
169de1f8ce0SMarc-André Lureau goto fail;
170de1f8ce0SMarc-André Lureau }
171de1f8ce0SMarc-André Lureau
172de1f8ce0SMarc-André Lureau hr = dxgiMutex->lpVtbl->AcquireSync(dxgiMutex, 0, INFINITE);
173de1f8ce0SMarc-André Lureau
174de1f8ce0SMarc-André Lureau dxgiMutex->lpVtbl->Release(dxgiMutex);
175de1f8ce0SMarc-André Lureau
176de1f8ce0SMarc-André Lureau if (SUCCEEDED(hr)) {
177de1f8ce0SMarc-André Lureau return true;
178de1f8ce0SMarc-André Lureau }
179de1f8ce0SMarc-André Lureau
180de1f8ce0SMarc-André Lureau fail:
181de1f8ce0SMarc-André Lureau error_setg_win32(errp, GetLastError(), "failed to acquire texture mutex");
182de1f8ce0SMarc-André Lureau return false;
183de1f8ce0SMarc-André Lureau }
184de1f8ce0SMarc-André Lureau
d3d_texture2d_release0(ID3D11Texture2D * d3d_texture,Error ** errp)185de1f8ce0SMarc-André Lureau static bool d3d_texture2d_release0(ID3D11Texture2D *d3d_texture, Error **errp)
186de1f8ce0SMarc-André Lureau {
187de1f8ce0SMarc-André Lureau IDXGIKeyedMutex *dxgiMutex = NULL;
188de1f8ce0SMarc-André Lureau HRESULT hr;
189de1f8ce0SMarc-André Lureau
190de1f8ce0SMarc-André Lureau hr = d3d_texture->lpVtbl->QueryInterface(d3d_texture,
191de1f8ce0SMarc-André Lureau &IID_IDXGIKeyedMutex,
192de1f8ce0SMarc-André Lureau (void **)&dxgiMutex);
193de1f8ce0SMarc-André Lureau if (FAILED(hr)) {
194de1f8ce0SMarc-André Lureau goto fail;
195de1f8ce0SMarc-André Lureau }
196de1f8ce0SMarc-André Lureau
197de1f8ce0SMarc-André Lureau hr = dxgiMutex->lpVtbl->ReleaseSync(dxgiMutex, 0);
198d39a84b7SRichard Henderson
199142ca628SMarc-André Lureau dxgiMutex->lpVtbl->Release(dxgiMutex);
200142ca628SMarc-André Lureau
201142ca628SMarc-André Lureau if (SUCCEEDED(hr)) {
202142ca628SMarc-André Lureau return true;
203142ca628SMarc-André Lureau }
204142ca628SMarc-André Lureau
205de1f8ce0SMarc-André Lureau fail:
206142ca628SMarc-André Lureau error_setg_win32(errp, GetLastError(), "failed to release texture mutex");
207de1f8ce0SMarc-André Lureau return false;
208de1f8ce0SMarc-André Lureau }
209de1f8ce0SMarc-André Lureau #endif /* WIN32 */
210de1f8ce0SMarc-André Lureau
211de1f8ce0SMarc-André Lureau #if defined(CONFIG_GBM) || defined(WIN32)
dbus_update_gl_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)212de1f8ce0SMarc-André Lureau static void dbus_update_gl_cb(GObject *source_object,
213de1f8ce0SMarc-André Lureau GAsyncResult *res,
214de1f8ce0SMarc-André Lureau gpointer user_data)
215de1f8ce0SMarc-André Lureau {
216de1f8ce0SMarc-André Lureau g_autoptr(GError) err = NULL;
217de1f8ce0SMarc-André Lureau DBusDisplayListener *ddl = user_data;
218de1f8ce0SMarc-André Lureau bool success;
219142ca628SMarc-André Lureau
220142ca628SMarc-André Lureau #ifdef CONFIG_GBM
221142ca628SMarc-André Lureau success = qemu_dbus_display1_listener_call_update_dmabuf_finish(
222142ca628SMarc-André Lureau ddl->proxy, res, &err);
223142ca628SMarc-André Lureau #endif
224142ca628SMarc-André Lureau
225d39a84b7SRichard Henderson #ifdef WIN32
226142ca628SMarc-André Lureau success = qemu_dbus_display1_listener_win32_d3d11_call_update_texture2d_finish(
227f43bf0a7SMarc-André Lureau ddl->d3d11_proxy, res, &err);
228142ca628SMarc-André Lureau d3d_texture2d_acquire0(ddl->d3d_texture, &error_warn);
229142ca628SMarc-André Lureau #endif
230d39a84b7SRichard Henderson
231f43bf0a7SMarc-André Lureau if (!success) {
232d39a84b7SRichard Henderson error_report("Failed to call update: %s", err->message);
233f43bf0a7SMarc-André Lureau }
234cf283fb4SMarc-André Lureau
235cf283fb4SMarc-André Lureau graphic_hw_gl_block(ddl->dcl.con, false);
236142ca628SMarc-André Lureau g_object_unref(ddl);
237f43bf0a7SMarc-André Lureau }
238f43bf0a7SMarc-André Lureau #endif
239142ca628SMarc-André Lureau
dbus_call_update_gl(DisplayChangeListener * dcl,int x,int y,int w,int h)240142ca628SMarc-André Lureau static void dbus_call_update_gl(DisplayChangeListener *dcl,
241142ca628SMarc-André Lureau int x, int y, int w, int h)
242142ca628SMarc-André Lureau {
243142ca628SMarc-André Lureau #if defined(CONFIG_GBM) || defined(WIN32)
244142ca628SMarc-André Lureau DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl);
245f43bf0a7SMarc-André Lureau #endif
246f43bf0a7SMarc-André Lureau
247f43bf0a7SMarc-André Lureau trace_dbus_update_gl(x, y, w, h);
248de1f8ce0SMarc-André Lureau
249de1f8ce0SMarc-André Lureau glFlush();
250f43bf0a7SMarc-André Lureau #ifdef CONFIG_GBM
251f43bf0a7SMarc-André Lureau graphic_hw_gl_block(ddl->dcl.con, true);
252de1f8ce0SMarc-André Lureau qemu_dbus_display1_listener_call_update_dmabuf(ddl->proxy,
2537b4a3f81SMarc-André Lureau x, y, w, h,
254de1f8ce0SMarc-André Lureau G_DBUS_CALL_FLAGS_NONE,
255de1f8ce0SMarc-André Lureau DBUS_DEFAULT_TIMEOUT, NULL,
256de1f8ce0SMarc-André Lureau dbus_update_gl_cb,
257de1f8ce0SMarc-André Lureau g_object_ref(ddl));
258de1f8ce0SMarc-André Lureau #endif
259de1f8ce0SMarc-André Lureau
260de1f8ce0SMarc-André Lureau #ifdef WIN32
261de1f8ce0SMarc-André Lureau switch (ddl->ds_share) {
262de1f8ce0SMarc-André Lureau case SHARE_KIND_MAPPED:
263de1f8ce0SMarc-André Lureau egl_fb_read_rect(ddl->ds, &ddl->fb, x, y, w, h);
264de1f8ce0SMarc-André Lureau dbus_gfx_update(dcl, x, y, w, h);
265de1f8ce0SMarc-André Lureau break;
266de1f8ce0SMarc-André Lureau case SHARE_KIND_D3DTEX: {
267de1f8ce0SMarc-André Lureau Error *err = NULL;
268de1f8ce0SMarc-André Lureau assert(ddl->d3d_texture);
269de1f8ce0SMarc-André Lureau
2707b4a3f81SMarc-André Lureau graphic_hw_gl_block(ddl->dcl.con, true);
271de1f8ce0SMarc-André Lureau if (!d3d_texture2d_release0(ddl->d3d_texture, &err)) {
272de1f8ce0SMarc-André Lureau error_report_err(err);
273de1f8ce0SMarc-André Lureau return;
274f43bf0a7SMarc-André Lureau }
275142ca628SMarc-André Lureau qemu_dbus_display1_listener_win32_d3d11_call_update_texture2d(
276142ca628SMarc-André Lureau ddl->d3d11_proxy,
277f43bf0a7SMarc-André Lureau x, y, w, h,
278142ca628SMarc-André Lureau G_DBUS_CALL_FLAGS_NONE,
279142ca628SMarc-André Lureau DBUS_DEFAULT_TIMEOUT, NULL,
280142ca628SMarc-André Lureau dbus_update_gl_cb,
281142ca628SMarc-André Lureau g_object_ref(ddl));
282142ca628SMarc-André Lureau break;
283142ca628SMarc-André Lureau }
2846779a307SDongwon Kim default:
2856779a307SDongwon Kim g_warn_if_reached();
2866779a307SDongwon Kim }
2876779a307SDongwon Kim #endif
288142ca628SMarc-André Lureau }
2896779a307SDongwon Kim
290142ca628SMarc-André Lureau #ifdef CONFIG_GBM
dbus_scanout_dmabuf(DisplayChangeListener * dcl,QemuDmaBuf * dmabuf)2916779a307SDongwon Kim static void dbus_scanout_dmabuf(DisplayChangeListener *dcl,
292142ca628SMarc-André Lureau QemuDmaBuf *dmabuf)
293142ca628SMarc-André Lureau {
294142ca628SMarc-André Lureau DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl);
295142ca628SMarc-André Lureau g_autoptr(GError) err = NULL;
296*01fff506SMarc-André Lureau g_autoptr(GUnixFDList) fd_list = NULL;
297fa88b85dSMarc-André Lureau int fd;
2986779a307SDongwon Kim uint32_t width, height, stride, fourcc;
2996779a307SDongwon Kim uint64_t modifier;
3006779a307SDongwon Kim bool y0_top;
3016779a307SDongwon Kim
3026779a307SDongwon Kim fd = qemu_dmabuf_get_fd(dmabuf);
3036779a307SDongwon Kim fd_list = g_unix_fd_list_new();
3046779a307SDongwon Kim if (g_unix_fd_list_append(fd_list, fd, &err) != 0) {
305da1d066cSMarc-André Lureau error_report("Failed to setup dmabuf fdlist: %s", err->message);
306142ca628SMarc-André Lureau return;
3076779a307SDongwon Kim }
3086779a307SDongwon Kim
3096779a307SDongwon Kim ddl_discard_display_messages(ddl);
3106779a307SDongwon Kim
311142ca628SMarc-André Lureau width = qemu_dmabuf_get_width(dmabuf);
312f43bf0a7SMarc-André Lureau height = qemu_dmabuf_get_height(dmabuf);
313f43bf0a7SMarc-André Lureau stride = qemu_dmabuf_get_stride(dmabuf);
314142ca628SMarc-André Lureau fourcc = qemu_dmabuf_get_fourcc(dmabuf);
31548dddba1SMarc-André Lureau modifier = qemu_dmabuf_get_modifier(dmabuf);
31648dddba1SMarc-André Lureau y0_top = qemu_dmabuf_get_y0_top(dmabuf);
31748dddba1SMarc-André Lureau
31848dddba1SMarc-André Lureau /* FIXME: add missing x/y/w/h support */
31948dddba1SMarc-André Lureau qemu_dbus_display1_listener_call_scanout_dmabuf(
32048dddba1SMarc-André Lureau ddl->proxy, g_variant_new_handle(0),
32148dddba1SMarc-André Lureau width, height, stride, fourcc, modifier,
322de1f8ce0SMarc-André Lureau y0_top, G_DBUS_CALL_FLAGS_NONE,
32348dddba1SMarc-André Lureau -1, fd_list, NULL, NULL, NULL);
32448dddba1SMarc-André Lureau }
32548dddba1SMarc-André Lureau #endif /* GBM */
32648dddba1SMarc-André Lureau #endif /* OPENGL */
32748dddba1SMarc-André Lureau
32848dddba1SMarc-André Lureau #ifdef WIN32
dbus_scanout_map(DBusDisplayListener * ddl)32948dddba1SMarc-André Lureau static bool dbus_scanout_map(DBusDisplayListener *ddl)
33048dddba1SMarc-André Lureau {
33148dddba1SMarc-André Lureau g_autoptr(GError) err = NULL;
33248dddba1SMarc-André Lureau BOOL success;
33348dddba1SMarc-André Lureau HANDLE target_handle;
33448dddba1SMarc-André Lureau
33548dddba1SMarc-André Lureau if (ddl->ds_share == SHARE_KIND_MAPPED) {
33648dddba1SMarc-André Lureau return true;
33748dddba1SMarc-André Lureau }
33848dddba1SMarc-André Lureau
33948dddba1SMarc-André Lureau if (!ddl->can_share_map || !ddl->ds->share_handle) {
34048dddba1SMarc-André Lureau return false;
34148dddba1SMarc-André Lureau }
34248dddba1SMarc-André Lureau
34348dddba1SMarc-André Lureau success = DuplicateHandle(
344*01fff506SMarc-André Lureau GetCurrentProcess(),
345fa88b85dSMarc-André Lureau ddl->ds->share_handle,
34648dddba1SMarc-André Lureau ddl->peer_process,
34748dddba1SMarc-André Lureau &target_handle,
34848dddba1SMarc-André Lureau FILE_MAP_READ | SECTION_QUERY,
34948dddba1SMarc-André Lureau FALSE, 0);
35048dddba1SMarc-André Lureau if (!success) {
35148dddba1SMarc-André Lureau g_autofree char *msg = g_win32_error_message(GetLastError());
35248dddba1SMarc-André Lureau g_debug("Failed to DuplicateHandle: %s", msg);
35348dddba1SMarc-André Lureau ddl->can_share_map = false;
35448dddba1SMarc-André Lureau return false;
35548dddba1SMarc-André Lureau }
35648dddba1SMarc-André Lureau
35748dddba1SMarc-André Lureau ddl_discard_display_messages(ddl);
35848dddba1SMarc-André Lureau
35948dddba1SMarc-André Lureau if (!qemu_dbus_display1_listener_win32_map_call_scanout_map_sync(
36048dddba1SMarc-André Lureau ddl->map_proxy,
36148dddba1SMarc-André Lureau GPOINTER_TO_UINT(target_handle),
36248dddba1SMarc-André Lureau ddl->ds->share_handle_offset,
363de1f8ce0SMarc-André Lureau surface_width(ddl->ds),
364de1f8ce0SMarc-André Lureau surface_height(ddl->ds),
365de1f8ce0SMarc-André Lureau surface_stride(ddl->ds),
366de1f8ce0SMarc-André Lureau surface_format(ddl->ds),
367de1f8ce0SMarc-André Lureau G_DBUS_CALL_FLAGS_NONE,
368866b24e4SMarc-Andre Lureau DBUS_DEFAULT_TIMEOUT,
369de1f8ce0SMarc-André Lureau NULL,
370de1f8ce0SMarc-André Lureau &err)) {
371de1f8ce0SMarc-André Lureau g_debug("Failed to call ScanoutMap: %s", err->message);
372de1f8ce0SMarc-André Lureau ddl->can_share_map = false;
373de1f8ce0SMarc-André Lureau return false;
374de1f8ce0SMarc-André Lureau }
375de1f8ce0SMarc-André Lureau
376de1f8ce0SMarc-André Lureau ddl->ds_share = SHARE_KIND_MAPPED;
377de1f8ce0SMarc-André Lureau
378de1f8ce0SMarc-André Lureau return true;
379de1f8ce0SMarc-André Lureau }
380de1f8ce0SMarc-André Lureau
381de1f8ce0SMarc-André Lureau #ifdef CONFIG_OPENGL
382de1f8ce0SMarc-André Lureau static bool
dbus_scanout_share_d3d_texture(DBusDisplayListener * ddl,ID3D11Texture2D * tex,bool backing_y_0_top,uint32_t backing_width,uint32_t backing_height,uint32_t x,uint32_t y,uint32_t w,uint32_t h)383de1f8ce0SMarc-André Lureau dbus_scanout_share_d3d_texture(
384de1f8ce0SMarc-André Lureau DBusDisplayListener *ddl,
385de1f8ce0SMarc-André Lureau ID3D11Texture2D *tex,
386de1f8ce0SMarc-André Lureau bool backing_y_0_top,
387de1f8ce0SMarc-André Lureau uint32_t backing_width,
388de1f8ce0SMarc-André Lureau uint32_t backing_height,
389de1f8ce0SMarc-André Lureau uint32_t x, uint32_t y,
390de1f8ce0SMarc-André Lureau uint32_t w, uint32_t h)
391de1f8ce0SMarc-André Lureau {
392de1f8ce0SMarc-André Lureau Error *err = NULL;
393de1f8ce0SMarc-André Lureau BOOL success;
394de1f8ce0SMarc-André Lureau HANDLE share_handle, target_handle;
395de1f8ce0SMarc-André Lureau
396de1f8ce0SMarc-André Lureau if (!d3d_texture2d_release0(tex, &err)) {
397de1f8ce0SMarc-André Lureau error_report_err(err);
398de1f8ce0SMarc-André Lureau return false;
399de1f8ce0SMarc-André Lureau }
400de1f8ce0SMarc-André Lureau
401de1f8ce0SMarc-André Lureau if (!d3d_texture2d_share(tex, &share_handle, &err)) {
402de1f8ce0SMarc-André Lureau error_report_err(err);
403de1f8ce0SMarc-André Lureau return false;
404de1f8ce0SMarc-André Lureau }
405de1f8ce0SMarc-André Lureau
406de1f8ce0SMarc-André Lureau success = DuplicateHandle(
407*01fff506SMarc-André Lureau GetCurrentProcess(),
408fa88b85dSMarc-André Lureau share_handle,
409de1f8ce0SMarc-André Lureau ddl->peer_process,
410de1f8ce0SMarc-André Lureau &target_handle,
411de1f8ce0SMarc-André Lureau 0,
412de1f8ce0SMarc-André Lureau FALSE, DUPLICATE_SAME_ACCESS);
413de1f8ce0SMarc-André Lureau if (!success) {
414de1f8ce0SMarc-André Lureau g_autofree char *msg = g_win32_error_message(GetLastError());
415de1f8ce0SMarc-André Lureau g_debug("Failed to DuplicateHandle: %s", msg);
416de1f8ce0SMarc-André Lureau CloseHandle(share_handle);
417de1f8ce0SMarc-André Lureau return false;
418de1f8ce0SMarc-André Lureau }
419de1f8ce0SMarc-André Lureau
420de1f8ce0SMarc-André Lureau ddl_discard_display_messages(ddl);
421de1f8ce0SMarc-André Lureau
422de1f8ce0SMarc-André Lureau qemu_dbus_display1_listener_win32_d3d11_call_scanout_texture2d(
423de1f8ce0SMarc-André Lureau ddl->d3d11_proxy,
424de1f8ce0SMarc-André Lureau GPOINTER_TO_INT(target_handle),
425de1f8ce0SMarc-André Lureau backing_width,
426de1f8ce0SMarc-André Lureau backing_height,
427de1f8ce0SMarc-André Lureau backing_y_0_top,
428de1f8ce0SMarc-André Lureau x, y, w, h,
42948dddba1SMarc-André Lureau G_DBUS_CALL_FLAGS_NONE,
43048dddba1SMarc-André Lureau -1,
43148dddba1SMarc-André Lureau NULL, NULL, NULL);
432866b24e4SMarc-Andre Lureau
433866b24e4SMarc-Andre Lureau CloseHandle(share_handle);
43448dddba1SMarc-André Lureau
435f43bf0a7SMarc-André Lureau if (!d3d_texture2d_acquire0(tex, &err)) {
436142ca628SMarc-André Lureau error_report_err(err);
437142ca628SMarc-André Lureau return false;
438142ca628SMarc-André Lureau }
439142ca628SMarc-André Lureau
440142ca628SMarc-André Lureau ddl->d3d_texture = tex;
441142ca628SMarc-André Lureau ddl->ds_share = SHARE_KIND_D3DTEX;
442bf41ab61SMarc-André Lureau
443bf41ab61SMarc-André Lureau return true;
444142ca628SMarc-André Lureau }
445cf283fb4SMarc-André Lureau #endif /* CONFIG_OPENGL */
446cf283fb4SMarc-André Lureau #else /* !WIN32 */
dbus_scanout_map(DBusDisplayListener * ddl)447f43bf0a7SMarc-André Lureau static bool dbus_scanout_map(DBusDisplayListener *ddl)
448c0fcd633SDongwon Kim {
449c0fcd633SDongwon Kim g_autoptr(GError) err = NULL;
450c0fcd633SDongwon Kim g_autoptr(GUnixFDList) fd_list = NULL;
451c0fcd633SDongwon Kim
452142ca628SMarc-André Lureau if (ddl->ds_share == SHARE_KIND_MAPPED) {
453142ca628SMarc-André Lureau return true;
454c0fcd633SDongwon Kim }
455c0fcd633SDongwon Kim
456c0fcd633SDongwon Kim if (!ddl->can_share_map || ddl->ds->share_handle == SHAREABLE_NONE) {
457142ca628SMarc-André Lureau return false;
458142ca628SMarc-André Lureau }
459142ca628SMarc-André Lureau
460c0fcd633SDongwon Kim ddl_discard_display_messages(ddl);
461c0fcd633SDongwon Kim fd_list = g_unix_fd_list_new();
462c0fcd633SDongwon Kim if (g_unix_fd_list_append(fd_list, ddl->ds->share_handle, &err) != 0) {
463142ca628SMarc-André Lureau g_debug("Failed to setup scanout map fdlist: %s", err->message);
464c0fcd633SDongwon Kim ddl->can_share_map = false;
465c0fcd633SDongwon Kim return false;
466f43bf0a7SMarc-André Lureau }
467f43bf0a7SMarc-André Lureau
468f43bf0a7SMarc-André Lureau if (!qemu_dbus_display1_listener_unix_map_call_scanout_map_sync(
469f43bf0a7SMarc-André Lureau ddl->map_proxy,
470f43bf0a7SMarc-André Lureau g_variant_new_handle(0),
471f43bf0a7SMarc-André Lureau ddl->ds->share_handle_offset,
472f43bf0a7SMarc-André Lureau surface_width(ddl->ds),
473f43bf0a7SMarc-André Lureau surface_height(ddl->ds),
474de1f8ce0SMarc-André Lureau surface_stride(ddl->ds),
475de1f8ce0SMarc-André Lureau surface_format(ddl->ds),
476de1f8ce0SMarc-André Lureau G_DBUS_CALL_FLAGS_NONE,
477de1f8ce0SMarc-André Lureau DBUS_DEFAULT_TIMEOUT,
478de1f8ce0SMarc-André Lureau fd_list,
479de1f8ce0SMarc-André Lureau NULL,
480f43bf0a7SMarc-André Lureau NULL,
481de1f8ce0SMarc-André Lureau &err)) {
482f43bf0a7SMarc-André Lureau g_debug("Failed to call ScanoutMap: %s", err->message);
483142ca628SMarc-André Lureau ddl->can_share_map = false;
484142ca628SMarc-André Lureau return false;
485f43bf0a7SMarc-André Lureau }
486142ca628SMarc-André Lureau
487142ca628SMarc-André Lureau ddl->ds_share = SHARE_KIND_MAPPED;
488142ca628SMarc-André Lureau
489142ca628SMarc-André Lureau return true;
490142ca628SMarc-André Lureau }
491142ca628SMarc-André Lureau #endif /* WIN32 */
492142ca628SMarc-André Lureau
4938bb6af67SMarc-André Lureau #ifdef CONFIG_OPENGL
dbus_scanout_texture(DisplayChangeListener * dcl,uint32_t tex_id,bool backing_y_0_top,uint32_t backing_width,uint32_t backing_height,uint32_t x,uint32_t y,uint32_t w,uint32_t h,void * d3d_tex2d)4946779a307SDongwon Kim static void dbus_scanout_texture(DisplayChangeListener *dcl,
495142ca628SMarc-André Lureau uint32_t tex_id,
496142ca628SMarc-André Lureau bool backing_y_0_top,
497142ca628SMarc-André Lureau uint32_t backing_width,
498142ca628SMarc-André Lureau uint32_t backing_height,
499142ca628SMarc-André Lureau uint32_t x, uint32_t y,
500142ca628SMarc-André Lureau uint32_t w, uint32_t h,
501142ca628SMarc-André Lureau void *d3d_tex2d)
502142ca628SMarc-André Lureau {
503142ca628SMarc-André Lureau trace_dbus_scanout_texture(tex_id, backing_y_0_top,
5046779a307SDongwon Kim backing_width, backing_height, x, y, w, h);
5056779a307SDongwon Kim #ifdef CONFIG_GBM
506142ca628SMarc-André Lureau g_autoptr(QemuDmaBuf) dmabuf = NULL;
507142ca628SMarc-André Lureau int fd;
5086779a307SDongwon Kim uint32_t stride, fourcc;
5096779a307SDongwon Kim uint64_t modifier;
5106779a307SDongwon Kim
5116779a307SDongwon Kim assert(tex_id);
5126779a307SDongwon Kim fd = egl_get_fd_for_texture(tex_id, (EGLint *)&stride, (EGLint *)&fourcc,
5136779a307SDongwon Kim &modifier);
514142ca628SMarc-André Lureau if (fd < 0) {
515142ca628SMarc-André Lureau error_report("%s: failed to get fd for texture", __func__);
516142ca628SMarc-André Lureau return;
517142ca628SMarc-André Lureau }
518142ca628SMarc-André Lureau dmabuf = qemu_dmabuf_new(w, h, stride, x, y, backing_width,
519142ca628SMarc-André Lureau backing_height, fourcc, modifier, fd,
520142ca628SMarc-André Lureau false, backing_y_0_top);
521142ca628SMarc-André Lureau
522142ca628SMarc-André Lureau dbus_scanout_dmabuf(dcl, dmabuf);
523142ca628SMarc-André Lureau qemu_dmabuf_close(dmabuf);
524142ca628SMarc-André Lureau #endif
525142ca628SMarc-André Lureau
526142ca628SMarc-André Lureau #ifdef WIN32
527142ca628SMarc-André Lureau DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl);
528142ca628SMarc-André Lureau
529142ca628SMarc-André Lureau /* there must be a matching gfx_switch before */
530142ca628SMarc-André Lureau assert(surface_width(ddl->ds) == w);
531142ca628SMarc-André Lureau assert(surface_height(ddl->ds) == h);
532142ca628SMarc-André Lureau
533142ca628SMarc-André Lureau if (d3d_tex2d) {
534142ca628SMarc-André Lureau dbus_scanout_share_d3d_texture(ddl, d3d_tex2d, backing_y_0_top,
535142ca628SMarc-André Lureau backing_width, backing_height, x, y, w, h);
536142ca628SMarc-André Lureau } else {
537f43bf0a7SMarc-André Lureau dbus_scanout_map(ddl);
538f43bf0a7SMarc-André Lureau egl_fb_setup_for_tex(&ddl->fb, backing_width, backing_height, tex_id, false);
539f43bf0a7SMarc-André Lureau }
540f43bf0a7SMarc-André Lureau #endif
541f43bf0a7SMarc-André Lureau }
542f43bf0a7SMarc-André Lureau
543f43bf0a7SMarc-André Lureau #ifdef CONFIG_GBM
dbus_cursor_dmabuf(DisplayChangeListener * dcl,QemuDmaBuf * dmabuf,bool have_hot,uint32_t hot_x,uint32_t hot_y)544f43bf0a7SMarc-André Lureau static void dbus_cursor_dmabuf(DisplayChangeListener *dcl,
545142ca628SMarc-André Lureau QemuDmaBuf *dmabuf, bool have_hot,
546142ca628SMarc-André Lureau uint32_t hot_x, uint32_t hot_y)
547142ca628SMarc-André Lureau {
548142ca628SMarc-André Lureau DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl);
549142ca628SMarc-André Lureau DisplaySurface *ds;
550142ca628SMarc-André Lureau GVariant *v_data = NULL;
551142ca628SMarc-André Lureau egl_fb cursor_fb = EGL_FB_INIT;
552142ca628SMarc-André Lureau uint32_t width, height, texture;
553142ca628SMarc-André Lureau
554142ca628SMarc-André Lureau if (!dmabuf) {
555142ca628SMarc-André Lureau qemu_dbus_display1_listener_call_mouse_set(
556142ca628SMarc-André Lureau ddl->proxy, 0, 0, false,
557142ca628SMarc-André Lureau G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
558f43bf0a7SMarc-André Lureau return;
559142ca628SMarc-André Lureau }
560142ca628SMarc-André Lureau
561142ca628SMarc-André Lureau ddl_discard_cursor_messages(ddl);
562142ca628SMarc-André Lureau
563142ca628SMarc-André Lureau egl_dmabuf_import_texture(dmabuf);
564142ca628SMarc-André Lureau texture = qemu_dmabuf_get_texture(dmabuf);
565142ca628SMarc-André Lureau if (!texture) {
566142ca628SMarc-André Lureau return;
567142ca628SMarc-André Lureau }
568142ca628SMarc-André Lureau
569142ca628SMarc-André Lureau width = qemu_dmabuf_get_width(dmabuf);
570142ca628SMarc-André Lureau height = qemu_dmabuf_get_height(dmabuf);
571949c084aSMarc-André Lureau
5727007e98cSBilal Elmoussaoui egl_fb_setup_for_tex(&cursor_fb, width, height, texture, false);
5737007e98cSBilal Elmoussaoui ds = qemu_create_displaysurface(width, height);
5747007e98cSBilal Elmoussaoui egl_fb_read(ds, &cursor_fb);
5757007e98cSBilal Elmoussaoui
5767007e98cSBilal Elmoussaoui v_data = g_variant_new_from_data(
5777007e98cSBilal Elmoussaoui G_VARIANT_TYPE("ay"),
5787007e98cSBilal Elmoussaoui surface_data(ds),
5797007e98cSBilal Elmoussaoui surface_width(ds) * surface_height(ds) * 4,
580142ca628SMarc-André Lureau TRUE,
5817007e98cSBilal Elmoussaoui (GDestroyNotify)qemu_free_displaysurface,
582949c084aSMarc-André Lureau ds);
583949c084aSMarc-André Lureau qemu_dbus_display1_listener_call_cursor_define(
584949c084aSMarc-André Lureau ddl->proxy,
585949c084aSMarc-André Lureau surface_width(ds),
586949c084aSMarc-André Lureau surface_height(ds),
587949c084aSMarc-André Lureau hot_x,
588949c084aSMarc-André Lureau hot_y,
589142ca628SMarc-André Lureau v_data,
590f43bf0a7SMarc-André Lureau G_DBUS_CALL_FLAGS_NONE,
591142ca628SMarc-André Lureau -1,
592142ca628SMarc-André Lureau NULL,
593142ca628SMarc-André Lureau NULL,
594142ca628SMarc-André Lureau NULL);
595142ca628SMarc-André Lureau }
596142ca628SMarc-André Lureau
dbus_release_dmabuf(DisplayChangeListener * dcl,QemuDmaBuf * dmabuf)597f43bf0a7SMarc-André Lureau static void dbus_release_dmabuf(DisplayChangeListener *dcl,
598142ca628SMarc-André Lureau QemuDmaBuf *dmabuf)
599142ca628SMarc-André Lureau {
600142ca628SMarc-André Lureau dbus_scanout_disable(dcl);
601142ca628SMarc-André Lureau }
602142ca628SMarc-André Lureau #endif /* GBM */
603949c084aSMarc-André Lureau
dbus_gl_cursor_position(DisplayChangeListener * dcl,uint32_t pos_x,uint32_t pos_y)6047007e98cSBilal Elmoussaoui static void dbus_gl_cursor_position(DisplayChangeListener *dcl,
6057007e98cSBilal Elmoussaoui uint32_t pos_x, uint32_t pos_y)
6067007e98cSBilal Elmoussaoui {
6077007e98cSBilal Elmoussaoui DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl);
608949c084aSMarc-André Lureau
609949c084aSMarc-André Lureau qemu_dbus_display1_listener_call_mouse_set(
610949c084aSMarc-André Lureau ddl->proxy, pos_x, pos_y, true,
611142ca628SMarc-André Lureau G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
61284a0a2efSMarc-André Lureau }
613142ca628SMarc-André Lureau
dbus_scanout_update(DisplayChangeListener * dcl,uint32_t x,uint32_t y,uint32_t w,uint32_t h)614949c084aSMarc-André Lureau static void dbus_scanout_update(DisplayChangeListener *dcl,
615949c084aSMarc-André Lureau uint32_t x, uint32_t y,
616949c084aSMarc-André Lureau uint32_t w, uint32_t h)
617949c084aSMarc-André Lureau {
618949c084aSMarc-André Lureau dbus_call_update_gl(dcl, x, y, w, h);
619949c084aSMarc-André Lureau }
620949c084aSMarc-André Lureau
dbus_gl_refresh(DisplayChangeListener * dcl)621949c084aSMarc-André Lureau static void dbus_gl_refresh(DisplayChangeListener *dcl)
622949c084aSMarc-André Lureau {
623949c084aSMarc-André Lureau DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl);
624949c084aSMarc-André Lureau
625949c084aSMarc-André Lureau graphic_hw_update(dcl->con);
626949c084aSMarc-André Lureau
627949c084aSMarc-André Lureau if (!ddl->ds || qemu_console_is_gl_blocked(ddl->dcl.con)) {
628949c084aSMarc-André Lureau return;
629949c084aSMarc-André Lureau }
630949c084aSMarc-André Lureau
631949c084aSMarc-André Lureau #ifdef CONFIG_PIXMAN
632949c084aSMarc-André Lureau int n_rects = pixman_region32_n_rects(&ddl->gl_damage);
633949c084aSMarc-André Lureau
634949c084aSMarc-André Lureau for (int i = 0; i < n_rects; i++) {
635949c084aSMarc-André Lureau pixman_box32_t *box;
636949c084aSMarc-André Lureau box = pixman_region32_rectangles(&ddl->gl_damage, NULL) + i;
637949c084aSMarc-André Lureau /* TODO: Add a UpdateList call to send multiple updates at once */
638949c084aSMarc-André Lureau dbus_call_update_gl(dcl, box->x1, box->y1,
639949c084aSMarc-André Lureau box->x2 - box->x1, box->y2 - box->y1);
640949c084aSMarc-André Lureau }
641949c084aSMarc-André Lureau pixman_region32_clear(&ddl->gl_damage);
642949c084aSMarc-André Lureau #else
643949c084aSMarc-André Lureau if (ddl->gl_damage) {
644949c084aSMarc-André Lureau dbus_call_update_gl(dcl, 0, 0,
645949c084aSMarc-André Lureau surface_width(ddl->ds), surface_height(ddl->ds));
646949c084aSMarc-André Lureau ddl->gl_damage = 0;
647949c084aSMarc-André Lureau }
648949c084aSMarc-André Lureau #endif
649949c084aSMarc-André Lureau }
650949c084aSMarc-André Lureau #endif /* OPENGL */
651949c084aSMarc-André Lureau
dbus_refresh(DisplayChangeListener * dcl)652949c084aSMarc-André Lureau static void dbus_refresh(DisplayChangeListener *dcl)
653949c084aSMarc-André Lureau {
654949c084aSMarc-André Lureau graphic_hw_update(dcl->con);
655949c084aSMarc-André Lureau }
6567945576cSMarc-André Lureau
6577945576cSMarc-André Lureau #ifdef CONFIG_OPENGL
dbus_gl_gfx_update(DisplayChangeListener * dcl,int x,int y,int w,int h)6587945576cSMarc-André Lureau static void dbus_gl_gfx_update(DisplayChangeListener *dcl,
6597945576cSMarc-André Lureau int x, int y, int w, int h)
6607945576cSMarc-André Lureau {
6617945576cSMarc-André Lureau DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl);
6627945576cSMarc-André Lureau
6637945576cSMarc-André Lureau #ifdef CONFIG_PIXMAN
6647945576cSMarc-André Lureau pixman_region32_t rect_region;
665*01fff506SMarc-André Lureau pixman_region32_init_rect(&rect_region, x, y, w, h);
666fa88b85dSMarc-André Lureau pixman_region32_union(&ddl->gl_damage, &ddl->gl_damage, &rect_region);
6677945576cSMarc-André Lureau pixman_region32_fini(&rect_region);
6687945576cSMarc-André Lureau #else
6697945576cSMarc-André Lureau ddl->gl_damage++;
6707945576cSMarc-André Lureau #endif
6717945576cSMarc-André Lureau }
6727945576cSMarc-André Lureau #endif
6737945576cSMarc-André Lureau
dbus_gfx_update_sub(DBusDisplayListener * ddl,int x,int y,int w,int h)674142ca628SMarc-André Lureau static void dbus_gfx_update_sub(DBusDisplayListener *ddl,
675142ca628SMarc-André Lureau int x, int y, int w, int h)
676142ca628SMarc-André Lureau {
677142ca628SMarc-André Lureau pixman_image_t *img;
678142ca628SMarc-André Lureau size_t stride;
679142ca628SMarc-André Lureau GVariant *v_data;
680142ca628SMarc-André Lureau
681142ca628SMarc-André Lureau /* make a copy, since gvariant only handles linear data */
682142ca628SMarc-André Lureau stride = w * DIV_ROUND_UP(PIXMAN_FORMAT_BPP(surface_format(ddl->ds)), 8);
68348dddba1SMarc-André Lureau img = pixman_image_create_bits(surface_format(ddl->ds),
68448dddba1SMarc-André Lureau w, h, NULL, stride);
68548dddba1SMarc-André Lureau #ifdef CONFIG_PIXMAN
68648dddba1SMarc-André Lureau pixman_image_composite(PIXMAN_OP_SRC, ddl->ds->image, NULL, img,
68748dddba1SMarc-André Lureau x, y, 0, 0, 0, 0, w, h);
68848dddba1SMarc-André Lureau #else
68948dddba1SMarc-André Lureau {
69048dddba1SMarc-André Lureau uint8_t *src = (uint8_t *)pixman_image_get_data(ddl->ds->image);
69148dddba1SMarc-André Lureau uint8_t *dst = (uint8_t *)pixman_image_get_data(img);
69248dddba1SMarc-André Lureau int bp = PIXMAN_FORMAT_BPP(surface_format(ddl->ds)) / 8;
69348dddba1SMarc-André Lureau int hh;
6942fa2386eSMarc-André Lureau
6957945576cSMarc-André Lureau for (hh = 0; hh < h; hh++) {
6962fa2386eSMarc-André Lureau memcpy(&dst[stride * hh],
6972fa2386eSMarc-André Lureau &src[surface_stride(ddl->ds) * (hh + y) + x * bp],
698949c084aSMarc-André Lureau stride);
699142ca628SMarc-André Lureau }
700142ca628SMarc-André Lureau }
701f43bf0a7SMarc-André Lureau #endif
702142ca628SMarc-André Lureau v_data = g_variant_new_from_data(
703142ca628SMarc-André Lureau G_VARIANT_TYPE("ay"),
704142ca628SMarc-André Lureau pixman_image_get_data(img),
705142ca628SMarc-André Lureau pixman_image_get_stride(img) * h,
706142ca628SMarc-André Lureau TRUE,
707cf283fb4SMarc-André Lureau (GDestroyNotify)pixman_image_unref,
708cf283fb4SMarc-André Lureau img);
709142ca628SMarc-André Lureau qemu_dbus_display1_listener_call_update(ddl->proxy,
710de1f8ce0SMarc-André Lureau x, y, w, h, pixman_image_get_stride(img), pixman_image_get_format(img),
711142ca628SMarc-André Lureau v_data,
712142ca628SMarc-André Lureau G_DBUS_CALL_FLAGS_NONE,
713142ca628SMarc-André Lureau DBUS_DEFAULT_TIMEOUT, NULL, NULL, NULL);
714142ca628SMarc-André Lureau }
715142ca628SMarc-André Lureau
ddl_scanout(DBusDisplayListener * ddl)716142ca628SMarc-André Lureau static void ddl_scanout(DBusDisplayListener *ddl)
717bf41ab61SMarc-André Lureau {
718142ca628SMarc-André Lureau GVariant *v_data;
719142ca628SMarc-André Lureau
72084a0a2efSMarc-André Lureau v_data = g_variant_new_from_data(
721142ca628SMarc-André Lureau G_VARIANT_TYPE("ay"), surface_data(ddl->ds),
722142ca628SMarc-André Lureau surface_stride(ddl->ds) * surface_height(ddl->ds), TRUE,
723142ca628SMarc-André Lureau (GDestroyNotify)pixman_image_unref, pixman_image_ref(ddl->ds->image));
724142ca628SMarc-André Lureau
725142ca628SMarc-André Lureau ddl_discard_display_messages(ddl);
726142ca628SMarc-André Lureau
727142ca628SMarc-André Lureau qemu_dbus_display1_listener_call_scanout(
728de1f8ce0SMarc-André Lureau ddl->proxy, surface_width(ddl->ds), surface_height(ddl->ds),
729142ca628SMarc-André Lureau surface_stride(ddl->ds), surface_format(ddl->ds), v_data,
730142ca628SMarc-André Lureau G_DBUS_CALL_FLAGS_NONE, DBUS_DEFAULT_TIMEOUT, NULL, NULL,
731142ca628SMarc-André Lureau g_object_ref(ddl));
732a418e7aeSAkihiko Odaki }
733142ca628SMarc-André Lureau
dbus_gfx_update(DisplayChangeListener * dcl,int x,int y,int w,int h)734142ca628SMarc-André Lureau static void dbus_gfx_update(DisplayChangeListener *dcl,
735142ca628SMarc-André Lureau int x, int y, int w, int h)
736142ca628SMarc-André Lureau {
737142ca628SMarc-André Lureau DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl);
738142ca628SMarc-André Lureau
739142ca628SMarc-André Lureau assert(ddl->ds);
740142ca628SMarc-André Lureau
741142ca628SMarc-André Lureau trace_dbus_update(x, y, w, h);
742142ca628SMarc-André Lureau
743142ca628SMarc-André Lureau if (dbus_scanout_map(ddl)) {
744142ca628SMarc-André Lureau #ifdef WIN32
745142ca628SMarc-André Lureau qemu_dbus_display1_listener_win32_map_call_update_map(
746142ca628SMarc-André Lureau ddl->map_proxy,
747142ca628SMarc-André Lureau x, y, w, h,
748142ca628SMarc-André Lureau G_DBUS_CALL_FLAGS_NONE,
749142ca628SMarc-André Lureau DBUS_DEFAULT_TIMEOUT, NULL, NULL, NULL);
750142ca628SMarc-André Lureau #else
751f4579e28SMarc-André Lureau qemu_dbus_display1_listener_unix_map_call_update_map(
7522512a026SMarc-André Lureau ddl->map_proxy,
753142ca628SMarc-André Lureau x, y, w, h,
754142ca628SMarc-André Lureau G_DBUS_CALL_FLAGS_NONE,
755142ca628SMarc-André Lureau DBUS_DEFAULT_TIMEOUT, NULL, NULL, NULL);
756142ca628SMarc-André Lureau #endif
757142ca628SMarc-André Lureau return;
758142ca628SMarc-André Lureau }
759142ca628SMarc-André Lureau
760142ca628SMarc-André Lureau if (x == 0 && y == 0 && w == surface_width(ddl->ds) && h == surface_height(ddl->ds)) {
761142ca628SMarc-André Lureau return ddl_scanout(ddl);
762142ca628SMarc-André Lureau }
763142ca628SMarc-André Lureau
764142ca628SMarc-André Lureau dbus_gfx_update_sub(ddl, x, y, w, h);
765142ca628SMarc-André Lureau }
766142ca628SMarc-André Lureau
767142ca628SMarc-André Lureau #ifdef CONFIG_OPENGL
dbus_gl_gfx_switch(DisplayChangeListener * dcl,struct DisplaySurface * new_surface)768f43bf0a7SMarc-André Lureau static void dbus_gl_gfx_switch(DisplayChangeListener *dcl,
769142ca628SMarc-André Lureau struct DisplaySurface *new_surface)
770142ca628SMarc-André Lureau {
771142ca628SMarc-André Lureau DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl);
772142ca628SMarc-André Lureau
773142ca628SMarc-André Lureau trace_dbus_gl_gfx_switch(new_surface);
774142ca628SMarc-André Lureau
775142ca628SMarc-André Lureau ddl->ds = new_surface;
776142ca628SMarc-André Lureau ddl->ds_share = SHARE_KIND_NONE;
777142ca628SMarc-André Lureau if (ddl->ds) {
778142ca628SMarc-André Lureau int width = surface_width(ddl->ds);
779142ca628SMarc-André Lureau int height = surface_height(ddl->ds);
780f43bf0a7SMarc-André Lureau
781142ca628SMarc-André Lureau /* TODO: lazy send dmabuf (there are unnecessary sent otherwise) */
782142ca628SMarc-André Lureau dbus_scanout_texture(&ddl->dcl, ddl->ds->texture, false,
783142ca628SMarc-André Lureau width, height, 0, 0, width, height, NULL);
784f43bf0a7SMarc-André Lureau }
785f43bf0a7SMarc-André Lureau }
786142ca628SMarc-André Lureau #endif
787142ca628SMarc-André Lureau
dbus_gfx_switch(DisplayChangeListener * dcl,struct DisplaySurface * new_surface)78884a0a2efSMarc-André Lureau static void dbus_gfx_switch(DisplayChangeListener *dcl,
789142ca628SMarc-André Lureau struct DisplaySurface *new_surface)
790142ca628SMarc-André Lureau {
791142ca628SMarc-André Lureau DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl);
792142ca628SMarc-André Lureau
793142ca628SMarc-André Lureau ddl->ds = new_surface;
794142ca628SMarc-André Lureau ddl->ds_share = SHARE_KIND_NONE;
795142ca628SMarc-André Lureau }
796142ca628SMarc-André Lureau
dbus_mouse_set(DisplayChangeListener * dcl,int x,int y,bool on)797142ca628SMarc-André Lureau static void dbus_mouse_set(DisplayChangeListener *dcl,
798142ca628SMarc-André Lureau int x, int y, bool on)
799142ca628SMarc-André Lureau {
800142ca628SMarc-André Lureau DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl);
801142ca628SMarc-André Lureau
802142ca628SMarc-André Lureau qemu_dbus_display1_listener_call_mouse_set(
803142ca628SMarc-André Lureau ddl->proxy, x, y, on, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
804142ca628SMarc-André Lureau }
805142ca628SMarc-André Lureau
dbus_cursor_define(DisplayChangeListener * dcl,QEMUCursor * c)806142ca628SMarc-André Lureau static void dbus_cursor_define(DisplayChangeListener *dcl,
807142ca628SMarc-André Lureau QEMUCursor *c)
80848dddba1SMarc-André Lureau {
80948dddba1SMarc-André Lureau DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl);
810de1f8ce0SMarc-André Lureau GVariant *v_data = NULL;
81148dddba1SMarc-André Lureau
812949c084aSMarc-André Lureau ddl_discard_cursor_messages(ddl);
8137007e98cSBilal Elmoussaoui
814949c084aSMarc-André Lureau v_data = g_variant_new_from_data(
815949c084aSMarc-André Lureau G_VARIANT_TYPE("ay"),
816f43bf0a7SMarc-André Lureau c->data,
817f43bf0a7SMarc-André Lureau c->width * c->height * 4,
81848dddba1SMarc-André Lureau TRUE,
819142ca628SMarc-André Lureau (GDestroyNotify)cursor_unref,
820142ca628SMarc-André Lureau cursor_ref(c));
821142ca628SMarc-André Lureau
822142ca628SMarc-André Lureau qemu_dbus_display1_listener_call_cursor_define(
823142ca628SMarc-André Lureau ddl->proxy,
824142ca628SMarc-André Lureau c->width,
825142ca628SMarc-André Lureau c->height,
826142ca628SMarc-André Lureau c->hot_x,
827142ca628SMarc-André Lureau c->hot_y,
82884a0a2efSMarc-André Lureau v_data,
829f43bf0a7SMarc-André Lureau G_DBUS_CALL_FLAGS_NONE,
830142ca628SMarc-André Lureau -1,
831142ca628SMarc-André Lureau NULL,
832142ca628SMarc-André Lureau NULL,
83384a0a2efSMarc-André Lureau NULL);
834142ca628SMarc-André Lureau }
835142ca628SMarc-André Lureau
836142ca628SMarc-André Lureau #ifdef CONFIG_OPENGL
837142ca628SMarc-André Lureau const DisplayChangeListenerOps dbus_gl_dcl_ops = {
838142ca628SMarc-André Lureau .dpy_name = "dbus-gl",
839142ca628SMarc-André Lureau .dpy_gfx_update = dbus_gl_gfx_update,
840142ca628SMarc-André Lureau .dpy_gfx_switch = dbus_gl_gfx_switch,
841142ca628SMarc-André Lureau .dpy_gfx_check_format = console_gl_check_format,
842142ca628SMarc-André Lureau .dpy_refresh = dbus_gl_refresh,
843142ca628SMarc-André Lureau .dpy_mouse_set = dbus_mouse_set,
844142ca628SMarc-André Lureau .dpy_cursor_define = dbus_cursor_define,
845142ca628SMarc-André Lureau
846142ca628SMarc-André Lureau .dpy_gl_scanout_disable = dbus_scanout_disable,
847142ca628SMarc-André Lureau .dpy_gl_scanout_texture = dbus_scanout_texture,
848142ca628SMarc-André Lureau #ifdef CONFIG_GBM
849142ca628SMarc-André Lureau .dpy_gl_scanout_dmabuf = dbus_scanout_dmabuf,
850949c084aSMarc-André Lureau .dpy_gl_cursor_dmabuf = dbus_cursor_dmabuf,
8517007e98cSBilal Elmoussaoui .dpy_gl_release_dmabuf = dbus_release_dmabuf,
8527007e98cSBilal Elmoussaoui #endif
853142ca628SMarc-André Lureau .dpy_gl_cursor_position = dbus_gl_cursor_position,
854142ca628SMarc-André Lureau .dpy_gl_update = dbus_scanout_update,
855142ca628SMarc-André Lureau };
856142ca628SMarc-André Lureau #endif
857142ca628SMarc-André Lureau
85899997823SMarc-André Lureau const DisplayChangeListenerOps dbus_dcl_ops = {
859142ca628SMarc-André Lureau .dpy_name = "dbus",
860142ca628SMarc-André Lureau .dpy_gfx_update = dbus_gfx_update,
861142ca628SMarc-André Lureau .dpy_gfx_switch = dbus_gfx_switch,
862142ca628SMarc-André Lureau .dpy_refresh = dbus_refresh,
863142ca628SMarc-André Lureau .dpy_mouse_set = dbus_mouse_set,
864142ca628SMarc-André Lureau .dpy_cursor_define = dbus_cursor_define,
865142ca628SMarc-André Lureau };
866142ca628SMarc-André Lureau
86748dddba1SMarc-André Lureau static void
dbus_display_listener_dispose(GObject * object)86848dddba1SMarc-André Lureau dbus_display_listener_dispose(GObject *object)
86948dddba1SMarc-André Lureau {
87048dddba1SMarc-André Lureau DBusDisplayListener *ddl = DBUS_DISPLAY_LISTENER(object);
87148dddba1SMarc-André Lureau
87248dddba1SMarc-André Lureau unregister_displaychangelistener(&ddl->dcl);
87348dddba1SMarc-André Lureau g_clear_object(&ddl->conn);
87448dddba1SMarc-André Lureau g_clear_pointer(&ddl->bus_name, g_free);
87548dddba1SMarc-André Lureau g_clear_object(&ddl->proxy);
87648dddba1SMarc-André Lureau #ifdef WIN32
87748dddba1SMarc-André Lureau g_clear_object(&ddl->map_proxy);
87848dddba1SMarc-André Lureau g_clear_object(&ddl->d3d11_proxy);
87948dddba1SMarc-André Lureau g_clear_pointer(&ddl->peer_process, CloseHandle);
88048dddba1SMarc-André Lureau #ifdef CONFIG_PIXMAN
88148dddba1SMarc-André Lureau pixman_region32_fini(&ddl->gl_damage);
882de1f8ce0SMarc-André Lureau #endif
883de1f8ce0SMarc-André Lureau #ifdef CONFIG_OPENGL
88448dddba1SMarc-André Lureau egl_fb_destroy(&ddl->fb);
88548dddba1SMarc-André Lureau #endif
88648dddba1SMarc-André Lureau #endif
88748dddba1SMarc-André Lureau
88848dddba1SMarc-André Lureau G_OBJECT_CLASS(dbus_display_listener_parent_class)->dispose(object);
88948dddba1SMarc-André Lureau }
89048dddba1SMarc-André Lureau
89148dddba1SMarc-André Lureau static void
dbus_display_listener_constructed(GObject * object)892de1f8ce0SMarc-André Lureau dbus_display_listener_constructed(GObject *object)
893de1f8ce0SMarc-André Lureau {
89448dddba1SMarc-André Lureau DBusDisplayListener *ddl = DBUS_DISPLAY_LISTENER(object);
89548dddba1SMarc-André Lureau
89648dddba1SMarc-André Lureau ddl->dcl.ops = &dbus_dcl_ops;
89748dddba1SMarc-André Lureau #ifdef CONFIG_OPENGL
89848dddba1SMarc-André Lureau if (display_opengl) {
89948dddba1SMarc-André Lureau ddl->dcl.ops = &dbus_gl_dcl_ops;
900de1f8ce0SMarc-André Lureau }
90148dddba1SMarc-André Lureau #endif
90248dddba1SMarc-André Lureau
90348dddba1SMarc-André Lureau G_OBJECT_CLASS(dbus_display_listener_parent_class)->constructed(object);
90448dddba1SMarc-André Lureau }
90548dddba1SMarc-André Lureau
90648dddba1SMarc-André Lureau static void
dbus_display_listener_class_init(DBusDisplayListenerClass * klass)90748dddba1SMarc-André Lureau dbus_display_listener_class_init(DBusDisplayListenerClass *klass)
908de1f8ce0SMarc-André Lureau {
90948dddba1SMarc-André Lureau GObjectClass *object_class = G_OBJECT_CLASS(klass);
91048dddba1SMarc-André Lureau
91148dddba1SMarc-André Lureau object_class->dispose = dbus_display_listener_dispose;
91248dddba1SMarc-André Lureau object_class->constructed = dbus_display_listener_constructed;
91348dddba1SMarc-André Lureau }
91448dddba1SMarc-André Lureau
915de1f8ce0SMarc-André Lureau static void
dbus_display_listener_init(DBusDisplayListener * ddl)91648dddba1SMarc-André Lureau dbus_display_listener_init(DBusDisplayListener *ddl)
91748dddba1SMarc-André Lureau {
91848dddba1SMarc-André Lureau #ifdef CONFIG_PIXMAN
91948dddba1SMarc-André Lureau pixman_region32_init(&ddl->gl_damage);
92048dddba1SMarc-André Lureau #endif
92148dddba1SMarc-André Lureau }
92248dddba1SMarc-André Lureau
92348dddba1SMarc-André Lureau const char *
dbus_display_listener_get_bus_name(DBusDisplayListener * ddl)92448dddba1SMarc-André Lureau dbus_display_listener_get_bus_name(DBusDisplayListener *ddl)
925de1f8ce0SMarc-André Lureau {
926de1f8ce0SMarc-André Lureau return ddl->bus_name ?: "p2p";
927de1f8ce0SMarc-André Lureau }
928de1f8ce0SMarc-André Lureau
929de1f8ce0SMarc-André Lureau DBusDisplayConsole *
dbus_display_listener_get_console(DBusDisplayListener * ddl)930de1f8ce0SMarc-André Lureau dbus_display_listener_get_console(DBusDisplayListener *ddl)
931de1f8ce0SMarc-André Lureau {
932de1f8ce0SMarc-André Lureau return ddl->console;
933de1f8ce0SMarc-André Lureau }
934de1f8ce0SMarc-André Lureau
935de1f8ce0SMarc-André Lureau static bool
dbus_display_listener_implements(DBusDisplayListener * ddl,const char * iface)936de1f8ce0SMarc-André Lureau dbus_display_listener_implements(DBusDisplayListener *ddl, const char *iface)
937de1f8ce0SMarc-André Lureau {
938de1f8ce0SMarc-André Lureau QemuDBusDisplay1Listener *l = QEMU_DBUS_DISPLAY1_LISTENER(ddl->proxy);
939de1f8ce0SMarc-André Lureau bool implements;
940de1f8ce0SMarc-André Lureau
941de1f8ce0SMarc-André Lureau implements = g_strv_contains(qemu_dbus_display1_listener_get_interfaces(l), iface);
942de1f8ce0SMarc-André Lureau if (!implements) {
943de1f8ce0SMarc-André Lureau g_debug("Display listener does not implement: `%s`", iface);
944de1f8ce0SMarc-André Lureau }
945de1f8ce0SMarc-André Lureau
946de1f8ce0SMarc-André Lureau return implements;
947de1f8ce0SMarc-André Lureau }
948de1f8ce0SMarc-André Lureau
949de1f8ce0SMarc-André Lureau #ifdef WIN32
950de1f8ce0SMarc-André Lureau static bool
dbus_display_listener_setup_peer_process(DBusDisplayListener * ddl)951de1f8ce0SMarc-André Lureau dbus_display_listener_setup_peer_process(DBusDisplayListener *ddl)
952de1f8ce0SMarc-André Lureau {
953de1f8ce0SMarc-André Lureau g_autoptr(GError) err = NULL;
954de1f8ce0SMarc-André Lureau GDBusConnection *conn;
955de1f8ce0SMarc-André Lureau GIOStream *stream;
956de1f8ce0SMarc-André Lureau GSocket *sock;
957de1f8ce0SMarc-André Lureau g_autoptr(GCredentials) creds = NULL;
958de1f8ce0SMarc-André Lureau DWORD *pid;
959de1f8ce0SMarc-André Lureau
960de1f8ce0SMarc-André Lureau if (ddl->peer_process) {
961de1f8ce0SMarc-André Lureau return true;
962de1f8ce0SMarc-André Lureau }
963de1f8ce0SMarc-André Lureau
964de1f8ce0SMarc-André Lureau conn = g_dbus_proxy_get_connection(G_DBUS_PROXY(ddl->proxy));
965de1f8ce0SMarc-André Lureau stream = g_dbus_connection_get_stream(conn);
966de1f8ce0SMarc-André Lureau
967de1f8ce0SMarc-André Lureau if (!G_IS_UNIX_CONNECTION(stream)) {
968de1f8ce0SMarc-André Lureau return false;
969de1f8ce0SMarc-André Lureau }
970de1f8ce0SMarc-André Lureau
971de1f8ce0SMarc-André Lureau sock = g_socket_connection_get_socket(G_SOCKET_CONNECTION(stream));
97248dddba1SMarc-André Lureau creds = g_socket_get_credentials(sock, &err);
97348dddba1SMarc-André Lureau
97448dddba1SMarc-André Lureau if (!creds) {
97548dddba1SMarc-André Lureau g_debug("Failed to get peer credentials: %s", err->message);
976de1f8ce0SMarc-André Lureau return false;
97748dddba1SMarc-André Lureau }
97848dddba1SMarc-André Lureau
97948dddba1SMarc-André Lureau pid = g_credentials_get_native(creds, G_CREDENTIALS_TYPE_WIN32_PID);
98048dddba1SMarc-André Lureau
98148dddba1SMarc-André Lureau if (pid == NULL) {
98248dddba1SMarc-André Lureau g_debug("Failed to get peer PID");
98348dddba1SMarc-André Lureau return false;
98448dddba1SMarc-André Lureau }
98548dddba1SMarc-André Lureau
98648dddba1SMarc-André Lureau ddl->peer_process = OpenProcess(
98748dddba1SMarc-André Lureau PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION,
98848dddba1SMarc-André Lureau false, *pid);
98948dddba1SMarc-André Lureau
99048dddba1SMarc-André Lureau if (!ddl->peer_process) {
991fa88b85dSMarc-André Lureau g_autofree char *msg = g_win32_error_message(GetLastError());
992fa88b85dSMarc-André Lureau g_debug("Failed to OpenProcess: %s", msg);
993fa88b85dSMarc-André Lureau return false;
994fa88b85dSMarc-André Lureau }
995fa88b85dSMarc-André Lureau
996fa88b85dSMarc-André Lureau return true;
997fa88b85dSMarc-André Lureau }
998*01fff506SMarc-André Lureau #endif
999fa88b85dSMarc-André Lureau
1000fa88b85dSMarc-André Lureau static void
dbus_display_listener_setup_d3d11(DBusDisplayListener * ddl)1001fa88b85dSMarc-André Lureau dbus_display_listener_setup_d3d11(DBusDisplayListener *ddl)
1002fa88b85dSMarc-André Lureau {
1003fa88b85dSMarc-André Lureau #ifdef WIN32
1004fa88b85dSMarc-André Lureau g_autoptr(GError) err = NULL;
1005*01fff506SMarc-André Lureau
1006*01fff506SMarc-André Lureau if (!dbus_display_listener_implements(ddl,
1007*01fff506SMarc-André Lureau "org.qemu.Display1.Listener.Win32.D3d11")) {
1008*01fff506SMarc-André Lureau return;
1009*01fff506SMarc-André Lureau }
1010*01fff506SMarc-André Lureau
1011*01fff506SMarc-André Lureau if (!dbus_display_listener_setup_peer_process(ddl)) {
1012*01fff506SMarc-André Lureau return;
1013*01fff506SMarc-André Lureau }
1014*01fff506SMarc-André Lureau
1015*01fff506SMarc-André Lureau ddl->d3d11_proxy =
1016*01fff506SMarc-André Lureau qemu_dbus_display1_listener_win32_d3d11_proxy_new_sync(ddl->conn,
1017*01fff506SMarc-André Lureau G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
1018*01fff506SMarc-André Lureau NULL,
1019*01fff506SMarc-André Lureau "/org/qemu/Display1/Listener",
1020*01fff506SMarc-André Lureau NULL,
1021*01fff506SMarc-André Lureau &err);
1022*01fff506SMarc-André Lureau if (!ddl->d3d11_proxy) {
1023*01fff506SMarc-André Lureau g_debug("Failed to setup win32 d3d11 proxy: %s", err->message);
10249391f419SMarc-André Lureau return;
1025fa88b85dSMarc-André Lureau }
1026fa88b85dSMarc-André Lureau #endif
1027*01fff506SMarc-André Lureau }
1028fa88b85dSMarc-André Lureau
1029fa88b85dSMarc-André Lureau static void
dbus_display_listener_setup_shared_map(DBusDisplayListener * ddl)1030fa88b85dSMarc-André Lureau dbus_display_listener_setup_shared_map(DBusDisplayListener *ddl)
1031fa88b85dSMarc-André Lureau {
1032142ca628SMarc-André Lureau g_autoptr(GError) err = NULL;
1033142ca628SMarc-André Lureau
1034142ca628SMarc-André Lureau #ifdef WIN32
1035142ca628SMarc-André Lureau if (!dbus_display_listener_implements(
1036142ca628SMarc-André Lureau ddl, "org.qemu.Display1.Listener.Win32.Map")) {
1037142ca628SMarc-André Lureau return;
1038142ca628SMarc-André Lureau }
1039142ca628SMarc-André Lureau
1040142ca628SMarc-André Lureau if (!dbus_display_listener_setup_peer_process(ddl)) {
1041142ca628SMarc-André Lureau return;
1042142ca628SMarc-André Lureau }
1043142ca628SMarc-André Lureau
1044142ca628SMarc-André Lureau ddl->map_proxy =
1045142ca628SMarc-André Lureau qemu_dbus_display1_listener_win32_map_proxy_new_sync(ddl->conn,
1046142ca628SMarc-André Lureau G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
1047142ca628SMarc-André Lureau NULL,
1048142ca628SMarc-André Lureau "/org/qemu/Display1/Listener",
1049142ca628SMarc-André Lureau NULL,
1050142ca628SMarc-André Lureau &err);
1051142ca628SMarc-André Lureau if (!ddl->map_proxy) {
1052142ca628SMarc-André Lureau g_debug("Failed to setup win32 map proxy: %s", err->message);
1053142ca628SMarc-André Lureau return;
1054142ca628SMarc-André Lureau }
1055142ca628SMarc-André Lureau
1056fa88b85dSMarc-André Lureau ddl->can_share_map = true;
1057142ca628SMarc-André Lureau #else /* !WIN32 */
1058142ca628SMarc-André Lureau if (!dbus_display_listener_implements(
1059142ca628SMarc-André Lureau ddl, "org.qemu.Display1.Listener.Unix.Map")) {
1060142ca628SMarc-André Lureau return;
106148dddba1SMarc-André Lureau }
1062de1f8ce0SMarc-André Lureau ddl->map_proxy = qemu_dbus_display1_listener_unix_map_proxy_new_sync(
106348dddba1SMarc-André Lureau ddl->conn, G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, NULL,
1064142ca628SMarc-André Lureau "/org/qemu/Display1/Listener", NULL, &err);
1065142ca628SMarc-André Lureau if (!ddl->map_proxy) {
1066142ca628SMarc-André Lureau g_debug("Failed to setup Unix map proxy: %s", err->message);
1067142ca628SMarc-André Lureau return;
1068142ca628SMarc-André Lureau }
1069142ca628SMarc-André Lureau
1070142ca628SMarc-André Lureau ddl->can_share_map = true;
1071 #endif
1072 }
1073
1074 static GDBusMessage *
dbus_filter(GDBusConnection * connection,GDBusMessage * message,gboolean incoming,gpointer user_data)1075 dbus_filter(GDBusConnection *connection,
1076 GDBusMessage *message,
1077 gboolean incoming,
1078 gpointer user_data)
1079 {
1080 DBusDisplayListener *ddl = DBUS_DISPLAY_LISTENER(user_data);
1081 guint32 serial, discard_serial;
1082
1083 if (incoming) {
1084 return message;
1085 }
1086
1087 serial = g_dbus_message_get_serial(message);
1088
1089 discard_serial = g_atomic_int_get(&ddl->display_serial_to_discard);
1090 if (serial <= discard_serial) {
1091 const char *member = g_dbus_message_get_member(message);
1092 static const char *const display_messages[] = {
1093 "Scanout",
1094 "Update",
1095 #ifdef CONFIG_GBM
1096 "ScanoutDMABUF",
1097 "UpdateDMABUF",
1098 #endif
1099 "ScanoutMap",
1100 "UpdateMap",
1101 "Disable",
1102 NULL,
1103 };
1104
1105 if (g_strv_contains(display_messages, member)) {
1106 trace_dbus_filter(serial, discard_serial);
1107 g_object_unref(message);
1108 return NULL;
1109 }
1110 }
1111
1112 discard_serial = g_atomic_int_get(&ddl->cursor_serial_to_discard);
1113 if (serial <= discard_serial) {
1114 const gchar *member = g_dbus_message_get_member(message);
1115 static const char *const cursor_messages[] = {
1116 "CursorDefine",
1117 NULL
1118 };
1119
1120 if (g_strv_contains(cursor_messages, member)) {
1121 trace_dbus_filter(serial, discard_serial);
1122 g_object_unref(message);
1123 return NULL;
1124 }
1125 }
1126
1127 return message;
1128 }
1129
1130 DBusDisplayListener *
dbus_display_listener_new(const char * bus_name,GDBusConnection * conn,DBusDisplayConsole * console)1131 dbus_display_listener_new(const char *bus_name,
1132 GDBusConnection *conn,
1133 DBusDisplayConsole *console)
1134 {
1135 DBusDisplayListener *ddl;
1136 QemuConsole *con;
1137 g_autoptr(GError) err = NULL;
1138
1139 ddl = g_object_new(DBUS_DISPLAY_TYPE_LISTENER, NULL);
1140 ddl->proxy =
1141 qemu_dbus_display1_listener_proxy_new_sync(conn,
1142 G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
1143 NULL,
1144 "/org/qemu/Display1/Listener",
1145 NULL,
1146 &err);
1147 if (!ddl->proxy) {
1148 error_report("Failed to setup proxy: %s", err->message);
1149 g_object_unref(conn);
1150 g_object_unref(ddl);
1151 return NULL;
1152 }
1153
1154 ddl->dbus_filter = g_dbus_connection_add_filter(conn, dbus_filter, g_object_ref(ddl), g_object_unref);
1155 ddl->bus_name = g_strdup(bus_name);
1156 ddl->conn = conn;
1157 ddl->console = console;
1158
1159 dbus_display_listener_setup_shared_map(ddl);
1160 trace_dbus_can_share_map(ddl->can_share_map);
1161 dbus_display_listener_setup_d3d11(ddl);
1162
1163 con = qemu_console_lookup_by_index(dbus_display_console_get_index(console));
1164 assert(con);
1165 ddl->dcl.con = con;
1166 register_displaychangelistener(&ddl->dcl);
1167
1168 return ddl;
1169 }
1170