Add an EGL_ANGLE_surface_orientation extension.
BUG=angleproject:1262
Change-Id: Ifbb0f5302311a68a0c6f02baaea706cbb7055a52
Reviewed-on: https://chromium-review.googlesource.com/320011
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Tested-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/Caps.cpp b/src/libANGLE/Caps.cpp
index a7c7a0b..ca291a2 100644
--- a/src/libANGLE/Caps.cpp
+++ b/src/libANGLE/Caps.cpp
@@ -609,6 +609,7 @@
querySurfacePointer(false),
windowFixedSize(false),
keyedMutex(false),
+ surfaceOrientation(false),
postSubBuffer(false),
createContext(false),
deviceQuery(false),
@@ -636,6 +637,7 @@
InsertExtensionString("EGL_ANGLE_query_surface_pointer", querySurfacePointer, &extensionStrings);
InsertExtensionString("EGL_ANGLE_window_fixed_size", windowFixedSize, &extensionStrings);
InsertExtensionString("EGL_ANGLE_keyed_mutex", keyedMutex, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_surface_orientation", surfaceOrientation, &extensionStrings);
InsertExtensionString("EGL_NV_post_sub_buffer", postSubBuffer, &extensionStrings);
InsertExtensionString("EGL_KHR_create_context", createContext, &extensionStrings);
InsertExtensionString("EGL_EXT_device_query", deviceQuery, &extensionStrings);
diff --git a/src/libANGLE/Caps.h b/src/libANGLE/Caps.h
index 537f964..ecae714 100644
--- a/src/libANGLE/Caps.h
+++ b/src/libANGLE/Caps.h
@@ -427,6 +427,9 @@
// EGL_ANGLE_keyed_mutex
bool keyedMutex;
+ // EGL_ANGLE_surface_orientation
+ bool surfaceOrientation;
+
// EGL_NV_post_sub_buffer
bool postSubBuffer;
diff --git a/src/libANGLE/Config.cpp b/src/libANGLE/Config.cpp
index c558b31..d511df3 100644
--- a/src/libANGLE/Config.cpp
+++ b/src/libANGLE/Config.cpp
@@ -57,7 +57,8 @@
transparentType(EGL_NONE),
transparentRedValue(0),
transparentGreenValue(0),
- transparentBlueValue(0)
+ transparentBlueValue(0),
+ optimalOrientation(0)
{
}
@@ -251,6 +252,9 @@
case EGL_MAX_PBUFFER_WIDTH: match = config.maxPBufferWidth >= attributeValue; break;
case EGL_MAX_PBUFFER_HEIGHT: match = config.maxPBufferHeight >= attributeValue; break;
case EGL_MAX_PBUFFER_PIXELS: match = config.maxPBufferPixels >= attributeValue; break;
+ case EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE:
+ match = config.optimalOrientation == attributeValue;
+ break;
default: UNREACHABLE();
}
diff --git a/src/libANGLE/Config.h b/src/libANGLE/Config.h
index aed8aed..00f5673 100644
--- a/src/libANGLE/Config.h
+++ b/src/libANGLE/Config.h
@@ -64,6 +64,7 @@
EGLint transparentRedValue; // Transparent red value
EGLint transparentGreenValue; // Transparent green value
EGLint transparentBlueValue; // Transparent blue value
+ EGLint optimalOrientation; // Optimal window surface orientation
};
class ConfigSet
diff --git a/src/libANGLE/Display.cpp b/src/libANGLE/Display.cpp
index 5e71a90..439e433 100644
--- a/src/libANGLE/Display.cpp
+++ b/src/libANGLE/Display.cpp
@@ -483,6 +483,15 @@
case EGL_MAX_PBUFFER_WIDTH: *value = configuration->maxPBufferWidth; break;
case EGL_MAX_PBUFFER_HEIGHT: *value = configuration->maxPBufferHeight; break;
case EGL_MAX_PBUFFER_PIXELS: *value = configuration->maxPBufferPixels; break;
+
+ case EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE:
+ if (!getExtensions().surfaceOrientation)
+ {
+ return false;
+ }
+ *value = configuration->optimalOrientation;
+ break;
+
default:
return false;
}
diff --git a/src/libANGLE/Surface.cpp b/src/libANGLE/Surface.cpp
index e5c3aee..dc754ff 100644
--- a/src/libANGLE/Surface.cpp
+++ b/src/libANGLE/Surface.cpp
@@ -41,7 +41,9 @@
// FIXME: Determine actual pixel aspect ratio
mPixelAspectRatio(static_cast<EGLint>(1.0 * EGL_DISPLAY_SCALING)),
mRenderBuffer(EGL_BACK_BUFFER),
- mSwapBehavior(impl->getSwapBehavior())
+ mSwapBehavior(impl->getSwapBehavior()),
+ mOrientation(0),
+ mTexture()
{
mPostSubBufferRequested = (attributes.get(EGL_POST_SUB_BUFFER_SUPPORTED_NV, EGL_FALSE) == EGL_TRUE);
mFlexibleSurfaceCompatibilityRequested =
@@ -60,6 +62,8 @@
mTextureTarget = attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE);
}
+ mOrientation = attributes.get(EGL_SURFACE_ORIENTATION_ANGLE, 0);
+
mDefaultFramebuffer = createDefaultFramebuffer();
ASSERT(mDefaultFramebuffer != nullptr);
}
diff --git a/src/libANGLE/Surface.h b/src/libANGLE/Surface.h
index c7a3d78..813f2ef 100644
--- a/src/libANGLE/Surface.h
+++ b/src/libANGLE/Surface.h
@@ -82,6 +82,7 @@
{
return mFlexibleSurfaceCompatibilityRequested;
}
+ EGLint getOrientation() const { return mOrientation; }
private:
virtual ~Surface();
@@ -116,6 +117,8 @@
EGLenum mRenderBuffer; // Render buffer
EGLenum mSwapBehavior; // Buffer swap behavior
+ EGLint mOrientation;
+
BindingPointer<gl::Texture> mTexture;
};
diff --git a/src/libANGLE/renderer/d3d/DisplayD3D.cpp b/src/libANGLE/renderer/d3d/DisplayD3D.cpp
index 3aced4f..7c53c81 100644
--- a/src/libANGLE/renderer/d3d/DisplayD3D.cpp
+++ b/src/libANGLE/renderer/d3d/DisplayD3D.cpp
@@ -172,6 +172,7 @@
EGLint width = attribs.get(EGL_WIDTH, 0);
EGLint height = attribs.get(EGL_HEIGHT, 0);
EGLint fixedSize = attribs.get(EGL_FIXED_SIZE_ANGLE, EGL_FALSE);
+ EGLint orientation = attribs.get(EGL_SURFACE_ORIENTATION_ANGLE, 0);
if (!fixedSize)
{
@@ -179,8 +180,8 @@
height = -1;
}
- return SurfaceD3D::createFromWindow(
- mRenderer, mDisplay, configuration, window, fixedSize, width, height);
+ return SurfaceD3D::createFromWindow(mRenderer, mDisplay, configuration, window, fixedSize,
+ width, height, orientation);
}
SurfaceImpl *DisplayD3D::createPbufferSurface(const egl::Config *configuration,
diff --git a/src/libANGLE/renderer/d3d/RendererD3D.h b/src/libANGLE/renderer/d3d/RendererD3D.h
index f6c5be6..4a90fd1 100644
--- a/src/libANGLE/renderer/d3d/RendererD3D.h
+++ b/src/libANGLE/renderer/d3d/RendererD3D.h
@@ -143,7 +143,11 @@
// Direct3D Specific methods
virtual DeviceIdentifier getAdapterIdentifier() const = 0;
- virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0;
+ virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow,
+ HANDLE shareHandle,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat,
+ EGLint orientation) = 0;
virtual gl::Error generateSwizzle(gl::Texture *texture) = 0;
virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler) = 0;
diff --git a/src/libANGLE/renderer/d3d/SurfaceD3D.cpp b/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
index 613b9df..44c525b 100644
--- a/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
+++ b/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
@@ -24,13 +24,20 @@
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);
+ return new SurfaceD3D(renderer, display, config, width, height, EGL_TRUE, 0, shareHandle, NULL);
}
-SurfaceD3D *SurfaceD3D::createFromWindow(RendererD3D *renderer, egl::Display *display, const egl::Config *config, EGLNativeWindowType window,
- EGLint fixedSize, EGLint width, EGLint height)
+SurfaceD3D *SurfaceD3D::createFromWindow(RendererD3D *renderer,
+ egl::Display *display,
+ const egl::Config *config,
+ EGLNativeWindowType window,
+ EGLint fixedSize,
+ EGLint width,
+ EGLint height,
+ EGLint orientation)
{
- return new SurfaceD3D(renderer, display, config, width, height, fixedSize, static_cast<EGLClientBuffer>(0), window);
+ return new SurfaceD3D(renderer, display, config, width, height, fixedSize, orientation,
+ static_cast<EGLClientBuffer>(0), window);
}
SurfaceD3D::SurfaceD3D(RendererD3D *renderer,
@@ -39,12 +46,14 @@
EGLint width,
EGLint height,
EGLint fixedSize,
+ EGLint orientation,
EGLClientBuffer shareHandle,
EGLNativeWindowType window)
: SurfaceImpl(),
mRenderer(renderer),
mDisplay(display),
mFixedSize(fixedSize == EGL_TRUE),
+ mOrientation(orientation),
mRenderTargetFormat(config->renderTargetFormat),
mDepthStencilFormat(config->depthStencilFormat),
mSwapChain(nullptr),
@@ -128,7 +137,8 @@
height = mHeight;
}
- mSwapChain = mRenderer->createSwapChain(mNativeWindow, mShareHandle, mRenderTargetFormat, mDepthStencilFormat);
+ mSwapChain = mRenderer->createSwapChain(mNativeWindow, mShareHandle, mRenderTargetFormat,
+ mDepthStencilFormat, mOrientation);
if (!mSwapChain)
{
return egl::Error(EGL_BAD_ALLOC);
diff --git a/src/libANGLE/renderer/d3d/SurfaceD3D.h b/src/libANGLE/renderer/d3d/SurfaceD3D.h
index ed259de..a2929dc 100644
--- a/src/libANGLE/renderer/d3d/SurfaceD3D.h
+++ b/src/libANGLE/renderer/d3d/SurfaceD3D.h
@@ -25,8 +25,14 @@
class SurfaceD3D : public SurfaceImpl
{
public:
- static SurfaceD3D *createFromWindow(RendererD3D *renderer, egl::Display *display, const egl::Config *config,
- EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height);
+ static SurfaceD3D *createFromWindow(RendererD3D *renderer,
+ egl::Display *display,
+ const egl::Config *config,
+ EGLNativeWindowType window,
+ EGLint fixedSize,
+ EGLint width,
+ EGLint height,
+ EGLint orientation);
static SurfaceD3D *createOffscreen(RendererD3D *renderer, egl::Display *display, const egl::Config *config,
EGLClientBuffer shareHandle, EGLint width, EGLint height);
~SurfaceD3D() override;
@@ -60,8 +66,15 @@
FramebufferAttachmentRenderTarget **rtOut) override;
private:
- SurfaceD3D(RendererD3D *renderer, egl::Display *display, const egl::Config *config, EGLint width, EGLint height,
- EGLint fixedSize, EGLClientBuffer shareHandle, EGLNativeWindowType window);
+ SurfaceD3D(RendererD3D *renderer,
+ egl::Display *display,
+ const egl::Config *config,
+ EGLint width,
+ EGLint height,
+ EGLint fixedSize,
+ EGLint orientation,
+ EGLClientBuffer shareHandle,
+ EGLNativeWindowType window);
egl::Error swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
egl::Error resetSwapChain(int backbufferWidth, int backbufferHeight);
@@ -71,6 +84,7 @@
egl::Display *mDisplay;
bool mFixedSize;
+ GLint mOrientation;
GLenum mRenderTargetFormat;
GLenum mDepthStencilFormat;
diff --git a/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
index a808bb2..2db242c 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
@@ -989,6 +989,8 @@
const gl::Caps &rendererCaps = getRendererCaps();
const gl::TextureCapsMap &rendererTextureCaps = getRendererTextureCaps();
+ const EGLint optimalSurfaceOrientation = EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE;
+
egl::ConfigSet configs;
for (size_t formatIndex = 0; formatIndex < ArraySize(colorBufferFormats); formatIndex++)
{
@@ -1043,6 +1045,7 @@
config.transparentRedValue = 0;
config.transparentGreenValue = 0;
config.transparentBlueValue = 0;
+ config.optimalOrientation = optimalSurfaceOrientation;
configs.add(config);
}
@@ -1070,6 +1073,7 @@
outExtensions->querySurfacePointer = true;
outExtensions->windowFixedSize = true;
+ outExtensions->surfaceOrientation = true;
// D3D11 does not support present with dirty rectangles until DXGI 1.2.
outExtensions->postSubBuffer = mRenderer11DeviceCaps.supportsDXGI1_2;
@@ -1136,9 +1140,14 @@
return gl::Error(GL_NO_ERROR);
}
-SwapChainD3D *Renderer11::createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
+SwapChainD3D *Renderer11::createSwapChain(NativeWindow nativeWindow,
+ HANDLE shareHandle,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat,
+ EGLint orientation)
{
- return new SwapChain11(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat);
+ return new SwapChain11(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat,
+ orientation);
}
void *Renderer11::getD3DDevice()
@@ -2399,12 +2408,7 @@
{
TRACE_EVENT0("gpu.angle", "Renderer11::markAllStateDirty");
- for (size_t rtIndex = 0; rtIndex < ArraySize(mAppliedRTVs); rtIndex++)
- {
- mAppliedRTVs[rtIndex] = DirtyPointer;
- }
- mAppliedDSV = DirtyPointer;
- mDepthStencilInitialized = false;
+ markRenderTargetStateDirty();
// We reset the current SRV data because it might not be in sync with D3D's state
// anymore. For example when a currently used SRV is used as an RTV, D3D silently
@@ -2468,6 +2472,16 @@
mCurrentPrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
}
+void Renderer11::markRenderTargetStateDirty()
+{
+ for (size_t rtIndex = 0; rtIndex < ArraySize(mAppliedRTVs); rtIndex++)
+ {
+ mAppliedRTVs[rtIndex] = DirtyPointer;
+ }
+ mAppliedDSV = DirtyPointer;
+ mDepthStencilInitialized = false;
+}
+
void Renderer11::releaseDeviceResources()
{
mStateCache.clear();
diff --git a/src/libANGLE/renderer/d3d/d3d11/Renderer11.h b/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
index 7f80186..4bfcbf3 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
+++ b/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
@@ -111,7 +111,11 @@
gl::Error flush() override;
gl::Error finish() override;
- virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat);
+ SwapChainD3D *createSwapChain(NativeWindow nativeWindow,
+ HANDLE shareHandle,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat,
+ EGLint orientation) override;
virtual gl::Error generateSwizzle(gl::Texture *texture);
virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler);
@@ -139,6 +143,7 @@
void applyTransformFeedbackBuffers(const gl::State &state) override;
virtual void markAllStateDirty();
+ void markRenderTargetStateDirty();
// lost device
bool testDeviceLost() override;
diff --git a/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
index 8a4b619..21ce8bb 100644
--- a/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
@@ -8,6 +8,8 @@
#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
+#include <EGL/eglext.h>
+
#include "libANGLE/features.h"
#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h"
@@ -29,40 +31,43 @@
namespace rx
{
-SwapChain11::SwapChain11(Renderer11 *renderer, NativeWindow nativeWindow, HANDLE shareHandle,
- GLenum backBufferFormat, GLenum depthBufferFormat)
+SwapChain11::SwapChain11(Renderer11 *renderer,
+ NativeWindow nativeWindow,
+ HANDLE shareHandle,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat,
+ EGLint orientation)
: SwapChainD3D(nativeWindow, shareHandle, backBufferFormat, depthBufferFormat),
mRenderer(renderer),
+ mWidth(-1),
+ mHeight(-1),
+ mOrientation(orientation),
+ mAppCreatedShareHandle(mShareHandle != nullptr),
+ mSwapInterval(0),
mPassThroughResourcesInit(false),
+ mFirstSwap(true),
+ mSwapChain(nullptr),
+ mSwapChain1(nullptr),
+ mKeyedMutex(nullptr),
+ mNeedsOffscreenTexture(orientation != EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE),
+ mBackBufferTexture(nullptr),
+ mBackBufferRTView(nullptr),
+ mBackBufferSRView(nullptr),
+ mOffscreenTexture(nullptr),
+ mOffscreenRTView(nullptr),
+ mOffscreenSRView(nullptr),
+ mDepthStencilTexture(nullptr),
+ mDepthStencilDSView(nullptr),
+ mDepthStencilSRView(nullptr),
+ mQuadVB(nullptr),
+ mPassThroughSampler(nullptr),
+ mPassThroughIL(nullptr),
+ mPassThroughVS(nullptr),
+ mPassThroughPS(nullptr),
+ mPassThroughRS(nullptr),
mColorRenderTarget(this, renderer, false),
mDepthStencilRenderTarget(this, renderer, true)
{
- mHeight = -1;
- mWidth = -1;
- mAppCreatedShareHandle = mShareHandle != NULL;
- mSwapInterval = 0;
-
- mSwapChain = NULL;
- mSwapChain1 = nullptr;
-
- mKeyedMutex = nullptr;
-
- mBackBufferTexture = NULL;
- mBackBufferRTView = NULL;
-
- mOffscreenTexture = NULL;
- mOffscreenRTView = NULL;
- mOffscreenSRView = NULL;
-
- mDepthStencilTexture = NULL;
- mDepthStencilDSView = NULL;
- mDepthStencilSRView = NULL;
-
- mQuadVB = NULL;
- mPassThroughSampler = NULL;
- mPassThroughIL = NULL;
- mPassThroughVS = NULL;
- mPassThroughPS = NULL;
}
SwapChain11::~SwapChain11()
@@ -77,6 +82,7 @@
SafeRelease(mKeyedMutex);
SafeRelease(mBackBufferTexture);
SafeRelease(mBackBufferRTView);
+ SafeRelease(mBackBufferSRView);
SafeRelease(mOffscreenTexture);
SafeRelease(mOffscreenRTView);
SafeRelease(mOffscreenSRView);
@@ -88,6 +94,7 @@
SafeRelease(mPassThroughIL);
SafeRelease(mPassThroughVS);
SafeRelease(mPassThroughPS);
+ SafeRelease(mPassThroughRS);
if (!mAppCreatedShareHandle)
{
@@ -95,18 +102,47 @@
}
}
-void SwapChain11::releaseOffscreenTexture()
+void SwapChain11::releaseOffscreenColorBuffer()
{
SafeRelease(mOffscreenTexture);
SafeRelease(mOffscreenRTView);
SafeRelease(mOffscreenSRView);
+}
+
+void SwapChain11::releaseOffscreenDepthBuffer()
+{
SafeRelease(mDepthStencilTexture);
SafeRelease(mDepthStencilDSView);
SafeRelease(mDepthStencilSRView);
}
-EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHeight)
+EGLint SwapChain11::resetOffscreenBuffers(int backbufferWidth, int backbufferHeight)
{
+ if (mNeedsOffscreenTexture)
+ {
+ EGLint result = resetOffscreenColorBuffer(backbufferWidth, backbufferHeight);
+ if (result != EGL_SUCCESS)
+ {
+ return result;
+ }
+ }
+
+ EGLint result = resetOffscreenDepthBuffer(backbufferWidth, backbufferHeight);
+ if (result != EGL_SUCCESS)
+ {
+ return result;
+ }
+
+ mWidth = backbufferWidth;
+ mHeight = backbufferHeight;
+
+ return EGL_SUCCESS;
+}
+
+EGLint SwapChain11::resetOffscreenColorBuffer(int backbufferWidth, int backbufferHeight)
+{
+ ASSERT(mNeedsOffscreenTexture);
+
TRACE_EVENT0("gpu.angle", "SwapChain11::resetOffscreenTexture");
ID3D11Device *device = mRenderer->getDevice();
@@ -125,7 +161,7 @@
const int previousWidth = mWidth;
const int previousHeight = mHeight;
- releaseOffscreenTexture();
+ releaseOffscreenColorBuffer();
const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mOffscreenRenderTargetFormat, mRenderer->getRenderer11DeviceCaps());
@@ -230,7 +266,6 @@
mKeyedMutex = d3d11::DynamicCastComObject<IDXGIKeyedMutex>(mOffscreenTexture);
}
-
D3D11_RENDER_TARGET_VIEW_DESC offscreenRTVDesc;
offscreenRTVDesc.Format = backbufferFormatInfo.rtvFormat;
offscreenRTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
@@ -250,10 +285,41 @@
ASSERT(SUCCEEDED(result));
d3d11::SetDebugName(mOffscreenSRView, "Offscreen back buffer shader resource");
- const d3d11::TextureFormat &depthBufferFormatInfo = d3d11::GetTextureFormatInfo(mDepthBufferFormat, mRenderer->getRenderer11DeviceCaps());
+ if (previousOffscreenTexture != nullptr)
+ {
+ D3D11_BOX sourceBox = {0};
+ sourceBox.left = 0;
+ sourceBox.right = std::min(previousWidth, backbufferWidth);
+ sourceBox.top = std::max(previousHeight - backbufferHeight, 0);
+ sourceBox.bottom = previousHeight;
+ sourceBox.front = 0;
+ sourceBox.back = 1;
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ const int yoffset = std::max(backbufferHeight - previousHeight, 0);
+ deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0,
+ previousOffscreenTexture, 0, &sourceBox);
+
+ SafeRelease(previousOffscreenTexture);
+
+ if (mSwapChain)
+ {
+ swapRect(0, 0, backbufferWidth, backbufferHeight);
+ }
+ }
+
+ return EGL_SUCCESS;
+}
+
+EGLint SwapChain11::resetOffscreenDepthBuffer(int backbufferWidth, int backbufferHeight)
+{
+ releaseOffscreenDepthBuffer();
if (mDepthBufferFormat != GL_NONE)
{
+ const d3d11::TextureFormat &depthBufferFormatInfo =
+ d3d11::GetTextureFormatInfo(mDepthBufferFormat, mRenderer->getRenderer11DeviceCaps());
+
D3D11_TEXTURE2D_DESC depthStencilTextureDesc;
depthStencilTextureDesc.Width = backbufferWidth;
depthStencilTextureDesc.Height = backbufferHeight;
@@ -273,7 +339,9 @@
depthStencilTextureDesc.CPUAccessFlags = 0;
depthStencilTextureDesc.MiscFlags = 0;
- result = device->CreateTexture2D(&depthStencilTextureDesc, NULL, &mDepthStencilTexture);
+ ID3D11Device *device = mRenderer->getDevice();
+ HRESULT result =
+ device->CreateTexture2D(&depthStencilTextureDesc, NULL, &mDepthStencilTexture);
if (FAILED(result))
{
ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result);
@@ -314,31 +382,6 @@
}
}
- mWidth = backbufferWidth;
- mHeight = backbufferHeight;
-
- if (previousOffscreenTexture != NULL)
- {
- D3D11_BOX sourceBox = {0};
- sourceBox.left = 0;
- sourceBox.right = std::min(previousWidth, mWidth);
- sourceBox.top = std::max(previousHeight - mHeight, 0);
- sourceBox.bottom = previousHeight;
- sourceBox.front = 0;
- sourceBox.back = 1;
-
- ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
- const int yoffset = std::max(mHeight - previousHeight, 0);
- deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0, previousOffscreenTexture, 0, &sourceBox);
-
- SafeRelease(previousOffscreenTexture);
-
- if (mSwapChain)
- {
- swapRect(0, 0, mWidth, mHeight);
- }
- }
-
return EGL_SUCCESS;
}
@@ -358,11 +401,18 @@
return EGL_SUCCESS;
}
+ // Don't resize unnecessarily
+ if (mWidth == backbufferWidth && mHeight == backbufferHeight)
+ {
+ return EGL_SUCCESS;
+ }
+
// Can only call resize if we have already created our swap buffer and resources
- ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView);
+ ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView && mBackBufferSRView);
SafeRelease(mBackBufferTexture);
SafeRelease(mBackBufferRTView);
+ SafeRelease(mBackBufferSRView);
// Resize swap chain
DXGI_SWAP_CHAIN_DESC desc;
@@ -398,14 +448,22 @@
d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture");
result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView);
ASSERT(SUCCEEDED(result));
+ if (SUCCEEDED(result))
+ {
+ d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
+ }
+
+ result = device->CreateShaderResourceView(mBackBufferTexture, nullptr, &mBackBufferSRView);
+ ASSERT(SUCCEEDED(result));
+ if (SUCCEEDED(result))
+ {
+ d3d11::SetDebugName(mBackBufferSRView, "Back buffer shader resource");
+ }
}
- if (SUCCEEDED(result))
- {
- d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
- }
+ mFirstSwap = true;
- return resetOffscreenTexture(backbufferWidth, backbufferHeight);
+ return resetOffscreenBuffers(backbufferWidth, backbufferHeight);
}
DXGI_FORMAT SwapChain11::getSwapChainNativeFormat() const
@@ -417,6 +475,20 @@
EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval)
{
+ mSwapInterval = static_cast<unsigned int>(swapInterval);
+ if (mSwapInterval > 4)
+ {
+ // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4]
+ // range
+ return EGL_BAD_PARAMETER;
+ }
+
+ // If the swap chain already exists, just resize
+ if (mSwapChain != nullptr)
+ {
+ return resize(backbufferWidth, backbufferHeight);
+ }
+
TRACE_EVENT0("gpu.angle", "SwapChain11::reset");
ID3D11Device *device = mRenderer->getDevice();
@@ -432,17 +504,10 @@
SafeRelease(mBackBufferTexture);
SafeRelease(mBackBufferRTView);
- mSwapInterval = static_cast<unsigned int>(swapInterval);
- if (mSwapInterval > 4)
- {
- // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4] range
- return EGL_BAD_PARAMETER;
- }
-
// EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains
if (backbufferWidth < 1 || backbufferHeight < 1)
{
- releaseOffscreenTexture();
+ releaseOffscreenColorBuffer();
return EGL_SUCCESS;
}
@@ -479,9 +544,15 @@
result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView);
ASSERT(SUCCEEDED(result));
d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
+
+ result = device->CreateShaderResourceView(mBackBufferTexture, nullptr, &mBackBufferSRView);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mBackBufferSRView, "Back buffer shader resource view");
}
- return resetOffscreenTexture(backbufferWidth, backbufferHeight);
+ mFirstSwap = true;
+
+ return resetOffscreenBuffers(backbufferWidth, backbufferHeight);
}
void SwapChain11::initPassThroughResources()
@@ -549,12 +620,50 @@
ASSERT(SUCCEEDED(result));
d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader");
+ // Use the default rasterizer state but without culling
+ D3D11_RASTERIZER_DESC rasterizerDesc;
+ rasterizerDesc.FillMode = D3D11_FILL_SOLID;
+ rasterizerDesc.CullMode = D3D11_CULL_NONE;
+ rasterizerDesc.FrontCounterClockwise = FALSE;
+ rasterizerDesc.DepthBias = 0;
+ rasterizerDesc.SlopeScaledDepthBias = 0.0f;
+ rasterizerDesc.DepthBiasClamp = 0.0f;
+ rasterizerDesc.DepthClipEnable = TRUE;
+ rasterizerDesc.ScissorEnable = FALSE;
+ rasterizerDesc.MultisampleEnable = FALSE;
+ rasterizerDesc.AntialiasedLineEnable = FALSE;
+ result = device->CreateRasterizerState(&rasterizerDesc, &mPassThroughRS);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mPassThroughRS, "Swap chain pass through rasterizer state");
+
mPassThroughResourcesInit = true;
}
// parameters should be validated/clamped by caller
EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
{
+ if (mNeedsOffscreenTexture)
+ {
+ EGLint result = copyOffscreenToBackbuffer(x, y, width, height);
+ if (result != EGL_SUCCESS)
+ {
+ return result;
+ }
+ }
+
+ EGLint result = present(x, y, width, height);
+ if (result != EGL_SUCCESS)
+ {
+ return result;
+ }
+
+ mRenderer->onSwap();
+
+ return EGL_SUCCESS;
+}
+
+EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
if (!mSwapChain)
{
return EGL_SUCCESS;
@@ -562,7 +671,6 @@
initPassThroughResources();
- ID3D11Device *device = mRenderer->getDevice();
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
// Set vertices
@@ -586,6 +694,16 @@
float u2 = (x + width) / float(mWidth);
float v2 = (y + height) / float(mHeight);
+ // Invert the quad vertices depending on the surface orientation.
+ if ((mOrientation & EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE) != 0)
+ {
+ std::swap(x1, x2);
+ }
+ if ((mOrientation & EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE) != 0)
+ {
+ std::swap(y1, y2);
+ }
+
d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1);
d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2);
d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1);
@@ -603,7 +721,7 @@
static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF);
- deviceContext->RSSetState(NULL);
+ deviceContext->RSSetState(mPassThroughRS);
// Apply shaders
deviceContext->IASetInputLayout(mPassThroughIL);
@@ -640,28 +758,54 @@
mRenderer->unapplyRenderTargets();
mRenderer->markAllStateDirty();
+ return EGL_SUCCESS;
+}
+
+EGLint SwapChain11::present(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ if (!mSwapChain)
+ {
+ return EGL_SUCCESS;
+ }
+
+ UINT swapInterval = mSwapInterval;
#if ANGLE_VSYNC == ANGLE_DISABLED
- result = mSwapChain->Present(0, 0);
-#else
+ swapInterval = 0;
+#endif
+
+ HRESULT result = S_OK;
+
// Use IDXGISwapChain1::Present1 with a dirty rect if DXGI 1.2 is available.
if (mSwapChain1 != nullptr)
{
- RECT rect =
+ if (mFirstSwap)
{
- static_cast<LONG>(x), static_cast<LONG>(mHeight - y - height),
- static_cast<LONG>(x + width), static_cast<LONG>(mHeight - y)
- };
- DXGI_PRESENT_PARAMETERS params = { 1, &rect, nullptr, nullptr };
- result = mSwapChain1->Present1(mSwapInterval, 0, ¶ms);
+ // Can't swap with a dirty rect if this swap chain has never swapped before
+ DXGI_PRESENT_PARAMETERS params = {0, nullptr, nullptr, nullptr};
+ result = mSwapChain1->Present1(swapInterval, 0, ¶ms);
+ }
+ else
+ {
+ RECT rect = {static_cast<LONG>(x), static_cast<LONG>(mHeight - y - height),
+ static_cast<LONG>(x + width), static_cast<LONG>(mHeight - y)};
+ DXGI_PRESENT_PARAMETERS params = {1, &rect, nullptr, nullptr};
+ result = mSwapChain1->Present1(swapInterval, 0, ¶ms);
+ }
}
else
{
- result = mSwapChain->Present(mSwapInterval, 0);
+ result = mSwapChain->Present(swapInterval, 0);
}
-#endif
+
+ mFirstSwap = false;
+
+ // Some swapping mechanisms such as DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL unbind the current render
+ // target. Mark it dirty.
+ mRenderer->markRenderTargetStateDirty();
if (result == DXGI_ERROR_DEVICE_REMOVED)
{
+ ID3D11Device *device = mRenderer->getDevice();
HRESULT removedReason = device->GetDeviceRemovedReason();
UNUSED_TRACE_VARIABLE(removedReason);
ERR("Present failed: the D3D11 device was removed: 0x%08X", removedReason);
@@ -677,24 +821,22 @@
ERR("Present failed with error code 0x%08X", result);
}
- mRenderer->onSwap();
-
return EGL_SUCCESS;
}
ID3D11Texture2D *SwapChain11::getOffscreenTexture()
{
- return mOffscreenTexture;
+ return mNeedsOffscreenTexture ? mOffscreenTexture : mBackBufferTexture;
}
ID3D11RenderTargetView *SwapChain11::getRenderTarget()
{
- return mOffscreenRTView;
+ return mNeedsOffscreenTexture ? mOffscreenRTView : mBackBufferRTView;
}
ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource()
{
- return mOffscreenSRView;
+ return mNeedsOffscreenTexture ? mOffscreenSRView : mBackBufferSRView;
}
ID3D11DepthStencilView *SwapChain11::getDepthStencil()
diff --git a/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h b/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h
index 24c21e1..9c29cd8 100644
--- a/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h
+++ b/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h
@@ -20,8 +20,12 @@
class SwapChain11 : public SwapChainD3D
{
public:
- SwapChain11(Renderer11 *renderer, NativeWindow nativeWindow, HANDLE shareHandle,
- GLenum backBufferFormat, GLenum depthBufferFormat);
+ SwapChain11(Renderer11 *renderer,
+ NativeWindow nativeWindow,
+ HANDLE shareHandle,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat,
+ EGLint orientation);
virtual ~SwapChain11();
EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight);
@@ -47,24 +51,36 @@
private:
void release();
void initPassThroughResources();
- void releaseOffscreenTexture();
- EGLint resetOffscreenTexture(int backbufferWidth, int backbufferHeight);
+
+ void releaseOffscreenColorBuffer();
+ void releaseOffscreenDepthBuffer();
+ EGLint resetOffscreenBuffers(int backbufferWidth, int backbufferHeight);
+ EGLint resetOffscreenColorBuffer(int backbufferWidth, int backbufferHeight);
+ EGLint resetOffscreenDepthBuffer(int backbufferWidth, int backbufferHeight);
+
DXGI_FORMAT getSwapChainNativeFormat() const;
+ EGLint copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width, EGLint height);
+ EGLint present(EGLint x, EGLint y, EGLint width, EGLint height);
+
Renderer11 *mRenderer;
EGLint mHeight;
EGLint mWidth;
+ const EGLint mOrientation;
bool mAppCreatedShareHandle;
unsigned int mSwapInterval;
bool mPassThroughResourcesInit;
+ bool mFirstSwap;
DXGISwapChain *mSwapChain;
IDXGISwapChain1 *mSwapChain1;
IDXGIKeyedMutex *mKeyedMutex;
ID3D11Texture2D *mBackBufferTexture;
ID3D11RenderTargetView *mBackBufferRTView;
+ ID3D11ShaderResourceView *mBackBufferSRView;
+ const bool mNeedsOffscreenTexture;
ID3D11Texture2D *mOffscreenTexture;
ID3D11RenderTargetView *mOffscreenRTView;
ID3D11ShaderResourceView *mOffscreenSRView;
@@ -78,6 +94,7 @@
ID3D11InputLayout *mPassThroughIL;
ID3D11VertexShader *mPassThroughVS;
ID3D11PixelShader *mPassThroughPS;
+ ID3D11RasterizerState *mPassThroughRS;
SurfaceRenderTarget11 mColorRenderTarget;
SurfaceRenderTarget11 mDepthStencilRenderTarget;
diff --git a/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp b/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp
index 2b8b48c..4f773bb 100644
--- a/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp
@@ -59,7 +59,8 @@
swapChainDesc.Stereo = FALSE;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
- swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER;
+ swapChainDesc.BufferUsage =
+ DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_BACK_BUFFER;
swapChainDesc.BufferCount = 1;
swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL;
@@ -84,7 +85,8 @@
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.BufferUsage =
+ DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_BACK_BUFFER;
swapChainDesc.Flags = 0;
swapChainDesc.OutputWindow = mWindow;
swapChainDesc.SampleDesc.Count = 1;
diff --git a/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp b/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
index 49e4171..4718781 100644
--- a/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
+++ b/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
@@ -652,9 +652,14 @@
return gl::Error(GL_NO_ERROR);
}
-SwapChainD3D *Renderer9::createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
+SwapChainD3D *Renderer9::createSwapChain(NativeWindow nativeWindow,
+ HANDLE shareHandle,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat,
+ EGLint orientation)
{
- return new SwapChain9(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat);
+ return new SwapChain9(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat,
+ orientation);
}
void *Renderer9::getD3DDevice()
diff --git a/src/libANGLE/renderer/d3d/d3d9/Renderer9.h b/src/libANGLE/renderer/d3d/d3d9/Renderer9.h
index 6087b4e..4e3fb9c 100644
--- a/src/libANGLE/renderer/d3d/d3d9/Renderer9.h
+++ b/src/libANGLE/renderer/d3d/d3d9/Renderer9.h
@@ -79,7 +79,11 @@
gl::Error flush() override;
gl::Error finish() override;
- virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat);
+ SwapChainD3D *createSwapChain(NativeWindow nativeWindow,
+ HANDLE shareHandle,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat,
+ EGLint orientation) override;
gl::Error allocateEventQuery(IDirect3DQuery9 **outQuery);
void freeEventQuery(IDirect3DQuery9* query);
diff --git a/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp b/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp
index 5ce76f8..76b535e 100644
--- a/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp
+++ b/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp
@@ -15,21 +15,27 @@
namespace rx
{
-SwapChain9::SwapChain9(Renderer9 *renderer, NativeWindow nativeWindow, HANDLE shareHandle,
- GLenum backBufferFormat, GLenum depthBufferFormat)
+SwapChain9::SwapChain9(Renderer9 *renderer,
+ NativeWindow nativeWindow,
+ HANDLE shareHandle,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat,
+ EGLint orientation)
: SwapChainD3D(nativeWindow, shareHandle, backBufferFormat, depthBufferFormat),
mRenderer(renderer),
+ mWidth(-1),
+ mHeight(-1),
+ mOrientation(orientation),
+ mSwapInterval(-1),
+ mSwapChain(nullptr),
+ mBackBuffer(nullptr),
+ mRenderTarget(nullptr),
+ mDepthStencil(nullptr),
+ mOffscreenTexture(nullptr),
mColorRenderTarget(this, false),
mDepthStencilRenderTarget(this, true)
{
- mSwapChain = NULL;
- mBackBuffer = NULL;
- mDepthStencil = NULL;
- mRenderTarget = NULL;
- mOffscreenTexture = NULL;
- mWidth = -1;
- mHeight = -1;
- mSwapInterval = -1;
+ ASSERT(mOrientation == 0);
}
SwapChain9::~SwapChain9()
diff --git a/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h b/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h
index 9c67f71..6cee949 100644
--- a/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h
+++ b/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h
@@ -20,8 +20,12 @@
class SwapChain9 : public SwapChainD3D
{
public:
- SwapChain9(Renderer9 *renderer, NativeWindow nativeWindow, HANDLE shareHandle,
- GLenum backBufferFormat, GLenum depthBufferFormat);
+ SwapChain9(Renderer9 *renderer,
+ NativeWindow nativeWindow,
+ HANDLE shareHandle,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat,
+ EGLint orientation);
virtual ~SwapChain9();
EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight);
@@ -47,6 +51,7 @@
Renderer9 *mRenderer;
EGLint mHeight;
EGLint mWidth;
+ EGLint mOrientation;
EGLint mSwapInterval;
IDirect3DSwapChain9 *mSwapChain;
diff --git a/src/libANGLE/validationEGL.cpp b/src/libANGLE/validationEGL.cpp
index 5cbb6d8..a6d2313 100644
--- a/src/libANGLE/validationEGL.cpp
+++ b/src/libANGLE/validationEGL.cpp
@@ -372,6 +372,13 @@
}
break;
+ case EGL_SURFACE_ORIENTATION_ANGLE:
+ if (!displayExtensions.surfaceOrientation)
+ {
+ return Error(EGL_BAD_ATTRIBUTE, "EGL_ANGLE_surface_orientation is not enabled.");
+ }
+ break;
+
case EGL_VG_COLORSPACE:
return Error(EGL_BAD_MATCH);
diff --git a/src/libGLESv2/entry_points_egl.cpp b/src/libGLESv2/entry_points_egl.cpp
index 3f0f0e0..b67abe2 100644
--- a/src/libGLESv2/entry_points_egl.cpp
+++ b/src/libGLESv2/entry_points_egl.cpp
@@ -437,6 +437,16 @@
}
*value = eglSurface->flexibleSurfaceCompatibilityRequested();
break;
+ case EGL_SURFACE_ORIENTATION_ANGLE:
+ if (!display->getExtensions().surfaceOrientation)
+ {
+ SetGlobalError(Error(EGL_BAD_ATTRIBUTE,
+ "EGL_SURFACE_ORIENTATION_ANGLE cannot be queried without "
+ "EGL_ANGLE_surface_orientation support."));
+ return EGL_FALSE;
+ }
+ *value = eglSurface->getOrientation();
+ break;
default:
SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
return EGL_FALSE;