wpebackend-fdo/0004-ws-Accumulate-surface-frame-callbacks-until-commit.patch
2021-04-17 08:20:39 -05:00

263 lines
9.1 KiB
Diff

From 98ad602e5f5d51162ec715a023b87d06a71d627b Mon Sep 17 00:00:00 2001
From: Adrian Perez de Castro <aperez@igalia.com>
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<FdoIPC::Connection> 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<Surface*>(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<void(struct wpe_video_plane_display_dmabuf_export*, uint32_t, int, int32_t, int32_t, int32_t, int32_t, uint32_t)>;
using VideoPlaneDisplayDmaBufEndOfStreamCallback = std::function<void(uint32_t)>;
--
2.31.1