blob: 46a6189b958e4e8ca2fc250beb5ff8bce08049c3 [file] [log] [blame]
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