diff options
author | Andrew Knight <andrew.knight@intopalo.com> | 2015-04-08 17:04:36 +0300 |
---|---|---|
committer | Andrew Knight <qt@panimo.net> | 2015-04-09 10:31:12 +0000 |
commit | a218a252c4200cfe7048de81a46f7e48349084d5 (patch) | |
tree | c1a82865d97e610cd0abb3a1360408363b38205b /src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp | |
parent | 331ddacfca90c91c5b44484bf3c78e2aa5b85947 (diff) |
Upgrade ANGLE to 2.1~99f075dade7c
This aligns with Chromium branch 2356.
This version brings more complete OpenGL ES 3 support as well as various
bug fixes and performance improvements.
The following changes were made to earlier patches:
-0000-General-fixes-for-ANGLE-2.1
Removed. All changes are now handled elsewhere.
+0001-ANGLE-Improve-Windows-Phone-support
Consolidated remaining parts from 0009/0010.
+0002-ANGLE-Fix-compilation-with-MinGW
Remaining issues from patch 0016.
+0003-ANGLE-Fix-compilation-with-MSVC2010
Remaining issues from patch 0015.
+0004-ANGLE-Dynamically-load-D3D-compiler-from-list
Renamed from patch 0008.
+0005-ANGLE-Add-support-for-querying-platform-device
Renamed from patch 0013.
-0004-Make-it-possible-to-link-ANGLE-statically-for-single
Removed. Fixed by adding defines to project files.
-0008-ANGLE-Dynamically-load-D3D-compiler-from-a-list-or-t
Renamed to patch 0005.
-0009-ANGLE-Support-WinRT
Removed. Mostly fixed upstream; remaining parts in patch 0001.
-0010-ANGLE-Enable-D3D11-for-feature-level-9-cards
Removed. Mostly fixed upstream; remaining parts in patch 0001.
-0012-ANGLE-fix-semantic-index-lookup
Removed. Fixed upstream.
-0013-ANGLE-Add-support-for-querying-platform-device
Renamed to patch 0005.
-0014-Let-ANGLE-use-multithreaded-devices-if-necessary
Removed. No longer needed.
-0015-ANGLE-Fix-angle-d3d11-on-MSVC2010
Moved remaining parts to patch 0003.
-0016-ANGLE-Fix-compilation-with-MinGW-D3D11
Moved remaining parts to patch 0002.
-0017-ANGLE-Fix-compilation-with-D3D9
Removed. Fixed upstream.
-0018-ANGLE-Fix-releasing-textures-after-we-kill-D3D11
Removed. Fixed upstream.
-0019-ANGLE-Fix-handling-of-shader-source-with-fixed-lengt
Removed. Fixed upstream.
-0020-ANGLE-Do-not-use-std-strlen
Removed. Fixed upstream.
-0020-ANGLE-Fix-compilation-with-MSVC2013-Update4
Removed. Fixed upstream.
[ChangeLog][Third-party libraries] ANGLE was updated to Chromium branch
2356 (2.1~99f075dade7c).
Change-Id: I32ccbfe95e10986bd94be7191dfd53445ea09158
Task-number: QTBUG-44815
Task-number: QTBUG-37660
Task-number: QTBUG-44694
Task-number: QTBUG-42443
Reviewed-by: Andrew Knight <qt@panimo.net>
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@theqtcompany.com>
Diffstat (limited to 'src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp')
-rw-r--r-- | src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp | 396 |
1 files changed, 396 insertions, 0 deletions
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp new file mode 100644 index 0000000000..4fde295443 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp @@ -0,0 +1,396 @@ +// +// 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. +// + +// SurfaceD3D.cpp: D3D implementation of an EGL surface + +#include "libANGLE/renderer/d3d/SurfaceD3D.h" + +#include "libANGLE/Display.h" +#include "libANGLE/Surface.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/SwapChainD3D.h" + +#include <tchar.h> +#include <EGL/eglext.h> +#include <algorithm> + +namespace rx +{ + +SurfaceD3D *SurfaceD3D::createOffscreen(RendererD3D *renderer, egl::Display *display, const egl::Config *config, EGLClientBuffer shareHandle, + EGLint width, EGLint height) +{ + return new SurfaceD3D(renderer, display, config, width, height, EGL_TRUE, shareHandle, NULL); +} + +SurfaceD3D *SurfaceD3D::createFromWindow(RendererD3D *renderer, egl::Display *display, const egl::Config *config, EGLNativeWindowType window, + EGLint fixedSize, EGLint width, EGLint height) +{ + return new SurfaceD3D(renderer, display, config, width, height, fixedSize, static_cast<EGLClientBuffer>(0), window); +} + +SurfaceD3D::SurfaceD3D(RendererD3D *renderer, egl::Display *display, const egl::Config *config, EGLint width, EGLint height, EGLint fixedSize, + EGLClientBuffer shareHandle, EGLNativeWindowType window) + : SurfaceImpl(), + mRenderer(renderer), + mDisplay(display), + mFixedSize(fixedSize == EGL_TRUE), + mRenderTargetFormat(config->renderTargetFormat), + mDepthStencilFormat(config->depthStencilFormat), + mSwapChain(nullptr), + mSwapIntervalDirty(true), + mWindowSubclassed(false), + mNativeWindow(window), + mWidth(width), + mHeight(height), + mSwapInterval(1), + mShareHandle(reinterpret_cast<HANDLE*>(shareHandle)) +{ + subclassWindow(); +} + +SurfaceD3D::~SurfaceD3D() +{ + unsubclassWindow(); + releaseSwapChain(); +} + +void SurfaceD3D::releaseSwapChain() +{ + SafeDelete(mSwapChain); +} + +egl::Error SurfaceD3D::initialize() +{ + if (mNativeWindow.getNativeWindow()) + { + if (!mNativeWindow.initialize()) + { + return egl::Error(EGL_BAD_SURFACE); + } + } + + egl::Error error = resetSwapChain(); + if (error.isError()) + { + return error; + } + + return egl::Error(EGL_SUCCESS); +} + +egl::Error SurfaceD3D::bindTexImage(EGLint) +{ + return egl::Error(EGL_SUCCESS); +} + +egl::Error SurfaceD3D::releaseTexImage(EGLint) +{ + return egl::Error(EGL_SUCCESS); +} + +egl::Error SurfaceD3D::resetSwapChain() +{ + ASSERT(!mSwapChain); + + int width; + int height; + + if (!mFixedSize) + { + RECT windowRect; + if (!mNativeWindow.getClientRect(&windowRect)) + { + ASSERT(false); + + return egl::Error(EGL_BAD_SURFACE, "Could not retrieve the window dimensions"); + } + + width = windowRect.right - windowRect.left; + height = windowRect.bottom - windowRect.top; + } + else + { + // non-window surface - size is determined at creation + width = mWidth; + height = mHeight; + } + + mSwapChain = mRenderer->createSwapChain(mNativeWindow, mShareHandle, mRenderTargetFormat, mDepthStencilFormat); + if (!mSwapChain) + { + return egl::Error(EGL_BAD_ALLOC); + } + + egl::Error error = resetSwapChain(width, height); + if (error.isError()) + { + SafeDelete(mSwapChain); + return error; + } + + return egl::Error(EGL_SUCCESS); +} + +egl::Error SurfaceD3D::resizeSwapChain(int backbufferWidth, int backbufferHeight) +{ + ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0); + ASSERT(mSwapChain); + + EGLint status = mSwapChain->resize(std::max(1, backbufferWidth), std::max(1, backbufferHeight)); + + if (status == EGL_CONTEXT_LOST) + { + mDisplay->notifyDeviceLost(); + return egl::Error(status); + } + else if (status != EGL_SUCCESS) + { + return egl::Error(status); + } + + mWidth = backbufferWidth; + mHeight = backbufferHeight; + + return egl::Error(EGL_SUCCESS); +} + +egl::Error SurfaceD3D::resetSwapChain(int backbufferWidth, int backbufferHeight) +{ + ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0); + ASSERT(mSwapChain); + + EGLint status = mSwapChain->reset(std::max(1, backbufferWidth), std::max(1, backbufferHeight), mSwapInterval); + + if (status == EGL_CONTEXT_LOST) + { + mRenderer->notifyDeviceLost(); + return egl::Error(status); + } + else if (status != EGL_SUCCESS) + { + return egl::Error(status); + } + + mWidth = backbufferWidth; + mHeight = backbufferHeight; + mSwapIntervalDirty = false; + + return egl::Error(EGL_SUCCESS); +} + +egl::Error SurfaceD3D::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) +{ + if (!mSwapChain) + { + return egl::Error(EGL_SUCCESS); + } + + if (x + width > mWidth) + { + width = mWidth - x; + } + + if (y + height > mHeight) + { + height = mHeight - y; + } + + if (width == 0 || height == 0) + { + return egl::Error(EGL_SUCCESS); + } + + EGLint status = mSwapChain->swapRect(x, y, width, height); + + if (status == EGL_CONTEXT_LOST) + { + mRenderer->notifyDeviceLost(); + return egl::Error(status); + } + else if (status != EGL_SUCCESS) + { + return egl::Error(status); + } + + checkForOutOfDateSwapChain(); + + return egl::Error(EGL_SUCCESS); +} + +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) +#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) + { + SurfaceD3D* surf = reinterpret_cast<SurfaceD3D*>(GetProp(hwnd, kSurfaceProperty)); + if(surf) + { + surf->checkForOutOfDateSwapChain(); + } + } + WNDPROC prevWndFunc = reinterpret_cast<WNDPROC >(GetProp(hwnd, kParentWndProc)); + return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam); +} +#endif + +void SurfaceD3D::subclassWindow() +{ +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + HWND window = mNativeWindow.getNativeWindow(); + if (!window) + { + return; + } + + DWORD processId; + DWORD threadId = GetWindowThreadProcessId(window, &processId); + if (processId != GetCurrentProcessId() || threadId != GetCurrentThreadId()) + { + return; + } + + SetLastError(0); + LONG_PTR oldWndProc = SetWindowLongPtr(window, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(SurfaceWindowProc)); + if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS) + { + mWindowSubclassed = false; + return; + } + + SetProp(window, kSurfaceProperty, reinterpret_cast<HANDLE>(this)); + SetProp(window, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc)); + mWindowSubclassed = true; +#endif +} + +void SurfaceD3D::unsubclassWindow() +{ + if (!mWindowSubclassed) + { + return; + } + +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + HWND window = mNativeWindow.getNativeWindow(); + if (!window) + { + return; + } + + // un-subclass + LONG_PTR parentWndFunc = reinterpret_cast<LONG_PTR>(GetProp(window, kParentWndProc)); + + // Check the windowproc is still SurfaceWindowProc. + // If this assert fails, then it is likely the application has subclassed the + // hwnd as well and did not unsubclass before destroying its EGL context. The + // application should be modified to either subclass before initializing the + // EGL context, or to unsubclass before destroying the EGL context. + if(parentWndFunc) + { + LONG_PTR prevWndFunc = SetWindowLongPtr(window, GWLP_WNDPROC, parentWndFunc); + UNUSED_ASSERTION_VARIABLE(prevWndFunc); + ASSERT(prevWndFunc == reinterpret_cast<LONG_PTR>(SurfaceWindowProc)); + } + + RemoveProp(window, kSurfaceProperty); + RemoveProp(window, kParentWndProc); +#endif + mWindowSubclassed = false; +} + +bool SurfaceD3D::checkForOutOfDateSwapChain() +{ + RECT client; + int clientWidth = getWidth(); + int clientHeight = getHeight(); + bool sizeDirty = false; + if (!mFixedSize && !mNativeWindow.isIconic()) + { + // The window is automatically resized to 150x22 when it's minimized, but the swapchain shouldn't be resized + // because that's not a useful size to render to. + if (!mNativeWindow.getClientRect(&client)) + { + ASSERT(false); + return false; + } + + // Grow the buffer now, if the window has grown. We need to grow now to avoid losing information. + clientWidth = client.right - client.left; + clientHeight = client.bottom - client.top; + sizeDirty = clientWidth != getWidth() || clientHeight != getHeight(); + } + + bool wasDirty = (mSwapIntervalDirty || sizeDirty); + + if (mSwapIntervalDirty) + { + resetSwapChain(clientWidth, clientHeight); + } + else if (sizeDirty) + { + resizeSwapChain(clientWidth, clientHeight); + } + + return wasDirty; +} + +egl::Error SurfaceD3D::swap() +{ + return swapRect(0, 0, mWidth, mHeight); +} + +egl::Error SurfaceD3D::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) +{ + return swapRect(x, y, width, height); +} + +rx::SwapChainD3D *SurfaceD3D::getSwapChain() const +{ + return mSwapChain; +} + +void SurfaceD3D::setSwapInterval(EGLint interval) +{ + if (mSwapInterval == interval) + { + return; + } + + mSwapInterval = interval; + mSwapIntervalDirty = true; +} + +EGLint SurfaceD3D::getWidth() const +{ + return mWidth; +} + +EGLint SurfaceD3D::getHeight() const +{ + return mHeight; +} + +EGLint SurfaceD3D::isPostSubBufferSupported() const +{ + // post sub buffer is always possible on D3D surfaces + return EGL_TRUE; +} + +egl::Error SurfaceD3D::querySurfacePointerANGLE(EGLint attribute, void **value) +{ + ASSERT(attribute == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE || attribute == EGL_DEVICE_EXT); + if (attribute == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE) + *value = mSwapChain->getShareHandle(); + else if (attribute == EGL_DEVICE_EXT) + *value = mSwapChain->getDevice(); + return egl::Error(EGL_SUCCESS); +} + +} |