Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/angle
Path: blob/main_old/src/tests/egl_tests/EGLDirectCompositionTest.cpp
1693 views
1
//
2
// Copyright 2018 The ANGLE Project Authors. All rights reserved.
3
// Use of this source code is governed by a BSD-style license that can be
4
// found in the LICENSE file.
5
//
6
7
// EGLDirectCompositionTest.cpp:
8
// Tests pertaining to DirectComposition and WindowsUIComposition.
9
10
#ifdef ANGLE_ENABLE_D3D11_COMPOSITOR_NATIVE_WINDOW
11
12
# include <d3d11.h>
13
# include "test_utils/ANGLETest.h"
14
15
# include <DispatcherQueue.h>
16
# include <VersionHelpers.h>
17
# include <Windows.Foundation.h>
18
# include <windows.ui.composition.Desktop.h>
19
# include <windows.ui.composition.h>
20
# include <windows.ui.composition.interop.h>
21
# include <wrl.h>
22
# include <memory>
23
24
# include "libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.h"
25
# include "util/OSWindow.h"
26
# include "util/com_utils.h"
27
# include "util/test_utils.h"
28
29
using namespace angle;
30
using namespace ABI::Windows::System;
31
using namespace ABI::Windows::UI::Composition;
32
using namespace ABI::Windows::UI::Composition::Desktop;
33
using namespace ABI::Windows::Foundation;
34
using namespace Microsoft::WRL;
35
using namespace Microsoft::WRL::Wrappers;
36
37
const int WINDOWWIDTH = 200, WINDOWHEIGHT = 200;
38
39
class EGLDirectCompositionTest : public ANGLETest
40
{
41
protected:
42
EGLDirectCompositionTest() : mOSWindow(nullptr) {}
43
44
void testSetUp() override
45
{
46
if (!mRoHelper.SupportedWindowsRelease())
47
{
48
return;
49
}
50
51
// Create an OS Window
52
mOSWindow = OSWindow::New();
53
54
mOSWindow->initialize("EGLDirectCompositionTest", WINDOWWIDTH, WINDOWHEIGHT);
55
auto nativeWindow = mOSWindow->getNativeWindow();
56
setWindowVisible(mOSWindow, true);
57
58
// Create DispatcherQueue for window to process compositor callbacks
59
CreateDispatcherQueue(mDispatcherController);
60
61
HSTRING act;
62
HSTRING_HEADER header;
63
64
auto hr = mRoHelper.GetStringReference(RuntimeClass_Windows_UI_Composition_Compositor, &act,
65
&header);
66
67
ASSERT_TRUE(SUCCEEDED(hr));
68
69
void *fac = nullptr;
70
hr = mRoHelper.GetActivationFactory(act, __uuidof(IActivationFactory), &fac);
71
ASSERT_TRUE(SUCCEEDED(hr));
72
73
ComPtr<IActivationFactory> compositorFactory;
74
75
compositorFactory.Attach((IActivationFactory *)fac);
76
77
hr = compositorFactory->ActivateInstance(&mCompositor);
78
ASSERT_TRUE(SUCCEEDED(hr));
79
80
// Create a DesktopWindowTarget against native window (HWND)
81
CreateDesktopWindowTarget(mCompositor, static_cast<HWND>(nativeWindow), mDesktopTarget);
82
83
ASSERT_TRUE(SUCCEEDED(mCompositor->CreateSpriteVisual(mAngleHost.GetAddressOf())));
84
85
ComPtr<IVisual> angleVis;
86
ASSERT_TRUE(SUCCEEDED(mAngleHost.As(&angleVis)));
87
88
ASSERT_TRUE(SUCCEEDED(angleVis->put_Size(
89
{static_cast<FLOAT>(WINDOWWIDTH), static_cast<FLOAT>(WINDOWHEIGHT)})));
90
91
ASSERT_TRUE(SUCCEEDED(angleVis->put_Offset({0, 0, 0})));
92
93
ComPtr<ICompositionTarget> compTarget;
94
ASSERT_TRUE(SUCCEEDED(mDesktopTarget.As(&compTarget)));
95
ASSERT_TRUE(SUCCEEDED(compTarget->put_Root(angleVis.Get())));
96
97
Init();
98
}
99
100
void CreateDispatcherQueue(ComPtr<IDispatcherQueueController> &controller)
101
{
102
DispatcherQueueOptions options{sizeof(DispatcherQueueOptions), DQTYPE_THREAD_CURRENT,
103
DQTAT_COM_STA};
104
105
auto hr = mRoHelper.CreateDispatcherQueueController(options, controller.GetAddressOf());
106
107
ASSERT_TRUE(SUCCEEDED(hr));
108
}
109
110
void CreateDesktopWindowTarget(ComPtr<ICompositor> const &compositor,
111
const HWND window,
112
ComPtr<IDesktopWindowTarget> &target)
113
{
114
namespace abi = ABI::Windows::UI::Composition::Desktop;
115
116
ComPtr<ICompositorDesktopInterop> interop;
117
ASSERT_TRUE(SUCCEEDED(compositor.As(&interop)));
118
119
ASSERT_TRUE(SUCCEEDED(interop->CreateDesktopWindowTarget(
120
window, true, reinterpret_cast<abi::IDesktopWindowTarget **>(target.GetAddressOf()))));
121
}
122
123
void Init()
124
{
125
if (!mRoHelper.SupportedWindowsRelease())
126
{
127
return;
128
}
129
130
DPI_AWARENESS_CONTEXT
131
WINAPI
132
SetThreadDpiAwarenessContext(_In_ DPI_AWARENESS_CONTEXT dpiContext);
133
134
auto userModule = LoadLibraryA("user32.dll");
135
136
if (userModule == nullptr)
137
{
138
return;
139
}
140
141
auto temp = GetProcAddress(userModule, "SetThreadDpiAwarenessContext");
142
143
mFpSetThreadDpiAwarenessContext = reinterpret_cast<_SetThreadDpiAwarenessContext *>(temp);
144
145
const EGLint configAttributes[] = {
146
EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8,
147
EGL_DEPTH_SIZE, 8, EGL_STENCIL_SIZE, 8, EGL_NONE};
148
149
const EGLint defaultDisplayAttributes[] = {
150
EGL_PLATFORM_ANGLE_TYPE_ANGLE,
151
EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
152
EGL_NONE,
153
};
154
155
PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT =
156
reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(
157
eglGetProcAddress("eglGetPlatformDisplayEXT"));
158
ASSERT_TRUE(eglGetPlatformDisplayEXT != nullptr);
159
160
mEglDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE,
161
reinterpret_cast<void *>(EGL_DEFAULT_DISPLAY),
162
defaultDisplayAttributes);
163
ASSERT_TRUE(mEglDisplay != EGL_NO_DISPLAY);
164
165
ASSERT_EGL_TRUE(eglInitialize(mEglDisplay, nullptr, nullptr));
166
167
EGLint nConfigs = 0;
168
169
ASSERT_EGL_TRUE(eglGetConfigs(mEglDisplay, nullptr, 0, &nConfigs));
170
ASSERT_TRUE(nConfigs != 0);
171
172
ASSERT_EGL_TRUE(eglChooseConfig(mEglDisplay, configAttributes, &mEglConfig, 1, &nConfigs));
173
}
174
175
void CreateSurface(ComPtr<ABI::Windows::UI::Composition::ISpriteVisual> visual,
176
EGLSurface &surface)
177
{
178
auto displayExtensions = eglQueryString(mEglDisplay, EGL_EXTENSIONS);
179
180
// Check that the EGL_ANGLE_windows_ui_composition display extension is available
181
ASSERT_TRUE(strstr(displayExtensions, "EGL_ANGLE_windows_ui_composition") != nullptr);
182
183
const EGLint contextAttributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
184
185
// Use a spritevisual as the nativewindowtype
186
surface =
187
eglCreateWindowSurface(mEglDisplay, mEglConfig,
188
static_cast<EGLNativeWindowType>((void *)visual.Get()), nullptr);
189
ASSERT_TRUE(surface != EGL_NO_SURFACE);
190
191
mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT, contextAttributes);
192
ASSERT_TRUE(mEglContext != EGL_NO_CONTEXT);
193
194
ASSERT_TRUE(eglMakeCurrent(mEglDisplay, surface, surface, mEglContext) != EGL_FALSE);
195
}
196
197
void testTearDown() override
198
{
199
if (!mRoHelper.SupportedWindowsRelease())
200
{
201
return;
202
}
203
if (mEglDisplay != EGL_NO_DISPLAY)
204
{
205
ASSERT_EGL_TRUE(eglTerminate(mEglDisplay));
206
mEglDisplay = EGL_NO_DISPLAY;
207
}
208
209
OSWindow::Delete(&mOSWindow);
210
}
211
212
OSWindow *mOSWindow;
213
ComPtr<ICompositor> mCompositor;
214
ComPtr<IDispatcherQueueController> mDispatcherController;
215
ComPtr<ICompositionColorBrush> mColorBrush;
216
ComPtr<IDesktopWindowTarget> mDesktopTarget;
217
ComPtr<ISpriteVisual> mAngleHost;
218
219
EGLDisplay mEglDisplay;
220
EGLContext mEglContext;
221
EGLConfig mEglConfig;
222
rx::RoHelper mRoHelper;
223
224
using _SetThreadDpiAwarenessContext =
225
DPI_AWARENESS_CONTEXT WINAPI(DPI_AWARENESS_CONTEXT dpiContext);
226
227
_SetThreadDpiAwarenessContext *mFpSetThreadDpiAwarenessContext;
228
};
229
230
// This tests that a surface created using a SpriteVisual as container has the expected dimensions
231
// which should match the dimensions of the SpriteVisual passed in
232
TEST_P(EGLDirectCompositionTest, SurfaceSizeFromSpriteSize)
233
{
234
// Only attempt this test when on Windows 10 1803+
235
ANGLE_SKIP_TEST_IF(!mRoHelper.SupportedWindowsRelease());
236
237
EGLSurface s{nullptr};
238
CreateSurface(mAngleHost, s);
239
240
EGLint surfacewidth = 0, surfaceheight = 0;
241
eglQuerySurface(mEglDisplay, s, EGL_WIDTH, &surfacewidth);
242
eglQuerySurface(mEglDisplay, s, EGL_HEIGHT, &surfaceheight);
243
244
ComPtr<IVisual> angleVis;
245
ASSERT_TRUE(SUCCEEDED(mAngleHost.As(&angleVis)));
246
247
ABI::Windows::Foundation::Numerics::Vector2 visualsize{0, 0};
248
249
ASSERT_TRUE(SUCCEEDED(angleVis->get_Size(&visualsize)));
250
251
ASSERT_TRUE(surfacewidth == static_cast<int>(visualsize.X));
252
ASSERT_TRUE(surfaceheight == static_cast<int>(visualsize.Y));
253
254
ASSERT_TRUE(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) !=
255
EGL_FALSE);
256
ASSERT_EGL_TRUE(eglDestroySurface(mEglDisplay, s));
257
ASSERT_EGL_TRUE(eglDestroyContext(mEglDisplay, mEglContext));
258
mEglContext = EGL_NO_CONTEXT;
259
}
260
261
// This tests that a WindowSurface can be created using a SpriteVisual as the containing window
262
// and that pixels can be successfully rendered into the resulting WindowSurface
263
TEST_P(EGLDirectCompositionTest, RenderSolidColor)
264
{
265
// Only attempt this test when on Windows 10 1803+
266
ANGLE_SKIP_TEST_IF(!mRoHelper.SupportedWindowsRelease());
267
268
// http://crbug.com/1063962
269
ANGLE_SKIP_TEST_IF(isD3D11Renderer() && IsIntel());
270
271
EGLSurface s{nullptr};
272
CreateSurface(mAngleHost, s);
273
274
glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
275
276
glViewport(0, 0, WINDOWWIDTH, WINDOWHEIGHT);
277
glClear(GL_COLOR_BUFFER_BIT);
278
279
ASSERT_EGL_TRUE(eglSwapBuffers(mEglDisplay, s));
280
281
// ensure user/DWM have a chance to paint the window and kick it to the top of the desktop
282
// zorder before we attempt to sample
283
angle::Sleep(200);
284
mOSWindow->messageLoop();
285
286
uint8_t *pixelBuffer = static_cast<uint8_t *>(malloc(WINDOWWIDTH * WINDOWHEIGHT * 4));
287
ZeroMemory(pixelBuffer, WINDOWWIDTH * WINDOWHEIGHT * 4);
288
289
// In order to accurately capture a bitmap, we need to temporarily shift into per-monitor DPI
290
// mode in order to get the window offset from desktop correct
291
auto previous = mFpSetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE);
292
bool success = mOSWindow->takeScreenshot(pixelBuffer);
293
mFpSetThreadDpiAwarenessContext(previous);
294
ASSERT_EGL_TRUE(success);
295
296
ASSERT_EGL_TRUE(pixelBuffer[(50 * 50 * 4)] == 255);
297
ASSERT_EGL_TRUE(pixelBuffer[(50 * 50 * 4) + 1] == 0);
298
ASSERT_EGL_TRUE(pixelBuffer[(50 * 50 * 4) + 2] == 0);
299
ASSERT_EGL_TRUE(pixelBuffer[(50 * 50 * 4) + 3] == 255);
300
301
ASSERT_TRUE(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) !=
302
EGL_FALSE);
303
ASSERT_EGL_TRUE(eglDestroySurface(mEglDisplay, s));
304
ASSERT_EGL_TRUE(eglDestroyContext(mEglDisplay, mEglContext));
305
mEglContext = EGL_NO_CONTEXT;
306
}
307
308
ANGLE_INSTANTIATE_TEST(EGLDirectCompositionTest, WithNoFixture(ES2_D3D11()));
309
310
#endif // ANGLE_ENABLE_D3D11_COMPOSITOR_NATIVE_WINDOW
311
312