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