Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Force ViewBackend dispatch when the bridge connection is lost #161

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 20 additions & 15 deletions src/view-backend-private.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <cassert>
#include <sys/types.h>
#include <sys/socket.h>
#include <algorithm>

ViewBackend::ViewBackend(ClientBundle* clientBundle, struct wpe_view_backend* backend)
: m_clientBundle(clientBundle)
Expand All @@ -38,8 +39,9 @@ ViewBackend::ViewBackend(ClientBundle* clientBundle, struct wpe_view_backend* ba

ViewBackend::~ViewBackend()
{
unregisterSurface(m_bridgeId);

m_backend = nullptr;
for (auto bridgeId : m_bridgeIds)
WS::Instance::singleton().unregisterViewBackend(bridgeId);
if (m_clientFd != -1)
close(m_clientFd);
}
Expand Down Expand Up @@ -90,14 +92,6 @@ void ViewBackend::exportEGLStreamProducer(struct wl_resource* bufferResource)
m_clientBundle->exportEGLStreamProducer(bufferResource);
}

void ViewBackend::dispatchFrameCallbacks()
{
if (G_LIKELY(m_bridgeId))
WS::Instance::singleton().dispatchFrameCallbacks(m_bridgeId);

wpe_view_backend_dispatch_frame_displayed(m_backend);
}

void ViewBackend::releaseBuffer(struct wl_resource* buffer_resource)
{
wl_buffer_send_release(buffer_resource);
Expand All @@ -106,17 +100,28 @@ void ViewBackend::releaseBuffer(struct wl_resource* buffer_resource)

void ViewBackend::registerSurface(uint32_t bridgeId)
{
m_bridgeId = bridgeId;
WS::Instance::singleton().registerViewBackend(m_bridgeId, *this);
// The current surface will be made inactive (if any); make sure that
// surfaces other than the new active one do not have callbacks pending
// to be dispatched.
dispatchFrameCallbacks();

m_bridgeIds.push_back(bridgeId);
WS::Instance::singleton().registerViewBackend(m_bridgeIds.back(), *this);
}

void ViewBackend::unregisterSurface(uint32_t bridgeId)
{
if (!bridgeId || m_bridgeId != bridgeId)
auto it = std::find(m_bridgeIds.begin(), m_bridgeIds.end(), bridgeId);
if (it == m_bridgeIds.end())
return;

WS::Instance::singleton().unregisterViewBackend(m_bridgeId);
m_bridgeId = 0;
// If the item being removed corresponds to the active surface, make
// sure to avoid having frame callbacks pending dispatch before removing.
if (bridgeId == m_bridgeIds.back())
dispatchFrameCallbacks(bridgeId);

m_bridgeIds.erase(it);
WS::Instance::singleton().unregisterViewBackend(bridgeId);
}

void ViewBackend::didReceiveMessage(uint32_t messageId, uint32_t messageBody)
Expand Down
26 changes: 24 additions & 2 deletions src/view-backend-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

#include <gio/gio.h>
#include <wpe/wpe.h>
#include <vector>

class ViewBackend;

Expand Down Expand Up @@ -67,18 +68,39 @@ class ViewBackend final : public WS::APIClient, public FdoIPC::MessageReceiver {
void exportLinuxDmabuf(const struct linux_dmabuf_buffer *dmabuf_buffer) override;
void exportShmBuffer(struct wl_resource* bufferResource, struct wl_shm_buffer* shmBuffer) override;
void exportEGLStreamProducer(struct wl_resource*) override;
void dispatchFrameCallbacks();

void bridgeConnectionLost(uint32_t id) override
{
unregisterSurface(id);
dispatchFrameCallbacks();
}

inline void dispatchFrameCallbacks()
{
if (G_LIKELY(!m_bridgeIds.empty()))
dispatchFrameCallbacks(m_bridgeIds.back());
}

void releaseBuffer(struct wl_resource* buffer_resource);

private:
inline void dispatchFrameCallbacks(uint32_t bridgeId)
{
WS::Instance::singleton().dispatchFrameCallbacks(bridgeId);
if (G_LIKELY(m_backend))
wpe_view_backend_dispatch_frame_displayed(m_backend);
else
g_warning("Ignored dispatch frame displayed for bridgeId %" PRIu32 ": WPE view backend is gone", bridgeId);
}

void didReceiveMessage(uint32_t messageId, uint32_t messageBody) override;

void registerSurface(uint32_t);
void unregisterSurface(uint32_t);

static gboolean s_socketCallback(GSocket*, GIOCondition, gpointer);

uint32_t m_bridgeId { 0 };
std::vector<uint32_t> m_bridgeIds;

ClientBundle* m_clientBundle;
struct wpe_view_backend* m_backend;
Expand Down
5 changes: 4 additions & 1 deletion src/ws.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -545,8 +545,11 @@ void Instance::unregisterSurface(Surface* surface)
[surface](const std::pair<uint32_t, Surface*>& value) -> bool {
return value.second == surface;
});
if (it != m_viewBackendMap.end())
if (it != m_viewBackendMap.end()) {
m_viewBackendMap.erase(it);
if (surface->apiClient)
surface->apiClient->bridgeConnectionLost(it->first);
}
}

void Instance::dispatchFrameCallbacks(uint32_t bridgeId)
Expand Down
6 changes: 6 additions & 0 deletions src/ws.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ struct APIClient {
virtual void exportLinuxDmabuf(const struct linux_dmabuf_buffer *dmabuf_buffer) = 0;
virtual void exportShmBuffer(struct wl_resource*, struct wl_shm_buffer*) = 0;
virtual void exportEGLStreamProducer(struct wl_resource*) = 0;

// Invoked when the association with the surface associated with a given
// wpe_bridge identifier is no longer valid, typically due to the nested
// compositor client being disconnected before having the chance to read
// and process a FdoIPC::UnregisterSurface message.
virtual void bridgeConnectionLost(uint32_t bridgeId) = 0;
};

struct Surface {
Expand Down