[WPE] libepoxy headers can use EGL_CAST, which might not be defined by eglplatform.h
[WebKit-https.git] / Source / WebCore / platform / graphics / PlatformDisplay.cpp
1 /*
2  * Copyright (C) 2015 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  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "PlatformDisplay.h"
28
29 #include "GLContext.h"
30 #include <cstdlib>
31 #include <mutex>
32
33 #if PLATFORM(X11)
34 #include "PlatformDisplayX11.h"
35 #endif
36
37 #if PLATFORM(WAYLAND)
38 #include "PlatformDisplayWayland.h"
39 #endif
40
41 #if PLATFORM(WIN)
42 #include "PlatformDisplayWin.h"
43 #endif
44
45 #if PLATFORM(WPE)
46 #include "PlatformDisplayWPE.h"
47 #endif
48
49 #if PLATFORM(GTK)
50 #include <gdk/gdk.h>
51 #endif
52
53 #if PLATFORM(GTK) && PLATFORM(X11)
54 #include <gdk/gdkx.h>
55 #endif
56
57 #if PLATFORM(GTK) && PLATFORM(WAYLAND) && !defined(GTK_API_VERSION_2)
58 #include <gdk/gdkwayland.h>
59 #endif
60
61 #if USE(EGL)
62 #if USE(LIBEPOXY)
63 #include "EpoxyEGL.h"
64 #else
65 #include <EGL/egl.h>
66 #endif
67 #include <wtf/HashSet.h>
68 #include <wtf/NeverDestroyed.h>
69 #endif
70
71 namespace WebCore {
72
73 std::unique_ptr<PlatformDisplay> PlatformDisplay::createPlatformDisplay()
74 {
75 #if PLATFORM(GTK)
76 #if defined(GTK_API_VERSION_2)
77     return std::make_unique<PlatformDisplayX11>(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()));
78 #else
79     GdkDisplay* display = gdk_display_manager_get_default_display(gdk_display_manager_get());
80 #if PLATFORM(X11)
81     if (GDK_IS_X11_DISPLAY(display))
82         return std::make_unique<PlatformDisplayX11>(GDK_DISPLAY_XDISPLAY(display));
83 #endif
84 #if PLATFORM(WAYLAND)
85     if (GDK_IS_WAYLAND_DISPLAY(display))
86         return std::make_unique<PlatformDisplayWayland>(gdk_wayland_display_get_wl_display(display));
87 #endif
88 #endif
89 #elif PLATFORM(WIN)
90     return std::make_unique<PlatformDisplayWin>();
91 #endif
92
93 #if PLATFORM(WAYLAND)
94     if (auto platformDisplay = PlatformDisplayWayland::create())
95         return platformDisplay;
96 #endif
97
98 #if PLATFORM(X11)
99     if (auto platformDisplay = PlatformDisplayX11::create())
100         return platformDisplay;
101 #endif
102
103     // If at this point we still don't have a display, just create a fake display with no native.
104 #if PLATFORM(WAYLAND)
105     return std::make_unique<PlatformDisplayWayland>(nullptr);
106 #endif
107 #if PLATFORM(X11)
108     return std::make_unique<PlatformDisplayX11>(nullptr);
109 #endif
110
111 #if PLATFORM(WPE)
112     return std::make_unique<PlatformDisplayWPE>();
113 #endif
114
115     ASSERT_NOT_REACHED();
116     return nullptr;
117 }
118
119 PlatformDisplay& PlatformDisplay::sharedDisplay()
120 {
121     static std::once_flag onceFlag;
122 #if COMPILER(CLANG)
123 #pragma clang diagnostic push
124 #pragma clang diagnostic ignored "-Wexit-time-destructors"
125 #endif
126     static std::unique_ptr<PlatformDisplay> display;
127 #if COMPILER(CLANG)
128 #pragma clang diagnostic pop
129 #endif
130     std::call_once(onceFlag, []{
131         display = createPlatformDisplay();
132     });
133     return *display;
134 }
135
136 static PlatformDisplay* s_sharedDisplayForCompositing;
137
138 PlatformDisplay& PlatformDisplay::sharedDisplayForCompositing()
139 {
140     return s_sharedDisplayForCompositing ? *s_sharedDisplayForCompositing : sharedDisplay();
141 }
142
143 void PlatformDisplay::setSharedDisplayForCompositing(PlatformDisplay& display)
144 {
145     s_sharedDisplayForCompositing = &display;
146 }
147
148 PlatformDisplay::PlatformDisplay(NativeDisplayOwned displayOwned)
149     : m_nativeDisplayOwned(displayOwned)
150 #if USE(EGL)
151     , m_eglDisplay(EGL_NO_DISPLAY)
152 #endif
153 {
154 }
155
156 PlatformDisplay::~PlatformDisplay()
157 {
158 #if USE(EGL)
159     ASSERT(m_eglDisplay == EGL_NO_DISPLAY);
160 #endif
161 }
162
163 #if USE(EGL) || USE(GLX)
164 GLContext* PlatformDisplay::sharingGLContext()
165 {
166     if (!m_sharingGLContext)
167         m_sharingGLContext = GLContext::createSharingContext(*this);
168     return m_sharingGLContext.get();
169 }
170 #endif
171
172 #if USE(EGL)
173 static HashSet<PlatformDisplay*>& eglDisplays()
174 {
175     static NeverDestroyed<HashSet<PlatformDisplay*>> displays;
176     return displays;
177 }
178
179 EGLDisplay PlatformDisplay::eglDisplay() const
180 {
181     if (!m_eglDisplayInitialized)
182         const_cast<PlatformDisplay*>(this)->initializeEGLDisplay();
183     return m_eglDisplay;
184 }
185
186 bool PlatformDisplay::eglCheckVersion(int major, int minor) const
187 {
188     if (!m_eglDisplayInitialized)
189         const_cast<PlatformDisplay*>(this)->initializeEGLDisplay();
190
191     return (m_eglMajorVersion > major) || ((m_eglMajorVersion == major) && (m_eglMinorVersion >= minor));
192 }
193
194 void PlatformDisplay::initializeEGLDisplay()
195 {
196     m_eglDisplayInitialized = true;
197
198     if (m_eglDisplay == EGL_NO_DISPLAY) {
199         m_eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
200         if (m_eglDisplay == EGL_NO_DISPLAY)
201             return;
202     }
203
204     EGLint majorVersion, minorVersion;
205     if (eglInitialize(m_eglDisplay, &majorVersion, &minorVersion) == EGL_FALSE) {
206         LOG_ERROR("EGLDisplay Initialization failed.");
207         terminateEGLDisplay();
208         return;
209     }
210
211     m_eglMajorVersion = majorVersion;
212     m_eglMinorVersion = minorVersion;
213
214     eglDisplays().add(this);
215
216 #if !PLATFORM(WIN)
217     static bool eglAtexitHandlerInitialized = false;
218     if (!eglAtexitHandlerInitialized) {
219         // EGL registers atexit handlers to cleanup its global display list.
220         // Since the global PlatformDisplay instance is created before,
221         // when the PlatformDisplay destructor is called, EGL has already removed the
222         // display from the list, causing eglTerminate() to crash. So, here we register
223         // our own atexit handler, after EGL has been initialized and after the global
224         // instance has been created to ensure we call eglTerminate() before the other
225         // EGL atexit handlers and the PlatformDisplay destructor.
226         // See https://bugs.webkit.org/show_bug.cgi?id=157973.
227         eglAtexitHandlerInitialized = true;
228         std::atexit(shutDownEglDisplays);
229     }
230 #endif
231 }
232
233 void PlatformDisplay::terminateEGLDisplay()
234 {
235     m_sharingGLContext = nullptr;
236     ASSERT(m_eglDisplayInitialized);
237     if (m_eglDisplay == EGL_NO_DISPLAY)
238         return;
239     eglTerminate(m_eglDisplay);
240     m_eglDisplay = EGL_NO_DISPLAY;
241 }
242
243 void PlatformDisplay::shutDownEglDisplays()
244 {
245     while (!eglDisplays().isEmpty()) {
246         auto* display = eglDisplays().takeAny();
247         display->terminateEGLDisplay();
248     }
249 }
250
251 #endif // USE(EGL)
252
253 } // namespace WebCore