1 /*
2  * Copyright (C) 2018 Igalia S.L.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
15  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
16  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
17  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
19  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #pragma once
27 
28 #include "ipc.h"
29 #include "ws.h"
30 
31 #include <gio/gio.h>
32 #include <wpe/wpe.h>
33 #include <vector>
34 
35 class ViewBackend;
36 
37 class ClientBundle {
38 public:
ClientBundle(void * _data,ViewBackend * _viewBackend,uint32_t _initialWidth,uint32_t _initialHeight)39     ClientBundle(void* _data, ViewBackend* _viewBackend, uint32_t _initialWidth, uint32_t _initialHeight)
40         : data(_data)
41         , viewBackend(_viewBackend)
42         , initialWidth(_initialWidth)
43         , initialHeight(_initialHeight)
44     {
45     }
46 
47     virtual ~ClientBundle() = default;
48 
49     virtual void exportBuffer(struct wl_resource *bufferResource) = 0;
50     virtual void exportBuffer(const struct linux_dmabuf_buffer *dmabuf_buffer) = 0;
51     virtual void exportBuffer(struct wl_resource* bufferResource, struct wl_shm_buffer* shmBuffer) = 0;
52     virtual void exportEGLStreamProducer(struct wl_resource *bufferResource) = 0;
53 
54     virtual struct wpe_dmabuf_pool_entry* createDmabufPoolEntry() = 0;
55     virtual void commitDmabufPoolEntry(struct wpe_dmabuf_pool_entry*) = 0;
56 
57     void* data;
58     ViewBackend* viewBackend;
59     uint32_t initialWidth;
60     uint32_t initialHeight;
61 };
62 
63 class ViewBackend final : public WS::APIClient, public FdoIPC::MessageReceiver {
64 public:
65     ViewBackend(ClientBundle* clientBundle, struct wpe_view_backend* backend);
66     ~ViewBackend();
67 
68     void initialize();
69     int clientFd();
70     void exportBufferResource(struct wl_resource* bufferResource) override;
71     void exportLinuxDmabuf(const struct linux_dmabuf_buffer *dmabuf_buffer) override;
72     void exportShmBuffer(struct wl_resource* bufferResource, struct wl_shm_buffer* shmBuffer) override;
73     void exportEGLStreamProducer(struct wl_resource*) override;
74 
75     struct wpe_dmabuf_pool_entry* createDmabufPoolEntry() override;
76     void commitDmabufPoolEntry(struct wpe_dmabuf_pool_entry*) override;
77 
bridgeConnectionLost(uint32_t id)78     void bridgeConnectionLost(uint32_t id) override
79     {
80          unregisterSurface(id);
81     }
82 
83     void dispatchFrameCallbacks();
84     void releaseBuffer(struct wl_resource* buffer_resource);
85 
86 private:
87     void didReceiveMessage(uint32_t messageId, uint32_t messageBody) override;
88 
89     void registerSurface(uint32_t);
90     void unregisterSurface(uint32_t);
91 
92     static gboolean s_socketCallback(GSocket*, GIOCondition, gpointer);
93 
94     std::vector<uint32_t> m_bridgeIds;
95 
96     ClientBundle* m_clientBundle;
97     struct wpe_view_backend* m_backend;
98 
99     std::unique_ptr<FdoIPC::Connection> m_socket;
100     int m_clientFd { -1 };
101 };
102 
103 struct wpe_view_backend_private {
wpe_view_backend_privatewpe_view_backend_private104     wpe_view_backend_private(std::unique_ptr<ClientBundle>&& clientBundle, struct wpe_view_backend* backend)
105         : clientBundle(std::move(clientBundle))
106         , backend(backend)
107     {
108     }
109 
~wpe_view_backend_privatewpe_view_backend_private110     ~wpe_view_backend_private()
111     {
112         wpe_view_backend_destroy(backend);
113     }
114 
115     std::unique_ptr<ClientBundle> clientBundle;
116     struct wpe_view_backend* backend { nullptr };
117 };
118 
119 struct wpe_view_backend_exportable_fdo : wpe_view_backend_private {
wpe_view_backend_exportable_fdowpe_view_backend_exportable_fdo120     wpe_view_backend_exportable_fdo(std::unique_ptr<ClientBundle>&& clientBundle, struct wpe_view_backend* backend)
121         : wpe_view_backend_private(std::move(clientBundle), backend)
122     {
123     }
124 };
125 
126 struct wpe_view_backend_dmabuf_pool_fdo : wpe_view_backend_private {
wpe_view_backend_dmabuf_pool_fdowpe_view_backend_dmabuf_pool_fdo127     wpe_view_backend_dmabuf_pool_fdo(std::unique_ptr<ClientBundle>&& clientBundle, struct wpe_view_backend* backend)
128         : wpe_view_backend_private(std::move(clientBundle), backend)
129     {
130     }
131 };
132 
133 static struct wpe_view_backend_interface view_backend_private_interface = {
134     // create
135     [](void* data, struct wpe_view_backend* backend) -> void*
136     {
137         auto* clientBundle = reinterpret_cast<ClientBundle*>(data);
138         return new ViewBackend(clientBundle, backend);
139     },
140     // destroy
141     [](void* data)
142     {
143         auto* backend = reinterpret_cast<ViewBackend*>(data);
144         delete backend;
145     },
146     // initialize
147     [](void* data)
148     {
149         auto& backend = *reinterpret_cast<ViewBackend*>(data);
150         backend.initialize();
151     },
152     // get_renderer_host_fd
153     [](void* data) -> int
154     {
155         auto& backend = *reinterpret_cast<ViewBackend*>(data);
156         return backend.clientFd();
157     }
158 };
159