Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@
<AddSyntheticProjectReferencesForSolutionDependencies>false</AddSyntheticProjectReferencesForSolutionDependencies>
<RunApiCompat>False</RunApiCompat>
<LangVersion>12</LangVersion>

<CheckEolWorkloads>false</CheckEolWorkloads>
</PropertyGroup>
</Project>
3 changes: 2 additions & 1 deletion dirs.proj
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@
<ProjectReference Remove="samples/ControlCatalog.Desktop/*.*proj" />
</ItemGroup>

<ItemGroup Condition="!$([MSBuild]::IsOsPlatform('Windows'))">
<ItemGroup>
<!-- Build mobile backends only on Windows, where we have installed android workload -->
<ProjectReference Remove="src/Android/**/*.*proj" />
<ProjectReference Remove="src/Browser/**/*.*proj" />
<ProjectReference Remove="src/iOS/**/*.*proj" />
<ProjectReference Remove="src/Tizen/**/*.*proj" />
</ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"sdk": {
"version": "8.0.404",

"rollForward": "latestFeature"
},
"msbuild-sdks": {
Expand Down
16 changes: 8 additions & 8 deletions nukebuild/Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,14 @@ DotNetTestSettings ApplySetting(DotNetTestSettings c, Configure<DotNetTestSettin
.OnlyWhenStatic(() => !Parameters.SkipPreviewer)
.Executes(() =>
{
var webappDir = RootDirectory / "src" / "Avalonia.DesignerSupport" / "Remote" / "HtmlTransport" / "webapp";

NpmTasks.NpmInstall(c => c
.SetProcessWorkingDirectory(webappDir)
.SetProcessArgumentConfigurator(a => a.Add("--silent")));
NpmTasks.NpmRun(c => c
.SetProcessWorkingDirectory(webappDir)
.SetCommand("dist"));
//var webappDir = RootDirectory / "src" / "Avalonia.DesignerSupport" / "Remote" / "HtmlTransport" / "webapp";

//NpmTasks.NpmInstall(c => c
// .SetProcessWorkingDirectory(webappDir)
// .SetProcessArgumentConfigurator(a => a.Add("--silent")));
//NpmTasks.NpmRun(c => c
// .SetProcessWorkingDirectory(webappDir)
// .SetCommand("dist"));
});

Target CompileNative => _ => _
Expand Down
2 changes: 1 addition & 1 deletion nukebuild/BuildParameters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public class BuildParameters
public bool IsNuGetRelease { get; }
public bool PublishTestResults { get; }
public string Version { get; set; }
public const string LocalBuildVersion = "9999.0.0-localbuild";
public const string LocalBuildVersion = "11.3.6-hotfix.4";
public bool IsPackingToLocalCache { get; private set; }

public AbsolutePath ArtifactsDir { get; }
Expand Down
3 changes: 2 additions & 1 deletion src/Browser/Avalonia.Browser/Avalonia.Browser.csproj
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>$(AvsCurrentTargetFramework);$(AvsCurrentBrowserTargetFramework)</TargetFrameworks>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<AvsIncludeSkiaSharp3>true</AvsIncludeSkiaSharp3>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System;
using System.Numerics;
using System.Threading;
using Avalonia.Controls;
using Avalonia.OpenGL.Egl;
using Avalonia.Reactive;
using MicroCom.Runtime;
Expand Down Expand Up @@ -51,4 +51,13 @@ public IDisposable BeginTransaction()
Monitor.Exit(_shared.SyncRoot);
});
}

public bool IsTransparency => _transparencyLevel != WindowTransparencyLevel.None;

public void SetTransparencyLevel(WindowTransparencyLevel transparencyLevel)
{
_transparencyLevel = transparencyLevel;
}

private WindowTransparencyLevel _transparencyLevel;
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
using System;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;

using Avalonia.Controls;
using Avalonia.Controls.Shapes;
using Avalonia.OpenGL.Egl;
using Avalonia.Platform;
using Avalonia.Win32.DirectX;
using Avalonia.Win32.Interop;
using Avalonia.Win32.WinRT;

using MicroCom.Runtime;

