summaryrefslogtreecommitdiffstats
path: root/gfx/angle/src/tests/egl_tests/EGLPresentPathD3D11Test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/src/tests/egl_tests/EGLPresentPathD3D11Test.cpp')
-rwxr-xr-xgfx/angle/src/tests/egl_tests/EGLPresentPathD3D11Test.cpp378
1 files changed, 378 insertions, 0 deletions
diff --git a/gfx/angle/src/tests/egl_tests/EGLPresentPathD3D11Test.cpp b/gfx/angle/src/tests/egl_tests/EGLPresentPathD3D11Test.cpp
new file mode 100755
index 000000000..c73c7c4ff
--- /dev/null
+++ b/gfx/angle/src/tests/egl_tests/EGLPresentPathD3D11Test.cpp
@@ -0,0 +1,378 @@
+//
+// Copyright 2015 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.
+//
+
+#include "test_utils/ANGLETest.h"
+
+#include <cstdint>
+#include "com_utils.h"
+#include "OSWindow.h"
+#include <d3d11.h>
+
+using namespace angle;
+
+class EGLPresentPathD3D11 : public testing::TestWithParam<PlatformParameters>
+{
+ protected:
+ EGLPresentPathD3D11()
+ : mDisplay(EGL_NO_DISPLAY),
+ mContext(EGL_NO_CONTEXT),
+ mSurface(EGL_NO_SURFACE),
+ mOffscreenSurfaceD3D11Texture(nullptr),
+ mConfig(0),
+ mOSWindow(nullptr),
+ mWindowWidth(0)
+ {
+ }
+
+ void SetUp() override
+ {
+ mOSWindow = CreateOSWindow();
+ mWindowWidth = 64;
+ mOSWindow->initialize("EGLPresentPathD3D11", mWindowWidth, mWindowWidth);
+ }
+
+ void initializeEGL(bool usePresentPathFast)
+ {
+ int clientVersion = GetParam().majorVersion;
+
+ const char *extensionString =
+ static_cast<const char *>(eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS));
+ ASSERT_NE(nullptr, strstr(extensionString, "EGL_ANGLE_experimental_present_path"));
+
+ PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT =
+ reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(
+ eglGetProcAddress("eglGetPlatformDisplayEXT"));
+ ASSERT_NE(nullptr, eglGetPlatformDisplayEXT);
+
+ // Set up EGL Display
+ EGLint displayAttribs[] = {
+ EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(),
+ EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, GetParam().eglParameters.majorVersion,
+ EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, GetParam().eglParameters.majorVersion,
+ EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE,
+ usePresentPathFast ? EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE
+ : EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE,
+ EGL_NONE};
+ mDisplay =
+ eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, displayAttribs);
+ ASSERT_TRUE(EGL_NO_DISPLAY != mDisplay);
+ ASSERT_EGL_TRUE(eglInitialize(mDisplay, NULL, NULL));
+
+ // Choose the EGL config
+ EGLint numConfigs;
+ EGLint configAttribs[] = {EGL_RED_SIZE,
+ 8,
+ EGL_GREEN_SIZE,
+ 8,
+ EGL_BLUE_SIZE,
+ 8,
+ EGL_ALPHA_SIZE,
+ 8,
+ EGL_RENDERABLE_TYPE,
+ clientVersion == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT,
+ EGL_SURFACE_TYPE,
+ EGL_PBUFFER_BIT,
+ EGL_NONE};
+ ASSERT_EGL_TRUE(eglChooseConfig(mDisplay, configAttribs, &mConfig, 1, &numConfigs));
+ ASSERT_EQ(1, numConfigs);
+
+ // Set up the EGL context
+ EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, clientVersion, EGL_NONE};
+ mContext = eglCreateContext(mDisplay, mConfig, NULL, contextAttribs);
+ ASSERT_TRUE(EGL_NO_CONTEXT != mContext);
+ }
+
+ void createWindowSurface()
+ {
+ mSurface = eglCreateWindowSurface(mDisplay, mConfig, mOSWindow->getNativeWindow(), nullptr);
+ }
+
+ void createPbufferFromClientBufferSurface()
+ {
+ EGLAttrib device = 0;
+ EGLAttrib angleDevice = 0;
+
+ PFNEGLQUERYDISPLAYATTRIBEXTPROC queryDisplayAttribEXT;
+ PFNEGLQUERYDEVICEATTRIBEXTPROC queryDeviceAttribEXT;
+
+ const char *extensionString =
+ static_cast<const char *>(eglQueryString(mDisplay, EGL_EXTENSIONS));
+ EXPECT_TRUE(strstr(extensionString, "EGL_EXT_device_query"));
+
+ queryDisplayAttribEXT =
+ (PFNEGLQUERYDISPLAYATTRIBEXTPROC)eglGetProcAddress("eglQueryDisplayAttribEXT");
+ queryDeviceAttribEXT =
+ (PFNEGLQUERYDEVICEATTRIBEXTPROC)eglGetProcAddress("eglQueryDeviceAttribEXT");
+ ASSERT_NE(nullptr, queryDisplayAttribEXT);
+ ASSERT_NE(nullptr, queryDeviceAttribEXT);
+
+ ASSERT_EGL_TRUE(queryDisplayAttribEXT(mDisplay, EGL_DEVICE_EXT, &angleDevice));
+ ASSERT_EGL_TRUE(queryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(angleDevice),
+ EGL_D3D11_DEVICE_ANGLE, &device));
+ ID3D11Device *d3d11Device = reinterpret_cast<ID3D11Device *>(device);
+
+ D3D11_TEXTURE2D_DESC textureDesc = {0};
+ textureDesc.Width = mWindowWidth;
+ textureDesc.Height = mWindowWidth;
+ textureDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
+ textureDesc.MipLevels = 1;
+ textureDesc.ArraySize = 1;
+ textureDesc.SampleDesc.Count = 1;
+ textureDesc.SampleDesc.Quality = 0;
+ textureDesc.Usage = D3D11_USAGE_DEFAULT;
+ textureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
+ textureDesc.CPUAccessFlags = 0;
+ textureDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
+
+ ASSERT_TRUE(SUCCEEDED(
+ d3d11Device->CreateTexture2D(&textureDesc, nullptr, &mOffscreenSurfaceD3D11Texture)));
+
+ IDXGIResource *dxgiResource =
+ DynamicCastComObject<IDXGIResource>(mOffscreenSurfaceD3D11Texture);
+ ASSERT_NE(nullptr, dxgiResource);
+
+ HANDLE sharedHandle = 0;
+ ASSERT_TRUE(SUCCEEDED(dxgiResource->GetSharedHandle(&sharedHandle)));
+ SafeRelease(dxgiResource);
+
+ EGLint pBufferAttributes[] = {EGL_WIDTH, mWindowWidth, EGL_HEIGHT,
+ mWindowWidth, EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
+ EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA, EGL_NONE};
+
+ mSurface = eglCreatePbufferFromClientBuffer(mDisplay, EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE,
+ sharedHandle, mConfig, pBufferAttributes);
+ ASSERT_TRUE(EGL_NO_SURFACE != mSurface);
+ }
+
+ void makeCurrent() { ASSERT_EGL_TRUE(eglMakeCurrent(mDisplay, mSurface, mSurface, mContext)); }
+
+ void TearDown() override
+ {
+ SafeRelease(mOffscreenSurfaceD3D11Texture);
+
+ if (mDisplay != EGL_NO_DISPLAY)
+ {
+ eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+
+ if (mSurface != EGL_NO_SURFACE)
+ {
+ eglDestroySurface(mDisplay, mSurface);
+ mSurface = EGL_NO_SURFACE;
+ }
+
+ if (mContext != EGL_NO_CONTEXT)
+ {
+ eglDestroyContext(mDisplay, mContext);
+ mContext = EGL_NO_CONTEXT;
+ }
+
+ eglTerminate(mDisplay);
+ mDisplay = EGL_NO_DISPLAY;
+ }
+
+ mOSWindow->destroy();
+ SafeDelete(mOSWindow);
+ }
+
+ void drawQuadUsingGL()
+ {
+ GLuint m2DProgram;
+ GLint mTexture2DUniformLocation;
+
+ const std::string vertexShaderSource =
+ SHADER_SOURCE(precision highp float; attribute vec4 position; varying vec2 texcoord;
+
+ void main()
+ {
+ gl_Position = vec4(position.xy, 0.0, 1.0);
+ texcoord = (position.xy * 0.5) + 0.5;
+ });
+
+ const std::string fragmentShaderSource2D =
+ SHADER_SOURCE(precision highp float; uniform sampler2D tex; varying vec2 texcoord;
+
+ void main()
+ {
+ gl_FragColor = texture2D(tex, texcoord);
+ });
+
+ m2DProgram = CompileProgram(vertexShaderSource, fragmentShaderSource2D);
+ mTexture2DUniformLocation = glGetUniformLocation(m2DProgram, "tex");
+
+ uint8_t textureInitData[16] = {
+ 255, 0, 0, 255, // Red
+ 0, 255, 0, 255, // Green
+ 0, 0, 255, 255, // Blue
+ 255, 255, 0, 255 // Red + Green
+ };
+
+ // Create a simple RGBA texture
+ GLuint tex = 0;
+ glGenTextures(1, &tex);
+ glBindTexture(GL_TEXTURE_2D, tex);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+ textureInitData);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ ASSERT_GL_NO_ERROR();
+
+ // Draw a quad using the texture
+ glClear(GL_COLOR_BUFFER_BIT);
+ glUseProgram(m2DProgram);
+ glUniform1i(mTexture2DUniformLocation, 0);
+
+ GLint positionLocation = glGetAttribLocation(m2DProgram, "position");
+ glUseProgram(m2DProgram);
+ const GLfloat vertices[] =
+ {
+ -1.0f, 1.0f, 0.5f,
+ -1.0f, -1.0f, 0.5f,
+ 1.0f, -1.0f, 0.5f,
+ -1.0f, 1.0f, 0.5f,
+ 1.0f, -1.0f, 0.5f,
+ 1.0f, 1.0f, 0.5f,
+ };
+
+ glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices);
+ glEnableVertexAttribArray(positionLocation);
+
+ glDrawArrays(GL_TRIANGLES, 0, 6);
+ ASSERT_GL_NO_ERROR();
+
+ glDeleteProgram(m2DProgram);
+ }
+
+ void checkPixelsUsingGL()
+ {
+ // Note that the texture is in BGRA format
+ EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255); // Red
+ EXPECT_PIXEL_EQ(mWindowWidth - 1, 0, 0, 255, 0, 255); // Green
+ EXPECT_PIXEL_EQ(0, mWindowWidth - 1, 0, 0, 255, 255); // Blue
+ EXPECT_PIXEL_EQ(mWindowWidth - 1, mWindowWidth - 1, 255, 255, 0, 255); // Red + green
+ }
+
+ void checkPixelsUsingD3D(bool usingPresentPathFast)
+ {
+ ASSERT_NE(nullptr, mOffscreenSurfaceD3D11Texture);
+
+ D3D11_TEXTURE2D_DESC textureDesc = {0};
+ ID3D11Device *device;
+ ID3D11DeviceContext *context;
+ mOffscreenSurfaceD3D11Texture->GetDesc(&textureDesc);
+ mOffscreenSurfaceD3D11Texture->GetDevice(&device);
+ device->GetImmediateContext(&context);
+ ASSERT_NE(nullptr, device);
+ ASSERT_NE(nullptr, context);
+
+ textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+ textureDesc.Usage = D3D11_USAGE_STAGING;
+ textureDesc.BindFlags = 0;
+ textureDesc.MiscFlags = 0;
+ ID3D11Texture2D *cpuTexture = nullptr;
+ ASSERT_TRUE(SUCCEEDED(device->CreateTexture2D(&textureDesc, nullptr, &cpuTexture)));
+
+ context->CopyResource(cpuTexture, mOffscreenSurfaceD3D11Texture);
+
+ D3D11_MAPPED_SUBRESOURCE mappedSubresource;
+ context->Map(cpuTexture, 0, D3D11_MAP_READ, 0, &mappedSubresource);
+ ASSERT_EQ(static_cast<UINT>(mWindowWidth * 4), mappedSubresource.RowPitch);
+ ASSERT_EQ(static_cast<UINT>(mWindowWidth * mWindowWidth * 4), mappedSubresource.DepthPitch);
+
+ angle::GLColor *byteData = reinterpret_cast<angle::GLColor *>(mappedSubresource.pData);
+
+ // Note that the texture is in BGRA format, although the GLColor struct is RGBA
+ GLColor expectedTopLeftPixel = GLColor(0, 0, 255, 255); // Red
+ GLColor expectedTopRightPixel = GLColor(0, 255, 0, 255); // Green
+ GLColor expectedBottomLeftPixel = GLColor(255, 0, 0, 255); // Blue
+ GLColor expectedBottomRightPixel = GLColor(0, 255, 255, 255); // Red + Green
+
+ if (usingPresentPathFast)
+ {
+ // Invert the expected values
+ GLColor tempTopLeft = expectedTopLeftPixel;
+ GLColor tempTopRight = expectedTopRightPixel;
+ expectedTopLeftPixel = expectedBottomLeftPixel;
+ expectedTopRightPixel = expectedBottomRightPixel;
+ expectedBottomLeftPixel = tempTopLeft;
+ expectedBottomRightPixel = tempTopRight;
+ }
+
+ EXPECT_EQ(expectedTopLeftPixel, byteData[0]);
+ EXPECT_EQ(expectedTopRightPixel, byteData[(mWindowWidth - 1)]);
+ EXPECT_EQ(expectedBottomLeftPixel, byteData[(mWindowWidth - 1) * mWindowWidth]);
+ EXPECT_EQ(expectedBottomRightPixel,
+ byteData[(mWindowWidth - 1) * mWindowWidth + (mWindowWidth - 1)]);
+
+ context->Unmap(cpuTexture, 0);
+ SafeRelease(cpuTexture);
+ SafeRelease(device);
+ SafeRelease(context);
+ }
+
+ EGLDisplay mDisplay;
+ EGLContext mContext;
+ EGLSurface mSurface;
+ ID3D11Texture2D *mOffscreenSurfaceD3D11Texture;
+ EGLConfig mConfig;
+ OSWindow *mOSWindow;
+ GLint mWindowWidth;
+};
+
+// Test that rendering basic content onto a window surface when present path fast
+// is enabled works as expected
+TEST_P(EGLPresentPathD3D11, WindowPresentPathFast)
+{
+ initializeEGL(true);
+ createWindowSurface();
+ makeCurrent();
+
+ drawQuadUsingGL();
+
+ checkPixelsUsingGL();
+}
+
+// Test that rendering basic content onto a client buffer surface when present path fast
+// works as expected, and is also oriented the correct way around
+TEST_P(EGLPresentPathD3D11, ClientBufferPresentPathFast)
+{
+ initializeEGL(true);
+ createPbufferFromClientBufferSurface();
+ makeCurrent();
+
+ drawQuadUsingGL();
+
+ checkPixelsUsingGL();
+ checkPixelsUsingD3D(true);
+}
+
+// Test that rendering basic content onto a window surface when present path fast
+// is disabled works as expected
+TEST_P(EGLPresentPathD3D11, WindowPresentPathCopy)
+{
+ initializeEGL(false);
+ createWindowSurface();
+ makeCurrent();
+
+ drawQuadUsingGL();
+
+ checkPixelsUsingGL();
+}
+
+// Test that rendering basic content onto a client buffer surface when present path
+// fast is disabled works as expected, and is also oriented the correct way around
+TEST_P(EGLPresentPathD3D11, ClientBufferPresentPathCopy)
+{
+ initializeEGL(false);
+ createPbufferFromClientBufferSurface();
+ makeCurrent();
+
+ drawQuadUsingGL();
+
+ checkPixelsUsingGL();
+ checkPixelsUsingD3D(false);
+}
+
+ANGLE_INSTANTIATE_TEST(EGLPresentPathD3D11, ES2_D3D11(), ES2_D3D11_FL9_3()); \ No newline at end of file