diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/ThirdParty/ANGLE/util/EGLWindow.cpp | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/ThirdParty/ANGLE/util/EGLWindow.cpp')
-rw-r--r-- | Source/ThirdParty/ANGLE/util/EGLWindow.cpp | 395 |
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; +} |