[GTK] Avoid including egl.h headers in internal headers
authorcarlosgc@webkit.org <carlosgc@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 20 Oct 2016 12:37:53 +0000 (12:37 +0000)
committercarlosgc@webkit.org <carlosgc@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 20 Oct 2016 12:37:53 +0000 (12:37 +0000)
https://bugs.webkit.org/show_bug.cgi?id=163722

Reviewed by Žan Doberšek.

egl.h includes eglplatform.h that decides the native types for the platform at compile time. However, we support
to build with X11 and Wayland at the same time and decide what to use at runtime. Currently GLContext.h includes
eglplatform.h after wayland-egl.h if Wayland is enabled. That means that the wayland native types are used by
default from all cpp files including GLContext.h. It currently works in X11 because we cast the value anyway and
for example EGLNativeWindowType is a pointer in Wayland that can be casted to unsigned long in X11 to represent
the X Window. This is very fragile in any case, we should avoid adding egl headers in our headers and only
include it in cpp files. But we also need to ensure we don't use X11 and Wayland in the same cpp file.

* PlatformGTK.cmake:
* platform/graphics/GLContext.cpp:
(WebCore::GLContext::createContextForWindow):
* platform/graphics/GLContext.h:
* platform/graphics/egl/GLContextEGL.cpp:
(WebCore::GLContextEGL::createWindowContext):
(WebCore::GLContextEGL::createContext):
(WebCore::GLContextEGL::~GLContextEGL):
* platform/graphics/egl/GLContextEGL.h:
* platform/graphics/egl/GLContextEGLWayland.cpp: Added.
(WebCore::GLContextEGL::GLContextEGL):
(WebCore::GLContextEGL::createWindowSurfaceWayland):
(WebCore::GLContextEGL::createWaylandContext):
(WebCore::GLContextEGL::destroyWaylandWindow):
* platform/graphics/egl/GLContextEGLX11.cpp: Added.
(WebCore::GLContextEGL::GLContextEGL):
(WebCore::GLContextEGL::createWindowSurfaceX11):
(WebCore::GLContextEGL::createPixmapContext):
* platform/graphics/glx/GLContextGLX.cpp:
(WebCore::GLContextGLX::createWindowContext):
(WebCore::GLContextGLX::createContext):
(WebCore::GLContextGLX::GLContextGLX):
* platform/graphics/glx/GLContextGLX.h:
* platform/graphics/wayland/PlatformDisplayWayland.cpp:
* platform/graphics/x11/PlatformDisplayX11.cpp:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207615 268f45cc-cd09-0410-ab3c-d52691b4dbfc

12 files changed:
Source/WebCore/ChangeLog
Source/WebCore/PlatformGTK.cmake
Source/WebCore/platform/graphics/GLContext.cpp
Source/WebCore/platform/graphics/GLContext.h
Source/WebCore/platform/graphics/egl/GLContextEGL.cpp
Source/WebCore/platform/graphics/egl/GLContextEGL.h
Source/WebCore/platform/graphics/egl/GLContextEGLWayland.cpp [new file with mode: 0644]
Source/WebCore/platform/graphics/egl/GLContextEGLX11.cpp [new file with mode: 0644]
Source/WebCore/platform/graphics/glx/GLContextGLX.cpp
Source/WebCore/platform/graphics/glx/GLContextGLX.h
Source/WebCore/platform/graphics/wayland/PlatformDisplayWayland.cpp
Source/WebCore/platform/graphics/x11/PlatformDisplayX11.cpp

index d8e80a3..f418050 100644 (file)
@@ -1,5 +1,46 @@
 2016-10-20  Carlos Garcia Campos  <cgarcia@igalia.com>
 
