summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/libEGL
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/libEGL')
-rw-r--r--src/3rdparty/angle/src/libEGL/Config.cpp399
-rw-r--r--src/3rdparty/angle/src/libEGL/Config.h118
-rw-r--r--src/3rdparty/angle/src/libEGL/Display.cpp1292
-rw-r--r--src/3rdparty/angle/src/libEGL/Display.h167
-rw-r--r--src/3rdparty/angle/src/libEGL/ShaderCache.h116
-rw-r--r--src/3rdparty/angle/src/libEGL/Surface.cpp674
-rw-r--r--src/3rdparty/angle/src/libEGL/Surface.h112
-rw-r--r--src/3rdparty/angle/src/libEGL/libEGL.cpp1181
-rw-r--r--src/3rdparty/angle/src/libEGL/libEGL.def36
-rw-r--r--src/3rdparty/angle/src/libEGL/libEGL.rc102
-rw-r--r--src/3rdparty/angle/src/libEGL/main.cpp165
-rw-r--r--src/3rdparty/angle/src/libEGL/main.h61
-rw-r--r--src/3rdparty/angle/src/libEGL/resource.h14
13 files changed, 4437 insertions, 0 deletions
diff --git a/src/3rdparty/angle/src/libEGL/Config.cpp b/src/3rdparty/angle/src/libEGL/Config.cpp
new file mode 100644
index 0000000000..89bc8d89f4
--- /dev/null
+++ b/src/3rdparty/angle/src/libEGL/Config.cpp
@@ -0,0 +1,399 @@
+//
+// Copyright (c) 2002-2010 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.
+//
+
+// Config.cpp: Implements the egl::Config class, describing the format, type
+// and size for an egl::Surface. Implements EGLConfig and related functionality.
+// [EGL 1.4] section 3.4 page 15.
+
+#include "libEGL/Config.h"
+
+#include <algorithm>
+#include <vector>
+
+#include "common/debug.h"
+
+using namespace std;
+
+namespace egl
+{
+Config::Config(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight)
+ : mDisplayMode(displayMode), mRenderTargetFormat(renderTargetFormat), mDepthStencilFormat(depthStencilFormat), mMultiSample(multiSample)
+{
+ set(displayMode, minInterval, maxInterval, renderTargetFormat, depthStencilFormat, multiSample, texWidth, texHeight);
+}
+
+void Config::setDefaults()
+{
+ mBufferSize = 0;
+ mRedSize = 0;
+ mGreenSize = 0;
+ mBlueSize = 0;
+ mLuminanceSize = 0;
+ mAlphaSize = 0;
+ mAlphaMaskSize = 0;
+ mBindToTextureRGB = EGL_DONT_CARE;
+ mBindToTextureRGBA = EGL_DONT_CARE;
+ mColorBufferType = EGL_RGB_BUFFER;
+ mConfigCaveat = EGL_DONT_CARE;
+ mConfigID = EGL_DONT_CARE;
+ mConformant = 0;
+ mDepthSize = 0;
+ mLevel = 0;
+ mMatchNativePixmap = EGL_NONE;
+ mMaxPBufferWidth = 0;
+ mMaxPBufferHeight = 0;
+ mMaxPBufferPixels = 0;
+ mMaxSwapInterval = EGL_DONT_CARE;
+ mMinSwapInterval = EGL_DONT_CARE;
+ mNativeRenderable = EGL_DONT_CARE;
+ mNativeVisualID = 0;
+ mNativeVisualType = EGL_DONT_CARE;
+ mRenderableType = EGL_OPENGL_ES_BIT;
+ mSampleBuffers = 0;
+ mSamples = 0;
+ mStencilSize = 0;
+ mSurfaceType = EGL_WINDOW_BIT;
+ mTransparentType = EGL_NONE;
+ mTransparentRedValue = EGL_DONT_CARE;
+ mTransparentGreenValue = EGL_DONT_CARE;
+ mTransparentBlueValue = EGL_DONT_CARE;
+}
+
+void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight)
+{
+ mBindToTextureRGB = EGL_FALSE;
+ mBindToTextureRGBA = EGL_FALSE;
+ switch (renderTargetFormat)
+ {
+ case D3DFMT_A1R5G5B5:
+ mBufferSize = 16;
+ mRedSize = 5;
+ mGreenSize = 5;
+ mBlueSize = 5;
+ mAlphaSize = 1;
+ break;
+ case D3DFMT_A2R10G10B10:
+ mBufferSize = 32;
+ mRedSize = 10;
+ mGreenSize = 10;
+ mBlueSize = 10;
+ mAlphaSize = 2;
+ break;
+ case D3DFMT_A8R8G8B8:
+ mBufferSize = 32;
+ mRedSize = 8;
+ mGreenSize = 8;
+ mBlueSize = 8;
+ mAlphaSize = 8;
+ mBindToTextureRGBA = true;
+ break;
+ case D3DFMT_R5G6B5:
+ mBufferSize = 16;
+ mRedSize = 5;
+ mGreenSize = 6;
+ mBlueSize = 5;
+ mAlphaSize = 0;
+ break;
+ case D3DFMT_X8R8G8B8:
+ mBufferSize = 32;
+ mRedSize = 8;
+ mGreenSize = 8;
+ mBlueSize = 8;
+ mAlphaSize = 0;
+ mBindToTextureRGB = true;
+ break;
+ default:
+ UNREACHABLE(); // Other formats should not be valid
+ }
+
+ mLuminanceSize = 0;
+ mAlphaMaskSize = 0;
+ mColorBufferType = EGL_RGB_BUFFER;
+ mConfigCaveat = (displayMode.Format == renderTargetFormat) ? EGL_NONE : EGL_SLOW_CONFIG;
+ mConfigID = 0;
+ mConformant = EGL_OPENGL_ES2_BIT;
+
+ switch (depthStencilFormat)
+ {
+ case D3DFMT_UNKNOWN:
+ mDepthSize = 0;
+ mStencilSize = 0;
+ break;
+// case D3DFMT_D16_LOCKABLE:
+// mDepthSize = 16;
+// mStencilSize = 0;
+// break;
+ case D3DFMT_D32:
+ mDepthSize = 32;
+ mStencilSize = 0;
+ break;
+ case D3DFMT_D15S1:
+ mDepthSize = 15;
+ mStencilSize = 1;
+ break;
+ case D3DFMT_D24S8:
+ mDepthSize = 24;
+ mStencilSize = 8;
+ break;
+ case D3DFMT_D24X8:
+ mDepthSize = 24;
+ mStencilSize = 0;
+ break;
+ case D3DFMT_D24X4S4:
+ mDepthSize = 24;
+ mStencilSize = 4;
+ break;
+ case D3DFMT_D16:
+ mDepthSize = 16;
+ mStencilSize = 0;
+ break;
+// case D3DFMT_D32F_LOCKABLE:
+// mDepthSize = 32;
+// mStencilSize = 0;
+// break;
+// case D3DFMT_D24FS8:
+// mDepthSize = 24;
+// mStencilSize = 8;
+// break;
+ default:
+ UNREACHABLE();
+ }
+
+ mLevel = 0;
+ mMatchNativePixmap = EGL_NONE;
+ mMaxPBufferWidth = texWidth;
+ mMaxPBufferHeight = texHeight;
+ mMaxPBufferPixels = texWidth*texHeight;
+ mMaxSwapInterval = maxInterval;
+ mMinSwapInterval = minInterval;
+ mNativeRenderable = EGL_FALSE;
+ mNativeVisualID = 0;
+ mNativeVisualType = 0;
+ mRenderableType = EGL_OPENGL_ES2_BIT;
+ mSampleBuffers = multiSample ? 1 : 0;
+ mSamples = multiSample;
+ mSurfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
+ mTransparentType = EGL_NONE;
+ mTransparentRedValue = 0;
+ mTransparentGreenValue = 0;
+ mTransparentBlueValue = 0;
+}
+
+EGLConfig Config::getHandle() const
+{
+ return (EGLConfig)(size_t)mConfigID;
+}
+
+SortConfig::SortConfig(const EGLint *attribList)
+ : mWantRed(false), mWantGreen(false), mWantBlue(false), mWantAlpha(false), mWantLuminance(false)
+{
+ scanForWantedComponents(attribList);
+}
+
+void SortConfig::scanForWantedComponents(const EGLint *attribList)
+{
+ // [EGL] section 3.4.1 page 24
+ // Sorting rule #3: by larger total number of color bits, not considering
+ // components that are 0 or don't-care.
+ for (const EGLint *attr = attribList; attr[0] != EGL_NONE; attr += 2)
+ {
+ if (attr[1] != 0 && attr[1] != EGL_DONT_CARE)
+ {
+ switch (attr[0])
+ {
+ case EGL_RED_SIZE: mWantRed = true; break;
+ case EGL_GREEN_SIZE: mWantGreen = true; break;
+ case EGL_BLUE_SIZE: mWantBlue = true; break;
+ case EGL_ALPHA_SIZE: mWantAlpha = true; break;
+ case EGL_LUMINANCE_SIZE: mWantLuminance = true; break;
+ }
+ }
+ }
+}
+
+EGLint SortConfig::wantedComponentsSize(const Config &config) const
+{
+ EGLint total = 0;
+
+ if (mWantRed) total += config.mRedSize;
+ if (mWantGreen) total += config.mGreenSize;
+ if (mWantBlue) total += config.mBlueSize;
+ if (mWantAlpha) total += config.mAlphaSize;
+ if (mWantLuminance) total += config.mLuminanceSize;
+
+ return total;
+}
+
+bool SortConfig::operator()(const Config *x, const Config *y) const
+{
+ return (*this)(*x, *y);
+}
+
+bool SortConfig::operator()(const Config &x, const Config &y) const
+{
+ #define SORT(attribute) \
+ if (x.attribute != y.attribute) \
+ { \
+ return x.attribute < y.attribute; \
+ }
+
+ META_ASSERT(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG);
+ SORT(mConfigCaveat);
+
+ META_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER);
+ SORT(mColorBufferType);
+
+ // By larger total number of color bits, only considering those that are requested to be > 0.
+ EGLint xComponentsSize = wantedComponentsSize(x);
+ EGLint yComponentsSize = wantedComponentsSize(y);
+ if (xComponentsSize != yComponentsSize)
+ {
+ return xComponentsSize > yComponentsSize;
+ }
+
+ SORT(mBufferSize);
+ SORT(mSampleBuffers);
+ SORT(mSamples);
+ SORT(mDepthSize);
+ SORT(mStencilSize);
+ SORT(mAlphaMaskSize);
+ SORT(mNativeVisualType);
+ SORT(mConfigID);
+
+ #undef SORT
+
+ return false;
+}
+
+// We'd like to use SortConfig to also eliminate duplicate configs.
+// This works as long as we never have two configs with different per-RGB-component layouts,
+// but the same total.
+// 5551 and 565 are different because R+G+B is different.
+// 5551 and 555 are different because bufferSize is different.
+const EGLint ConfigSet::mSortAttribs[] =
+{
+ EGL_RED_SIZE, 1,
+ EGL_GREEN_SIZE, 1,
+ EGL_BLUE_SIZE, 1,
+ EGL_LUMINANCE_SIZE, 1,
+ // BUT NOT ALPHA
+ EGL_NONE
+};
+
+ConfigSet::ConfigSet()
+ : mSet(SortConfig(mSortAttribs))
+{
+}
+
+void ConfigSet::add(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight)
+{
+ Config config(displayMode, minSwapInterval, maxSwapInterval, renderTargetFormat, depthStencilFormat, multiSample, texWidth, texHeight);
+
+ mSet.insert(config);
+}
+
+size_t ConfigSet::size() const
+{
+ return mSet.size();
+}
+
+bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
+{
+ vector<const Config*> passed;
+ passed.reserve(mSet.size());
+
+ for (Iterator config = mSet.begin(); config != mSet.end(); config++)
+ {
+ bool match = true;
+ const EGLint *attribute = attribList;
+
+ while (attribute[0] != EGL_NONE)
+ {
+ switch (attribute[0])
+ {
+ case EGL_BUFFER_SIZE: match = config->mBufferSize >= attribute[1]; break;
+ case EGL_ALPHA_SIZE: match = config->mAlphaSize >= attribute[1]; break;
+ case EGL_BLUE_SIZE: match = config->mBlueSize >= attribute[1]; break;
+ case EGL_GREEN_SIZE: match = config->mGreenSize >= attribute[1]; break;
+ case EGL_RED_SIZE: match = config->mRedSize >= attribute[1]; break;
+ case EGL_DEPTH_SIZE: match = config->mDepthSize >= attribute[1]; break;
+ case EGL_STENCIL_SIZE: match = config->mStencilSize >= attribute[1]; break;
+ case EGL_CONFIG_CAVEAT: match = config->mConfigCaveat == (EGLenum) attribute[1]; break;
+ case EGL_CONFIG_ID: match = config->mConfigID == attribute[1]; break;
+ case EGL_LEVEL: match = config->mLevel >= attribute[1]; break;
+ case EGL_NATIVE_RENDERABLE: match = config->mNativeRenderable == (EGLBoolean) attribute[1]; break;
+ case EGL_NATIVE_VISUAL_TYPE: match = config->mNativeVisualType == attribute[1]; break;
+ case EGL_SAMPLES: match = config->mSamples >= attribute[1]; break;
+ case EGL_SAMPLE_BUFFERS: match = config->mSampleBuffers >= attribute[1]; break;
+ case EGL_SURFACE_TYPE: match = (config->mSurfaceType & attribute[1]) == attribute[1]; break;
+ case EGL_TRANSPARENT_TYPE: match = config->mTransparentType == (EGLenum) attribute[1]; break;
+ case EGL_TRANSPARENT_BLUE_VALUE: match = config->mTransparentBlueValue == attribute[1]; break;
+ case EGL_TRANSPARENT_GREEN_VALUE: match = config->mTransparentGreenValue == attribute[1]; break;
+ case EGL_TRANSPARENT_RED_VALUE: match = config->mTransparentRedValue == attribute[1]; break;
+ case EGL_BIND_TO_TEXTURE_RGB: match = config->mBindToTextureRGB == (EGLBoolean) attribute[1]; break;
+ case EGL_BIND_TO_TEXTURE_RGBA: match = config->mBindToTextureRGBA == (EGLBoolean) attribute[1]; break;
+ case EGL_MIN_SWAP_INTERVAL: match = config->mMinSwapInterval == attribute[1]; break;
+ case EGL_MAX_SWAP_INTERVAL: match = config->mMaxSwapInterval == attribute[1]; break;
+ case EGL_LUMINANCE_SIZE: match = config->mLuminanceSize >= attribute[1]; break;
+ case EGL_ALPHA_MASK_SIZE: match = config->mAlphaMaskSize >= attribute[1]; break;
+ case EGL_COLOR_BUFFER_TYPE: match = config->mColorBufferType == (EGLenum) attribute[1]; break;
+ case EGL_RENDERABLE_TYPE: match = (config->mRenderableType & attribute[1]) == attribute[1]; break;
+ case EGL_MATCH_NATIVE_PIXMAP: match = false; UNIMPLEMENTED(); break;
+ case EGL_CONFORMANT: match = (config->mConformant & attribute[1]) == attribute[1]; break;
+ case EGL_MAX_PBUFFER_WIDTH: match = config->mMaxPBufferWidth >= attribute[1]; break;
+ case EGL_MAX_PBUFFER_HEIGHT: match = config->mMaxPBufferHeight >= attribute[1]; break;
+ case EGL_MAX_PBUFFER_PIXELS: match = config->mMaxPBufferPixels >= attribute[1]; break;
+ default:
+ return false;
+ }
+
+ if (!match)
+ {
+ break;
+ }
+
+ attribute += 2;
+ }
+
+ if (match)
+ {
+ passed.push_back(&*config);
+ }
+ }
+
+ if (configs)
+ {
+ sort(passed.begin(), passed.end(), SortConfig(attribList));
+
+ EGLint index;
+ for (index = 0; index < configSize && index < static_cast<EGLint>(passed.size()); index++)
+ {
+ configs[index] = passed[index]->getHandle();
+ }
+
+ *numConfig = index;
+ }
+ else
+ {
+ *numConfig = passed.size();
+ }
+
+ return true;
+}
+
+const egl::Config *ConfigSet::get(EGLConfig configHandle)
+{
+ for (Iterator config = mSet.begin(); config != mSet.end(); config++)
+ {
+ if (config->getHandle() == configHandle)
+ {
+ return &(*config);
+ }
+ }
+
+ return NULL;
+}
+}
diff --git a/src/3rdparty/angle/src/libEGL/Config.h b/src/3rdparty/angle/src/libEGL/Config.h
new file mode 100644
index 0000000000..95626ed1ad
--- /dev/null
+++ b/src/3rdparty/angle/src/libEGL/Config.h
@@ -0,0 +1,118 @@
+//
+// Copyright (c) 2002-2010 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.
+//
+
+// Config.h: Defines the egl::Config class, describing the format, type
+// and size for an egl::Surface. Implements EGLConfig and related functionality.
+// [EGL 1.4] section 3.4 page 15.
+
+#ifndef INCLUDE_CONFIG_H_
+#define INCLUDE_CONFIG_H_
+
+#define EGLAPI
+#include <EGL/egl.h>
+#include <d3d9.h>
+
+#include <set>
+
+#include "common/angleutils.h"
+
+namespace egl
+{
+class Display;
+
+class Config
+{
+ public:
+ Config(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight);
+
+ void setDefaults();
+ void set(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight);
+ EGLConfig getHandle() const;
+
+ const D3DDISPLAYMODE mDisplayMode;
+ const D3DFORMAT mRenderTargetFormat;
+ const D3DFORMAT mDepthStencilFormat;
+ const EGLint mMultiSample;
+
+ EGLint mBufferSize; // Depth of the color buffer
+ EGLint mRedSize; // Bits of Red in the color buffer
+ EGLint mGreenSize; // Bits of Green in the color buffer
+ EGLint mBlueSize; // Bits of Blue in the color buffer
+ EGLint mLuminanceSize; // Bits of Luminance in the color buffer
+ EGLint mAlphaSize; // Bits of Alpha in the color buffer
+ EGLint mAlphaMaskSize; // Bits of Alpha Mask in the mask buffer
+ EGLBoolean mBindToTextureRGB; // True if bindable to RGB textures.
+ EGLBoolean mBindToTextureRGBA; // True if bindable to RGBA textures.
+ EGLenum mColorBufferType; // Color buffer type
+ EGLenum mConfigCaveat; // Any caveats for the configuration
+ EGLint mConfigID; // Unique EGLConfig identifier
+ EGLint mConformant; // Whether contexts created with this config are conformant
+ EGLint mDepthSize; // Bits of Z in the depth buffer
+ EGLint mLevel; // Frame buffer level
+ EGLBoolean mMatchNativePixmap; // Match the native pixmap format
+ EGLint mMaxPBufferWidth; // Maximum width of pbuffer
+ EGLint mMaxPBufferHeight; // Maximum height of pbuffer
+ EGLint mMaxPBufferPixels; // Maximum size of pbuffer
+ EGLint mMaxSwapInterval; // Maximum swap interval
+ EGLint mMinSwapInterval; // Minimum swap interval
+ EGLBoolean mNativeRenderable; // EGL_TRUE if native rendering APIs can render to surface
+ EGLint mNativeVisualID; // Handle of corresponding native visual
+ EGLint mNativeVisualType; // Native visual type of the associated visual
+ EGLint mRenderableType; // Which client rendering APIs are supported.
+ EGLint mSampleBuffers; // Number of multisample buffers
+ EGLint mSamples; // Number of samples per pixel
+ EGLint mStencilSize; // Bits of Stencil in the stencil buffer
+ EGLint mSurfaceType; // Which types of EGL surfaces are supported.
+ EGLenum mTransparentType; // Type of transparency supported
+ EGLint mTransparentRedValue; // Transparent red value
+ EGLint mTransparentGreenValue; // Transparent green value
+ EGLint mTransparentBlueValue; // Transparent blue value
+};
+
+// Function object used by STL sorting routines for ordering Configs according to [EGL] section 3.4.1 page 24.
+class SortConfig
+{
+ public:
+ explicit SortConfig(const EGLint *attribList);
+
+ bool operator()(const Config *x, const Config *y) const;
+ bool operator()(const Config &x, const Config &y) const;
+
+ private:
+ void scanForWantedComponents(const EGLint *attribList);
+ EGLint wantedComponentsSize(const Config &config) const;
+
+ bool mWantRed;
+ bool mWantGreen;
+ bool mWantBlue;
+ bool mWantAlpha;
+ bool mWantLuminance;
+};
+
+class ConfigSet
+{
+ friend Display;
+
+ public:
+ ConfigSet();
+
+ void add(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight);
+ size_t size() const;
+ bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig);
+ const egl::Config *get(EGLConfig configHandle);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ConfigSet);
+
+ typedef std::set<Config, SortConfig> Set;
+ typedef Set::iterator Iterator;
+ Set mSet;
+
+ static const EGLint mSortAttribs[];
+};
+}
+
+#endif // INCLUDE_CONFIG_H_
diff --git a/src/3rdparty/angle/src/libEGL/Display.cpp b/src/3rdparty/angle/src/libEGL/Display.cpp
new file mode 100644
index 0000000000..a2dee6d964
--- /dev/null
+++ b/src/3rdparty/angle/src/libEGL/Display.cpp
@@ -0,0 +1,1292 @@
+//
+// Copyright (c) 2002-2012 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.
+//
+
+// Display.cpp: Implements the egl::Display class, representing the abstract
+// display on which graphics are drawn. Implements EGLDisplay.
+// [EGL 1.4] section 2.1.2 page 3.
+
+#include "libEGL/Display.h"
+
+#include <algorithm>
+#include <map>
+#include <vector>
+
+#include "common/debug.h"
+#include "libGLESv2/mathutil.h"
+#include "libGLESv2/utilities.h"
+
+#include "libEGL/main.h"
+
+// Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros
+#define REF_RAST 0
+
+// The "Debug This Pixel..." feature in PIX often fails when using the
+// D3D9Ex interfaces. In order to get debug pixel to work on a Vista/Win 7
+// machine, define "ANGLE_ENABLE_D3D9EX=0" in your project file.
+#if !defined(ANGLE_ENABLE_D3D9EX)
+// Enables use of the IDirect3D9Ex interface, when available
+#define ANGLE_ENABLE_D3D9EX 1
+#endif // !defined(ANGLE_ENABLE_D3D9EX)
+
+namespace egl
+{
+namespace
+{
+ typedef std::map<EGLNativeDisplayType, Display*> DisplayMap;
+ DisplayMap displays;
+}
+
+egl::Display *Display::getDisplay(EGLNativeDisplayType displayId)
+{
+ if (displays.find(displayId) != displays.end())
+ {
+ return displays[displayId];
+ }
+
+ egl::Display *display = NULL;
+
+ if (displayId == EGL_DEFAULT_DISPLAY)
+ {
+ display = new egl::Display(displayId, (HDC)NULL, false);
+ }
+ else if (displayId == EGL_SOFTWARE_DISPLAY_ANGLE)
+ {
+ display = new egl::Display(displayId, (HDC)NULL, true);
+ }
+ else
+ {
+ // FIXME: Check if displayId is a valid display device context
+
+ display = new egl::Display(displayId, (HDC)displayId, false);
+ }
+
+ displays[displayId] = display;
+ return display;
+}
+
+Display::Display(EGLNativeDisplayType displayId, HDC deviceContext, bool software) : mDc(deviceContext)
+{
+ mD3d9Module = NULL;
+
+ mD3d9 = NULL;
+ mD3d9Ex = NULL;
+ mDevice = NULL;
+ mDeviceEx = NULL;
+ mDeviceWindow = NULL;
+
+ mAdapter = D3DADAPTER_DEFAULT;
+
+ #if REF_RAST == 1 || defined(FORCE_REF_RAST)
+ mDeviceType = D3DDEVTYPE_REF;
+ #else
+ mDeviceType = D3DDEVTYPE_HAL;
+ #endif
+
+ mMinSwapInterval = 1;
+ mMaxSwapInterval = 1;
+ mSoftwareDevice = software;
+ mDisplayId = displayId;
+ mDeviceLost = false;
+}
+
+Display::~Display()
+{
+ terminate();
+
+ DisplayMap::iterator thisDisplay = displays.find(mDisplayId);
+
+ if (thisDisplay != displays.end())
+ {
+ displays.erase(thisDisplay);
+ }
+}
+
+bool Display::initialize()
+{
+ if (isInitialized())
+ {
+ return true;
+ }
+
+ if (mSoftwareDevice)
+ {
+ mD3d9Module = GetModuleHandle(TEXT("swiftshader_d3d9.dll"));
+ }
+ else
+ {
+ mD3d9Module = GetModuleHandle(TEXT("d3d9.dll"));
+ }
+ if (mD3d9Module == NULL)
+ {
+ terminate();
+ return false;
+ }
+
+ typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**);
+ Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex"));
+
+ // Use Direct3D9Ex if available. Among other things, this version is less
+ // inclined to report a lost context, for example when the user switches
+ // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available.
+ if (ANGLE_ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex)))
+ {
+ ASSERT(mD3d9Ex);
+ mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9));
+ ASSERT(mD3d9);
+ }
+ else
+ {
+ mD3d9 = Direct3DCreate9(D3D_SDK_VERSION);
+ }
+
+ if (mD3d9)
+ {
+ if (mDc != NULL)
+ {
+ // UNIMPLEMENTED(); // FIXME: Determine which adapter index the device context corresponds to
+ }
+
+ HRESULT result;
+
+ // Give up on getting device caps after about one second.
+ for (int i = 0; i < 10; ++i)
+ {
+ result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps);
+
+ if (SUCCEEDED(result))
+ {
+ break;
+ }
+ else if (result == D3DERR_NOTAVAILABLE)
+ {
+ Sleep(100); // Give the driver some time to initialize/recover
+ }
+ else if (FAILED(result)) // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY, D3DERR_INVALIDDEVICE, or another error we can't recover from
+ {
+ terminate();
+ return error(EGL_BAD_ALLOC, false);
+ }
+ }
+
+ if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(2, 0))
+ {
+ terminate();
+ return error(EGL_NOT_INITIALIZED, false);
+ }
+
+ // When DirectX9 is running with an older DirectX8 driver, a StretchRect from a regular texture to a render target texture is not supported.
+ // This is required by Texture2D::convertToRenderTarget.
+ if ((mDeviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) == 0)
+ {
+ terminate();
+ return error(EGL_NOT_INITIALIZED, false);
+ }
+
+ mMinSwapInterval = 4;
+ mMaxSwapInterval = 0;
+
+ if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) {mMinSwapInterval = std::min(mMinSwapInterval, 0); mMaxSwapInterval = std::max(mMaxSwapInterval, 0);}
+ if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE) {mMinSwapInterval = std::min(mMinSwapInterval, 1); mMaxSwapInterval = std::max(mMaxSwapInterval, 1);}
+ if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO) {mMinSwapInterval = std::min(mMinSwapInterval, 2); mMaxSwapInterval = std::max(mMaxSwapInterval, 2);}
+ if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE) {mMinSwapInterval = std::min(mMinSwapInterval, 3); mMaxSwapInterval = std::max(mMaxSwapInterval, 3);}
+ if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR) {mMinSwapInterval = std::min(mMinSwapInterval, 4); mMaxSwapInterval = std::max(mMaxSwapInterval, 4);}
+
+ mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier);
+
+ // ATI cards on XP have problems with non-power-of-two textures.
+ mSupportsNonPower2Textures = !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) &&
+ !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) &&
+ !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) &&
+ !(getComparableOSVersion() < versionWindowsVista && mAdapterIdentifier.VendorId == VENDOR_ID_AMD);
+
+ const D3DFORMAT renderTargetFormats[] =
+ {
+ D3DFMT_A1R5G5B5,
+ // D3DFMT_A2R10G10B10, // The color_ramp conformance test uses ReadPixels with UNSIGNED_BYTE causing it to think that rendering skipped a colour value.
+ D3DFMT_A8R8G8B8,
+ D3DFMT_R5G6B5,
+ // D3DFMT_X1R5G5B5, // Has no compatible OpenGL ES renderbuffer format
+ D3DFMT_X8R8G8B8
+ };
+
+ const D3DFORMAT depthStencilFormats[] =
+ {
+ D3DFMT_UNKNOWN,
+ // D3DFMT_D16_LOCKABLE,
+ D3DFMT_D32,
+ // D3DFMT_D15S1,
+ D3DFMT_D24S8,
+ D3DFMT_D24X8,
+ // D3DFMT_D24X4S4,
+ D3DFMT_D16,
+ // D3DFMT_D32F_LOCKABLE,
+ // D3DFMT_D24FS8
+ };
+
+ D3DDISPLAYMODE currentDisplayMode;
+ mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
+
+ ConfigSet configSet;
+
+ for (int formatIndex = 0; formatIndex < sizeof(renderTargetFormats) / sizeof(D3DFORMAT); formatIndex++)
+ {
+ D3DFORMAT renderTargetFormat = renderTargetFormats[formatIndex];
+
+ HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, renderTargetFormat);
+
+ if (SUCCEEDED(result))
+ {
+ for (int depthStencilIndex = 0; depthStencilIndex < sizeof(depthStencilFormats) / sizeof(D3DFORMAT); depthStencilIndex++)
+ {
+ D3DFORMAT depthStencilFormat = depthStencilFormats[depthStencilIndex];
+ HRESULT result = D3D_OK;
+
+ if(depthStencilFormat != D3DFMT_UNKNOWN)
+ {
+ result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat);
+ }
+
+ if (SUCCEEDED(result))
+ {
+ if(depthStencilFormat != D3DFMT_UNKNOWN)
+ {
+ result = mD3d9->CheckDepthStencilMatch(mAdapter, mDeviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat);
+ }
+
+ if (SUCCEEDED(result))
+ {
+ // FIXME: enumerate multi-sampling
+
+ configSet.add(currentDisplayMode, mMinSwapInterval, mMaxSwapInterval, renderTargetFormat, depthStencilFormat, 0,
+ mDeviceCaps.MaxTextureWidth, mDeviceCaps.MaxTextureHeight);
+ }
+ }
+ }
+ }
+ }
+
+ // Give the sorted configs a unique ID and store them internally
+ EGLint index = 1;
+ for (ConfigSet::Iterator config = configSet.mSet.begin(); config != configSet.mSet.end(); config++)
+ {
+ Config configuration = *config;
+ configuration.mConfigID = index;
+ index++;
+
+ mConfigSet.mSet.insert(configuration);
+ }
+ }
+
+ if (!isInitialized())
+ {
+ terminate();
+
+ return false;
+ }
+
+ initExtensionString();
+
+ static const TCHAR windowName[] = TEXT("AngleHiddenWindow");
+ static const TCHAR className[] = TEXT("STATIC");
+
+ mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);
+
+ if (!createDevice())
+ {
+ terminate();
+ return false;
+ }
+
+ mVertexShaderCache.initialize(mDevice);
+ mPixelShaderCache.initialize(mDevice);
+
+ return true;
+}
+
+void Display::terminate()
+{
+ while (!mSurfaceSet.empty())
+ {
+ destroySurface(*mSurfaceSet.begin());
+ }
+
+ while (!mContextSet.empty())
+ {
+ destroyContext(*mContextSet.begin());
+ }
+
+ while (!mEventQueryPool.empty())
+ {
+ mEventQueryPool.back()->Release();
+ mEventQueryPool.pop_back();
+ }
+
+ mVertexShaderCache.clear();
+ mPixelShaderCache.clear();
+
+ if (mDevice)
+ {
+ // If the device is lost, reset it first to prevent leaving the driver in an unstable state
+ if (testDeviceLost())
+ {
+ resetDevice();
+ }
+
+ mDevice->Release();
+ mDevice = NULL;
+ }
+
+ if (mDeviceEx)
+ {
+ mDeviceEx->Release();
+ mDeviceEx = NULL;
+ }
+
+ if (mD3d9)
+ {
+ mD3d9->Release();
+ mD3d9 = NULL;
+ }
+
+ if (mDeviceWindow)
+ {
+ DestroyWindow(mDeviceWindow);
+ mDeviceWindow = NULL;
+ }
+
+ if (mD3d9Ex)
+ {
+ mD3d9Ex->Release();
+ mD3d9Ex = NULL;
+ }
+
+ if (mD3d9Module)
+ {
+ mD3d9Module = NULL;
+ }
+}
+
+void Display::startScene()
+{
+ if (!mSceneStarted)
+ {
+ long result = mDevice->BeginScene();
+ if (SUCCEEDED(result)) {
+ // This is defensive checking against the device being
+ // lost at unexpected times.
+ mSceneStarted = true;
+ }
+ }
+}
+
+void Display::endScene()
+{
+ if (mSceneStarted)
+ {
+ // EndScene can fail if the device was lost, for example due
+ // to a TDR during a draw call.
+ mDevice->EndScene();
+ mSceneStarted = false;
+ }
+}
+
+bool Display::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
+{
+ return mConfigSet.getConfigs(configs, attribList, configSize, numConfig);
+}
+
+bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value)
+{
+ const egl::Config *configuration = mConfigSet.get(config);
+
+ switch (attribute)
+ {
+ case EGL_BUFFER_SIZE: *value = configuration->mBufferSize; break;
+ case EGL_ALPHA_SIZE: *value = configuration->mAlphaSize; break;
+ case EGL_BLUE_SIZE: *value = configuration->mBlueSize; break;
+ case EGL_GREEN_SIZE: *value = configuration->mGreenSize; break;
+ case EGL_RED_SIZE: *value = configuration->mRedSize; break;
+ case EGL_DEPTH_SIZE: *value = configuration->mDepthSize; break;
+ case EGL_STENCIL_SIZE: *value = configuration->mStencilSize; break;
+ case EGL_CONFIG_CAVEAT: *value = configuration->mConfigCaveat; break;
+ case EGL_CONFIG_ID: *value = configuration->mConfigID; break;
+ case EGL_LEVEL: *value = configuration->mLevel; break;
+ case EGL_NATIVE_RENDERABLE: *value = configuration->mNativeRenderable; break;
+ case EGL_NATIVE_VISUAL_TYPE: *value = configuration->mNativeVisualType; break;
+ case EGL_SAMPLES: *value = configuration->mSamples; break;
+ case EGL_SAMPLE_BUFFERS: *value = configuration->mSampleBuffers; break;
+ case EGL_SURFACE_TYPE: *value = configuration->mSurfaceType; break;
+ case EGL_TRANSPARENT_TYPE: *value = configuration->mTransparentType; break;
+ case EGL_TRANSPARENT_BLUE_VALUE: *value = configuration->mTransparentBlueValue; break;
+ case EGL_TRANSPARENT_GREEN_VALUE: *value = configuration->mTransparentGreenValue; break;
+ case EGL_TRANSPARENT_RED_VALUE: *value = configuration->mTransparentRedValue; break;
+ case EGL_BIND_TO_TEXTURE_RGB: *value = configuration->mBindToTextureRGB; break;
+ case EGL_BIND_TO_TEXTURE_RGBA: *value = configuration->mBindToTextureRGBA; break;
+ case EGL_MIN_SWAP_INTERVAL: *value = configuration->mMinSwapInterval; break;
+ case EGL_MAX_SWAP_INTERVAL: *value = configuration->mMaxSwapInterval; break;
+ case EGL_LUMINANCE_SIZE: *value = configuration->mLuminanceSize; break;
+ case EGL_ALPHA_MASK_SIZE: *value = configuration->mAlphaMaskSize; break;
+ case EGL_COLOR_BUFFER_TYPE: *value = configuration->mColorBufferType; break;
+ case EGL_RENDERABLE_TYPE: *value = configuration->mRenderableType; break;
+ case EGL_MATCH_NATIVE_PIXMAP: *value = false; UNIMPLEMENTED(); break;
+ case EGL_CONFORMANT: *value = configuration->mConformant; break;
+ case EGL_MAX_PBUFFER_WIDTH: *value = configuration->mMaxPBufferWidth; break;
+ case EGL_MAX_PBUFFER_HEIGHT: *value = configuration->mMaxPBufferHeight; break;
+ case EGL_MAX_PBUFFER_PIXELS: *value = configuration->mMaxPBufferPixels; break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+bool Display::createDevice()
+{
+ D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
+ DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES;
+
+ HRESULT result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice);
+
+ if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST)
+ {
+ return error(EGL_BAD_ALLOC, false);
+ }
+
+ if (FAILED(result))
+ {
+ result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST);
+ return error(EGL_BAD_ALLOC, false);
+ }
+ }
+
+ if (mD3d9Ex)
+ {
+ result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**) &mDeviceEx);
+ ASSERT(SUCCEEDED(result));
+ }
+
+ initializeDevice();
+
+ return true;
+}
+
+// do any one-time device initialization
+// NOTE: this is also needed after a device lost/reset
+// to reset the scene status and ensure the default states are reset.
+void Display::initializeDevice()
+{
+ // Permanent non-default states
+ mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
+ mDevice->SetRenderState(D3DRS_LASTPIXEL, FALSE);
+
+ if (mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0))
+ {
+ mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, (DWORD&)mDeviceCaps.MaxPointSize);
+ }
+ else
+ {
+ mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, 0x3F800000); // 1.0f
+ }
+
+ mSceneStarted = false;
+}
+
+bool Display::resetDevice()
+{
+ D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
+
+ HRESULT result = D3D_OK;
+ bool lost = testDeviceLost();
+ int attempts = 3;
+
+ while (lost && attempts > 0)
+ {
+ if (mDeviceEx)
+ {
+ Sleep(500); // Give the graphics driver some CPU time
+ result = mDeviceEx->ResetEx(&presentParameters, NULL);
+ }
+ else
+ {
+ result = mDevice->TestCooperativeLevel();
+
+ while (result == D3DERR_DEVICELOST)
+ {
+ Sleep(100); // Give the graphics driver some CPU time
+ result = mDevice->TestCooperativeLevel();
+ }
+
+ if (result == D3DERR_DEVICENOTRESET)
+ {
+ result = mDevice->Reset(&presentParameters);
+ }
+ }
+
+ lost = testDeviceLost();
+ attempts --;
+ }
+
+ if (FAILED(result))
+ {
+ ERR("Reset/ResetEx failed multiple times: 0x%08X", result);
+ return error(EGL_BAD_ALLOC, false);
+ }
+
+ // reset device defaults
+ initializeDevice();
+
+ return true;
+}
+
+EGLSurface Display::createWindowSurface(HWND window, EGLConfig config, const EGLint *attribList)
+{
+ const Config *configuration = mConfigSet.get(config);
+ EGLint postSubBufferSupported = EGL_FALSE;
+
+ if (attribList)
+ {
+ while (*attribList != EGL_NONE)
+ {
+ switch (attribList[0])
+ {
+ case EGL_RENDER_BUFFER:
+ switch (attribList[1])
+ {
+ case EGL_BACK_BUFFER:
+ break;
+ case EGL_SINGLE_BUFFER:
+ return error(EGL_BAD_MATCH, EGL_NO_SURFACE); // Rendering directly to front buffer not supported
+ default:
+ return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+ }
+ break;
+ case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
+ postSubBufferSupported = attribList[1];
+ break;
+ case EGL_VG_COLORSPACE:
+ return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
+ case EGL_VG_ALPHA_FORMAT:
+ return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
+ default:
+ return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+ }
+
+ attribList += 2;
+ }
+ }
+
+ if (hasExistingWindowSurface(window))
+ {
+ return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+ }
+
+ if (testDeviceLost())
+ {
+ if (!restoreLostDevice())
+ return EGL_NO_SURFACE;
+ }
+
+ Surface *surface = new Surface(this, configuration, window, postSubBufferSupported);
+
+ if (!surface->initialize())
+ {
+ delete surface;
+ return EGL_NO_SURFACE;
+ }
+
+ mSurfaceSet.insert(surface);
+
+ return success(surface);
+}
+
+EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList)
+{
+ EGLint width = 0, height = 0;
+ EGLenum textureFormat = EGL_NO_TEXTURE;
+ EGLenum textureTarget = EGL_NO_TEXTURE;
+ const Config *configuration = mConfigSet.get(config);
+
+ if (attribList)
+ {
+ while (*attribList != EGL_NONE)
+ {
+ switch (attribList[0])
+ {
+ case EGL_WIDTH:
+ width = attribList[1];
+ break;
+ case EGL_HEIGHT:
+ height = attribList[1];
+ break;
+ case EGL_LARGEST_PBUFFER:
+ if (attribList[1] != EGL_FALSE)
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_TEXTURE_FORMAT:
+ switch (attribList[1])
+ {
+ case EGL_NO_TEXTURE:
+ case EGL_TEXTURE_RGB:
+ case EGL_TEXTURE_RGBA:
+ textureFormat = attribList[1];
+ break;
+ default:
+ return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+ }
+ break;
+ case EGL_TEXTURE_TARGET:
+ switch (attribList[1])
+ {
+ case EGL_NO_TEXTURE:
+ case EGL_TEXTURE_2D:
+ textureTarget = attribList[1];
+ break;
+ default:
+ return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+ }
+ break;
+ case EGL_MIPMAP_TEXTURE:
+ if (attribList[1] != EGL_FALSE)
+ return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+ break;
+ case EGL_VG_COLORSPACE:
+ return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
+ case EGL_VG_ALPHA_FORMAT:
+ return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
+ default:
+ return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+ }
+
+ attribList += 2;
+ }
+ }
+
+ if (width < 0 || height < 0)
+ {
+ return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
+ }
+
+ if (width == 0 || height == 0)
+ {
+ return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+ }
+
+ if (textureFormat != EGL_NO_TEXTURE && !getNonPower2TextureSupport() && (!gl::isPow2(width) || !gl::isPow2(height)))
+ {
+ return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
+ }
+
+ if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
+ (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
+ {
+ return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
+ }
+
+ if (!(configuration->mSurfaceType & EGL_PBUFFER_BIT))
+ {
+ return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
+ }
+
+ if ((textureFormat == EGL_TEXTURE_RGB && configuration->mBindToTextureRGB != EGL_TRUE) ||
+ (textureFormat == EGL_TEXTURE_RGBA && configuration->mBindToTextureRGBA != EGL_TRUE))
+ {
+ return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+ }
+
+ if (testDeviceLost())
+ {
+ if (!restoreLostDevice())
+ return EGL_NO_SURFACE;
+ }
+
+ Surface *surface = new Surface(this, configuration, shareHandle, width, height, textureFormat, textureTarget);
+
+ if (!surface->initialize())
+ {
+ delete surface;
+ return EGL_NO_SURFACE;
+ }
+
+ mSurfaceSet.insert(surface);
+
+ return success(surface);
+}
+
+EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *shareContext, bool notifyResets, bool robustAccess)
+{
+ if (!mDevice)
+ {
+ if (!createDevice())
+ {
+ return NULL;
+ }
+ }
+ else if (testDeviceLost()) // Lost device
+ {
+ if (!restoreLostDevice())
+ return NULL;
+ }
+
+ const egl::Config *config = mConfigSet.get(configHandle);
+
+ gl::Context *context = glCreateContext(config, shareContext, notifyResets, robustAccess);
+ mContextSet.insert(context);
+ mDeviceLost = false;
+
+ return context;
+}
+
+bool Display::restoreLostDevice()
+{
+ for (ContextSet::iterator ctx = mContextSet.begin(); ctx != mContextSet.end(); ctx++)
+ {
+ if ((*ctx)->isResetNotificationEnabled())
+ return false; // If reset notifications have been requested, application must delete all contexts first
+ }
+
+ // Release surface resources to make the Reset() succeed
+ for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
+ {
+ (*surface)->release();
+ }
+
+ while (!mEventQueryPool.empty())
+ {
+ mEventQueryPool.back()->Release();
+ mEventQueryPool.pop_back();
+ }
+
+ mVertexShaderCache.clear();
+ mPixelShaderCache.clear();
+
+ if (!resetDevice())
+ {
+ return false;
+ }
+
+ // Restore any surfaces that may have been lost
+ for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
+ {
+ (*surface)->resetSwapChain();
+ }
+
+ return true;
+}
+
+
+void Display::destroySurface(egl::Surface *surface)
+{
+ delete surface;
+ mSurfaceSet.erase(surface);
+}
+
+void Display::destroyContext(gl::Context *context)
+{
+ glDestroyContext(context);
+ mContextSet.erase(context);
+}
+
+void Display::notifyDeviceLost()
+{
+ for (ContextSet::iterator context = mContextSet.begin(); context != mContextSet.end(); context++)
+ {
+ (*context)->markContextLost();
+ }
+ mDeviceLost = true;
+ error(EGL_CONTEXT_LOST);
+}
+
+bool Display::isDeviceLost()
+{
+ return mDeviceLost;
+}
+
+bool Display::isInitialized() const
+{
+ return mD3d9 != NULL && mConfigSet.size() > 0;
+}
+
+bool Display::isValidConfig(EGLConfig config)
+{
+ return mConfigSet.get(config) != NULL;
+}
+
+bool Display::isValidContext(gl::Context *context)
+{
+ return mContextSet.find(context) != mContextSet.end();
+}
+
+bool Display::isValidSurface(egl::Surface *surface)
+{
+ return mSurfaceSet.find(surface) != mSurfaceSet.end();
+}
+
+bool Display::hasExistingWindowSurface(HWND window)
+{
+ for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
+ {
+ if ((*surface)->getWindowHandle() == window)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+EGLint Display::getMinSwapInterval()
+{
+ return mMinSwapInterval;
+}
+
+EGLint Display::getMaxSwapInterval()
+{
+ return mMaxSwapInterval;
+}
+
+IDirect3DDevice9 *Display::getDevice()
+{
+ if (!mDevice)
+ {
+ if (!createDevice())
+ {
+ return NULL;
+ }
+ }
+
+ return mDevice;
+}
+
+D3DCAPS9 Display::getDeviceCaps()
+{
+ return mDeviceCaps;
+}
+
+D3DADAPTER_IDENTIFIER9 *Display::getAdapterIdentifier()
+{
+ return &mAdapterIdentifier;
+}
+
+bool Display::testDeviceLost()
+{
+ if (mDeviceEx)
+ {
+ return FAILED(mDeviceEx->CheckDeviceState(NULL));
+ }
+ else if (mDevice)
+ {
+ return FAILED(mDevice->TestCooperativeLevel());
+ }
+
+ return false; // No device yet, so no reset required
+}
+
+bool Display::testDeviceResettable()
+{
+ HRESULT status = D3D_OK;
+
+ if (mDeviceEx)
+ {
+ status = mDeviceEx->CheckDeviceState(NULL);
+ }
+ else if (mDevice)
+ {
+ status = mDevice->TestCooperativeLevel();
+ }
+
+ switch (status)
+ {
+ case D3DERR_DEVICENOTRESET:
+ case D3DERR_DEVICEHUNG:
+ return true;
+ default:
+ return false;
+ }
+}
+
+void Display::sync(bool block)
+{
+ HRESULT result;
+
+ IDirect3DQuery9* query = allocateEventQuery();
+ if (!query)
+ {
+ return;
+ }
+
+ result = query->Issue(D3DISSUE_END);
+ ASSERT(SUCCEEDED(result));
+
+ do
+ {
+ result = query->GetData(NULL, 0, D3DGETDATA_FLUSH);
+
+ if(block && result == S_FALSE)
+ {
+ // Keep polling, but allow other threads to do something useful first
+ Sleep(0);
+ // explicitly check for device loss
+ // some drivers seem to return S_FALSE even if the device is lost
+ // instead of D3DERR_DEVICELOST like they should
+ if (testDeviceLost())
+ {
+ result = D3DERR_DEVICELOST;
+ }
+ }
+ }
+ while(block && result == S_FALSE);
+
+ freeEventQuery(query);
+
+ if (isDeviceLostError(result))
+ {
+ notifyDeviceLost();
+ }
+}
+
+IDirect3DQuery9* Display::allocateEventQuery()
+{
+ IDirect3DQuery9 *query = NULL;
+
+ if (mEventQueryPool.empty())
+ {
+ HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &query);
+ ASSERT(SUCCEEDED(result));
+ }
+ else
+ {
+ query = mEventQueryPool.back();
+ mEventQueryPool.pop_back();
+ }
+
+ return query;
+}
+
+void Display::freeEventQuery(IDirect3DQuery9* query)
+{
+ if (mEventQueryPool.size() > 1000)
+ {
+ query->Release();
+ }
+ else
+ {
+ mEventQueryPool.push_back(query);
+ }
+}
+
+void Display::getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray)
+{
+ for (int multiSampleIndex = 0; multiSampleIndex <= D3DMULTISAMPLE_16_SAMPLES; multiSampleIndex++)
+ {
+ HRESULT result = mD3d9->CheckDeviceMultiSampleType(mAdapter, mDeviceType, format,
+ TRUE, (D3DMULTISAMPLE_TYPE)multiSampleIndex, NULL);
+
+ multiSampleArray[multiSampleIndex] = SUCCEEDED(result);
+ }
+}
+
+bool Display::getDXT1TextureSupport()
+{
+ D3DDISPLAYMODE currentDisplayMode;
+ mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
+
+ return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1));
+}
+
+bool Display::getDXT3TextureSupport()
+{
+ D3DDISPLAYMODE currentDisplayMode;
+ mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
+
+ return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT3));
+}
+
+bool Display::getDXT5TextureSupport()
+{
+ D3DDISPLAYMODE currentDisplayMode;
+ mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
+
+ return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5));
+}
+
+// we use INTZ for depth textures in Direct3D9
+// we also want NULL texture support to ensure the we can make depth-only FBOs
+// see http://aras-p.info/texts/D3D9GPUHacks.html
+bool Display::getDepthTextureSupport() const
+{
+ D3DDISPLAYMODE currentDisplayMode;
+ mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
+
+ bool intz = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
+ D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, D3DFMT_INTZ));
+ bool null = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
+ D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL));
+
+ return intz && null;
+}
+
+bool Display::getFloat32TextureSupport(bool *filtering, bool *renderable)
+{
+ D3DDISPLAYMODE currentDisplayMode;
+ mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
+
+ *filtering = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
+ D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
+ SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
+ D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
+
+ *renderable = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
+ D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F))&&
+ SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
+ D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
+
+ if (!*filtering && !*renderable)
+ {
+ return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
+ D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
+ SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
+ D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
+ }
+ else
+ {
+ return true;
+ }
+}
+
+bool Display::getFloat16TextureSupport(bool *filtering, bool *renderable)
+{
+ D3DDISPLAYMODE currentDisplayMode;
+ mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
+
+ *filtering = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
+ D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
+ SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
+ D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
+
+ *renderable = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
+ D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
+ SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
+ D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
+
+ if (!*filtering && !*renderable)
+ {
+ return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
+ D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
+ SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
+ D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
+ }
+ else
+ {
+ return true;
+ }
+}
+
+bool Display::getLuminanceTextureSupport()
+{
+ D3DDISPLAYMODE currentDisplayMode;
+ mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
+
+ return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_L8));
+}
+
+bool Display::getLuminanceAlphaTextureSupport()
+{
+ D3DDISPLAYMODE currentDisplayMode;
+ mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
+
+ return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8L8));
+}
+
+float Display::getTextureFilterAnisotropySupport() const
+{
+ // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec
+ if ((mDeviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) && (mDeviceCaps.MaxAnisotropy >= 2))
+ {
+ return mDeviceCaps.MaxAnisotropy;
+ }
+ return 1.0f;
+}
+
+D3DPOOL Display::getBufferPool(DWORD usage) const
+{
+ if (mD3d9Ex != NULL)
+ {
+ return D3DPOOL_DEFAULT;
+ }
+ else
+ {
+ if (!(usage & D3DUSAGE_DYNAMIC))
+ {
+ return D3DPOOL_MANAGED;
+ }
+ }
+
+ return D3DPOOL_DEFAULT;
+}
+
+D3DPOOL Display::getTexturePool(DWORD usage) const
+{
+ if (mD3d9Ex != NULL)
+ {
+ return D3DPOOL_DEFAULT;
+ }
+ else
+ {
+ if (!(usage & (D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET)))
+ {
+ return D3DPOOL_MANAGED;
+ }
+ }
+
+ return D3DPOOL_DEFAULT;
+}
+
+bool Display::getEventQuerySupport()
+{
+ IDirect3DQuery9 *query = allocateEventQuery();
+ if (query)
+ {
+ freeEventQuery(query);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+D3DPRESENT_PARAMETERS Display::getDefaultPresentParameters()
+{
+ D3DPRESENT_PARAMETERS presentParameters = {0};
+
+ // The default swap chain is never actually used. Surface will create a new swap chain with the proper parameters.
+ presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
+ presentParameters.BackBufferCount = 1;
+ presentParameters.BackBufferFormat = D3DFMT_UNKNOWN;
+ presentParameters.BackBufferWidth = 1;
+ presentParameters.BackBufferHeight = 1;
+ presentParameters.EnableAutoDepthStencil = FALSE;
+ presentParameters.Flags = 0;
+ presentParameters.hDeviceWindow = mDeviceWindow;
+ presentParameters.MultiSampleQuality = 0;
+ presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
+ presentParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
+ presentParameters.Windowed = TRUE;
+
+ return presentParameters;
+}
+
+void Display::initExtensionString()
+{
+ HMODULE swiftShader = GetModuleHandle(TEXT("swiftshader_d3d9.dll"));
+
+ mExtensionString = "";
+
+ // Multi-vendor (EXT) extensions
+ mExtensionString += "EGL_EXT_create_context_robustness ";
+
+ // ANGLE-specific extensions
+ if (shareHandleSupported())
+ {
+ mExtensionString += "EGL_ANGLE_d3d_share_handle_client_buffer ";
+ }
+
+ mExtensionString += "EGL_ANGLE_query_surface_pointer ";
+
+ if (swiftShader)
+ {
+ mExtensionString += "EGL_ANGLE_software_display ";
+ }
+
+ if (shareHandleSupported())
+ {
+ mExtensionString += "EGL_ANGLE_surface_d3d_texture_2d_share_handle ";
+ }
+
+ mExtensionString += "EGL_NV_post_sub_buffer";
+
+ std::string::size_type end = mExtensionString.find_last_not_of(' ');
+ if (end != std::string::npos)
+ {
+ mExtensionString.resize(end+1);
+ }
+}
+
+const char *Display::getExtensionString() const
+{
+ return mExtensionString.c_str();
+}
+
+bool Display::shareHandleSupported() const
+{
+ // PIX doesn't seem to support using share handles, so disable them.
+ return isD3d9ExDevice() && !gl::perfActive();
+}
+
+IDirect3DVertexShader9 *Display::createVertexShader(const DWORD *function, size_t length)
+{
+ return mVertexShaderCache.create(function, length);
+}
+
+IDirect3DPixelShader9 *Display::createPixelShader(const DWORD *function, size_t length)
+{
+ return mPixelShaderCache.create(function, length);
+}
+
+// Only Direct3D 10 ready devices support all the necessary vertex texture formats.
+// We test this using D3D9 by checking support for the R16F format.
+bool Display::getVertexTextureSupport() const
+{
+ if (!isInitialized() || mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(3, 0))
+ {
+ return false;
+ }
+
+ D3DDISPLAYMODE currentDisplayMode;
+ mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
+
+ HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F);
+
+ return SUCCEEDED(result);
+}
+
+bool Display::getNonPower2TextureSupport() const
+{
+ return mSupportsNonPower2Textures;
+}
+
+bool Display::getOcclusionQuerySupport() const
+{
+ if (!isInitialized())
+ {
+ return false;
+ }
+
+ IDirect3DQuery9 *query = NULL;
+ HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &query);
+
+ if (SUCCEEDED(result) && query)
+ {
+ query->Release();
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool Display::getInstancingSupport() const
+{
+ return mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0);
+}
+
+}
diff --git a/src/3rdparty/angle/src/libEGL/Display.h b/src/3rdparty/angle/src/libEGL/Display.h
new file mode 100644
index 0000000000..23b57b74c6
--- /dev/null
+++ b/src/3rdparty/angle/src/libEGL/Display.h
@@ -0,0 +1,167 @@
+//
+// Copyright (c) 2002-2012 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.
+//
+
+// Display.h: Defines the egl::Display class, representing the abstract
+// display on which graphics are drawn. Implements EGLDisplay.
+// [EGL 1.4] section 2.1.2 page 3.
+
+#ifndef LIBEGL_DISPLAY_H_
+#define LIBEGL_DISPLAY_H_
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#include <d3d9.h>
+
+#include <set>
+#include <vector>
+
+#include "libGLESv2/Context.h"
+
+#include "libEGL/Config.h"
+#include "libEGL/ShaderCache.h"
+#include "libEGL/Surface.h"
+
+const int versionWindowsVista = MAKEWORD(0x00, 0x06);
+const int versionWindows7 = MAKEWORD(0x01, 0x06);
+
+// Return the version of the operating system in a format suitable for ordering
+// comparison.
+inline int getComparableOSVersion()
+{
+ DWORD version = GetVersion();
+ int majorVersion = LOBYTE(LOWORD(version));
+ int minorVersion = HIBYTE(LOWORD(version));
+ return MAKEWORD(minorVersion, majorVersion);
+}
+
+namespace egl
+{
+class Display
+{
+ public:
+ ~Display();
+
+ bool initialize();
+ void terminate();
+
+ virtual void startScene();
+ virtual void endScene();
+
+ static egl::Display *getDisplay(EGLNativeDisplayType displayId);
+
+ bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig);
+ bool getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value);
+
+ EGLSurface createWindowSurface(HWND window, EGLConfig config, const EGLint *attribList);
+ EGLSurface createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList);
+ EGLContext createContext(EGLConfig configHandle, const gl::Context *shareContext, bool notifyResets, bool robustAccess);
+
+ void destroySurface(egl::Surface *surface);
+ void destroyContext(gl::Context *context);
+
+ bool isInitialized() const;
+ bool isValidConfig(EGLConfig config);
+ bool isValidContext(gl::Context *context);
+ bool isValidSurface(egl::Surface *surface);
+ bool hasExistingWindowSurface(HWND window);
+
+ EGLint getMinSwapInterval();
+ EGLint getMaxSwapInterval();
+
+ virtual IDirect3DDevice9 *getDevice();
+ virtual D3DCAPS9 getDeviceCaps();
+ virtual D3DADAPTER_IDENTIFIER9 *getAdapterIdentifier();
+ virtual bool testDeviceLost();
+ virtual bool testDeviceResettable();
+ virtual void sync(bool block);
+ virtual IDirect3DQuery9* allocateEventQuery();
+ virtual void freeEventQuery(IDirect3DQuery9* query);
+ virtual void getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray);
+ virtual bool getDXT1TextureSupport();
+ virtual bool getDXT3TextureSupport();
+ virtual bool getDXT5TextureSupport();
+ virtual bool getEventQuerySupport();
+ virtual bool getFloat32TextureSupport(bool *filtering, bool *renderable);
+ virtual bool getFloat16TextureSupport(bool *filtering, bool *renderable);
+ virtual bool getLuminanceTextureSupport();
+ virtual bool getLuminanceAlphaTextureSupport();
+ virtual bool getVertexTextureSupport() const;
+ virtual bool getNonPower2TextureSupport() const;
+ virtual bool getDepthTextureSupport() const;
+ virtual bool getOcclusionQuerySupport() const;
+ virtual bool getInstancingSupport() const;
+ virtual float getTextureFilterAnisotropySupport() const;
+ virtual D3DPOOL getBufferPool(DWORD usage) const;
+ virtual D3DPOOL getTexturePool(DWORD usage) const;
+
+ virtual void notifyDeviceLost();
+ bool isDeviceLost();
+
+ bool isD3d9ExDevice() const { return mD3d9Ex != NULL; }
+ const char *getExtensionString() const;
+ bool shareHandleSupported() const;
+
+ virtual IDirect3DVertexShader9 *createVertexShader(const DWORD *function, size_t length);
+ virtual IDirect3DPixelShader9 *createPixelShader(const DWORD *function, size_t length);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Display);
+
+ Display(EGLNativeDisplayType displayId, HDC deviceContext, bool software);
+
+ D3DPRESENT_PARAMETERS getDefaultPresentParameters();
+
+ bool restoreLostDevice();
+
+ EGLNativeDisplayType mDisplayId;
+ const HDC mDc;
+
+ HMODULE mD3d9Module;
+
+ UINT mAdapter;
+ D3DDEVTYPE mDeviceType;
+ IDirect3D9 *mD3d9; // Always valid after successful initialization.
+ IDirect3D9Ex *mD3d9Ex; // Might be null if D3D9Ex is not supported.
+ IDirect3DDevice9 *mDevice;
+ IDirect3DDevice9Ex *mDeviceEx; // Might be null if D3D9Ex is not supported.
+
+ // A pool of event queries that are currently unused.
+ std::vector<IDirect3DQuery9*> mEventQueryPool;
+
+ VertexShaderCache mVertexShaderCache;
+ PixelShaderCache mPixelShaderCache;
+
+ D3DCAPS9 mDeviceCaps;
+ D3DADAPTER_IDENTIFIER9 mAdapterIdentifier;
+ HWND mDeviceWindow;
+
+ bool mSceneStarted;
+ EGLint mMaxSwapInterval;
+ EGLint mMinSwapInterval;
+ bool mSoftwareDevice;
+ bool mSupportsNonPower2Textures;
+
+ typedef std::set<Surface*> SurfaceSet;
+ SurfaceSet mSurfaceSet;
+
+ ConfigSet mConfigSet;
+
+ typedef std::set<gl::Context*> ContextSet;
+ ContextSet mContextSet;
+ bool mDeviceLost;
+
+ bool createDevice();
+ void initializeDevice();
+ bool resetDevice();
+
+ void initExtensionString();
+ std::string mExtensionString;
+};
+}
+
+#endif // LIBEGL_DISPLAY_H_
diff --git a/src/3rdparty/angle/src/libEGL/ShaderCache.h b/src/3rdparty/angle/src/libEGL/ShaderCache.h
new file mode 100644
index 0000000000..cfe523ba09
--- /dev/null
+++ b/src/3rdparty/angle/src/libEGL/ShaderCache.h
@@ -0,0 +1,116 @@
+//
+// Copyright (c) 2012 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.
+//
+
+// Display.h: Defines egl::ShaderCache, a cache of Direct3D shader objects
+// keyed by their byte code.
+
+#ifndef LIBEGL_SHADER_CACHE_H_
+#define LIBEGL_SHADER_CACHE_H_
+
+#include <d3d9.h>
+
+#ifdef _MSC_VER
+#include <hash_map>
+#else
+#include <unordered_map>
+#endif
+
+namespace egl
+{
+template <typename ShaderObject>
+class ShaderCache
+{
+ public:
+ ShaderCache() : mDevice(NULL)
+ {
+ }
+
+ ~ShaderCache()
+ {
+ // Call clear while the device is still valid.
+ ASSERT(mMap.empty());
+ }
+
+ void initialize(IDirect3DDevice9* device)
+ {
+ mDevice = device;
+ }
+
+ ShaderObject *create(const DWORD *function, size_t length)
+ {
+ std::string key(reinterpret_cast<const char*>(function), length);
+ typename Map::iterator it = mMap.find(key);
+ if (it != mMap.end())
+ {
+ it->second->AddRef();
+ return it->second;
+ }
+
+ ShaderObject *shader;
+ HRESULT result = createShader(function, &shader);
+ if (FAILED(result))
+ {
+ return NULL;
+ }
+
+ // Random eviction policy.
+ if (mMap.size() >= kMaxMapSize)
+ {
+ mMap.begin()->second->Release();
+ mMap.erase(mMap.begin());
+ }
+
+ shader->AddRef();
+ mMap[key] = shader;
+
+ return shader;
+ }
+
+ void clear()
+ {
+ for (typename Map::iterator it = mMap.begin(); it != mMap.end(); ++it)
+ {
+ it->second->Release();
+ }
+
+ mMap.clear();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ShaderCache);
+
+ const static size_t kMaxMapSize = 100;
+
+ HRESULT createShader(const DWORD *function, IDirect3DVertexShader9 **shader)
+ {
+ return mDevice->CreateVertexShader(function, shader);
+ }
+
+ HRESULT createShader(const DWORD *function, IDirect3DPixelShader9 **shader)
+ {
+ return mDevice->CreatePixelShader(function, shader);
+ }
+
+#ifndef HASH_MAP
+# ifdef _MSC_VER
+# define HASH_MAP stdext::hash_map
+# else
+# define HASH_MAP std::unordered_map
+# endif
+#endif
+
+ typedef HASH_MAP<std::string, ShaderObject*> Map;
+ Map mMap;
+
+ IDirect3DDevice9 *mDevice;
+};
+
+typedef ShaderCache<IDirect3DVertexShader9> VertexShaderCache;
+typedef ShaderCache<IDirect3DPixelShader9> PixelShaderCache;
+
+}
+
+#endif // LIBEGL_SHADER_CACHE_H_
diff --git a/src/3rdparty/angle/src/libEGL/Surface.cpp b/src/3rdparty/angle/src/libEGL/Surface.cpp
new file mode 100644
index 0000000000..732c404b10
--- /dev/null
+++ b/src/3rdparty/angle/src/libEGL/Surface.cpp
@@ -0,0 +1,674 @@
+//
+// Copyright (c) 2002-2010 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.
+//
+
+// Surface.cpp: Implements the egl::Surface class, representing a drawing surface
+// such as the client area of a window, including any back buffers.
+// Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3.
+
+#include <tchar.h>
+
+#include "libEGL/Surface.h"
+
+#include "common/debug.h"
+#include "libGLESv2/Texture.h"
+
+#include "libEGL/main.h"
+#include "libEGL/Display.h"
+
+#include <dwmapi.h>
+
+namespace egl
+{
+
+Surface::Surface(Display *display, const Config *config, HWND window, EGLint postSubBufferSupported)
+ : mDisplay(display), mConfig(config), mWindow(window), mPostSubBufferSupported(postSubBufferSupported)
+{
+ mSwapChain = NULL;
+ mBackBuffer = NULL;
+ mDepthStencil = NULL;
+ mRenderTarget = NULL;
+ mOffscreenTexture = NULL;
+ mShareHandle = NULL;
+ mTexture = NULL;
+ mTextureFormat = EGL_NO_TEXTURE;
+ mTextureTarget = EGL_NO_TEXTURE;
+
+ mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING); // FIXME: Determine actual pixel aspect ratio
+ mRenderBuffer = EGL_BACK_BUFFER;
+ mSwapBehavior = EGL_BUFFER_PRESERVED;
+ mSwapInterval = -1;
+ setSwapInterval(1);
+
+ subclassWindow();
+}
+
+Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureType)
+ : mDisplay(display), mWindow(NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE)
+{
+ mSwapChain = NULL;
+ mBackBuffer = NULL;
+ mDepthStencil = NULL;
+ mRenderTarget = NULL;
+ mOffscreenTexture = NULL;
+ mWindowSubclassed = false;
+ mTexture = NULL;
+ mTextureFormat = textureFormat;
+ mTextureTarget = textureType;
+
+ mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING); // FIXME: Determine actual pixel aspect ratio
+ mRenderBuffer = EGL_BACK_BUFFER;
+ mSwapBehavior = EGL_BUFFER_PRESERVED;
+ mSwapInterval = -1;
+ setSwapInterval(1);
+}
+
+Surface::~Surface()
+{
+ unsubclassWindow();
+ release();
+}
+
+bool Surface::initialize()
+{
+ ASSERT(!mSwapChain && !mOffscreenTexture && !mDepthStencil);
+
+ if (!resetSwapChain())
+ return false;
+
+ // Modify present parameters for this window, if we are composited,
+ // to minimize the amount of queuing done by DWM between our calls to
+ // present and the actual screen.
+ if (mWindow && (getComparableOSVersion() >= versionWindowsVista)) {
+ BOOL isComposited;
+ HRESULT result = DwmIsCompositionEnabled(&isComposited);
+ if (SUCCEEDED(result) && isComposited) {
+ DWM_PRESENT_PARAMETERS presentParams;
+ memset(&presentParams, 0, sizeof(presentParams));
+ presentParams.cbSize = sizeof(DWM_PRESENT_PARAMETERS);
+ presentParams.cBuffer = 2;
+
+ result = DwmSetPresentParameters(mWindow, &presentParams);
+ if (FAILED(result))
+ ERR("Unable to set present parameters: 0x%08X", result);
+ }
+ }
+
+ return true;
+}
+
+void Surface::release()
+{
+ if (mSwapChain)
+ {
+ mSwapChain->Release();
+ mSwapChain = NULL;
+ }
+
+ if (mBackBuffer)
+ {
+ mBackBuffer->Release();
+ mBackBuffer = NULL;
+ }
+
+ if (mDepthStencil)
+ {
+ mDepthStencil->Release();
+ mDepthStencil = NULL;
+ }
+
+ if (mRenderTarget)
+ {
+ mRenderTarget->Release();
+ mRenderTarget = NULL;
+ }
+
+ if (mOffscreenTexture)
+ {
+ mOffscreenTexture->Release();
+ mOffscreenTexture = NULL;
+ }
+
+ if (mTexture)
+ {
+ mTexture->releaseTexImage();
+ mTexture = NULL;
+ }
+
+ mShareHandle = NULL;
+}
+
+bool Surface::resetSwapChain()
+{
+ if (!mWindow)
+ {
+ return resetSwapChain(mWidth, mHeight);
+ }
+
+ RECT windowRect;
+ if (!GetClientRect(getWindowHandle(), &windowRect))
+ {
+ ASSERT(false);
+
+ ERR("Could not retrieve the window dimensions");
+ return false;
+ }
+
+ return resetSwapChain(windowRect.right - windowRect.left, windowRect.bottom - windowRect.top);
+}
+
+bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
+{
+ IDirect3DDevice9 *device = mDisplay->getDevice();
+
+ if (device == NULL)
+ {
+ return false;
+ }
+
+ // Evict all non-render target textures to system memory and release all resources
+ // before reallocating them to free up as much video memory as possible.
+ device->EvictManagedResources();
+
+ HRESULT result;
+
+ // Release specific resources to free up memory for the new render target, while the
+ // old render target still exists for the purpose of preserving its contents.
+ if (mSwapChain)
+ {
+ mSwapChain->Release();
+ mSwapChain = NULL;
+ }
+
+ if (mBackBuffer)
+ {
+ mBackBuffer->Release();
+ mBackBuffer = NULL;
+ }
+
+ if (mOffscreenTexture)
+ {
+ mOffscreenTexture->Release();
+ mOffscreenTexture = NULL;
+ }
+
+ if (mDepthStencil)
+ {
+ mDepthStencil->Release();
+ mDepthStencil = NULL;
+ }
+
+ mShareHandle = NULL;
+ HANDLE *pShareHandle = NULL;
+ if (!mWindow && mDisplay->shareHandleSupported())
+ {
+ pShareHandle = &mShareHandle;
+ }
+
+ result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET,
+ mConfig->mRenderTargetFormat, D3DPOOL_DEFAULT, &mOffscreenTexture, pShareHandle);
+ if (FAILED(result))
+ {
+ ERR("Could not create offscreen texture: %08lX", result);
+ release();
+
+ if(isDeviceLostError(result))
+ {
+ mDisplay->notifyDeviceLost();
+ return false;
+ }
+ else
+ {
+ return error(EGL_BAD_ALLOC, false);
+ }
+ }
+
+ IDirect3DSurface9 *oldRenderTarget = mRenderTarget;
+
+ result = mOffscreenTexture->GetSurfaceLevel(0, &mRenderTarget);
+ ASSERT(SUCCEEDED(result));
+
+ if (oldRenderTarget)
+ {
+ RECT rect =
+ {
+ 0, 0,
+ mWidth, mHeight
+ };
+
+ if (rect.right > static_cast<LONG>(backbufferWidth))
+ {
+ rect.right = backbufferWidth;
+ }
+
+ if (rect.bottom > static_cast<LONG>(backbufferHeight))
+ {
+ rect.bottom = backbufferHeight;
+ }
+
+ mDisplay->endScene();
+
+ result = device->StretchRect(oldRenderTarget, &rect, mRenderTarget, &rect, D3DTEXF_NONE);
+ ASSERT(SUCCEEDED(result));
+
+ oldRenderTarget->Release();
+ }
+
+ if (mWindow)
+ {
+ D3DPRESENT_PARAMETERS presentParameters = {0};
+ presentParameters.AutoDepthStencilFormat = mConfig->mDepthStencilFormat;
+ presentParameters.BackBufferCount = 1;
+ presentParameters.BackBufferFormat = mConfig->mRenderTargetFormat;
+ presentParameters.EnableAutoDepthStencil = FALSE;
+ presentParameters.Flags = 0;
+ presentParameters.hDeviceWindow = getWindowHandle();
+ presentParameters.MultiSampleQuality = 0; // FIXME: Unimplemented
+ presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; // FIXME: Unimplemented
+ presentParameters.PresentationInterval = mPresentInterval;
+ presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
+ presentParameters.Windowed = TRUE;
+ presentParameters.BackBufferWidth = backbufferWidth;
+ presentParameters.BackBufferHeight = backbufferHeight;
+
+ // http://crbug.com/140239
+ // http://crbug.com/143434
+ //
+ // Some AMD/Intel switchable systems / drivers appear to round swap chain surfaces to a multiple of 64 pixels in width
+ // when using the integrated Intel. This rounds the width up rather than down.
+ //
+ // Some non-switchable AMD GPUs / drivers do not respect the source rectangle to Present. Therefore, when the vendor ID
+ // is not Intel, the back buffer width must be exactly the same width as the window or horizontal scaling will occur.
+ D3DADAPTER_IDENTIFIER9* adapterIdentifier = mDisplay->getAdapterIdentifier();
+ if (adapterIdentifier->VendorId == VENDOR_ID_INTEL)
+ {
+ presentParameters.BackBufferWidth = (presentParameters.BackBufferWidth + 63) / 64 * 64;
+ }
+
+ result = device->CreateAdditionalSwapChain(&presentParameters, &mSwapChain);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL || result == D3DERR_DEVICELOST);
+
+ ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
+ release();
+
+ if(isDeviceLostError(result))
+ {
+ mDisplay->notifyDeviceLost();
+ return false;
+ }
+ else
+ {
+ return error(EGL_BAD_ALLOC, false);
+ }
+ }
+
+ result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer);
+ ASSERT(SUCCEEDED(result));
+ }
+
+ if (mConfig->mDepthStencilFormat != D3DFMT_UNKNOWN)
+ {
+ result = device->CreateDepthStencilSurface(backbufferWidth, backbufferHeight, mConfig->mDepthStencilFormat, D3DMULTISAMPLE_NONE,
+ 0, FALSE, &mDepthStencil, NULL);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL);
+
+ ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result);
+ release();
+
+ if(isDeviceLostError(result))
+ {
+ mDisplay->notifyDeviceLost();
+ return false;
+ }
+ else
+ {
+ return error(EGL_BAD_ALLOC, false);
+ }
+ }
+ }
+
+ mWidth = backbufferWidth;
+ mHeight = backbufferHeight;
+
+ mPresentIntervalDirty = false;
+ return true;
+}
+
+bool Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ if (!mSwapChain)
+ {
+ return true;
+ }
+
+ if (x + width > mWidth)
+ {
+ width = mWidth - x;
+ }
+
+ if (y + height > mHeight)
+ {
+ height = mHeight - y;
+ }
+
+ if (width == 0 || height == 0)
+ {
+ return true;
+ }
+
+ IDirect3DDevice9 *device = mDisplay->getDevice();
+
+ // Disable all pipeline operations
+ device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
+ device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
+ device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
+ device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
+ device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+ device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+ device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
+ device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED);
+ device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE);
+ device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
+ device->SetPixelShader(NULL);
+ device->SetVertexShader(NULL);
+
+ device->SetRenderTarget(0, mBackBuffer);
+ device->SetDepthStencilSurface(NULL);
+
+ device->SetTexture(0, mOffscreenTexture);
+ device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+ device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
+ device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
+ device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
+ device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
+ device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
+ device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
+
+ D3DVIEWPORT9 viewport = {0, 0, mWidth, mHeight, 0.0f, 1.0f};
+ device->SetViewport(&viewport);
+
+ float x1 = x - 0.5f;
+ float y1 = (mHeight - y - height) - 0.5f;
+ float x2 = (x + width) - 0.5f;
+ float y2 = (mHeight - y) - 0.5f;
+
+ float u1 = x / float(mWidth);
+ float v1 = y / float(mHeight);
+ float u2 = (x + width) / float(mWidth);
+ float v2 = (y + height) / float(mHeight);
+
+ float quad[4][6] = {{x1, y1, 0.0f, 1.0f, u1, v2},
+ {x2, y1, 0.0f, 1.0f, u2, v2},
+ {x2, y2, 0.0f, 1.0f, u2, v1},
+ {x1, y2, 0.0f, 1.0f, u1, v1}}; // x, y, z, rhw, u, v
+
+ mDisplay->startScene();
+ device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float));
+ mDisplay->endScene();
+
+ device->SetTexture(0, NULL);
+
+ RECT rect =
+ {
+ x, mHeight - y - height,
+ x + width, mHeight - y
+ };
+
+ HRESULT result = mSwapChain->Present(&rect, &rect, NULL, NULL, 0);
+
+ gl::Context *context = static_cast<gl::Context*>(glGetCurrentContext());
+ if (context)
+ {
+ context->markAllStateDirty();
+ }
+
+ if (isDeviceLostError(result))
+ {
+ mDisplay->notifyDeviceLost();
+ return false;
+ }
+
+ if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR)
+ {
+ return error(EGL_BAD_ALLOC, false);
+ }
+
+ ASSERT(SUCCEEDED(result));
+
+ checkForOutOfDateSwapChain();
+
+ return true;
+}
+
+HWND Surface::getWindowHandle()
+{
+ return mWindow;
+}
+
+
+#define kSurfaceProperty _TEXT("Egl::SurfaceOwner")
+#define kParentWndProc _TEXT("Egl::SurfaceParentWndProc")
+
+static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
+{
+ if (message == WM_SIZE)
+ {
+ Surface* surf = reinterpret_cast<Surface*>(GetProp(hwnd, kSurfaceProperty));
+ if(surf)
+ {
+ surf->checkForOutOfDateSwapChain();
+ }
+ }
+ WNDPROC prevWndFunc = reinterpret_cast<WNDPROC >(GetProp(hwnd, kParentWndProc));
+ return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam);
+}
+
+void Surface::subclassWindow()
+{
+ if (!mWindow)
+ {
+ return;
+ }
+
+ DWORD processId;
+ DWORD threadId = GetWindowThreadProcessId(mWindow, &processId);
+ if (processId != GetCurrentProcessId() || threadId != GetCurrentThreadId())
+ {
+ return;
+ }
+
+ SetLastError(0);
+ LONG_PTR oldWndProc = SetWindowLongPtr(mWindow, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
+ if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS)
+ {
+ mWindowSubclassed = false;
+ return;
+ }
+
+ SetProp(mWindow, kSurfaceProperty, reinterpret_cast<HANDLE>(this));
+ SetProp(mWindow, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc));
+ mWindowSubclassed = true;
+}
+
+void Surface::unsubclassWindow()
+{
+ if(!mWindowSubclassed)
+ {
+ return;
+ }
+
+ // un-subclass
+ LONG_PTR parentWndFunc = reinterpret_cast<LONG_PTR>(GetProp(mWindow, kParentWndProc));
+
+ // Check the windowproc is still SurfaceWindowProc.
+ // If this assert fails, then it is likely the application has subclassed the
+ // hwnd as well and did not unsubclass before destroying its EGL context. The
+ // application should be modified to either subclass before initializing the
+ // EGL context, or to unsubclass before destroying the EGL context.
+ if(parentWndFunc)
+ {
+ LONG_PTR prevWndFunc = SetWindowLongPtr(mWindow, GWLP_WNDPROC, parentWndFunc);
+ ASSERT(prevWndFunc == reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
+ }
+
+ RemoveProp(mWindow, kSurfaceProperty);
+ RemoveProp(mWindow, kParentWndProc);
+ mWindowSubclassed = false;
+}
+
+bool Surface::checkForOutOfDateSwapChain()
+{
+ RECT client;
+ if (!GetClientRect(getWindowHandle(), &client))
+ {
+ ASSERT(false);
+ return false;
+ }
+
+ // Grow the buffer now, if the window has grown. We need to grow now to avoid losing information.
+ int clientWidth = client.right - client.left;
+ int clientHeight = client.bottom - client.top;
+ bool sizeDirty = clientWidth != getWidth() || clientHeight != getHeight();
+
+ if (sizeDirty || mPresentIntervalDirty)
+ {
+ resetSwapChain(clientWidth, clientHeight);
+ if (static_cast<egl::Surface*>(getCurrentDrawSurface()) == this)
+ {
+ glMakeCurrent(glGetCurrentContext(), static_cast<egl::Display*>(getCurrentDisplay()), this);
+ }
+
+ return true;
+ }
+ return false;
+}
+
+DWORD Surface::convertInterval(EGLint interval)
+{
+ switch(interval)
+ {
+ case 0: return D3DPRESENT_INTERVAL_IMMEDIATE;
+ case 1: return D3DPRESENT_INTERVAL_ONE;
+ case 2: return D3DPRESENT_INTERVAL_TWO;
+ case 3: return D3DPRESENT_INTERVAL_THREE;
+ case 4: return D3DPRESENT_INTERVAL_FOUR;
+ default: UNREACHABLE();
+ }
+
+ return D3DPRESENT_INTERVAL_DEFAULT;
+}
+
+bool Surface::swap()
+{
+ return swapRect(0, 0, mWidth, mHeight);
+}
+
+bool Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ if (!mPostSubBufferSupported)
+ {
+ // Spec is not clear about how this should be handled.
+ return true;
+ }
+
+ return swapRect(x, y, width, height);
+}
+
+EGLint Surface::getWidth() const
+{
+ return mWidth;
+}
+
+EGLint Surface::getHeight() const
+{
+ return mHeight;
+}
+
+EGLint Surface::isPostSubBufferSupported() const
+{
+ return mPostSubBufferSupported;
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+IDirect3DSurface9 *Surface::getRenderTarget()
+{
+ if (mRenderTarget)
+ {
+ mRenderTarget->AddRef();
+ }
+
+ return mRenderTarget;
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+IDirect3DSurface9 *Surface::getDepthStencil()
+{
+ if (mDepthStencil)
+ {
+ mDepthStencil->AddRef();
+ }
+
+ return mDepthStencil;
+}
+
+IDirect3DTexture9 *Surface::getOffscreenTexture()
+{
+ if (mOffscreenTexture)
+ {
+ mOffscreenTexture->AddRef();
+ }
+
+ return mOffscreenTexture;
+}
+
+void Surface::setSwapInterval(EGLint interval)
+{
+ if (mSwapInterval == interval)
+ {
+ return;
+ }
+
+ mSwapInterval = interval;
+ mSwapInterval = std::max(mSwapInterval, mDisplay->getMinSwapInterval());
+ mSwapInterval = std::min(mSwapInterval, mDisplay->getMaxSwapInterval());
+
+ mPresentInterval = convertInterval(mSwapInterval);
+ mPresentIntervalDirty = true;
+}
+
+EGLenum Surface::getTextureFormat() const
+{
+ return mTextureFormat;
+}
+
+EGLenum Surface::getTextureTarget() const
+{
+ return mTextureTarget;
+}
+
+void Surface::setBoundTexture(gl::Texture2D *texture)
+{
+ mTexture = texture;
+}
+
+gl::Texture2D *Surface::getBoundTexture() const
+{
+ return mTexture;
+}
+
+D3DFORMAT Surface::getFormat() const
+{
+ return mConfig->mRenderTargetFormat;
+}
+}
diff --git a/src/3rdparty/angle/src/libEGL/Surface.h b/src/3rdparty/angle/src/libEGL/Surface.h
new file mode 100644
index 0000000000..40bd7028ab
--- /dev/null
+++ b/src/3rdparty/angle/src/libEGL/Surface.h
@@ -0,0 +1,112 @@
+//
+// Copyright (c) 2002-2010 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.
+//
+
+// Surface.h: Defines the egl::Surface class, representing a drawing surface
+// such as the client area of a window, including any back buffers.
+// Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3.
+
+#ifndef INCLUDE_SURFACE_H_
+#define INCLUDE_SURFACE_H_
+
+#define EGLAPI
+#include <EGL/egl.h>
+#include <d3d9.h>
+
+#include "common/angleutils.h"
+
+namespace gl
+{
+class Texture2D;
+}
+
+namespace egl
+{
+class Display;
+class Config;
+
+class Surface
+{
+ public:
+ Surface(Display *display, const egl::Config *config, HWND window, EGLint postSubBufferSupported);
+ Surface(Display *display, const egl::Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureTarget);
+
+ ~Surface();
+
+ bool initialize();
+ void release();
+ bool resetSwapChain();
+
+ HWND getWindowHandle();
+ bool swap();
+ bool postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height);
+
+ virtual EGLint getWidth() const;
+ virtual EGLint getHeight() const;
+
+ virtual EGLint isPostSubBufferSupported() const;
+
+ virtual IDirect3DSurface9 *getRenderTarget();
+ virtual IDirect3DSurface9 *getDepthStencil();
+ virtual IDirect3DTexture9 *getOffscreenTexture();
+
+ HANDLE getShareHandle() { return mShareHandle; }
+
+ void setSwapInterval(EGLint interval);
+ bool checkForOutOfDateSwapChain(); // Returns true if swapchain changed due to resize or interval update
+
+ virtual EGLenum getTextureFormat() const;
+ virtual EGLenum getTextureTarget() const;
+ virtual D3DFORMAT getFormat() const;
+
+ virtual void setBoundTexture(gl::Texture2D *texture);
+ virtual gl::Texture2D *getBoundTexture() const;
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(Surface);
+
+ Display *const mDisplay;
+ IDirect3DSwapChain9 *mSwapChain;
+ IDirect3DSurface9 *mBackBuffer;
+ IDirect3DSurface9 *mDepthStencil;
+ IDirect3DSurface9* mRenderTarget;
+ IDirect3DTexture9* mOffscreenTexture;
+
+ HANDLE mShareHandle;
+
+ void subclassWindow();
+ void unsubclassWindow();
+ bool resetSwapChain(int backbufferWidth, int backbufferHeight);
+ bool swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
+ static DWORD convertInterval(EGLint interval);
+
+ const HWND mWindow; // Window that the surface is created for.
+ bool mWindowSubclassed; // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking
+ const egl::Config *mConfig; // EGL config surface was created with
+ EGLint mHeight; // Height of surface
+ EGLint mWidth; // Width of surface
+// EGLint horizontalResolution; // Horizontal dot pitch
+// EGLint verticalResolution; // Vertical dot pitch
+// EGLBoolean largestPBuffer; // If true, create largest pbuffer possible
+// EGLBoolean mipmapTexture; // True if texture has mipmaps
+// EGLint mipmapLevel; // Mipmap level to render to
+// EGLenum multisampleResolve; // Multisample resolve behavior
+ EGLint mPixelAspectRatio; // Display aspect ratio
+ EGLenum mRenderBuffer; // Render buffer
+ EGLenum mSwapBehavior; // Buffer swap behavior
+ EGLenum mTextureFormat; // Format of texture: RGB, RGBA, or no texture
+ EGLenum mTextureTarget; // Type of texture: 2D or no texture
+// EGLenum vgAlphaFormat; // Alpha format for OpenVG
+// EGLenum vgColorSpace; // Color space for OpenVG
+ EGLint mSwapInterval;
+ EGLint mPostSubBufferSupported;
+
+ DWORD mPresentInterval;
+ bool mPresentIntervalDirty;
+ gl::Texture2D *mTexture;
+};
+}
+
+#endif // INCLUDE_SURFACE_H_
diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp
new file mode 100644
index 0000000000..25df1c8c24
--- /dev/null
+++ b/src/3rdparty/angle/src/libEGL/libEGL.cpp
@@ -0,0 +1,1181 @@
+//
+// Copyright (c) 2002-2010 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.
+//
+
+// libEGL.cpp: Implements the exported EGL functions.
+
+#include <exception>
+
+#include "common/debug.h"
+#include "common/version.h"
+#include "libGLESv2/Context.h"
+#include "libGLESv2/Texture.h"
+
+#include "libEGL/main.h"
+#include "libEGL/Display.h"
+
+
+bool validateDisplay(egl::Display *display)
+{
+ if (display == EGL_NO_DISPLAY)
+ {
+ return error(EGL_BAD_DISPLAY, false);
+ }
+
+ if (!display->isInitialized())
+ {
+ return error(EGL_NOT_INITIALIZED, false);
+ }
+
+ return true;
+}
+
+bool validateConfig(egl::Display *display, EGLConfig config)
+{
+ if (!validateDisplay(display))
+ {
+ return false;
+ }
+
+ if (!display->isValidConfig(config))
+ {
+ return error(EGL_BAD_CONFIG, false);
+ }
+
+ return true;
+}
+
+bool validateContext(egl::Display *display, gl::Context *context)
+{
+ if (!validateDisplay(display))
+ {
+ return false;
+ }
+
+ if (!display->isValidContext(context))
+ {
+ return error(EGL_BAD_CONTEXT, false);
+ }
+
+ return true;
+}
+
+bool validateSurface(egl::Display *display, egl::Surface *surface)
+{
+ if (!validateDisplay(display))
+ {
+ return false;
+ }
+
+ if (!display->isValidSurface(surface))
+ {
+ return error(EGL_BAD_SURFACE, false);
+ }
+
+ return true;
+}
+
+extern "C"
+{
+EGLint __stdcall eglGetError(void)
+{
+ EVENT("()");
+
+ EGLint error = egl::getCurrentError();
+
+ if (error != EGL_SUCCESS)
+ {
+ egl::setCurrentError(EGL_SUCCESS);
+ }
+
+ return error;
+}
+
+EGLDisplay __stdcall eglGetDisplay(EGLNativeDisplayType display_id)
+{
+ EVENT("(EGLNativeDisplayType display_id = 0x%0.8p)", display_id);
+
+ try
+ {
+ return egl::Display::getDisplay(display_id);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_NO_DISPLAY);
+ }
+}
+
+EGLBoolean __stdcall eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint *major = 0x%0.8p, EGLint *minor = 0x%0.8p)",
+ dpy, major, minor);
+
+ try
+ {
+ if (dpy == EGL_NO_DISPLAY)
+ {
+ return error(EGL_BAD_DISPLAY, EGL_FALSE);
+ }
+
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!display->initialize())
+ {
+ return error(EGL_NOT_INITIALIZED, EGL_FALSE);
+ }
+
+ if (major) *major = 1;
+ if (minor) *minor = 4;
+
+ return success(EGL_TRUE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+}
+
+EGLBoolean __stdcall eglTerminate(EGLDisplay dpy)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p)", dpy);
+
+ try
+ {
+ if (dpy == EGL_NO_DISPLAY)
+ {
+ return error(EGL_BAD_DISPLAY, EGL_FALSE);
+ }
+
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ display->terminate();
+
+ return success(EGL_TRUE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+}
+
+const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint name = %d)", dpy, name);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!validateDisplay(display))
+ {
+ return NULL;
+ }
+
+ switch (name)
+ {
+ case EGL_CLIENT_APIS:
+ return success("OpenGL_ES");
+ case EGL_EXTENSIONS:
+ return display->getExtensionString();
+ case EGL_VENDOR:
+ return success("Google Inc.");
+ case EGL_VERSION:
+ return success("1.4 (ANGLE " VERSION_STRING ")");
+ }
+
+ return error(EGL_BAD_PARAMETER, (const char*)NULL);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, (const char*)NULL);
+ }
+}
+
+EGLBoolean __stdcall eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig *configs = 0x%0.8p, "
+ "EGLint config_size = %d, EGLint *num_config = 0x%0.8p)",
+ dpy, configs, config_size, num_config);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!validateDisplay(display))
+ {
+ return EGL_FALSE;
+ }
+
+ if (!num_config)
+ {
+ return error(EGL_BAD_PARAMETER, EGL_FALSE);
+ }
+
+ const EGLint attribList[] = {EGL_NONE};
+
+ if (!display->getConfigs(configs, attribList, config_size, num_config))
+ {
+ return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+ }
+
+ return success(EGL_TRUE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+}
+
+EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p, "
+ "EGLConfig *configs = 0x%0.8p, EGLint config_size = %d, EGLint *num_config = 0x%0.8p)",
+ dpy, attrib_list, configs, config_size, num_config);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!validateDisplay(display))
+ {
+ return EGL_FALSE;
+ }
+
+ if (!num_config)
+ {
+ return error(EGL_BAD_PARAMETER, EGL_FALSE);
+ }
+
+ const EGLint attribList[] = {EGL_NONE};
+
+ if (!attrib_list)
+ {
+ attrib_list = attribList;
+ }
+
+ display->getConfigs(configs, attrib_list, config_size, num_config);
+
+ return success(EGL_TRUE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+}
+
+EGLBoolean __stdcall eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)",
+ dpy, config, attribute, value);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!validateConfig(display, config))
+ {
+ return EGL_FALSE;
+ }
+
+ if (!display->getConfigAttrib(config, attribute, value))
+ {
+ return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+ }
+
+ return success(EGL_TRUE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+}
+
+EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativeWindowType win = 0x%0.8p, "
+ "const EGLint *attrib_list = 0x%0.8p)", dpy, config, win, attrib_list);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!validateConfig(display, config))
+ {
+ return EGL_NO_SURFACE;
+ }
+
+ HWND window = (HWND)win;
+
+ if (!IsWindow(window))
+ {
+ return error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
+ }
+
+ return display->createWindowSurface(window, config, attrib_list);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+ }
+}
+
+EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)",
+ dpy, config, attrib_list);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!validateConfig(display, config))
+ {
+ return EGL_NO_SURFACE;
+ }
+
+ return display->createOffscreenSurface(config, NULL, attrib_list);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+ }
+}
+
+EGLSurface __stdcall eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativePixmapType pixmap = 0x%0.8p, "
+ "const EGLint *attrib_list = 0x%0.8p)", dpy, config, pixmap, attrib_list);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!validateConfig(display, config))
+ {
+ return EGL_NO_SURFACE;
+ }
+
+ UNIMPLEMENTED(); // FIXME
+
+ return success(EGL_NO_SURFACE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+ }
+}
+
+EGLBoolean __stdcall eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+ egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
+
+ if (!validateSurface(display, eglSurface))
+ {
+ return EGL_FALSE;
+ }
+
+ if (surface == EGL_NO_SURFACE)
+ {
+ return error(EGL_BAD_SURFACE, EGL_FALSE);
+ }
+
+ display->destroySurface((egl::Surface*)surface);
+
+ return success(EGL_TRUE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+}
+
+EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)",
+ dpy, surface, attribute, value);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+ egl::Surface *eglSurface = (egl::Surface*)surface;
+
+ if (!validateSurface(display, eglSurface))
+ {
+ return EGL_FALSE;
+ }
+
+ if (surface == EGL_NO_SURFACE)
+ {
+ return error(EGL_BAD_SURFACE, EGL_FALSE);
+ }
+
+ switch (attribute)
+ {
+ case EGL_VG_ALPHA_FORMAT:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_VG_COLORSPACE:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_CONFIG_ID:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_HEIGHT:
+ *value = eglSurface->getHeight();
+ break;
+ case EGL_HORIZONTAL_RESOLUTION:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_LARGEST_PBUFFER:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_MIPMAP_TEXTURE:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_MIPMAP_LEVEL:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_MULTISAMPLE_RESOLVE:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_PIXEL_ASPECT_RATIO:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_RENDER_BUFFER:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_SWAP_BEHAVIOR:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_TEXTURE_FORMAT:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_TEXTURE_TARGET:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_VERTICAL_RESOLUTION:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_WIDTH:
+ *value = eglSurface->getWidth();
+ break;
+ case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
+ *value = eglSurface->isPostSubBufferSupported();
+ break;
+ default:
+ return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+ }
+
+ return success(EGL_TRUE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+}
+
+EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value)
+{
+ TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, void **value = 0x%0.8p)",
+ dpy, surface, attribute, value);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+ egl::Surface *eglSurface = (egl::Surface*)surface;
+
+ if (!validateSurface(display, eglSurface))
+ {
+ return EGL_FALSE;
+ }
+
+ if (surface == EGL_NO_SURFACE)
+ {
+ return error(EGL_BAD_SURFACE, EGL_FALSE);
+ }
+
+ switch (attribute)
+ {
+ case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
+ *value = (void*) eglSurface->getShareHandle();
+ break;
+ default:
+ return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+ }
+
+ return success(EGL_TRUE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+}
+
+EGLBoolean __stdcall eglBindAPI(EGLenum api)
+{
+ EVENT("(EGLenum api = 0x%X)", api);
+
+ try
+ {
+ switch (api)
+ {
+ case EGL_OPENGL_API:
+ case EGL_OPENVG_API:
+ return error(EGL_BAD_PARAMETER, EGL_FALSE); // Not supported by this implementation
+ case EGL_OPENGL_ES_API:
+ break;
+ default:
+ return error(EGL_BAD_PARAMETER, EGL_FALSE);
+ }
+
+ egl::setCurrentAPI(api);
+
+ return success(EGL_TRUE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+}
+
+EGLenum __stdcall eglQueryAPI(void)
+{
+ EVENT("()");
+
+ try
+ {
+ EGLenum API = egl::getCurrentAPI();
+
+ return success(API);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+}
+
+EGLBoolean __stdcall eglWaitClient(void)
+{
+ EVENT("()");
+
+ try
+ {
+ UNIMPLEMENTED(); // FIXME
+
+ return success(0);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+}
+
+EGLBoolean __stdcall eglReleaseThread(void)
+{
+ EVENT("()");
+
+ try
+ {
+ eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
+
+ return success(EGL_TRUE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+}
+
+EGLSurface __stdcall eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLenum buftype = 0x%X, EGLClientBuffer buffer = 0x%0.8p, "
+ "EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)",
+ dpy, buftype, buffer, config, attrib_list);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!validateConfig(display, config))
+ {
+ return EGL_NO_SURFACE;
+ }
+
+ if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE || !buffer)
+ {
+ return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
+ }
+
+ return display->createOffscreenSurface(config, (HANDLE)buffer, attrib_list);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+ }
+}
+
+EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint value = %d)",
+ dpy, surface, attribute, value);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+ egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
+
+ if (!validateSurface(display, eglSurface))
+ {
+ return EGL_FALSE;
+ }
+
+ UNIMPLEMENTED(); // FIXME
+
+ return success(EGL_TRUE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+}
+
+EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+ egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
+
+ if (!validateSurface(display, eglSurface))
+ {
+ return EGL_FALSE;
+ }
+
+ if (buffer != EGL_BACK_BUFFER)
+ {
+ return error(EGL_BAD_PARAMETER, EGL_FALSE);
+ }
+
+ if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle())
+ {
+ return error(EGL_BAD_SURFACE, EGL_FALSE);
+ }
+
+ if (eglSurface->getBoundTexture())
+ {
+ return error(EGL_BAD_ACCESS, EGL_FALSE);
+ }
+
+ if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
+ {
+ return error(EGL_BAD_MATCH, EGL_FALSE);
+ }
+
+ if (!glBindTexImage(eglSurface))
+ {
+ return error(EGL_BAD_MATCH, EGL_FALSE);
+ }
+
+ return success(EGL_TRUE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+}
+
+EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+ egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
+
+ if (!validateSurface(display, eglSurface))
+ {
+ return EGL_FALSE;
+ }
+
+ if (buffer != EGL_BACK_BUFFER)
+ {
+ return error(EGL_BAD_PARAMETER, EGL_FALSE);
+ }
+
+ if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle())
+ {
+ return error(EGL_BAD_SURFACE, EGL_FALSE);
+ }
+
+ if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
+ {
+ return error(EGL_BAD_MATCH, EGL_FALSE);
+ }
+
+ gl::Texture2D *texture = eglSurface->getBoundTexture();
+
+ if (texture)
+ {
+ texture->releaseTexImage();
+ }
+
+ return success(EGL_TRUE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+}
+
+EGLBoolean __stdcall eglSwapInterval(EGLDisplay dpy, EGLint interval)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint interval = %d)", dpy, interval);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!validateDisplay(display))
+ {
+ return EGL_FALSE;
+ }
+
+ egl::Surface *draw_surface = static_cast<egl::Surface*>(egl::getCurrentDrawSurface());
+
+ if (draw_surface == NULL)
+ {
+ return error(EGL_BAD_SURFACE, EGL_FALSE);
+ }
+
+ draw_surface->setSwapInterval(interval);
+
+ return success(EGL_TRUE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+}
+
+EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLContext share_context = 0x%0.8p, "
+ "const EGLint *attrib_list = 0x%0.8p)", dpy, config, share_context, attrib_list);
+
+ try
+ {
+ // Get the requested client version (default is 1) and check it is two.
+ EGLint client_version = 1;
+ bool reset_notification = false;
+ bool robust_access = false;
+
+ if (attrib_list)
+ {
+ for (const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)
+ {
+ switch (attribute[0])
+ {
+ case EGL_CONTEXT_CLIENT_VERSION:
+ client_version = attribute[1];
+ break;
+ case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
+ if (attribute[1] == EGL_TRUE)
+ {
+ return error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); // Unimplemented
+ // robust_access = true;
+ }
+ else if (attribute[1] != EGL_FALSE)
+ return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
+ break;
+ case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
+ if (attribute[1] == EGL_LOSE_CONTEXT_ON_RESET_EXT)
+ reset_notification = true;
+ else if (attribute[1] != EGL_NO_RESET_NOTIFICATION_EXT)
+ return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
+ break;
+ default:
+ return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
+ }
+ }
+ }
+
+ if (client_version != 2)
+ {
+ return error(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
+ }
+
+ if (share_context && static_cast<gl::Context*>(share_context)->isResetNotificationEnabled() != reset_notification)
+ {
+ return error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
+ }
+
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!validateConfig(display, config))
+ {
+ return EGL_NO_CONTEXT;
+ }
+
+ EGLContext context = display->createContext(config, static_cast<gl::Context*>(share_context), reset_notification, robust_access);
+
+ if (context)
+ return success(context);
+ else
+ return error(EGL_CONTEXT_LOST, EGL_NO_CONTEXT);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
+ }
+}
+
+EGLBoolean __stdcall eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p)", dpy, ctx);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+ gl::Context *context = static_cast<gl::Context*>(ctx);
+
+ if (!validateContext(display, context))
+ {
+ return EGL_FALSE;
+ }
+
+ if (ctx == EGL_NO_CONTEXT)
+ {
+ return error(EGL_BAD_CONTEXT, EGL_FALSE);
+ }
+
+ display->destroyContext(context);
+
+ return success(EGL_TRUE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+}
+
+EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface draw = 0x%0.8p, EGLSurface read = 0x%0.8p, EGLContext ctx = 0x%0.8p)",
+ dpy, draw, read, ctx);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+ gl::Context *context = static_cast<gl::Context*>(ctx);
+ IDirect3DDevice9 *device = display->getDevice();
+
+ if (!device || display->testDeviceLost())
+ {
+ display->notifyDeviceLost();
+ return EGL_FALSE;
+ }
+
+ if (display->isDeviceLost())
+ {
+ return error(EGL_CONTEXT_LOST, EGL_FALSE);
+ }
+
+ if (ctx != EGL_NO_CONTEXT && !validateContext(display, context))
+ {
+ return EGL_FALSE;
+ }
+
+ if ((draw != EGL_NO_SURFACE && !validateSurface(display, static_cast<egl::Surface*>(draw))) ||
+ (read != EGL_NO_SURFACE && !validateSurface(display, static_cast<egl::Surface*>(read))))
+ {
+ return EGL_FALSE;
+ }
+
+ if (draw != read)
+ {
+ UNIMPLEMENTED(); // FIXME
+ }
+
+ egl::setCurrentDisplay(dpy);
+ egl::setCurrentDrawSurface(draw);
+ egl::setCurrentReadSurface(read);
+
+ glMakeCurrent(context, display, static_cast<egl::Surface*>(draw));
+
+ return success(EGL_TRUE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+}
+
+EGLContext __stdcall eglGetCurrentContext(void)
+{
+ EVENT("()");
+
+ try
+ {
+ EGLContext context = glGetCurrentContext();
+
+ return success(context);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
+ }
+}
+
+EGLSurface __stdcall eglGetCurrentSurface(EGLint readdraw)
+{
+ EVENT("(EGLint readdraw = %d)", readdraw);
+
+ try
+ {
+ if (readdraw == EGL_READ)
+ {
+ EGLSurface read = egl::getCurrentReadSurface();
+ return success(read);
+ }
+ else if (readdraw == EGL_DRAW)
+ {
+ EGLSurface draw = egl::getCurrentDrawSurface();
+ return success(draw);
+ }
+ else
+ {
+ return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+ }
+}
+
+EGLDisplay __stdcall eglGetCurrentDisplay(void)
+{
+ EVENT("()");
+
+ try
+ {
+ EGLDisplay dpy = egl::getCurrentDisplay();
+
+ return success(dpy);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_NO_DISPLAY);
+ }
+}
+
+EGLBoolean __stdcall eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)",
+ dpy, ctx, attribute, value);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+ gl::Context *context = static_cast<gl::Context*>(ctx);
+
+ if (!validateContext(display, context))
+ {
+ return EGL_FALSE;
+ }
+
+ UNIMPLEMENTED(); // FIXME
+
+ return success(0);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+}
+
+EGLBoolean __stdcall eglWaitGL(void)
+{
+ EVENT("()");
+
+ try
+ {
+ UNIMPLEMENTED(); // FIXME
+
+ return success(0);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+}
+
+EGLBoolean __stdcall eglWaitNative(EGLint engine)
+{
+ EVENT("(EGLint engine = %d)", engine);
+
+ try
+ {
+ UNIMPLEMENTED(); // FIXME
+
+ return success(0);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+}
+
+EGLBoolean __stdcall eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+ egl::Surface *eglSurface = (egl::Surface*)surface;
+
+ if (!validateSurface(display, eglSurface))
+ {
+ return EGL_FALSE;
+ }
+
+ if (display->isDeviceLost())
+ {
+ return error(EGL_CONTEXT_LOST, EGL_FALSE);
+ }
+
+ if (surface == EGL_NO_SURFACE)
+ {
+ return error(EGL_BAD_SURFACE, EGL_FALSE);
+ }
+
+ if (eglSurface->swap())
+ {
+ return success(EGL_TRUE);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+
+ return EGL_FALSE;
+}
+
+EGLBoolean __stdcall eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLNativePixmapType target = 0x%0.8p)", dpy, surface, target);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+ egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
+
+ if (!validateSurface(display, eglSurface))
+ {
+ return EGL_FALSE;
+ }
+
+ if (display->isDeviceLost())
+ {
+ return error(EGL_CONTEXT_LOST, EGL_FALSE);
+ }
+
+ UNIMPLEMENTED(); // FIXME
+
+ return success(0);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+}
+
+EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint x = %d, EGLint y = %d, EGLint width = %d, EGLint height = %d)", dpy, surface, x, y, width, height);
+
+ try
+ {
+ if (x < 0 || y < 0 || width < 0 || height < 0)
+ {
+ return error(EGL_BAD_PARAMETER, EGL_FALSE);
+ }
+
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+ egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
+
+ if (!validateSurface(display, eglSurface))
+ {
+ return EGL_FALSE;
+ }
+
+ if (display->isDeviceLost())
+ {
+ return error(EGL_CONTEXT_LOST, EGL_FALSE);
+ }
+
+ if (surface == EGL_NO_SURFACE)
+ {
+ return error(EGL_BAD_SURFACE, EGL_FALSE);
+ }
+
+ if (eglSurface->postSubBuffer(x, y, width, height))
+ {
+ return success(EGL_TRUE);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+
+ return EGL_FALSE;
+}
+
+__eglMustCastToProperFunctionPointerType __stdcall eglGetProcAddress(const char *procname)
+{
+ EVENT("(const char *procname = \"%s\")", procname);
+
+ try
+ {
+ struct Extension
+ {
+ const char *name;
+ __eglMustCastToProperFunctionPointerType address;
+ };
+
+ static const Extension eglExtensions[] =
+ {
+ {"eglQuerySurfacePointerANGLE", (__eglMustCastToProperFunctionPointerType)eglQuerySurfacePointerANGLE},
+ {"eglPostSubBufferNV", (__eglMustCastToProperFunctionPointerType)eglPostSubBufferNV},
+ {"", NULL},
+ };
+
+ for (int ext = 0; ext < sizeof(eglExtensions) / sizeof(Extension); ext++)
+ {
+ if (strcmp(procname, eglExtensions[ext].name) == 0)
+ {
+ return (__eglMustCastToProperFunctionPointerType)eglExtensions[ext].address;
+ }
+ }
+
+ return glGetProcAddress(procname);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, (__eglMustCastToProperFunctionPointerType)NULL);
+ }
+}
+}
diff --git a/src/3rdparty/angle/src/libEGL/libEGL.def b/src/3rdparty/angle/src/libEGL/libEGL.def
new file mode 100644
index 0000000000..71a5e67977
--- /dev/null
+++ b/src/3rdparty/angle/src/libEGL/libEGL.def
@@ -0,0 +1,36 @@
+LIBRARY libEGL
+EXPORTS
+ eglBindAPI @14
+ eglBindTexImage @20
+ eglChooseConfig @7
+ eglCopyBuffers @33
+ eglCreateContext @23
+ eglCreatePbufferFromClientBuffer @18
+ eglCreatePbufferSurface @10
+ eglCreatePixmapSurface @11
+ eglCreateWindowSurface @9
+ eglDestroyContext @24
+ eglDestroySurface @12
+ eglGetConfigAttrib @8
+ eglGetConfigs @6
+ eglGetCurrentContext @26
+ eglGetCurrentDisplay @28
+ eglGetCurrentSurface @27
+ eglGetDisplay @2
+ eglGetError @1
+ eglGetProcAddress @34
+ eglInitialize @3
+ eglMakeCurrent @25
+ eglQueryAPI @15
+ eglQueryContext @29
+ eglQueryString @5
+ eglQuerySurface @13
+ eglReleaseTexImage @21
+ eglReleaseThread @17
+ eglSurfaceAttrib @19
+ eglSwapBuffers @32
+ eglSwapInterval @22
+ eglTerminate @4
+ eglWaitClient @16
+ eglWaitGL @30
+ eglWaitNative @31 \ No newline at end of file
diff --git a/src/3rdparty/angle/src/libEGL/libEGL.rc b/src/3rdparty/angle/src/libEGL/libEGL.rc
new file mode 100644
index 0000000000..5d1f32f1c9
--- /dev/null
+++ b/src/3rdparty/angle/src/libEGL/libEGL.rc
@@ -0,0 +1,102 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include <windows.h>
+#include "../common/version.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "#include ""../common/version.h""\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION MAJOR_VERSION,MINOR_VERSION,BUILD_VERSION,BUILD_REVISION
+ PRODUCTVERSION MAJOR_VERSION,MINOR_VERSION,BUILD_VERSION,BUILD_REVISION
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "FileDescription", "ANGLE libEGL Dynamic Link Library"
+ VALUE "FileVersion", VERSION_STRING
+ VALUE "InternalName", "libEGL"
+ VALUE "LegalCopyright", "Copyright (C) 2011 Google Inc."
+ VALUE "OriginalFilename", "libEGL.dll"
+ VALUE "PrivateBuild", VERSION_STRING
+ VALUE "ProductName", "ANGLE libEGL Dynamic Link Library"
+ VALUE "ProductVersion", VERSION_STRING
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
diff --git a/src/3rdparty/angle/src/libEGL/main.cpp b/src/3rdparty/angle/src/libEGL/main.cpp
new file mode 100644
index 0000000000..dc24c4fb04
--- /dev/null
+++ b/src/3rdparty/angle/src/libEGL/main.cpp
@@ -0,0 +1,165 @@
+//
+// Copyright (c) 2002-2012 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.
+//
+
+// main.cpp: DLL entry point and management of thread-local data.
+
+#include "libEGL/main.h"
+
+#include "common/debug.h"
+
+static DWORD currentTLS = TLS_OUT_OF_INDEXES;
+
+extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
+{
+ switch (reason)
+ {
+ case DLL_PROCESS_ATTACH:
+ {
+#if !defined(ANGLE_DISABLE_TRACE)
+ FILE *debug = fopen(TRACE_OUTPUT_FILE, "rt");
+
+ if (debug)
+ {
+ fclose(debug);
+ debug = fopen(TRACE_OUTPUT_FILE, "wt"); // Erase
+
+ if (debug)
+ {
+ fclose(debug);
+ }
+ }
+#endif
+
+ currentTLS = TlsAlloc();
+
+ if (currentTLS == TLS_OUT_OF_INDEXES)
+ {
+ return FALSE;
+ }
+ }
+ // Fall throught to initialize index
+ case DLL_THREAD_ATTACH:
+ {
+ egl::Current *current = (egl::Current*)LocalAlloc(LPTR, sizeof(egl::Current));
+
+ if (current)
+ {
+ TlsSetValue(currentTLS, current);
+
+ current->error = EGL_SUCCESS;
+ current->API = EGL_OPENGL_ES_API;
+ current->display = EGL_NO_DISPLAY;
+ current->drawSurface = EGL_NO_SURFACE;
+ current->readSurface = EGL_NO_SURFACE;
+ }
+ }
+ break;
+ case DLL_THREAD_DETACH:
+ {
+ void *current = TlsGetValue(currentTLS);
+
+ if (current)
+ {
+ LocalFree((HLOCAL)current);
+ }
+ }
+ break;
+ case DLL_PROCESS_DETACH:
+ {
+ void *current = TlsGetValue(currentTLS);
+
+ if (current)
+ {
+ LocalFree((HLOCAL)current);
+ }
+
+ TlsFree(currentTLS);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+
+namespace egl
+{
+void setCurrentError(EGLint error)
+{
+ Current *current = (Current*)TlsGetValue(currentTLS);
+
+ current->error = error;
+}
+
+EGLint getCurrentError()
+{
+ Current *current = (Current*)TlsGetValue(currentTLS);
+
+ return current->error;
+}
+
+void setCurrentAPI(EGLenum API)
+{
+ Current *current = (Current*)TlsGetValue(currentTLS);
+
+ current->API = API;
+}
+
+EGLenum getCurrentAPI()
+{
+ Current *current = (Current*)TlsGetValue(currentTLS);
+
+ return current->API;
+}
+
+void setCurrentDisplay(EGLDisplay dpy)
+{
+ Current *current = (Current*)TlsGetValue(currentTLS);
+
+ current->display = dpy;
+}
+
+EGLDisplay getCurrentDisplay()
+{
+ Current *current = (Current*)TlsGetValue(currentTLS);
+
+ return current->display;
+}
+
+void setCurrentDrawSurface(EGLSurface surface)
+{
+ Current *current = (Current*)TlsGetValue(currentTLS);
+
+ current->drawSurface = surface;
+}
+
+EGLSurface getCurrentDrawSurface()
+{
+ Current *current = (Current*)TlsGetValue(currentTLS);
+
+ return current->drawSurface;
+}
+
+void setCurrentReadSurface(EGLSurface surface)
+{
+ Current *current = (Current*)TlsGetValue(currentTLS);
+
+ current->readSurface = surface;
+}
+
+EGLSurface getCurrentReadSurface()
+{
+ Current *current = (Current*)TlsGetValue(currentTLS);
+
+ return current->readSurface;
+}
+}
+
+void error(EGLint errorCode)
+{
+ egl::setCurrentError(errorCode);
+}
diff --git a/src/3rdparty/angle/src/libEGL/main.h b/src/3rdparty/angle/src/libEGL/main.h
new file mode 100644
index 0000000000..d09d9e6bc3
--- /dev/null
+++ b/src/3rdparty/angle/src/libEGL/main.h
@@ -0,0 +1,61 @@
+//
+// Copyright (c) 2002-2010 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.
+//
+
+// main.h: Management of thread-local data.
+
+#ifndef LIBEGL_MAIN_H_
+#define LIBEGL_MAIN_H_
+
+#define EGLAPI
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+namespace egl
+{
+struct Current
+{
+ EGLint error;
+ EGLenum API;
+ EGLDisplay display;
+ EGLSurface drawSurface;
+ EGLSurface readSurface;
+};
+
+void setCurrentError(EGLint error);
+EGLint getCurrentError();
+
+void setCurrentAPI(EGLenum API);
+EGLenum getCurrentAPI();
+
+void setCurrentDisplay(EGLDisplay dpy);
+EGLDisplay getCurrentDisplay();
+
+void setCurrentDrawSurface(EGLSurface surface);
+EGLSurface getCurrentDrawSurface();
+
+void setCurrentReadSurface(EGLSurface surface);
+EGLSurface getCurrentReadSurface();
+}
+
+void error(EGLint errorCode);
+
+template<class T>
+const T &error(EGLint errorCode, const T &returnValue)
+{
+ error(errorCode);
+
+ return returnValue;
+}
+
+template<class T>
+const T &success(const T &returnValue)
+{
+ egl::setCurrentError(EGL_SUCCESS);
+
+ return returnValue;
+}
+
+#endif // LIBEGL_MAIN_H_
diff --git a/src/3rdparty/angle/src/libEGL/resource.h b/src/3rdparty/angle/src/libEGL/resource.h
new file mode 100644
index 0000000000..3921f4c077
--- /dev/null
+++ b/src/3rdparty/angle/src/libEGL/resource.h
@@ -0,0 +1,14 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by libEGL.rc
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif