summaryrefslogtreecommitdiff
path: root/Source/ThirdParty/ANGLE/src/tests/egl_tests/EGLSyncControlTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/ThirdParty/ANGLE/src/tests/egl_tests/EGLSyncControlTest.cpp')
-rw-r--r--Source/ThirdParty/ANGLE/src/tests/egl_tests/EGLSyncControlTest.cpp270
1 files changed, 270 insertions, 0 deletions
diff --git a/Source/ThirdParty/ANGLE/src/tests/egl_tests/EGLSyncControlTest.cpp b/Source/ThirdParty/ANGLE/src/tests/egl_tests/EGLSyncControlTest.cpp
new file mode 100644
index 000000000..793910970
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/tests/egl_tests/EGLSyncControlTest.cpp
@@ -0,0 +1,270 @@
+//
+// Copyright 2016 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.
+//
+
+#ifndef ANGLE_ENABLE_D3D9
+#define ANGLE_ENABLE_D3D9
+#endif
+
+#ifndef ANGLE_ENABLE_D3D11
+#define ANGLE_ENABLE_D3D11
+#endif
+
+#include <d3d11.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include "com_utils.h"
+#include "OSWindow.h"
+#include "test_utils/ANGLETest.h"
+
+using namespace angle;
+
+typedef EGLBoolean(EGLAPIENTRYP PFNEGLGETSYNCVALUESCHROMIUMPROC)(EGLDisplay dpy,
+ EGLSurface surface,
+ EGLuint64KHR *ust,
+ EGLuint64KHR *msc,
+ EGLuint64KHR *sbc);
+
+class EGLSyncControlTest : public testing::Test
+{
+ protected:
+ EGLSyncControlTest() {}
+
+ void SetUp() override
+ {
+ mD3D11Module = LoadLibrary(TEXT("d3d11.dll"));
+ if (mD3D11Module == nullptr)
+ {
+ std::cout << "Unable to LoadLibrary D3D11" << std::endl;
+ return;
+ }
+
+ mD3D11CreateDevice = reinterpret_cast<PFN_D3D11_CREATE_DEVICE>(
+ GetProcAddress(mD3D11Module, "D3D11CreateDevice"));
+ if (mD3D11CreateDevice == nullptr)
+ {
+ std::cout << "Could not retrieve D3D11CreateDevice from d3d11.dll" << std::endl;
+ return;
+ }
+
+ mD3D11Available = true;
+
+ const char *extensionString =
+ static_cast<const char *>(eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS));
+ if (strstr(extensionString, "EGL_ANGLE_device_creation"))
+ {
+ if (strstr(extensionString, "EGL_ANGLE_device_creation_d3d11"))
+ {
+ mDeviceCreationD3D11ExtAvailable = true;
+ }
+ }
+
+ eglGetSyncValuesCHROMIUM = reinterpret_cast<PFNEGLGETSYNCVALUESCHROMIUMPROC>(
+ eglGetProcAddress("eglGetSyncValuesCHROMIUM"));
+ }
+
+ void TearDown() override
+ {
+ SafeRelease(mDevice);
+ SafeRelease(mDeviceContext);
+
+ SafeDelete(mOSWindow);
+
+ if (mSurface != EGL_NO_SURFACE)
+ {
+ eglDestroySurface(mDisplay, mSurface);
+ mSurface = EGL_NO_SURFACE;
+ }
+
+ if (mContext != EGL_NO_CONTEXT)
+ {
+ eglDestroyContext(mDisplay, mContext);
+ mContext = EGL_NO_CONTEXT;
+ }
+
+ if (mDisplay != EGL_NO_DISPLAY)
+ {
+ eglTerminate(mDisplay);
+ mDisplay = EGL_NO_DISPLAY;
+ }
+ }
+
+ void CreateD3D11Device()
+ {
+ ASSERT_TRUE(mD3D11Available);
+ ASSERT_EQ(nullptr, mDevice); // The device shouldn't be created twice
+
+ HRESULT hr =
+ mD3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, 0, 0, nullptr, 0,
+ D3D11_SDK_VERSION, &mDevice, &mFeatureLevel, &mDeviceContext);
+
+ ASSERT_TRUE(SUCCEEDED(hr));
+ }
+
+ void InitializeDisplay()
+ {
+ EGLint displayAttribs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE,
+ EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+ EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE,
+ EGL_DONT_CARE,
+ EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE,
+ EGL_DONT_CARE,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE,
+ EGL_NONE};
+
+ // Create an OS Window
+ mOSWindow = CreateOSWindow();
+ mOSWindow->initialize("EGLSyncControlTest", 64, 64);
+ mOSWindow->setVisible(true);
+
+ // Create an EGLDisplay using the EGLDevice
+ mDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE,
+ reinterpret_cast<void *>(mOSWindow->getNativeDisplay()),
+ displayAttribs);
+ ASSERT_TRUE(mDisplay != EGL_NO_DISPLAY);
+
+ EGLint majorVersion, minorVersion;
+ ASSERT_TRUE(eglInitialize(mDisplay, &majorVersion, &minorVersion) == EGL_TRUE);
+ }
+
+ void CreateWindowSurface()
+ {
+ eglBindAPI(EGL_OPENGL_ES_API);
+ ASSERT_EGL_SUCCESS();
+
+ // Choose a config
+ const EGLint configAttributes[] = {EGL_NONE};
+
+ EGLint configCount = 0;
+ ASSERT_EGL_TRUE(eglChooseConfig(mDisplay, configAttributes, &mConfig, 1, &configCount));
+
+ const EGLint surfaceAttributes[] = {EGL_DIRECT_COMPOSITION_ANGLE, EGL_TRUE, EGL_NONE};
+
+ // Create window surface
+ mSurface = eglCreateWindowSurface(mDisplay, mConfig, mOSWindow->getNativeWindow(),
+ surfaceAttributes);
+ if (mSurface == nullptr)
+ {
+ std::cout << "Unable to create window surface with Direct Composition" << std::endl;
+ return;
+ }
+
+ mDirectCompositionSurfaceAvailable = true;
+
+ // Create EGL context
+ EGLint contextAttibutes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
+
+ mContext = eglCreateContext(mDisplay, mConfig, nullptr, contextAttibutes);
+ ASSERT_EGL_SUCCESS();
+
+ // Make the surface current
+ eglMakeCurrent(mDisplay, mSurface, mSurface, mContext);
+ ASSERT_EGL_SUCCESS();
+ }
+
+ bool mD3D11Available = false;
+ HMODULE mD3D11Module = nullptr;
+ PFN_D3D11_CREATE_DEVICE mD3D11CreateDevice = nullptr;
+
+ ID3D11Device *mDevice = nullptr;
+ ID3D11DeviceContext *mDeviceContext = nullptr;
+ D3D_FEATURE_LEVEL mFeatureLevel;
+
+ bool mDeviceCreationD3D11ExtAvailable = false;
+
+ bool mDirectCompositionSurfaceAvailable = false;
+
+ OSWindow *mOSWindow = nullptr;
+
+ EGLDisplay mDisplay = EGL_NO_DISPLAY;
+ EGLSurface mSurface = EGL_NO_SURFACE;
+ EGLContext mContext = EGL_NO_CONTEXT;
+ EGLConfig mConfig = 0;
+ PFNEGLGETSYNCVALUESCHROMIUMPROC eglGetSyncValuesCHROMIUM = nullptr;
+};
+
+// Basic test for eglGetSyncValuesCHROMIUM extension. Verifies that eglGetSyncValuesCHROMIUM
+// can be called on DX11 with direct composition and that it returns reasonable enough values.
+TEST_F(EGLSyncControlTest, SyncValuesTest)
+{
+ static const DWORD kPollInterval = 10;
+ static const int kNumPollIterations = 100;
+
+ if (!mD3D11Available)
+ {
+ std::cout << "D3D11 not available, skipping test" << std::endl;
+ return;
+ }
+
+ CreateD3D11Device();
+ InitializeDisplay();
+ CreateWindowSurface();
+
+ if (!mDirectCompositionSurfaceAvailable)
+ {
+ std::cout << "Direct Composition surface not available, skipping test" << std::endl;
+ return;
+ }
+
+ const char *extensionString =
+ static_cast<const char *>(eglQueryString(mDisplay, EGL_EXTENSIONS));
+ ASSERT_TRUE(strstr(extensionString, "EGL_CHROMIUM_sync_control"));
+
+ EGLuint64KHR ust = 0, msc = 0, sbc = 0;
+ // It appears there is a race condition so the very first call to eglGetSyncValuesCHROMIUM
+ // can fail within D3D with DXGI_ERROR_FRAME_STATISTICS_DISJOINT.
+ // Should that be handled inside eglGetSyncValuesCHROMIUM?
+ eglGetSyncValuesCHROMIUM(mDisplay, mSurface, &ust, &msc, &sbc);
+
+ ASSERT_EGL_TRUE(eglGetSyncValuesCHROMIUM(mDisplay, mSurface, &ust, &msc, &sbc));
+ // Initial msc and sbc value should be true. Initial ust value is unspecified.
+ ASSERT_EQ(0ull, msc);
+ ASSERT_EQ(0ull, sbc);
+
+ // Perform some very basic rendering.
+ glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ ASSERT_GL_NO_ERROR();
+
+ ASSERT_EGL_TRUE(eglSwapBuffers(mDisplay, mSurface));
+
+ // Poll until sbc value increases. Normally it should change within 16-17 ms.
+ for (int i = 0; i < kNumPollIterations; i++)
+ {
+ ::Sleep(kPollInterval);
+ ASSERT_EGL_TRUE(eglGetSyncValuesCHROMIUM(mDisplay, mSurface, &ust, &msc, &sbc));
+ if (sbc > 0)
+ break;
+ }
+
+ // sbc should change to 1. msc and ust to some non-zero values.
+ ASSERT_EQ(1ull, sbc);
+ ASSERT_GT(ust, 0ull);
+ ASSERT_GT(msc, 0ull);
+
+ // Perform more rendering.
+ glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ ASSERT_GL_NO_ERROR();
+
+ ASSERT_EGL_TRUE(eglSwapBuffers(mDisplay, mSurface));
+
+ // Poll until sbc value increases. Normally it should change within 16-17 ms.
+ EGLuint64KHR ust2 = 0, msc2 = 0, sbc2 = 0;
+ for (int i = 0; i < kNumPollIterations; i++)
+ {
+ ::Sleep(kPollInterval);
+ ASSERT_EGL_TRUE(eglGetSyncValuesCHROMIUM(mDisplay, mSurface, &ust2, &msc2, &sbc2));
+ if (sbc2 > sbc)
+ break;
+ }
+
+ // sbc2 should be 2. msc2 and ust2 should be greater than previous msc and ust values.
+ ASSERT_EQ(2ull, sbc2);
+ ASSERT_GT((ust2 - ust), 0ull);
+ ASSERT_GT((msc2 - msc), 0ull);
+}