+        [GTK] Avoid including egl.h headers in internal headers
+        https://bugs.webkit.org/show_bug.cgi?id=163722
+
+        Reviewed by Žan Doberšek.
+
+        egl.h includes eglplatform.h that decides the native types for the platform at compile time. However, we support
+        to build with X11 and Wayland at the same time and decide what to use at runtime. Currently GLContext.h includes
+        eglplatform.h after wayland-egl.h if Wayland is enabled. That means that the wayland native types are used by
+        default from all cpp files including GLContext.h. It currently works in X11 because we cast the value anyway and
+        for example EGLNativeWindowType is a pointer in Wayland that can be casted to unsigned long in X11 to represent
+        the X Window. This is very fragile in any case, we should avoid adding egl headers in our headers and only
+        include it in cpp files. But we also need to ensure we don't use X11 and Wayland in the same cpp file.
+
+        * PlatformGTK.cmake:
+        * platform/graphics/GLContext.cpp:
+        (WebCore::GLContext::createContextForWindow):
+        * platform/graphics/GLContext.h:
+        * platform/graphics/egl/GLContextEGL.cpp:
+        (WebCore::GLContextEGL::createWindowContext):
+        (WebCore::GLContextEGL::createContext):
+        (WebCore::GLContextEGL::~GLContextEGL):
+        * platform/graphics/egl/GLContextEGL.h:
+        * platform/graphics/egl/GLContextEGLWayland.cpp: Added.
+        (WebCore::GLContextEGL::GLContextEGL):
+        (WebCore::GLContextEGL::createWindowSurfaceWayland):
+        (WebCore::GLContextEGL::createWaylandContext):
+        (WebCore::GLContextEGL::destroyWaylandWindow):
+        * platform/graphics/egl/GLContextEGLX11.cpp: Added.
+        (WebCore::GLContextEGL::GLContextEGL):
+        (WebCore::GLContextEGL::createWindowSurfaceX11):
+        (WebCore::GLContextEGL::createPixmapContext):
+        * platform/graphics/glx/GLContextGLX.cpp:
+        (WebCore::GLContextGLX::createWindowContext):
+        (WebCore::GLContextGLX::createContext):
+        (WebCore::GLContextGLX::GLContextGLX):
+        * platform/graphics/glx/GLContextGLX.h:
+        * platform/graphics/wayland/PlatformDisplayWayland.cpp:
+        * platform/graphics/x11/PlatformDisplayX11.cpp:
+
+2016-10-20  Carlos Garcia Campos  <cgarcia@igalia.com>
+
         [GTK] Avoid strstr() when checking (E)GL extensions
         https://bugs.webkit.org/show_bug.cgi?id=161958
 
