[WTF] Add makeUnique<T>, which ensures T is fast-allocated, makeUnique / makeUniqueWi...
[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/Extensions3DOpenGLES.h>
45 #else
46 #include <WebCore/Extensions3DOpenGL.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(PFNEGLQUERYWAYLANDBUFFERWL)
62 typedef EGLBoolean (*PFNEGLQUERYWAYLANDBUFFERWL) (EGLDisplay, struct wl_resource*, EGLint attribute, EGLint* value);
63 #endif
64
65 #if !defined(PFNEGLCREATEIMAGEKHRPROC)
66 typedef EGLImageKHR (*PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay, EGLContext, EGLenum target, EGLClientBuffer, const EGLint* attribList);
67 #endif
68
69 #if !defined(PFNEGLDESTROYIMAGEKHRPROC)
70 typedef EGLBoolean (*PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay, EGLImageKHR);
71 #endif
72
73 #if !defined(PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)
74 typedef void (*PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES);
75 #endif
76
77 static PFNEGLBINDWAYLANDDISPLAYWL eglBindWaylandDisplay;
78 static PFNEGLUNBINDWAYLANDDISPLAYWL eglUnbindWaylandDisplay;
79 static PFNEGLQUERYWAYLANDBUFFERWL eglQueryWaylandBuffer;
80 static PFNEGLCREATEIMAGEKHRPROC eglCreateImage;
81 static PFNEGLDESTROYIMAGEKHRPROC eglDestroyImage;
82 static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glImageTargetTexture2D;
83
84 WaylandCompositor& WaylandCompositor::singleton()
85 {
86     static NeverDestroyed<WaylandCompositor> waylandCompositor;
87     return waylandCompositor;
88 }
89
90 WaylandCompositor::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
100 WaylandCompositor::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
108 WaylandCompositor::Buffer::~Buffer()
109 {
110     wl_list_remove(&m_destroyListener.link);
111 }
112
113 void 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
120 void WaylandCompositor::Buffer::use()
121 {
122     m_busyCount++;
123 }
124
125 void WaylandCompositor::Buffer::unuse()
126 {
127     m_busyCount--;
128     if (!m_busyCount)
129         wl_resource_queue_event(m_resource, WL_BUFFER_RELEASE);
130 }
131
132 EGLImageKHR 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
137 IntSize 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
147 WaylandCompositor::Surface::Surface()
148     : m_image(EGL_NO_IMAGE_KHR)
149 {
150 }
151
152 WaylandCompositor::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
168 void 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
207 void 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
221 void 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
232 void 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
242 bool 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
258 void 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
267 void 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
276 void 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
301 static 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
357 static 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
374 static 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
387 bool 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 = makeUnique<Extensions3DOpenGLES>(nullptr,  false);
424 #else
425     std::unique_ptr<Extensions3DOpenGL> glExtensions = makeUnique<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
438 typedef struct {
439     GSource source;
440     gpointer fdTag;
441     struct wl_display* display;
442 } WaylandLoopSource;
443
444 static const unsigned waylandLoopSourceCondition = G_IO_IN | G_IO_HUP | G_IO_ERR;
445
446 static 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
475 static 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
488 WaylandCompositor::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
543 bool 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
550 void 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
566 void WaylandCompositor::registerWebPage(WebPageProxy& webPage)
567 {
568     m_pageMap.add(&webPage, nullptr);
569 }
570
571 void 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)