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