summaryrefslogtreecommitdiffstats
path: root/Source/ThirdParty/ANGLE/src/libEGL/Display.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/ThirdParty/ANGLE/src/libEGL/Display.cpp')
-rw-r--r--Source/ThirdParty/ANGLE/src/libEGL/Display.cpp721
1 files changed, 648 insertions, 73 deletions
diff --git a/Source/ThirdParty/ANGLE/src/libEGL/Display.cpp b/Source/ThirdParty/ANGLE/src/libEGL/Display.cpp
index 6f1a335..6a5cfd3 100644
--- a/Source/ThirdParty/ANGLE/src/libEGL/Display.cpp
+++ b/Source/ThirdParty/ANGLE/src/libEGL/Display.cpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// 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.
//
@@ -11,24 +11,70 @@
#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"
-#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
+// 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
{
-Display::Display(HDC deviceContext) : mDc(deviceContext)
+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;
+ mD3d9Ex = NULL;
mDevice = NULL;
+ mDeviceEx = NULL;
mDeviceWindow = NULL;
mAdapter = D3DADAPTER_DEFAULT;
@@ -41,11 +87,21 @@ Display::Display(HDC deviceContext) : mDc(deviceContext)
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()
@@ -55,17 +111,15 @@ bool Display::initialize()
return true;
}
- mD3d9Module = LoadLibrary(TEXT("d3d9.dll"));
- if (mD3d9Module == NULL)
+ if (mSoftwareDevice)
{
- terminate();
- return false;
+ mD3d9Module = GetModuleHandle(TEXT("swiftshader_d3d9.dll"));
+ }
+ else
+ {
+ mD3d9Module = GetModuleHandle(TEXT("d3d9.dll"));
}
-
- typedef IDirect3D9* (WINAPI *Direct3DCreate9Func)(UINT);
- Direct3DCreate9Func Direct3DCreate9Ptr = reinterpret_cast<Direct3DCreate9Func>(GetProcAddress(mD3d9Module, "Direct3DCreate9"));
-
- if (Direct3DCreate9Ptr == NULL)
+ if (mD3d9Module == NULL)
{
terminate();
return false;
@@ -77,15 +131,15 @@ 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 (ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9ex)))
+ if (ANGLE_ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex)))
{
- ASSERT(mD3d9ex);
- mD3d9ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9));
+ ASSERT(mD3d9Ex);
+ mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9));
ASSERT(mD3d9);
}
else
{
- mD3d9 = Direct3DCreate9Ptr(D3D_SDK_VERSION);
+ mD3d9 = Direct3DCreate9(D3D_SDK_VERSION);
}
if (mD3d9)
@@ -140,6 +194,8 @@ bool Display::initialize()
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);
+
const D3DFORMAT renderTargetFormats[] =
{
D3DFMT_A1R5G5B5,
@@ -152,6 +208,7 @@ bool Display::initialize()
const D3DFORMAT depthStencilFormats[] =
{
+ D3DFMT_UNKNOWN,
// D3DFMT_D16_LOCKABLE,
D3DFMT_D32,
// D3DFMT_D15S1,
@@ -179,17 +236,26 @@ bool Display::initialize()
for (int depthStencilIndex = 0; depthStencilIndex < sizeof(depthStencilFormats) / sizeof(D3DFORMAT); depthStencilIndex++)
{
D3DFORMAT depthStencilFormat = depthStencilFormats[depthStencilIndex];
- HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat);
+ HRESULT result = D3D_OK;
+
+ if(depthStencilFormat != D3DFMT_UNKNOWN)
+ {
+ result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat);
+ }
if (SUCCEEDED(result))
{
- HRESULT result = mD3d9->CheckDepthStencilMatch(mAdapter, mDeviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat);
+ 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);
+ configSet.add(currentDisplayMode, mMinSwapInterval, mMaxSwapInterval, renderTargetFormat, depthStencilFormat, 0,
+ mDeviceCaps.MaxTextureWidth, mDeviceCaps.MaxTextureHeight);
}
}
}
@@ -215,11 +281,19 @@ bool Display::initialize()
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;
+ }
+
return true;
}
@@ -235,10 +309,16 @@ void Display::terminate()
destroyContext(*mContextSet.begin());
}
+ while (!mEventQueryPool.empty())
+ {
+ mEventQueryPool.back()->Release();
+ mEventQueryPool.pop_back();
+ }
+
if (mDevice)
{
// If the device is lost, reset it first to prevent leaving the driver in an unstable state
- if (FAILED(mDevice->TestCooperativeLevel()))
+ if (testDeviceLost())
{
resetDevice();
}
@@ -247,6 +327,12 @@ void Display::terminate()
mDevice = NULL;
}
+ if (mDeviceEx)
+ {
+ mDeviceEx->Release();
+ mDeviceEx = NULL;
+ }
+
if (mD3d9)
{
mD3d9->Release();
@@ -259,15 +345,14 @@ void Display::terminate()
mDeviceWindow = NULL;
}
- if (mD3d9ex)
+ if (mD3d9Ex)
{
- mD3d9ex->Release();
- mD3d9ex = NULL;
+ mD3d9Ex->Release();
+ mD3d9Ex = NULL;
}
if (mD3d9Module)
{
- FreeLibrary(mD3d9Module);
mD3d9Module = NULL;
}
}
@@ -277,8 +362,11 @@ void Display::startScene()
if (!mSceneStarted)
{
long result = mDevice->BeginScene();
- ASSERT(SUCCEEDED(result));
- mSceneStarted = true;
+ if (SUCCEEDED(result)) {
+ // This is defensive checking against the device being
+ // lost at unexpected times.
+ mSceneStarted = true;
+ }
}
}
@@ -286,8 +374,9 @@ void Display::endScene()
{
if (mSceneStarted)
{
- long result = mDevice->EndScene();
- ASSERT(SUCCEEDED(result));
+ // EndScene can fail if the device was lost, for example due
+ // to a TDR during a draw call.
+ mDevice->EndScene();
mSceneStarted = false;
}
}
@@ -332,6 +421,9 @@ bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value)
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;
}
@@ -362,48 +454,251 @@ bool Display::createDevice()
}
}
+ 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);
mSceneStarted = false;
-
- return true;
}
bool Display::resetDevice()
{
D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
- HRESULT result;
-
- do
+
+ HRESULT result = D3D_OK;
+ bool lost = testDeviceLost();
+ int attempts = 3;
+
+ while (lost && attempts > 0)
{
- Sleep(0); // Give the graphics driver some CPU time
+ 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();
+ }
- result = mDevice->Reset(&presentParameters);
+ if (result == D3DERR_DEVICENOTRESET)
+ {
+ result = mDevice->Reset(&presentParameters);
+ }
+ }
+
+ lost = testDeviceLost();
+ attempts --;
}
- while (result == D3DERR_DEVICELOST);
if (FAILED(result))
{
+ ERR("Reset/ResetEx failed multiple times: 0x%08X", result);
return error(EGL_BAD_ALLOC, false);
}
- ASSERT(SUCCEEDED(result));
+ // reset device defaults
+ initializeDevice();
return true;
}
-Surface *Display::createWindowSurface(HWND window, EGLConfig config)
+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;
+ }
- Surface *surface = new Surface(this, configuration, window);
mSurfaceSet.insert(surface);
- return surface;
+ return success(surface);
}
-EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *shareContext)
+EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *shareContext, bool notifyResets, bool robustAccess)
{
if (!mDevice)
{
@@ -412,28 +707,56 @@ EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *sha
return NULL;
}
}
- else if (FAILED(mDevice->TestCooperativeLevel())) // Lost device
+ else if (testDeviceLost()) // Lost device
{
- if (!resetDevice())
- {
+ if (!restoreLostDevice())
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);
+ 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();
+ }
+
+ 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;
@@ -444,17 +767,24 @@ void Display::destroyContext(gl::Context *context)
{
glDestroyContext(context);
mContextSet.erase(context);
+}
- if (mContextSet.empty() && mDevice && FAILED(mDevice->TestCooperativeLevel())) // Last context of a lost device
+void Display::notifyDeviceLost()
+{
+ for (ContextSet::iterator context = mContextSet.begin(); context != mContextSet.end(); context++)
{
- for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
- {
- (*surface)->release();
- }
+ (*context)->markContextLost();
}
+ mDeviceLost = true;
+ error(EGL_CONTEXT_LOST);
+}
+
+bool Display::isDeviceLost()
+{
+ return mDeviceLost;
}
-bool Display::isInitialized()
+bool Display::isInitialized() const
{
return mD3d9 != NULL && mConfigSet.size() > 0;
}
@@ -515,6 +845,118 @@ 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++)
@@ -526,7 +968,7 @@ void Display::getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray)
}
}
-bool Display::getCompressedTextureSupport()
+bool Display::getDXT1TextureSupport()
{
D3DDISPLAYMODE currentDisplayMode;
mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
@@ -534,7 +976,23 @@ bool Display::getCompressedTextureSupport()
return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1));
}
-bool Display::getFloatTextureSupport(bool *filtering, bool *renderable)
+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));
+}
+
+bool Display::getFloat32TextureSupport(bool *filtering, bool *renderable)
{
D3DDISPLAYMODE currentDisplayMode;
mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
@@ -549,7 +1007,7 @@ bool Display::getFloatTextureSupport(bool *filtering, bool *renderable)
SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
- if (!filtering && !renderable)
+ if (!*filtering && !*renderable)
{
return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
@@ -562,7 +1020,7 @@ bool Display::getFloatTextureSupport(bool *filtering, bool *renderable)
}
}
-bool Display::getHalfFloatTextureSupport(bool *filtering, bool *renderable)
+bool Display::getFloat16TextureSupport(bool *filtering, bool *renderable)
{
D3DDISPLAYMODE currentDisplayMode;
mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
@@ -577,7 +1035,7 @@ bool Display::getHalfFloatTextureSupport(bool *filtering, bool *renderable)
SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
- if (!filtering && !renderable)
+ if (!*filtering && !*renderable)
{
return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
@@ -608,7 +1066,7 @@ bool Display::getLuminanceAlphaTextureSupport()
D3DPOOL Display::getBufferPool(DWORD usage) const
{
- if (mD3d9ex != NULL)
+ if (mD3d9Ex != NULL)
{
return D3DPOOL_DEFAULT;
}
@@ -623,16 +1081,35 @@ D3DPOOL Display::getBufferPool(DWORD usage) const
return D3DPOOL_DEFAULT;
}
-bool Display::getEventQuerySupport()
+D3DPOOL Display::getTexturePool(bool renderable) const
{
- IDirect3DQuery9 *query;
- HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &query);
- if (SUCCEEDED(result))
+ if (mD3d9Ex != NULL)
{
- query->Release();
+ return D3DPOOL_DEFAULT;
+ }
+ else
+ {
+ if (!renderable)
+ {
+ return D3DPOOL_MANAGED;
+ }
}
- return result != D3DERR_NOTAVAILABLE;
+ return D3DPOOL_DEFAULT;
+}
+
+bool Display::getEventQuerySupport()
+{
+ IDirect3DQuery9 *query = allocateEventQuery();
+ if (query)
+ {
+ freeEventQuery(query);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
}
D3DPRESENT_PARAMETERS Display::getDefaultPresentParameters()
@@ -656,4 +1133,102 @@ D3DPRESENT_PARAMETERS Display::getDefaultPresentParameters()
return presentParameters;
}
-} \ No newline at end of file
+
+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();
+}
+
+// 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 !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) &&
+ !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) &&
+ !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL);
+}
+
+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);
+}
+
+}