index 16edad4..baaa5c2 100644 (file)
@@ -126,6 +126,8 @@ list(APPEND WebCore_SOURCES
     platform/graphics/cairo/TransformationMatrixCairo.cpp
 
     platform/graphics/egl/GLContextEGL.cpp
+    platform/graphics/egl/GLContextEGLWayland.cpp
+    platform/graphics/egl/GLContextEGLX11.cpp
 
     platform/graphics/freetype/FontCacheFreeType.cpp
     platform/graphics/freetype/FontCustomPlatformDataFreeType.cpp
index 6fda631..c199781 100644 (file)
@@ -84,12 +84,7 @@ std::unique_ptr<GLContext> GLContext::createContextForWindow(GLNativeWindowType
 #endif
 
 #if USE(GLX)
-#if PLATFORM(WAYLAND) // Building both X11 and Wayland targets
-    XID GLXWindowHandle = reinterpret_cast<XID>(windowHandle);
-#else
-    XID GLXWindowHandle = static_cast<XID>(windowHandle);
-#endif
-    if (auto glxContext = GLContextGLX::createContext(GLXWindowHandle, display))
+    if (auto glxContext = GLContextGLX::createContext(windowHandle, display))
         return WTFMove(glxContext);
 #endif
 #if USE(EGL)
index b41170b..576ccad 100644 (file)
 #if USE(EGL) && !PLATFORM(GTK)
 #include "eglplatform.h"
 typedef EGLNativeWindowType GLNativeWindowType;
-#elif PLATFORM(GTK) && PLATFORM(WAYLAND) && !defined(GTK_API_VERSION_2)
-#include <wayland-egl.h>
-#include <EGL/eglplatform.h>
-typedef EGLNativeWindowType GLNativeWindowType;
 #else
 typedef uint64_t GLNativeWindowType;
 #endif
index 1948f2e..a086efa 100644 (file)
@@ -22,6 +22,8 @@
 #if USE(EGL)
 
 #include "GraphicsContext3D.h"
+#include "PlatformDisplay.h"
+#include <EGL/egl.h>
 
 #if USE(CAIRO)
 #include <cairo.h>
 #include "OpenGLShims.h"
 #endif
 
-#if PLATFORM(X11)
-#include "PlatformDisplayX11.h"
-#include "XErrorTrapper.h"
-#include "XUniquePtr.h"
-#include <X11/Xlib.h>
-#endif
-
-#if PLATFORM(WAYLAND)
-#include "PlatformDisplayWayland.h"
-#include <wayland-egl.h>
-#endif
-
 #if ENABLE(ACCELERATED_2D_CANVAS)
 // cairo-gl.h includes some definitions from GLX that conflict with
 // the ones provided by us. Since GLContextEGL doesn't use any GLX
@@ -103,7 +93,7 @@ bool GLContextEGL::getEGLConfig(EGLDisplay display, EGLConfig* config, EGLSurfac
     return eglChooseConfig(display, attributeList, config, 1, &numberConfigsReturned) && numberConfigsReturned;
 }
 
-std::unique_ptr<GLContextEGL> GLContextEGL::createWindowContext(EGLNativeWindowType window, PlatformDisplay& platformDisplay, EGLContext sharingContext)
+std::unique_ptr<GLContextEGL> GLContextEGL::createWindowContext(GLNativeWindowType window, PlatformDisplay& platformDisplay, EGLContext sharingContext)
 {
     EGLDisplay display = platformDisplay.eglDisplay();
     EGLConfig config;
@@ -114,7 +104,19 @@ std::unique_ptr<GLContextEGL> GLContextEGL::createWindowContext(EGLNativeWindowT
     if (context == EGL_NO_CONTEXT)
         return nullptr;
 
-    EGLSurface surface = eglCreateWindowSurface(display, config, window, 0);
+    EGLSurface surface = EGL_NO_SURFACE;
+#if PLATFORM(GTK)
+#if PLATFORM(X11)
+    if (platformDisplay.type() == PlatformDisplay::Type::X11)
+        surface = createWindowSurfaceX11(display, config, window);
+#endif
+#if PLATFORM(WAYLAND)
+    if (platformDisplay.type() == PlatformDisplay::Type::Wayland)
+        surface = createWindowSurfaceWayland(display, config, window);
+#endif
+#else
+    surface = eglCreateWindowSurface(display, config, static_cast<EGLNativeWindowType>(window), nullptr);
+#endif
     if (surface == EGL_NO_SURFACE) {
         eglDestroyContext(display, context);
         return nullptr;
@@ -165,90 +167,7 @@ std::unique_ptr<GLContextEGL> GLContextEGL::createSurfacelessContext(PlatformDis
     return std::unique_ptr<GLContextEGL>(new GLContextEGL(platformDisplay, context, EGL_NO_SURFACE, Surfaceless));
 }
 
-#if PLATFORM(X11)
-std::unique_ptr<GLContextEGL> GLContextEGL::createPixmapContext(PlatformDisplay& platformDisplay, EGLContext sharingContext)
-{
-    EGLDisplay display = platformDisplay.eglDisplay();
-    EGLConfig config;
-    if (!getEGLConfig(display, &config, PixmapSurface))
-        return nullptr;
-
-    EGLContext context = eglCreateContext(display, config, sharingContext, gContextAttributes);
-    if (context == EGL_NO_CONTEXT)
-        return nullptr;
-
-    EGLint visualId;
-    if (!eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &visualId)) {
-        eglDestroyContext(display, context);
-        return nullptr;
-    }
-
-    Display* x11Display = downcast<PlatformDisplayX11>(platformDisplay).native();
-
-    XVisualInfo visualInfo;
-    visualInfo.visualid = visualId;
-    int numVisuals = 0;
-    XUniquePtr<XVisualInfo> visualInfoList(XGetVisualInfo(x11Display, VisualIDMask, &visualInfo, &numVisuals));
-    if (!visualInfoList || !numVisuals) {
-        eglDestroyContext(display, context);
-        return nullptr;
-    }
-
-    // We are using VisualIDMask so there must be only one.
-    ASSERT(numVisuals == 1);
-    XUniquePixmap pixmap = XCreatePixmap(x11Display, DefaultRootWindow(x11Display), 1, 1, visualInfoList.get()[0].depth);
-    if (!pixmap) {
-        eglDestroyContext(display, context);
-        return nullptr;
-    }
-
-    // Some drivers fail to create the surface producing BadDrawable X error and the default XError handler normally aborts.
-    // However, if the X error is ignored, eglCreatePixmapSurface() ends up returning a surface and we can continue creating
-    // the context. Since this is an offscreen context, it doesn't matter if the pixmap used is not valid because we never do
-    // swap buffers. So, we use a custom XError handler here that ignores BadDrawable errors and only warns about any other
-    // errors without aborting in any case.
-    XErrorTrapper trapper(x11Display, XErrorTrapper::Policy::Warn, { BadDrawable });
-    EGLSurface surface = eglCreatePixmapSurface(display, config, reinterpret_cast<EGLNativePixmapType>(pixmap.get()), 0);
-    if (surface == EGL_NO_SURFACE) {
-        eglDestroyContext(display, context);
-        return nullptr;
-    }
-
-    return std::unique_ptr<GLContextEGL>(new GLContextEGL(platformDisplay, context, surface, WTFMove(pixmap)));
-}
-#endif // PLATFORM(X11)
-
-#if PLATFORM(WAYLAND)
-std::unique_ptr<GLContextEGL> GLContextEGL::createWaylandContext(PlatformDisplay& platformDisplay, EGLContext sharingContext)
-{
-    EGLDisplay display = platformDisplay.eglDisplay();
-    EGLConfig config;
-    if (!getEGLConfig(display, &config, WindowSurface))
-        return nullptr;
-
-    EGLContext context = eglCreateContext(display, config, sharingContext, gContextAttributes);
-    if (context == EGL_NO_CONTEXT)
-        return nullptr;
-
-    WlUniquePtr<struct wl_surface> wlSurface(downcast<PlatformDisplayWayland>(platformDisplay).createSurface());
-    if (!wlSurface) {
-        eglDestroyContext(display, context);
-        return nullptr;
-    }
-
-    EGLNativeWindowType window = wl_egl_window_create(wlSurface.get(), 1, 1);
-    EGLSurface surface = eglCreateWindowSurface(display, config, window, 0);
-    if (surface == EGL_NO_SURFACE) {
-        eglDestroyContext(display, context);
-        wl_egl_window_destroy(window);
-        return nullptr;
-    }
-
-    return std::unique_ptr<GLContextEGL>(new GLContextEGL(platformDisplay, context, surface, WTFMove(wlSurface), window));
-}
-#endif
-
-std::unique_ptr<GLContextEGL> GLContextEGL::createContext(EGLNativeWindowType window, PlatformDisplay& platformDisplay)
+std::unique_ptr<GLContextEGL> GLContextEGL::createContext(GLNativeWindowType window, PlatformDisplay& platformDisplay)
 {
     if (platformDisplay.eglDisplay() == EGL_NO_DISPLAY)
         return nullptr;
@@ -311,29 +230,6 @@ GLContextEGL::GLContextEGL(PlatformDisplay& display, EGLContext context, EGLSurf
     ASSERT(type == Surfaceless || surface != EGL_NO_SURFACE);
 }
 
-#if PLATFORM(X11)
-GLContextEGL::GLContextEGL(PlatformDisplay& display, EGLContext context, EGLSurface surface, XUniquePixmap&& pixmap)
-    : GLContext(display)
-    , m_context(context)
-    , m_surface(surface)
-    , m_type(PixmapSurface)
-    , m_pixmap(WTFMove(pixmap))
-{
-}
-#endif
-
-#if PLATFORM(WAYLAND)
-GLContextEGL::GLContextEGL(PlatformDisplay& display, EGLContext context, EGLSurface surface, WlUniquePtr<struct wl_surface>&& wlSurface, EGLNativeWindowType wlWindow)
-    : GLContext(display)
-    , m_context(context)
-    , m_surface(surface)
-    , m_type(WindowSurface)
-    , m_wlSurface(WTFMove(wlSurface))
-    , m_wlWindow(wlWindow)
-{
-}
-#endif
-
 GLContextEGL::~GLContextEGL()
 {
 #if USE(CAIRO)
@@ -352,8 +248,7 @@ GLContextEGL::~GLContextEGL()
         eglDestroySurface(display, m_surface);
 
 #if PLATFORM(WAYLAND)
-    if (m_wlWindow)
-        wl_egl_window_destroy(m_wlWindow);
+    destroyWaylandWindow();
 #endif
 }
 
index 702535c..e5a3359 100644 (file)
  *  Boston, MA 02110-1301 USA
  */
 
-#ifndef GLContextEGL_h
-#define GLContextEGL_h
+#pragma once
 
 #if USE(EGL)
 
 #include "GLContext.h"
-#include <EGL/egl.h>
 
 #if PLATFORM(X11)
 #include "XUniqueResource.h"
 
 #if PLATFORM(WAYLAND)
 #include "WlUniquePtr.h"
+struct wl_egl_window;
 #endif
 
+typedef void *EGLConfig;
+typedef void *EGLContext;
+typedef void *EGLDisplay;
+typedef void *EGLSurface;
+
 namespace WebCore {
 
 class GLContextEGL final : public GLContext {
     WTF_MAKE_NONCOPYABLE(GLContextEGL);
 public:
-    static std::unique_ptr<GLContextEGL> createContext(EGLNativeWindowType, PlatformDisplay&);
+    static std::unique_ptr<GLContextEGL> createContext(GLNativeWindowType, PlatformDisplay&);
     static std::unique_ptr<GLContextEGL> createSharingContext(PlatformDisplay&);
 
     virtual ~GLContextEGL();
 
+private:
     bool makeContextCurrent() override;
     void swapBuffers() override;
     void waitNative() override;
@@ -58,7 +63,6 @@ public:
     PlatformGraphicsContext3D platformContext() override;
 #endif
 
-private:
     enum EGLSurfaceType { PbufferSurface, WindowSurface, PixmapSurface, Surfaceless };
 
     GLContextEGL(PlatformDisplay&, EGLContext, EGLSurface, EGLSurfaceType);
@@ -66,23 +70,26 @@ private:
     GLContextEGL(PlatformDisplay&, EGLContext, EGLSurface, XUniquePixmap&&);
 #endif
 #if PLATFORM(WAYLAND)
-    GLContextEGL(PlatformDisplay&, EGLContext, EGLSurface, WlUniquePtr<struct wl_surface>&&, EGLNativeWindowType);
+    GLContextEGL(PlatformDisplay&, EGLContext, EGLSurface, WlUniquePtr<struct wl_surface>&&, struct wl_egl_window*);
+    void destroyWaylandWindow();
 #endif
 
-    static std::unique_ptr<GLContextEGL> createWindowContext(EGLNativeWindowType, PlatformDisplay&, EGLContext sharingContext = EGL_NO_CONTEXT);
-    static std::unique_ptr<GLContextEGL> createPbufferContext(PlatformDisplay&, EGLContext sharingContext = EGL_NO_CONTEXT);
-    static std::unique_ptr<GLContextEGL> createSurfacelessContext(PlatformDisplay&, EGLContext sharingContext = EGL_NO_CONTEXT);
+    static std::unique_ptr<GLContextEGL> createWindowContext(GLNativeWindowType, PlatformDisplay&, EGLContext sharingContext = nullptr);
+    static std::unique_ptr<GLContextEGL> createPbufferContext(PlatformDisplay&, EGLContext sharingContext = nullptr);
+    static std::unique_ptr<GLContextEGL> createSurfacelessContext(PlatformDisplay&, EGLContext sharingContext = nullptr);
 #if PLATFORM(X11)
-    static std::unique_ptr<GLContextEGL> createPixmapContext(PlatformDisplay&, EGLContext sharingContext = EGL_NO_CONTEXT);
+    static std::unique_ptr<GLContextEGL> createPixmapContext(PlatformDisplay&, EGLContext sharingContext = nullptr);
+    static EGLSurface createWindowSurfaceX11(EGLDisplay, EGLConfig, GLNativeWindowType);
 #endif
 #if PLATFORM(WAYLAND)
-    static std::unique_ptr<GLContextEGL> createWaylandContext(PlatformDisplay&, EGLContext sharingContext = EGL_NO_CONTEXT);
+    static std::unique_ptr<GLContextEGL> createWaylandContext(PlatformDisplay&, EGLContext sharingContext = nullptr);
+    static EGLSurface createWindowSurfaceWayland(EGLDisplay, EGLConfig, GLNativeWindowType);
 #endif
 
     static bool getEGLConfig(EGLDisplay, EGLConfig*, EGLSurfaceType);
 
-    EGLContext m_context { EGL_NO_CONTEXT };
-    EGLSurface m_surface { EGL_NO_SURFACE };
+    EGLContext m_context { nullptr };
+    EGLSurface m_surface { nullptr };
     EGLSurfaceType m_type;
 #if PLATFORM(X11)
     XUniquePixmap m_pixmap;
@@ -99,5 +106,3 @@ private:
 } // namespace WebCore
 
 #endif // USE(EGL)
-
-#endif // GLContextEGL_h
diff --git a/Source/WebCore/platform/graphics/egl/GLContextEGLWayland.cpp b/Source/WebCore/platform/graphics/egl/GLContextEGLWayland.cpp
new file mode 100644 (file)
index 0000000..a0ed56f
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2016 Igalia, S.L.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "config.h"
+#include "GLContextEGL.h"
+
+#if USE(EGL) && PLATFORM(WAYLAND)
+
+#include "PlatformDisplayWayland.h"
+// These includes need to be in this order because wayland-egl.h defines WL_EGL_PLATFORM
+// and egl.h checks that to decide whether it's Wayland platform.
+#include <wayland-egl.h>
+#include <EGL/egl.h>
+
+namespace WebCore {
+
+GLContextEGL::GLContextEGL(PlatformDisplay& display, EGLContext context, EGLSurface surface, WlUniquePtr<struct wl_surface>&& wlSurface, struct wl_egl_window* wlWindow)
+    : GLContext(display)
+    , m_context(context)
+    , m_surface(surface)
+    , m_type(WindowSurface)
+    , m_wlSurface(WTFMove(wlSurface))
+    , m_wlWindow(wlWindow)
+{
+}
+
+EGLSurface GLContextEGL::createWindowSurfaceWayland(EGLDisplay display, EGLConfig config, GLNativeWindowType window)
+{
+    return eglCreateWindowSurface(display, config, reinterpret_cast<EGLNativeWindowType>(window), nullptr);
+}
+
+std::unique_ptr<GLContextEGL> GLContextEGL::createWaylandContext(PlatformDisplay& platformDisplay, EGLContext sharingContext)
+{
+    EGLDisplay display = platformDisplay.eglDisplay();
+    EGLConfig config;
+    if (!getEGLConfig(display, &config, WindowSurface))
+        return nullptr;
+
+    static const EGLint contextAttributes[] = {
+#if USE(OPENGL_ES_2)
+        EGL_CONTEXT_CLIENT_VERSION, 2,
+#endif
+        EGL_NONE
+    };
+
+    EGLContext context = eglCreateContext(display, config, sharingContext, contextAttributes);
+    if (context == EGL_NO_CONTEXT)
+        return nullptr;
+
+    WlUniquePtr<struct wl_surface> wlSurface(downcast<PlatformDisplayWayland>(platformDisplay).createSurface());
+    if (!wlSurface) {
+        eglDestroyContext(display, context);
+        return nullptr;
+    }
+
+    EGLNativeWindowType window = wl_egl_window_create(wlSurface.get(), 1, 1);
+    EGLSurface surface = eglCreateWindowSurface(display, config, window, 0);
+    if (surface == EGL_NO_SURFACE) {
+        eglDestroyContext(display, context);
+        wl_egl_window_destroy(window);
+        return nullptr;
+    }
+
+    return std::unique_ptr<GLContextEGL>(new GLContextEGL(platformDisplay, context, surface, WTFMove(wlSurface), window));
+}
+
+void GLContextEGL::destroyWaylandWindow()
+{
+    if (m_wlWindow)
+        wl_egl_window_destroy(m_wlWindow);
+}
+
+} // namespace WebCore
+
+#endif //  USE(EGL) && PLATFORM(WAYLAND)
diff --git a/Source/WebCore/platform/graphics/egl/GLContextEGLX11.cpp b/Source/WebCore/platform/graphics/egl/GLContextEGLX11.cpp
new file mode 100644 (file)
index 0000000..8fdd4ca
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2016 Igalia, S.L.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "config.h"
+#include "GLContextEGL.h"
+
+#if USE(EGL) && PLATFORM(X11)
+#include "PlatformDisplayX11.h"
+#include "XErrorTrapper.h"
+#include "XUniquePtr.h"
+#include <EGL/egl.h>
+#include <X11/Xlib.h>
+
+namespace WebCore {
+
+GLContextEGL::GLContextEGL(PlatformDisplay& display, EGLContext context, EGLSurface surface, XUniquePixmap&& pixmap)
+    : GLContext(display)
+    , m_context(context)
+    , m_surface(surface)
+    , m_type(PixmapSurface)
+    , m_pixmap(WTFMove(pixmap))
+{
+}
+
+EGLSurface GLContextEGL::createWindowSurfaceX11(EGLDisplay display, EGLConfig config, GLNativeWindowType window)
+{
+    return eglCreateWindowSurface(display, config, static_cast<EGLNativeWindowType>(window), nullptr);
+}
+
+std::unique_ptr<GLContextEGL> GLContextEGL::createPixmapContext(PlatformDisplay& platformDisplay, EGLContext sharingContext)
+{
+    EGLDisplay display = platformDisplay.eglDisplay();
+    EGLConfig config;
+    if (!getEGLConfig(display, &config, PixmapSurface))
+        return nullptr;
+
+    static const EGLint contextAttributes[] = {
+#if USE(OPENGL_ES_2)
+        EGL_CONTEXT_CLIENT_VERSION, 2,
+#endif
+        EGL_NONE
+    };
+    EGLContext context = eglCreateContext(display, config, sharingContext, contextAttributes);
+    if (context == EGL_NO_CONTEXT)
+        return nullptr;
+
+    EGLint visualId;
+    if (!eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &visualId)) {
+        eglDestroyContext(display, context);
+        return nullptr;
+    }
+
+    Display* x11Display = downcast<PlatformDisplayX11>(platformDisplay).native();
+
+    XVisualInfo visualInfo;
+    visualInfo.visualid = visualId;
+    int numVisuals = 0;
+    XUniquePtr<XVisualInfo> visualInfoList(XGetVisualInfo(x11Display, VisualIDMask, &visualInfo, &numVisuals));
+    if (!visualInfoList || !numVisuals) {
+        eglDestroyContext(display, context);
+        return nullptr;
+    }
+
+    // We are using VisualIDMask so there must be only one.
+    ASSERT(numVisuals == 1);
+    XUniquePixmap pixmap = XCreatePixmap(x11Display, DefaultRootWindow(x11Display), 1, 1, visualInfoList.get()[0].depth);
+    if (!pixmap) {
+        eglDestroyContext(display, context);
+        return nullptr;
+    }
+
+    // Some drivers fail to create the surface producing BadDrawable X error and the default XError handler normally aborts.
+    // However, if the X error is ignored, eglCreatePixmapSurface() ends up returning a surface and we can continue creating
+    // the context. Since this is an offscreen context, it doesn't matter if the pixmap used is not valid because we never do
+    // swap buffers. So, we use a custom XError handler here that ignores BadDrawable errors and only warns about any other
+    // errors without aborting in any case.
+    XErrorTrapper trapper(x11Display, XErrorTrapper::Policy::Warn, { BadDrawable });
+    EGLSurface surface = eglCreatePixmapSurface(display, config, reinterpret_cast<EGLNativePixmapType>(pixmap.get()), 0);
+    if (surface == EGL_NO_SURFACE) {
+        eglDestroyContext(display, context);
+        return nullptr;
+    }
+
+    return std::unique_ptr<GLContextEGL>(new GLContextEGL(platformDisplay, context, surface, WTFMove(pixmap)));
+}
+
+} // namespace WebCore
+
+#endif // USE(EGL) && PLATFORM(X11)
index e71c4f2..9c2ed3d 100644 (file)
@@ -52,11 +52,11 @@ static bool hasSGISwapControlExtension(Display* display)
     return !!glXSwapIntervalSGI;
 }
 
-std::unique_ptr<GLContextGLX> GLContextGLX::createWindowContext(XID window, PlatformDisplay& platformDisplay, GLXContext sharingContext)
+std::unique_ptr<GLContextGLX> GLContextGLX::createWindowContext(GLNativeWindowType window, PlatformDisplay& platformDisplay, GLXContext sharingContext)
 {
     Display* display = downcast<PlatformDisplayX11>(platformDisplay).native();
     XWindowAttributes attributes;
-    if (!XGetWindowAttributes(display, window, &attributes))
+    if (!XGetWindowAttributes(display, static_cast<Window>(window), &attributes))
         return nullptr;
 
     XVisualInfo visualInfo;
@@ -135,7 +135,7 @@ std::unique_ptr<GLContextGLX> GLContextGLX::createPixmapContext(PlatformDisplay&
     return std::unique_ptr<GLContextGLX>(new GLContextGLX(platformDisplay, WTFMove(context), WTFMove(pixmap), WTFMove(glxPixmap)));
 }
 
-std::unique_ptr<GLContextGLX> GLContextGLX::createContext(XID window, PlatformDisplay& platformDisplay)
+std::unique_ptr<GLContextGLX> GLContextGLX::createContext(GLNativeWindowType window, PlatformDisplay& platformDisplay)
 {
     GLXContext glxSharingContext = platformDisplay.sharingGLContext() ? static_cast<GLContextGLX*>(platformDisplay.sharingGLContext())->m_context.get() : nullptr;
     auto context = window ? createWindowContext(window, platformDisplay, glxSharingContext) : nullptr;
@@ -155,11 +155,11 @@ std::unique_ptr<GLContextGLX> GLContextGLX::createSharingContext(PlatformDisplay
     return context;
 }
 
-GLContextGLX::GLContextGLX(PlatformDisplay& display, XUniqueGLXContext&& context, XID window)
+GLContextGLX::GLContextGLX(PlatformDisplay& display, XUniqueGLXContext&& context, GLNativeWindowType window)
     : GLContext(display)
     , m_x11Display(downcast<PlatformDisplayX11>(m_display).native())
     , m_context(WTFMove(context))
-    , m_window(window)
+    , m_window(static_cast<Window>(window))
 {
 }
 
index be3c23b..ca24024 100644 (file)
@@ -17,8 +17,7 @@
  *  Boston, MA 02110-1301 USA
  */
 
-#ifndef GLContextGLX_h
-#define GLContextGLX_h
+#pragma once
 
 #if USE(GLX)
 
@@ -27,7 +26,7 @@
 #include "XUniqueResource.h"
 
 typedef unsigned char GLubyte;
-typedef unsigned long XID;
+typedef unsigned long Window;
 typedef void* ContextKeyType;
 typedef struct _XDisplay Display;
 
@@ -36,11 +35,12 @@ namespace WebCore {
 class GLContextGLX final : public GLContext {
     WTF_MAKE_NONCOPYABLE(GLContextGLX);
 public:
-    static std::unique_ptr<GLContextGLX> createContext(XID window, PlatformDisplay&);
+    static std::unique_ptr<GLContextGLX> createContext(GLNativeWindowType, PlatformDisplay&);
     static std::unique_ptr<GLContextGLX> createSharingContext(PlatformDisplay&);
 
     virtual ~GLContextGLX();
 
+private:
     bool makeContextCurrent() override;
     void swapBuffers() override;
     void waitNative() override;
@@ -54,18 +54,17 @@ public:
     PlatformGraphicsContext3D platformContext() override;
 #endif
 
-private:
-    GLContextGLX(PlatformDisplay&, XUniqueGLXContext&&, XID);
+    GLContextGLX(PlatformDisplay&, XUniqueGLXContext&&, GLNativeWindowType);
     GLContextGLX(PlatformDisplay&, XUniqueGLXContext&&, XUniqueGLXPbuffer&&);
     GLContextGLX(PlatformDisplay&, XUniqueGLXContext&&, XUniquePixmap&&, XUniqueGLXPixmap&&);
 
-    static std::unique_ptr<GLContextGLX> createWindowContext(XID window, PlatformDisplay&, GLXContext sharingContext = nullptr);
+    static std::unique_ptr<GLContextGLX> createWindowContext(GLNativeWindowType, PlatformDisplay&, GLXContext sharingContext = nullptr);
     static std::unique_ptr<GLContextGLX> createPbufferContext(PlatformDisplay&, GLXContext sharingContext = nullptr);
     static std::unique_ptr<GLContextGLX> createPixmapContext(PlatformDisplay&, GLXContext sharingContext = nullptr);
 
     Display* m_x11Display { nullptr };
     XUniqueGLXContext m_context;
-    XID m_window { 0 };
+    Window m_window { 0 };
     XUniqueGLXPbuffer m_pbuffer;
     XUniquePixmap m_pixmap;
     XUniqueGLXPixmap m_glxPixmap;
@@ -76,4 +75,3 @@ private:
 
 #endif // USE(GLX)
 
-#endif // GLContextGLX_h
index 47924a7..6c5004a 100644 (file)
 
 #include "GLContextEGL.h"
 #include <cstring>
+// These includes need to be in this order because wayland-egl.h defines WL_EGL_PLATFORM
+// and egl.h checks that to decide whether it's Wayland platform.
 #include <wayland-egl.h>
+#include <EGL/egl.h>
 #include <wtf/Assertions.h>
 
 namespace WebCore {
index c705997..1ab856b 100644 (file)
@@ -26,6 +26,8 @@
 #include "config.h"
 #include "PlatformDisplayX11.h"
 
+#include "GLContext.h"
+
 #if PLATFORM(X11)
 #include <X11/Xlib.h>
 #include <X11/extensions/Xcomposite.h>
 
 #if USE(EGL)
 #include <EGL/egl.h>
-#include <EGL/eglplatform.h>
 #endif
 
-// FIXME: this needs to be here, after eglplatform.h, to avoid EGLNativeDisplayType to be defined as wl_display.
-// Since we support Wayland and X11 to be built at the same time, but eglplatform.h defines are decided at compile time
-// we need to ensure we only include eglplatform.h from X11 or Wayland specific files.
-#include "GLContext.h"
-
 namespace WebCore {
 
 PlatformDisplayX11::PlatformDisplayX11()