smourier / DirectN

Direct interop Code for .NET Framework, .NET Core and .NET 5+ : DXGI, WIC, DirectX 9 to 12, Direct2D, Direct Write, Direct Composition, Media Foundation, WASAPI, CodecAPI, GDI, Spatial Audio, DVD, Windows Media Player, UWP DXInterop, WinUI3, etc.
MIT License
319 stars 28 forks source link

Is it possible to display IDComposition Visual or Windows.UI.Composition.Visual in WinUI3 #9

Closed selastingeorge closed 3 years ago

selastingeorge commented 3 years ago

Hi, i was developing a project based on Win UI 3, i was trying to display and IDCompositionVisual (or Windows.UI.Composition.Visual) into WinUI3 Desktop Application without airspace issue. is it possible to do it using DirectN or in any other possible way ?

smourier commented 3 years ago

Hi,

IDCompositionVisual is an "old" thing (Dcomp V1/V2) that is supported by Win32 (and WinRT). Windows.UI.Composition.Visual is more recent (Dcomp V3) but reserved for WinRT.

Both are supported by a Windows-only Dll: %windir%\system32\Dcomp.dll

I'm not expert enough in WinUI 3 but my understanding is it comes with its own "Dcomp" which is in a Microsoft namespace: Microsoft.UI.Composition.Visual (https://docs.microsoft.com/en-us/windows/winui/api/microsoft.ui.composition.visual) in a specific .dll (Dcompi.dll) also associated with a custom DWM that are shipped with the Win UI 3 runtime or packaged with your WinUI 3 app.

So, in the end what it means is:

selastingeorge commented 3 years ago

Since Microsoft has Decoupled from OS Microsoft.UI.Composition stops supporting most of the functionalities that Windows.UI.Composition supports (like interop). IDComposition is an old thing but in most part of windows 10 they are using the same thing. For example you can take the DWM Thumbnail, Even the Acrylic Effect internal uses this IDCompositionVisual, i just recreated the Windows Acrylic Effect on Win32 using DWM Thumbnail, but I need a Way to render it into a Win UI Window or at least WPF without airspace issue. I tried most of the methods and none of them are working.

Here is my Current Project Win32-Acrylic-Effect

After Some research I think, it might be possible to do so in WPF, i was able to hook to WPF SwapChain and I was able to control the WPF Swap chain. The WPF SwapChain is of type IDirect3DSwapChain9, so if it is possible to get the back buffer into an ID2D1Bitmap (using Surface Queueing mentioned over Here ) it is possible to render the WPF Content on top of Direct Composition. But i haven't found a single sample to do this.

smourier commented 3 years ago

Direct Composition is indeed tightly coupled with the DWM.

