summaryrefslogtreecommitdiffstats
path: root/Source/ThirdParty/ANGLE/src/libEGL
diff options
context:
space:
mode:
Diffstat (limited to 'Source/ThirdParty/ANGLE/src/libEGL')
-rw-r--r--Source/ThirdParty/ANGLE/src/libEGL/Config.cpp7
-rw-r--r--Source/ThirdParty/ANGLE/src/libEGL/Display.cpp301
-rw-r--r--Source/ThirdParty/ANGLE/src/libEGL/Display.h19
-rw-r--r--Source/ThirdParty/ANGLE/src/libEGL/Surface.cpp266
-rw-r--r--Source/ThirdParty/ANGLE/src/libEGL/Surface.h19
-rw-r--r--Source/ThirdParty/ANGLE/src/libEGL/libEGL.cpp35
6 files changed, 462 insertions, 185 deletions
diff --git a/Source/ThirdParty/ANGLE/src/libEGL/Config.cpp b/Source/ThirdParty/ANGLE/src/libEGL/Config.cpp
index 21d4661..284f61d 100644
--- a/Source/ThirdParty/ANGLE/src/libEGL/Config.cpp
+++ b/Source/ThirdParty/ANGLE/src/libEGL/Config.cpp
@@ -94,13 +94,6 @@ void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInter
mBlueSize = 5;
mAlphaSize = 0;
break;
- case D3DFMT_X1R5G5B5:
- mBufferSize = 16;
- mRedSize = 5;
- mGreenSize = 5;
- mBlueSize = 5;
- mAlphaSize = 0;
- break;
case D3DFMT_X8R8G8B8:
mBufferSize = 32;
mRedSize = 8;
diff --git a/Source/ThirdParty/ANGLE/src/libEGL/Display.cpp b/Source/ThirdParty/ANGLE/src/libEGL/Display.cpp
index e2802da..6f1a335 100644
--- a/Source/ThirdParty/ANGLE/src/libEGL/Display.cpp
+++ b/Source/ThirdParty/ANGLE/src/libEGL/Display.cpp
@@ -17,7 +17,8 @@
#include "libEGL/main.h"
-#define REF_RAST 0 // Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros
+#define REF_RAST 0 // Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros
+#define ENABLE_D3D9EX 1 // Enables use of the IDirect3D9Ex interface, when available
namespace egl
{
@@ -40,7 +41,6 @@ Display::Display(HDC deviceContext) : mDc(deviceContext)
mMinSwapInterval = 1;
mMaxSwapInterval = 1;
- setSwapInterval(1);
}
Display::~Display()
@@ -77,7 +77,7 @@ bool Display::initialize()
// 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 (Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9ex)))
+ if (ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9ex)))
{
ASSERT(mD3d9ex);
mD3d9ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9));
@@ -95,11 +95,26 @@ bool Display::initialize()
// UNIMPLEMENTED(); // FIXME: Determine which adapter index the device context corresponds to
}
- HRESULT result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps);
-
- if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+ HRESULT result;
+
+ // Give up on getting device caps after about one second.
+ for (int i = 0; i < 10; ++i)
{
- return error(EGL_BAD_ALLOC, false);
+ 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))
@@ -108,6 +123,14 @@ bool Display::initialize()
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;
@@ -123,7 +146,7 @@ bool Display::initialize()
// 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,
+ // D3DFMT_X1R5G5B5, // Has no compatible OpenGL ES renderbuffer format
D3DFMT_X8R8G8B8
};
@@ -183,13 +206,6 @@ bool Display::initialize()
mConfigSet.mSet.insert(configuration);
}
-
- if (!createDevice())
- {
- terminate();
-
- return false;
- }
}
if (!isInitialized())
@@ -199,23 +215,34 @@ bool Display::initialize()
return false;
}
+ 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);
+
return true;
}
void Display::terminate()
{
- for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
+ while (!mSurfaceSet.empty())
{
- delete *surface;
+ destroySurface(*mSurfaceSet.begin());
}
- for (ContextSet::iterator context = mContextSet.begin(); context != mContextSet.end(); context++)
+ while (!mContextSet.empty())
{
- glDestroyContext(*context);
+ destroyContext(*mContextSet.begin());
}
if (mDevice)
{
+ // If the device is lost, reset it first to prevent leaving the driver in an unstable state
+ if (FAILED(mDevice->TestCooperativeLevel()))
+ {
+ resetDevice();
+ }
+
mDevice->Release();
mDevice = NULL;
}
@@ -314,33 +341,12 @@ bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value)
bool Display::createDevice()
{
- 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);
-
- 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 = convertInterval(mMinSwapInterval);
- presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
- presentParameters.Windowed = TRUE;
-
+ 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)
+ if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST)
{
return error(EGL_BAD_ALLOC, false);
}
@@ -349,14 +355,13 @@ bool Display::createDevice()
{
result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice);
- if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+ if (FAILED(result))
{
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST);
return error(EGL_BAD_ALLOC, false);
}
}
- ASSERT(SUCCEEDED(result));
-
// Permanent non-default states
mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
@@ -365,6 +370,29 @@ bool Display::createDevice()
return true;
}
+bool Display::resetDevice()
+{
+ D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
+ HRESULT result;
+
+ do
+ {
+ Sleep(0); // Give the graphics driver some CPU time
+
+ result = mDevice->Reset(&presentParameters);
+ }
+ while (result == D3DERR_DEVICELOST);
+
+ if (FAILED(result))
+ {
+ return error(EGL_BAD_ALLOC, false);
+ }
+
+ ASSERT(SUCCEEDED(result));
+
+ return true;
+}
+
Surface *Display::createWindowSurface(HWND window, EGLConfig config)
{
const Config *configuration = mConfigSet.get(config);
@@ -377,6 +405,27 @@ Surface *Display::createWindowSurface(HWND window, EGLConfig config)
EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *shareContext)
{
+ if (!mDevice)
+ {
+ if (!createDevice())
+ {
+ return NULL;
+ }
+ }
+ else if (FAILED(mDevice->TestCooperativeLevel())) // Lost device
+ {
+ if (!resetDevice())
+ {
+ return NULL;
+ }
+
+ // Restore any surfaces that may have been lost
+ for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
+ {
+ (*surface)->resetSwapChain();
+ }
+ }
+
const egl::Config *config = mConfigSet.get(configHandle);
gl::Context *context = glCreateContext(config, shareContext);
@@ -395,6 +444,14 @@ void Display::destroyContext(gl::Context *context)
{
glDestroyContext(context);
mContextSet.erase(context);
+
+ if (mContextSet.empty() && mDevice && FAILED(mDevice->TestCooperativeLevel())) // Last context of a lost device
+ {
+ for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
+ {
+ (*surface)->release();
+ }
+ }
}
bool Display::isInitialized()
@@ -430,37 +487,26 @@ bool Display::hasExistingWindowSurface(HWND window)
return false;
}
-void Display::setSwapInterval(GLint interval)
+EGLint Display::getMinSwapInterval()
{
- mSwapInterval = interval;
- mSwapInterval = std::max(mSwapInterval, mMinSwapInterval);
- mSwapInterval = std::min(mSwapInterval, mMaxSwapInterval);
-
- mPresentInterval = convertInterval(mSwapInterval);
+ return mMinSwapInterval;
}
-DWORD Display::getPresentInterval()
+EGLint Display::getMaxSwapInterval()
{
- return mPresentInterval;
+ return mMaxSwapInterval;
}
-DWORD Display::convertInterval(GLint interval)
+IDirect3DDevice9 *Display::getDevice()
{
- switch(interval)
+ if (!mDevice)
{
- 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();
+ if (!createDevice())
+ {
+ return NULL;
+ }
}
- return D3DPRESENT_INTERVAL_DEFAULT;
-}
-
-IDirect3DDevice9 *Display::getDevice()
-{
return mDevice;
}
@@ -487,4 +533,127 @@ bool Display::getCompressedTextureSupport()
return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1));
}
+
+bool Display::getFloatTextureSupport(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::getHalfFloatTextureSupport(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));
+}
+
+D3DPOOL Display::getBufferPool(DWORD usage) const
+{
+ if (mD3d9ex != NULL)
+ {
+ return D3DPOOL_DEFAULT;
+ }
+ else
+ {
+ if (!(usage & D3DUSAGE_DYNAMIC))
+ {
+ return D3DPOOL_MANAGED;
+ }
+ }
+
+ return D3DPOOL_DEFAULT;
+}
+
+bool Display::getEventQuerySupport()
+{
+ IDirect3DQuery9 *query;
+ HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &query);
+ if (SUCCEEDED(result))
+ {
+ query->Release();
+ }
+
+ return result != D3DERR_NOTAVAILABLE;
+}
+
+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;
}
+} \ No newline at end of file
diff --git a/Source/ThirdParty/ANGLE/src/libEGL/Display.h b/Source/ThirdParty/ANGLE/src/libEGL/Display.h
index bd33012..4b74e1e 100644
--- a/Source/ThirdParty/ANGLE/src/libEGL/Display.h
+++ b/Source/ThirdParty/ANGLE/src/libEGL/Display.h
@@ -54,17 +54,25 @@ class Display
bool isValidSurface(egl::Surface *surface);
bool hasExistingWindowSurface(HWND window);
- void setSwapInterval(GLint interval);
- DWORD getPresentInterval();
- static DWORD convertInterval(GLint interval);
+ EGLint getMinSwapInterval();
+ EGLint getMaxSwapInterval();
virtual IDirect3DDevice9 *getDevice();
virtual D3DCAPS9 getDeviceCaps();
virtual void getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray);
virtual bool getCompressedTextureSupport();
+ virtual bool getEventQuerySupport();
+ virtual bool getFloatTextureSupport(bool *filtering, bool *renderable);
+ virtual bool getHalfFloatTextureSupport(bool *filtering, bool *renderable);
+ virtual bool getLuminanceTextureSupport();
+ virtual bool getLuminanceAlphaTextureSupport();
+ virtual D3DPOOL getBufferPool(DWORD usage) const;
private:
DISALLOW_COPY_AND_ASSIGN(Display);
+
+ D3DPRESENT_PARAMETERS getDefaultPresentParameters();
+
const HDC mDc;
HMODULE mD3d9Module;
@@ -78,11 +86,9 @@ class Display
HWND mDeviceWindow;
bool mSceneStarted;
- GLint mSwapInterval;
EGLint mMaxSwapInterval;
EGLint mMinSwapInterval;
- DWORD mPresentInterval;
-
+
typedef std::set<Surface*> SurfaceSet;
SurfaceSet mSurfaceSet;
@@ -92,6 +98,7 @@ class Display
ContextSet mContextSet;
bool createDevice();
+ bool resetDevice();
};
}
diff --git a/Source/ThirdParty/ANGLE/src/libEGL/Surface.cpp b/Source/ThirdParty/ANGLE/src/libEGL/Surface.cpp
index a5638d4..2736a7f 100644
--- a/Source/ThirdParty/ANGLE/src/libEGL/Surface.cpp
+++ b/Source/ThirdParty/ANGLE/src/libEGL/Surface.cpp
@@ -8,6 +8,8 @@
// 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"
@@ -23,7 +25,6 @@ Surface::Surface(Display *display, const Config *config, HWND window)
mSwapChain = NULL;
mDepthStencil = NULL;
mBackBuffer = NULL;
- mRenderTarget = NULL;
mFlipTexture = NULL;
mFlipState = NULL;
mPreFlipState = NULL;
@@ -31,52 +32,86 @@ Surface::Surface(Display *display, const Config *config, HWND window)
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();
resetSwapChain();
}
Surface::~Surface()
{
+ unsubclassWindow();
+ release();
+}
+
+void Surface::release()
+{
if (mSwapChain)
{
mSwapChain->Release();
+ mSwapChain = NULL;
}
if (mBackBuffer)
{
mBackBuffer->Release();
- }
-
- if (mRenderTarget)
- {
- mRenderTarget->Release();
+ mBackBuffer = NULL;
}
if (mDepthStencil)
{
mDepthStencil->Release();
+ mDepthStencil = NULL;
}
if (mFlipTexture)
{
mFlipTexture->Release();
+ mFlipTexture = NULL;
}
if (mFlipState)
{
mFlipState->Release();
+ mFlipState = NULL;
}
if (mPreFlipState)
{
mPreFlipState->Release();
+ mPreFlipState = NULL;
}
}
void Surface::resetSwapChain()
{
+ RECT windowRect;
+ if (!GetClientRect(getWindowHandle(), &windowRect))
+ {
+ ASSERT(false);
+
+ ERR("Could not retrieve the window dimensions");
+ return;
+ }
+
+ resetSwapChain(windowRect.right - windowRect.left, windowRect.bottom - windowRect.top);
+}
+
+void Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
+{
IDirect3DDevice9 *device = mDisplay->getDevice();
+ if (device == NULL)
+ {
+ return;
+ }
+
+ // 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();
+ release();
+
D3DPRESENT_PARAMETERS presentParameters = {0};
presentParameters.AutoDepthStencilFormat = mConfig->mDepthStencilFormat;
@@ -87,96 +122,57 @@ void Surface::resetSwapChain()
presentParameters.hDeviceWindow = getWindowHandle();
presentParameters.MultiSampleQuality = 0; // FIXME: Unimplemented
presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; // FIXME: Unimplemented
- presentParameters.PresentationInterval = Display::convertInterval(mConfig->mMinSwapInterval);
+ presentParameters.PresentationInterval = mPresentInterval;
presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
presentParameters.Windowed = TRUE;
+ presentParameters.BackBufferWidth = backbufferWidth;
+ presentParameters.BackBufferHeight = backbufferHeight;
- RECT windowRect;
- if (!GetClientRect(getWindowHandle(), &windowRect))
- {
- ASSERT(false);
- return;
- }
-
- presentParameters.BackBufferWidth = windowRect.right - windowRect.left;
- presentParameters.BackBufferHeight = windowRect.bottom - windowRect.top;
-
- IDirect3DSwapChain9 *swapChain = NULL;
- HRESULT result = device->CreateAdditionalSwapChain(&presentParameters, &swapChain);
+ HRESULT result = device->CreateAdditionalSwapChain(&presentParameters, &mSwapChain);
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
ERR("Could not create additional swap chains: %08lX", result);
+ release();
return error(EGL_BAD_ALLOC);
}
- IDirect3DSurface9 *depthStencilSurface = NULL;
result = device->CreateDepthStencilSurface(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight,
presentParameters.AutoDepthStencilFormat, presentParameters.MultiSampleType,
- presentParameters.MultiSampleQuality, FALSE, &depthStencilSurface, NULL);
+ presentParameters.MultiSampleQuality, FALSE, &mDepthStencil, NULL);
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
- swapChain->Release();
-
ERR("Could not create depthstencil surface for new swap chain: %08lX", result);
- return error(EGL_BAD_ALLOC);
- }
-
- IDirect3DSurface9 *renderTarget = NULL;
- result = device->CreateRenderTarget(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight, presentParameters.BackBufferFormat,
- presentParameters.MultiSampleType, presentParameters.MultiSampleQuality, FALSE, &renderTarget, NULL);
-
- if (FAILED(result))
- {
- ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-
- swapChain->Release();
- depthStencilSurface->Release();
-
- ERR("Could not create render target surface for new swap chain: %08lX", result);
+ release();
return error(EGL_BAD_ALLOC);
}
ASSERT(SUCCEEDED(result));
- IDirect3DTexture9 *flipTexture = NULL;
result = device->CreateTexture(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight, 1, D3DUSAGE_RENDERTARGET,
- presentParameters.BackBufferFormat, D3DPOOL_DEFAULT, &flipTexture, NULL);
+ presentParameters.BackBufferFormat, D3DPOOL_DEFAULT, &mFlipTexture, NULL);
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
- swapChain->Release();
- depthStencilSurface->Release();
- renderTarget->Release();
-
ERR("Could not create flip texture for new swap chain: %08lX", result);
+ release();
return error(EGL_BAD_ALLOC);
}
- IDirect3DSurface9 *backBuffer = NULL;
- swapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
-
- if (mSwapChain) mSwapChain->Release();
- if (mDepthStencil) mDepthStencil->Release();
- if (mBackBuffer) mBackBuffer->Release();
- if (mRenderTarget) mRenderTarget->Release();
- if (mFlipTexture) mFlipTexture->Release();
-
+ mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer);
mWidth = presentParameters.BackBufferWidth;
mHeight = presentParameters.BackBufferHeight;
- mSwapChain = swapChain;
- mDepthStencil = depthStencilSurface;
- mBackBuffer = backBuffer;
- mRenderTarget = renderTarget;
- mFlipTexture = flipTexture;
+ mPresentIntervalDirty = false;
+
+ InvalidateRect(mWindow, NULL, FALSE);
// The flip state block recorded mFlipTexture so it is now invalid.
releaseRecordedState(device);
@@ -199,6 +195,7 @@ void Surface::writeRecordableFlipState(IDirect3DDevice9 *device)
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);
@@ -206,7 +203,7 @@ void Surface::writeRecordableFlipState(IDirect3DDevice9 *device)
device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
- device->SetTexture(0, NULL); // The actual texture will change after resizing. But the pre-flip state block must save/restore the texture.
+ device->SetTexture(0, NULL); // The actual texture will change after resizing. But the pre-flip state block must save/restore the texture.
device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
device->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, FALSE);
@@ -214,7 +211,10 @@ void Surface::writeRecordableFlipState(IDirect3DDevice9 *device)
device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
- device->SetStreamSourceFreq(0, 1); // DrawPrimitiveUP only cares about stream 0, not the rest.
+ RECT scissorRect = {0}; // Scissoring is disabled for flipping, but we need this to capture and restore the old rectangle
+ device->SetScissorRect(&scissorRect);
+ D3DVIEWPORT9 viewport = {0, 0, mWidth, mHeight, 0.0f, 1.0f};
+ device->SetViewport(&viewport);
}
void Surface::applyFlipState(IDirect3DDevice9 *device)
@@ -275,8 +275,6 @@ void Surface::applyFlipState(IDirect3DDevice9 *device)
void Surface::restoreState(IDirect3DDevice9 *device)
{
- mPreFlipState->Apply();
-
device->SetRenderTarget(0, mPreFlipBackBuffer);
device->SetDepthStencilSurface(mPreFlipDepthStencil);
@@ -291,6 +289,8 @@ void Surface::restoreState(IDirect3DDevice9 *device)
mPreFlipDepthStencil->Release();
mPreFlipDepthStencil = NULL;
}
+
+ mPreFlipState->Apply();
}
// On the next flip, this will cause the state to be recorded from scratch.
@@ -309,8 +309,58 @@ void Surface::releaseRecordedState(IDirect3DDevice9 *device)
mPreFlipState = NULL;
}
}
+#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);
+}
-bool Surface::checkForWindowResize()
+void Surface::subclassWindow()
+{
+ SetLastError(0);
+ LONG oldWndProc = SetWindowLong(mWindow, GWL_WNDPROC, reinterpret_cast<LONG>(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 parentWndFunc = reinterpret_cast<LONG>(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 prevWndFunc = SetWindowLong(mWindow, GWL_WNDPROC, parentWndFunc);
+ ASSERT(prevWndFunc == reinterpret_cast<LONG>(SurfaceWindowProc));
+ }
+
+ RemoveProp(mWindow, kSurfaceProperty);
+ RemoveProp(mWindow, kParentWndProc);
+ mWindowSubclassed = false;
+}
+
+bool Surface::checkForOutOfDateSwapChain()
{
RECT client;
if (!GetClientRect(getWindowHandle(), &client))
@@ -319,10 +369,14 @@ bool Surface::checkForWindowResize()
return false;
}
- if (getWidth() != client.right - client.left || getHeight() != client.bottom - client.top)
- {
- resetSwapChain();
+ // 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);
@@ -330,57 +384,51 @@ bool Surface::checkForWindowResize()
return true;
}
-
return false;
}
-bool Surface::swap()
+DWORD Surface::convertInterval(EGLint interval)
{
- if (mSwapChain)
+ switch(interval)
{
- IDirect3DTexture9 *flipTexture = mFlipTexture;
- flipTexture->AddRef();
-
- IDirect3DSurface9 *renderTarget = mRenderTarget;
- renderTarget->AddRef();
+ 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();
+ }
- EGLint oldWidth = mWidth;
- EGLint oldHeight = mHeight;
+ return D3DPRESENT_INTERVAL_DEFAULT;
+}
- checkForWindowResize();
+bool Surface::swap()
+{
+ if (mSwapChain)
+ {
IDirect3DDevice9 *device = mDisplay->getDevice();
- IDirect3DSurface9 *textureSurface;
- flipTexture->GetSurfaceLevel(0, &textureSurface);
-
- mDisplay->endScene();
- device->StretchRect(renderTarget, NULL, textureSurface, NULL, D3DTEXF_NONE);
- renderTarget->Release();
-
applyFlipState(device);
- device->SetTexture(0, flipTexture);
-
- float xscale = (float)mWidth / oldWidth;
- float yscale = (float)mHeight / oldHeight;
+ device->SetTexture(0, mFlipTexture);
// Render the texture upside down into the back buffer
- // Texcoords are chosen to pin a potentially resized image into the upper-left corner without scaling.
- float quad[4][6] = {{ 0 - 0.5f, 0 - 0.5f, 0.0f, 1.0f, 0.0f, 1.0f },
- {mWidth - 0.5f, 0 - 0.5f, 0.0f, 1.0f, xscale, 1.0f },
- {mWidth - 0.5f, mHeight - 0.5f, 0.0f, 1.0f, xscale, 1.0f-yscale},
- { 0 - 0.5f, mHeight - 0.5f, 0.0f, 1.0f, 0.0f, 1.0f-yscale}}; // x, y, z, rhw, u, v
+ // Texcoords are chosen to flip the renderTarget about its Y axis.
+ float w = static_cast<float>(getWidth());
+ float h = static_cast<float>(getHeight());
+ float quad[4][6] = {{0 - 0.5f, 0 - 0.5f, 0.0f, 1.0f, 0.0f, 1.0f},
+ {w - 0.5f, 0 - 0.5f, 0.0f, 1.0f, 1.0f, 1.0f},
+ {w - 0.5f, h - 0.5f, 0.0f, 1.0f, 1.0f, 0.0f},
+ {0 - 0.5f, h - 0.5f, 0.0f, 1.0f, 0.0f, 0.0f}}; // x, y, z, rhw, u, v
mDisplay->startScene();
device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float));
- flipTexture->Release();
- textureSurface->Release();
-
restoreState(device);
mDisplay->endScene();
- HRESULT result = mSwapChain->Present(NULL, NULL, NULL, NULL, mDisplay->getPresentInterval());
+
+ HRESULT result = mSwapChain->Present(NULL, NULL, NULL, NULL, 0);
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR)
{
@@ -394,6 +442,7 @@ bool Surface::swap()
ASSERT(SUCCEEDED(result));
+ checkForOutOfDateSwapChain();
}
return true;
@@ -411,12 +460,14 @@ EGLint Surface::getHeight() const
IDirect3DSurface9 *Surface::getRenderTarget()
{
- if (mRenderTarget)
+ IDirect3DSurface9 *textureSurface = NULL;
+
+ if (mFlipTexture)
{
- mRenderTarget->AddRef();
+ mFlipTexture->GetSurfaceLevel(0, &textureSurface);
}
- return mRenderTarget;
+ return textureSurface;
}
IDirect3DSurface9 *Surface::getDepthStencil()
@@ -428,4 +479,19 @@ IDirect3DSurface9 *Surface::getDepthStencil()
return mDepthStencil;
}
+
+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;
+}
}
diff --git a/Source/ThirdParty/ANGLE/src/libEGL/Surface.h b/Source/ThirdParty/ANGLE/src/libEGL/Surface.h
index 5bc912c..422d3d5 100644
--- a/Source/ThirdParty/ANGLE/src/libEGL/Surface.h
+++ b/Source/ThirdParty/ANGLE/src/libEGL/Surface.h
@@ -29,6 +29,9 @@ class Surface
~Surface();
+ void release();
+ void resetSwapChain();
+
HWND getWindowHandle();
bool swap();
@@ -38,18 +41,22 @@ class Surface
virtual IDirect3DSurface9 *getRenderTarget();
virtual IDirect3DSurface9 *getDepthStencil();
- private:
+ void setSwapInterval(EGLint interval);
+ bool checkForOutOfDateSwapChain(); // Returns true if swapchain changed due to resize or interval update
+
+private:
DISALLOW_COPY_AND_ASSIGN(Surface);
Display *const mDisplay;
IDirect3DSwapChain9 *mSwapChain;
IDirect3DSurface9 *mBackBuffer;
- IDirect3DSurface9 *mRenderTarget;
IDirect3DSurface9 *mDepthStencil;
IDirect3DTexture9 *mFlipTexture;
- void resetSwapChain();
- bool checkForWindowResize();
+ void subclassWindow();
+ void unsubclassWindow();
+ void resetSwapChain(int backbufferWidth, int backbufferHeight);
+ static DWORD convertInterval(EGLint interval);
void applyFlipState(IDirect3DDevice9 *device);
void restoreState(IDirect3DDevice9 *device);
@@ -61,6 +68,7 @@ class Surface
IDirect3DSurface9 *mPreFlipDepthStencil;
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
@@ -77,6 +85,9 @@ class Surface
// EGLenum textureTarget; // Type of texture: 2D or no texture
// EGLenum vgAlphaFormat; // Alpha format for OpenVG
// EGLenum vgColorSpace; // Color space for OpenVG
+ EGLint mSwapInterval;
+ DWORD mPresentInterval;
+ bool mPresentIntervalDirty;
};
}
diff --git a/Source/ThirdParty/ANGLE/src/libEGL/libEGL.cpp b/Source/ThirdParty/ANGLE/src/libEGL/libEGL.cpp
index 5ceb6ef..8dfe6e5 100644
--- a/Source/ThirdParty/ANGLE/src/libEGL/libEGL.cpp
+++ b/Source/ThirdParty/ANGLE/src/libEGL/libEGL.cpp
@@ -360,6 +360,8 @@ EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EG
default:
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
}
+
+ attrib_list += 2;
}
}
@@ -746,7 +748,14 @@ EGLBoolean __stdcall eglSwapInterval(EGLDisplay dpy, EGLint interval)
return EGL_FALSE;
}
- display->setSwapInterval(interval);
+ 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);
}
@@ -765,6 +774,28 @@ EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLConte
try
{
+ // Get the requested client version (default is 1) and check it is two.
+ EGLint client_version = 1;
+ if (attrib_list)
+ {
+ for (const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)
+ {
+ if (attribute[0] == EGL_CONTEXT_CLIENT_VERSION)
+ {
+ client_version = attribute[1];
+ }
+ else
+ {
+ return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
+ }
+ }
+ }
+
+ if (client_version != 2)
+ {
+ return error(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
+ }
+
egl::Display *display = static_cast<egl::Display*>(dpy);
if (!validate(display, config))
@@ -825,7 +856,7 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface
gl::Context *context = static_cast<gl::Context*>(ctx);
IDirect3DDevice9 *device = display->getDevice();
- if (!device || device->TestCooperativeLevel() != D3D_OK)
+ if (!device || FAILED(device->TestCooperativeLevel()))
{
return error(EGL_CONTEXT_LOST, EGL_FALSE);
}