summaryrefslogtreecommitdiffstats
path: root/gfx/angle/src/libANGLE/renderer/gl/glx
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/src/libANGLE/renderer/gl/glx')
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp981
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.h151
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/glx/FBConfigCompatibility.md204
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.cpp398
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.h96
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.cpp143
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h64
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/glx/SurfaceGLX.h26
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.cpp244
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.h73
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/glx/functionsglx_typedefs.h52
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/glx/platform_glx.h190
12 files changed, 2622 insertions, 0 deletions
diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp b/gfx/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp
new file mode 100755
index 000000000..e98401d0a
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp
@@ -0,0 +1,981 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DisplayGLX.cpp: GLX implementation of egl::Display
+
+#include "libANGLE/renderer/gl/glx/DisplayGLX.h"
+
+#include <EGL/eglext.h>
+#include <algorithm>
+#include <cstring>
+#include <fstream>
+
+#include "common/debug.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h"
+#include "libANGLE/renderer/gl/glx/WindowSurfaceGLX.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+#include "libANGLE/renderer/gl/renderergl_utils.h"
+#include "third_party/libXNVCtrl/NVCtrl.h"
+#include "third_party/libXNVCtrl/NVCtrlLib.h"
+
+namespace
+{
+
+// Scan /etc/ati/amdpcsdb.default for "ReleaseVersion".
+// Return empty string on failing.
+egl::Error GetAMDDriverVersion(std::string *version)
+{
+ *version = "";
+
+ const char kAMDDriverInfoFileName[] = "/etc/ati/amdpcsdb.default";
+ std::ifstream file(kAMDDriverInfoFileName);
+
+ if (!file)
+ {
+ return egl::Error(EGL_SUCCESS);
+ }
+
+ std::string line;
+ while (std::getline(file, line))
+ {
+ static const char kReleaseVersion[] = "ReleaseVersion=";
+ if (line.compare(0, std::strlen(kReleaseVersion), kReleaseVersion) != 0)
+ {
+ continue;
+ }
+
+ const size_t begin = line.find_first_of("0123456789");
+ if (begin == std::string::npos)
+ {
+ continue;
+ }
+
+ const size_t end = line.find_first_not_of("0123456789.", begin);
+ if (end == std::string::npos)
+ {
+ *version = line.substr(begin);
+ }
+ else
+ {
+ *version = line.substr(begin, end - begin);
+ }
+ return egl::Error(EGL_SUCCESS);
+ }
+ return egl::Error(EGL_SUCCESS);
+}
+
+} // anonymous namespace
+
+namespace rx
+{
+
+static int IgnoreX11Errors(Display *, XErrorEvent *)
+{
+ return 0;
+}
+
+SwapControlData::SwapControlData()
+ : targetSwapInterval(0),
+ maxSwapInterval(-1),
+ currentSwapInterval(-1)
+{
+}
+
+class FunctionsGLGLX : public FunctionsGL
+{
+ public:
+ FunctionsGLGLX(PFNGETPROCPROC getProc)
+ : mGetProc(getProc)
+ {
+ }
+
+ ~FunctionsGLGLX() override {}
+
+ private:
+ void *loadProcAddress(const std::string &function) override
+ {
+ return reinterpret_cast<void*>(mGetProc(function.c_str()));
+ }
+
+ PFNGETPROCPROC mGetProc;
+};
+
+DisplayGLX::DisplayGLX()
+ : DisplayGL(),
+ mFunctionsGL(nullptr),
+ mRequestedVisual(-1),
+ mContextConfig(nullptr),
+ mContext(nullptr),
+ mDummyPbuffer(0),
+ mUsesNewXDisplay(false),
+ mIsMesa(false),
+ mHasMultisample(false),
+ mHasARBCreateContext(false),
+ mHasARBCreateContextProfile(false),
+ mHasARBCreateContextRobustness(false),
+ mHasEXTCreateContextES2Profile(false),
+ mSwapControl(SwapControl::Absent),
+ mMinSwapInterval(0),
+ mMaxSwapInterval(0),
+ mCurrentSwapInterval(-1),
+ mXDisplay(nullptr),
+ mEGLDisplay(nullptr)
+{
+}
+
+DisplayGLX::~DisplayGLX()
+{
+}
+
+egl::Error DisplayGLX::initialize(egl::Display *display)
+{
+ mEGLDisplay = display;
+ mXDisplay = display->getNativeDisplayId();
+ const auto &attribMap = display->getAttributeMap();
+
+ // ANGLE_platform_angle allows the creation of a default display
+ // using EGL_DEFAULT_DISPLAY (= nullptr). In this case just open
+ // the display specified by the DISPLAY environment variable.
+ if (mXDisplay == EGL_DEFAULT_DISPLAY)
+ {
+ mUsesNewXDisplay = true;
+ mXDisplay = XOpenDisplay(NULL);
+ if (!mXDisplay)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not open the default X display.");
+ }
+ }
+
+ std::string glxInitError;
+ if (!mGLX.initialize(mXDisplay, DefaultScreen(mXDisplay), &glxInitError))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, glxInitError.c_str());
+ }
+
+ mHasMultisample = mGLX.minorVersion > 3 || mGLX.hasExtension("GLX_ARB_multisample");
+ mHasARBCreateContext = mGLX.hasExtension("GLX_ARB_create_context");
+ mHasARBCreateContextProfile = mGLX.hasExtension("GLX_ARB_create_context_profile");
+ mHasARBCreateContextRobustness = mGLX.hasExtension("GLX_ARB_create_context_robustness");
+ mHasEXTCreateContextES2Profile = mGLX.hasExtension("GLX_EXT_create_context_es2_profile");
+
+ std::string clientVendor = mGLX.getClientString(GLX_VENDOR);
+ mIsMesa = clientVendor.find("Mesa") != std::string::npos;
+
+ // Choose the swap_control extension to use, if any.
+ // The EXT version is better as it allows glXSwapInterval to be called per
+ // window, while we'll potentially need to change the swap interval on each
+ // swap buffers when using the SGI or MESA versions.
+ if (mGLX.hasExtension("GLX_EXT_swap_control"))
+ {
+ mSwapControl = SwapControl::EXT;
+
+ // In GLX_EXT_swap_control querying these is done on a GLXWindow so we just
+ // set default values.
+ mMinSwapInterval = 0;
+ mMaxSwapInterval = 4;
+ }
+ else if (mGLX.hasExtension("GLX_MESA_swap_control"))
+ {
+ // If we have the Mesa or SGI extension, assume that you can at least set
+ // a swap interval of 0 or 1.
+ mSwapControl = SwapControl::Mesa;
+ mMinSwapInterval = 0;
+ mMinSwapInterval = 1;
+ }
+ else if (mGLX.hasExtension("GLX_SGI_swap_control"))
+ {
+ mSwapControl = SwapControl::SGI;
+ mMinSwapInterval = 0;
+ mMinSwapInterval = 1;
+ }
+ else
+ {
+ mSwapControl = SwapControl::Absent;
+ mMinSwapInterval = 1;
+ mMinSwapInterval = 1;
+ }
+
+ if (attribMap.contains(EGL_X11_VISUAL_ID_ANGLE))
+ {
+ mRequestedVisual = static_cast<EGLint>(attribMap.get(EGL_X11_VISUAL_ID_ANGLE, -1));
+
+ // There is no direct way to get the GLXFBConfig matching an X11 visual ID
+ // so we have to iterate over all the GLXFBConfigs to find the right one.
+ int nConfigs;
+ int attribList[] = {
+ None,
+ };
+ glx::FBConfig *allConfigs = mGLX.chooseFBConfig(attribList, &nConfigs);
+
+ for (int i = 0; i < nConfigs; ++i)
+ {
+ if (getGLXFBConfigAttrib(allConfigs[i], GLX_VISUAL_ID) == mRequestedVisual)
+ {
+ mContextConfig = allConfigs[i];
+ break;
+ }
+ }
+ XFree(allConfigs);
+
+ if (mContextConfig == nullptr)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Invalid visual ID requested.");
+ }
+ }
+ else
+ {
+ // When glXMakeCurrent is called, the context and the surface must be
+ // compatible which in glX-speak means that their config have the same
+ // color buffer type, are both RGBA or ColorIndex, and their buffers have
+ // the same depth, if they exist.
+ // Since our whole EGL implementation is backed by only one GL context, this
+ // context must be compatible with all the GLXFBConfig corresponding to the
+ // EGLconfigs that we will be exposing.
+ int nConfigs;
+ int attribList[] =
+ {
+ // We want RGBA8 and DEPTH24_STENCIL8
+ GLX_RED_SIZE, 8,
+ GLX_GREEN_SIZE, 8,
+ GLX_BLUE_SIZE, 8,
+ GLX_ALPHA_SIZE, 8,
+ GLX_DEPTH_SIZE, 24,
+ GLX_STENCIL_SIZE, 8,
+ // We want RGBA rendering (vs COLOR_INDEX) and doublebuffer
+ GLX_RENDER_TYPE, GLX_RGBA_BIT,
+ // Double buffer is not strictly required as a non-doublebuffer
+ // context can work with a doublebuffered surface, but it still
+ // flickers and all applications want doublebuffer anyway.
+ GLX_DOUBLEBUFFER, True,
+ // All of these must be supported for full EGL support
+ GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT | GLX_PBUFFER_BIT | GLX_PIXMAP_BIT,
+ // This makes sure the config have an associated visual Id
+ GLX_X_RENDERABLE, True,
+ GLX_CONFIG_CAVEAT, GLX_NONE,
+ None
+ };
+ glx::FBConfig *candidates = mGLX.chooseFBConfig(attribList, &nConfigs);
+ if (nConfigs == 0)
+ {
+ XFree(candidates);
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not find a decent GLX FBConfig to create the context.");
+ }
+ mContextConfig = candidates[0];
+ XFree(candidates);
+ }
+
+ const auto &eglAttributes = display->getAttributeMap();
+ if (mHasARBCreateContext)
+ {
+ egl::Error error = initializeContext(mContextConfig, eglAttributes, &mContext);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+ else
+ {
+ if (eglAttributes.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE,
+ EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE) ==
+ EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED,
+ "Cannot create an OpenGL ES platform on GLX without the "
+ "GLX_ARB_create_context extension.");
+ }
+
+ XVisualInfo visualTemplate;
+ visualTemplate.visualid = getGLXFBConfigAttrib(mContextConfig, GLX_VISUAL_ID);
+
+ int numVisuals = 0;
+ XVisualInfo *visuals =
+ XGetVisualInfo(mXDisplay, VisualIDMask, &visualTemplate, &numVisuals);
+ if (numVisuals <= 0)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED,
+ "Could not get the visual info from the fb config");
+ }
+ ASSERT(numVisuals == 1);
+
+ mContext = mGLX.createContext(&visuals[0], nullptr, true);
+ XFree(visuals);
+
+ if (!mContext)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not create GL context.");
+ }
+ }
+ ASSERT(mContext);
+
+ // FunctionsGL and DisplayGL need to make a few GL calls, for example to
+ // query the version of the context so we need to make the context current.
+ // glXMakeCurrent requires a GLXDrawable so we create a temporary Pbuffer
+ // (of size 1, 1) for the duration of these calls.
+ // Ideally we would want to unset the current context and destroy the pbuffer
+ // before going back to the application but this is TODO
+ // We could use a pbuffer of size (0, 0) but it fails on the Intel Mesa driver
+ // as commented on https://bugs.freedesktop.org/show_bug.cgi?id=38869 so we
+ // use (1, 1) instead.
+
+ int dummyPbufferAttribs[] =
+ {
+ GLX_PBUFFER_WIDTH, 1,
+ GLX_PBUFFER_HEIGHT, 1,
+ None,
+ };
+ mDummyPbuffer = mGLX.createPbuffer(mContextConfig, dummyPbufferAttribs);
+ if (!mDummyPbuffer)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not create the dummy pbuffer.");
+ }
+
+ if (!mGLX.makeCurrent(mDummyPbuffer, mContext))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not make the dummy pbuffer current.");
+ }
+
+ mFunctionsGL = new FunctionsGLGLX(mGLX.getProc);
+ mFunctionsGL->initialize();
+
+ // TODO(cwallez, angleproject:1303) Disable the OpenGL ES backend on Linux NVIDIA and Intel as
+ // it has problems on our automated testing. An OpenGL ES backend might not trigger this test if
+ // there is no Desktop OpenGL support, but that's not the case in our automated testing.
+ VendorID vendor = GetVendorID(mFunctionsGL);
+ bool isOpenGLES =
+ eglAttributes.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE) ==
+ EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE;
+ if (isOpenGLES && (IsIntel(vendor) || IsNvidia(vendor)))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Intel or NVIDIA OpenGL ES drivers are not supported.");
+ }
+
+ syncXCommands();
+
+ return DisplayGL::initialize(display);
+}
+
+void DisplayGLX::terminate()
+{
+ DisplayGL::terminate();
+
+ if (mDummyPbuffer)
+ {
+ mGLX.destroyPbuffer(mDummyPbuffer);
+ mDummyPbuffer = 0;
+ }
+
+ if (mContext)
+ {
+ mGLX.destroyContext(mContext);
+ mContext = nullptr;
+ }
+
+ mGLX.terminate();
+
+ SafeDelete(mFunctionsGL);
+}
+
+SurfaceImpl *DisplayGLX::createWindowSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs)
+{
+ ASSERT(configIdToGLXConfig.count(configuration->configID) > 0);
+ glx::FBConfig fbConfig = configIdToGLXConfig[configuration->configID];
+
+ return new WindowSurfaceGLX(state, mGLX, this, getRenderer(), window, mGLX.getDisplay(),
+ mContext, fbConfig);
+}
+
+SurfaceImpl *DisplayGLX::createPbufferSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ const egl::AttributeMap &attribs)
+{
+ ASSERT(configIdToGLXConfig.count(configuration->configID) > 0);
+ glx::FBConfig fbConfig = configIdToGLXConfig[configuration->configID];
+
+ EGLint width = static_cast<EGLint>(attribs.get(EGL_WIDTH, 0));
+ EGLint height = static_cast<EGLint>(attribs.get(EGL_HEIGHT, 0));
+ bool largest = (attribs.get(EGL_LARGEST_PBUFFER, EGL_FALSE) == EGL_TRUE);
+
+ return new PbufferSurfaceGLX(state, getRenderer(), width, height, largest, mGLX, mContext,
+ fbConfig);
+}
+
+SurfaceImpl *DisplayGLX::createPbufferFromClientBuffer(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return nullptr;
+}
+
+SurfaceImpl *DisplayGLX::createPixmapSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ NativePixmapType nativePixmap,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return nullptr;
+}
+
+egl::Error DisplayGLX::getDevice(DeviceImpl **device)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_DISPLAY);
+}
+
+egl::Error DisplayGLX::initializeContext(glx::FBConfig config,
+ const egl::AttributeMap &eglAttributes,
+ glx::Context *context)
+{
+ int profileMask = 0;
+
+ EGLint requestedDisplayType = static_cast<EGLint>(
+ eglAttributes.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE));
+ if (requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
+ {
+ if (!mHasEXTCreateContextES2Profile)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED,
+ "Cannot create an OpenGL ES platform on GLX without the "
+ "GLX_EXT_create_context_es_profile extension.");
+ }
+
+ ASSERT(mHasARBCreateContextProfile);
+ profileMask |= GLX_CONTEXT_ES2_PROFILE_BIT_EXT;
+ }
+
+ // Create a context of the requested version, if any.
+ gl::Version requestedVersion(static_cast<EGLint>(eglAttributes.get(
+ EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE)),
+ static_cast<EGLint>(eglAttributes.get(
+ EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE)));
+ if (static_cast<EGLint>(requestedVersion.major) != EGL_DONT_CARE &&
+ static_cast<EGLint>(requestedVersion.minor) != EGL_DONT_CARE)
+ {
+ if (!(profileMask & GLX_CONTEXT_ES2_PROFILE_BIT_EXT) &&
+ requestedVersion >= gl::Version(3, 2))
+ {
+ profileMask |= GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
+ }
+ return createContextAttribs(config, requestedVersion, profileMask, context);
+ }
+
+ // It is commonly assumed that glXCreateContextAttrib will create a context
+ // of the highest version possible but it is not specified in the spec and
+ // is not true on the Mesa drivers. On Mesa, Instead we try to create a
+ // context per GL version until we succeed, starting from newer version.
+ // On both Mesa and other drivers we try to create a desktop context and fall
+ // back to ES context.
+ // The code could be simpler if the Mesa code path was used for all drivers,
+ // however the cost of failing a context creation can be high (3 milliseconds
+ // for the NVIDIA driver). The good thing is that failed context creation only
+ // takes 0.1 milliseconds on Mesa.
+
+ struct ContextCreationInfo
+ {
+ EGLint displayType;
+ int profileFlag;
+ Optional<gl::Version> version;
+ };
+
+ // clang-format off
+ // For regular drivers we try to create a core, compatibility, then ES context.
+ // Without requiring any specific version (the Optional version is undefined).
+ const ContextCreationInfo contextsToTry[] = {
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, {} },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, {} },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, {} },
+ };
+
+ // On Mesa we try to create a core context, except for versions below 3.2
+ // where it is not applicable. (and fallback to ES as well)
+ const ContextCreationInfo mesaContextsToTry[] = {
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { gl::Version(4, 5) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { gl::Version(4, 4) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { gl::Version(4, 3) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { gl::Version(4, 2) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { gl::Version(4, 1) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { gl::Version(4, 0) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { gl::Version(3, 3) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { gl::Version(3, 2) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(3, 1) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(3, 0) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(2, 0) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(1, 5) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(1, 4) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(1, 3) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(1, 2) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(1, 1) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(1, 0) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, { gl::Version(3, 2) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, { gl::Version(3, 1) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, { gl::Version(3, 0) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, { gl::Version(2, 0) } },
+ };
+ // clang-format on
+
+ const ContextCreationInfo *toTry = contextsToTry;
+ size_t toTryLength = ArraySize(contextsToTry);
+ if (mIsMesa)
+ {
+ toTry = mesaContextsToTry;
+ toTryLength = ArraySize(mesaContextsToTry);
+ }
+
+ // NOTE: below we return as soon as we're able to create a context so the
+ // "error" variable is EGL_SUCCESS when returned contrary to the common idiom
+ // of returning "error" when there is an actual error.
+ for (size_t i = 0; i < toTryLength; ++i)
+ {
+ const ContextCreationInfo &info = toTry[i];
+ if (requestedDisplayType != EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE &&
+ requestedDisplayType != info.displayType)
+ {
+ continue;
+ }
+
+ egl::Error error = createContextAttribs(config, info.version, info.profileFlag, context);
+ if (!error.isError())
+ {
+ return error;
+ }
+ }
+
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not create a backing OpenGL context.");
+}
+
+egl::ConfigSet DisplayGLX::generateConfigs()
+{
+ egl::ConfigSet configs;
+ configIdToGLXConfig.clear();
+
+ const gl::Version &maxVersion = getMaxSupportedESVersion();
+ ASSERT(maxVersion >= gl::Version(2, 0));
+ bool supportsES3 = maxVersion >= gl::Version(3, 0);
+
+ int contextRedSize = getGLXFBConfigAttrib(mContextConfig, GLX_RED_SIZE);
+ int contextGreenSize = getGLXFBConfigAttrib(mContextConfig, GLX_GREEN_SIZE);
+ int contextBlueSize = getGLXFBConfigAttrib(mContextConfig, GLX_BLUE_SIZE);
+ int contextAlphaSize = getGLXFBConfigAttrib(mContextConfig, GLX_ALPHA_SIZE);
+
+ int contextDepthSize = getGLXFBConfigAttrib(mContextConfig, GLX_DEPTH_SIZE);
+ int contextStencilSize = getGLXFBConfigAttrib(mContextConfig, GLX_STENCIL_SIZE);
+
+ int contextSamples = mHasMultisample ? getGLXFBConfigAttrib(mContextConfig, GLX_SAMPLES) : 0;
+ int contextSampleBuffers =
+ mHasMultisample ? getGLXFBConfigAttrib(mContextConfig, GLX_SAMPLE_BUFFERS) : 0;
+
+ int contextAccumRedSize = getGLXFBConfigAttrib(mContextConfig, GLX_ACCUM_RED_SIZE);
+ int contextAccumGreenSize = getGLXFBConfigAttrib(mContextConfig, GLX_ACCUM_GREEN_SIZE);
+ int contextAccumBlueSize = getGLXFBConfigAttrib(mContextConfig, GLX_ACCUM_BLUE_SIZE);
+ int contextAccumAlphaSize = getGLXFBConfigAttrib(mContextConfig, GLX_ACCUM_ALPHA_SIZE);
+
+ int attribList[] =
+ {
+ GLX_RENDER_TYPE, GLX_RGBA_BIT,
+ GLX_X_RENDERABLE, True,
+ GLX_DOUBLEBUFFER, True,
+ None,
+ };
+
+ int glxConfigCount;
+ glx::FBConfig *glxConfigs = mGLX.chooseFBConfig(attribList, &glxConfigCount);
+
+ for (int i = 0; i < glxConfigCount; i++)
+ {
+ glx::FBConfig glxConfig = glxConfigs[i];
+ egl::Config config;
+
+ // Native stuff
+ config.nativeVisualID = getGLXFBConfigAttrib(glxConfig, GLX_VISUAL_ID);
+ config.nativeVisualType = getGLXFBConfigAttrib(glxConfig, GLX_X_VISUAL_TYPE);
+ config.nativeRenderable = EGL_TRUE;
+
+ // When a visual ID has been specified with EGL_ANGLE_x11_visual we should
+ // only return configs with this visual: it will maximize performance by avoid
+ // blits in the driver when showing the window on the screen.
+ if (mRequestedVisual != -1 && config.nativeVisualID != mRequestedVisual)
+ {
+ continue;
+ }
+
+ // Buffer sizes
+ config.redSize = getGLXFBConfigAttrib(glxConfig, GLX_RED_SIZE);
+ config.greenSize = getGLXFBConfigAttrib(glxConfig, GLX_GREEN_SIZE);
+ config.blueSize = getGLXFBConfigAttrib(glxConfig, GLX_BLUE_SIZE);
+ config.alphaSize = getGLXFBConfigAttrib(glxConfig, GLX_ALPHA_SIZE);
+ config.depthSize = getGLXFBConfigAttrib(glxConfig, GLX_DEPTH_SIZE);
+ config.stencilSize = getGLXFBConfigAttrib(glxConfig, GLX_STENCIL_SIZE);
+
+ // We require RGBA8 and the D24S8 (or no DS buffer)
+ if (config.redSize != contextRedSize || config.greenSize != contextGreenSize ||
+ config.blueSize != contextBlueSize || config.alphaSize != contextAlphaSize)
+ {
+ continue;
+ }
+ // The GLX spec says that it is ok for a whole buffer to not be present
+ // however the Mesa Intel driver (and probably on other Mesa drivers)
+ // fails to make current when the Depth stencil doesn't exactly match the
+ // configuration.
+ bool hasSameDepthStencil =
+ config.depthSize == contextDepthSize && config.stencilSize == contextStencilSize;
+ bool hasNoDepthStencil = config.depthSize == 0 && config.stencilSize == 0;
+ if (!hasSameDepthStencil && (mIsMesa || !hasNoDepthStencil))
+ {
+ continue;
+ }
+
+ config.colorBufferType = EGL_RGB_BUFFER;
+ config.luminanceSize = 0;
+ config.alphaMaskSize = 0;
+
+ config.bufferSize = config.redSize + config.greenSize + config.blueSize + config.alphaSize;
+
+ // Multisample and accumulation buffers
+ int samples = mHasMultisample ? getGLXFBConfigAttrib(glxConfig, GLX_SAMPLES) : 0;
+ int sampleBuffers =
+ mHasMultisample ? getGLXFBConfigAttrib(glxConfig, GLX_SAMPLE_BUFFERS) : 0;
+
+ int accumRedSize = getGLXFBConfigAttrib(glxConfig, GLX_ACCUM_RED_SIZE);
+ int accumGreenSize = getGLXFBConfigAttrib(glxConfig, GLX_ACCUM_GREEN_SIZE);
+ int accumBlueSize = getGLXFBConfigAttrib(glxConfig, GLX_ACCUM_BLUE_SIZE);
+ int accumAlphaSize = getGLXFBConfigAttrib(glxConfig, GLX_ACCUM_ALPHA_SIZE);
+
+ if (samples != contextSamples ||
+ sampleBuffers != contextSampleBuffers ||
+ accumRedSize != contextAccumRedSize ||
+ accumGreenSize != contextAccumGreenSize ||
+ accumBlueSize != contextAccumBlueSize ||
+ accumAlphaSize != contextAccumAlphaSize)
+ {
+ continue;
+ }
+
+ config.samples = samples;
+ config.sampleBuffers = sampleBuffers;
+
+ // Transparency
+ if (getGLXFBConfigAttrib(glxConfig, GLX_TRANSPARENT_TYPE) == GLX_TRANSPARENT_RGB)
+ {
+ config.transparentType = EGL_TRANSPARENT_RGB;
+ config.transparentRedValue = getGLXFBConfigAttrib(glxConfig, GLX_TRANSPARENT_RED_VALUE);
+ config.transparentGreenValue = getGLXFBConfigAttrib(glxConfig, GLX_TRANSPARENT_GREEN_VALUE);
+ config.transparentBlueValue = getGLXFBConfigAttrib(glxConfig, GLX_TRANSPARENT_BLUE_VALUE);
+ }
+ else
+ {
+ config.transparentType = EGL_NONE;
+ }
+
+ // Pbuffer
+ config.maxPBufferWidth = getGLXFBConfigAttrib(glxConfig, GLX_MAX_PBUFFER_WIDTH);
+ config.maxPBufferHeight = getGLXFBConfigAttrib(glxConfig, GLX_MAX_PBUFFER_HEIGHT);
+ config.maxPBufferPixels = getGLXFBConfigAttrib(glxConfig, GLX_MAX_PBUFFER_PIXELS);
+
+ // Caveat
+ config.configCaveat = EGL_NONE;
+
+ int caveat = getGLXFBConfigAttrib(glxConfig, GLX_CONFIG_CAVEAT);
+ if (caveat == GLX_SLOW_CONFIG)
+ {
+ config.configCaveat = EGL_SLOW_CONFIG;
+ }
+ else if (caveat == GLX_NON_CONFORMANT_CONFIG)
+ {
+ continue;
+ }
+
+ // Misc
+ config.level = getGLXFBConfigAttrib(glxConfig, GLX_LEVEL);
+
+ config.bindToTextureRGB = EGL_FALSE;
+ config.bindToTextureRGBA = EGL_FALSE;
+
+ int glxDrawable = getGLXFBConfigAttrib(glxConfig, GLX_DRAWABLE_TYPE);
+ config.surfaceType = 0 |
+ (glxDrawable & GLX_WINDOW_BIT ? EGL_WINDOW_BIT : 0) |
+ (glxDrawable & GLX_PBUFFER_BIT ? EGL_PBUFFER_BIT : 0) |
+ (glxDrawable & GLX_PIXMAP_BIT ? EGL_PIXMAP_BIT : 0);
+
+ config.minSwapInterval = mMinSwapInterval;
+ config.maxSwapInterval = mMaxSwapInterval;
+
+ // TODO(cwallez) wildly guessing these formats, another TODO says they should be removed anyway
+ config.renderTargetFormat = GL_RGBA8;
+ config.depthStencilFormat = GL_DEPTH24_STENCIL8;
+
+ config.conformant = EGL_OPENGL_ES2_BIT | (supportsES3 ? EGL_OPENGL_ES3_BIT_KHR : 0);
+ config.renderableType = config.conformant;
+
+ // TODO(cwallez) I have no idea what this is
+ config.matchNativePixmap = EGL_NONE;
+
+ int id = configs.add(config);
+ configIdToGLXConfig[id] = glxConfig;
+ }
+
+ XFree(glxConfigs);
+
+ return configs;
+}
+
+bool DisplayGLX::testDeviceLost()
+{
+ if (mHasARBCreateContextRobustness)
+ {
+ return getRenderer()->getResetStatus() != GL_NO_ERROR;
+ }
+
+ return false;
+}
+
+egl::Error DisplayGLX::restoreLostDevice()
+{
+ return egl::Error(EGL_BAD_DISPLAY);
+}
+
+bool DisplayGLX::isValidNativeWindow(EGLNativeWindowType window) const
+{
+ // There is no function in Xlib to check the validity of a Window directly.
+ // However a small number of functions used to obtain window information
+ // return a status code (0 meaning failure) and guarantee that they will
+ // fail if the window doesn't exist (the rational is that these function
+ // are used by window managers). Out of these function we use XQueryTree
+ // as it seems to be the simplest; a drawback is that it will allocate
+ // memory for the list of children, because we use a child window for
+ // WindowSurface.
+ Window root;
+ Window parent;
+ Window *children = nullptr;
+ unsigned nChildren;
+ int status = XQueryTree(mGLX.getDisplay(), window, &root, &parent, &children, &nChildren);
+ if (children)
+ {
+ XFree(children);
+ }
+ return status != 0;
+}
+
+std::string DisplayGLX::getVendorString() const
+{
+ // UNIMPLEMENTED();
+ return "";
+}
+
+egl::Error DisplayGLX::waitClient() const
+{
+ mGLX.waitGL();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayGLX::getDriverVersion(std::string *version) const
+{
+ VendorID vendor = GetVendorID(mFunctionsGL);
+
+ switch (vendor)
+ {
+ case VENDOR_ID_NVIDIA:
+ return getNVIDIADriverVersion(version);
+ case VENDOR_ID_AMD:
+ return GetAMDDriverVersion(version);
+ default:
+ *version = "";
+ return egl::Error(EGL_SUCCESS);
+ }
+}
+
+egl::Error DisplayGLX::waitNative(EGLint engine,
+ egl::Surface *drawSurface,
+ egl::Surface *readSurface) const
+{
+ // eglWaitNative is used to notice the driver of changes in X11 for the current surface, such as
+ // changes of the window size. We use this event to update the child window of WindowSurfaceGLX
+ // to match its parent window's size.
+ // Handling eglWaitNative this way helps the application control when resize happens. This is
+ // important because drivers have a tendency to clobber the back buffer when the windows are
+ // resized. See http://crbug.com/326995
+ if (drawSurface != nullptr)
+ {
+ SurfaceGLX *glxDrawSurface = GetImplAs<SurfaceGLX>(drawSurface);
+ egl::Error error = glxDrawSurface->checkForResize();
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ if (readSurface != drawSurface && readSurface != nullptr)
+ {
+ SurfaceGLX *glxReadSurface = GetImplAs<SurfaceGLX>(readSurface);
+ egl::Error error = glxReadSurface->checkForResize();
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ // We still need to forward the resizing of the child window to the driver.
+ mGLX.waitX();
+ return egl::Error(EGL_SUCCESS);
+}
+
+void DisplayGLX::syncXCommands() const
+{
+ if (mUsesNewXDisplay)
+ {
+ XSync(mGLX.getDisplay(), False);
+ }
+}
+
+void DisplayGLX::setSwapInterval(glx::Drawable drawable, SwapControlData *data)
+{
+ ASSERT(data != nullptr);
+
+ // TODO(cwallez) error checking?
+ if (mSwapControl == SwapControl::EXT)
+ {
+ // Prefer the EXT extension, it gives per-drawable swap intervals, which will
+ // minimize the number of driver calls.
+ if (data->maxSwapInterval < 0)
+ {
+ unsigned int maxSwapInterval = 0;
+ mGLX.queryDrawable(drawable, GLX_MAX_SWAP_INTERVAL_EXT, &maxSwapInterval);
+ data->maxSwapInterval = static_cast<int>(maxSwapInterval);
+ }
+
+ // When the egl configs were generated we had to guess what the max swap interval
+ // was because we didn't have a window to query it one (and that this max could
+ // depend on the monitor). This means that the target interval might be higher
+ // than the max interval and needs to be clamped.
+ const int realInterval = std::min(data->targetSwapInterval, data->maxSwapInterval);
+ if (data->currentSwapInterval != realInterval)
+ {
+ mGLX.swapIntervalEXT(drawable, realInterval);
+ data->currentSwapInterval = realInterval;
+ }
+ }
+ else if (mCurrentSwapInterval != data->targetSwapInterval)
+ {
+ // With the Mesa or SGI extensions we can still do per-drawable swap control
+ // manually but it is more expensive in number of driver calls.
+ if (mSwapControl == SwapControl::Mesa)
+ {
+ mGLX.swapIntervalMESA(data->targetSwapInterval);
+ }
+ else if (mSwapControl == SwapControl::SGI)
+ {
+ mGLX.swapIntervalSGI(data->targetSwapInterval);
+ }
+ mCurrentSwapInterval = data->targetSwapInterval;
+ }
+}
+
+bool DisplayGLX::isValidWindowVisualId(unsigned long visualId) const
+{
+ return mRequestedVisual == -1 || static_cast<unsigned long>(mRequestedVisual) == visualId;
+}
+
+const FunctionsGL *DisplayGLX::getFunctionsGL() const
+{
+ return mFunctionsGL;
+}
+
+void DisplayGLX::generateExtensions(egl::DisplayExtensions *outExtensions) const
+{
+ outExtensions->createContextRobustness = mHasARBCreateContextRobustness;
+}
+
+void DisplayGLX::generateCaps(egl::Caps *outCaps) const
+{
+ outCaps->textureNPOT = true;
+}
+
+int DisplayGLX::getGLXFBConfigAttrib(glx::FBConfig config, int attrib) const
+{
+ int result;
+ mGLX.getFBConfigAttrib(config, attrib, &result);
+ return result;
+}
+
+egl::Error DisplayGLX::createContextAttribs(glx::FBConfig,
+ const Optional<gl::Version> &version,
+ int profileMask,
+ glx::Context *context) const
+{
+ std::vector<int> attribs;
+
+ if (mHasARBCreateContextRobustness)
+ {
+ attribs.push_back(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB);
+ attribs.push_back(GLX_LOSE_CONTEXT_ON_RESET_ARB);
+ }
+
+ if (version.valid())
+ {
+ attribs.push_back(GLX_CONTEXT_MAJOR_VERSION_ARB);
+ attribs.push_back(version.value().major);
+
+ attribs.push_back(GLX_CONTEXT_MINOR_VERSION_ARB);
+ attribs.push_back(version.value().minor);
+ }
+
+ if (profileMask != 0 && mHasARBCreateContextProfile)
+ {
+ attribs.push_back(GLX_CONTEXT_PROFILE_MASK_ARB);
+ attribs.push_back(profileMask);
+ }
+
+ attribs.push_back(None);
+
+ // When creating a context with glXCreateContextAttribsARB, a variety of X11 errors can
+ // be generated. To prevent these errors from crashing our process, we simply ignore
+ // them and only look if GLXContext was created.
+ // Process all events before setting the error handler to avoid desynchronizing XCB instances
+ // (the error handler is NOT per-display).
+ XSync(mXDisplay, False);
+ auto oldErrorHandler = XSetErrorHandler(IgnoreX11Errors);
+ *context = mGLX.createContextAttribsARB(mContextConfig, nullptr, True, attribs.data());
+ XSetErrorHandler(oldErrorHandler);
+
+ if (!*context)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not create GL context.");
+ }
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayGLX::getNVIDIADriverVersion(std::string *version) const
+{
+ *version = "";
+
+ int eventBase = 0;
+ int errorBase = 0;
+ if (XNVCTRLQueryExtension(mXDisplay, &eventBase, &errorBase))
+ {
+ int screenCount = ScreenCount(mXDisplay);
+ for (int screen = 0; screen < screenCount; ++screen)
+ {
+ char *buffer = nullptr;
+ if (XNVCTRLIsNvScreen(mXDisplay, screen) &&
+ XNVCTRLQueryStringAttribute(mXDisplay, screen, 0,
+ NV_CTRL_STRING_NVIDIA_DRIVER_VERSION, &buffer))
+ {
+ *version = buffer;
+ XFree(buffer);
+ }
+ }
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.h b/gfx/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.h
new file mode 100755
index 000000000..7e870c2f3
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.h
@@ -0,0 +1,151 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DisplayGLX.h: GLX implementation of egl::Display
+
+#ifndef LIBANGLE_RENDERER_GL_GLX_DISPLAYGLX_H_
+#define LIBANGLE_RENDERER_GL_GLX_DISPLAYGLX_H_
+
+#include <string>
+#include <vector>
+
+#include "common/Optional.h"
+#include "libANGLE/renderer/gl/DisplayGL.h"
+#include "libANGLE/renderer/gl/glx/FunctionsGLX.h"
+
+namespace rx
+{
+
+class FunctionsGLX;
+
+// State-tracking data for the swap control to allow DisplayGLX to remember per
+// drawable information for swap control.
+struct SwapControlData
+{
+ SwapControlData();
+
+ // Set by the drawable
+ int targetSwapInterval;
+
+ // DisplayGLX-side state-tracking
+ int maxSwapInterval;
+ int currentSwapInterval;
+};
+
+class DisplayGLX : public DisplayGL
+{
+ public:
+ DisplayGLX();
+ ~DisplayGLX() override;
+
+ egl::Error initialize(egl::Display *display) override;
+ void terminate() override;
+
+ SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ NativePixmapType nativePixmap,
+ const egl::AttributeMap &attribs) override;
+
+ egl::ConfigSet generateConfigs() override;
+
+ bool testDeviceLost() override;
+ egl::Error restoreLostDevice() override;
+
+ bool isValidNativeWindow(EGLNativeWindowType window) const override;
+
+ egl::Error getDevice(DeviceImpl **device) override;
+
+ std::string getVendorString() const override;
+
+ egl::Error waitClient() const override;
+ egl::Error waitNative(EGLint engine,
+ egl::Surface *drawSurface,
+ egl::Surface *readSurface) const override;
+
+ egl::Error getDriverVersion(std::string *version) const override;
+
+ // Synchronizes with the X server, if the display has been opened by ANGLE.
+ // Calling this is required at the end of every functions that does buffered
+ // X calls (not for glX calls) otherwise there might be race conditions
+ // between the application's display and ANGLE's one.
+ void syncXCommands() const;
+
+ // Depending on the supported GLX extension, swap interval can be set
+ // globally or per drawable. This function will make sure the drawable's
+ // swap interval is the one required so that the subsequent swapBuffers
+ // acts as expected.
+ void setSwapInterval(glx::Drawable drawable, SwapControlData *data);
+
+ bool isValidWindowVisualId(unsigned long visualId) const;
+
+ private:
+ const FunctionsGL *getFunctionsGL() const override;
+
+ egl::Error initializeContext(glx::FBConfig config,
+ const egl::AttributeMap &eglAttributes,
+ glx::Context *context);
+
+ void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
+ void generateCaps(egl::Caps *outCaps) const override;
+
+ int getGLXFBConfigAttrib(glx::FBConfig config, int attrib) const;
+ egl::Error createContextAttribs(glx::FBConfig,
+ const Optional<gl::Version> &version,
+ int profileMask,
+ glx::Context *context) const;
+
+ egl::Error getNVIDIADriverVersion(std::string *version) const;
+
+ FunctionsGL *mFunctionsGL;
+
+ std::map<int, glx::FBConfig> configIdToGLXConfig;
+
+ EGLint mRequestedVisual;
+ glx::FBConfig mContextConfig;
+ glx::Context mContext;
+ // A pbuffer the context is current on during ANGLE initialization
+ glx::Pbuffer mDummyPbuffer;
+
+ bool mUsesNewXDisplay;
+ bool mIsMesa;
+ bool mHasMultisample;
+ bool mHasARBCreateContext;
+ bool mHasARBCreateContextProfile;
+ bool mHasARBCreateContextRobustness;
+ bool mHasEXTCreateContextES2Profile;
+
+ enum class SwapControl
+ {
+ Absent,
+ EXT,
+ Mesa,
+ SGI,
+ };
+ SwapControl mSwapControl;
+ int mMinSwapInterval;
+ int mMaxSwapInterval;
+ int mCurrentSwapInterval;
+
+ FunctionsGLX mGLX;
+ Display *mXDisplay;
+ egl::Display *mEGLDisplay;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_GLX_DISPLAYGLX_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/FBConfigCompatibility.md b/gfx/angle/src/libANGLE/renderer/gl/glx/FBConfigCompatibility.md
new file mode 100755
index 000000000..2343ad086
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/glx/FBConfigCompatibility.md
@@ -0,0 +1,204 @@
+GLX Framebuffer Compatibility investigation
+===========================================
+
+In GLX and EGL, contexts are created with respect to a config that
+describes the type of surfaces they will be used to render to.
+Likewise surfaces are created with respect to a config and for
+a context to be able to render to a surface, both their configs
+must be compatible. Compatibility is losely described in both
+the GLX and EGL specs but the following is clear:
+ * In GLX the config's color buffer must have the same type, including
+RGBA vs. ColorIndex and the buffers must have the same depth, if they
+exist.
+ * In EGL the config's color buffer must have the same type and the
+buffers must have the same depth (not clear if it is only if they exist)
+
+Obviously the EGLconfig we will expose will have a one-to-one
+correspondance with GLXFBConfigs.
+
+Our EGL implementation uses a single OpenGL context to back all
+the EGLcontexts created by the application. Since our GL context
+and GLXContext are the same object but in two APIs, we will make
+the confusion and call the GLX context our backing context.
+
+The problem we have is that the the GLX context is created before
+the application can choose what type of context it wants to use,
+that means we have to expose EGLconfigs whose respective GLXFBConfigs
+are compatible with the GLXFBConfig of our GLX context; we also need
+to choose the GLXFBConfig of our GLX context so that it matches the
+most common needs of application.
+
+Choice of the GLX context GLXFBConfig
+-------------------------------------
+
+We decided that our GLX context's configuration must satisfy the following:
+ * Have a RGBA8 color buffer and D24S8 depth-stencil buffer which is what
+the vast majority of applications use.
+ * It must render in direct colors, i.e. not in a color indexed format.
+ * It must be double-buffered (see later)
+ * It must support rendering to all the types of GLX surfaces so that we can
+use it for all types of EGL surfaces
+ * It must have an associated visual ID so that we can use it with X, it seems
+like this would be strongly tied to it having the ```WINDOW_BIT``` set.
+ * We would like a conformant context.
+
+Study of compatible GLXFBConfigs
+--------------------------------
+
+When using the condition of compatibility defined in the GLX spec and filtering
+out the non-conformant GLXFBConfig we got the following list (see function
+```print_visual_attribs_short``` in [glxinfo's source code](http://cgit.freedesktop.org/mesa/demos/tree/src/xdemos/glxinfo.c)
+to understand how to read the table):
+
+```
+ visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav
+ id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat Result
+----------------------------------------------------------------------------
+0x02e 24 tc 0 32 0 r . . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Fail
+0x0e4 32 tc 0 32 0 r . . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None BadMatch
+0x02c 24 tc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Pass
+0x0e2 32 tc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None BadMatch
+0x089 24 dc 0 32 0 r . . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Fail
+0x087 24 dc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Pass
+0x026 24 tc 0 32 0 r . . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Fail
+0x0dc 32 tc 0 32 0 r . . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None BadMatch
+0x024 24 tc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Pass
+0x0da 32 tc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None BadMatch
+0x081 24 dc 0 32 0 r . . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Fail
+0x07f 24 dc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Pass
+```
+
+The last column shows the result of trying to render on a window using the config,
+with a GLX context using config 0x024. The first thing we see is that BadMatch is
+thrown by the X server when creating the subwindow for rendering. This was because
+we didn't set the border pixel of the subwindow *shake fist at X11* (see this [StackOverflow question](http://stackoverflow.com/questions/3645632/how-to-create-a-window-with-a-bit-depth-of-32)).
+The result updated with this fix give:
+
+```
+ visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav
+ id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat
+----------------------------------------------------------------------------
+0x02e 24 tc 0 32 0 r . . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Fail
+0x0e4 32 tc 0 32 0 r . . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Fail
+0x02c 24 tc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Pass
+0x0e2 32 tc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Pass
+0x089 24 dc 0 32 0 r . . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Fail
+0x087 24 dc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Pass
+0x026 24 tc 0 32 0 r . . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Fail
+0x0dc 32 tc 0 32 0 r . . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Fail
+0x024 24 tc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Pass
+0x0da 32 tc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Pass
+0x081 24 dc 0 32 0 r . . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Fail
+0x07f 24 dc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Pass
+```
+
+From this we see that our rendering test passed if and only if the config was double
+buffered like 0x024 which is our GLX context config. The compatible configs are then:
+
+```
+ visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav
+ id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat
+----------------------------------------------------------------------------
+0x02c 24 tc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None
+0x0e2 32 tc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None
+0x087 24 dc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None
+0x024 24 tc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None
+0x0da 32 tc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None
+0x07f 24 dc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None
+```
+
+We can see two dimensions, with our without a depth-stencil buffer and with TrueColor
+or DirectColor. The depth-stencil will be useful to expose to application.
+
+More on double buffering
+------------------------
+The tests above show that double-buffered contexts are not compatible with single-
+buffered surfaces; however other tests show that single-buffered contexts are
+compatible with both single and double-buffered surfaces. The problem is that in
+that case, we can see some flickering even with double-buffered surfaces. If we
+can find a trick to avoid that flicker, then we would be able to expose single
+and double-buffered surfaces at the EGL level. Not exposing them isn't too much
+of a problem though as the vast majority of application want double-buffering.
+
+AMD and extra buffers
+---------------------
+As can be seen above, NVIDIA does not expose conformant context with multisampled
+buffers or non RGBA16 accumulation buffers. The behavior is different on AMD that
+exposes them as conformant, which gives the following list after filtering as
+explained above:
+
+```
+ visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav
+ id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat
+----------------------------------------------------------------------------
+0x023 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 16 16 16 16 0 0 None
+0x027 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
+0x02b 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 2 1 None
+0x02f 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 4 1 None
+0x03b 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 16 16 16 16 0 0 None
+0x03f 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
+0x043 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 2 1 None
+0x047 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 4 1 None
+```
+
+ANGLE's context is created using 0x027 and experimentation shows it is only compatible
+with 0x03f which is the only other config lacking both an accumulation buffer and a
+multisample buffer. The GLX spec seems to hint it should still work ("should have the
+same size, if they exist") but it doesn't work in this case. Filtering the configs to
+have the same multisample and accumulation buffers gives the following:
+
+```
+ visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav
+ id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat
+----------------------------------------------------------------------------
+0x027 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
+0x03f 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
+```
+
+Mesa Intel driver
+-----------------
+In GLX, a criterium for context and surface compatibility is that buffers
+should have the same depth, if they exist at all in the surface. This means
+that it should be possible to make a context with a D24S8 depth-stencil
+buffer to a surface without a depth-stencil buffer. This doesn't work on the
+Mesa Intel driver. The list before the workaround was the following, with
+0x020 being the fbconfig chosen for the context:
+
+```
+ visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav
+ id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat
+----------------------------------------------------------------------------
+0x020 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
+0x021 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
+0x08f 32 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
+0x0d0 24 tc 0 32 0 r y . 8 8 8 8 . . 0 0 0 0 0 0 0 0 0 None
+0x0e2 24 dc 0 32 0 r y . 8 8 8 8 . . 0 0 0 0 0 0 0 0 0 None
+0x0e9 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
+```
+
+After the workaround that list becomes the following:
+
+```
+ visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav
+ id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat
+----------------------------------------------------------------------------
+0x020 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
+0x021 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
+0x08f 32 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
+0x0e9 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
+```
+
+Future investigation
+--------------------
+All the non-conformant configs have a multisampled buffer, so it could be interesting
+to see if we can use them to expose another EGL extension.
+
+Finally this document is written with respect to a small number of drivers, before
+using the GLX EGL implementation in the wild it would be good to test it on other
+drivers and hardware.
+
+The drivers tested were:
+
+ - the proprietary NVIDIA driver
+ - the proprietary AMD driver
+ - the open source Intel (Broadwell) Mesa driver
diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.cpp b/gfx/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.cpp
new file mode 100755
index 000000000..4ec38dd81
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.cpp
@@ -0,0 +1,398 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// FunctionsGLX.cpp: Implements the FunctionsGLX class.
+
+#define ANGLE_SKIP_GLX_DEFINES 1
+#include "libANGLE/renderer/gl/glx/FunctionsGLX.h"
+#undef ANGLE_SKIP_GLX_DEFINES
+
+// We can only include glx.h in files which do not include ANGLE's GLES
+// headers, to avoid doubly-defined GLenum macros, typedefs, etc.
+#include <GL/glx.h>
+
+#include <dlfcn.h>
+#include <algorithm>
+
+#include "common/string_utils.h"
+#include "libANGLE/renderer/gl/glx/functionsglx_typedefs.h"
+
+namespace rx
+{
+
+void* FunctionsGLX::sLibHandle = nullptr;
+
+template<typename T>
+static bool GetProc(PFNGETPROCPROC getProc, T *member, const char *name)
+{
+ *member = reinterpret_cast<T>(getProc(name));
+ return *member != nullptr;
+}
+
+struct FunctionsGLX::GLXFunctionTable
+{
+ GLXFunctionTable()
+ : createContextPtr(nullptr),
+ destroyContextPtr(nullptr),
+ makeCurrentPtr(nullptr),
+ swapBuffersPtr(nullptr),
+ queryExtensionPtr(nullptr),
+ queryVersionPtr(nullptr),
+ getCurrentContextPtr(nullptr),
+ getCurrentDrawablePtr(nullptr),
+ waitXPtr(nullptr),
+ waitGLPtr(nullptr),
+ getClientStringPtr(nullptr),
+ queryExtensionsStringPtr(nullptr),
+ getFBConfigsPtr(nullptr),
+ chooseFBConfigPtr(nullptr),
+ getFBConfigAttribPtr(nullptr),
+ getVisualFromFBConfigPtr(nullptr),
+ createWindowPtr(nullptr),
+ destroyWindowPtr(nullptr),
+ createPbufferPtr(nullptr),
+ destroyPbufferPtr(nullptr),
+ queryDrawablePtr(nullptr),
+ createContextAttribsARBPtr(nullptr),
+ swapIntervalEXTPtr(nullptr),
+ swapIntervalMESAPtr(nullptr),
+ swapIntervalSGIPtr(nullptr)
+ {
+ }
+
+ // GLX 1.0
+ PFNGLXCREATECONTEXTPROC createContextPtr;
+ PFNGLXDESTROYCONTEXTPROC destroyContextPtr;
+ PFNGLXMAKECURRENTPROC makeCurrentPtr;
+ PFNGLXSWAPBUFFERSPROC swapBuffersPtr;
+ PFNGLXQUERYEXTENSIONPROC queryExtensionPtr;
+ PFNGLXQUERYVERSIONPROC queryVersionPtr;
+ PFNGLXGETCURRENTCONTEXTPROC getCurrentContextPtr;
+ PFNGLXGETCURRENTDRAWABLEPROC getCurrentDrawablePtr;
+ PFNGLXWAITXPROC waitXPtr;
+ PFNGLXWAITGLPROC waitGLPtr;
+
+ // GLX 1.1
+ PFNGLXGETCLIENTSTRINGPROC getClientStringPtr;
+ PFNGLXQUERYEXTENSIONSSTRINGPROC queryExtensionsStringPtr;
+
+ //GLX 1.3
+ PFNGLXGETFBCONFIGSPROC getFBConfigsPtr;
+ PFNGLXCHOOSEFBCONFIGPROC chooseFBConfigPtr;
+ PFNGLXGETFBCONFIGATTRIBPROC getFBConfigAttribPtr;
+ PFNGLXGETVISUALFROMFBCONFIGPROC getVisualFromFBConfigPtr;
+ PFNGLXCREATEWINDOWPROC createWindowPtr;
+ PFNGLXDESTROYWINDOWPROC destroyWindowPtr;
+ PFNGLXCREATEPBUFFERPROC createPbufferPtr;
+ PFNGLXDESTROYPBUFFERPROC destroyPbufferPtr;
+ PFNGLXQUERYDRAWABLEPROC queryDrawablePtr;
+
+ // GLX_ARB_create_context
+ PFNGLXCREATECONTEXTATTRIBSARBPROC createContextAttribsARBPtr;
+
+ // GLX_EXT_swap_control
+ PFNGLXSWAPINTERVALEXTPROC swapIntervalEXTPtr;
+
+ // GLX_MESA_swap_control
+ PFNGLXSWAPINTERVALMESAPROC swapIntervalMESAPtr;
+
+ // GLX_SGI_swap_control
+ PFNGLXSWAPINTERVALSGIPROC swapIntervalSGIPtr;
+};
+
+FunctionsGLX::FunctionsGLX()
+ : majorVersion(0),
+ minorVersion(0),
+ mXDisplay(nullptr),
+ mXScreen(-1),
+ mFnPtrs(new GLXFunctionTable())
+{
+}
+
+FunctionsGLX::~FunctionsGLX()
+{
+ delete mFnPtrs;
+ terminate();
+}
+
+bool FunctionsGLX::initialize(Display *xDisplay, int screen, std::string *errorString)
+{
+ terminate();
+ mXDisplay = xDisplay;
+ mXScreen = screen;
+
+#if !defined(ANGLE_LINK_GLX)
+ // Some OpenGL implementations can't handle having this library
+ // handle closed while there's any X window still open against
+ // which a GLXWindow was ever created.
+ if (!sLibHandle)
+ {
+ sLibHandle = dlopen("libGL.so.1", RTLD_NOW);
+ if (!sLibHandle)
+ {
+ *errorString = std::string("Could not dlopen libGL.so.1: ") + dlerror();
+ return false;
+ }
+ }
+
+ getProc = reinterpret_cast<PFNGETPROCPROC>(dlsym(sLibHandle, "glXGetProcAddress"));
+ if (!getProc)
+ {
+ getProc = reinterpret_cast<PFNGETPROCPROC>(dlsym(sLibHandle, "glXGetProcAddressARB"));
+ }
+ if (!getProc)
+ {
+ *errorString = "Could not retrieve glXGetProcAddress";
+ return false;
+ }
+#else
+ getProc = reinterpret_cast<PFNGETPROCPROC>(glXGetProcAddress);
+#endif
+
+#define GET_PROC_OR_ERROR(MEMBER, NAME) \
+ if (!GetProc(getProc, MEMBER, #NAME)) \
+ { \
+ *errorString = "Could not load GLX entry point " #NAME; \
+ return false; \
+ }
+#if !defined(ANGLE_LINK_GLX)
+#define GET_FNPTR_OR_ERROR(MEMBER, NAME) GET_PROC_OR_ERROR(MEMBER, NAME)
+#else
+#define GET_FNPTR_OR_ERROR(MEMBER, NAME) *MEMBER = NAME;
+#endif
+
+ // GLX 1.0
+ GET_FNPTR_OR_ERROR(&mFnPtrs->createContextPtr, glXCreateContext);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->destroyContextPtr, glXDestroyContext);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->makeCurrentPtr, glXMakeCurrent);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->swapBuffersPtr, glXSwapBuffers);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->queryExtensionPtr, glXQueryExtension);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->queryVersionPtr, glXQueryVersion);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->getCurrentContextPtr, glXGetCurrentContext);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->getCurrentDrawablePtr, glXGetCurrentDrawable);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->waitXPtr, glXWaitX);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->waitGLPtr, glXWaitGL);
+
+ // GLX 1.1
+ GET_FNPTR_OR_ERROR(&mFnPtrs->getClientStringPtr, glXGetClientString);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->queryExtensionsStringPtr, glXQueryExtensionsString);
+
+ // Check we have a working GLX
+ {
+ int errorBase;
+ int eventBase;
+ if (!queryExtension(&errorBase, &eventBase))
+ {
+ *errorString = "GLX is not present.";
+ return false;
+ }
+ }
+
+ // Check we have a supported version of GLX
+ if (!queryVersion(&majorVersion, &minorVersion))
+ {
+ *errorString = "Could not query the GLX version.";
+ return false;
+ }
+ if (majorVersion != 1 || minorVersion < 3)
+ {
+ *errorString = "Unsupported GLX version (requires at least 1.3).";
+ return false;
+ }
+
+ const char *extensions = queryExtensionsString();
+ if (!extensions)
+ {
+ *errorString = "glXQueryExtensionsString returned NULL";
+ return false;
+ }
+ angle::SplitStringAlongWhitespace(extensions, &mExtensions);
+
+ // GLX 1.3
+ GET_FNPTR_OR_ERROR(&mFnPtrs->getFBConfigsPtr, glXGetFBConfigs);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->chooseFBConfigPtr, glXChooseFBConfig);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->getFBConfigAttribPtr, glXGetFBConfigAttrib);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->getVisualFromFBConfigPtr, glXGetVisualFromFBConfig);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->createWindowPtr, glXCreateWindow);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->destroyWindowPtr, glXDestroyWindow);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->createPbufferPtr, glXCreatePbuffer);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->destroyPbufferPtr, glXDestroyPbuffer);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->queryDrawablePtr, glXQueryDrawable);
+
+ // Extensions
+ if (hasExtension("GLX_ARB_create_context"))
+ {
+ GET_PROC_OR_ERROR(&mFnPtrs->createContextAttribsARBPtr, glXCreateContextAttribsARB);
+ }
+ if (hasExtension("GLX_EXT_swap_control"))
+ {
+ GET_PROC_OR_ERROR(&mFnPtrs->swapIntervalEXTPtr, glXSwapIntervalEXT);
+ }
+ if (hasExtension("GLX_MESA_swap_control"))
+ {
+ GET_PROC_OR_ERROR(&mFnPtrs->swapIntervalMESAPtr, glXSwapIntervalMESA);
+ }
+ if (hasExtension("GLX_SGI_swap_control"))
+ {
+ GET_PROC_OR_ERROR(&mFnPtrs->swapIntervalSGIPtr, glXSwapIntervalSGI);
+ }
+
+#undef GET_FNPTR_OR_ERROR
+#undef GET_PROC_OR_ERROR
+
+ *errorString = "";
+ return true;
+}
+
+void FunctionsGLX::terminate()
+{
+}
+
+bool FunctionsGLX::hasExtension(const char *extension) const
+{
+ return std::find(mExtensions.begin(), mExtensions.end(), extension) != mExtensions.end();
+}
+
+Display *FunctionsGLX::getDisplay() const
+{
+ return mXDisplay;
+}
+
+int FunctionsGLX::getScreen() const
+{
+ return mXScreen;
+}
+
+// GLX functions
+
+// GLX 1.0
+glx::Context FunctionsGLX::createContext(XVisualInfo *visual, glx::Context share, bool direct) const
+{
+ GLXContext shareCtx = reinterpret_cast<GLXContext>(share);
+ GLXContext context = mFnPtrs->createContextPtr(mXDisplay, visual, shareCtx, direct);
+ return reinterpret_cast<glx::Context>(context);
+}
+void FunctionsGLX::destroyContext(glx::Context context) const
+{
+ GLXContext ctx = reinterpret_cast<GLXContext>(context);
+ mFnPtrs->destroyContextPtr(mXDisplay, ctx);
+}
+Bool FunctionsGLX::makeCurrent(glx::Drawable drawable, glx::Context context) const
+{
+ GLXContext ctx = reinterpret_cast<GLXContext>(context);
+ return mFnPtrs->makeCurrentPtr(mXDisplay, drawable, ctx);
+}
+void FunctionsGLX::swapBuffers(glx::Drawable drawable) const
+{
+ mFnPtrs->swapBuffersPtr(mXDisplay, drawable);
+}
+Bool FunctionsGLX::queryExtension(int *errorBase, int *event) const
+{
+ return mFnPtrs->queryExtensionPtr(mXDisplay, errorBase, event);
+}
+Bool FunctionsGLX::queryVersion(int *major, int *minor) const
+{
+ return mFnPtrs->queryVersionPtr(mXDisplay, major, minor);
+}
+glx::Context FunctionsGLX::getCurrentContext() const
+{
+ GLXContext context = mFnPtrs->getCurrentContextPtr();
+ return reinterpret_cast<glx::Context>(context);
+}
+glx::Drawable FunctionsGLX::getCurrentDrawable() const
+{
+ GLXDrawable drawable = mFnPtrs->getCurrentDrawablePtr();
+ return reinterpret_cast<glx::Drawable>(drawable);
+}
+void FunctionsGLX::waitX() const
+{
+ mFnPtrs->waitXPtr();
+}
+void FunctionsGLX::waitGL() const
+{
+ mFnPtrs->waitGLPtr();
+}
+
+// GLX 1.1
+const char *FunctionsGLX::getClientString(int name) const
+{
+ return mFnPtrs->getClientStringPtr(mXDisplay, name);
+}
+
+const char *FunctionsGLX::queryExtensionsString() const
+{
+ return mFnPtrs->queryExtensionsStringPtr(mXDisplay, mXScreen);
+}
+
+// GLX 1.4
+glx::FBConfig *FunctionsGLX::getFBConfigs(int *nElements) const
+{
+ GLXFBConfig *configs = mFnPtrs->getFBConfigsPtr(mXDisplay, mXScreen, nElements);
+ return reinterpret_cast<glx::FBConfig*>(configs);
+}
+glx::FBConfig *FunctionsGLX::chooseFBConfig(const int *attribList, int *nElements) const
+{
+ GLXFBConfig *configs = mFnPtrs->chooseFBConfigPtr(mXDisplay, mXScreen, attribList, nElements);
+ return reinterpret_cast<glx::FBConfig*>(configs);
+}
+int FunctionsGLX::getFBConfigAttrib(glx::FBConfig config, int attribute, int *value) const
+{
+ GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config);
+ return mFnPtrs->getFBConfigAttribPtr(mXDisplay, cfg, attribute, value);
+}
+XVisualInfo *FunctionsGLX::getVisualFromFBConfig(glx::FBConfig config) const
+{
+ GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config);
+ return mFnPtrs->getVisualFromFBConfigPtr(mXDisplay, cfg);
+}
+GLXWindow FunctionsGLX::createWindow(glx::FBConfig config, Window window, const int *attribList) const
+{
+ GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config);
+ return mFnPtrs->createWindowPtr(mXDisplay, cfg, window, attribList);
+}
+void FunctionsGLX::destroyWindow(glx::Window window) const
+{
+ mFnPtrs->destroyWindowPtr(mXDisplay, window);
+}
+glx::Pbuffer FunctionsGLX::createPbuffer(glx::FBConfig config, const int *attribList) const
+{
+ GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config);
+ return mFnPtrs->createPbufferPtr(mXDisplay, cfg, attribList);
+}
+void FunctionsGLX::destroyPbuffer(glx::Pbuffer pbuffer) const
+{
+ mFnPtrs->destroyPbufferPtr(mXDisplay, pbuffer);
+}
+void FunctionsGLX::queryDrawable(glx::Drawable drawable, int attribute, unsigned int *value) const
+{
+ mFnPtrs->queryDrawablePtr(mXDisplay, drawable, attribute, value);
+}
+
+// GLX_ARB_create_context
+glx::Context FunctionsGLX::createContextAttribsARB(glx::FBConfig config, glx::Context shareContext, Bool direct, const int *attribList) const
+{
+ GLXContext shareCtx = reinterpret_cast<GLXContext>(shareContext);
+ GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config);
+ GLXContext ctx = mFnPtrs->createContextAttribsARBPtr(mXDisplay, cfg, shareCtx, direct, attribList);
+ return reinterpret_cast<glx::Context>(ctx);
+}
+
+void FunctionsGLX::swapIntervalEXT(glx::Drawable drawable, int intervals) const
+{
+ mFnPtrs->swapIntervalEXTPtr(mXDisplay, drawable, intervals);
+}
+
+int FunctionsGLX::swapIntervalMESA(int intervals) const
+{
+ return mFnPtrs->swapIntervalMESAPtr(intervals);
+}
+
+int FunctionsGLX::swapIntervalSGI(int intervals) const
+{
+ return mFnPtrs->swapIntervalSGIPtr(intervals);
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.h b/gfx/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.h
new file mode 100755
index 000000000..98c2fef46
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.h
@@ -0,0 +1,96 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// FunctionsGLX.h: Defines the FunctionsGLX class to load functions and data from GLX
+
+#ifndef LIBANGLE_RENDERER_GL_GLX_FUNCTIONSGLX_H_
+#define LIBANGLE_RENDERER_GL_GLX_FUNCTIONSGLX_H_
+
+#include <string>
+#include <vector>
+
+#include "libANGLE/renderer/gl/glx/platform_glx.h"
+
+namespace rx
+{
+
+class FunctionsGLX
+{
+ public:
+ FunctionsGLX();
+ ~FunctionsGLX();
+
+ // Load data from GLX, can be called multiple times
+ bool initialize(Display *xDisplay, int screen, std::string *errorString);
+ void terminate();
+
+ bool hasExtension(const char *extension) const;
+ int majorVersion;
+ int minorVersion;
+
+ Display *getDisplay() const;
+ int getScreen() const;
+
+ PFNGETPROCPROC getProc;
+
+ // GLX 1.0
+ glx::Context createContext(XVisualInfo *visual, glx::Context share, bool direct) const;
+ void destroyContext(glx::Context context) const;
+ Bool makeCurrent(glx::Drawable drawable, glx::Context context) const;
+ void swapBuffers(glx::Drawable drawable) const;
+ Bool queryExtension(int *errorBase, int *event) const;
+ Bool queryVersion(int *major, int *minor) const;
+ glx::Context getCurrentContext() const;
+ glx::Drawable getCurrentDrawable() const;
+ void waitX() const;
+ void waitGL() const;
+
+ // GLX 1.1
+ const char *getClientString(int name) const;
+ const char *queryExtensionsString() const;
+
+ // GLX 1.3
+ glx::FBConfig *getFBConfigs(int *nElements) const;
+ glx::FBConfig *chooseFBConfig(const int *attribList, int *nElements) const;
+ int getFBConfigAttrib(glx::FBConfig config, int attribute, int *value) const;
+ XVisualInfo *getVisualFromFBConfig(glx::FBConfig config) const;
+ glx::Window createWindow(glx::FBConfig config, Window window, const int *attribList) const;
+ void destroyWindow(glx::Window window) const;
+ glx::Pbuffer createPbuffer(glx::FBConfig config, const int *attribList) const;
+ void destroyPbuffer(glx::Pbuffer pbuffer) const;
+ void queryDrawable(glx::Drawable drawable, int attribute, unsigned int *value) const;
+
+ // GLX_ARB_create_context
+ glx::Context createContextAttribsARB(glx::FBConfig config, glx::Context shareContext, Bool direct, const int *attribList) const;
+
+ // GLX_EXT_swap_control
+ void swapIntervalEXT(glx::Drawable drawable, int interval) const;
+
+ // GLX_MESA_swap_control
+ int swapIntervalMESA(int interval) const;
+
+ // GLX_SGI_swap_control
+ int swapIntervalSGI(int interval) const;
+
+ private:
+ // So as to isolate GLX from angle we do not include angleutils.h and cannot
+ // use angle::NonCopyable so we replicated it here instead.
+ FunctionsGLX(const FunctionsGLX&) = delete;
+ void operator=(const FunctionsGLX&) = delete;
+
+ struct GLXFunctionTable;
+
+ static void *sLibHandle;
+ Display *mXDisplay;
+ int mXScreen;
+
+ GLXFunctionTable *mFnPtrs;
+ std::vector<std::string> mExtensions;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_GLX_FUNCTIONSGLX_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.cpp b/gfx/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.cpp
new file mode 100755
index 000000000..a97021b40
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.cpp
@@ -0,0 +1,143 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// PbufferSurfaceGLX.cpp: GLX implementation of egl::Surface for PBuffers
+
+#include "libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h"
+
+#include "common/debug.h"
+#include "libANGLE/renderer/gl/glx/DisplayGLX.h"
+#include "libANGLE/renderer/gl/glx/FunctionsGLX.h"
+
+namespace rx
+{
+
+PbufferSurfaceGLX::PbufferSurfaceGLX(const egl::SurfaceState &state,
+ RendererGL *renderer,
+ EGLint width,
+ EGLint height,
+ bool largest,
+ const FunctionsGLX &glx,
+ glx::Context context,
+ glx::FBConfig fbConfig)
+ : SurfaceGLX(state, renderer),
+ mWidth(width),
+ mHeight(height),
+ mLargest(largest),
+ mGLX(glx),
+ mContext(context),
+ mFBConfig(fbConfig),
+ mPbuffer(0)
+{
+}
+
+PbufferSurfaceGLX::~PbufferSurfaceGLX()
+{
+ if (mPbuffer)
+ {
+ mGLX.destroyPbuffer(mPbuffer);
+ }
+}
+
+egl::Error PbufferSurfaceGLX::initialize()
+{
+ // Avoid creating 0-sized PBuffers as it fails on the Intel Mesa driver
+ // as commented on https://bugs.freedesktop.org/show_bug.cgi?id=38869 so we
+ // use (w, 1) or (1, h) instead.
+ int width = std::max(1, static_cast<int>(mWidth));
+ int height = std::max(1, static_cast<int>(mHeight));
+
+ const int attribs[] =
+ {
+ GLX_PBUFFER_WIDTH, width,
+ GLX_PBUFFER_HEIGHT, height,
+ GLX_LARGEST_PBUFFER, mLargest,
+ None
+ };
+
+ mPbuffer = mGLX.createPbuffer(mFBConfig, attribs);
+ if (!mPbuffer)
+ {
+ return egl::Error(EGL_BAD_ALLOC, "Failed to create a native GLX pbuffer.");
+ }
+
+ if (mLargest)
+ {
+ mGLX.queryDrawable(mPbuffer, GLX_WIDTH, &mWidth);
+ mGLX.queryDrawable(mPbuffer, GLX_HEIGHT, &mHeight);
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceGLX::makeCurrent()
+{
+ if (mGLX.makeCurrent(mPbuffer, mContext) != True)
+ {
+ return egl::Error(EGL_BAD_DISPLAY);
+ }
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceGLX::swap()
+{
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceGLX::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceGLX::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceGLX::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceGLX::releaseTexImage(EGLint buffer)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+void PbufferSurfaceGLX::setSwapInterval(EGLint interval)
+{
+}
+
+EGLint PbufferSurfaceGLX::getWidth() const
+{
+ return mWidth;
+}
+
+EGLint PbufferSurfaceGLX::getHeight() const
+{
+ return mHeight;
+}
+
+EGLint PbufferSurfaceGLX::isPostSubBufferSupported() const
+{
+ UNIMPLEMENTED();
+ return EGL_FALSE;
+}
+
+EGLint PbufferSurfaceGLX::getSwapBehavior() const
+{
+ return EGL_BUFFER_PRESERVED;
+}
+
+egl::Error PbufferSurfaceGLX::checkForResize()
+{
+ // The size of pbuffers never change
+ return egl::Error(EGL_SUCCESS);
+}
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h b/gfx/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h
new file mode 100755
index 000000000..d346634b2
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h
@@ -0,0 +1,64 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// PBufferSurfaceGLX.h: GLX implementation of egl::Surface for PBuffers
+
+#ifndef LIBANGLE_RENDERER_GL_GLX_PBUFFERSURFACEGLX_H_
+#define LIBANGLE_RENDERER_GL_GLX_PBUFFERSURFACEGLX_H_
+
+#include "libANGLE/renderer/gl/glx/platform_glx.h"
+#include "libANGLE/renderer/gl/glx/SurfaceGLX.h"
+
+namespace rx
+{
+
+class FunctionsGLX;
+
+class PbufferSurfaceGLX : public SurfaceGLX
+{
+ public:
+ PbufferSurfaceGLX(const egl::SurfaceState &state,
+ RendererGL *renderer,
+ EGLint width,
+ EGLint height,
+ bool largest,
+ const FunctionsGLX &glx,
+ glx::Context context,
+ glx::FBConfig fbConfig);
+ ~PbufferSurfaceGLX() override;
+
+ egl::Error initialize() override;
+ egl::Error makeCurrent() override;
+
+ egl::Error swap() override;
+ egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+ egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+ egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+ egl::Error releaseTexImage(EGLint buffer) override;
+ void setSwapInterval(EGLint interval) override;
+
+ EGLint getWidth() const override;
+ EGLint getHeight() const override;
+
+ EGLint isPostSubBufferSupported() const override;
+ EGLint getSwapBehavior() const override;
+
+ egl::Error checkForResize() override;
+
+ private:
+ unsigned mWidth;
+ unsigned mHeight;
+ bool mLargest;
+
+ const FunctionsGLX &mGLX;
+ glx::Context mContext;
+ glx::FBConfig mFBConfig;
+ glx::Pbuffer mPbuffer;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_GLX_PBUFFERSURFACEGLX_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/SurfaceGLX.h b/gfx/angle/src/libANGLE/renderer/gl/glx/SurfaceGLX.h
new file mode 100755
index 000000000..813516e80
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/glx/SurfaceGLX.h
@@ -0,0 +1,26 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SurfaceGLX.h: common interface for GLX surfaces
+
+#ifndef LIBANGLE_RENDERER_GL_GLX_SURFACEGLX_H_
+#define LIBANGLE_RENDERER_GL_GLX_SURFACEGLX_H_
+
+#include "libANGLE/renderer/gl/SurfaceGL.h"
+
+namespace rx
+{
+
+class SurfaceGLX : public SurfaceGL
+{
+ public:
+ SurfaceGLX(const egl::SurfaceState &state, RendererGL *renderer) : SurfaceGL(state, renderer) {}
+
+ virtual egl::Error checkForResize() = 0;
+};
+}
+
+#endif // LIBANGLE_RENDERER_GL_GLX_SURFACEGLX_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.cpp b/gfx/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.cpp
new file mode 100755
index 000000000..21b1b316f
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.cpp
@@ -0,0 +1,244 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// WindowSurfaceGLX.cpp: GLX implementation of egl::Surface for windows
+
+#include "libANGLE/renderer/gl/glx/WindowSurfaceGLX.h"
+
+#include "common/debug.h"
+
+#include "libANGLE/renderer/gl/glx/DisplayGLX.h"
+#include "libANGLE/renderer/gl/glx/FunctionsGLX.h"
+
+namespace rx
+{
+
+static int IgnoreX11Errors(Display *, XErrorEvent *)
+{
+ return 0;
+}
+
+WindowSurfaceGLX::WindowSurfaceGLX(const egl::SurfaceState &state,
+ const FunctionsGLX &glx,
+ DisplayGLX *glxDisplay,
+ RendererGL *renderer,
+ Window window,
+ Display *display,
+ glx::Context context,
+ glx::FBConfig fbConfig)
+ : SurfaceGLX(state, renderer),
+ mParent(window),
+ mWindow(0),
+ mDisplay(display),
+ mGLX(glx),
+ mGLXDisplay(glxDisplay),
+ mContext(context),
+ mFBConfig(fbConfig),
+ mGLXWindow(0)
+{
+}
+
+WindowSurfaceGLX::~WindowSurfaceGLX()
+{
+ if (mGLXWindow)
+ {
+ mGLX.destroyWindow(mGLXWindow);
+ }
+
+ if (mWindow)
+ {
+ // When destroying the window, it may happen that the window has already been
+ // destroyed by the application (this happens in Chromium). There is no way to
+ // atomically check that a window exists and to destroy it so instead we call
+ // XDestroyWindow, ignoring any errors.
+ auto oldErrorHandler = XSetErrorHandler(IgnoreX11Errors);
+ XDestroyWindow(mDisplay, mWindow);
+ XSync(mDisplay, False);
+ XSetErrorHandler(oldErrorHandler);
+ }
+
+ mGLXDisplay->syncXCommands();
+}
+
+egl::Error WindowSurfaceGLX::initialize()
+{
+ // Check that the window's visual ID is valid, as part of the AMGLE_x11_visual
+ // extension.
+ {
+ XWindowAttributes windowAttributes;
+ XGetWindowAttributes(mDisplay, mParent, &windowAttributes);
+ unsigned long visualId = windowAttributes.visual->visualid;
+
+ if (!mGLXDisplay->isValidWindowVisualId(visualId))
+ {
+ return egl::Error(EGL_BAD_MATCH,
+ "The visual of native_window doesn't match the visual given with "
+ "ANGLE_X11_VISUAL_ID");
+ }
+ }
+
+ // The visual of the X window, GLX window and GLX context must match,
+ // however we received a user-created window that can have any visual
+ // and wouldn't work with our GLX context. To work in all cases, we
+ // create a child window with the right visual that covers all of its
+ // parent.
+ XVisualInfo *visualInfo = mGLX.getVisualFromFBConfig(mFBConfig);
+ if (!visualInfo)
+ {
+ return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to get the XVisualInfo for the child window.");
+ }
+ Visual* visual = visualInfo->visual;
+
+ if (!getWindowDimensions(mParent, &mParentWidth, &mParentHeight))
+ {
+ return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to get the parent window's dimensions.");
+ }
+
+ // The depth, colormap and visual must match otherwise we get a X error
+ // so we specify the colormap attribute. Also we do not want the window
+ // to be taken into account for input so we specify the event and
+ // do-not-propagate masks to 0 (the defaults). Finally we specify the
+ // border pixel attribute so that we can use a different visual depth
+ // than our parent (seems like X uses that as a condition to render
+ // the subwindow in a different buffer)
+ XSetWindowAttributes attributes;
+ unsigned long attributeMask = CWColormap | CWBorderPixel;
+
+ Colormap colormap = XCreateColormap(mDisplay, mParent, visual, AllocNone);
+ if(!colormap)
+ {
+ XFree(visualInfo);
+ return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to create the Colormap for the child window.");
+ }
+ attributes.colormap = colormap;
+ attributes.border_pixel = 0;
+
+ //TODO(cwallez) set up our own error handler to see if the call failed
+ mWindow = XCreateWindow(mDisplay, mParent, 0, 0, mParentWidth, mParentHeight,
+ 0, visualInfo->depth, InputOutput, visual, attributeMask, &attributes);
+ mGLXWindow = mGLX.createWindow(mFBConfig, mWindow, nullptr);
+
+ XMapWindow(mDisplay, mWindow);
+ XFlush(mDisplay);
+
+ XFree(visualInfo);
+ XFreeColormap(mDisplay, colormap);
+
+ mGLXDisplay->syncXCommands();
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceGLX::makeCurrent()
+{
+ if (mGLX.makeCurrent(mGLXWindow, mContext) != True)
+ {
+ return egl::Error(EGL_BAD_DISPLAY);
+ }
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceGLX::swap()
+{
+ // We need to swap before resizing as some drivers clobber the back buffer
+ // when the window is resized.
+ mGLXDisplay->setSwapInterval(mGLXWindow, &mSwapControl);
+ mGLX.swapBuffers(mGLXWindow);
+
+ egl::Error error = checkForResize();
+ if (error.isError())
+ {
+ return error;
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceGLX::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceGLX::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceGLX::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceGLX::releaseTexImage(EGLint buffer)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+void WindowSurfaceGLX::setSwapInterval(EGLint interval)
+{
+ mSwapControl.targetSwapInterval = interval;
+}
+
+EGLint WindowSurfaceGLX::getWidth() const
+{
+ // The size of the window is always the same as the cached size of its parent.
+ return mParentWidth;
+}
+
+EGLint WindowSurfaceGLX::getHeight() const
+{
+ // The size of the window is always the same as the cached size of its parent.
+ return mParentHeight;
+}
+
+EGLint WindowSurfaceGLX::isPostSubBufferSupported() const
+{
+ UNIMPLEMENTED();
+ return EGL_FALSE;
+}
+
+EGLint WindowSurfaceGLX::getSwapBehavior() const
+{
+ return EGL_BUFFER_PRESERVED;
+}
+
+egl::Error WindowSurfaceGLX::checkForResize()
+{
+ // TODO(cwallez) set up our own error handler to see if the call failed
+ unsigned int newParentWidth, newParentHeight;
+ if (!getWindowDimensions(mParent, &newParentWidth, &newParentHeight))
+ {
+ return egl::Error(EGL_BAD_CURRENT_SURFACE,
+ "Failed to retrieve the size of the parent window.");
+ }
+
+ if (mParentWidth != newParentWidth || mParentHeight != newParentHeight)
+ {
+ mParentWidth = newParentWidth;
+ mParentHeight = newParentHeight;
+
+ mGLX.waitGL();
+ XResizeWindow(mDisplay, mWindow, mParentWidth, mParentHeight);
+ mGLX.waitX();
+ XSync(mDisplay, False);
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+bool WindowSurfaceGLX::getWindowDimensions(Window window, unsigned int *width, unsigned int *height) const
+{
+ Window root;
+ int x, y;
+ unsigned int border, depth;
+ return XGetGeometry(mDisplay, window, &root, &x, &y, width, height, &border, &depth) != 0;
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.h b/gfx/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.h
new file mode 100755
index 000000000..0cdda96e6
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.h
@@ -0,0 +1,73 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// WindowSurfaceGLX.h: GLX implementation of egl::Surface for windows
+
+#ifndef LIBANGLE_RENDERER_GL_GLX_WINDOWSURFACEGLX_H_
+#define LIBANGLE_RENDERER_GL_GLX_WINDOWSURFACEGLX_H_
+
+#include "libANGLE/renderer/gl/glx/DisplayGLX.h"
+#include "libANGLE/renderer/gl/glx/platform_glx.h"
+#include "libANGLE/renderer/gl/glx/SurfaceGLX.h"
+
+namespace rx
+{
+
+class DisplayGLX;
+class FunctionsGLX;
+
+class WindowSurfaceGLX : public SurfaceGLX
+{
+ public:
+ WindowSurfaceGLX(const egl::SurfaceState &state,
+ const FunctionsGLX &glx,
+ DisplayGLX *glxDisplay,
+ RendererGL *renderer,
+ Window window,
+ Display *display,
+ glx::Context context,
+ glx::FBConfig fbConfig);
+ ~WindowSurfaceGLX() override;
+
+ egl::Error initialize() override;
+ egl::Error makeCurrent() override;
+
+ egl::Error swap() override;
+ egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+ egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+ egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+ egl::Error releaseTexImage(EGLint buffer) override;
+ void setSwapInterval(EGLint interval) override;
+
+ EGLint getWidth() const override;
+ EGLint getHeight() const override;
+
+ EGLint isPostSubBufferSupported() const override;
+ EGLint getSwapBehavior() const override;
+
+ egl::Error checkForResize() override;
+
+ private:
+ bool getWindowDimensions(Window window, unsigned int *width, unsigned int *height) const;
+
+ Window mParent;
+ unsigned int mParentWidth, mParentHeight;
+ Window mWindow;
+ Display *mDisplay;
+
+ const FunctionsGLX &mGLX;
+ DisplayGLX *mGLXDisplay;
+
+ glx::Context mContext;
+ glx::FBConfig mFBConfig;
+ glx::Window mGLXWindow;
+
+ SwapControlData mSwapControl;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_GLX_WINDOWSURFACEGLX_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/functionsglx_typedefs.h b/gfx/angle/src/libANGLE/renderer/gl/glx/functionsglx_typedefs.h
new file mode 100755
index 000000000..b0ba033c7
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/glx/functionsglx_typedefs.h
@@ -0,0 +1,52 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// functionsglx_typedefs.h: Typedefs of GLX functions.
+
+#ifndef LIBANGLE_RENDERER_GL_GLX_FUNCTIONSGLXTYPEDEFS_H_
+#define LIBANGLE_RENDERER_GL_GLX_FUNCTIONSGLXTYPEDEFS_H_
+
+#include "libANGLE/renderer/gl/glx/platform_glx.h"
+
+namespace rx
+{
+
+// Only the functions of GLX 1.2 and earlier need to be typdefed; the other
+// functions are already typedefed in glx.h
+
+// GLX 1.0
+typedef XVisualInfo *(*PFNGLXCHOOSEVISUALPROC) (Display *dpy, int screen, int *attribList);
+typedef GLXContext (*PFNGLXCREATECONTEXTPROC) (Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct);
+typedef void (*PFNGLXDESTROYCONTEXTPROC) (Display *dpy, GLXContext ctx);
+typedef Bool (*PFNGLXMAKECURRENTPROC) (Display *dpy, GLXDrawable drawable, GLXContext ctx);
+typedef void (*PFNGLXCOPYCONTEXTPROC) (Display *dpy, GLXContext src, GLXContext dst, unsigned long mask);
+typedef void (*PFNGLXSWAPBUFFERSPROC) (Display *dpy, GLXDrawable drawable);
+typedef GLXPixmap (*PFNGLXCREATEGLXPIXMAPPROC) (Display *dpy, XVisualInfo *visual, Pixmap pixmap);
+typedef void (*PFNGLXDESTROYGLXPIXMAPPROC) (Display *dpy, GLXPixmap pixmap);
+typedef Bool (*PFNGLXQUERYEXTENSIONPROC) (Display *dpy, int *errorb, int *event);
+typedef Bool (*PFNGLXQUERYVERSIONPROC) (Display *dpy, int *maj, int *min);
+typedef Bool (*PFNGLXISDIRECTPROC) (Display *dpy, GLXContext ctx);
+typedef int (*PFNGLXGETCONFIGPROC) (Display *dpy, XVisualInfo *visual, int attrib, int *value);
+typedef GLXContext (*PFNGLXGETCURRENTCONTEXTPROC) ();
+typedef GLXDrawable (*PFNGLXGETCURRENTDRAWABLEPROC) ();
+typedef GLXContext (*PFNGLXGETCURRENTCONTEXTPROC) ();
+typedef GLXDrawable (*PFNGLXGETCURRENTDRAWABLEPROC) ();
+typedef void (*PFNGLXWAITGLPROC) ();
+typedef void (*PFNGLXWAITXPROC) ();
+typedef void (*PFNGLXUSEXFONT) (Font font, int first, int count, int list);
+
+// GLX 1.1
+typedef const char *(*PFNGLXQUERYEXTENSIONSSTRINGPROC) (Display *dpy, int screen);
+typedef const char *(*PFNGLXQUERYSERVERSTRINGPROC) (Display *dpy, int screen, int name);
+typedef const char *(*PFNGLXGETCLIENTSTRINGPROC) (Display *dpy, int name);
+
+
+// GLX 1.2
+typedef Display *(*PFNGLXGETCURRENTDISPLAYPROC) ();
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_GLX_FUNCTIONSGLXTYPEDEFS_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/platform_glx.h b/gfx/angle/src/libANGLE/renderer/gl/glx/platform_glx.h
new file mode 100755
index 000000000..3ffb609d5
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/glx/platform_glx.h
@@ -0,0 +1,190 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// platform_glx.h: Includes specific to GLX.
+
+#ifndef LIBANGLE_RENDERER_GL_GLX_PLATFORMGLX_H_
+#define LIBANGLE_RENDERER_GL_GLX_PLATFORMGLX_H_
+
+#if !defined(ANGLE_SKIP_GLX_DEFINES)
+// GLX 1.0
+#define GLX_USE_GL 1
+#define GLX_BUFFER_SIZE 2
+#define GLX_LEVEL 3
+#define GLX_RGBA 4
+#define GLX_DOUBLEBUFFER 5
+#define GLX_STEREO 6
+#define GLX_AUX_BUFFERS 7
+#define GLX_RED_SIZE 8
+#define GLX_GREEN_SIZE 9
+#define GLX_BLUE_SIZE 10
+#define GLX_ALPHA_SIZE 11
+#define GLX_DEPTH_SIZE 12
+#define GLX_STENCIL_SIZE 13
+#define GLX_ACCUM_RED_SIZE 14
+#define GLX_ACCUM_GREEN_SIZE 15
+#define GLX_ACCUM_BLUE_SIZE 16
+#define GLX_ACCUM_ALPHA_SIZE 17
+
+#define GLX_BAD_SCREEN 1
+#define GLX_BAD_ATTRIBUTE 2
+#define GLX_NO_EXTENSION 3
+#define GLX_BAD_VISUAL 4
+#define GLX_BAD_CONTEXT 5
+#define GLX_BAD_VALUE 6
+#define GLX_BAD_ENUM 7
+
+// GLX 1.1
+#define GLX_VENDOR 1
+#define GLX_VERSION 2
+#define GLX_EXTENSIONS 3
+
+// GLX 1.3
+#define GLX_CONFIG_CAVEAT 0x20
+#define GLX_DONT_CARE 0xFFFFFFFF
+#define GLX_X_VISUAL_TYPE 0x22
+#define GLX_TRANSPARENT_TYPE 0x23
+#define GLX_TRANSPARENT_INDEX_VALUE 0x24
+#define GLX_TRANSPARENT_RED_VALUE 0x25
+#define GLX_TRANSPARENT_GREEN_VALUE 0x26
+#define GLX_TRANSPARENT_BLUE_VALUE 0x27
+#define GLX_TRANSPARENT_ALPHA_VALUE 0x28
+#define GLX_WINDOW_BIT 0x00000001
+#define GLX_PIXMAP_BIT 0x00000002
+#define GLX_PBUFFER_BIT 0x00000004
+#define GLX_AUX_BUFFERS_BIT 0x00000010
+#define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001
+#define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002
+#define GLX_BACK_LEFT_BUFFER_BIT 0x00000004
+#define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008
+#define GLX_DEPTH_BUFFER_BIT 0x00000020
+#define GLX_STENCIL_BUFFER_BIT 0x00000040
+#define GLX_ACCUM_BUFFER_BIT 0x00000080
+#define GLX_NONE 0x8000
+#define GLX_SLOW_CONFIG 0x8001
+#define GLX_TRUE_COLOR 0x8002
+#define GLX_DIRECT_COLOR 0x8003
+#define GLX_PSEUDO_COLOR 0x8004
+#define GLX_STATIC_COLOR 0x8005
+#define GLX_GRAY_SCALE 0x8006
+#define GLX_STATIC_GRAY 0x8007
+#define GLX_TRANSPARENT_RGB 0x8008
+#define GLX_TRANSPARENT_INDEX 0x8009
+#define GLX_VISUAL_ID 0x800B
+#define GLX_SCREEN 0x800C
+#define GLX_NON_CONFORMANT_CONFIG 0x800D
+#define GLX_DRAWABLE_TYPE 0x8010
+#define GLX_RENDER_TYPE 0x8011
+#define GLX_X_RENDERABLE 0x8012
+#define GLX_FBCONFIG_ID 0x8013
+#define GLX_RGBA_TYPE 0x8014
+#define GLX_COLOR_INDEX_TYPE 0x8015
+#define GLX_MAX_PBUFFER_WIDTH 0x8016
+#define GLX_MAX_PBUFFER_HEIGHT 0x8017
+#define GLX_MAX_PBUFFER_PIXELS 0x8018
+#define GLX_PRESERVED_CONTENTS 0x801B
+#define GLX_LARGEST_PBUFFER 0x801C
+#define GLX_WIDTH 0x801D
+#define GLX_HEIGHT 0x801E
+#define GLX_EVENT_MASK 0x801F
+#define GLX_DAMAGED 0x8020
+#define GLX_SAVED 0x8021
+#define GLX_WINDOW 0x8022
+#define GLX_PBUFFER 0x8023
+#define GLX_PBUFFER_HEIGHT 0x8040
+#define GLX_PBUFFER_WIDTH 0x8041
+#define GLX_RGBA_BIT 0x00000001
+#define GLX_COLOR_INDEX_BIT 0x00000002
+#define GLX_PBUFFER_CLOBBER_MASK 0x08000000
+
+// GLX 1.4
+#define GLX_SAMPLE_BUFFERS 0x186a0
+#define GLX_SAMPLES 0x186a1
+
+// GLX_ARB_create_context
+#define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001
+#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
+#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
+#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
+#define GLX_CONTEXT_FLAGS_ARB 0x2094
+
+// GLX_ARB_create_context_profile
+#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
+
+// GLX_ARB_create_context_robustness
+#define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
+#define GLX_LOSE_CONTEXT_ON_RESET_ARB 0x8252
+#define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
+#define GLX_NO_RESET_NOTIFICATION_ARB 0x8261
+
+// GLX_EXT_create_context_es2_profile
+#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
+
+// GLX_EXT_texture_from_pixmap
+#define GLX_TEXTURE_1D_BIT_EXT 0x00000001
+#define GLX_TEXTURE_2D_BIT_EXT 0x00000002
+#define GLX_TEXTURE_RECTANGLE_BIT_EXT 0x00000004
+#define GLX_BIND_TO_TEXTURE_RGB_EXT 0x20D0
+#define GLX_BIND_TO_TEXTURE_RGBA_EXT 0x20D1
+#define GLX_BIND_TO_MIPMAP_TEXTURE_EXT 0x20D2
+#define GLX_BIND_TO_TEXTURE_TARGETS_EXT 0x20D3
+#define GLX_Y_INVERTED_EXT 0x20D4
+#define GLX_TEXTURE_FORMAT_EXT 0x20D5
+#define GLX_TEXTURE_TARGET_EXT 0x20D6
+#define GLX_MIPMAP_TEXTURE_EXT 0x20D7
+#define GLX_TEXTURE_FORMAT_NONE_EXT 0x20D8
+#define GLX_TEXTURE_FORMAT_RGB_EXT 0x20D9
+#define GLX_TEXTURE_FORMAT_RGBA_EXT 0x20DA
+#define GLX_TEXTURE_1D_EXT 0x20DB
+#define GLX_TEXTURE_2D_EXT 0x20DC
+#define GLX_TEXTURE_RECTANGLE_EXT 0x20DD
+#define GLX_FRONT_LEFT_EXT 0x20DE
+#define GLX_FRONT_RIGHT_EXT 0x20DF
+#define GLX_BACK_LEFT_EXT 0x20E0
+#define GLX_BACK_RIGHT_EXT 0x20E1
+#define GLX_FRONT_EXT 0x20DE
+#define GLX_BACK_EXT 0x20E0
+#define GLX_AUX0_EXT 0x20E2
+#define GLX_AUX1_EXT 0x20E3
+#define GLX_AUX2_EXT 0x20E4
+#define GLX_AUX3_EXT 0x20E5
+#define GLX_AUX4_EXT 0x20E6
+#define GLX_AUX5_EXT 0x20E7
+#define GLX_AUX6_EXT 0x20E8
+#define GLX_AUX7_EXT 0x20E9
+#define GLX_AUX8_EXT 0x20EA
+#define GLX_AUX9_EXT 0x20EB
+
+// GLX_EXT_swap_control
+#define GLX_SWAP_INTERVAL_EXT 0x20F1
+#define GLX_MAX_SWAP_INTERVAL_EXT 0x20F2
+#endif // !defined(ANGLE_SKIP_GLX_DEFINES)
+
+// GLX typedefs depend on the X headers
+#include <X11/Xlib.h>
+#include <X11/Xresource.h>
+#include <X11/Xutil.h>
+
+// GLX typedefs
+namespace glx
+{
+
+typedef void *Context;
+typedef void *FBConfig;
+typedef XID FBConfigID;
+typedef XID ContextID;
+typedef XID Window;
+typedef XID Pbuffer;
+typedef XID Pixmap;
+typedef XID Drawable;
+
+}
+
+typedef void* (*PFNGETPROCPROC) (const char *name);
+
+#endif // LIBANGLE_RENDERER_GL_GLX_PLATFORMGLX_H_