From f562d7765f04079883a13cd232c5ac8388d9f248 Mon Sep 17 00:00:00 2001 From: Igor Demin Date: Fri, 12 Apr 2024 20:27:38 +0200 Subject: [PATCH 1/7] Windows. Fix a crash on CI without `dcomp.dll` ## Issues fixed Some CI don't have this library and when we run an application we have a crash: ``` ...\skiko-windows-x64.dll: Can't find dependent libraries java.lang.UnsatisfiedLinkError: ...\skiko-windows-x64.dll: Can't find dependent libraries at java.base/jdk.internal.loader.NativeLibraries.load(Native Method) at java.base/jdk.internal.loader.NativeLibraries$NativeLibraryImpl.open(NativeLibraries.java:388) at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:232) at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:174) at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2394) at java.base/java.lang.Runtime.load0(Runtime.java:755) at java.base/java.lang.System.load(System.java:1957) at org.jetbrains.skiko.Library.loadLibraryOrCopy(Library.kt:17) at org.jetbrains.skiko.Library.findAndLoad(Library.kt:111) at org.jetbrains.skiko.Library.load(Library.kt:56) at org.jetbrains.skia.impl.Library$Companion.staticLoad(Library.jvm.kt:12) at org.jetbrains.skia.Surface.(Surface.kt:539) at androidx.compose.ui.test.SkikoComposeUiTest.(ComposeUiTest.skikoMain.kt:172) at androidx.compose.ui.test.SkikoComposeUiTest.(ComposeUiTest.skikoMain.kt:118) at androidx.compose.ui.test.SkikoComposeUiTest.(ComposeUiTest.skikoMain.kt:139) at androidx.compose.ui.test.SkikoComposeUiTest.(ComposeUiTest.skikoMain.kt:134) at androidx.compose.ui.test.junit4.DesktopComposeTestRule.(DesktopComposeTestRule.desktop.kt:54) at androidx.compose.ui.test.junit4.DesktopComposeTestRule_desktopKt.createComposeRule(DesktopComposeTestRule.desktop.kt:41) at com.android.tools.adtui.compose.HideablePanelTest.(HideablePanelTest.kt:27) at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499) at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480) at org.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:250) at org.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:260) at org.junit.runners.BlockJUnit4ClassRunner$2.runReflectiveCall(BlockJUnit4ClassRunner.java:309) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:306) at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63) at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329) at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293) at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306) at org.junit.runners.ParentRunner.run(ParentRunner.java:413) at org.junit.runners.Suite.runChild(Suite.java:128) at org.junit.runners.Suite.runChild(Suite.java:27) at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329) at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293) at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306) at com.android.testutils.JarTestSuiteRunner$1.evaluate(JarTestSuiteRunner.java:129) at org.junit.runners.ParentRunner.run(ParentRunner.java:413) at com.google.testing.junit.runner.internal.junit4.CancellableRequestFactory$CancellableRunner.run(CancellableRequestFactory.java:108) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at org.junit.runner.JUnitCore.run(JUnitCore.java:115) at com.google.testing.junit.runner.junit4.JUnit4Runner.run(JUnit4Runner.java:116) at com.google.testing.junit.runner.BazelTestRunner.runTestsInSuite(BazelTestRunner.java:145) at com.google.testing.junit.runner.BazelTestRunner.main(BazelTestRunner.java:76) ``` Reported in https://jetbrains.slack.com/archives/C5VQN94SH/p1712564847131459?thread_ts=1712091431.760099&cid=C5VQN94SH ## Proposed changes Load this library in runtime, and fallback to `CreateSwapChainForComposition` ## Testing 1. Run Compose with transparent window: ``` import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.Surface import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Window import androidx.compose.ui.window.application import androidx.compose.material.Text import androidx.compose.runtime.* fun main() = application { var isOpen by remember { mutableStateOf(true) } if (isOpen) { Window( onCloseRequest = { isOpen = false }, title = "Transparent Window Example", transparent = true, undecorated = true, //transparent window must be undecorated ) { Surface( modifier = Modifier.fillMaxSize().padding(5.dp).shadow(3.dp, RoundedCornerShape(20.dp)), color = Color(55, 55, 55), shape = RoundedCornerShape(20.dp) //window has round corners now ) { Text("Hello World!", color = Color.White) } } } } ``` Transparency should work, there shouldn't be errors in the log. 2. change `transparent = false` Transparency shouldn't work, there shouldn't be errors in the log. This should be tested by QA. --- .../awtMain/cpp/windows/directXRedrawer.cc | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/skiko/src/awtMain/cpp/windows/directXRedrawer.cc b/skiko/src/awtMain/cpp/windows/directXRedrawer.cc index db7a1489c..a8f9bf119 100644 --- a/skiko/src/awtMain/cpp/windows/directXRedrawer.cc +++ b/skiko/src/awtMain/cpp/windows/directXRedrawer.cc @@ -21,10 +21,37 @@ #include #include -#pragma comment(lib, "dcomp.lib") const int BuffersCount = 2; +namespace DCompLibrary { + static bool isInit = false; + static HINSTANCE library = nullptr; + + void load() { + if (!isInit) { + isInit = true; + library = LoadLibrary("dcomp.dll"); + } + } + + HRESULT DCompositionCreateDevice( + IDXGIDevice *dxgiDevice, + REFIID iid, + void **dcompositionDevice + ) { + load(); + + if (library != nullptr) { + typedef HRESULT(WINAPI * PROC_DCompositionCreateDevice)(IDXGIDevice * dxgiDevice, REFIID iid, void **dcompositionDevice); + static auto compositionCreateDevice = (PROC_DCompositionCreateDevice) GetProcAddress(library, "DCompositionCreateDevice"); + return compositionCreateDevice(dxgiDevice, iid, dcompositionDevice); + } else { + return E_FAIL; + } + } +}; + class DirectXDevice { public: @@ -95,7 +122,7 @@ class DirectXDevice HRESULT result = swapChainFactory4->CreateSwapChainForComposition(queue.get(), &swapChainDesc, nullptr, swapChain1); if (FAILED(result)) { return result; } - result = DCompositionCreateDevice(0, IID_PPV_ARGS(&dcDevice)); + result = DCompLibrary::DCompositionCreateDevice(0, IID_PPV_ARGS(&dcDevice)); if (FAILED(result)) { return result; } result = dcDevice->CreateTargetForHwnd(hWnd, true, &dcTarget); if (FAILED(result)) { return result; } From 84fe5ec0dff4914ed82544c8d2fe903b5c66f106 Mon Sep 17 00:00:00 2001 From: Igor Demin Date: Tue, 16 Apr 2024 10:46:23 +0200 Subject: [PATCH 2/7] Discussions --- skiko/src/awtMain/cpp/windows/DCompLibrary.hh | 26 ++++++++++++++++ .../awtMain/cpp/windows/directXRedrawer.cc | 31 +------------------ 2 files changed, 27 insertions(+), 30 deletions(-) create mode 100644 skiko/src/awtMain/cpp/windows/DCompLibrary.hh diff --git a/skiko/src/awtMain/cpp/windows/DCompLibrary.hh b/skiko/src/awtMain/cpp/windows/DCompLibrary.hh new file mode 100644 index 000000000..26ab0d6e4 --- /dev/null +++ b/skiko/src/awtMain/cpp/windows/DCompLibrary.hh @@ -0,0 +1,26 @@ +#pragma once + +#include + +namespace DCompLibrary { + HINSTANCE getLibrary() { + static HINSTANCE library = LoadLibrary("dcomp.dll"); + return library; + } + + HRESULT DCompositionCreateDevice( + IDXGIDevice *dxgiDevice, + REFIID iid, + void **dcompositionDevice + ) { + HINSTANCE library = getLibrary(); + + if (library != nullptr) { + typedef HRESULT(WINAPI * PROC_DCompositionCreateDevice)(IDXGIDevice * dxgiDevice, REFIID iid, void **dcompositionDevice); + static auto compositionCreateDevice = (PROC_DCompositionCreateDevice) GetProcAddress(library, "DCompositionCreateDevice"); + return compositionCreateDevice(dxgiDevice, iid, dcompositionDevice); + } else { + return E_FAIL; + } + } +}; diff --git a/skiko/src/awtMain/cpp/windows/directXRedrawer.cc b/skiko/src/awtMain/cpp/windows/directXRedrawer.cc index a8f9bf119..499fef03e 100644 --- a/skiko/src/awtMain/cpp/windows/directXRedrawer.cc +++ b/skiko/src/awtMain/cpp/windows/directXRedrawer.cc @@ -12,6 +12,7 @@ #include "SkSurface.h" #include "include/gpu/ganesh/SkSurfaceGanesh.h" #include "../common/interop.hh" +#include "DCompLibrary.hh" #include "d3d/GrD3DTypes.h" #include @@ -20,38 +21,8 @@ #include #include -#include - const int BuffersCount = 2; -namespace DCompLibrary { - static bool isInit = false; - static HINSTANCE library = nullptr; - - void load() { - if (!isInit) { - isInit = true; - library = LoadLibrary("dcomp.dll"); - } - } - - HRESULT DCompositionCreateDevice( - IDXGIDevice *dxgiDevice, - REFIID iid, - void **dcompositionDevice - ) { - load(); - - if (library != nullptr) { - typedef HRESULT(WINAPI * PROC_DCompositionCreateDevice)(IDXGIDevice * dxgiDevice, REFIID iid, void **dcompositionDevice); - static auto compositionCreateDevice = (PROC_DCompositionCreateDevice) GetProcAddress(library, "DCompositionCreateDevice"); - return compositionCreateDevice(dxgiDevice, iid, dcompositionDevice); - } else { - return E_FAIL; - } - } -}; - class DirectXDevice { public: From fb879ccdcd8d8da370687816282fb8bcf839c9ac Mon Sep 17 00:00:00 2001 From: Igor Demin Date: Tue, 16 Apr 2024 11:31:55 +0200 Subject: [PATCH 3/7] Discussions --- .../cpp/windows/{DCompLibrary.hh => DCompLibrary.cc} | 6 +++--- skiko/src/awtMain/cpp/windows/directXRedrawer.cc | 2 +- skiko/src/awtMain/cpp/windows/include/DCompLibrary.h | 11 +++++++++++ 3 files changed, 15 insertions(+), 4 deletions(-) rename skiko/src/awtMain/cpp/windows/{DCompLibrary.hh => DCompLibrary.cc} (89%) create mode 100644 skiko/src/awtMain/cpp/windows/include/DCompLibrary.h diff --git a/skiko/src/awtMain/cpp/windows/DCompLibrary.hh b/skiko/src/awtMain/cpp/windows/DCompLibrary.cc similarity index 89% rename from skiko/src/awtMain/cpp/windows/DCompLibrary.hh rename to skiko/src/awtMain/cpp/windows/DCompLibrary.cc index 26ab0d6e4..dd5348882 100644 --- a/skiko/src/awtMain/cpp/windows/DCompLibrary.hh +++ b/skiko/src/awtMain/cpp/windows/DCompLibrary.cc @@ -1,6 +1,6 @@ #pragma once -#include +#include "include/DCompLibrary.h" namespace DCompLibrary { HINSTANCE getLibrary() { @@ -10,8 +10,8 @@ namespace DCompLibrary { HRESULT DCompositionCreateDevice( IDXGIDevice *dxgiDevice, - REFIID iid, - void **dcompositionDevice + REFIID iid, + void **dcompositionDevice ) { HINSTANCE library = getLibrary(); diff --git a/skiko/src/awtMain/cpp/windows/directXRedrawer.cc b/skiko/src/awtMain/cpp/windows/directXRedrawer.cc index 499fef03e..1d8d06789 100644 --- a/skiko/src/awtMain/cpp/windows/directXRedrawer.cc +++ b/skiko/src/awtMain/cpp/windows/directXRedrawer.cc @@ -12,7 +12,7 @@ #include "SkSurface.h" #include "include/gpu/ganesh/SkSurfaceGanesh.h" #include "../common/interop.hh" -#include "DCompLibrary.hh" +#include "include/DCompLibrary.h" #include "d3d/GrD3DTypes.h" #include diff --git a/skiko/src/awtMain/cpp/windows/include/DCompLibrary.h b/skiko/src/awtMain/cpp/windows/include/DCompLibrary.h new file mode 100644 index 000000000..a5ef47cc7 --- /dev/null +++ b/skiko/src/awtMain/cpp/windows/include/DCompLibrary.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +namespace DCompLibrary { + HRESULT DCompositionCreateDevice( + IDXGIDevice *dxgiDevice, + REFIID iid, + void **dcompositionDevice + ); +}; From 971b67c68607b588adbd70915657737a2dc764ee Mon Sep 17 00:00:00 2001 From: Igor Demin Date: Tue, 16 Apr 2024 11:34:43 +0200 Subject: [PATCH 4/7] static HINSTANCE getLibrary --- skiko/src/awtMain/cpp/windows/DCompLibrary.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skiko/src/awtMain/cpp/windows/DCompLibrary.cc b/skiko/src/awtMain/cpp/windows/DCompLibrary.cc index dd5348882..ec7b10a11 100644 --- a/skiko/src/awtMain/cpp/windows/DCompLibrary.cc +++ b/skiko/src/awtMain/cpp/windows/DCompLibrary.cc @@ -3,7 +3,7 @@ #include "include/DCompLibrary.h" namespace DCompLibrary { - HINSTANCE getLibrary() { + static HINSTANCE getLibrary() { static HINSTANCE library = LoadLibrary("dcomp.dll"); return library; } From e91b98c8f5f9f59ede131f38cee2df18d872e021 Mon Sep 17 00:00:00 2001 From: Igor Demin Date: Tue, 16 Apr 2024 12:14:23 +0200 Subject: [PATCH 5/7] Discussions --- skiko/src/awtMain/cpp/windows/DCompLibrary.cc | 4 +--- skiko/src/awtMain/cpp/windows/{include => }/DCompLibrary.h | 0 skiko/src/awtMain/cpp/windows/directXRedrawer.cc | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) rename skiko/src/awtMain/cpp/windows/{include => }/DCompLibrary.h (100%) diff --git a/skiko/src/awtMain/cpp/windows/DCompLibrary.cc b/skiko/src/awtMain/cpp/windows/DCompLibrary.cc index ec7b10a11..920ece437 100644 --- a/skiko/src/awtMain/cpp/windows/DCompLibrary.cc +++ b/skiko/src/awtMain/cpp/windows/DCompLibrary.cc @@ -1,6 +1,4 @@ -#pragma once - -#include "include/DCompLibrary.h" +#include "DCompLibrary.h" namespace DCompLibrary { static HINSTANCE getLibrary() { diff --git a/skiko/src/awtMain/cpp/windows/include/DCompLibrary.h b/skiko/src/awtMain/cpp/windows/DCompLibrary.h similarity index 100% rename from skiko/src/awtMain/cpp/windows/include/DCompLibrary.h rename to skiko/src/awtMain/cpp/windows/DCompLibrary.h diff --git a/skiko/src/awtMain/cpp/windows/directXRedrawer.cc b/skiko/src/awtMain/cpp/windows/directXRedrawer.cc index 1d8d06789..18b02f098 100644 --- a/skiko/src/awtMain/cpp/windows/directXRedrawer.cc +++ b/skiko/src/awtMain/cpp/windows/directXRedrawer.cc @@ -12,7 +12,7 @@ #include "SkSurface.h" #include "include/gpu/ganesh/SkSurfaceGanesh.h" #include "../common/interop.hh" -#include "include/DCompLibrary.h" +#include "DCompLibrary.h" #include "d3d/GrD3DTypes.h" #include From 8fa2b1c22893a983d6e76e18bc52c17d7570cba8 Mon Sep 17 00:00:00 2001 From: Igor Demin Date: Tue, 16 Apr 2024 13:00:13 +0200 Subject: [PATCH 6/7] Update skiko/src/awtMain/cpp/windows/DCompLibrary.cc Co-authored-by: Ivan Matkov --- skiko/src/awtMain/cpp/windows/DCompLibrary.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skiko/src/awtMain/cpp/windows/DCompLibrary.cc b/skiko/src/awtMain/cpp/windows/DCompLibrary.cc index 920ece437..7cbbdd1cf 100644 --- a/skiko/src/awtMain/cpp/windows/DCompLibrary.cc +++ b/skiko/src/awtMain/cpp/windows/DCompLibrary.cc @@ -21,4 +21,4 @@ namespace DCompLibrary { return E_FAIL; } } -}; +} From c6cd6085887626f62d7a19d4bf3035bbac99a159 Mon Sep 17 00:00:00 2001 From: Igor Demin Date: Tue, 16 Apr 2024 13:00:17 +0200 Subject: [PATCH 7/7] Update skiko/src/awtMain/cpp/windows/DCompLibrary.h Co-authored-by: Ivan Matkov --- skiko/src/awtMain/cpp/windows/DCompLibrary.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skiko/src/awtMain/cpp/windows/DCompLibrary.h b/skiko/src/awtMain/cpp/windows/DCompLibrary.h index a5ef47cc7..8a0df3ec3 100644 --- a/skiko/src/awtMain/cpp/windows/DCompLibrary.h +++ b/skiko/src/awtMain/cpp/windows/DCompLibrary.h @@ -8,4 +8,4 @@ namespace DCompLibrary { REFIID iid, void **dcompositionDevice ); -}; +}