namespace Avalonia.Win32.DComposition;
Expand All @@ -25,6 +31,7 @@ public IDirect3D11TextureRenderTarget CreateRenderTarget(IPlatformGraphicsContex
{
_window ??= new DirectCompositedWindow(_info, _shared);
SetBlur(_blurEffect);
_window.SetTransparencyLevel(_windowTransparencyLevel);

return new DirectCompositedWindowRenderTarget(context, d3dDevice, _shared, _window);
}
Expand All @@ -43,18 +50,28 @@ public void SetBlur(BlurEffect enable)
_blurEffect = enable;
// _window?.SetBlur(enable);
}

public void SetTransparencyLevel(WindowTransparencyLevel transparencyLevel)
{
_windowTransparencyLevel = transparencyLevel;
_window?.SetTransparencyLevel(transparencyLevel);
}

private WindowTransparencyLevel _windowTransparencyLevel;
}

internal class DirectCompositedWindowRenderTarget : IDirect3D11TextureRenderTarget
{
private static readonly Guid IID_ID3D11Texture2D = Guid.Parse("6f15aaf2-d208-4e89-9ab4-489535d34f9c");

private readonly IPlatformGraphicsContext _context;
private readonly DirectCompositionShared _shared;
private readonly DirectCompositedWindow _window;
private readonly IDCompositionVirtualSurface _surface;
private IDCompositionVirtualSurface _surface;
private bool _lost;
private PixelSize _size;
private readonly IUnknown _d3dDevice;
private bool _isSurfaceSupportTransparency;

public DirectCompositedWindowRenderTarget(
IPlatformGraphicsContext context, IntPtr d3dDevice,
Expand All @@ -63,13 +80,25 @@ public DirectCompositedWindowRenderTarget(
_d3dDevice = MicroComRuntime.CreateProxyFor<IUnknown>(d3dDevice, false).CloneReference();

_context = context;
_shared = shared;
_window = window;

using (var surfaceFactory = shared.Device.CreateSurfaceFactory(_d3dDevice))
{
_surface = surfaceFactory.CreateVirtualSurface(1, 1, DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM,
DXGI_ALPHA_MODE.DXGI_ALPHA_MODE_PREMULTIPLIED);
}
CreateSurface(window);
}

[MemberNotNull(nameof(_surface))]
private void CreateSurface(DirectCompositedWindow window)
{
using var surfaceFactory = _shared.Device.CreateSurfaceFactory(_d3dDevice);

const uint initialSize = 1;
var alphaMode = window.IsTransparency ?
DXGI_ALPHA_MODE.DXGI_ALPHA_MODE_PREMULTIPLIED :
DXGI_ALPHA_MODE.DXGI_ALPHA_MODE_IGNORE;
_isSurfaceSupportTransparency = window.IsTransparency;

_surface = surfaceFactory.CreateVirtualSurface(initialSize, initialSize, DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM,
alphaMode);
}

public void Dispose()
Expand All @@ -88,9 +117,19 @@ public unsafe IDirect3D11TextureRenderTargetRenderSession BeginDraw()
bool needsEndDraw = false;
try
{
bool forceResize = false;
if (_window.IsTransparency != _isSurfaceSupportTransparency)
{
_surface.Dispose();

CreateSurface(_window);

forceResize = true;
}

var size = _window.WindowInfo.Size;
var scale = _window.WindowInfo.Scaling;
if (_size != size)
if (forceResize || _size != size)
{
_surface.Resize((ushort)size.Width, (ushort)size.Height);
_size = size;
Expand Down
8 changes: 8 additions & 0 deletions src/Windows/Avalonia.Win32/DirectX/DirectXEnums.cs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,14 @@ internal enum DXGI_ERROR : uint
DXGI_ERROR_WAS_STILL_DRAWING = 0x887A000A
}

[Flags]
internal enum DXGI_MWA : uint
{
DXGI_MWA_NO_WINDOW_CHANGES = 1,
DXGI_MWA_NO_ALT_ENTER = 2,
DXGI_MWA_NO_PRINT_SCREEN = 4
}

internal static class DxgiErrorExtensions
{
public static bool IsDeviceLostError(this DXGI_ERROR error)
Expand Down
60 changes: 55 additions & 5 deletions src/Windows/Avalonia.Win32/DirectX/DxgiConnection.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Avalonia.Logging;
using Avalonia.OpenGL.Egl;
using Avalonia.Rendering;
using static Avalonia.Win32.Interop.UnmanagedMethods;
using static Avalonia.Win32.DirectX.DirectXUnmanagedMethods;

using MicroCom.Runtime;

using Windows.Win32;
using Windows.Win32.Graphics.Gdi;

using static Avalonia.Win32.DirectX.DirectXUnmanagedMethods;
using static Avalonia.Win32.Interop.UnmanagedMethods;

namespace Avalonia.Win32.DirectX
{
internal unsafe class DxgiConnection : IRenderTimer, IWindowsSurfaceFactory
Expand Down Expand Up @@ -111,6 +118,8 @@ private void GetBestOutputToVWaitOn()

ushort adapterIndex = 0;

Dictionary<HMONITOR /*MonitorHandler*/, uint /*Frequency*/> monitorFrequencies = GetAllMonitorFrequencies();

// this looks odd, but that's just how one enumerates adapters in DXGI
while (fact.EnumAdapters(adapterIndex, &adapterPointer) == 0)
{
Expand All @@ -122,8 +131,12 @@ private void GetBestOutputToVWaitOn()
using var output = MicroComRuntime.CreateProxyFor<IDXGIOutput>(outputPointer, true);
DXGI_OUTPUT_DESC outputDesc = output.Desc;

var screen = Win32Platform.Instance.Screen.ScreenFromHMonitor((IntPtr)outputDesc.Monitor.Value);
var frequency = screen?.Frequency ?? highestRefreshRate;
var hMonitor = new HMONITOR((nint) outputDesc.Monitor.Value);

var frequency =
monitorFrequencies.TryGetValue(hMonitor, out uint frequencyValue) ?
frequencyValue :
highestRefreshRate;

if (highestRefreshRate < frequency)
{
Expand All @@ -145,6 +158,33 @@ private void GetBestOutputToVWaitOn()

}

private unsafe Dictionary<HMONITOR /*MonitorHandler*/, uint /*Frequency*/> GetAllMonitorFrequencies()
{
var monitorHandlers = ScreenImpl.GetAllDisplayMonitorHandlers();
var dictionary = new Dictionary<HMONITOR /*MonitorHandler*/, uint /*Frequency*/>(monitorHandlers.Count);

foreach (var monitorHandler in monitorHandlers)
{
var info = MONITORINFOEX.Create();
var hMonitor = new HMONITOR(monitorHandler);
PInvoke.GetMonitorInfo(hMonitor, (MONITORINFO*)&info);

var deviceMode = new DEVMODEW
{
dmFields = DEVMODE_FIELD_FLAGS.DM_DISPLAYORIENTATION | DEVMODE_FIELD_FLAGS.DM_DISPLAYFREQUENCY,
dmSize = (ushort)Marshal.SizeOf<DEVMODEW>()
};
PInvoke.EnumDisplaySettings(info.szDevice.ToString(), ENUM_DISPLAY_SETTINGS_MODE.ENUM_CURRENT_SETTINGS,
ref deviceMode);

var frequency = deviceMode.dmDisplayFrequency;

dictionary[hMonitor] = frequency;
}

return dictionary;
}

// Used the windows composition as a blueprint for this startup/creation
private static bool TryCreateAndRegisterCore()
{
Expand All @@ -168,12 +208,22 @@ private static bool TryCreateAndRegisterCore()
});
thread.IsBackground = true;
thread.SetApartmentState(System.Threading.ApartmentState.STA);
thread.Name = "DxgiRenderTimerLoop";
thread.Start();
// block until
return tcs.Task.Result;
}

public bool RequiresNoRedirectionBitmap => false;
public bool RequiresNoRedirectionBitmap => IsTransparencySupported()
? true
: false;

public object CreateSurface(EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo info) => new DxgiSwapchainWindow(this, info);

public static bool IsTransparencySupported()
{
// We can use the DirectComposited+CreateSwapChainForComposition to create the Transparency window.
return Win32Platform.WindowsVersion >= PlatformConstants.Windows8_1;
}
}
}
Loading