summaryrefslogtreecommitdiff
path: root/Source/ThirdParty/ANGLE/util/EGLWindow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/ThirdParty/ANGLE/util/EGLWindow.cpp')
-rw-r--r--Source/ThirdParty/ANGLE/util/EGLWindow.cpp395
1 files changed, 395 insertions, 0 deletions
diff --git a/Source/ThirdParty/ANGLE/util/EGLWindow.cpp b/Source/ThirdParty/ANGLE/util/EGLWindow.cpp
new file mode 100644
index 000000000..71ad51ea0
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/util/EGLWindow.cpp
@@ -0,0 +1,395 @@
+//
+// Copyright (c) 2013 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.
+//
+
+#include <string.h>
+#include <cassert>
+#include <vector>
+
+#include "EGLWindow.h"
+#include "OSWindow.h"
+#include "common/debug.h"
+
+EGLPlatformParameters::EGLPlatformParameters()
+ : renderer(EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE),
+ majorVersion(EGL_DONT_CARE),
+ minorVersion(EGL_DONT_CARE),
+ deviceType(EGL_DONT_CARE),
+ presentPath(EGL_DONT_CARE)
+{
+}
+
+EGLPlatformParameters::EGLPlatformParameters(EGLint renderer)
+ : renderer(renderer),
+ majorVersion(EGL_DONT_CARE),
+ minorVersion(EGL_DONT_CARE),
+ deviceType(EGL_DONT_CARE),
+ presentPath(EGL_DONT_CARE)
+{
+ if (renderer == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE ||
+ renderer == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+ {
+ deviceType = EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE;
+ }
+}
+
+EGLPlatformParameters::EGLPlatformParameters(EGLint renderer,
+ EGLint majorVersion,
+ EGLint minorVersion,
+ EGLint useWarp)
+ : renderer(renderer),
+ majorVersion(majorVersion),
+ minorVersion(minorVersion),
+ deviceType(useWarp),
+ presentPath(EGL_DONT_CARE)
+{
+}
+
+EGLPlatformParameters::EGLPlatformParameters(EGLint renderer,
+ EGLint majorVersion,
+ EGLint minorVersion,
+ EGLint useWarp,
+ EGLint presentPath)
+ : renderer(renderer),
+ majorVersion(majorVersion),
+ minorVersion(minorVersion),
+ deviceType(useWarp),
+ presentPath(presentPath)
+{
+}
+
+bool operator<(const EGLPlatformParameters &a, const EGLPlatformParameters &b)
+{
+ if (a.renderer != b.renderer)
+ {
+ return a.renderer < b.renderer;
+ }
+
+ if (a.majorVersion != b.majorVersion)
+ {
+ return a.majorVersion < b.majorVersion;
+ }
+
+ if (a.minorVersion != b.minorVersion)
+ {
+ return a.minorVersion < b.minorVersion;
+ }
+
+ if (a.deviceType != b.deviceType)
+ {
+ return a.deviceType < b.deviceType;
+ }
+
+ return a.presentPath < b.presentPath;
+}
+
+bool operator==(const EGLPlatformParameters &a, const EGLPlatformParameters &b)
+{
+ return (a.renderer == b.renderer) && (a.majorVersion == b.majorVersion) &&
+ (a.minorVersion == b.minorVersion) && (a.deviceType == b.deviceType) &&
+ (a.presentPath == b.presentPath);
+}
+
+EGLWindow::EGLWindow(EGLint glesMajorVersion,
+ EGLint glesMinorVersion,
+ const EGLPlatformParameters &platform)
+ : mDisplay(EGL_NO_DISPLAY),
+ mSurface(EGL_NO_SURFACE),
+ mContext(EGL_NO_CONTEXT),
+ mClientMajorVersion(glesMajorVersion),
+ mClientMinorVersion(glesMinorVersion),
+ mPlatform(platform),
+ mRedBits(-1),
+ mGreenBits(-1),
+ mBlueBits(-1),
+ mAlphaBits(-1),
+ mDepthBits(-1),
+ mStencilBits(-1),
+ mMultisample(false),
+ mDebug(false),
+ mNoError(false),
+ mWebGLCompatibility(false),
+ mBindGeneratesResource(true),
+ mSwapInterval(-1)
+{
+}
+
+EGLWindow::~EGLWindow()
+{
+ destroyGL();
+}
+
+void EGLWindow::swap()
+{
+ eglSwapBuffers(mDisplay, mSurface);
+}
+
+EGLConfig EGLWindow::getConfig() const
+{
+ return mConfig;
+}
+
+EGLDisplay EGLWindow::getDisplay() const
+{
+ return mDisplay;
+}
+
+EGLSurface EGLWindow::getSurface() const
+{
+ return mSurface;
+}
+
+EGLContext EGLWindow::getContext() const
+{
+ return mContext;
+}
+
+bool EGLWindow::initializeGL(OSWindow *osWindow)
+{
+ PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(eglGetProcAddress("eglGetPlatformDisplayEXT"));
+ if (!eglGetPlatformDisplayEXT)
+ {
+ return false;
+ }
+
+ std::vector<EGLint> displayAttributes;
+ displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
+ displayAttributes.push_back(mPlatform.renderer);
+ displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE);
+ displayAttributes.push_back(mPlatform.majorVersion);
+ displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE);
+ displayAttributes.push_back(mPlatform.minorVersion);
+
+ if (mPlatform.deviceType != EGL_DONT_CARE)
+ {
+ displayAttributes.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
+ displayAttributes.push_back(mPlatform.deviceType);
+ }
+
+ if (mPlatform.presentPath != EGL_DONT_CARE)
+ {
+ const char *extensionString =
+ static_cast<const char *>(eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS));
+ if (strstr(extensionString, "EGL_ANGLE_experimental_present_path") == nullptr)
+ {
+ destroyGL();
+ return false;
+ }
+
+ displayAttributes.push_back(EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE);
+ displayAttributes.push_back(mPlatform.presentPath);
+ }
+ displayAttributes.push_back(EGL_NONE);
+
+ mDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE,
+ reinterpret_cast<void *>(osWindow->getNativeDisplay()),
+ &displayAttributes[0]);
+ if (mDisplay == EGL_NO_DISPLAY)
+ {
+ destroyGL();
+ return false;
+ }
+
+ EGLint majorVersion, minorVersion;
+ if (eglInitialize(mDisplay, &majorVersion, &minorVersion) == EGL_FALSE)
+ {
+ destroyGL();
+ return false;
+ }
+
+ const char *displayExtensions = eglQueryString(mDisplay, EGL_EXTENSIONS);
+
+ // EGL_KHR_create_context is required to request a non-ES2 context.
+ bool hasKHRCreateContext = strstr(displayExtensions, "EGL_KHR_create_context") != nullptr;
+ if (majorVersion != 2 && minorVersion != 0 && !hasKHRCreateContext)
+ {
+ destroyGL();
+ return false;
+ }
+
+ bool hasWebGLCompatibility =
+ strstr(displayExtensions, "EGL_ANGLE_create_context_webgl_compatibility") != nullptr;
+ if (mWebGLCompatibility && !hasWebGLCompatibility)
+ {
+ destroyGL();
+ return false;
+ }
+
+ bool hasBindGeneratesResource =
+ strstr(displayExtensions, "EGL_CHROMIUM_create_context_bind_generates_resource") != nullptr;
+ if (!mBindGeneratesResource && !hasBindGeneratesResource)
+ {
+ destroyGL();
+ return false;
+ }
+
+ eglBindAPI(EGL_OPENGL_ES_API);
+ if (eglGetError() != EGL_SUCCESS)
+ {
+ destroyGL();
+ return false;
+ }
+
+ const EGLint configAttributes[] =
+ {
+ EGL_RED_SIZE, (mRedBits >= 0) ? mRedBits : EGL_DONT_CARE,
+ EGL_GREEN_SIZE, (mGreenBits >= 0) ? mGreenBits : EGL_DONT_CARE,
+ EGL_BLUE_SIZE, (mBlueBits >= 0) ? mBlueBits : EGL_DONT_CARE,
+ EGL_ALPHA_SIZE, (mAlphaBits >= 0) ? mAlphaBits : EGL_DONT_CARE,
+ EGL_DEPTH_SIZE, (mDepthBits >= 0) ? mDepthBits : EGL_DONT_CARE,
+ EGL_STENCIL_SIZE, (mStencilBits >= 0) ? mStencilBits : EGL_DONT_CARE,
+ EGL_SAMPLE_BUFFERS, mMultisample ? 1 : 0,
+ EGL_NONE
+ };
+
+ EGLint configCount;
+ if (!eglChooseConfig(mDisplay, configAttributes, &mConfig, 1, &configCount) || (configCount != 1))
+ {
+ destroyGL();
+ return false;
+ }
+
+ eglGetConfigAttrib(mDisplay, mConfig, EGL_RED_SIZE, &mRedBits);
+ eglGetConfigAttrib(mDisplay, mConfig, EGL_GREEN_SIZE, &mGreenBits);
+ eglGetConfigAttrib(mDisplay, mConfig, EGL_BLUE_SIZE, &mBlueBits);
+ eglGetConfigAttrib(mDisplay, mConfig, EGL_ALPHA_SIZE, &mAlphaBits);
+ eglGetConfigAttrib(mDisplay, mConfig, EGL_DEPTH_SIZE, &mDepthBits);
+ eglGetConfigAttrib(mDisplay, mConfig, EGL_STENCIL_SIZE, &mStencilBits);
+
+ std::vector<EGLint> surfaceAttributes;
+ if (strstr(displayExtensions, "EGL_NV_post_sub_buffer") != nullptr)
+ {
+ surfaceAttributes.push_back(EGL_POST_SUB_BUFFER_SUPPORTED_NV);
+ surfaceAttributes.push_back(EGL_TRUE);
+ }
+
+ surfaceAttributes.push_back(EGL_NONE);
+
+ mSurface = eglCreateWindowSurface(mDisplay, mConfig, osWindow->getNativeWindow(), &surfaceAttributes[0]);
+ if (eglGetError() != EGL_SUCCESS)
+ {
+ destroyGL();
+ return false;
+ }
+ ASSERT(mSurface != EGL_NO_SURFACE);
+
+ std::vector<EGLint> contextAttributes;
+ if (hasKHRCreateContext)
+ {
+ contextAttributes.push_back(EGL_CONTEXT_MAJOR_VERSION_KHR);
+ contextAttributes.push_back(mClientMajorVersion);
+
+ contextAttributes.push_back(EGL_CONTEXT_MINOR_VERSION_KHR);
+ contextAttributes.push_back(mClientMinorVersion);
+
+ contextAttributes.push_back(EGL_CONTEXT_OPENGL_DEBUG);
+ contextAttributes.push_back(mDebug ? EGL_TRUE : EGL_FALSE);
+
+ // TODO(jmadill): Check for the extension string.
+ // bool hasKHRCreateContextNoError = strstr(displayExtensions,
+ // "EGL_KHR_create_context_no_error") != nullptr;
+
+ contextAttributes.push_back(EGL_CONTEXT_OPENGL_NO_ERROR_KHR);
+ contextAttributes.push_back(mNoError ? EGL_TRUE : EGL_FALSE);
+
+ if (hasWebGLCompatibility)
+ {
+ contextAttributes.push_back(EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE);
+ contextAttributes.push_back(mWebGLCompatibility ? EGL_TRUE : EGL_FALSE);
+ }
+
+ if (hasBindGeneratesResource)
+ {
+ contextAttributes.push_back(EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM);
+ contextAttributes.push_back(mBindGeneratesResource ? EGL_TRUE : EGL_FALSE);
+ }
+ }
+ contextAttributes.push_back(EGL_NONE);
+
+ mContext = eglCreateContext(mDisplay, mConfig, nullptr, &contextAttributes[0]);
+ if (eglGetError() != EGL_SUCCESS)
+ {
+ destroyGL();
+ return false;
+ }
+
+ eglMakeCurrent(mDisplay, mSurface, mSurface, mContext);
+ if (eglGetError() != EGL_SUCCESS)
+ {
+ destroyGL();
+ return false;
+ }
+
+ if (mSwapInterval != -1)
+ {
+ eglSwapInterval(mDisplay, mSwapInterval);
+ }
+
+ return true;
+}
+
+void EGLWindow::destroyGL()
+{
+ if (mSurface != EGL_NO_SURFACE)
+ {
+ assert(mDisplay != EGL_NO_DISPLAY);
+ eglDestroySurface(mDisplay, mSurface);
+ mSurface = EGL_NO_SURFACE;
+ }
+
+ if (mContext != EGL_NO_CONTEXT)
+ {
+ assert(mDisplay != EGL_NO_DISPLAY);
+ eglDestroyContext(mDisplay, mContext);
+ mContext = EGL_NO_CONTEXT;
+ }
+
+ if (mDisplay != EGL_NO_DISPLAY)
+ {
+ eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglTerminate(mDisplay);
+ mDisplay = EGL_NO_DISPLAY;
+ }
+}
+
+bool EGLWindow::isGLInitialized() const
+{
+ return mSurface != EGL_NO_SURFACE &&
+ mContext != EGL_NO_CONTEXT &&
+ mDisplay != EGL_NO_DISPLAY;
+}
+
+// Find an EGLConfig that is an exact match for the specified attributes. EGL_FALSE is returned if
+// the EGLConfig is found. This indicates that the EGLConfig is not supported.
+EGLBoolean EGLWindow::FindEGLConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *config)
+{
+ EGLint numConfigs = 0;
+ eglGetConfigs(dpy, nullptr, 0, &numConfigs);
+ std::vector<EGLConfig> allConfigs(numConfigs);
+ eglGetConfigs(dpy, allConfigs.data(), static_cast<EGLint>(allConfigs.size()), &numConfigs);
+
+ for (size_t i = 0; i < allConfigs.size(); i++)
+ {
+ bool matchFound = true;
+ for (const EGLint *curAttrib = attrib_list; curAttrib[0] != EGL_NONE; curAttrib += 2)
+ {
+ EGLint actualValue = EGL_DONT_CARE;
+ eglGetConfigAttrib(dpy, allConfigs[i], curAttrib[0], &actualValue);
+ if (curAttrib[1] != actualValue)
+ {
+ matchFound = false;
+ break;
+ }
+ }
+
+ if (matchFound)
+ {
+ *config = allConfigs[i];
+ return EGL_TRUE;
+ }
+ }
+
+ return EGL_FALSE;
+}