diff --git a/0001-Add-some-checks-to-ensure-we-properly-bind-server-gl.patch b/0001-Add-some-checks-to-ensure-we-properly-bind-server-gl.patch new file mode 100644 index 0000000..1678328 --- /dev/null +++ b/0001-Add-some-checks-to-ensure-we-properly-bind-server-gl.patch @@ -0,0 +1,76 @@ +From 951ce45d4c229a4f6abea39acd4f7dc759d9ef10 Mon Sep 17 00:00:00 2001 +From: Michael Catanzaro +Date: Fri, 9 Apr 2021 13:10:02 -0500 +Subject: [PATCH 01/13] Add some checks to ensure we properly bind server + globals + +If we fail to bind any global objects, we are going to crash. Let's do +that as nicely as possible using g_error(), rather than dereferencing +null pointers later on. + +Suggested by #145 + +(cherry picked from commit a4eb79d12fc851ea7cef616afa0d77668e83ea61) +--- + src/extensions/audio.cpp | 3 +++ + src/extensions/video-plane-display-dmabuf.cpp | 3 +++ + src/ws-client.cpp | 8 ++++++++ + 3 files changed, 14 insertions(+) + +diff --git a/src/extensions/audio.cpp b/src/extensions/audio.cpp +index b3043ac..5d2dd91 100644 +--- a/src/extensions/audio.cpp ++++ b/src/extensions/audio.cpp +@@ -159,6 +159,9 @@ public: + wl_display_roundtrip_queue(display, eventQueue); + wl_registry_destroy(registry); + ++ if (!m_wl.audio) ++ g_error("Failed to bind wpe_audio"); ++ + wl_event_queue_destroy(eventQueue); + } + +diff --git a/src/extensions/video-plane-display-dmabuf.cpp b/src/extensions/video-plane-display-dmabuf.cpp +index 953cb4c..96fabcf 100644 +--- a/src/extensions/video-plane-display-dmabuf.cpp ++++ b/src/extensions/video-plane-display-dmabuf.cpp +@@ -159,6 +159,9 @@ public: + wl_display_roundtrip_queue(display, eventQueue); + wl_registry_destroy(registry); + ++ if (!m_wl.videoPlaneDisplayDmaBuf) ++ g_error("Failed to bind wpe_video_plane_display_dmabuf"); ++ + wl_event_queue_destroy(eventQueue); + } + +diff --git a/src/ws-client.cpp b/src/ws-client.cpp +index 6dc98ca..4ffa090 100644 +--- a/src/ws-client.cpp ++++ b/src/ws-client.cpp +@@ -126,6 +126,9 @@ BaseBackend::BaseBackend(int hostFD) + wl_display_roundtrip(m_wl.display); + wl_registry_destroy(registry); + ++ if (!m_wl.wpeBridge) ++ g_error("Failed to bind wpe_bridge"); ++ + wpe_bridge_add_listener(m_wl.wpeBridge, &s_bridgeListener, this); + wpe_bridge_initialize(m_wl.wpeBridge); + wl_display_roundtrip(m_wl.display); +@@ -204,6 +207,11 @@ void BaseTarget::initialize(BaseBackend& backend) + wl_display_roundtrip_queue(display, m_wl.eventQueue); + wl_registry_destroy(registry); + ++ if (!m_wl.compositor) ++ g_error("Failed to bind wl_compositor"); ++ if (!m_wl.wpeBridge) ++ g_error("Failed to bind wpe_bridge"); ++ + m_wl.surface = wl_compositor_create_surface(m_wl.compositor); + wl_proxy_set_queue(reinterpret_cast(m_wl.surface), m_wl.eventQueue); + +-- +2.31.1 + diff --git a/0002-ws-Remove-unneeded-Surface-id-member.patch b/0002-ws-Remove-unneeded-Surface-id-member.patch new file mode 100644 index 0000000..4c43b87 --- /dev/null +++ b/0002-ws-Remove-unneeded-Surface-id-member.patch @@ -0,0 +1,63 @@ +From 6963a05959d8be52d4b8ee0cafc49da72a04a6dd Mon Sep 17 00:00:00 2001 +From: Adrian Perez de Castro +Date: Tue, 13 Apr 2021 00:30:08 +0300 +Subject: [PATCH 02/13] ws: Remove unneeded Surface::id member + +The Wayland resource identifier is not used at the moment, and moreover +if ever needed wl_resource_get_id(surface->bufferResource) can be used +to retrieve it. + +(cherry picked from commit 55d05be5529635b7797f34b3e9871612909859fc) +--- + src/ws.cpp | 6 ++---- + src/ws.h | 9 ++++++--- + 2 files changed, 8 insertions(+), 7 deletions(-) + +diff --git a/src/ws.cpp b/src/ws.cpp +index 5602595..c23e53c 100644 +--- a/src/ws.cpp ++++ b/src/ws.cpp +@@ -144,9 +144,7 @@ static const struct wl_compositor_interface s_compositorInterface = { + return; + } + +- auto* surface = new Surface; +- surface->client = client; +- surface->id = id; ++ auto* surface = new Surface {surfaceResource}; + wl_resource_set_implementation(surfaceResource, &s_surfaceInterface, surface, + [](struct wl_resource* resource) + { +@@ -524,7 +522,7 @@ struct wl_client* Instance::registerViewBackend(uint32_t surfaceId, APIClient& a + g_error("Instance::registerViewBackend(): " "Cannot find surface %" PRIu32 " in view backend map.", surfaceId); + + it->second->apiClient = &apiClient; +- return it->second->client; ++ return wl_resource_get_client(it->second->resource); + } + + void Instance::unregisterViewBackend(uint32_t surfaceId) +diff --git a/src/ws.h b/src/ws.h +index d4376c4..683b679 100644 +--- a/src/ws.h ++++ b/src/ws.h +@@ -48,10 +48,13 @@ struct APIClient { + virtual void exportEGLStreamProducer(struct wl_resource*) = 0; + }; + +-struct Surface; + struct Surface { +- uint32_t id { 0 }; +- struct wl_client* client { nullptr }; ++ explicit Surface(struct wl_resource* surfaceResource): ++ resource {surfaceResource} ++ { ++ } ++ ++ struct wl_resource* resource; + + APIClient* apiClient { nullptr }; + +-- +2.31.1 + diff --git a/0003-ws-Rename-surfaceId-to-bridgeId-where-appropriate.patch b/0003-ws-Rename-surfaceId-to-bridgeId-where-appropriate.patch new file mode 100644 index 0000000..1fa9ca3 --- /dev/null +++ b/0003-ws-Rename-surfaceId-to-bridgeId-where-appropriate.patch @@ -0,0 +1,135 @@ +From 2722e7369ae746cc71604bcd13e1f4c6dd5816c3 Mon Sep 17 00:00:00 2001 +From: Adrian Perez de Castro +Date: Tue, 13 Apr 2021 01:06:41 +0300 +Subject: [PATCH 03/13] ws: Rename surfaceId to bridgeId where appropriate + +The fact is that WS::Instance::m_viewBackendMap associated wpe_bridge +identifiers with a Surface, therefore it is clearer when reading the +code to name variables accordingly. + +(cherry picked from commit 2d58520c94cd1c06d940621acaf409480ef908e8) +--- + src/view-backend-private.cpp | 23 +++++++++++------------ + src/view-backend-private.h | 2 +- + src/ws.cpp | 10 +++++----- + src/ws.h | 1 + + 4 files changed, 18 insertions(+), 18 deletions(-) + +diff --git a/src/view-backend-private.cpp b/src/view-backend-private.cpp +index 78f0e2f..367e6c3 100644 +--- a/src/view-backend-private.cpp ++++ b/src/view-backend-private.cpp +@@ -41,7 +41,7 @@ ViewBackend::ViewBackend(ClientBundle* clientBundle, struct wpe_view_backend* ba + + ViewBackend::~ViewBackend() + { +- unregisterSurface(m_surfaceId); ++ unregisterSurface(m_bridgeId); + if (m_clientFd != -1) + close(m_clientFd); + } +@@ -131,29 +131,28 @@ void ViewBackend::clientDestroyNotify(struct wl_listener* listener, void*) + ViewBackend* self = wl_container_of(listener, self, m_clientDestroy); + + self->clearFrameCallbacks(); +- WS::Instance::singleton().unregisterViewBackend(self->m_surfaceId); ++ WS::Instance::singleton().unregisterViewBackend(self->m_bridgeId); + self->m_client = nullptr; +- self->m_surfaceId = 0; ++ self->m_bridgeId = 0; + + wl_list_remove(&self->m_clientDestroy.link); + } + +-void ViewBackend::registerSurface(uint32_t surfaceId) ++void ViewBackend::registerSurface(uint32_t bridgeId) + { +- +- if (m_surfaceId == surfaceId) ++ if (m_bridgeId == bridgeId) + return; + +- unregisterSurface(m_surfaceId); ++ unregisterSurface(m_bridgeId); + +- m_surfaceId = surfaceId; +- m_client = WS::Instance::singleton().registerViewBackend(m_surfaceId, *this); ++ m_bridgeId = bridgeId; ++ m_client = WS::Instance::singleton().registerViewBackend(m_bridgeId, *this); + wl_client_add_destroy_listener(m_client, &m_clientDestroy); + } + +-void ViewBackend::unregisterSurface(uint32_t surfaceId) ++void ViewBackend::unregisterSurface(uint32_t bridgeId) + { +- if (!surfaceId || m_surfaceId != surfaceId) ++ if (!bridgeId || m_bridgeId != bridgeId) + return; + + // If the surfaceId is valid, we cannot have an invalid wl_client. +@@ -165,7 +164,7 @@ void ViewBackend::unregisterSurface(uint32_t surfaceId) + + // After destroying the client, none of these can be valid. + g_assert(m_client == nullptr); +- g_assert(m_surfaceId == 0); ++ g_assert(m_bridgeId == 0); + } + + void ViewBackend::didReceiveMessage(uint32_t messageId, uint32_t messageBody) +diff --git a/src/view-backend-private.h b/src/view-backend-private.h +index 918ec0e..9500262 100644 +--- a/src/view-backend-private.h ++++ b/src/view-backend-private.h +@@ -90,7 +90,7 @@ private: + + static gboolean s_socketCallback(GSocket*, GIOCondition, gpointer); + +- uint32_t m_surfaceId { 0 }; ++ uint32_t m_bridgeId { 0 }; + + static void clientDestroyNotify(struct wl_listener*, void*); + struct wl_listener m_clientDestroy { {}, clientDestroyNotify }; +diff --git a/src/ws.cpp b/src/ws.cpp +index c23e53c..a044b2e 100644 +--- a/src/ws.cpp ++++ b/src/ws.cpp +@@ -515,19 +515,19 @@ void Instance::releaseAudioPacketExport(struct wpe_audio_packet_export* packet_e + wpe_audio_packet_export_send_release(packet_export->exportResource); + } + +-struct wl_client* Instance::registerViewBackend(uint32_t surfaceId, APIClient& apiClient) ++struct wl_client* Instance::registerViewBackend(uint32_t bridgeId, APIClient& apiClient) + { +- auto it = m_viewBackendMap.find(surfaceId); ++ auto it = m_viewBackendMap.find(bridgeId); + if (it == m_viewBackendMap.end()) +- g_error("Instance::registerViewBackend(): " "Cannot find surface %" PRIu32 " in view backend map.", surfaceId); ++ g_error("Instance::registerViewBackend(): " "Cannot find surface with bridgeId %" PRIu32 " in view backend map.", bridgeId); + + it->second->apiClient = &apiClient; + return wl_resource_get_client(it->second->resource); + } + +-void Instance::unregisterViewBackend(uint32_t surfaceId) ++void Instance::unregisterViewBackend(uint32_t bridgeId) + { +- auto it = m_viewBackendMap.find(surfaceId); ++ auto it = m_viewBackendMap.find(bridgeId); + if (it != m_viewBackendMap.end()) { + it->second->apiClient = nullptr; + m_viewBackendMap.erase(it); +diff --git a/src/ws.h b/src/ws.h +index 683b679..aa0c083 100644 +--- a/src/ws.h ++++ b/src/ws.h +@@ -128,6 +128,7 @@ private: + struct wl_global* m_wpeBridge { nullptr }; + GSource* m_source { nullptr }; + ++ // (bridgeId -> Surface) + std::unordered_map m_viewBackendMap; + + struct { +-- +2.31.1 + diff --git a/0004-ws-Accumulate-surface-frame-callbacks-until-commit.patch b/0004-ws-Accumulate-surface-frame-callbacks-until-commit.patch new file mode 100644 index 0000000..efe34bf --- /dev/null +++ b/0004-ws-Accumulate-surface-frame-callbacks-until-commit.patch @@ -0,0 +1,262 @@ +From 98ad602e5f5d51162ec715a023b87d06a71d627b Mon Sep 17 00:00:00 2001 +From: Adrian Perez de Castro +Date: Thu, 8 Apr 2021 00:57:49 +0300 +Subject: [PATCH 04/13] ws: Accumulate surface frame callbacks until commit + +Move code around to accumulate surface frame callback additions until +changes are comitted to the surface, as intended according to the base +Wayland protocol specification. + +As a bonus, remove the auxiliar ViewBackend::FrameCallbackResource +by passing a destruction callback to wl_resource_set_implementation() +and using the internal wl_resource list link. + +(cherry picked from commit 3ab4a3c9770d333ebbc65ab42a604836c6da57ec) +--- + src/view-backend-private.cpp | 45 ++---------------------------------- + src/view-backend-private.h | 14 ----------- + src/ws.cpp | 19 +++++++++++++-- + src/ws.h | 39 ++++++++++++++++++++++++++++++- + 4 files changed, 57 insertions(+), 60 deletions(-) + +diff --git a/src/view-backend-private.cpp b/src/view-backend-private.cpp +index 367e6c3..f04a57e 100644 +--- a/src/view-backend-private.cpp ++++ b/src/view-backend-private.cpp +@@ -35,7 +35,6 @@ ViewBackend::ViewBackend(ClientBundle* clientBundle, struct wpe_view_backend* ba + { + m_clientBundle->viewBackend = this; + +- wl_list_init(&m_frameCallbacks); + wl_list_init(&m_clientDestroy.link); + } + +@@ -72,15 +71,6 @@ int ViewBackend::clientFd() + return dup(m_clientFd); + } + +-void ViewBackend::frameCallback(struct wl_resource* callback) +-{ +- auto* resource = new FrameCallbackResource; +- resource->resource = callback; +- resource->destroyListener.notify = FrameCallbackResource::destroyNotify; +- wl_resource_add_destroy_listener(callback, &resource->destroyListener); +- wl_list_insert(&m_frameCallbacks, &resource->link); +-} +- + void ViewBackend::exportBufferResource(struct wl_resource* bufferResource) + { + m_clientBundle->exportBuffer(bufferResource); +@@ -103,16 +93,8 @@ void ViewBackend::exportEGLStreamProducer(struct wl_resource* bufferResource) + + void ViewBackend::dispatchFrameCallbacks() + { +- if (G_UNLIKELY(!m_client)) +- return; +- +- FrameCallbackResource* resource; +- wl_list_for_each(resource, &m_frameCallbacks, link) { +- wl_callback_send_done(resource->resource, 0); +- } +- clearFrameCallbacks(); +- +- wl_client_flush(m_client); ++ if (G_LIKELY(m_bridgeId)) ++ WS::Instance::singleton().dispatchFrameCallbacks(m_bridgeId); + + wpe_view_backend_dispatch_frame_displayed(m_backend); + } +@@ -130,7 +112,6 @@ void ViewBackend::clientDestroyNotify(struct wl_listener* listener, void*) + { + ViewBackend* self = wl_container_of(listener, self, m_clientDestroy); + +- self->clearFrameCallbacks(); + WS::Instance::singleton().unregisterViewBackend(self->m_bridgeId); + self->m_client = nullptr; + self->m_bridgeId = 0; +@@ -180,25 +161,3 @@ void ViewBackend::didReceiveMessage(uint32_t messageId, uint32_t messageBody) + assert(!"WPE fdo received an invalid IPC message"); + } + } +- +-void ViewBackend::clearFrameCallbacks() +-{ +- FrameCallbackResource* resource; +- FrameCallbackResource* next; +- wl_list_for_each_safe(resource, next, &m_frameCallbacks, link) { +- wl_list_remove(&resource->link); +- wl_list_remove(&resource->destroyListener.link); +- wl_resource_destroy(resource->resource); +- delete resource; +- } +- wl_list_init(&m_frameCallbacks); +-} +- +-void ViewBackend::FrameCallbackResource::destroyNotify(struct wl_listener* listener, void*) +-{ +- FrameCallbackResource* resource; +- resource = wl_container_of(listener, resource, destroyListener); +- +- wl_list_remove(&resource->link); +- delete resource; +-} +diff --git a/src/view-backend-private.h b/src/view-backend-private.h +index 9500262..a598dee 100644 +--- a/src/view-backend-private.h ++++ b/src/view-backend-private.h +@@ -63,7 +63,6 @@ public: + + void initialize(); + int clientFd(); +- void frameCallback(struct wl_resource* callbackResource) override; + void exportBufferResource(struct wl_resource* bufferResource) override; + void exportLinuxDmabuf(const struct linux_dmabuf_buffer *dmabuf_buffer) override; + void exportShmBuffer(struct wl_resource* bufferResource, struct wl_shm_buffer* shmBuffer) override; +@@ -72,22 +71,11 @@ public: + void releaseBuffer(struct wl_resource* buffer_resource); + + private: +- struct FrameCallbackResource { +- struct wl_resource* resource; +- +- struct wl_list link; +- struct wl_listener destroyListener; +- +- static void destroyNotify(struct wl_listener*, void*); +- }; +- + void didReceiveMessage(uint32_t messageId, uint32_t messageBody) override; + + void registerSurface(uint32_t); + void unregisterSurface(uint32_t); + +- void clearFrameCallbacks(); +- + static gboolean s_socketCallback(GSocket*, GIOCondition, gpointer); + + uint32_t m_bridgeId { 0 }; +@@ -99,8 +87,6 @@ private: + ClientBundle* m_clientBundle; + struct wpe_view_backend* m_backend; + +- struct wl_list m_frameCallbacks; +- + std::unique_ptr m_socket; + int m_clientFd { -1 }; + }; +diff --git a/src/ws.cpp b/src/ws.cpp +index a044b2e..87faaf3 100644 +--- a/src/ws.cpp ++++ b/src/ws.cpp +@@ -110,8 +110,11 @@ static const struct wl_surface_interface s_surfaceInterface = { + return; + } + +- wl_resource_set_implementation(callbackResource, nullptr, nullptr, nullptr); +- surface.apiClient->frameCallback(callbackResource); ++ wl_resource_set_implementation(callbackResource, nullptr, nullptr, ++ [](struct wl_resource* resource) { ++ wl_list_remove(wl_resource_get_link(resource)); ++ }); ++ surface.addFrameCallback(callbackResource); + }, + // set_opaque_region + [](struct wl_client*, struct wl_resource*, struct wl_resource*) { }, +@@ -121,6 +124,7 @@ static const struct wl_surface_interface s_surfaceInterface = { + [](struct wl_client*, struct wl_resource* surfaceResource) + { + auto& surface = *static_cast(wl_resource_get_user_data(surfaceResource)); ++ surface.commit(); + WS::Instance::singleton().impl().surfaceCommit(surface); + }, + // set_buffer_transform +@@ -534,4 +538,15 @@ void Instance::unregisterViewBackend(uint32_t bridgeId) + } + } + ++void Instance::dispatchFrameCallbacks(uint32_t bridgeId) ++{ ++ auto it = m_viewBackendMap.find(bridgeId); ++ if (it == m_viewBackendMap.end()) { ++ g_error("Instance::dispatchFrameCallbacks(): " ++ "Cannot find surface with bridgeId %" PRIu32 " in view backend map.", bridgeId); ++ } ++ ++ it->second->dispatchFrameCallbacks(); ++} ++ + } // namespace WS +diff --git a/src/ws.h b/src/ws.h +index aa0c083..30baf8e 100644 +--- a/src/ws.h ++++ b/src/ws.h +@@ -41,7 +41,6 @@ namespace WS { + struct APIClient { + virtual ~APIClient() = default; + +- virtual void frameCallback(struct wl_resource*) = 0; + virtual void exportBufferResource(struct wl_resource*) = 0; + virtual void exportLinuxDmabuf(const struct linux_dmabuf_buffer *dmabuf_buffer) = 0; + virtual void exportShmBuffer(struct wl_resource*, struct wl_shm_buffer*) = 0; +@@ -52,6 +51,18 @@ struct Surface { + explicit Surface(struct wl_resource* surfaceResource): + resource {surfaceResource} + { ++ wl_list_init(&m_pendingFrameCallbacks); ++ wl_list_init(&m_currentFrameCallbacks); ++ } ++ ++ ~Surface() ++ { ++ struct wl_resource* resource; ++ struct wl_resource* tmp; ++ wl_resource_for_each_safe(resource, tmp, &m_pendingFrameCallbacks) ++ wl_resource_destroy(resource); ++ wl_resource_for_each_safe(resource, tmp, &m_currentFrameCallbacks) ++ wl_resource_destroy(resource); + } + + struct wl_resource* resource; +@@ -61,6 +72,31 @@ struct Surface { + struct wl_resource* bufferResource { nullptr }; + const struct linux_dmabuf_buffer* dmabufBuffer { nullptr }; + struct wl_shm_buffer* shmBuffer { nullptr }; ++ ++ void commit() ++ { ++ wl_list_insert_list(&m_currentFrameCallbacks, &m_pendingFrameCallbacks); ++ wl_list_init(&m_pendingFrameCallbacks); ++ } ++ ++ void addFrameCallback(struct wl_resource* resource) ++ { ++ wl_list_insert(m_pendingFrameCallbacks.prev, wl_resource_get_link(resource)); ++ } ++ ++ void dispatchFrameCallbacks() ++ { ++ struct wl_resource* resource; ++ struct wl_resource* tmp; ++ wl_resource_for_each_safe(resource, tmp, &m_currentFrameCallbacks) { ++ wl_callback_send_done(resource, 0); ++ wl_resource_destroy(resource); ++ } ++ } ++ ++private: ++ struct wl_list m_pendingFrameCallbacks; ++ struct wl_list m_currentFrameCallbacks; + }; + + class Instance { +@@ -95,6 +131,7 @@ public: + void registerSurface(uint32_t, Surface*); + struct wl_client* registerViewBackend(uint32_t, APIClient&); + void unregisterViewBackend(uint32_t); ++ void dispatchFrameCallbacks(uint32_t); + + using VideoPlaneDisplayDmaBufCallback = std::function; + using VideoPlaneDisplayDmaBufEndOfStreamCallback = std::function; +-- +2.31.1 + diff --git a/0006-meson-Make-scripts-version.py-work-with-older-Python.patch b/0006-meson-Make-scripts-version.py-work-with-older-Python.patch new file mode 100644 index 0000000..be46355 --- /dev/null +++ b/0006-meson-Make-scripts-version.py-work-with-older-Python.patch @@ -0,0 +1,29 @@ +From 89e4b1683ad51c1b066fc10c748e5d524fb37cd2 Mon Sep 17 00:00:00 2001 +From: Adrian Perez de Castro +Date: Wed, 14 Apr 2021 21:56:12 +0300 +Subject: [PATCH 06/13] meson: Make scripts/version.py work with older Pythons + +Older Python versions (3.5, 2.x) do not have a __getitem__ method +on regex match objects, so use the .group() method instead, which is +available in all versions. + +(cherry picked from commit 8c4b29f973500a9a596e27a2b3042923e4c905f7) +--- + scripts/version.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/scripts/version.py b/scripts/version.py +index 1dbbdb3..e2af013 100644 +--- a/scripts/version.py ++++ b/scripts/version.py +@@ -18,6 +18,6 @@ with open(version_file, "r") as f: + for line in f.readlines(): + m = version_re.match(line) + if m: +- version[m[1]] = m[2] ++ version[m.group(1)] = m.group(2) + + print("{}.{}.{}".format(version["MAJOR"], version["MINOR"], version["MICRO"])) +-- +2.31.1 + diff --git a/0007-Revert-view-backend-Properly-unregister-surfaces.patch b/0007-Revert-view-backend-Properly-unregister-surfaces.patch new file mode 100644 index 0000000..348fa09 --- /dev/null +++ b/0007-Revert-view-backend-Properly-unregister-surfaces.patch @@ -0,0 +1,132 @@ +From 4657edaf9f798863d16d94e61a3f467ee656e908 Mon Sep 17 00:00:00 2001 +From: Adrian Perez de Castro +Date: Sat, 10 Apr 2021 18:27:42 +0300 +Subject: [PATCH 07/13] Revert "view backend: Properly unregister surfaces" + +This reverts commit 99bd04019800f84a722ae99bf1a352f225d93002. +--- + src/view-backend-private.cpp | 52 +++++++++++++----------------------- + src/view-backend-private.h | 8 +++--- + 2 files changed, 24 insertions(+), 36 deletions(-) + +diff --git a/src/view-backend-private.cpp b/src/view-backend-private.cpp +index f04a57e..4920037 100644 +--- a/src/view-backend-private.cpp ++++ b/src/view-backend-private.cpp +@@ -34,13 +34,12 @@ ViewBackend::ViewBackend(ClientBundle* clientBundle, struct wpe_view_backend* ba + , m_backend(backend) + { + m_clientBundle->viewBackend = this; +- +- wl_list_init(&m_clientDestroy.link); + } + + ViewBackend::~ViewBackend() + { + unregisterSurface(m_bridgeId); ++ + if (m_clientFd != -1) + close(m_clientFd); + } +@@ -96,39 +95,24 @@ void ViewBackend::dispatchFrameCallbacks() + if (G_LIKELY(m_bridgeId)) + WS::Instance::singleton().dispatchFrameCallbacks(m_bridgeId); + ++ if (m_client.object) ++ wl_client_flush(m_client.object); + wpe_view_backend_dispatch_frame_displayed(m_backend); + } + + void ViewBackend::releaseBuffer(struct wl_resource* buffer_resource) + { +- if (G_UNLIKELY(!m_client)) +- return; +- + wl_buffer_send_release(buffer_resource); +- wl_client_flush(m_client); +-} +- +-void ViewBackend::clientDestroyNotify(struct wl_listener* listener, void*) +-{ +- ViewBackend* self = wl_container_of(listener, self, m_clientDestroy); +- +- WS::Instance::singleton().unregisterViewBackend(self->m_bridgeId); +- self->m_client = nullptr; +- self->m_bridgeId = 0; +- +- wl_list_remove(&self->m_clientDestroy.link); ++ if (m_client.object) ++ wl_client_flush(m_client.object); + } + + void ViewBackend::registerSurface(uint32_t bridgeId) + { +- if (m_bridgeId == bridgeId) +- return; +- +- unregisterSurface(m_bridgeId); +- + m_bridgeId = bridgeId; +- m_client = WS::Instance::singleton().registerViewBackend(m_bridgeId, *this); +- wl_client_add_destroy_listener(m_client, &m_clientDestroy); ++ m_client.object = WS::Instance::singleton().registerViewBackend(m_bridgeId, *this); ++ m_client.destroyListener.notify = Client::destroyNotify; ++ wl_client_add_destroy_listener(m_client.object, &m_client.destroyListener); + } + + void ViewBackend::unregisterSurface(uint32_t bridgeId) +@@ -136,16 +120,10 @@ void ViewBackend::unregisterSurface(uint32_t bridgeId) + if (!bridgeId || m_bridgeId != bridgeId) + return; + +- // If the surfaceId is valid, we cannot have an invalid wl_client. +- g_assert(m_client != nullptr); +- +- // Destroying the client triggers the m_clientDestroy callback, +- // the rest of the teardown is done from there. +- wl_client_destroy(m_client); ++ g_clear_pointer(&m_client.object, wl_client_destroy); + +- // After destroying the client, none of these can be valid. +- g_assert(m_client == nullptr); +- g_assert(m_bridgeId == 0); ++ WS::Instance::singleton().unregisterViewBackend(m_bridgeId); ++ m_bridgeId = 0; + } + + void ViewBackend::didReceiveMessage(uint32_t messageId, uint32_t messageBody) +@@ -161,3 +139,11 @@ void ViewBackend::didReceiveMessage(uint32_t messageId, uint32_t messageBody) + assert(!"WPE fdo received an invalid IPC message"); + } + } ++ ++void ViewBackend::Client::destroyNotify(struct wl_listener* listener, void*) ++{ ++ Client* client; ++ client = wl_container_of(listener, client, destroyListener); ++ ++ client->object = nullptr; ++} +diff --git a/src/view-backend-private.h b/src/view-backend-private.h +index a598dee..37eab08 100644 +--- a/src/view-backend-private.h ++++ b/src/view-backend-private.h +@@ -79,10 +79,12 @@ private: + static gboolean s_socketCallback(GSocket*, GIOCondition, gpointer); + + uint32_t m_bridgeId { 0 }; ++ struct Client { ++ struct wl_client* object { nullptr }; ++ struct wl_listener destroyListener; + +- static void clientDestroyNotify(struct wl_listener*, void*); +- struct wl_listener m_clientDestroy { {}, clientDestroyNotify }; +- struct wl_client* m_client { nullptr }; ++ static void destroyNotify(struct wl_listener*, void*); ++ } m_client; + + ClientBundle* m_clientBundle; + struct wpe_view_backend* m_backend; +-- +2.31.1 + diff --git a/0008-Revert-view-backend-private-Move-wl_client_destroy-t.patch b/0008-Revert-view-backend-private-Move-wl_client_destroy-t.patch new file mode 100644 index 0000000..0e457fb --- /dev/null +++ b/0008-Revert-view-backend-private-Move-wl_client_destroy-t.patch @@ -0,0 +1,40 @@ +From 00a6f6d61cb20af45714360bf458348aeaf08751 Mon Sep 17 00:00:00 2001 +From: Adrian Perez de Castro +Date: Sat, 10 Apr 2021 18:27:55 +0300 +Subject: [PATCH 08/13] Revert "view-backend-private: Move wl_client_destroy to + unregisterSurface()" + +This reverts commit f54135e65a6894bdf509153d2f6e96a627352306. +--- + src/view-backend-private.cpp | 2 -- + src/ws.cpp | 1 + + 2 files changed, 1 insertion(+), 2 deletions(-) + +diff --git a/src/view-backend-private.cpp b/src/view-backend-private.cpp +index 4920037..e1554bb 100644 +--- a/src/view-backend-private.cpp ++++ b/src/view-backend-private.cpp +@@ -120,8 +120,6 @@ void ViewBackend::unregisterSurface(uint32_t bridgeId) + if (!bridgeId || m_bridgeId != bridgeId) + return; + +- g_clear_pointer(&m_client.object, wl_client_destroy); +- + WS::Instance::singleton().unregisterViewBackend(m_bridgeId); + m_bridgeId = 0; + } +diff --git a/src/ws.cpp b/src/ws.cpp +index 87faaf3..80cb39b 100644 +--- a/src/ws.cpp ++++ b/src/ws.cpp +@@ -534,6 +534,7 @@ void Instance::unregisterViewBackend(uint32_t bridgeId) + auto it = m_viewBackendMap.find(bridgeId); + if (it != m_viewBackendMap.end()) { + it->second->apiClient = nullptr; ++ wl_client_destroy(wl_resource_get_client(it->second->resource)); + m_viewBackendMap.erase(it); + } + } +-- +2.31.1 + diff --git a/0009-Revert-ws-Call-wl_client_destroy-for-the-created-wl_.patch b/0009-Revert-ws-Call-wl_client_destroy-for-the-created-wl_.patch new file mode 100644 index 0000000..53d9982 --- /dev/null +++ b/0009-Revert-ws-Call-wl_client_destroy-for-the-created-wl_.patch @@ -0,0 +1,26 @@ +From 542587bae6b894bdd1a5cfd38223f8054d166fc3 Mon Sep 17 00:00:00 2001 +From: Adrian Perez de Castro +Date: Sat, 10 Apr 2021 18:28:43 +0300 +Subject: [PATCH 09/13] Revert "ws: Call wl_client_destroy for the created + wl_client in Instance::unregisterViewBackend()" + +This reverts commit 9a0e6cb62bfae44ef3496d950899ecb34ddd24a5. +--- + src/ws.cpp | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/ws.cpp b/src/ws.cpp +index 80cb39b..87faaf3 100644 +--- a/src/ws.cpp ++++ b/src/ws.cpp +@@ -534,7 +534,6 @@ void Instance::unregisterViewBackend(uint32_t bridgeId) + auto it = m_viewBackendMap.find(bridgeId); + if (it != m_viewBackendMap.end()) { + it->second->apiClient = nullptr; +- wl_client_destroy(wl_resource_get_client(it->second->resource)); + m_viewBackendMap.erase(it); + } + } +-- +2.31.1 + diff --git a/0010-Revert-Cleanups.patch b/0010-Revert-Cleanups.patch new file mode 100644 index 0000000..4662e52 --- /dev/null +++ b/0010-Revert-Cleanups.patch @@ -0,0 +1,101 @@ +From 18244c702bba27d32a022bd8a2ff9269fcb18cc5 Mon Sep 17 00:00:00 2001 +From: Adrian Perez de Castro +Date: Sat, 10 Apr 2021 18:29:05 +0300 +Subject: [PATCH 10/13] Revert "Cleanups." + +This reverts commit 9e7dfbe7cbca8bc59c81d1e6421a527a87796880. +--- + src/view-backend-private.cpp | 31 ++++++++++++++++--------------- + src/view-backend-private.h | 12 ++++++------ + 2 files changed, 22 insertions(+), 21 deletions(-) + +diff --git a/src/view-backend-private.cpp b/src/view-backend-private.cpp +index e1554bb..6ba3fcb 100644 +--- a/src/view-backend-private.cpp ++++ b/src/view-backend-private.cpp +@@ -95,24 +95,33 @@ void ViewBackend::dispatchFrameCallbacks() + if (G_LIKELY(m_bridgeId)) + WS::Instance::singleton().dispatchFrameCallbacks(m_bridgeId); + +- if (m_client.object) +- wl_client_flush(m_client.object); ++ if (m_client) ++ wl_client_flush(m_client); + wpe_view_backend_dispatch_frame_displayed(m_backend); + } + + void ViewBackend::releaseBuffer(struct wl_resource* buffer_resource) + { + wl_buffer_send_release(buffer_resource); +- if (m_client.object) +- wl_client_flush(m_client.object); ++ if (m_client) ++ wl_client_flush(m_client); + } + + void ViewBackend::registerSurface(uint32_t bridgeId) + { + m_bridgeId = bridgeId; +- m_client.object = WS::Instance::singleton().registerViewBackend(m_bridgeId, *this); +- m_client.destroyListener.notify = Client::destroyNotify; +- wl_client_add_destroy_listener(m_client.object, &m_client.destroyListener); ++ m_client = WS::Instance::singleton().registerViewBackend(m_bridgeId, *this); ++ ++ struct wl_client_destroy_listener *listener = new wl_client_destroy_listener {this, }; ++ listener->destroyClientListener.notify = (wl_notify_func_t) [](struct wl_listener* listener, void* data) ++ { ++ struct wl_client_destroy_listener *container; ++ container = wl_container_of(listener, container, destroyClientListener); ++ container->backend->m_client = NULL; ++ delete container; // Release the wl_client_destroy_listener instance since this is not longer needed. ++ }; ++ wl_client_add_destroy_listener(m_client, ++ &listener->destroyClientListener); + } + + void ViewBackend::unregisterSurface(uint32_t bridgeId) +@@ -137,11 +146,3 @@ void ViewBackend::didReceiveMessage(uint32_t messageId, uint32_t messageBody) + assert(!"WPE fdo received an invalid IPC message"); + } + } +- +-void ViewBackend::Client::destroyNotify(struct wl_listener* listener, void*) +-{ +- Client* client; +- client = wl_container_of(listener, client, destroyListener); +- +- client->object = nullptr; +-} +diff --git a/src/view-backend-private.h b/src/view-backend-private.h +index 37eab08..81b083c 100644 +--- a/src/view-backend-private.h ++++ b/src/view-backend-private.h +@@ -79,12 +79,7 @@ private: + static gboolean s_socketCallback(GSocket*, GIOCondition, gpointer); + + uint32_t m_bridgeId { 0 }; +- struct Client { +- struct wl_client* object { nullptr }; +- struct wl_listener destroyListener; +- +- static void destroyNotify(struct wl_listener*, void*); +- } m_client; ++ struct wl_client* m_client { nullptr }; + + ClientBundle* m_clientBundle; + struct wpe_view_backend* m_backend; +@@ -93,6 +88,11 @@ private: + int m_clientFd { -1 }; + }; + ++struct wl_client_destroy_listener { ++ ViewBackend* backend; ++ struct wl_listener destroyClientListener; ++}; ++ + struct wpe_view_backend_private { + wpe_view_backend_private(std::unique_ptr&& clientBundle, struct wpe_view_backend* backend) + : clientBundle(std::move(clientBundle)) +-- +2.31.1 + diff --git a/0011-Revert-view-backend-exportable-private-Move-ViewBack.patch b/0011-Revert-view-backend-exportable-private-Move-ViewBack.patch new file mode 100644 index 0000000..6527853 --- /dev/null +++ b/0011-Revert-view-backend-exportable-private-Move-ViewBack.patch @@ -0,0 +1,60 @@ +From 862764947c6a62e27371d0b31660ff41cd70b674 Mon Sep 17 00:00:00 2001 +From: Adrian Perez de Castro +Date: Sat, 10 Apr 2021 18:29:13 +0300 +Subject: [PATCH 11/13] Revert "view-backend-exportable-private: Move + ViewBackend::m_destroyClientListener" + +This reverts commit d7577891d505a3fb037ec14e54568fe59e310941. +--- + src/view-backend-private.cpp | 14 +++++++------- + src/view-backend-private.h | 6 +----- + 2 files changed, 8 insertions(+), 12 deletions(-) + +diff --git a/src/view-backend-private.cpp b/src/view-backend-private.cpp +index 6ba3fcb..af5472f 100644 +--- a/src/view-backend-private.cpp ++++ b/src/view-backend-private.cpp +@@ -112,16 +112,16 @@ void ViewBackend::registerSurface(uint32_t bridgeId) + m_bridgeId = bridgeId; + m_client = WS::Instance::singleton().registerViewBackend(m_bridgeId, *this); + +- struct wl_client_destroy_listener *listener = new wl_client_destroy_listener {this, }; +- listener->destroyClientListener.notify = (wl_notify_func_t) [](struct wl_listener* listener, void* data) ++ this->m_destroyClientListener.notify = (wl_notify_func_t) [](struct wl_listener* listener, void* data) + { +- struct wl_client_destroy_listener *container; +- container = wl_container_of(listener, container, destroyClientListener); +- container->backend->m_client = NULL; +- delete container; // Release the wl_client_destroy_listener instance since this is not longer needed. ++ ViewBackend *viewBackend = wl_container_of(listener, viewBackend, m_destroyClientListener); ++ ++ struct wl_client* client = (struct wl_client*) data; ++ g_debug("ViewBackend <%p>: wl_client <%p> destroy notification for fd %d", viewBackend, data, wl_client_get_fd(client)); ++ viewBackend->m_client = NULL; + }; + wl_client_add_destroy_listener(m_client, +- &listener->destroyClientListener); ++ &this->m_destroyClientListener); + } + + void ViewBackend::unregisterSurface(uint32_t bridgeId) +diff --git a/src/view-backend-private.h b/src/view-backend-private.h +index 81b083c..599382b 100644 +--- a/src/view-backend-private.h ++++ b/src/view-backend-private.h +@@ -86,11 +86,7 @@ private: + + std::unique_ptr m_socket; + int m_clientFd { -1 }; +-}; +- +-struct wl_client_destroy_listener { +- ViewBackend* backend; +- struct wl_listener destroyClientListener; ++ struct wl_listener m_destroyClientListener; + }; + + struct wpe_view_backend_private { +-- +2.31.1 + diff --git a/0012-Revert-view-backend-exportable-private-Add-wl_client.patch b/0012-Revert-view-backend-exportable-private-Add-wl_client.patch new file mode 100644 index 0000000..e3b90dd --- /dev/null +++ b/0012-Revert-view-backend-exportable-private-Add-wl_client.patch @@ -0,0 +1,67 @@ +From 229b2601804049d94f09006e8c4a542c78158ab9 Mon Sep 17 00:00:00 2001 +From: Adrian Perez de Castro +Date: Sat, 10 Apr 2021 18:29:24 +0300 +Subject: [PATCH 12/13] Revert "view-backend-exportable-private: Add + wl_client_add_destroy_listener in the ViewBackend" + +This reverts commit d688cd2558807c1ed15d67e5b0ecfad52a2bf90b. +--- + src/view-backend-private.cpp | 17 ++--------------- + src/view-backend-private.h | 1 - + 2 files changed, 2 insertions(+), 16 deletions(-) + +diff --git a/src/view-backend-private.cpp b/src/view-backend-private.cpp +index af5472f..b78831d 100644 +--- a/src/view-backend-private.cpp ++++ b/src/view-backend-private.cpp +@@ -95,33 +95,20 @@ void ViewBackend::dispatchFrameCallbacks() + if (G_LIKELY(m_bridgeId)) + WS::Instance::singleton().dispatchFrameCallbacks(m_bridgeId); + +- if (m_client) +- wl_client_flush(m_client); ++ wl_client_flush(m_client); + wpe_view_backend_dispatch_frame_displayed(m_backend); + } + + void ViewBackend::releaseBuffer(struct wl_resource* buffer_resource) + { + wl_buffer_send_release(buffer_resource); +- if (m_client) +- wl_client_flush(m_client); ++ wl_client_flush(m_client); + } + + void ViewBackend::registerSurface(uint32_t bridgeId) + { + m_bridgeId = bridgeId; + m_client = WS::Instance::singleton().registerViewBackend(m_bridgeId, *this); +- +- this->m_destroyClientListener.notify = (wl_notify_func_t) [](struct wl_listener* listener, void* data) +- { +- ViewBackend *viewBackend = wl_container_of(listener, viewBackend, m_destroyClientListener); +- +- struct wl_client* client = (struct wl_client*) data; +- g_debug("ViewBackend <%p>: wl_client <%p> destroy notification for fd %d", viewBackend, data, wl_client_get_fd(client)); +- viewBackend->m_client = NULL; +- }; +- wl_client_add_destroy_listener(m_client, +- &this->m_destroyClientListener); + } + + void ViewBackend::unregisterSurface(uint32_t bridgeId) +diff --git a/src/view-backend-private.h b/src/view-backend-private.h +index 599382b..15e98e6 100644 +--- a/src/view-backend-private.h ++++ b/src/view-backend-private.h +@@ -86,7 +86,6 @@ private: + + std::unique_ptr m_socket; + int m_clientFd { -1 }; +- struct wl_listener m_destroyClientListener; + }; + + struct wpe_view_backend_private { +-- +2.31.1 + diff --git a/0013-ws-Remove-wl_client-pointer-that-can-end-up-dangling.patch b/0013-ws-Remove-wl_client-pointer-that-can-end-up-dangling.patch new file mode 100644 index 0000000..ce09b36 --- /dev/null +++ b/0013-ws-Remove-wl_client-pointer-that-can-end-up-dangling.patch @@ -0,0 +1,122 @@ +From 328397f4f4d0e6a3608f6fd8c3ec0abdd5763135 Mon Sep 17 00:00:00 2001 +From: Adrian Perez de Castro +Date: Wed, 14 Apr 2021 15:55:59 +0300 +Subject: [PATCH 13/13] ws: Remove wl_client pointer that can end up dangling + +Instead of trying to keep track of the destruction of the wl_client +references from ViewBackend::m_client, completely remove the member +variable and instead: + +- In ViewBackend::releaseBuffer() use wl_resource_get_client() to obtain + the wl_client from the buffer resource. Given that the buffer resource + has just been used, it is guaranteed that the wl_client it refers to + should be still valid. + +- In ViewBackend::dispatchFrameCallbacks() remove the flush call, and + instead do it in WS::Surface::dispatchFrameCallbacks(), and pick the + wl_client from the callback resource objects, if any callback was + dispatched at all. Again, if any callback was dispatched their + associated wl_client should be still valid. Skipping the flush if + no callbacks are dispatched is fine because in that case there would + not be any messages pending be sent over the wire anyway to trigger + dispatching the callbacks in the client side. +--- + src/view-backend-private.cpp | 5 ++--- + src/view-backend-private.h | 1 - + src/ws.cpp | 3 +-- + src/ws.h | 9 ++++++++- + 4 files changed, 11 insertions(+), 7 deletions(-) + +diff --git a/src/view-backend-private.cpp b/src/view-backend-private.cpp +index b78831d..7e3a738 100644 +--- a/src/view-backend-private.cpp ++++ b/src/view-backend-private.cpp +@@ -95,20 +95,19 @@ void ViewBackend::dispatchFrameCallbacks() + if (G_LIKELY(m_bridgeId)) + WS::Instance::singleton().dispatchFrameCallbacks(m_bridgeId); + +- wl_client_flush(m_client); + wpe_view_backend_dispatch_frame_displayed(m_backend); + } + + void ViewBackend::releaseBuffer(struct wl_resource* buffer_resource) + { + wl_buffer_send_release(buffer_resource); +- wl_client_flush(m_client); ++ wl_client_flush(wl_resource_get_client(buffer_resource)); + } + + void ViewBackend::registerSurface(uint32_t bridgeId) + { + m_bridgeId = bridgeId; +- m_client = WS::Instance::singleton().registerViewBackend(m_bridgeId, *this); ++ WS::Instance::singleton().registerViewBackend(m_bridgeId, *this); + } + + void ViewBackend::unregisterSurface(uint32_t bridgeId) +diff --git a/src/view-backend-private.h b/src/view-backend-private.h +index 15e98e6..363b787 100644 +--- a/src/view-backend-private.h ++++ b/src/view-backend-private.h +@@ -79,7 +79,6 @@ private: + static gboolean s_socketCallback(GSocket*, GIOCondition, gpointer); + + uint32_t m_bridgeId { 0 }; +- struct wl_client* m_client { nullptr }; + + ClientBundle* m_clientBundle; + struct wpe_view_backend* m_backend; +diff --git a/src/ws.cpp b/src/ws.cpp +index 87faaf3..622bbf3 100644 +--- a/src/ws.cpp ++++ b/src/ws.cpp +@@ -519,14 +519,13 @@ void Instance::releaseAudioPacketExport(struct wpe_audio_packet_export* packet_e + wpe_audio_packet_export_send_release(packet_export->exportResource); + } + +-struct wl_client* Instance::registerViewBackend(uint32_t bridgeId, APIClient& apiClient) ++void Instance::registerViewBackend(uint32_t bridgeId, APIClient& apiClient) + { + auto it = m_viewBackendMap.find(bridgeId); + if (it == m_viewBackendMap.end()) + g_error("Instance::registerViewBackend(): " "Cannot find surface with bridgeId %" PRIu32 " in view backend map.", bridgeId); + + it->second->apiClient = &apiClient; +- return wl_resource_get_client(it->second->resource); + } + + void Instance::unregisterViewBackend(uint32_t bridgeId) +diff --git a/src/ws.h b/src/ws.h +index 30baf8e..1bf528e 100644 +--- a/src/ws.h ++++ b/src/ws.h +@@ -88,10 +88,17 @@ struct Surface { + { + struct wl_resource* resource; + struct wl_resource* tmp; ++ struct wl_client* client { nullptr }; ++ + wl_resource_for_each_safe(resource, tmp, &m_currentFrameCallbacks) { ++ g_assert(!client || client == wl_resource_get_client(resource)); ++ client = wl_resource_get_client(resource); + wl_callback_send_done(resource, 0); + wl_resource_destroy(resource); + } ++ ++ if (client) ++ wl_client_flush(client); + } + + private: +@@ -129,7 +136,7 @@ public: + int createClient(); + + void registerSurface(uint32_t, Surface*); +- struct wl_client* registerViewBackend(uint32_t, APIClient&); ++ void registerViewBackend(uint32_t, APIClient&); + void unregisterViewBackend(uint32_t); + void dispatchFrameCallbacks(uint32_t); + +-- +2.31.1 + diff --git a/wpebackend-fdo.spec b/wpebackend-fdo.spec index a3fa011..87df1e8 100644 --- a/wpebackend-fdo.spec +++ b/wpebackend-fdo.spec @@ -2,13 +2,27 @@ Name: wpebackend-fdo Version: 1.9.90 -Release: 1%{?dist} +Release: 2%{?dist} Summary: A WPE backend designed for Linux desktop systems License: BSD URL: https://github.com/Igalia/%{name} Source0: https://github.com/Igalia/%{name}/archive/%{version}/%{name}-%{version}.tar.xz +# https://github.com/Igalia/WPEBackend-fdo/issues/145 +Patch0: 0001-Add-some-checks-to-ensure-we-properly-bind-server-gl.patch +Patch1: 0002-ws-Remove-unneeded-Surface-id-member.patch +Patch2: 0003-ws-Rename-surfaceId-to-bridgeId-where-appropriate.patch +Patch3: 0004-ws-Accumulate-surface-frame-callbacks-until-commit.patch +Patch4: 0006-meson-Make-scripts-version.py-work-with-older-Python.patch +Patch5: 0007-Revert-view-backend-Properly-unregister-surfaces.patch +Patch6: 0008-Revert-view-backend-private-Move-wl_client_destroy-t.patch +Patch7: 0009-Revert-ws-Call-wl_client_destroy-for-the-created-wl_.patch +Patch8: 0010-Revert-Cleanups.patch +Patch9: 0011-Revert-view-backend-exportable-private-Move-ViewBack.patch +Patch10: 0012-Revert-view-backend-exportable-private-Add-wl_client.patch +Patch11: 0013-ws-Remove-wl_client-pointer-that-can-end-up-dangling.patch + BuildRequires: gcc-c++ BuildRequires: meson BuildRequires: pkgconfig(egl) @@ -53,6 +67,9 @@ files for developing applications that use %{name}. %{_libdir}/pkgconfig/wpebackend-fdo-1.0.pc %changelog +* Sat Apr 17 2021 Michael Catanzaro - 1.9.90-2 +- Stop crashing after process swap + * Thu Apr 01 2021 Michael Catanzaro - 1.9.90-1 - Update to 1.9.90