diff options
Diffstat (limited to 'src/3rdparty/angle/src/common')
19 files changed, 1559 insertions, 143 deletions
diff --git a/src/3rdparty/angle/src/common/NativeWindow.h b/src/3rdparty/angle/src/common/NativeWindow.h new file mode 100644 index 0000000000..c4a0e42bcc --- /dev/null +++ b/src/3rdparty/angle/src/common/NativeWindow.h @@ -0,0 +1,82 @@ +// +// Copyright (c) 2014 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. +// + +// NativeWindow.h: Defines NativeWindow, a class for managing and +// performing operations on an EGLNativeWindowType. +// It is used for HWND (Desktop Windows) and IInspectable objects +//(Windows Store Applications). + +#ifndef COMMON_NATIVEWINDOW_H_ +#define COMMON_NATIVEWINDOW_H_ + +#include <EGL/eglplatform.h> +#include "common/debug.h" +#include "common/platform.h" + +// DXGISwapChain and DXGIFactory are typedef'd to specific required +// types. The HWND NativeWindow implementation requires IDXGISwapChain +// and IDXGIFactory and the Windows Store NativeWindow +// implementation requires IDXGISwapChain1 and IDXGIFactory2. +#if defined(ANGLE_ENABLE_WINDOWS_STORE) +typedef IDXGISwapChain1 DXGISwapChain; +typedef IDXGIFactory2 DXGIFactory; + +#include <wrl.h> +#include <wrl/wrappers/corewrappers.h> +#include <windows.applicationmodel.core.h> +#include <memory> + +namespace rx +{ +class InspectableNativeWindow; +} + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; + +#else +typedef IDXGISwapChain DXGISwapChain; +typedef IDXGIFactory DXGIFactory; +#endif + +namespace rx +{ + +class NativeWindow +{ +public: + explicit NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display); + + bool initialize(); + bool getClientRect(LPRECT rect); + bool isIconic(); + +# if defined(ANGLE_ENABLE_D3D11) + typedef ID3D11Device Device; +#else + typedef IDirect3DDevice9 Device; +#endif + HRESULT createSwapChain(Device* device, DXGIFactory* factory, + DXGI_FORMAT format, UINT width, UINT height, + DXGISwapChain** swapChain); + + inline EGLNativeWindowType getNativeWindow() const { return mWindow; } + inline EGLNativeDisplayType getNativeDisplay() const { return mDisplay; } + + private: + EGLNativeWindowType mWindow; + EGLNativeDisplayType mDisplay; + +#if defined(ANGLE_ENABLE_WINDOWS_STORE) + std::shared_ptr<InspectableNativeWindow> mImpl; +#endif + +}; + +bool IsValidEGLNativeWindowType(EGLNativeWindowType window); +} + +#endif // COMMON_NATIVEWINDOW_H_ diff --git a/src/3rdparty/angle/src/common/angleutils.cpp b/src/3rdparty/angle/src/common/angleutils.cpp index 2673abf30a..c1367c460a 100644 --- a/src/3rdparty/angle/src/common/angleutils.cpp +++ b/src/3rdparty/angle/src/common/angleutils.cpp @@ -5,26 +5,33 @@ // #include "common/angleutils.h" - +#include "debug.h" +#include <stdio.h> #include <vector> -std::string FormatString(const char *fmt, va_list vararg) +size_t FormatStringIntoVector(const char *fmt, va_list vararg, std::vector<char>& outBuffer) { - static std::vector<char> buffer(512); - // Attempt to just print to the current buffer - int len = vsnprintf(&buffer[0], buffer.size(), fmt, vararg); - if (len < 0 || static_cast<size_t>(len) >= buffer.size()) + int len = vsnprintf(&(outBuffer.front()), outBuffer.size(), fmt, vararg); + if (len < 0 || static_cast<size_t>(len) >= outBuffer.size()) { // Buffer was not large enough, calculate the required size and resize the buffer len = vsnprintf(NULL, 0, fmt, vararg); - buffer.resize(len + 1); + outBuffer.resize(len + 1); // Print again - vsnprintf(&buffer[0], buffer.size(), fmt, vararg); + len = vsnprintf(&(outBuffer.front()), outBuffer.size(), fmt, vararg); } + ASSERT(len >= 0); + return static_cast<size_t>(len); +} + +std::string FormatString(const char *fmt, va_list vararg) +{ + static std::vector<char> buffer(512); - return std::string(buffer.data(), len); + size_t len = FormatStringIntoVector(fmt, vararg, buffer); + return std::string(&buffer[0], len); } std::string FormatString(const char *fmt, ...) diff --git a/src/3rdparty/angle/src/common/angleutils.h b/src/3rdparty/angle/src/common/angleutils.h index ddbbd5f501..b343ece5bc 100644 --- a/src/3rdparty/angle/src/common/angleutils.h +++ b/src/3rdparty/angle/src/common/angleutils.h @@ -17,6 +17,7 @@ #include <set> #include <sstream> #include <cstdarg> +#include <vector> // A macro to disallow the copy constructor and operator= functions // This must be used in the private: declarations for a class @@ -95,6 +96,13 @@ inline void StructZero(T *obj) memset(obj, 0, sizeof(T)); } +template <typename T> +inline bool IsMaskFlagSet(T mask, T flag) +{ + // Handles multibit flags as well + return (mask & flag) == flag; +} + inline const char* MakeStaticString(const std::string &str) { static std::set<std::string> strings; @@ -132,9 +140,12 @@ inline std::string Str(int i) return strstr.str(); } +size_t FormatStringIntoVector(const char *fmt, va_list vararg, std::vector<char>& buffer); + std::string FormatString(const char *fmt, va_list vararg); std::string FormatString(const char *fmt, ...); +// snprintf is not defined with MSVC prior to to msvc14 #if defined(_MSC_VER) && _MSC_VER < 1900 #define snprintf _snprintf #endif diff --git a/src/3rdparty/angle/src/common/debug.cpp b/src/3rdparty/angle/src/common/debug.cpp index dcad327564..5f55ff1e39 100644 --- a/src/3rdparty/angle/src/common/debug.cpp +++ b/src/3rdparty/angle/src/common/debug.cpp @@ -17,41 +17,211 @@ namespace gl { -#if defined(ANGLE_ENABLE_PERF) -typedef void (WINAPI *PerfOutputFunction)(D3DCOLOR, LPCWSTR); -#else -typedef void (*PerfOutputFunction)(unsigned int, const wchar_t*); -#endif +#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) +// Wraps the D3D9/D3D11 debug annotation functions. +class DebugAnnotationWrapper +{ + public: + DebugAnnotationWrapper() { }; + virtual ~DebugAnnotationWrapper() { }; + virtual void beginEvent(const std::wstring &eventName) = 0; + virtual void endEvent() = 0; + virtual void setMarker(const std::wstring &markerName) = 0; + virtual bool getStatus() = 0; +}; -static void output(bool traceFileDebugOnly, PerfOutputFunction perfFunc, const char *format, va_list vararg) +#if defined(ANGLE_ENABLE_D3D9) +class D3D9DebugAnnotationWrapper : public DebugAnnotationWrapper { -#if defined(ANGLE_ENABLE_PERF) || defined(ANGLE_ENABLE_TRACE) - std::string formattedMessage = FormatString(format, vararg); + public: + void beginEvent(const std::wstring &eventName) + { + D3DPERF_BeginEvent(0, eventName.c_str()); + } + + void endEvent() + { + D3DPERF_EndEvent(); + } + + void setMarker(const std::wstring &markerName) + { + D3DPERF_SetMarker(0, markerName.c_str()); + } + + bool getStatus() + { + return !!D3DPERF_GetStatus(); + } +}; +#endif // ANGLE_ENABLE_D3D9 + +#if defined(ANGLE_ENABLE_D3D11) +class D3D11DebugAnnotationWrapper : public DebugAnnotationWrapper +{ + public: + + D3D11DebugAnnotationWrapper() + : mInitialized(false), + mD3d11Module(NULL), + mUserDefinedAnnotation(NULL) + { + // D3D11 devices can't be created during DllMain. + // We defer device creation until the object is actually used. + } + + ~D3D11DebugAnnotationWrapper() + { + if (mInitialized) + { + SafeRelease(mUserDefinedAnnotation); + FreeLibrary(mD3d11Module); + } + } + + virtual void beginEvent(const std::wstring &eventName) + { + initializeDevice(); + + mUserDefinedAnnotation->BeginEvent(eventName.c_str()); + } + + virtual void endEvent() + { + initializeDevice(); + + mUserDefinedAnnotation->EndEvent(); + } + + virtual void setMarker(const std::wstring &markerName) + { + initializeDevice(); + + mUserDefinedAnnotation->SetMarker(markerName.c_str()); + } + + virtual bool getStatus() + { + // ID3DUserDefinedAnnotation::GetStatus doesn't work with the Graphics Diagnostics tools in Visual Studio 2013. + +#if defined(_DEBUG) && defined(ANGLE_ENABLE_WINDOWS_STORE) + // In the Windows Store, we can use IDXGraphicsAnalysis. The call to GetDebugInterface1 only succeeds if the app is under capture. + // This should only be called in DEBUG mode. + // If an app links against DXGIGetDebugInterface1 in release mode then it will fail Windows Store ingestion checks. + IDXGraphicsAnalysis* graphicsAnalysis; + DXGIGetDebugInterface1(0, IID_PPV_ARGS(&graphicsAnalysis)); + bool underCapture = (graphicsAnalysis != NULL); + SafeRelease(graphicsAnalysis); + return underCapture; #endif -#if defined(ANGLE_ENABLE_PERF) - if (perfActive()) + // Otherwise, we have to return true here. + return true; + } + + protected: + + void initializeDevice() { - // The perf function only accepts wide strings, widen the ascii message - static std::wstring wideMessage; - if (wideMessage.capacity() < formattedMessage.length()) + if (!mInitialized) { - wideMessage.reserve(formattedMessage.size()); +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + mD3d11Module = LoadLibrary(TEXT("d3d11.dll")); + ASSERT(mD3d11Module); + + PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); + ASSERT(D3D11CreateDevice != NULL); +#endif // !ANGLE_ENABLE_WINDOWS_STORE + + ID3D11Device* device = NULL; + ID3D11DeviceContext* context = NULL; + + HRESULT hr = E_FAIL; + + // Create a D3D_DRIVER_TYPE_NULL device, which is much cheaper than other types of device. + hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_NULL, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &device, NULL, &context); + ASSERT(SUCCEEDED(hr)); + + hr = context->QueryInterface(__uuidof(mUserDefinedAnnotation), reinterpret_cast<void**>(&mUserDefinedAnnotation)); + ASSERT(SUCCEEDED(hr) && mUserDefinedAnnotation != NULL); + + SafeRelease(device); + SafeRelease(context); + + mInitialized = true; } + } + + bool mInitialized; + HMODULE mD3d11Module; + ID3DUserDefinedAnnotation* mUserDefinedAnnotation; +}; +#endif // ANGLE_ENABLE_D3D11 + +static DebugAnnotationWrapper* g_DebugAnnotationWrapper = NULL; + +void InitializeDebugAnnotations() +{ +#if defined(ANGLE_ENABLE_D3D9) + g_DebugAnnotationWrapper = new D3D9DebugAnnotationWrapper(); +#elif defined(ANGLE_ENABLE_D3D11) + // If the project uses D3D9 then we can use the D3D9 debug annotations, even with the D3D11 renderer. + // However, if D3D9 is unavailable (e.g. in Windows Store), then we use D3D11 debug annotations. + // The D3D11 debug annotations are methods on ID3DUserDefinedAnnotation, which is implemented by the DeviceContext. + // This doesn't have to be the same DeviceContext that the renderer uses, though. + g_DebugAnnotationWrapper = new D3D11DebugAnnotationWrapper(); +#endif +} + +void UninitializeDebugAnnotations() +{ + if (g_DebugAnnotationWrapper != NULL) + { + SafeDelete(g_DebugAnnotationWrapper); + } +} + +#endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS - wideMessage.assign(formattedMessage.begin(), formattedMessage.end()); +enum DebugTraceOutputType +{ + DebugTraceOutputTypeNone, + DebugTraceOutputTypeSetMarker, + DebugTraceOutputTypeBeginEvent +}; + +static void output(bool traceInDebugOnly, DebugTraceOutputType outputType, const char *format, va_list vararg) +{ +#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) + static std::vector<char> buffer(512); - perfFunc(0, wideMessage.c_str()); + if (perfActive()) + { + size_t len = FormatStringIntoVector(format, vararg, buffer); + std::wstring formattedWideMessage(buffer.begin(), buffer.begin() + len); + + switch (outputType) + { + case DebugTraceOutputTypeNone: + break; + case DebugTraceOutputTypeBeginEvent: + g_DebugAnnotationWrapper->beginEvent(formattedWideMessage); + break; + case DebugTraceOutputTypeSetMarker: + g_DebugAnnotationWrapper->setMarker(formattedWideMessage); + break; + } } -#endif // ANGLE_ENABLE_PERF +#endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS -#if defined(ANGLE_ENABLE_TRACE) +#if defined(ANGLE_ENABLE_DEBUG_TRACE) #if defined(NDEBUG) - if (traceFileDebugOnly) + if (traceInDebugOnly) { return; } #endif // NDEBUG + std::string formattedMessage = FormatString(format, vararg); static std::ofstream file(TRACE_OUTPUT_FILE, std::ofstream::app); if (file) @@ -60,25 +230,29 @@ static void output(bool traceFileDebugOnly, PerfOutputFunction perfFunc, const c file.flush(); } -#endif // ANGLE_ENABLE_TRACE +#if defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER) + OutputDebugStringA(formattedMessage.c_str()); +#endif // ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER + +#endif // ANGLE_ENABLE_DEBUG_TRACE } -void trace(bool traceFileDebugOnly, const char *format, ...) +void trace(bool traceInDebugOnly, const char *format, ...) { va_list vararg; va_start(vararg, format); -#if defined(ANGLE_ENABLE_PERF) - output(traceFileDebugOnly, D3DPERF_SetMarker, format, vararg); +#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) + output(traceInDebugOnly, DebugTraceOutputTypeSetMarker, format, vararg); #else - output(traceFileDebugOnly, NULL, format, vararg); + output(traceInDebugOnly, DebugTraceOutputTypeNone, format, vararg); #endif va_end(vararg); } bool perfActive() { -#if defined(ANGLE_ENABLE_PERF) - static bool active = D3DPERF_GetStatus() != 0; +#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) + static bool active = g_DebugAnnotationWrapper->getStatus(); return active; #else return false; @@ -87,26 +261,28 @@ bool perfActive() ScopedPerfEventHelper::ScopedPerfEventHelper(const char* format, ...) { -#if defined(ANGLE_ENABLE_PERF) -#if !defined(ANGLE_ENABLE_TRACE) +#if !defined(ANGLE_ENABLE_DEBUG_TRACE) if (!perfActive()) { return; } -#endif // !ANGLE_ENABLE_TRACE +#endif // !ANGLE_ENABLE_DEBUG_TRACE va_list vararg; va_start(vararg, format); - output(true, reinterpret_cast<PerfOutputFunction>(D3DPERF_BeginEvent), format, vararg); +#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) + output(true, DebugTraceOutputTypeBeginEvent, format, vararg); +#else + output(true, DebugTraceOutputTypeNone, format, vararg); +#endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS va_end(vararg); -#endif // ANGLE_ENABLE_PERF } ScopedPerfEventHelper::~ScopedPerfEventHelper() { -#if defined(ANGLE_ENABLE_PERF) +#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) if (perfActive()) { - D3DPERF_EndEvent(); + g_DebugAnnotationWrapper->endEvent(); } #endif } diff --git a/src/3rdparty/angle/src/common/debug.h b/src/3rdparty/angle/src/common/debug.h index bf2bca8f24..c177f51314 100644 --- a/src/3rdparty/angle/src/common/debug.h +++ b/src/3rdparty/angle/src/common/debug.h @@ -20,8 +20,8 @@ namespace gl { - // Outputs text to the debugging log - void trace(bool traceFileDebugOnly, const char *format, ...); + // Outputs text to the debugging log, or the debugging window + void trace(bool traceInDebugOnly, const char *format, ...); // Returns whether D3DPERF is active. bool perfActive(); @@ -36,31 +36,34 @@ namespace gl private: DISALLOW_COPY_AND_ASSIGN(ScopedPerfEventHelper); }; + + void InitializeDebugAnnotations(); + void UninitializeDebugAnnotations(); } // A macro to output a trace of a function call and its arguments to the debugging log -#if defined(ANGLE_ENABLE_TRACE) || defined(ANGLE_ENABLE_PERF) +#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) #define TRACE(message, ...) gl::trace(true, "trace: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) #else #define TRACE(message, ...) (void(0)) #endif // A macro to output a function call and its arguments to the debugging log, to denote an item in need of fixing. -#if defined(ANGLE_ENABLE_TRACE) || defined(ANGLE_ENABLE_PERF) +#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) #define FIXME(message, ...) gl::trace(false, "fixme: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) #else #define FIXME(message, ...) (void(0)) #endif // A macro to output a function call and its arguments to the debugging log, in case of error. -#if defined(ANGLE_ENABLE_TRACE) || defined(ANGLE_ENABLE_PERF) +#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) #define ERR(message, ...) gl::trace(false, "err: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) #else #define ERR(message, ...) (void(0)) #endif // A macro to log a performance event around a scope. -#if defined(ANGLE_ENABLE_TRACE) || defined(ANGLE_ENABLE_PERF) +#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) #if defined(_MSC_VER) #define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper ## __LINE__("%s" message "\n", __FUNCTION__, __VA_ARGS__); #else @@ -83,7 +86,7 @@ namespace gl #define UNUSED_ASSERTION_VARIABLE(variable) ((void)variable) #endif -#ifndef ANGLE_ENABLE_TRACE +#ifndef ANGLE_ENABLE_DEBUG_TRACE #define UNUSED_TRACE_VARIABLE(variable) ((void)variable) #else #define UNUSED_TRACE_VARIABLE(variable) @@ -128,7 +131,7 @@ namespace gl #endif // A macro functioning as a compile-time assert to validate constant conditions -#if defined(_MSC_VER) && _MSC_VER >= 1600 +#if (defined(_MSC_VER) && _MSC_VER >= 1600) || (defined(__GNUC__) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3)) #define META_ASSERT_MSG(condition, msg) static_assert(condition, msg) #else #define META_ASSERT_CONCAT(a, b) a ## b diff --git a/src/3rdparty/angle/src/common/features.h b/src/3rdparty/angle/src/common/features.h new file mode 100644 index 0000000000..b49a0ee852 --- /dev/null +++ b/src/3rdparty/angle/src/common/features.h @@ -0,0 +1,35 @@ +// +// Copyright (c) 2014 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. +// + +#define ANGLE_DISABLED 0 +#define ANGLE_ENABLED 1 + +// Feature defaults + +// Direct3D9EX +// 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_D3D9EX=0" in your project file. +#if !defined(ANGLE_D3D9EX) +#define ANGLE_D3D9EX ANGLE_ENABLED +#endif + +// Vsync +// ENABLED allows Vsync to be configured at runtime +// DISABLED disallows Vsync +#if !defined(ANGLE_VSYNC) +#define ANGLE_VSYNC ANGLE_ENABLED +#endif + +// Program binary loading +#if !defined(ANGLE_PROGRAM_BINARY_LOAD) +#define ANGLE_PROGRAM_BINARY_LOAD ANGLE_ENABLED +#endif + +// Shader debug info +#if !defined(ANGLE_SHADER_DEBUG_INFO) +#define ANGLE_SHADER_DEBUG_INFO ANGLE_DISABLED +#endif diff --git a/src/3rdparty/angle/src/common/mathutil.h b/src/3rdparty/angle/src/common/mathutil.h index 52f2bc1c0e..a1717892fd 100644 --- a/src/3rdparty/angle/src/common/mathutil.h +++ b/src/3rdparty/angle/src/common/mathutil.h @@ -109,7 +109,7 @@ inline unsigned int unorm(float x) inline bool supportsSSE2() { -#ifdef ANGLE_PLATFORM_WINDOWS +#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(_M_ARM) static bool checked = false; static bool supports = false; @@ -118,7 +118,6 @@ inline bool supportsSSE2() return supports; } -#if defined(_M_IX86) || defined(_M_AMD64) // ARM doesn't provide __cpuid() int info[4]; __cpuid(info, 0); @@ -128,7 +127,6 @@ inline bool supportsSSE2() supports = (info[3] >> 26) & 1; } -#endif checked = true; diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h index b53394f337..5bf97f9184 100644 --- a/src/3rdparty/angle/src/common/platform.h +++ b/src/3rdparty/angle/src/common/platform.h @@ -11,9 +11,6 @@ #if defined(_WIN32) || defined(_WIN64) # define ANGLE_PLATFORM_WINDOWS 1 -# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) -# define ANGLE_PLATFORM_WINRT 1 -# endif #elif defined(__APPLE__) # define ANGLE_PLATFORM_APPLE 1 # define ANGLE_PLATFORM_POSIX 1 @@ -37,6 +34,9 @@ #endif #ifdef ANGLE_PLATFORM_WINDOWS +# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) +# define ANGLE_ENABLE_WINDOWS_STORE 1 +# endif # ifndef STRICT # define STRICT 1 # endif @@ -50,8 +50,9 @@ # include <windows.h> # include <intrin.h> -# if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_PERF) +# if defined(ANGLE_ENABLE_D3D9) # include <d3d9.h> +# include <dxgi.h> # if !defined(COMPILER_IMPLEMENTATION) # include <d3dcompiler.h> # endif @@ -62,13 +63,26 @@ # include <d3d10.h> # include <d3d11.h> # include <dxgi.h> -# if _MSC_VER >= 1700 +# if defined(_MSC_VER) && (_MSC_VER >= 1700) +# include <d3d11_1.h> # include <dxgi1_2.h> # endif # if !defined(COMPILER_IMPLEMENTATION) # include <d3dcompiler.h> # endif -# if defined(__MINGW32__) +# endif + +# if defined(ANGLE_ENABLE_WINDOWS_STORE) +# include <dxgi1_3.h> +# if defined(_DEBUG) +# if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) +# include <DXProgrammableCapture.h> +# endif +# include <dxgidebug.h> +# endif +# endif + +# if defined(__MINGW32__) // Missing defines on MinGW typedef enum D3D11_MAP_FLAG { D3D11_MAP_FLAG_DO_NOT_WAIT = 0x100000L @@ -78,8 +92,68 @@ typedef struct D3D11_QUERY_DATA_SO_STATISTICS UINT64 NumPrimitivesWritten; UINT64 PrimitivesStorageNeeded; } D3D11_QUERY_DATA_SO_STATISTICS; -# endif -# endif +typedef HRESULT (WINAPI *PFN_D3D11_CREATE_DEVICE)( + IDXGIAdapter *, D3D_DRIVER_TYPE, HMODULE, UINT, CONST D3D_FEATURE_LEVEL *, + UINT FeatureLevels, UINT, ID3D11Device **, D3D_FEATURE_LEVEL *, ID3D11DeviceContext **); +#define D3D11_MESSAGE_CATEGORY UINT +#define D3D11_MESSAGE_SEVERITY UINT +#define D3D11_MESSAGE_ID UINT +struct D3D11_MESSAGE; +typedef struct D3D11_INFO_QUEUE_FILTER_DESC +{ + UINT NumCategories; + D3D11_MESSAGE_CATEGORY *pCategoryList; + UINT NumSeverities; + D3D11_MESSAGE_SEVERITY *pSeverityList; + UINT NumIDs; + D3D11_MESSAGE_ID *pIDList; +} D3D11_INFO_QUEUE_FILTER_DESC; +typedef struct D3D11_INFO_QUEUE_FILTER +{ + D3D11_INFO_QUEUE_FILTER_DESC AllowList; + D3D11_INFO_QUEUE_FILTER_DESC DenyList; +} D3D11_INFO_QUEUE_FILTER; +static const IID IID_ID3D11InfoQueue = { 0x6543dbb6, 0x1b48, 0x42f5, 0xab, 0x82, 0xe9, 0x7e, 0xc7, 0x43, 0x26, 0xf6 }; +MIDL_INTERFACE("6543dbb6-1b48-42f5-ab82-e97ec74326f6") ID3D11InfoQueue : public IUnknown +{ +public: + virtual HRESULT __stdcall SetMessageCountLimit(UINT64) = 0; + virtual void __stdcall ClearStoredMessages() = 0; + virtual HRESULT __stdcall GetMessage(UINT64, D3D11_MESSAGE *, SIZE_T *) = 0; + virtual UINT64 __stdcall GetNumMessagesAllowedByStorageFilter() = 0; + virtual UINT64 __stdcall GetNumMessagesDeniedByStorageFilter() = 0; + virtual UINT64 __stdcall GetNumStoredMessages() = 0; + virtual UINT64 __stdcall GetNumStoredMessagesAllowedByRetrievalFilter() = 0; + virtual UINT64 __stdcall GetNumMessagesDiscardedByMessageCountLimit() = 0; + virtual UINT64 __stdcall GetMessageCountLimit() = 0; + virtual HRESULT __stdcall AddStorageFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0; + virtual HRESULT __stdcall GetStorageFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0; + virtual void __stdcall ClearStorageFilter() = 0; + virtual HRESULT __stdcall PushEmptyStorageFilter() = 0; + virtual HRESULT __stdcall PushCopyOfStorageFilter() = 0; + virtual HRESULT __stdcall PushStorageFilter(D3D11_INFO_QUEUE_FILTER *) = 0; + virtual void __stdcall PopStorageFilter() = 0; + virtual UINT __stdcall GetStorageFilterStackSize() = 0; + virtual HRESULT __stdcall AddRetrievalFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0; + virtual HRESULT __stdcall GetRetrievalFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0; + virtual void __stdcall ClearRetrievalFilter() = 0; + virtual HRESULT __stdcall PushEmptyRetrievalFilter() = 0; + virtual HRESULT __stdcall PushCopyOfRetrievalFilter() = 0; + virtual HRESULT __stdcall PushRetrievalFilter(D3D11_INFO_QUEUE_FILTER *) = 0; + virtual void __stdcall PopRetrievalFilter() = 0; + virtual UINT __stdcall GetRetrievalFilterStackSize() = 0; + virtual HRESULT __stdcall AddMessage(D3D11_MESSAGE_CATEGORY, D3D11_MESSAGE_SEVERITY, D3D11_MESSAGE_ID, LPCSTR) = 0; + virtual HRESULT __stdcall AddApplicationMessage(D3D11_MESSAGE_SEVERITY, LPCSTR) = 0; + virtual HRESULT __stdcall SetBreakOnCategory(D3D11_MESSAGE_CATEGORY, BOOL) = 0; + virtual HRESULT __stdcall SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY, BOOL) = 0; + virtual HRESULT __stdcall SetBreakOnID(D3D11_MESSAGE_ID, BOOL) = 0; + virtual BOOL __stdcall GetBreakOnCategory(D3D11_MESSAGE_CATEGORY) = 0; + virtual BOOL __stdcall GetBreakOnSeverity(D3D11_MESSAGE_SEVERITY) = 0; + virtual BOOL __stdcall GetBreakOnID(D3D11_MESSAGE_ID) = 0; + virtual void __stdcall SetMuteDebugOutput(BOOL) = 0; + virtual BOOL __stdcall GetMuteDebugOutput() = 0; +}; +#endif // __MINGW32__ # undef near # undef far diff --git a/src/3rdparty/angle/src/common/tls.cpp b/src/3rdparty/angle/src/common/tls.cpp index c46fab5303..cb1b32d325 100644 --- a/src/3rdparty/angle/src/common/tls.cpp +++ b/src/3rdparty/angle/src/common/tls.cpp @@ -10,29 +10,50 @@ #include <assert.h> -#if defined(ANGLE_PLATFORM_WINRT) +#ifdef ANGLE_ENABLE_WINDOWS_STORE #include <vector> -std::vector<void *> *tls = nullptr; -std::vector<TLSIndex> *freeIndices = nullptr; +#include <set> +#include <map> +#include <mutex> + +#include <wrl/client.h> +#include <wrl/async.h> +#include <Windows.System.Threading.h> + +using namespace std; +using namespace Windows::Foundation; +using namespace ABI::Windows::System::Threading; + +// Thread local storage for Windows Store support +typedef vector<void*> ThreadLocalData; + +static __declspec(thread) ThreadLocalData* currentThreadData = nullptr; +static set<ThreadLocalData*> allThreadData; +static DWORD nextTlsIndex = 0; +static vector<DWORD> freeTlsIndices; + #endif TLSIndex CreateTLSIndex() { TLSIndex index; -#if defined(ANGLE_PLATFORM_WINRT) - if (!tls) - tls = new std::vector<void *>; - if (freeIndices && !freeIndices->empty()) { - index = freeIndices->back(); - freeIndices->pop_back(); - return index; - } else { - tls->push_back(nullptr); - return tls->size() - 1; +#ifdef ANGLE_PLATFORM_WINDOWS +#ifdef ANGLE_ENABLE_WINDOWS_STORE + if (!freeTlsIndices.empty()) + { + DWORD result = freeTlsIndices.back(); + freeTlsIndices.pop_back(); + index = result; } -#elif defined(ANGLE_PLATFORM_WINDOWS) + else + { + index = nextTlsIndex++; + } +#else index = TlsAlloc(); +#endif + #elif defined(ANGLE_PLATFORM_POSIX) // Create global pool key if ((pthread_key_create(&index, NULL)) != 0) @@ -53,13 +74,23 @@ bool DestroyTLSIndex(TLSIndex index) return false; } -#if defined(ANGLE_PLATFORM_WINRT) - if (!freeIndices) - freeIndices = new std::vector<TLSIndex>; - freeIndices->push_back(index); +#ifdef ANGLE_PLATFORM_WINDOWS +#ifdef ANGLE_ENABLE_WINDOWS_STORE + assert(index < nextTlsIndex); + assert(find(freeTlsIndices.begin(), freeTlsIndices.end(), index) == freeTlsIndices.end()); + + freeTlsIndices.push_back(index); + for (auto threadData : allThreadData) + { + if (threadData->size() > index) + { + threadData->at(index) = nullptr; + } + } return true; -#elif ANGLE_PLATFORM_WINDOWS +#else return (TlsFree(index) == TRUE); +#endif #elif defined(ANGLE_PLATFORM_POSIX) return (pthread_key_delete(index) == 0); #endif @@ -73,11 +104,25 @@ bool SetTLSValue(TLSIndex index, void *value) return false; } -#if defined(ANGLE_PLATFORM_WINRT) - tls->at(index) = value; +#ifdef ANGLE_PLATFORM_WINDOWS +#ifdef ANGLE_ENABLE_WINDOWS_STORE + ThreadLocalData* threadData = currentThreadData; + if (!threadData) + { + threadData = new ThreadLocalData(index + 1, nullptr); + allThreadData.insert(threadData); + currentThreadData = threadData; + } + else if (threadData->size() <= index) + { + threadData->resize(index + 1, nullptr); + } + + threadData->at(index) = value; return true; -#elif defined(ANGLE_PLATFORM_WINDOWS) +#else return (TlsSetValue(index, value) == TRUE); +#endif #elif defined(ANGLE_PLATFORM_POSIX) return (pthread_setspecific(index, value) == 0); #endif @@ -85,18 +130,26 @@ bool SetTLSValue(TLSIndex index, void *value) void *GetTLSValue(TLSIndex index) { -#if !defined(ANGLE_PLATFORM_WINRT) // Valid on WinRT, as Alloc handles the index creation assert(index != TLS_INVALID_INDEX && "GetTLSValue(): Invalid TLS Index"); -#endif if (index == TLS_INVALID_INDEX) { return NULL; } -#if defined(ANGLE_PLATFORM_WINRT) - return tls->at(index); -#elif defined(ANGLE_PLATFORM_WINDOWS) +#ifdef ANGLE_PLATFORM_WINDOWS +#ifdef ANGLE_ENABLE_WINDOWS_STORE + ThreadLocalData* threadData = currentThreadData; + if (threadData && threadData->size() > index) + { + return threadData->at(index); + } + else + { + return nullptr; + } +#else return TlsGetValue(index); +#endif #elif defined(ANGLE_PLATFORM_POSIX) return pthread_getspecific(index); #endif diff --git a/src/3rdparty/angle/src/common/tls.h b/src/3rdparty/angle/src/common/tls.h index c40ae1a061..8a06e92d1a 100644 --- a/src/3rdparty/angle/src/common/tls.h +++ b/src/3rdparty/angle/src/common/tls.h @@ -11,11 +11,15 @@ #include "common/platform.h" -#if defined(ANGLE_PLATFORM_WINRT) - typedef size_t TLSIndex; -# define TLS_OUT_OF_INDEXES (static_cast<TLSIndex>(-1)) -# define TLS_INVALID_INDEX TLS_OUT_OF_INDEXES -#elif defined(ANGLE_PLATFORM_WINDOWS) +#ifdef ANGLE_PLATFORM_WINDOWS + +// TLS does not exist for Windows Store and needs to be emulated +# ifdef ANGLE_ENABLE_WINDOWS_STORE +# define TLS_OUT_OF_INDEXES -1 +# ifndef CREATE_SUSPENDED +# define CREATE_SUSPENDED 0x00000004 +# endif +# endif typedef DWORD TLSIndex; # define TLS_INVALID_INDEX (TLS_OUT_OF_INDEXES) #elif defined(ANGLE_PLATFORM_POSIX) @@ -28,6 +32,9 @@ # error Unsupported platform. #endif +// TODO(kbr): for POSIX platforms this will have to be changed to take +// in a destructor function pointer, to allow the thread-local storage +// to be properly deallocated upon thread exit. TLSIndex CreateTLSIndex(); bool DestroyTLSIndex(TLSIndex index); diff --git a/src/3rdparty/angle/src/common/utilities.cpp b/src/3rdparty/angle/src/common/utilities.cpp index 4b8e325d22..9d797a6612 100644 --- a/src/3rdparty/angle/src/common/utilities.cpp +++ b/src/3rdparty/angle/src/common/utilities.cpp @@ -9,17 +9,16 @@ #include "common/utilities.h" #include "common/mathutil.h" #include "common/platform.h" -#if defined(ANGLE_PLATFORM_WINRT) -# include <locale> -# include <codecvt> -# include <wrl.h> -# include <windows.storage.h> - using namespace Microsoft::WRL; - using namespace ABI::Windows::Storage; -#endif #include <set> +#if defined(ANGLE_ENABLE_WINDOWS_STORE) +# include <wrl.h> +# include <wrl/wrappers/corewrappers.h> +# include <windows.applicationmodel.core.h> +# include <windows.graphics.display.h> +#endif + namespace gl { @@ -447,50 +446,10 @@ int VariableSortOrder(GLenum type) } +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) std::string getTempPath() { -#if defined(ANGLE_PLATFORM_WINRT) - static std::string path; - - while (path.empty()) - { - ComPtr<IApplicationDataStatics> factory; - Wrappers::HStringReference classId(RuntimeClass_Windows_Storage_ApplicationData); - HRESULT result = RoGetActivationFactory(classId.Get(), IID_PPV_ARGS(&factory)); - if (FAILED(result)) - break; - - ComPtr<IApplicationData> applicationData; - result = factory->get_Current(&applicationData); - if (FAILED(result)) - break; - - ComPtr<IStorageFolder> storageFolder; - result = applicationData->get_LocalFolder(&storageFolder); - if (FAILED(result)) - break; - - ComPtr<IStorageItem> localFolder; - result = storageFolder.As(&localFolder); - if (FAILED(result)) - break; - - HSTRING localFolderPath; - result = localFolder->get_Path(&localFolderPath); - if (FAILED(result)) - break; - - std::wstring_convert< std::codecvt_utf8<wchar_t> > converter; - path = converter.to_bytes(WindowsGetStringRawBuffer(localFolderPath, NULL)); - if (path.empty()) - { - UNREACHABLE(); - break; - } - } - - return path; -#elif defined(ANGLE_PLATFORM_WINDOWS) +#ifdef ANGLE_PLATFORM_WINDOWS char path[MAX_PATH]; DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path); if (pathLen == 0) @@ -525,3 +484,33 @@ void writeFile(const char* path, const void* content, size_t size) fwrite(content, sizeof(char), size, file); fclose(file); } +#endif // !ANGLE_ENABLE_WINDOWS_STORE + +#if defined(ANGLE_ENABLE_WINDOWS_STORE) + +void Sleep(unsigned long dwMilliseconds) +{ + static HANDLE singletonEvent = nullptr; + HANDLE sleepEvent = singletonEvent; + if (!sleepEvent) + { + sleepEvent = CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS); + + if (!sleepEvent) + return; + + HANDLE previousEvent = InterlockedCompareExchangePointerRelease(&singletonEvent, sleepEvent, nullptr); + + if (previousEvent) + { + // Back out if multiple threads try to demand create at the same time. + CloseHandle(sleepEvent); + sleepEvent = previousEvent; + } + } + + // Emulate sleep by waiting with timeout on an event that is never signalled. + WaitForSingleObjectEx(sleepEvent, dwMilliseconds, false); +} + +#endif // ANGLE_ENABLE_WINDOWS_STORE diff --git a/src/3rdparty/angle/src/common/utilities.h b/src/3rdparty/angle/src/common/utilities.h index a823184ecd..2cf6bed176 100644 --- a/src/3rdparty/angle/src/common/utilities.h +++ b/src/3rdparty/angle/src/common/utilities.h @@ -46,7 +46,13 @@ template <typename outT> outT uiround(GLfloat value) { return static_cast<outT>( } +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) std::string getTempPath(); void writeFile(const char* path, const void* data, size_t size); +#endif + +#if defined(ANGLE_ENABLE_WINDOWS_STORE) +void Sleep(_In_ unsigned long dwMilliseconds); +#endif #endif // LIBGLESV2_UTILITIES_H diff --git a/src/3rdparty/angle/src/common/win32/NativeWindow.cpp b/src/3rdparty/angle/src/common/win32/NativeWindow.cpp new file mode 100644 index 0000000000..46082a2e28 --- /dev/null +++ b/src/3rdparty/angle/src/common/win32/NativeWindow.cpp @@ -0,0 +1,66 @@ +// +// Copyright (c) 2014 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. +// + +// NativeWindow.cpp: Handler for managing HWND native window types. + +#include "common/NativeWindow.h" +#include "common/debug.h" + +namespace rx +{ +bool IsValidEGLNativeWindowType(EGLNativeWindowType window) +{ + return (IsWindow(window) == TRUE); +} + +NativeWindow::NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display) : mWindow(window), mDisplay(display) +{ +} + +bool NativeWindow::initialize() +{ + return true; +} + +bool NativeWindow::getClientRect(LPRECT rect) +{ + return GetClientRect(mWindow, rect) == TRUE; +} + +bool NativeWindow::isIconic() +{ + return IsIconic(mWindow) == TRUE; +} + +HRESULT NativeWindow::createSwapChain(NativeWindow::Device* device, DXGIFactory* factory, + DXGI_FORMAT format, unsigned int width, unsigned int height, + DXGISwapChain** swapChain) +{ + if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0) + { + return E_INVALIDARG; + } + + DXGI_SWAP_CHAIN_DESC swapChainDesc = { 0 }; + swapChainDesc.BufferCount = 1; + swapChainDesc.BufferDesc.Format = format; + swapChainDesc.BufferDesc.Width = width; + swapChainDesc.BufferDesc.Height = height; + swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + swapChainDesc.BufferDesc.RefreshRate.Numerator = 0; + swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER; + swapChainDesc.Flags = 0; + swapChainDesc.OutputWindow = mWindow; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Windowed = TRUE; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + + return factory->CreateSwapChain(device, &swapChainDesc, swapChain); +} +} diff --git a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp new file mode 100644 index 0000000000..9b65c15625 --- /dev/null +++ b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp @@ -0,0 +1,200 @@ +// +// Copyright (c) 2014 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. +// + +// CoreWindowNativeWindow.cpp: NativeWindow for managing ICoreWindow native window types. + +#include <algorithm> +#include "common/winrt/CoreWindowNativeWindow.h" +using namespace ABI::Windows::Foundation::Collections; + +namespace rx +{ + +typedef ITypedEventHandler<ABI::Windows::UI::Core::CoreWindow *, ABI::Windows::UI::Core::WindowSizeChangedEventArgs *> SizeChangedHandler; + +CoreWindowNativeWindow::~CoreWindowNativeWindow() +{ + unregisterForSizeChangeEvents(); +} + +bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet) +{ + ComPtr<IPropertySet> props = propertySet; + ComPtr<IInspectable> win = window; + ComPtr<IInspectable> displayInformation = display; + SIZE swapChainSize = {}; + bool swapChainSizeSpecified = false; + HRESULT result = S_OK; + + // IPropertySet is an optional parameter and can be null. + // If one is specified, cache as an IMap and read the properties + // used for initial host initialization. + if (propertySet) + { + result = props.As(&mPropertyMap); + if (SUCCEEDED(result)) + { + // The EGLRenderSurfaceSizeProperty is optional and may be missing. The IPropertySet + // was prevalidated to contain the EGLNativeWindowType before being passed to + // this host. + result = GetOptionalSizePropertyValue(mPropertyMap, EGLRenderSurfaceSizeProperty, &swapChainSize, &swapChainSizeSpecified); + } + } + + if (SUCCEEDED(result)) + { + result = win.As(&mCoreWindow); + } + + if (SUCCEEDED(result)) + { + result = displayInformation.As(&mDisplayInformation); + } + + if (SUCCEEDED(result)) + { +#if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP + ComPtr<ABI::Windows::Graphics::Display::IDisplayInformation2> displayInformation2; + result = mDisplayInformation.As(&displayInformation2); + ASSERT(SUCCEEDED(result)); + + result = displayInformation2->get_RawPixelsPerViewPixel(&mScaleFactor); + ASSERT(SUCCEEDED(result)); +#else + ABI::Windows::Graphics::Display::ResolutionScale resolutionScale; + result = mDisplayInformation->get_ResolutionScale(&resolutionScale); + ASSERT(SUCCEEDED(result)); + + mScaleFactor = DOUBLE(resolutionScale) / 100.0; +#endif + } + + if (SUCCEEDED(result)) + { + // If a swapchain size is specfied, then the automatic resize + // behaviors implemented by the host should be disabled. The swapchain + // will be still be scaled when being rendered to fit the bounds + // of the host. + // Scaling of the swapchain output occurs automatically because if + // the scaling mode setting DXGI_SCALING_STRETCH on the swapchain. + if (swapChainSizeSpecified) + { + mClientRect = { 0, 0, swapChainSize.cx, swapChainSize.cy }; + mSupportsSwapChainResize = false; + } + else + { + ABI::Windows::Foundation::Rect rect; + HRESULT result = mCoreWindow->get_Bounds(&rect); + if (SUCCEEDED(result)) + { + LONG width = std::floor(rect.Width * mScaleFactor + 0.5); + LONG height = std::floor(rect.Height * mScaleFactor + 0.5); + mClientRect = { 0, 0, width, height }; + } + } + } + + if (SUCCEEDED(result)) + { + mNewClientRect = mClientRect; + mClientRectChanged = false; + return registerForSizeChangeEvents(); + } + + return false; +} + +bool CoreWindowNativeWindow::registerForSizeChangeEvents() +{ + HRESULT result = mCoreWindow->add_SizeChanged(Callback<SizeChangedHandler>(this, &CoreWindowNativeWindow::onSizeChanged).Get(), + &mSizeChangedEventToken); + + if (SUCCEEDED(result)) + { + return true; + } + + return false; +} + +void CoreWindowNativeWindow::unregisterForSizeChangeEvents() +{ + if (mCoreWindow) + { + (void)mCoreWindow->remove_SizeChanged(mSizeChangedEventToken); + } + mSizeChangedEventToken.value = 0; +} + +HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) +{ + if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0) + { + return E_INVALIDARG; + } + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 }; + swapChainDesc.Width = width; + swapChainDesc.Height = height; + swapChainDesc.Format = format; + swapChainDesc.Stereo = FALSE; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER; + swapChainDesc.BufferCount = 2; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + + *swapChain = nullptr; + + ComPtr<IDXGISwapChain1> newSwapChain; + HRESULT result = factory->CreateSwapChainForCoreWindow(device, mCoreWindow.Get(), &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf()); + if (SUCCEEDED(result)) + { + +#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) // This block is disabled for Qt applications, as the resize events are expected + // Test if swapchain supports resize. On Windows Phone devices, this will return DXGI_ERROR_UNSUPPORTED. On + // other devices DXGI_ERROR_INVALID_CALL should be returned because the combination of flags passed + // (DXGI_SWAP_CHAIN_FLAG_NONPREROTATED | DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE) are invalid flag combinations. + if (newSwapChain->ResizeBuffers(swapChainDesc.BufferCount, swapChainDesc.Width, swapChainDesc.Height, swapChainDesc.Format, DXGI_SWAP_CHAIN_FLAG_NONPREROTATED | DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE) == DXGI_ERROR_UNSUPPORTED) + { + mSupportsSwapChainResize = false; + } +#endif // (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + + result = newSwapChain.CopyTo(swapChain); + } + + if (SUCCEEDED(result)) + { + // If automatic swapchain resize behaviors have been disabled, then + // unregister for the resize change events. + if (mSupportsSwapChainResize == false) + { + unregisterForSizeChangeEvents(); + } + } + + return result; +} + +// Basically, this shouldn't be used on Phone +HRESULT CoreWindowNativeWindow::onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *e) +{ + ABI::Windows::Foundation::Size size; + if (SUCCEEDED(e->get_Size(&size))) + { + SIZE windowSizeInPixels = { + std::floor(size.Width * mScaleFactor + 0.5), + std::floor(size.Height * mScaleFactor + 0.5) + }; + setNewClientSize(windowSizeInPixels); + } + + return S_OK; +} +} diff --git a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h new file mode 100644 index 0000000000..1c5512417d --- /dev/null +++ b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h @@ -0,0 +1,39 @@ +// +// Copyright (c) 2014 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. +// + +// CoreWindowNativeWindow.h: NativeWindow for managing ICoreWindow native window types. + +#ifndef COMMON_WINRT_COREWINDOWNATIVEWINDOW_H_ +#define COMMON_WINRT_COREWINDOWNATIVEWINDOW_H_ + +#include "common/winrt/InspectableNativeWindow.h" +#include <memory> +#include <windows.graphics.display.h> + +namespace rx +{ + +class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this<CoreWindowNativeWindow> +{ + public: + ~CoreWindowNativeWindow(); + + bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet); + bool registerForSizeChangeEvents(); + void unregisterForSizeChangeEvents(); + HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain); + + private: + HRESULT onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *); + + ComPtr<ABI::Windows::UI::Core::ICoreWindow> mCoreWindow; + ComPtr<ABI::Windows::Graphics::Display::IDisplayInformation> mDisplayInformation; + ComPtr<IMap<HSTRING, IInspectable*>> mPropertyMap; +}; + +} + +#endif // COMMON_WINRT_COREWINDOWNATIVEWINDOW_H_ diff --git a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp new file mode 100644 index 0000000000..0589f6dce5 --- /dev/null +++ b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp @@ -0,0 +1,274 @@ +// +// Copyright (c) 2014 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. +// + +// InspectableNativeWindow.cpp: NativeWindow base class for managing IInspectable native window types. + +#include "common/winrt/CoreWindowNativeWindow.h" +#include "common/winrt/SwapChainPanelNativeWindow.h" + +namespace rx +{ +NativeWindow::NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display) + : mWindow(window), mDisplay(display) +{ +} + +bool NativeWindow::initialize() +{ + // If the native window type is a IPropertySet, extract the + // EGLNativeWindowType (IInspectable) and initialize the + // proper host with this IPropertySet. + ComPtr<ABI::Windows::Foundation::Collections::IPropertySet> propertySet; + ComPtr<IInspectable> eglNativeWindow; + if (IsEGLConfiguredPropertySet(mWindow, &propertySet, &eglNativeWindow)) + { + // A property set was found and the EGLNativeWindowType was + // retrieved. The mWindow member of the host to must be updated + // to use the EGLNativeWindowType specified in the property set. + // mWindow is treated as a raw pointer not an AddRef'd interface, so + // the old mWindow does not need a Release() before this assignment. + mWindow = eglNativeWindow.Get(); + } + + ComPtr<ABI::Windows::UI::Core::ICoreWindow> coreWindow; + ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> swapChainPanel; + if (IsCoreWindow(mWindow, &coreWindow)) + { + mImpl = std::make_shared<CoreWindowNativeWindow>(); + if (mImpl) + { + return mImpl->initialize(mWindow, mDisplay, propertySet.Get()); + } + } + else if (IsSwapChainPanel(mWindow, &swapChainPanel)) + { + mImpl = std::make_shared<SwapChainPanelNativeWindow>(); + if (mImpl) + { + return mImpl->initialize(mWindow, mDisplay, propertySet.Get()); + } + } + else + { + ERR("Invalid IInspectable EGLNativeWindowType detected. Valid IInspectables include ICoreWindow, ISwapChainPanel and IPropertySet"); + } + + return false; +} + +bool NativeWindow::getClientRect(RECT *rect) +{ + if (mImpl) + { + return mImpl->getClientRect(rect); + } + + return false; +} + +bool NativeWindow::isIconic() +{ + return false; +} + +HRESULT NativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) +{ + if (mImpl) + { + return mImpl->createSwapChain(device, factory, format, width, height, swapChain); + } + + return E_UNEXPECTED; +} + +bool IsCoreWindow(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Core::ICoreWindow> *coreWindow) +{ + if (!window) + { + return false; + } + + ComPtr<IInspectable> win = window; + ComPtr<ABI::Windows::UI::Core::ICoreWindow> coreWin; + if (SUCCEEDED(win.As(&coreWin))) + { + if (coreWindow != nullptr) + { + *coreWindow = coreWin.Detach(); + } + return true; + } + + return false; +} + +bool IsSwapChainPanel(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> *swapChainPanel) +{ + if (!window) + { + return false; + } + + ComPtr<IInspectable> win = window; + ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> panel; + if (SUCCEEDED(win.As(&panel))) + { + if (swapChainPanel != nullptr) + { + *swapChainPanel = panel.Detach(); + } + return true; + } + + return false; +} + +bool IsEGLConfiguredPropertySet(EGLNativeWindowType window, ABI::Windows::Foundation::Collections::IPropertySet **propertySet, IInspectable **eglNativeWindow) +{ + if (!window) + { + return false; + } + + ComPtr<IInspectable> props = window; + ComPtr<IPropertySet> propSet; + ComPtr<IInspectable> nativeWindow; + ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>> propMap; + boolean hasEglNativeWindowPropertyKey = false; + + HRESULT result = props.As(&propSet); + if (SUCCEEDED(result)) + { + result = propSet.As(&propMap); + } + + // Look for the presence of the EGLNativeWindowType in the property set + if (SUCCEEDED(result)) + { + result = propMap->HasKey(HStringReference(EGLNativeWindowTypeProperty).Get(), &hasEglNativeWindowPropertyKey); + } + + // If the IPropertySet does not contain the required EglNativeWindowType key, the property set is + // considered invalid. + if (SUCCEEDED(result) && !hasEglNativeWindowPropertyKey) + { + ERR("Could not find EGLNativeWindowTypeProperty in IPropertySet. Valid EGLNativeWindowTypeProperty values include ICoreWindow"); + return false; + } + + // The EglNativeWindowType property exists, so retreive the IInspectable that represents the EGLNativeWindowType + if (SUCCEEDED(result) && hasEglNativeWindowPropertyKey) + { + result = propMap->Lookup(HStringReference(EGLNativeWindowTypeProperty).Get(), &nativeWindow); + } + + if (SUCCEEDED(result)) + { + if (propertySet != nullptr) + { + result = propSet.CopyTo(propertySet); + } + } + + if (SUCCEEDED(result)) + { + if (eglNativeWindow != nullptr) + { + result = nativeWindow.CopyTo(eglNativeWindow); + } + } + + if (SUCCEEDED(result)) + { + return true; + } + + return false; +} + +// A Valid EGLNativeWindowType IInspectable can only be: +// +// ICoreWindow +// IPropertySet +// +// Anything else will be rejected as an invalid IInspectable. +bool IsValidEGLNativeWindowType(EGLNativeWindowType window) +{ + return IsCoreWindow(window) || IsSwapChainPanel(window) || IsEGLConfiguredPropertySet(window); +} + +// Attempts to read an optional SIZE property value that is assumed to be in the form of +// an ABI::Windows::Foundation::Size. This function validates the Size value before returning +// it to the caller. +// +// Possible return values are: +// S_OK, valueExists == true - optional SIZE value was successfully retrieved and validated +// S_OK, valueExists == false - optional SIZE value was not found +// E_INVALIDARG, valueExists = false - optional SIZE value was malformed in the property set. +// * Incorrect property type ( must be PropertyType_Size) +// * Invalid property value (width/height must be > 0) +// Additional errors may be returned from IMap or IPropertyValue +// +HRESULT GetOptionalSizePropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>>& propertyMap, const wchar_t *propertyName, SIZE *value, bool *valueExists) +{ + if (!propertyMap || !propertyName || !value || !valueExists) + { + return false; + } + + // Assume that the value does not exist + *valueExists = false; + *value = { 0, 0 }; + + ComPtr<ABI::Windows::Foundation::IPropertyValue> propertyValue; + ABI::Windows::Foundation::PropertyType propertyType = ABI::Windows::Foundation::PropertyType::PropertyType_Empty; + Size sizeValue = { 0, 0 }; + boolean hasKey = false; + + HRESULT result = propertyMap->HasKey(HStringReference(propertyName).Get(), &hasKey); + if (SUCCEEDED(result) && !hasKey) + { + // Value does not exist, so return S_OK and set the exists parameter to false to indicate + // that a the optional property does not exist. + *valueExists = false; + return S_OK; + } + + if (SUCCEEDED(result)) + { + result = propertyMap->Lookup(HStringReference(propertyName).Get(), &propertyValue); + } + + if (SUCCEEDED(result)) + { + result = propertyValue->get_Type(&propertyType); + } + + // Check if the expected Size property is of PropertyType_Size type. + if (SUCCEEDED(result) && propertyType == ABI::Windows::Foundation::PropertyType::PropertyType_Size) + { + if (SUCCEEDED(propertyValue->GetSize(&sizeValue)) && (sizeValue.Width > 0 && sizeValue.Height > 0)) + { + // A valid property value exists + *value = { static_cast<long>(sizeValue.Width), static_cast<long>(sizeValue.Height) }; + *valueExists = true; + result = S_OK; + } + else + { + // An invalid Size property was detected. Width/Height values must > 0 + result = E_INVALIDARG; + } + } + else + { + // An invalid property type was detected. Size property must be of PropertyType_Size + result = E_INVALIDARG; + } + + return result; +} +} diff --git a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h new file mode 100644 index 0000000000..402941a788 --- /dev/null +++ b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h @@ -0,0 +1,91 @@ +// +// Copyright (c) 2014 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. +// + +// InspectableNativeWindow.h: Host specific implementation interface for +// managing IInspectable native window types. + +#ifndef COMMON_WINRT_INSPECTABLENATIVEWINDOW_H_ +#define COMMON_WINRT_INSPECTABLENATIVEWINDOW_H_ + +#include "common/platform.h" +#include "common/NativeWindow.h" +#include "angle_windowsstore.h" + +#include <windows.ui.xaml.h> +#include <windows.ui.xaml.media.dxinterop.h> + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; + +namespace rx +{ +class InspectableNativeWindow +{ + public: + InspectableNativeWindow() : + mSupportsSwapChainResize(true), + mRequiresSwapChainScaling(false), + mClientRectChanged(false), + mClientRect({0,0,0,0}), + mNewClientRect({0,0,0,0}), + mScaleFactor(1.0) + { + mSizeChangedEventToken.value = 0; + } + virtual ~InspectableNativeWindow(){} + + virtual bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet) = 0; + virtual HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) = 0; + virtual bool registerForSizeChangeEvents() = 0; + virtual void unregisterForSizeChangeEvents() = 0; + virtual HRESULT scaleSwapChain(const SIZE& newSize) { return S_OK; } + + bool getClientRect(RECT *rect) + { + if (mClientRectChanged && mSupportsSwapChainResize) + { + mClientRect = mNewClientRect; + mClientRectChanged = false; + } + + *rect = mClientRect; + + return true; + } + + void setNewClientSize(const SIZE &newSize) + { + if (mSupportsSwapChainResize && !mRequiresSwapChainScaling) + { + mNewClientRect = { 0, 0, newSize.cx, newSize.cy }; + mClientRectChanged = true; + } + + if (mRequiresSwapChainScaling) + { + scaleSwapChain(newSize); + } + } + +protected: + bool mSupportsSwapChainResize; + bool mRequiresSwapChainScaling; + RECT mClientRect; + RECT mNewClientRect; + bool mClientRectChanged; + DOUBLE mScaleFactor; + + EventRegistrationToken mSizeChangedEventToken; +}; + +bool IsCoreWindow(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Core::ICoreWindow> *coreWindow = nullptr); +bool IsSwapChainPanel(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> *swapChainPanel = nullptr); +bool IsEGLConfiguredPropertySet(EGLNativeWindowType window, ABI::Windows::Foundation::Collections::IPropertySet **propertySet = nullptr, IInspectable **inspectable = nullptr); +HRESULT GetOptionalSizePropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>>& propertyMap, const wchar_t *propertyName, SIZE *value, bool *valueExists); +} +#endif // COMMON_WINRT_INSPECTABLENATIVEWINDOW_H_ diff --git a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp new file mode 100644 index 0000000000..268dfbd8f0 --- /dev/null +++ b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp @@ -0,0 +1,226 @@ +// +// Copyright (c) 2014 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. +// + +// SwapChainPanelNativeWindow.cpp: NativeWindow for managing ISwapChainPanel native window types. + +#include "common/winrt/SwapChainPanelNativeWindow.h" +#include <algorithm> +#include <math.h> +using namespace ABI::Windows::Foundation::Collections; + +namespace rx +{ +SwapChainPanelNativeWindow::~SwapChainPanelNativeWindow() +{ + unregisterForSizeChangeEvents(); +} + +bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet) +{ + ComPtr<IPropertySet> props = propertySet; + ComPtr<IInspectable> win = window; + SIZE swapChainSize = {}; + bool swapChainSizeSpecified = false; + HRESULT result = S_OK; + + // IPropertySet is an optional parameter and can be null. + // If one is specified, cache as an IMap and read the properties + // used for initial host initialization. + if (propertySet) + { + result = props.As(&mPropertyMap); + if (SUCCEEDED(result)) + { + // The EGLRenderSurfaceSizeProperty is optional and may be missing. The IPropertySet + // was prevalidated to contain the EGLNativeWindowType before being passed to + // this host. + result = GetOptionalSizePropertyValue(mPropertyMap, EGLRenderSurfaceSizeProperty, &swapChainSize, &swapChainSizeSpecified); + } + } + + if (SUCCEEDED(result)) + { + result = win.As(&mSwapChainPanel); + } + + if (SUCCEEDED(result)) + { + // If a swapchain size is specfied, then the automatic resize + // behaviors implemented by the host should be disabled. The swapchain + // will be still be scaled when being rendered to fit the bounds + // of the host. + // Scaling of the swapchain output needs to be handled by the + // host for swapchain panels even though the scaling mode setting + // DXGI_SCALING_STRETCH is configured on the swapchain. + if (swapChainSizeSpecified) + { + mClientRect = { 0, 0, swapChainSize.cx, swapChainSize.cy }; + + // Enable host swapchain scaling + mRequiresSwapChainScaling = true; + } + else + { + result = GetSwapChainPanelSize(mSwapChainPanel, &mClientRect); + } + } + + if (SUCCEEDED(result)) + { + mNewClientRect = mClientRect; + mClientRectChanged = false; + return registerForSizeChangeEvents(); + } + + return false; +} + +bool SwapChainPanelNativeWindow::registerForSizeChangeEvents() +{ + ComPtr<ABI::Windows::UI::Xaml::ISizeChangedEventHandler> sizeChangedHandler; + ComPtr<ABI::Windows::UI::Xaml::IFrameworkElement> frameworkElement; + HRESULT result = Microsoft::WRL::MakeAndInitialize<SwapChainPanelSizeChangedHandler>(sizeChangedHandler.ReleaseAndGetAddressOf(), this->shared_from_this()); + + if (SUCCEEDED(result)) + { + result = mSwapChainPanel.As(&frameworkElement); + } + + if (SUCCEEDED(result)) + { + result = frameworkElement->add_SizeChanged(sizeChangedHandler.Get(), &mSizeChangedEventToken); + } + + if (SUCCEEDED(result)) + { + return true; + } + + return false; +} + +void SwapChainPanelNativeWindow::unregisterForSizeChangeEvents() +{ + ComPtr<ABI::Windows::UI::Xaml::IFrameworkElement> frameworkElement; + if (SUCCEEDED(mSwapChainPanel.As(&frameworkElement))) + { + (void)frameworkElement->remove_SizeChanged(mSizeChangedEventToken); + } + + mSizeChangedEventToken.value = 0; +} + +HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) +{ + if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0) + { + return E_INVALIDARG; + } + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 }; + swapChainDesc.Width = width; + swapChainDesc.Height = height; + swapChainDesc.Format = format; + swapChainDesc.Stereo = FALSE; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER; + swapChainDesc.BufferCount = 2; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + + *swapChain = nullptr; + + ComPtr<IDXGISwapChain1> newSwapChain; + ComPtr<ISwapChainPanelNative> swapChainPanelNative; + RECT currentPanelSize = {}; + + HRESULT result = factory->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf()); + + if (SUCCEEDED(result)) + { + result = mSwapChainPanel.As(&swapChainPanelNative); + } + + if (SUCCEEDED(result)) + { + result = swapChainPanelNative->SetSwapChain(newSwapChain.Get()); + } + + if (SUCCEEDED(result)) + { + // The swapchain panel host requires an instance of the swapchain set on the SwapChainPanel + // to perform the runtime-scale behavior. This swapchain is cached here because there are + // no methods for retreiving the currently configured on from ISwapChainPanelNative. + mSwapChain = newSwapChain; + result = newSwapChain.CopyTo(swapChain); + } + + // If the host is responsible for scaling the output of the swapchain, then + // scale it now before returning an instance to the caller. This is done by + // first reading the current size of the swapchain panel, then scaling + if (SUCCEEDED(result) && mRequiresSwapChainScaling) + { + result = GetSwapChainPanelSize(mSwapChainPanel, ¤tPanelSize); + } + + // Scale the swapchain to fit inside the contents of the panel. + if (SUCCEEDED(result) && mRequiresSwapChainScaling) + { + SIZE currentSize = { currentPanelSize.right, currentPanelSize.bottom }; + result = scaleSwapChain(currentSize); + } + + if (SUCCEEDED(result)) + { + // If automatic swapchain resize behaviors have been disabled, then + // unregister for the resize change events. + if (mSupportsSwapChainResize == false) + { + unregisterForSizeChangeEvents(); + } + } + + return result; +} + +HRESULT SwapChainPanelNativeWindow::scaleSwapChain(const SIZE &newSize) +{ + ABI::Windows::Foundation::Size renderScale = { (float)newSize.cx/(float)mClientRect.right, (float)newSize.cy/(float)mClientRect.bottom }; + // Setup a scale matrix for the swap chain + DXGI_MATRIX_3X2_F scaleMatrix = {}; + scaleMatrix._11 = renderScale.Width; + scaleMatrix._22 = renderScale.Height; + + ComPtr<IDXGISwapChain2> swapChain2; + HRESULT result = mSwapChain.As(&swapChain2); + if (SUCCEEDED(result)) + { + result = swapChain2->SetMatrixTransform(&scaleMatrix); + } + + return result; +} + +HRESULT GetSwapChainPanelSize(const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel, RECT *windowSize) +{ + ComPtr<ABI::Windows::UI::Xaml::IUIElement> uiElement; + ABI::Windows::Foundation::Size renderSize = { 0, 0 }; + HRESULT result = swapChainPanel.As(&uiElement); + if (SUCCEEDED(result)) + { + result = uiElement->get_RenderSize(&renderSize); + } + + if (SUCCEEDED(result)) + { + *windowSize = { 0, 0, lround(renderSize.Width), lround(renderSize.Height) }; + } + + return result; +} +} diff --git a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h new file mode 100644 index 0000000000..5bbf274e64 --- /dev/null +++ b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h @@ -0,0 +1,79 @@ +// +// Copyright (c) 2014 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. +// + +// SwapChainPanelNativeWindow.h: NativeWindow for managing ISwapChainPanel native window types. + +#ifndef COMMON_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_ +#define COMMON_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_ + +#include "common/winrt/InspectableNativeWindow.h" + +namespace rx +{ +class SwapChainPanelNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this<SwapChainPanelNativeWindow> +{ + public: + ~SwapChainPanelNativeWindow(); + + bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet); + bool registerForSizeChangeEvents(); + void unregisterForSizeChangeEvents(); + HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain); + HRESULT scaleSwapChain(const SIZE &newSize); + + private: + ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> mSwapChainPanel; + ComPtr<IMap<HSTRING, IInspectable*>> mPropertyMap; + ComPtr<DXGISwapChain> mSwapChain; +}; + +[uuid(8ACBD974-8187-4508-AD80-AEC77F93CF36)] +class SwapChainPanelSizeChangedHandler : + public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, ABI::Windows::UI::Xaml::ISizeChangedEventHandler> +{ + public: + SwapChainPanelSizeChangedHandler() { } + HRESULT RuntimeClassInitialize(std::shared_ptr<InspectableNativeWindow> host) + { + if (!host) + { + return E_INVALIDARG; + } + + mHost = host; + return S_OK; + } + + // ISizeChangedEventHandler + IFACEMETHOD(Invoke)(IInspectable *sender, ABI::Windows::UI::Xaml::ISizeChangedEventArgs *sizeChangedEventArgs) + { + std::shared_ptr<InspectableNativeWindow> host = mHost.lock(); + if (host) + { + // The size of the ISwapChainPanel control is returned in DIPs. + // We are keeping these in dips because the swapchain created for composition + // also uses dip units. This keeps dimensions, viewports, etc in the same unit. + // XAML Clients of the ISwapChainPanel are required to use dips to define their + // layout sizes as well. + ABI::Windows::Foundation::Size newSize; + HRESULT result = sizeChangedEventArgs->get_NewSize(&newSize); + if (SUCCEEDED(result)) + { + SIZE windowSize = { lround(newSize.Width), lround(newSize.Height) }; + host->setNewClientSize(windowSize); + } + } + + return S_OK; + } + + private: + std::weak_ptr<InspectableNativeWindow> mHost; +}; + +HRESULT GetSwapChainPanelSize(const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel, RECT *windowSize); +} +#endif // COMMON_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_ |