Your code uses a lot of undocumented functions. You don't need to use any undocumented function to get the true acrylic effect. You only need WinRT's Windows.UI.Composition (and connect the dots as it's not super documented outside of UWP sandboxed crap):

Compositor.CreateHostBackdropBrush: https://docs.microsoft.com/en-us/uwp/api/windows.ui.composition.compositor.createhostbackdropbrush

Compositor.CreateBackdropBrush https://docs.microsoft.com/en-us/uwp/api/windows.ui.composition.compositor.createbackdropbrush

And then, the exact recipe for the effect graph is here https://github.com/microsoft/microsoft-ui-xaml/blob/main/dev/Materials/Acrylic/AcrylicBrush.cpp#L697

Unfortunately, IDComposition doesn't have these methods, they're only available with WinRT which is not anymore a problem today since many WinRT APIs are accessible to regular unpackaged Win32 desktop apps. So IDComposition is not from a public API point of view the same as Windows.UI.Composition. Although they are technically both implemented in dcomp.dll, there are things that you can only do with WinRT Windows.UI.Composition.

As for WPF, I the problem to me is really the fact they're hooked on DX9. Maybe you can do it, but only with severe hacking.

I have all that working fine with .NET and DirectN w/o any undocumented function (I can't today paste the code here because it's proprietary, but there are plans to do so). And once you start using Windows.UI.Composition, you don't need to touch IDComposition at all.

selastingeorge commented 3 years ago

But the problem is when i use Windows.UI.Composition 's CreateHostBackdropBrush() in win32 Apps it only produces BLACK Rectangle instead of The host Backdrop. it's mentioned over Here

The main issue is the flickering of Window while resizing. Compared to Windows.UI.Composition in win32 apps IDComposition has less Flickering on resize. The flickering still exist in WinUI3.

The WinUI3 looks a bit complicated, it is even difficult to get just the HWND from a C++ WinUI3 Project.

Suppose, even if I created the Acrylic Effect using Windows.UI.Composition, till now no one haven't found any way to host it into winUI application,

smourier commented 3 years ago

Yes, for CreateHostBackdropBrush to not be black you do need to enable blur behind on the window, something like this with DirectN C#:

        var accent = new ACCENT_POLICY();
        accent.AccentState = ACCENT_STATE.ACCENT_ENABLE_BLURBEHIND;
        var data = new WINDOWCOMPOSITIONATTRIBDATA();
        data.dwAttrib = WINDOWCOMPOSITIONATTRIB.WCA_ACCENT_POLICY;
        using (var mem = new ComMemory(accent))
        {
            data.cbData = new IntPtr(mem.Size);
            data.pvData = mem.Pointer;
            WindowsFunctions.SetWindowCompositionAttribute(hwnd, ref data).ThrowOnError();
        }

About flickering, I don't know, I have zero flickering with Windows.UI.Composition. I don't use any swap chain, you don't need any with Windows.UI.Composition, check this great seminal sample: https://gist.github.com/kennykerr/62923cdacaba28fedc4f3dab6e0c12ec. There's no reason there should be any flickering.

As for hosting in WinUI 3, as I said, I've not investigated it so far because it's not really finished (it still needs packaging and tooling as compilation times are awful, showstopper for me). In fact I've written my own WPF/WinUI3-like framework in C# because of all these reasons.

selastingeorge commented 3 years ago

Thank you let me give it a try

On Mon, 21 Jun, 2021, 1:16 pm Simon Mourier, @.***> wrote:

Yes, for CreateHostBackdropBrush to not be black you do need to enable blur behind on the window, something like this with DirectN C#:

    var accent = new ACCENT_POLICY();
    accent.AccentState = ACCENT_STATE.ACCENT_ENABLE_BLURBEHIND;
    var data = new WINDOWCOMPOSITIONATTRIBDATA();
    data.dwAttrib = WINDOWCOMPOSITIONATTRIB.WCA_ACCENT_POLICY;
    using (var mem = new ComMemory(accent))
    {
        data.cbData = new IntPtr(mem.Size);
        data.pvData = mem.Pointer;
        WindowsFunctions.SetWindowCompositionAttribute(hwnd, ref data).ThrowOnError();
    }

About flickering, I don't know, I have zero flickering with Windows.UI.Composition. I don't use any swap chain, you don't need any with Windows.UI.Composition, check this great seminal sample: https://gist.github.com/kennykerr/62923cdacaba28fedc4f3dab6e0c12ec. There's no reason there should be any flickering.

As for hosting in WinUI 3, as I said, I've not investigated it so far because it's not really finished (it still needs packaging and tooling as compilation times are awful, showstopper for me). In fact I've written my own WPF/WinUI3-like framework in C# because of all these reasons.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/smourier/DirectN/issues/9#issuecomment-864807732, or unsubscribe https://github.com/notifications/unsubscribe-auth/ARKGWVJBKPSV3UM7ZSJG5G3TT3U6LANCNFSM47ADRRRA .

selastingeorge commented 3 years ago

Hi, i Checkout, it's working fine and it is same as the Acrylic Effect that i have created. the private dwm api that i used is the same which they used here in CreateHostBackdropBrush(). Because this acrylic effect also wont update when the window is not activated, like the one that i built.

See this : image

Both uses the DWM Private API's, but when using direct composition the flickering is lesser compared to Windows.UI.Composition, but it it is unable to apply AtlasEffect in DirectComposition.

I got the DWM Private functions when i decompiled the dwmapi.dll and searched for DWMEnableBlurBehindWindow().

If there was any way to copy the content from IDCompositionVisual to ID2D1Bitmap, WinUI3 can support Acrylic and transparency.

smourier commented 3 years ago

Well, in my case, beyond the ACCENT_ENABLE_BLURBEHIND undocumented hack, I use only public API, WinRT's Windows.UI.Composition, and Direct2D (with DirectN, not with the Win2D UWP-only crap), and have no problem with deactivated windows nor flickering.

Here is a .NET Framework 4.8 C# sample: Acrylic

selastingeorge commented 3 years ago

Open any Window like mspaint, Maximize it , open your acrylic window, maximize that too, then restore the paint window the acrylic window wont update. Microsoft has introduced a new DWMWINDOWATTRIBUTE called DWMWA_USE_HOSTBACKDROPBRUSH, so i think ACCENT_ENABLE_BLURBEHIND will not be needed anymore, currently it is only supported in InsderPreview.

I use only public API, WinRT's Windows.UI.Composition, and Direct2D

Is it possible to share the Windows.UI.Composition.Visual With Direct2D ?

smourier commented 3 years ago

Not sure what problem you have, like I said, I have zero issue.

https://user-images.githubusercontent.com/5328574/122744677-85605400-d288-11eb-887e-8df17b7d5b4e.mp4

To use Direct2D with Windows.UI.Composition.Visual you need to

That's why you don't need any swapchain. You use the DWM/Dcomp one implicitely

selastingeorge commented 3 years ago

You have done that wrong, try this It is possible to draw Direct2D Contents on to visual, but i was looking to do it in reverse, i need the Windows.UI.Composition.Visual into an ID2D1Bitmap.

smourier commented 3 years ago

Whatever I try, it works fine:

https://user-images.githubusercontent.com/5328574/122763822-12160c80-d29f-11eb-93fe-be3f6c0356ba.mp4

As for the other question, it don't think you can do this. The logic is the calling developer sets a given visual's content, so he should know what it contains and doesn't need to read it back.

selastingeorge commented 3 years ago

Ok then it might be something wrong with my code, thank you for letting me know.

On Mon, 21 Jun, 2021, 6:26 pm Simon Mourier, @.***> wrote:

Whatever I try, it works fine:

https://user-images.githubusercontent.com/5328574/122763822-12160c80-d29f-11eb-93fe-be3f6c0356ba.mp4

As for the other question, it don't think you can do this. The logic is the calling developer sets a given visual's content, so he should know what it contains and doesn't need to read it back.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/smourier/DirectN/issues/9#issuecomment-865010101, or unsubscribe https://github.com/notifications/unsubscribe-auth/ARKGWVI75OC2AJ5DE2NUNW3TT4ZJFANCNFSM47ADRRRA .

selastingeorge commented 3 years ago

In one of my WPF project i created, i was able to get the IDirect3DSwapChain9 from my WPF app through hooking. i was able to get the Back buffer from the Swap chain, will it be possible for me to copy it into IDComposition Visual or Windows.UI.Composition.Visual. I have heard about a method called Shared Surfaces, but i wasn't able to find any code on it. i read about it on surface-sharing-between-windows-graphics-apis, So if it was possible i can just copy the content of swapchain to a visual and render it top on Acrylic Right?, it could avoid airspace issue in wpf.

smourier commented 3 years ago

WPF is based on dcomp/d2d/wic primitive ancestors. Even if you can do it, there can be sync issues I guess. Real "sharing", not "copying" seems the way to go to avoid flickering, but I don't think you can do achieve it with WPF. Maybe if you hook everything you can manage to do something, but there's nothing sure I think. One of the best description (w/o solution...) of all this is here from a Microsoft guy: https://dwayneneed.github.io/wpf/2013/02/26/mitigating-airspace-issues-in-wpf-applications.html

selastingeorge commented 3 years ago

Looks like i am at another dead end. Any way thank you very much for sharing your knowledge. Will there be any other way that i could contact you like discord or something, just for resolving doubts, if any.

I am closing this issue, Thank you

smourier commented 3 years ago

I'm here :-) https://stackoverflow.com/users/403671/simon-mourier?tab=profile

selastingeorge commented 3 years ago

Thank you, i will drop a question if i have doubts.

selastingeorge commented 3 years ago

Whatever I try, it works fine:

2021-06-21_14-42-46.mp4 As for the other question, it don't think you can do this. The logic is the calling developer sets a given visual's content, so he should know what it contains and doesn't need to read it back.

Hi can you please share the code that you used here?

smourier commented 3 years ago

The code is currently proprietary. But it will be made public hopefully in the next week(s). I'll keep you posted

selastingeorge commented 3 years ago

Thank you,please let me know once you post it.

On Sun, 27 Jun, 2021, 7:53 pm Simon Mourier, @.***> wrote:

The code is currently proprietary. But it will be made public hopefully in the next week(s). I'll keep you posted

— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub https://github.com/smourier/DirectN/issues/9#issuecomment-869171981, or unsubscribe https://github.com/notifications/unsubscribe-auth/ARKGWVIRJXIM4BLSYM4WB4LTU4X6XANCNFSM47ADRRRA .

selastingeorge commented 3 years ago

Hi could you please clear one doubt, I was using Windows.UI.Composition to create acrylic in my app, to avoid airspace issue, I overlaid Windows (one foreground window - With my controls, One background window with acrylic) I resize the background window along with foreground and all window animations work well except the minimize animation, I need to hide my Background Window from taskbar and alt+tab, but using WS_EX_NOACTIVE will minimize Window to the bottom left corner of desktop and using WS_EXTOOLWINDOW will remove the animations, so I used ITaskbarList3 interface and used deleteTab() function, and this works perfectly and hides the window from taskbar and alt+tab, but during minimize the window is minimized to taskbar but to some other location (exactly to bottom right corner in my system)_, it's looks like the window is scaling up instead of scaling down. but in another pc it is minimizing to correct position but not shrinking the window size. Checkout these screenshots:

image

Using WS_EX_NOACTIVATE

https://user-images.githubusercontent.com/72641365/130591600-8827ee3e-2f8e-4d7c-be9c-db9a7220b8df.mp4

(Here I slowed down the DWM animation using registry tweak to see what exactly is happening) Here is the result when i tested it on a good performance computer, it minimize to correct location but the size is not changing, In my Computer the window size is increasing and it is minimizing to the bottom right corner near to the battery indicator.

Here is the another Case :

https://user-images.githubusercontent.com/72641365/130594549-a0095b94-6318-4449-89aa-9d4213e02a30.mp4

(the flickering of acrylic is just in screen recorder otherwise, it's fine) is there any way that i could change the location to which window is minimized.

smourier commented 3 years ago

I'm not sure how I can help you here :-) This seems specific to what you do. Anyway the code I use is now public: https://github.com/aelyo-softworks/Wice

selastingeorge commented 3 years ago

Thankyou, i will try to find another way around. The project you mentioned, is it like a wpf project but renders everything using Windows.UI.Composition

smourier commented 3 years ago

It's similar to WPF in many ways yes (but different in others like no XAML), and uses Windows.UI.Composition at its core, and Direct2D for what DComp can't do (bitmaps, texts, etc.).

selastingeorge commented 3 years ago

let me try it out

selastingeorge commented 3 years ago

image Wow it looks Great, you have built all the controls from scratch, including the button on title bar.

selastingeorge commented 3 years ago

This is one similar to your project but uses Direct Composition Instead of Windows.UI.Composition,https://github.com/ByteJammer/Win11RCT

smourier commented 3 years ago

It sure looks nice on your Windows 11 background :-) More samples will be added to the gallery in the next days hopefully.

selastingeorge commented 3 years ago

Unfortunately my system won't support windows 11

On Wed, 25 Aug, 2021, 12:30 pm Simon Mourier, @.***> wrote:

It sure looks nice on your Windows 11 background :-) More samples will be added to the gallery in the next days hopefully.

— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub https://github.com/smourier/DirectN/issues/9#issuecomment-905237015, or unsubscribe https://github.com/notifications/unsubscribe-auth/ARKGWVL54SIUQSMZMKIHZQDT6SIKVANCNFSM47ADRRRA .