| From 13cae95a3b38899f8fd5fc39a5d25fcc9500e09a Mon Sep 17 00:00:00 2001 |
| From: Carlos Garcia Campos <cgarcia@igalia.com> |
| Date: Thu, 30 May 2019 14:04:29 +0200 |
| Subject: [PATCH] Handle the case of new target created for the same view |
| backend |
| |
| The client can remove a target and create a new one for the same view |
| backend. In that case we need to unregister the current view backend in |
| the wayland compositor before registering the new one. This patch renames |
| WS::Instance::createSurface as registerSurface to clarify that it's not |
| creating a new surface but registering a new one for the given id. Also |
| ViewBackend::m_id has been renamed as m_surfaceId to clarify that's not |
| the backend identifier, but the current surface identifier. |
| --- |
| src/renderer-backend-egl.cpp | 8 +++++- |
| src/view-backend-exportable-private.cpp | 35 +++++++++++++++++++++---- |
| src/view-backend-exportable-private.h | 5 +++- |
| src/ws.cpp | 12 ++++----- |
| src/ws.h | 2 +- |
| 5 files changed, 48 insertions(+), 14 deletions(-) |
| |
| diff --git a/src/renderer-backend-egl.cpp b/src/renderer-backend-egl.cpp |
| index 726d61c..7e11d5e 100644 |
| --- a/src/renderer-backend-egl.cpp |
| +++ b/src/renderer-backend-egl.cpp |
| @@ -139,6 +139,11 @@ public: |
| |
| ~Target() |
| { |
| + if (m_wl.wpeBridgeId && m_glib.socket) { |
| + uint32_t message[] = { 0x43, m_wl.wpeBridgeId }; |
| + g_socket_send(m_glib.socket, reinterpret_cast<gchar*>(message), 2 * sizeof(uint32_t), nullptr, nullptr); |
| + } |
| + |
| g_clear_pointer(&m_wl.frameCallback, wl_callback_destroy); |
| g_clear_pointer(&m_wl.window, wl_egl_window_destroy); |
| g_clear_pointer(&m_wl.surface, wl_surface_destroy); |
| @@ -223,6 +228,7 @@ public: |
| |
| void bridgeConnected(uint32_t bridgeID) |
| { |
| + m_wl.wpeBridgeId = bridgeID; |
| uint32_t message[] = { 0x42, bridgeID }; |
| if (m_glib.socket) |
| g_socket_send(m_glib.socket, reinterpret_cast<gchar*>(message), 2 * sizeof(uint32_t), nullptr, nullptr); |
| @@ -246,11 +252,11 @@ private: |
| } m_glib; |
| |
| struct { |
| - struct wl_display* displayWrapper { nullptr }; |
| struct wl_event_queue* eventQueue { nullptr }; |
| struct wl_registry* registry { nullptr }; |
| struct wl_compositor* compositor { nullptr }; |
| struct wpe_bridge* wpeBridge { nullptr }; |
| + uint32_t wpeBridgeId { 0 }; |
| |
| struct wl_surface* surface { nullptr }; |
| struct wl_egl_window* window { nullptr }; |
| diff --git a/src/view-backend-exportable-private.cpp b/src/view-backend-exportable-private.cpp |
| index d73102f..d10679b 100644 |
| --- a/src/view-backend-exportable-private.cpp |
| +++ b/src/view-backend-exportable-private.cpp |
| @@ -39,7 +39,7 @@ ViewBackend::~ViewBackend() |
| for (auto* resource : m_callbackResources) |
| wl_resource_destroy(resource); |
| |
| - WS::Instance::singleton().unregisterViewBackend(m_id); |
| + unregisterSurface(m_surfaceId); |
| |
| if (m_clientFd != -1) |
| close(m_clientFd); |
| @@ -117,6 +117,24 @@ void ViewBackend::releaseBuffer(struct wl_resource* buffer_resource) |
| wl_client_flush(m_client); |
| } |
| |
| +void ViewBackend::registerSurface(uint32_t surfaceId) |
| +{ |
| + m_surfaceId = surfaceId; |
| + m_client = WS::Instance::singleton().registerViewBackend(m_surfaceId, *this); |
| +} |
| + |
| +void ViewBackend::unregisterSurface(uint32_t surfaceId) |
| +{ |
| + if (!surfaceId || m_surfaceId != surfaceId) |
| + return; |
| + |
| + for (auto* resource : m_callbackResources) |
| + wl_resource_destroy(resource); |
| + m_callbackResources.clear(); |
| + WS::Instance::singleton().unregisterViewBackend(m_surfaceId); |
| + m_surfaceId = 0; |
| +} |
| + |
| gboolean ViewBackend::s_socketCallback(GSocket* socket, GIOCondition condition, gpointer data) |
| { |
| if (!(condition & G_IO_IN)) |
| @@ -128,10 +146,17 @@ gboolean ViewBackend::s_socketCallback(GSocket* socket, GIOCondition condition, |
| if (len == -1) |
| return FALSE; |
| |
| - if (len == sizeof(uint32_t) * 2 && message[0] == 0x42) { |
| - auto& viewBackend = *static_cast<ViewBackend*>(data); |
| - viewBackend.m_id = message[1]; |
| - viewBackend.m_client = WS::Instance::singleton().registerViewBackend(viewBackend.m_id, viewBackend); |
| + if (len != sizeof(uint32_t) * 2) |
| + return TRUE; |
| + |
| + auto& viewBackend = *static_cast<ViewBackend*>(data); |
| + switch (message[0]) { |
| + case 0x42: |
| + viewBackend.registerSurface(message[1]); |
| + break; |
| + case 0x43: |
| + viewBackend.unregisterSurface(message[1]); |
| + break; |
| } |
| |
| return TRUE; |
| diff --git a/src/view-backend-exportable-private.h b/src/view-backend-exportable-private.h |
| index b27494e..73f3497 100644 |
| --- a/src/view-backend-exportable-private.h |
| +++ b/src/view-backend-exportable-private.h |
| @@ -67,9 +67,12 @@ public: |
| void releaseBuffer(struct wl_resource* buffer_resource); |
| |
| private: |
| + void registerSurface(uint32_t); |
| + void unregisterSurface(uint32_t); |
| + |
| static gboolean s_socketCallback(GSocket*, GIOCondition, gpointer); |
| |
| - uint32_t m_id { 0 }; |
| + uint32_t m_surfaceId { 0 }; |
| struct wl_client* m_client { nullptr }; |
| |
| ClientBundle* m_clientBundle; |
| diff --git a/src/ws.cpp b/src/ws.cpp |
| index a856e0b..1aac351 100644 |
| --- a/src/ws.cpp |
| +++ b/src/ws.cpp |
| @@ -231,7 +231,7 @@ static const struct wpe_bridge_interface s_wpeBridgeInterface = { |
| static uint32_t bridgeID = 0; |
| ++bridgeID; |
| wpe_bridge_send_connected(resource, bridgeID); |
| - Instance::singleton().createSurface(bridgeID, surface); |
| + Instance::singleton().registerSurface(bridgeID, surface); |
| }, |
| }; |
| |
| @@ -393,7 +393,7 @@ int Instance::createClient() |
| return clientFd; |
| } |
| |
| -void Instance::createSurface(uint32_t id, Surface* surface) |
| +void Instance::registerSurface(uint32_t id, Surface* surface) |
| { |
| m_viewBackendMap.insert({ id, surface }); |
| } |
| @@ -538,9 +538,9 @@ void Instance::foreachDmaBufModifier(std::function<void (int format, uint64_t mo |
| } |
| } |
| |
| -struct wl_client* Instance::registerViewBackend(uint32_t id, ExportableClient& exportableClient) |
| +struct wl_client* Instance::registerViewBackend(uint32_t surfaceId, ExportableClient& exportableClient) |
| { |
| - auto it = m_viewBackendMap.find(id); |
| + auto it = m_viewBackendMap.find(surfaceId); |
| if (it == m_viewBackendMap.end()) |
| std::abort(); |
| |
| @@ -548,9 +548,9 @@ struct wl_client* Instance::registerViewBackend(uint32_t id, ExportableClient& e |
| return it->second->client; |
| } |
| |
| -void Instance::unregisterViewBackend(uint32_t id) |
| +void Instance::unregisterViewBackend(uint32_t surfaceId) |
| { |
| - auto it = m_viewBackendMap.find(id); |
| + auto it = m_viewBackendMap.find(surfaceId); |
| if (it != m_viewBackendMap.end()) { |
| it->second->exportableClient = nullptr; |
| m_viewBackendMap.erase(it); |
| diff --git a/src/ws.h b/src/ws.h |
| index d4c2bff..5cb88e7 100644 |
| --- a/src/ws.h |
| +++ b/src/ws.h |
| @@ -53,7 +53,7 @@ public: |
| |
| int createClient(); |
| |
| - void createSurface(uint32_t, Surface*); |
| + void registerSurface(uint32_t, Surface*); |
| struct wl_client* registerViewBackend(uint32_t, ExportableClient&); |
| void unregisterViewBackend(uint32_t); |
| |
| -- |
| 2.20.1 |
| |