Path: blob/main_old/src/tests/egl_tests/EGLDirectCompositionTest.cpp
1693 views
//1// Copyright 2018 The ANGLE Project Authors. All rights reserved.2// Use of this source code is governed by a BSD-style license that can be3// found in the LICENSE file.4//56// EGLDirectCompositionTest.cpp:7// Tests pertaining to DirectComposition and WindowsUIComposition.89#ifdef ANGLE_ENABLE_D3D11_COMPOSITOR_NATIVE_WINDOW1011# include <d3d11.h>12# include "test_utils/ANGLETest.h"1314# include <DispatcherQueue.h>15# include <VersionHelpers.h>16# include <Windows.Foundation.h>17# include <windows.ui.composition.Desktop.h>18# include <windows.ui.composition.h>19# include <windows.ui.composition.interop.h>20# include <wrl.h>21# include <memory>2223# include "libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.h"24# include "util/OSWindow.h"25# include "util/com_utils.h"26# include "util/test_utils.h"2728using namespace angle;29using namespace ABI::Windows::System;30using namespace ABI::Windows::UI::Composition;31using namespace ABI::Windows::UI::Composition::Desktop;32using namespace ABI::Windows::Foundation;33using namespace Microsoft::WRL;34using namespace Microsoft::WRL::Wrappers;3536const int WINDOWWIDTH = 200, WINDOWHEIGHT = 200;3738class EGLDirectCompositionTest : public ANGLETest39{40protected:41EGLDirectCompositionTest() : mOSWindow(nullptr) {}4243void testSetUp() override44{45if (!mRoHelper.SupportedWindowsRelease())46{47return;48}4950// Create an OS Window51mOSWindow = OSWindow::New();5253mOSWindow->initialize("EGLDirectCompositionTest", WINDOWWIDTH, WINDOWHEIGHT);54auto nativeWindow = mOSWindow->getNativeWindow();55setWindowVisible(mOSWindow, true);5657// Create DispatcherQueue for window to process compositor callbacks58CreateDispatcherQueue(mDispatcherController);5960HSTRING act;61HSTRING_HEADER header;6263auto hr = mRoHelper.GetStringReference(RuntimeClass_Windows_UI_Composition_Compositor, &act,64&header);6566ASSERT_TRUE(SUCCEEDED(hr));6768void *fac = nullptr;69hr = mRoHelper.GetActivationFactory(act, __uuidof(IActivationFactory), &fac);70ASSERT_TRUE(SUCCEEDED(hr));7172ComPtr<IActivationFactory> compositorFactory;7374compositorFactory.Attach((IActivationFactory *)fac);7576hr = compositorFactory->ActivateInstance(&mCompositor);77ASSERT_TRUE(SUCCEEDED(hr));7879// Create a DesktopWindowTarget against native window (HWND)80CreateDesktopWindowTarget(mCompositor, static_cast<HWND>(nativeWindow), mDesktopTarget);8182ASSERT_TRUE(SUCCEEDED(mCompositor->CreateSpriteVisual(mAngleHost.GetAddressOf())));8384ComPtr<IVisual> angleVis;85ASSERT_TRUE(SUCCEEDED(mAngleHost.As(&angleVis)));8687ASSERT_TRUE(SUCCEEDED(angleVis->put_Size(88{static_cast<FLOAT>(WINDOWWIDTH), static_cast<FLOAT>(WINDOWHEIGHT)})));8990ASSERT_TRUE(SUCCEEDED(angleVis->put_Offset({0, 0, 0})));9192ComPtr<ICompositionTarget> compTarget;93ASSERT_TRUE(SUCCEEDED(mDesktopTarget.As(&compTarget)));94ASSERT_TRUE(SUCCEEDED(compTarget->put_Root(angleVis.Get())));9596Init();97}9899void CreateDispatcherQueue(ComPtr<IDispatcherQueueController> &controller)100{101DispatcherQueueOptions options{sizeof(DispatcherQueueOptions), DQTYPE_THREAD_CURRENT,102DQTAT_COM_STA};103104auto hr = mRoHelper.CreateDispatcherQueueController(options, controller.GetAddressOf());105106ASSERT_TRUE(SUCCEEDED(hr));107}108109void CreateDesktopWindowTarget(ComPtr<ICompositor> const &compositor,110const HWND window,111ComPtr<IDesktopWindowTarget> &target)112{113namespace abi = ABI::Windows::UI::Composition::Desktop;114115ComPtr<ICompositorDesktopInterop> interop;116ASSERT_TRUE(SUCCEEDED(compositor.As(&interop)));117118ASSERT_TRUE(SUCCEEDED(interop->CreateDesktopWindowTarget(119window, true, reinterpret_cast<abi::IDesktopWindowTarget **>(target.GetAddressOf()))));120}121122void Init()123{124if (!mRoHelper.SupportedWindowsRelease())125{126return;127}128129DPI_AWARENESS_CONTEXT130WINAPI131SetThreadDpiAwarenessContext(_In_ DPI_AWARENESS_CONTEXT dpiContext);132133auto userModule = LoadLibraryA("user32.dll");134135if (userModule == nullptr)136{137return;138}139140auto temp = GetProcAddress(userModule, "SetThreadDpiAwarenessContext");141142mFpSetThreadDpiAwarenessContext = reinterpret_cast<_SetThreadDpiAwarenessContext *>(temp);143144const EGLint configAttributes[] = {145EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8,146EGL_DEPTH_SIZE, 8, EGL_STENCIL_SIZE, 8, EGL_NONE};147148const EGLint defaultDisplayAttributes[] = {149EGL_PLATFORM_ANGLE_TYPE_ANGLE,150EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,151EGL_NONE,152};153154PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT =155reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(156eglGetProcAddress("eglGetPlatformDisplayEXT"));157ASSERT_TRUE(eglGetPlatformDisplayEXT != nullptr);158159mEglDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE,160reinterpret_cast<void *>(EGL_DEFAULT_DISPLAY),161defaultDisplayAttributes);162ASSERT_TRUE(mEglDisplay != EGL_NO_DISPLAY);163164ASSERT_EGL_TRUE(eglInitialize(mEglDisplay, nullptr, nullptr));165166EGLint nConfigs = 0;167168ASSERT_EGL_TRUE(eglGetConfigs(mEglDisplay, nullptr, 0, &nConfigs));169ASSERT_TRUE(nConfigs != 0);170171ASSERT_EGL_TRUE(eglChooseConfig(mEglDisplay, configAttributes, &mEglConfig, 1, &nConfigs));172}173174void CreateSurface(ComPtr<ABI::Windows::UI::Composition::ISpriteVisual> visual,175EGLSurface &surface)176{177auto displayExtensions = eglQueryString(mEglDisplay, EGL_EXTENSIONS);178179// Check that the EGL_ANGLE_windows_ui_composition display extension is available180ASSERT_TRUE(strstr(displayExtensions, "EGL_ANGLE_windows_ui_composition") != nullptr);181182const EGLint contextAttributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};183184// Use a spritevisual as the nativewindowtype185surface =186eglCreateWindowSurface(mEglDisplay, mEglConfig,187static_cast<EGLNativeWindowType>((void *)visual.Get()), nullptr);188ASSERT_TRUE(surface != EGL_NO_SURFACE);189190mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT, contextAttributes);191ASSERT_TRUE(mEglContext != EGL_NO_CONTEXT);192193ASSERT_TRUE(eglMakeCurrent(mEglDisplay, surface, surface, mEglContext) != EGL_FALSE);194}195196void testTearDown() override197{198if (!mRoHelper.SupportedWindowsRelease())199{200return;201}202if (mEglDisplay != EGL_NO_DISPLAY)203{204ASSERT_EGL_TRUE(eglTerminate(mEglDisplay));205mEglDisplay = EGL_NO_DISPLAY;206}207208OSWindow::Delete(&mOSWindow);209}210211OSWindow *mOSWindow;212ComPtr<ICompositor> mCompositor;213ComPtr<IDispatcherQueueController> mDispatcherController;214ComPtr<ICompositionColorBrush> mColorBrush;215ComPtr<IDesktopWindowTarget> mDesktopTarget;216ComPtr<ISpriteVisual> mAngleHost;217218EGLDisplay mEglDisplay;219EGLContext mEglContext;220EGLConfig mEglConfig;221rx::RoHelper mRoHelper;222223using _SetThreadDpiAwarenessContext =224DPI_AWARENESS_CONTEXT WINAPI(DPI_AWARENESS_CONTEXT dpiContext);225226_SetThreadDpiAwarenessContext *mFpSetThreadDpiAwarenessContext;227};228229// This tests that a surface created using a SpriteVisual as container has the expected dimensions230// which should match the dimensions of the SpriteVisual passed in231TEST_P(EGLDirectCompositionTest, SurfaceSizeFromSpriteSize)232{233// Only attempt this test when on Windows 10 1803+234ANGLE_SKIP_TEST_IF(!mRoHelper.SupportedWindowsRelease());235236EGLSurface s{nullptr};237CreateSurface(mAngleHost, s);238239EGLint surfacewidth = 0, surfaceheight = 0;240eglQuerySurface(mEglDisplay, s, EGL_WIDTH, &surfacewidth);241eglQuerySurface(mEglDisplay, s, EGL_HEIGHT, &surfaceheight);242243ComPtr<IVisual> angleVis;244ASSERT_TRUE(SUCCEEDED(mAngleHost.As(&angleVis)));245246ABI::Windows::Foundation::Numerics::Vector2 visualsize{0, 0};247248ASSERT_TRUE(SUCCEEDED(angleVis->get_Size(&visualsize)));249250ASSERT_TRUE(surfacewidth == static_cast<int>(visualsize.X));251ASSERT_TRUE(surfaceheight == static_cast<int>(visualsize.Y));252253ASSERT_TRUE(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) !=254EGL_FALSE);255ASSERT_EGL_TRUE(eglDestroySurface(mEglDisplay, s));256ASSERT_EGL_TRUE(eglDestroyContext(mEglDisplay, mEglContext));257mEglContext = EGL_NO_CONTEXT;258}259260// This tests that a WindowSurface can be created using a SpriteVisual as the containing window261// and that pixels can be successfully rendered into the resulting WindowSurface262TEST_P(EGLDirectCompositionTest, RenderSolidColor)263{264// Only attempt this test when on Windows 10 1803+265ANGLE_SKIP_TEST_IF(!mRoHelper.SupportedWindowsRelease());266267// http://crbug.com/1063962268ANGLE_SKIP_TEST_IF(isD3D11Renderer() && IsIntel());269270EGLSurface s{nullptr};271CreateSurface(mAngleHost, s);272273glClearColor(0.0f, 0.0f, 1.0f, 1.0f);274275glViewport(0, 0, WINDOWWIDTH, WINDOWHEIGHT);276glClear(GL_COLOR_BUFFER_BIT);277278ASSERT_EGL_TRUE(eglSwapBuffers(mEglDisplay, s));279280// ensure user/DWM have a chance to paint the window and kick it to the top of the desktop281// zorder before we attempt to sample282angle::Sleep(200);283mOSWindow->messageLoop();284285uint8_t *pixelBuffer = static_cast<uint8_t *>(malloc(WINDOWWIDTH * WINDOWHEIGHT * 4));286ZeroMemory(pixelBuffer, WINDOWWIDTH * WINDOWHEIGHT * 4);287288// In order to accurately capture a bitmap, we need to temporarily shift into per-monitor DPI289// mode in order to get the window offset from desktop correct290auto previous = mFpSetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE);291bool success = mOSWindow->takeScreenshot(pixelBuffer);292mFpSetThreadDpiAwarenessContext(previous);293ASSERT_EGL_TRUE(success);294295ASSERT_EGL_TRUE(pixelBuffer[(50 * 50 * 4)] == 255);296ASSERT_EGL_TRUE(pixelBuffer[(50 * 50 * 4) + 1] == 0);297ASSERT_EGL_TRUE(pixelBuffer[(50 * 50 * 4) + 2] == 0);298ASSERT_EGL_TRUE(pixelBuffer[(50 * 50 * 4) + 3] == 255);299300ASSERT_TRUE(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) !=301EGL_FALSE);302ASSERT_EGL_TRUE(eglDestroySurface(mEglDisplay, s));303ASSERT_EGL_TRUE(eglDestroyContext(mEglDisplay, mEglContext));304mEglContext = EGL_NO_CONTEXT;305}306307ANGLE_INSTANTIATE_TEST(EGLDirectCompositionTest, WithNoFixture(ES2_D3D11()));308309#endif // ANGLE_ENABLE_D3D11_COMPOSITOR_NATIVE_WINDOW310311312