Browse Source

Added Direct2D-specific IExternalDirect2DRenderTargetSurface

Nikita Tsukanov 8 years ago
parent
commit
2f34c124e6

+ 2 - 0
src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj

@@ -50,7 +50,9 @@
     </Compile>
     <Compile Include="Direct2D1Platform.cs" />
     <Compile Include="Disposable.cs" />
+    <Compile Include="ExternalRenderTarget.cs" />
     <Compile Include="HwndRenderTarget.cs" />
+    <Compile Include="IExternalDirect2DRenderTargetSurface.cs" />
     <Compile Include="Media\BrushImpl.cs" />
     <Compile Include="Media\BrushWrapper.cs" />
     <Compile Include="Media\DrawingContextImpl.cs" />

+ 5 - 0
src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs

@@ -141,6 +141,11 @@ namespace Avalonia.Direct2D1
                 if(nativeWindow.HandleDescriptor != "HWND")
                     throw new NotSupportedException("Don't know how to create a Direct2D1 renderer from " + nativeWindow.HandleDescriptor);
                 return new HwndRenderTarget(nativeWindow);
+            }
+            var external = surfaces?.OfType<IExternalDirect2DRenderTargetSurface>();
+            if (external != null)
+            {
+                
             }
             throw new NotSupportedException("Don't know how to create a Direct2D1 renderer from any of provided surfaces");
         }

+ 50 - 0
src/Windows/Avalonia.Direct2D1/ExternalRenderTarget.cs

@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Direct2D1.Media;
+using Avalonia.Platform;
+using Avalonia.Rendering;
+using SharpDX;
+using DirectWriteFactory = SharpDX.DirectWrite.Factory;
+
+namespace Avalonia.Direct2D1
+{
+    class ExternalRenderTarget : IRenderTarget
+    {
+        private readonly IExternalDirect2DRenderTargetSurface _externalRenderTargetProvider;
+        private readonly DirectWriteFactory _dwFactory;
+        private SharpDX.Direct2D1.RenderTarget _target;
+        public ExternalRenderTarget(IExternalDirect2DRenderTargetSurface externalRenderTargetProvider,
+            DirectWriteFactory dwFactory)
+        {
+            _externalRenderTargetProvider = externalRenderTargetProvider;
+            _dwFactory = dwFactory;
+        }
+
+        public void Dispose()
+        {
+            _target?.Dispose();
+            _target = null;
+        }
+
+        public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer)
+        {
+            _target = _target ?? _externalRenderTargetProvider.CreateRenderTarget();
+            _externalRenderTargetProvider.BeforeDrawing();
+            return new DrawingContextImpl(visualBrushRenderer, _target, _dwFactory, null, () =>
+            {
+                try
+                {
+                    _externalRenderTargetProvider.AfterDrawing();
+                }
+                catch (SharpDXException ex) when ((uint) ex.HResult == 0x8899000C) // D2DERR_RECREATE_TARGET
+                {
+                    _target?.Dispose();
+                    _target = null;
+                }
+            });
+        }
+    }
+}

+ 15 - 0
src/Windows/Avalonia.Direct2D1/IExternalDirect2DRenderTargetSurface.cs

@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Avalonia.Direct2D1
+{
+    public interface IExternalDirect2DRenderTargetSurface
+    {
+        SharpDX.Direct2D1.RenderTarget CreateRenderTarget();
+        void BeforeDrawing();
+        void AfterDrawing();
+    }
+}

+ 6 - 1
src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs

@@ -23,6 +23,7 @@ namespace Avalonia.Direct2D1.Media
         private readonly IVisualBrushRenderer _visualBrushRenderer;
         private readonly SharpDX.Direct2D1.RenderTarget _renderTarget;
         private readonly SharpDX.DXGI.SwapChain1 _swapChain;
+        private readonly Action _finishedCallback;
         private SharpDX.DirectWrite.Factory _directWriteFactory;
 
         /// <summary>
@@ -32,15 +33,18 @@ namespace Avalonia.Direct2D1.Media
         /// <param name="renderTarget">The render target to draw to.</param>
         /// <param name="directWriteFactory">The DirectWrite factory.</param>
         /// <param name="swapChain">An optional swap chain associated with this drawing context.</param>
+        /// <param name="finishedCallback">An optional delegate to be called when context is disposed.</param>
         public DrawingContextImpl(
             IVisualBrushRenderer visualBrushRenderer,
             SharpDX.Direct2D1.RenderTarget renderTarget,
             SharpDX.DirectWrite.Factory directWriteFactory,
-            SharpDX.DXGI.SwapChain1 swapChain = null)
+            SharpDX.DXGI.SwapChain1 swapChain = null,
+            Action finishedCallback = null)
         {
             _visualBrushRenderer = visualBrushRenderer;
             _renderTarget = renderTarget;
             _swapChain = swapChain;
+            _finishedCallback = finishedCallback;
             _directWriteFactory = directWriteFactory;
             _swapChain = swapChain;
             _renderTarget.BeginDraw();
@@ -73,6 +77,7 @@ namespace Avalonia.Direct2D1.Media
                 _renderTarget.EndDraw();
 
                 _swapChain?.Present(1, SharpDX.DXGI.PresentFlags.None);
+                _finishedCallback?.Invoke();
             }
             catch (SharpDXException ex) when ((uint)ex.HResult == 0x8899000C) // D2DERR_RECREATE_TARGET
             {