xref: /aosp_15_r20/external/angle/src/tests/egl_tests/EGLSyncControlTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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