[GTK] Fix PlatformDisplayWayland construction error, implement the destructor
[WebKit-https.git] / Source / WebCore / platform / graphics / wayland / PlatformDisplayWayland.cpp
1 /*
2  * Copyright (C) 2014 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 "PlatformDisplayWayland.h"
28
29 #if PLATFORM(WAYLAND)
30
31 #include "GLContextEGL.h"
32 #include "WaylandSurface.h"
33 #include <cstring>
34 #include <glib.h>
35
36 namespace WebCore {
37
38 const struct wl_registry_listener PlatformDisplayWayland::m_registryListener = {
39     PlatformDisplayWayland::globalCallback,
40     PlatformDisplayWayland::globalRemoveCallback
41 };
42
43 void PlatformDisplayWayland::globalCallback(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t)
44 {
45     auto display = static_cast<PlatformDisplayWayland*>(data);
46     if (!std::strcmp(interface, "wl_compositor"))
47         display->m_compositor = static_cast<struct wl_compositor*>(wl_registry_bind(registry, name, &wl_compositor_interface, 1));
48     else if (!std::strcmp(interface, "wl_webkitgtk"))
49         display->m_webkitgtk = static_cast<struct wl_webkitgtk*>(wl_registry_bind(registry, name, &wl_webkitgtk_interface, 1));
50 }
51
52 void PlatformDisplayWayland::globalRemoveCallback(void*, struct wl_registry*, uint32_t)
53 {
54     // FIXME: if this can happen without the UI Process getting shut down
55     // we should probably destroy our cached display instance.
56 }
57
58 std::unique_ptr<PlatformDisplayWayland> PlatformDisplayWayland::create()
59 {
60     struct wl_display* wlDisplay = wl_display_connect("webkitgtk-wayland-compositor-socket");
61     if (!wlDisplay)
62         return nullptr;
63
64     auto display = std::unique_ptr<PlatformDisplayWayland>(new PlatformDisplayWayland(wlDisplay));
65     if (!display->isInitialized())
66         return nullptr;
67
68     return display;
69 }
70
71 PlatformDisplayWayland::PlatformDisplayWayland(struct wl_display* wlDisplay)
72     : m_display(wlDisplay)
73     , m_registry(wl_display_get_registry(m_display))
74     , m_eglConfigChosen(false)
75 {
76     wl_registry_add_listener(m_registry, &m_registryListener, this);
77     wl_display_roundtrip(m_display);
78
79     static const EGLint configAttributes[] = {
80         EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
81         EGL_RED_SIZE, 1,
82         EGL_GREEN_SIZE, 1,
83         EGL_BLUE_SIZE, 1,
84         EGL_ALPHA_SIZE, 1,
85         EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
86         EGL_NONE
87     };
88
89     m_eglDisplay = eglGetDisplay(m_display);
90     PlatformDisplay::initializeEGLDisplay();
91     if (m_eglDisplay == EGL_NO_DISPLAY)
92         return;
93
94     EGLint numberOfConfigs;
95     if (!eglChooseConfig(m_eglDisplay, configAttributes, &m_eglConfig, 1, &numberOfConfigs) || numberOfConfigs != 1) {
96         g_warning("PlatformDisplayWayland initialization: failed to find the desired EGL configuration.");
97         return;
98     }
99
100     m_eglConfigChosen = true;
101 }
102
103 PlatformDisplayWayland::~PlatformDisplayWayland()
104 {
105     if (m_webkitgtk)
106         wl_webkitgtk_destroy(m_webkitgtk);
107     if (m_compositor)
108         wl_compositor_destroy(m_compositor);
109     if (m_registry)
110         wl_registry_destroy(m_registry);
111     if (m_display)
112         wl_display_disconnect(m_display);
113 }
114
115 std::unique_ptr<WaylandSurface> PlatformDisplayWayland::createSurface(const IntSize& size, int widgetId)
116 {
117     struct wl_surface* wlSurface = wl_compositor_create_surface(m_compositor);
118     // We keep the minimum size at 1x1px since Mesa returns null values in wl_egl_window_create() for zero width or height.
119     EGLNativeWindowType nativeWindow = wl_egl_window_create(wlSurface, std::max(1, size.width()), std::max(1, size.height()));
120
121     wl_webkitgtk_set_surface_for_widget(m_webkitgtk, wlSurface, widgetId);
122     wl_display_roundtrip(m_display);
123
124     return std::make_unique<WaylandSurface>(wlSurface, nativeWindow);
125 }
126
127 std::unique_ptr<GLContextEGL> PlatformDisplayWayland::createSharingGLContext()
128 {
129     struct wl_surface* wlSurface = wl_compositor_create_surface(m_compositor);
130     EGLNativeWindowType nativeWindow = wl_egl_window_create(wlSurface, 1, 1);
131     return GLContextEGL::createWindowContext(nativeWindow, nullptr);
132 }
133
134 } // namespace WebCore
135
136 #endif // PLATFORM(WAYLAND)