1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2016 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker
7*8975f5c5SAndroid Build Coastguard Worker // EGLSyncControlTest.cpp:
8*8975f5c5SAndroid Build Coastguard Worker // Tests pertaining to eglGetSyncValuesCHROMIUM.
9*8975f5c5SAndroid Build Coastguard Worker
10*8975f5c5SAndroid Build Coastguard Worker #include <d3d11.h>
11*8975f5c5SAndroid Build Coastguard Worker
12*8975f5c5SAndroid Build Coastguard Worker #include "test_utils/ANGLETest.h"
13*8975f5c5SAndroid Build Coastguard Worker #include "util/OSWindow.h"
14*8975f5c5SAndroid Build Coastguard Worker #include "util/com_utils.h"
15*8975f5c5SAndroid Build Coastguard Worker
16*8975f5c5SAndroid Build Coastguard Worker using namespace angle;
17*8975f5c5SAndroid Build Coastguard Worker
18*8975f5c5SAndroid Build Coastguard Worker class EGLSyncControlTest : public testing::Test
19*8975f5c5SAndroid Build Coastguard Worker {
20*8975f5c5SAndroid Build Coastguard Worker protected:
EGLSyncControlTest()21*8975f5c5SAndroid Build Coastguard Worker EGLSyncControlTest() {}
22*8975f5c5SAndroid Build Coastguard Worker
SetUp()23*8975f5c5SAndroid Build Coastguard Worker void SetUp() override
24*8975f5c5SAndroid Build Coastguard Worker {
25*8975f5c5SAndroid Build Coastguard Worker mD3D11Module = LoadLibrary(TEXT("d3d11.dll"));
26*8975f5c5SAndroid Build Coastguard Worker if (mD3D11Module == nullptr)
27*8975f5c5SAndroid Build Coastguard Worker {
28*8975f5c5SAndroid Build Coastguard Worker std::cout << "Unable to LoadLibrary D3D11" << std::endl;
29*8975f5c5SAndroid Build Coastguard Worker return;
30*8975f5c5SAndroid Build Coastguard Worker }
31*8975f5c5SAndroid Build Coastguard Worker
32*8975f5c5SAndroid Build Coastguard Worker mD3D11CreateDevice = reinterpret_cast<PFN_D3D11_CREATE_DEVICE>(
33*8975f5c5SAndroid Build Coastguard Worker GetProcAddress(mD3D11Module, "D3D11CreateDevice"));
34*8975f5c5SAndroid Build Coastguard Worker if (mD3D11CreateDevice == nullptr)
35*8975f5c5SAndroid Build Coastguard Worker {
36*8975f5c5SAndroid Build Coastguard Worker std::cout << "Could not retrieve D3D11CreateDevice from d3d11.dll" << std::endl;
37*8975f5c5SAndroid Build Coastguard Worker return;
38*8975f5c5SAndroid Build Coastguard Worker }
39*8975f5c5SAndroid Build Coastguard Worker
40*8975f5c5SAndroid Build Coastguard Worker mD3D11Available = true;
41*8975f5c5SAndroid Build Coastguard Worker
42*8975f5c5SAndroid Build Coastguard Worker const char *extensionString =
43*8975f5c5SAndroid Build Coastguard Worker static_cast<const char *>(eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS));
44*8975f5c5SAndroid Build Coastguard Worker if (strstr(extensionString, "EGL_ANGLE_device_creation"))
45*8975f5c5SAndroid Build Coastguard Worker {
46*8975f5c5SAndroid Build Coastguard Worker if (strstr(extensionString, "EGL_ANGLE_device_creation_d3d11"))
47*8975f5c5SAndroid Build Coastguard Worker {
48*8975f5c5SAndroid Build Coastguard Worker mDeviceCreationD3D11ExtAvailable = true;
49*8975f5c5SAndroid Build Coastguard Worker }
50*8975f5c5SAndroid Build Coastguard Worker }
51*8975f5c5SAndroid Build Coastguard Worker }
52*8975f5c5SAndroid Build Coastguard Worker
TearDown()53*8975f5c5SAndroid Build Coastguard Worker void TearDown() override
54*8975f5c5SAndroid Build Coastguard Worker {
55*8975f5c5SAndroid Build Coastguard Worker SafeRelease(mDevice);
56*8975f5c5SAndroid Build Coastguard Worker SafeRelease(mDeviceContext);
57*8975f5c5SAndroid Build Coastguard Worker
58*8975f5c5SAndroid Build Coastguard Worker OSWindow::Delete(&mOSWindow);
59*8975f5c5SAndroid Build Coastguard Worker
60*8975f5c5SAndroid Build Coastguard Worker if (mSurface != EGL_NO_SURFACE)
61*8975f5c5SAndroid Build Coastguard Worker {
62*8975f5c5SAndroid Build Coastguard Worker eglDestroySurface(mDisplay, mSurface);
63*8975f5c5SAndroid Build Coastguard Worker mSurface = EGL_NO_SURFACE;
64*8975f5c5SAndroid Build Coastguard Worker }
65*8975f5c5SAndroid Build Coastguard Worker
66*8975f5c5SAndroid Build Coastguard Worker if (mContext != EGL_NO_CONTEXT)
67*8975f5c5SAndroid Build Coastguard Worker {
68*8975f5c5SAndroid Build Coastguard Worker eglDestroyContext(mDisplay, mContext);
69*8975f5c5SAndroid Build Coastguard Worker mContext = EGL_NO_CONTEXT;
70*8975f5c5SAndroid Build Coastguard Worker }
71*8975f5c5SAndroid Build Coastguard Worker
72*8975f5c5SAndroid Build Coastguard Worker if (mDisplay != EGL_NO_DISPLAY)
73*8975f5c5SAndroid Build Coastguard Worker {
74*8975f5c5SAndroid Build Coastguard Worker eglTerminate(mDisplay);
75*8975f5c5SAndroid Build Coastguard Worker mDisplay = EGL_NO_DISPLAY;
76*8975f5c5SAndroid Build Coastguard Worker }
77*8975f5c5SAndroid Build Coastguard Worker }
78*8975f5c5SAndroid Build Coastguard Worker
CreateD3D11Device()79*8975f5c5SAndroid Build Coastguard Worker void CreateD3D11Device()
80*8975f5c5SAndroid Build Coastguard Worker {
81*8975f5c5SAndroid Build Coastguard Worker ASSERT_TRUE(mD3D11Available);
82*8975f5c5SAndroid Build Coastguard Worker ASSERT_EQ(nullptr, mDevice); // The device shouldn't be created twice
83*8975f5c5SAndroid Build Coastguard Worker
84*8975f5c5SAndroid Build Coastguard Worker HRESULT hr =
85*8975f5c5SAndroid Build Coastguard Worker mD3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, 0, 0, nullptr, 0,
86*8975f5c5SAndroid Build Coastguard Worker D3D11_SDK_VERSION, &mDevice, &mFeatureLevel, &mDeviceContext);
87*8975f5c5SAndroid Build Coastguard Worker
88*8975f5c5SAndroid Build Coastguard Worker ASSERT_TRUE(SUCCEEDED(hr));
89*8975f5c5SAndroid Build Coastguard Worker }
90*8975f5c5SAndroid Build Coastguard Worker
InitializeDisplay()91*8975f5c5SAndroid Build Coastguard Worker void InitializeDisplay()
92*8975f5c5SAndroid Build Coastguard Worker {
93*8975f5c5SAndroid Build Coastguard Worker EGLint displayAttribs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE,
94*8975f5c5SAndroid Build Coastguard Worker EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
95*8975f5c5SAndroid Build Coastguard Worker EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE,
96*8975f5c5SAndroid Build Coastguard Worker EGL_DONT_CARE,
97*8975f5c5SAndroid Build Coastguard Worker EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE,
98*8975f5c5SAndroid Build Coastguard Worker EGL_DONT_CARE,
99*8975f5c5SAndroid Build Coastguard Worker EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE,
100*8975f5c5SAndroid Build Coastguard Worker EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE,
101*8975f5c5SAndroid Build Coastguard Worker EGL_NONE};
102*8975f5c5SAndroid Build Coastguard Worker
103*8975f5c5SAndroid Build Coastguard Worker // Create an OS Window
104*8975f5c5SAndroid Build Coastguard Worker mOSWindow = OSWindow::New();
105*8975f5c5SAndroid Build Coastguard Worker mOSWindow->initialize("EGLSyncControlTest", 64, 64);
106*8975f5c5SAndroid Build Coastguard Worker mOSWindow->setVisible(true);
107*8975f5c5SAndroid Build Coastguard Worker
108*8975f5c5SAndroid Build Coastguard Worker // Create an EGLDisplay using the EGLDevice
109*8975f5c5SAndroid Build Coastguard Worker mDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE,
110*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<void *>(mOSWindow->getNativeDisplay()),
111*8975f5c5SAndroid Build Coastguard Worker displayAttribs);
112*8975f5c5SAndroid Build Coastguard Worker ASSERT_TRUE(mDisplay != EGL_NO_DISPLAY);
113*8975f5c5SAndroid Build Coastguard Worker
114*8975f5c5SAndroid Build Coastguard Worker EGLint majorVersion, minorVersion;
115*8975f5c5SAndroid Build Coastguard Worker ASSERT_TRUE(eglInitialize(mDisplay, &majorVersion, &minorVersion) == EGL_TRUE);
116*8975f5c5SAndroid Build Coastguard Worker }
117*8975f5c5SAndroid Build Coastguard Worker
CreateWindowSurface()118*8975f5c5SAndroid Build Coastguard Worker void CreateWindowSurface()
119*8975f5c5SAndroid Build Coastguard Worker {
120*8975f5c5SAndroid Build Coastguard Worker eglBindAPI(EGL_OPENGL_ES_API);
121*8975f5c5SAndroid Build Coastguard Worker ASSERT_EGL_SUCCESS();
122*8975f5c5SAndroid Build Coastguard Worker
123*8975f5c5SAndroid Build Coastguard Worker // Choose a config
124*8975f5c5SAndroid Build Coastguard Worker const EGLint configAttributes[] = {EGL_NONE};
125*8975f5c5SAndroid Build Coastguard Worker
126*8975f5c5SAndroid Build Coastguard Worker EGLint configCount = 0;
127*8975f5c5SAndroid Build Coastguard Worker ASSERT_EGL_TRUE(eglChooseConfig(mDisplay, configAttributes, &mConfig, 1, &configCount));
128*8975f5c5SAndroid Build Coastguard Worker
129*8975f5c5SAndroid Build Coastguard Worker const EGLint surfaceAttributes[] = {EGL_DIRECT_COMPOSITION_ANGLE, EGL_TRUE, EGL_NONE};
130*8975f5c5SAndroid Build Coastguard Worker
131*8975f5c5SAndroid Build Coastguard Worker // Create window surface
132*8975f5c5SAndroid Build Coastguard Worker mSurface = eglCreateWindowSurface(mDisplay, mConfig, mOSWindow->getNativeWindow(),
133*8975f5c5SAndroid Build Coastguard Worker surfaceAttributes);
134*8975f5c5SAndroid Build Coastguard Worker if (mSurface == nullptr)
135*8975f5c5SAndroid Build Coastguard Worker {
136*8975f5c5SAndroid Build Coastguard Worker std::cout << "Unable to create window surface with Direct Composition" << std::endl;
137*8975f5c5SAndroid Build Coastguard Worker return;
138*8975f5c5SAndroid Build Coastguard Worker }
139*8975f5c5SAndroid Build Coastguard Worker
140*8975f5c5SAndroid Build Coastguard Worker mDirectCompositionSurfaceAvailable = true;
141*8975f5c5SAndroid Build Coastguard Worker
142*8975f5c5SAndroid Build Coastguard Worker // Create EGL context
143*8975f5c5SAndroid Build Coastguard Worker EGLint contextAttibutes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
144*8975f5c5SAndroid Build Coastguard Worker
145*8975f5c5SAndroid Build Coastguard Worker mContext = eglCreateContext(mDisplay, mConfig, nullptr, contextAttibutes);
146*8975f5c5SAndroid Build Coastguard Worker ASSERT_EGL_SUCCESS();
147*8975f5c5SAndroid Build Coastguard Worker
148*8975f5c5SAndroid Build Coastguard Worker // Make the surface current
149*8975f5c5SAndroid Build Coastguard Worker eglMakeCurrent(mDisplay, mSurface, mSurface, mContext);
150*8975f5c5SAndroid Build Coastguard Worker ASSERT_EGL_SUCCESS();
151*8975f5c5SAndroid Build Coastguard Worker }
152*8975f5c5SAndroid Build Coastguard Worker
153*8975f5c5SAndroid Build Coastguard Worker bool mD3D11Available = false;
154*8975f5c5SAndroid Build Coastguard Worker HMODULE mD3D11Module = nullptr;
155*8975f5c5SAndroid Build Coastguard Worker PFN_D3D11_CREATE_DEVICE mD3D11CreateDevice = nullptr;
156*8975f5c5SAndroid Build Coastguard Worker
157*8975f5c5SAndroid Build Coastguard Worker ID3D11Device *mDevice = nullptr;
158*8975f5c5SAndroid Build Coastguard Worker ID3D11DeviceContext *mDeviceContext = nullptr;
159*8975f5c5SAndroid Build Coastguard Worker D3D_FEATURE_LEVEL mFeatureLevel;
160*8975f5c5SAndroid Build Coastguard Worker
161*8975f5c5SAndroid Build Coastguard Worker bool mDeviceCreationD3D11ExtAvailable = false;
162*8975f5c5SAndroid Build Coastguard Worker
163*8975f5c5SAndroid Build Coastguard Worker bool mDirectCompositionSurfaceAvailable = false;
164*8975f5c5SAndroid Build Coastguard Worker
165*8975f5c5SAndroid Build Coastguard Worker OSWindow *mOSWindow = nullptr;
166*8975f5c5SAndroid Build Coastguard Worker
167*8975f5c5SAndroid Build Coastguard Worker EGLDisplay mDisplay = EGL_NO_DISPLAY;
168*8975f5c5SAndroid Build Coastguard Worker EGLSurface mSurface = EGL_NO_SURFACE;
169*8975f5c5SAndroid Build Coastguard Worker EGLContext mContext = EGL_NO_CONTEXT;
170*8975f5c5SAndroid Build Coastguard Worker EGLConfig mConfig = 0;
171*8975f5c5SAndroid Build Coastguard Worker };
172*8975f5c5SAndroid Build Coastguard Worker
173*8975f5c5SAndroid Build Coastguard Worker // Basic test for eglGetSyncValuesCHROMIUM extension. Verifies that eglGetSyncValuesCHROMIUM
174*8975f5c5SAndroid Build Coastguard Worker // can be called on DX11 with direct composition and that it returns reasonable enough values.
TEST_F(EGLSyncControlTest,DISABLED_SyncValuesTest)175*8975f5c5SAndroid Build Coastguard Worker TEST_F(EGLSyncControlTest, DISABLED_SyncValuesTest)
176*8975f5c5SAndroid Build Coastguard Worker {
177*8975f5c5SAndroid Build Coastguard Worker static const DWORD kPollInterval = 10;
178*8975f5c5SAndroid Build Coastguard Worker static const int kNumPollIterations = 100;
179*8975f5c5SAndroid Build Coastguard Worker
180*8975f5c5SAndroid Build Coastguard Worker if (!mD3D11Available)
181*8975f5c5SAndroid Build Coastguard Worker {
182*8975f5c5SAndroid Build Coastguard Worker std::cout << "D3D11 not available, skipping test" << std::endl;
183*8975f5c5SAndroid Build Coastguard Worker return;
184*8975f5c5SAndroid Build Coastguard Worker }
185*8975f5c5SAndroid Build Coastguard Worker
186*8975f5c5SAndroid Build Coastguard Worker CreateD3D11Device();
187*8975f5c5SAndroid Build Coastguard Worker InitializeDisplay();
188*8975f5c5SAndroid Build Coastguard Worker CreateWindowSurface();
189*8975f5c5SAndroid Build Coastguard Worker
190*8975f5c5SAndroid Build Coastguard Worker if (!mDirectCompositionSurfaceAvailable)
191*8975f5c5SAndroid Build Coastguard Worker {
192*8975f5c5SAndroid Build Coastguard Worker std::cout << "Direct Composition surface not available, skipping test" << std::endl;
193*8975f5c5SAndroid Build Coastguard Worker return;
194*8975f5c5SAndroid Build Coastguard Worker }
195*8975f5c5SAndroid Build Coastguard Worker
196*8975f5c5SAndroid Build Coastguard Worker const char *extensionString =
197*8975f5c5SAndroid Build Coastguard Worker static_cast<const char *>(eglQueryString(mDisplay, EGL_EXTENSIONS));
198*8975f5c5SAndroid Build Coastguard Worker ASSERT_TRUE(strstr(extensionString, "EGL_CHROMIUM_sync_control"));
199*8975f5c5SAndroid Build Coastguard Worker
200*8975f5c5SAndroid Build Coastguard Worker EGLuint64KHR ust = 0, msc = 0, sbc = 0;
201*8975f5c5SAndroid Build Coastguard Worker // It appears there is a race condition so the very first call to eglGetSyncValuesCHROMIUM
202*8975f5c5SAndroid Build Coastguard Worker // can fail within D3D with DXGI_ERROR_FRAME_STATISTICS_DISJOINT.
203*8975f5c5SAndroid Build Coastguard Worker // Should that be handled inside eglGetSyncValuesCHROMIUM?
204*8975f5c5SAndroid Build Coastguard Worker eglGetSyncValuesCHROMIUM(mDisplay, mSurface, &ust, &msc, &sbc);
205*8975f5c5SAndroid Build Coastguard Worker
206*8975f5c5SAndroid Build Coastguard Worker ASSERT_EGL_TRUE(eglGetSyncValuesCHROMIUM(mDisplay, mSurface, &ust, &msc, &sbc));
207*8975f5c5SAndroid Build Coastguard Worker // Initial msc and sbc value should be true. Initial ust value is unspecified.
208*8975f5c5SAndroid Build Coastguard Worker ASSERT_EQ(0ull, msc);
209*8975f5c5SAndroid Build Coastguard Worker ASSERT_EQ(0ull, sbc);
210*8975f5c5SAndroid Build Coastguard Worker
211*8975f5c5SAndroid Build Coastguard Worker // Perform some very basic rendering.
212*8975f5c5SAndroid Build Coastguard Worker glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
213*8975f5c5SAndroid Build Coastguard Worker glClear(GL_COLOR_BUFFER_BIT);
214*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
215*8975f5c5SAndroid Build Coastguard Worker
216*8975f5c5SAndroid Build Coastguard Worker ASSERT_EGL_TRUE(eglSwapBuffers(mDisplay, mSurface));
217*8975f5c5SAndroid Build Coastguard Worker
218*8975f5c5SAndroid Build Coastguard Worker // Poll until sbc value increases. Normally it should change within 16-17 ms.
219*8975f5c5SAndroid Build Coastguard Worker for (int i = 0; i < kNumPollIterations; i++)
220*8975f5c5SAndroid Build Coastguard Worker {
221*8975f5c5SAndroid Build Coastguard Worker ::Sleep(kPollInterval);
222*8975f5c5SAndroid Build Coastguard Worker ASSERT_EGL_TRUE(eglGetSyncValuesCHROMIUM(mDisplay, mSurface, &ust, &msc, &sbc));
223*8975f5c5SAndroid Build Coastguard Worker if (sbc > 0)
224*8975f5c5SAndroid Build Coastguard Worker break;
225*8975f5c5SAndroid Build Coastguard Worker }
226*8975f5c5SAndroid Build Coastguard Worker
227*8975f5c5SAndroid Build Coastguard Worker // sbc should change to 1. msc and ust to some non-zero values.
228*8975f5c5SAndroid Build Coastguard Worker ASSERT_EQ(1ull, sbc);
229*8975f5c5SAndroid Build Coastguard Worker ASSERT_GT(ust, 0ull);
230*8975f5c5SAndroid Build Coastguard Worker ASSERT_GT(msc, 0ull);
231*8975f5c5SAndroid Build Coastguard Worker
232*8975f5c5SAndroid Build Coastguard Worker // Perform more rendering.
233*8975f5c5SAndroid Build Coastguard Worker glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
234*8975f5c5SAndroid Build Coastguard Worker glClear(GL_COLOR_BUFFER_BIT);
235*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
236*8975f5c5SAndroid Build Coastguard Worker
237*8975f5c5SAndroid Build Coastguard Worker ASSERT_EGL_TRUE(eglSwapBuffers(mDisplay, mSurface));
238*8975f5c5SAndroid Build Coastguard Worker
239*8975f5c5SAndroid Build Coastguard Worker // Poll until sbc value increases. Normally it should change within 16-17 ms.
240*8975f5c5SAndroid Build Coastguard Worker EGLuint64KHR ust2 = 0, msc2 = 0, sbc2 = 0;
241*8975f5c5SAndroid Build Coastguard Worker for (int i = 0; i < kNumPollIterations; i++)
242*8975f5c5SAndroid Build Coastguard Worker {
243*8975f5c5SAndroid Build Coastguard Worker ::Sleep(kPollInterval);
244*8975f5c5SAndroid Build Coastguard Worker ASSERT_EGL_TRUE(eglGetSyncValuesCHROMIUM(mDisplay, mSurface, &ust2, &msc2, &sbc2));
245*8975f5c5SAndroid Build Coastguard Worker if (sbc2 > sbc)
246*8975f5c5SAndroid Build Coastguard Worker break;
247*8975f5c5SAndroid Build Coastguard Worker }
248*8975f5c5SAndroid Build Coastguard Worker
249*8975f5c5SAndroid Build Coastguard Worker // sbc2 should be 2. msc2 and ust2 should be greater than previous msc and ust values.
250*8975f5c5SAndroid Build Coastguard Worker ASSERT_EQ(2ull, sbc2);
251*8975f5c5SAndroid Build Coastguard Worker ASSERT_GT(ust2, ust);
252*8975f5c5SAndroid Build Coastguard Worker ASSERT_GT(msc2, msc);
253*8975f5c5SAndroid Build Coastguard Worker }
254