1/*
2 * Copyright (C) 2016 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 APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * 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#include "config.h"
27#include "WaylandCompositor.h"
28
29#if PLATFORM(WAYLAND) && USE(EGL) && !USE(WPE_RENDERER)
30
31#include "WebKitWaylandServerProtocol.h"
32#include <EGL/egl.h>
33#include <EGL/eglext.h>
34#include <WebCore/GLContext.h>
35#include <WebCore/PlatformDisplayWayland.h>
36#include <WebCore/Region.h>
37#include <gtk/gtk.h>
38#include <wayland-server-protocol.h>
39#include <wtf/UUID.h>
40
41#if USE(OPENGL_ES)
42#include <GLES2/gl2.h>
43#include <GLES2/gl2ext.h>
44#include <WebCore/Extensions3DOpenGLES.h>
45#else
46#include <WebCore/Extensions3DOpenGL.h>
47#include <WebCore/OpenGLShims.h>
48#endif
49
50namespace WebKit {
51using namespace WebCore;
52
53#if !defined(PFNEGLBINDWAYLANDDISPLAYWL)
54typedef EGLBoolean (*PFNEGLBINDWAYLANDDISPLAYWL) (EGLDisplay, struct wl_display*);
55#endif
56
57#if !defined(PFNEGLUNBINDWAYLANDDISPLAYWL)
58typedef EGLBoolean (*PFNEGLUNBINDWAYLANDDISPLAYWL) (EGLDisplay, struct wl_display*);
59#endif
60
61#if !defined(PFNEGLQUERYWAYLANDBUFFERWL)
62typedef EGLBoolean (*PFNEGLQUERYWAYLANDBUFFERWL) (EGLDisplay, struct wl_resource*, EGLint attribute, EGLint* value);
63#endif
64
65#if !defined(PFNEGLCREATEIMAGEKHRPROC)
66typedef EGLImageKHR (*PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay, EGLContext, EGLenum target, EGLClientBuffer, const EGLint* attribList);
67#endif
68
69#if !defined(PFNEGLDESTROYIMAGEKHRPROC)
70typedef EGLBoolean (*PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay, EGLImageKHR);
71#endif
72
73#if !defined(PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)
74typedef void (*PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES);
75#endif
76
77static PFNEGLBINDWAYLANDDISPLAYWL eglBindWaylandDisplay;
78static PFNEGLUNBINDWAYLANDDISPLAYWL eglUnbindWaylandDisplay;
79static PFNEGLQUERYWAYLANDBUFFERWL eglQueryWaylandBuffer;
80static PFNEGLCREATEIMAGEKHRPROC eglCreateImage;
81static PFNEGLDESTROYIMAGEKHRPROC eglDestroyImage;
82static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glImageTargetTexture2D;
83
84WaylandCompositor& WaylandCompositor::singleton()
85{
86 static NeverDestroyed<WaylandCompositor> waylandCompositor;
87 return waylandCompositor;
88}
89
90WaylandCompositor::Buffer* WaylandCompositor::Buffer::getOrCreate(struct wl_resource* resource)
91{
92 if (struct wl_listener* listener = wl_resource_get_destroy_listener(resource, destroyListenerCallback)) {
93 WaylandCompositor::Buffer* buffer;
94 return wl_container_of(listener, buffer, m_destroyListener);
95 }
96
97 return new WaylandCompositor::Buffer(resource);
98}
99
100WaylandCompositor::Buffer::Buffer(struct wl_resource* resource)
101 : m_resource(resource)
102{
103 wl_list_init(&m_destroyListener.link);
104 m_destroyListener.notify = destroyListenerCallback;
105 wl_resource_add_destroy_listener(m_resource, &m_destroyListener);
106}
107
108WaylandCompositor::Buffer::~Buffer()
109{
110 wl_list_remove(&m_destroyListener.link);
111}
112
113void WaylandCompositor::Buffer::destroyListenerCallback(struct wl_listener* listener, void*)
114{
115 WaylandCompositor::Buffer* buffer;
116 buffer = wl_container_of(listener, buffer, m_destroyListener);
117 delete buffer;
118}
119
120void WaylandCompositor::Buffer::use()
121{
122 m_busyCount++;
123}
124
125void WaylandCompositor::Buffer::unuse()
126{
127 m_busyCount--;
128 if (!m_busyCount)
129 wl_resource_queue_event(m_resource, WL_BUFFER_RELEASE);
130}
131
132EGLImageKHR WaylandCompositor::Buffer::createImage() const
133{
134 return static_cast<EGLImageKHR*>(eglCreateImage(PlatformDisplay::sharedDisplay().eglDisplay(), EGL_NO_CONTEXT, EGL_WAYLAND_BUFFER_WL, m_resource, nullptr));
135}
136
137IntSize WaylandCompositor::Buffer::size() const
138{
139 EGLDisplay eglDisplay = PlatformDisplay::sharedDisplay().eglDisplay();
140 int width, height;
141 eglQueryWaylandBuffer(eglDisplay, m_resource, EGL_WIDTH, &width);
142 eglQueryWaylandBuffer(eglDisplay, m_resource, EGL_HEIGHT, &height);
143
144 return { width, height };
145}
146
147WaylandCompositor::Surface::Surface()
148 : m_image(EGL_NO_IMAGE_KHR)
149{
150}
151
152WaylandCompositor::Surface::~Surface()
153{
154 setWebPage(nullptr);
155
156 // Destroy pending frame callbacks.
157 auto pendingList = WTFMove(m_pendingFrameCallbackList);
158 for (auto* resource : pendingList)
159 wl_resource_destroy(resource);
160 auto list = WTFMove(m_frameCallbackList);
161 for (auto* resource : list)
162 wl_resource_destroy(resource);
163
164 if (m_buffer)
165 m_buffer->unuse();
166}
167
168void WaylandCompositor::Surface::setWebPage(WebPageProxy* webPage)
169{
170 if (m_webPage) {
171 flushPendingFrameCallbacks();
172 flushFrameCallbacks();
173 gtk_widget_remove_tick_callback(m_webPage->viewWidget(), m_tickCallbackID);
174 m_tickCallbackID = 0;
175
176 if (m_webPage->makeGLContextCurrent()) {
177 if (m_image != EGL_NO_IMAGE_KHR)
178 eglDestroyImage(PlatformDisplay::sharedDisplay().eglDisplay(), m_image);
179 if (m_texture)
180 glDeleteTextures(1, &m_texture);
181 }
182
183 m_image = EGL_NO_IMAGE_KHR;
184 m_texture = 0;
185 }
186
187 m_webPage = webPage;
188 if (!m_webPage)
189 return;
190
191 if (m_webPage->makeGLContextCurrent()) {
192 glGenTextures(1, &m_texture);
193 glBindTexture(GL_TEXTURE_2D, m_texture);
194 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
195 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
196 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
197 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
198 }
199
200 m_tickCallbackID = gtk_widget_add_tick_callback(m_webPage->viewWidget(), [](GtkWidget*, GdkFrameClock*, gpointer userData) -> gboolean {
201 auto* surface = static_cast<Surface*>(userData);
202 surface->flushFrameCallbacks();
203 return G_SOURCE_CONTINUE;
204 }, this, nullptr);
205}
206
207void WaylandCompositor::Surface::makePendingBufferCurrent()
208{
209 if (m_pendingBuffer == m_buffer)
210 return;
211
212 if (m_buffer)
213 m_buffer->unuse();
214
215 if (m_pendingBuffer)
216 m_pendingBuffer->use();
217
218 m_buffer = m_pendingBuffer;
219}
220
221void WaylandCompositor::Surface::attachBuffer(struct wl_resource* buffer)
222{
223 if (m_pendingBuffer)
224 m_pendingBuffer = nullptr;
225
226 if (buffer) {
227 auto* compositorBuffer = WaylandCompositor::Buffer::getOrCreate(buffer);
228 m_pendingBuffer = makeWeakPtr(*compositorBuffer);
229 }
230}
231
232void WaylandCompositor::Surface::requestFrame(struct wl_resource* resource)
233{
234 wl_resource_set_implementation(resource, nullptr, this, [](struct wl_resource* resource) {
235 auto* surface = static_cast<WaylandCompositor::Surface*>(wl_resource_get_user_data(resource));
236 if (size_t item = surface->m_pendingFrameCallbackList.find(resource) != notFound)
237 surface->m_pendingFrameCallbackList.remove(item);
238 });
239 m_pendingFrameCallbackList.append(resource);
240}
241
242bool WaylandCompositor::Surface::prepareTextureForPainting(unsigned& texture, IntSize& textureSize)
243{
244 if (!m_texture || m_image == EGL_NO_IMAGE_KHR)
245 return false;
246
247 if (!m_webPage || !m_webPage->makeGLContextCurrent())
248 return false;
249
250 glBindTexture(GL_TEXTURE_2D, m_texture);
251 glImageTargetTexture2D(GL_TEXTURE_2D, m_image);
252
253 texture = m_texture;
254 textureSize = m_imageSize;
255 return true;
256}
257
258void WaylandCompositor::Surface::flushFrameCallbacks()
259{
260 auto list = WTFMove(m_frameCallbackList);
261 for (auto* resource : list) {
262 wl_callback_send_done(resource, 0);
263 wl_resource_destroy(resource);
264 }
265}
266
267void WaylandCompositor::Surface::flushPendingFrameCallbacks()
268{
269 auto list = WTFMove(m_pendingFrameCallbackList);
270 for (auto* resource : list) {
271 wl_callback_send_done(resource, 0);
272 wl_resource_destroy(resource);
273 }
274}
275
276void WaylandCompositor::Surface::commit()
277{
278 if (!m_webPage || !m_webPage->makeGLContextCurrent()) {
279 makePendingBufferCurrent();
280 flushPendingFrameCallbacks();
281 return;
282 }
283
284 EGLDisplay eglDisplay = PlatformDisplay::sharedDisplay().eglDisplay();
285 if (m_image != EGL_NO_IMAGE_KHR)
286 eglDestroyImage(eglDisplay, m_image);
287 m_image = m_pendingBuffer->createImage();
288 if (m_image == EGL_NO_IMAGE_KHR)
289 return;
290
291 m_imageSize = m_pendingBuffer->size();
292
293 makePendingBufferCurrent();
294
295 m_webPage->setViewNeedsDisplay(IntRect(IntPoint::zero(), m_webPage->viewSize()));
296
297 auto list = WTFMove(m_pendingFrameCallbackList);
298 m_frameCallbackList.appendVector(list);
299}
300
301static const struct wl_surface_interface surfaceInterface = {
302 // destroyCallback
303 [](struct wl_client*, struct wl_resource* resource)
304 {
305 wl_resource_destroy(resource);
306 },
307 // attachCallback
308 [](struct wl_client* client, struct wl_resource* resource, struct wl_resource* buffer, int32_t sx, int32_t sy)
309 {
310 auto* surface = static_cast<WaylandCompositor::Surface*>(wl_resource_get_user_data(resource));
311 if (!surface)
312 return;
313
314 EGLint format;
315 if (!eglQueryWaylandBuffer(PlatformDisplay::sharedDisplay().eglDisplay(), buffer, EGL_TEXTURE_FORMAT, &format)
316 || (format != EGL_TEXTURE_RGB && format != EGL_TEXTURE_RGBA))
317 return;
318
319 surface->attachBuffer(buffer);
320 },
321 // damageCallback
322 [](struct wl_client*, struct wl_resource*, int32_t, int32_t, int32_t, int32_t) { },
323 // frameCallback
324 [](struct wl_client* client, struct wl_resource* resource, uint32_t id)
325 {
326 auto* surface = static_cast<WaylandCompositor::Surface*>(wl_resource_get_user_data(resource));
327 if (!surface)
328 return;
329
330 if (struct wl_resource* callbackResource = wl_resource_create(client, &wl_callback_interface, 1, id))
331 surface->requestFrame(callbackResource);
332 else
333 wl_client_post_no_memory(client);
334 },
335 // setOpaqueRegionCallback
336 [](struct wl_client*, struct wl_resource*, struct wl_resource*) { },
337 // setInputRegionCallback
338 [](struct wl_client*, struct wl_resource*, struct wl_resource*) { },
339 // commitCallback
340 [](struct wl_client* client, struct wl_resource* resource)
341 {
342 auto* surface = static_cast<WaylandCompositor::Surface*>(wl_resource_get_user_data(resource));
343 if (!surface)
344 return;
345 surface->commit();
346 },
347 // setBufferTransformCallback
348 [](struct wl_client*, struct wl_resource*, int32_t) { },
349 // setBufferScaleCallback
350 [](struct wl_client*, struct wl_resource*, int32_t) { },
351#if WAYLAND_VERSION_MAJOR > 1 || (WAYLAND_VERSION_MAJOR == 1 && WAYLAND_VERSION_MINOR >= 10)
352 // damageBufferCallback
353 [](struct wl_client*, struct wl_resource*, int32_t, int32_t, int32_t, int32_t) { },
354#endif
355};
356
357static const struct wl_compositor_interface compositorInterface = {
358 // createSurfaceCallback
359 [](struct wl_client* client, struct wl_resource* resource, uint32_t id)
360 {
361 if (struct wl_resource* surfaceResource = wl_resource_create(client, &wl_surface_interface, 1, id)) {
362 wl_resource_set_implementation(surfaceResource, &surfaceInterface, new WaylandCompositor::Surface(),
363 [](struct wl_resource* resource) {
364 auto* surface = static_cast<WaylandCompositor::Surface*>(wl_resource_get_user_data(resource));
365 delete surface;
366 });
367 } else
368 wl_client_post_no_memory(client);
369 },
370 // createRegionCallback
371 [](struct wl_client*, struct wl_resource*, uint32_t) { }
372};
373
374static const struct wl_webkitgtk_interface webkitgtkInterface = {
375 // bindSurfaceToPageCallback
376 [](struct wl_client*, struct wl_resource* resource, struct wl_resource* surfaceResource, uint32_t pageID)
377 {
378 auto* surface = static_cast<WaylandCompositor::Surface*>(wl_resource_get_user_data(surfaceResource));
379 if (!surface)
380 return;
381
382 auto* compositor = static_cast<WaylandCompositor*>(wl_resource_get_user_data(resource));
383 compositor->bindSurfaceToWebPage(surface, makeObjectIdentifier<PageIdentifierType>(pageID));
384 }
385};
386
387bool WaylandCompositor::initializeEGL()
388{
389 const char* extensions = eglQueryString(PlatformDisplay::sharedDisplay().eglDisplay(), EGL_EXTENSIONS);
390
391 if (PlatformDisplay::sharedDisplay().eglCheckVersion(1, 5)) {
392 eglCreateImage = reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImage"));
393 eglDestroyImage = reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>(eglGetProcAddress("eglDestroyImage"));
394 } else {
395 if (GLContext::isExtensionSupported(extensions, "EGL_KHR_image_base")) {
396 eglCreateImage = reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR"));
397 eglDestroyImage = reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>(eglGetProcAddress("eglDestroyImageKHR"));
398 }
399 }
400 if (!eglCreateImage || !eglDestroyImage) {
401 WTFLogAlways("WaylandCompositor requires eglCreateImage and eglDestroyImage.");
402 return false;
403 }
404
405 if (GLContext::isExtensionSupported(extensions, "EGL_WL_bind_wayland_display")) {
406 eglBindWaylandDisplay = reinterpret_cast<PFNEGLBINDWAYLANDDISPLAYWL>(eglGetProcAddress("eglBindWaylandDisplayWL"));
407 eglUnbindWaylandDisplay = reinterpret_cast<PFNEGLUNBINDWAYLANDDISPLAYWL>(eglGetProcAddress("eglUnbindWaylandDisplayWL"));
408 eglQueryWaylandBuffer = reinterpret_cast<PFNEGLQUERYWAYLANDBUFFERWL>(eglGetProcAddress("eglQueryWaylandBufferWL"));
409 }
410 if (!eglBindWaylandDisplay || !eglUnbindWaylandDisplay || !eglQueryWaylandBuffer) {
411 WTFLogAlways("WaylandCompositor requires eglBindWaylandDisplayWL, eglUnbindWaylandDisplayWL and eglQueryWaylandBuffer.");
412 return false;
413 }
414
415 std::unique_ptr<WebCore::GLContext> eglContext = GLContext::createOffscreenContext();
416 if (!eglContext)
417 return false;
418
419 if (!eglContext->makeContextCurrent())
420 return false;
421
422#if USE(OPENGL_ES)
423 std::unique_ptr<Extensions3DOpenGLES> glExtensions = std::make_unique<Extensions3DOpenGLES>(nullptr, false);
424#else
425 std::unique_ptr<Extensions3DOpenGL> glExtensions = std::make_unique<Extensions3DOpenGL>(nullptr, GLContext::current()->version() >= 320);
426#endif
427 if (glExtensions->supports("GL_OES_EGL_image") || glExtensions->supports("GL_OES_EGL_image_external"))
428 glImageTargetTexture2D = reinterpret_cast<PFNGLEGLIMAGETARGETTEXTURE2DOESPROC>(eglGetProcAddress("glEGLImageTargetTexture2DOES"));
429
430 if (!glImageTargetTexture2D) {
431 WTFLogAlways("WaylandCompositor requires glEGLImageTargetTexture2D.");
432 return false;
433 }
434
435 return true;
436}
437
438typedef struct {
439 GSource source;
440 gpointer fdTag;
441 struct wl_display* display;
442} WaylandLoopSource;
443
444static const unsigned waylandLoopSourceCondition = G_IO_IN | G_IO_HUP | G_IO_ERR;
445
446static GSourceFuncs waylandLoopSourceFunctions = {
447 // prepare
448 [](GSource *source, int *timeout) -> gboolean
449 {
450 *timeout = -1;
451 auto* wlLoopSource = reinterpret_cast<WaylandLoopSource*>(source);
452 wl_display_flush_clients(wlLoopSource->display);
453 return FALSE;
454 },
455 nullptr, // check
456 // dispatch
457 [](GSource* source, GSourceFunc callback, gpointer userData) -> gboolean
458 {
459 auto* wlLoopSource = reinterpret_cast<WaylandLoopSource*>(source);
460 unsigned events = g_source_query_unix_fd(source, wlLoopSource->fdTag) & waylandLoopSourceCondition;
461 if (events & G_IO_HUP || events & G_IO_ERR) {
462 WTFLogAlways("Wayland Display Event Source: lost connection to nested Wayland compositor");
463 return G_SOURCE_REMOVE;
464 }
465
466 if (events & G_IO_IN)
467 wl_event_loop_dispatch(wl_display_get_event_loop(wlLoopSource->display), 0);
468 return G_SOURCE_CONTINUE;
469 },
470 nullptr, // finalize
471 nullptr, // closure_callback
472 nullptr, // closure_marshall
473};
474
475static GRefPtr<GSource> createWaylandLoopSource(struct wl_display* display)
476{
477 GRefPtr<GSource> source = adoptGRef(g_source_new(&waylandLoopSourceFunctions, sizeof(WaylandLoopSource)));
478 g_source_set_name(source.get(), "Nested Wayland compositor display event source");
479
480 auto* wlLoopSource = reinterpret_cast<WaylandLoopSource*>(source.get());
481 wlLoopSource->display = display;
482 wlLoopSource->fdTag = g_source_add_unix_fd(source.get(), wl_event_loop_get_fd(wl_display_get_event_loop(display)), static_cast<GIOCondition>(waylandLoopSourceCondition));
483 g_source_attach(source.get(), nullptr);
484
485 return source;
486}
487
488WaylandCompositor::WaylandCompositor()
489{
490 std::unique_ptr<struct wl_display, DisplayDeleter> display(wl_display_create());
491 if (!display) {
492 WTFLogAlways("Nested Wayland compositor could not create display object");
493 return;
494 }
495
496 String displayName = "webkitgtk-wayland-compositor-" + createCanonicalUUIDString();
497 if (wl_display_add_socket(display.get(), displayName.utf8().data()) == -1) {
498 WTFLogAlways("Nested Wayland compositor could not create display socket");
499 return;
500 }
501
502 WlUniquePtr<struct wl_global> compositorGlobal(wl_global_create(display.get(), &wl_compositor_interface, wl_compositor_interface.version, this,
503 [](struct wl_client* client, void* data, uint32_t version, uint32_t id) {
504 if (struct wl_resource* resource = wl_resource_create(client, &wl_compositor_interface, std::min(static_cast<int>(version), 3), id))
505 wl_resource_set_implementation(resource, &compositorInterface, static_cast<WaylandCompositor*>(data), nullptr);
506 else
507 wl_client_post_no_memory(client);
508 }));
509 if (!compositorGlobal) {
510 WTFLogAlways("Nested Wayland compositor could not register compositor global");
511 return;
512 }
513
514 WlUniquePtr<struct wl_global> webkitgtkGlobal(wl_global_create(display.get(), &wl_webkitgtk_interface, 1, this,
515 [](struct wl_client* client, void* data, uint32_t version, uint32_t id) {
516 if (struct wl_resource* resource = wl_resource_create(client, &wl_webkitgtk_interface, 1, id))
517 wl_resource_set_implementation(resource, &webkitgtkInterface, static_cast<WaylandCompositor*>(data), nullptr);
518 else
519 wl_client_post_no_memory(client);
520 }));
521 if (!webkitgtkGlobal) {
522 WTFLogAlways("Nested Wayland compositor could not register webkitgtk global");
523 return;
524 }
525
526 if (!initializeEGL()) {
527 WTFLogAlways("Nested Wayland compositor could not initialize EGL");
528 return;
529 }
530
531 if (!eglBindWaylandDisplay(PlatformDisplay::sharedDisplay().eglDisplay(), display.get())) {
532 WTFLogAlways("Nested Wayland compositor could not bind nested display");
533 return;
534 }
535
536 m_displayName = WTFMove(displayName);
537 m_display = WTFMove(display);
538 m_compositorGlobal = WTFMove(compositorGlobal);
539 m_webkitgtkGlobal = WTFMove(webkitgtkGlobal);
540 m_eventSource = createWaylandLoopSource(m_display.get());
541}
542
543bool WaylandCompositor::getTexture(WebPageProxy& webPage, unsigned& texture, IntSize& textureSize)
544{
545 if (WeakPtr<Surface> surface = m_pageMap.get(&webPage))
546 return surface->prepareTextureForPainting(texture, textureSize);
547 return false;
548}
549
550void WaylandCompositor::bindSurfaceToWebPage(WaylandCompositor::Surface* surface, WebCore::PageIdentifier pageID)
551{
552 WebPageProxy* webPage = nullptr;
553 for (auto* page : m_pageMap.keys()) {
554 if (page->pageID() == pageID) {
555 webPage = page;
556 break;
557 }
558 }
559 if (!webPage)
560 return;
561
562 surface->setWebPage(webPage);
563 m_pageMap.set(webPage, makeWeakPtr(*surface));
564}
565
566void WaylandCompositor::registerWebPage(WebPageProxy& webPage)
567{
568 m_pageMap.add(&webPage, nullptr);
569}
570
571void WaylandCompositor::unregisterWebPage(WebPageProxy& webPage)
572{
573 if (WeakPtr<Surface> surface = m_pageMap.take(&webPage))
574 surface->setWebPage(nullptr);
575}
576
577} // namespace WebKit
578
579#endif // PLATFORM(WAYLAND) && USE(EGL) && !USE(WPE_RENDERER)
580