diff --git a/src/Avalonia.Base/Platform/IPlatformThreadingInterface.cs b/src/Avalonia.Base/Platform/IPlatformThreadingInterface.cs index e4f24d8638..202ccf9495 100644 --- a/src/Avalonia.Base/Platform/IPlatformThreadingInterface.cs +++ b/src/Avalonia.Base/Platform/IPlatformThreadingInterface.cs @@ -29,6 +29,5 @@ namespace Avalonia.Platform bool CurrentThreadIsLoopThread { get; } event Action Signaled; - } } diff --git a/src/Avalonia.Controls/Application.cs b/src/Avalonia.Controls/Application.cs index 1991f49ac0..0fd4572088 100644 --- a/src/Avalonia.Controls/Application.cs +++ b/src/Avalonia.Controls/Application.cs @@ -112,6 +112,11 @@ namespace Avalonia /// public Styles Styles { get; } = new Styles(); + /// + /// Gets the application's render loop. + /// + public IRenderLoop RenderLoop { get; private set; } + /// /// Gets the styling parent of the application, which is null. /// @@ -167,6 +172,7 @@ namespace Avalonia AvaloniaSynchronizationContext.InstallIfNeeded(); FocusManager = new FocusManager(); InputManager = new InputManager(); + RenderLoop = new RenderLoop(60); AvaloniaLocator.CurrentMutable .Bind().ToTransient() @@ -177,7 +183,8 @@ namespace Avalonia .Bind().ToTransient() .Bind().ToConstant(_styler) .Bind().ToSingleton() - .Bind().ToTransient() + .Bind().ToTransient() + .Bind().ToConstant(RenderLoop) .Bind().ToConstant(this); } } diff --git a/src/Avalonia.Controls/Avalonia.Controls.csproj b/src/Avalonia.Controls/Avalonia.Controls.csproj index 7192abd620..6183604280 100644 --- a/src/Avalonia.Controls/Avalonia.Controls.csproj +++ b/src/Avalonia.Controls/Avalonia.Controls.csproj @@ -72,7 +72,6 @@ - diff --git a/src/Avalonia.Controls/Platform/ITopLevelRenderer.cs b/src/Avalonia.Controls/Platform/ITopLevelRenderer.cs deleted file mode 100644 index 1653ff0a6d..0000000000 --- a/src/Avalonia.Controls/Platform/ITopLevelRenderer.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Avalonia.Platform; -using Avalonia.Rendering; -using Avalonia.Threading; - -namespace Avalonia.Controls.Platform -{ - public interface ITopLevelRenderer - { - void Attach(TopLevel topLevel); - } - - - class DefaultTopLevelRenderer : ITopLevelRenderer - { - - public void Attach(TopLevel topLevel) - { - var resources = new List(); - var initialClientSize = topLevel.PlatformImpl.ClientSize; - - - var queueManager = ((IRenderRoot)topLevel).RenderQueueManager; - - if (queueManager == null) - return; - - - var viewport = PlatformManager.CreateRenderTarget(topLevel.PlatformImpl); - resources.Add(viewport); - resources.Add(queueManager.RenderNeeded.Subscribe(_ - => - Dispatcher.UIThread.InvokeAsync(() => topLevel.PlatformImpl.Invalidate(new Rect(topLevel.ClientSize))))); - - topLevel.PlatformImpl.Paint = rect => - { - try - { - viewport.Render(topLevel); - } - catch (RenderTargetCorruptedException ex) - { - Logging.Logger.Error("Renderer", this, "Render target was corrupted. Exception: {0}", ex); - viewport.Dispose(); - resources.Remove(viewport); - viewport = PlatformManager.CreateRenderTarget(topLevel.PlatformImpl); - resources.Add(viewport); - topLevel.PlatformImpl.Paint(rect); // Retry painting - } - queueManager.RenderFinished(); - }; - - topLevel.Closed += delegate - { - foreach (var disposable in resources) - disposable.Dispose(); - resources.Clear(); - }; - - } - } -} diff --git a/src/Avalonia.Controls/Platform/PlatformManager.cs b/src/Avalonia.Controls/Platform/PlatformManager.cs index e57eb21b91..3283f64ca2 100644 --- a/src/Avalonia.Controls/Platform/PlatformManager.cs +++ b/src/Avalonia.Controls/Platform/PlatformManager.cs @@ -13,13 +13,6 @@ namespace Avalonia.Controls.Platform static bool s_designerMode; private static double _designerScalingFactor = 1; - public static IRenderTarget CreateRenderTarget(ITopLevelImpl window) - { - return AvaloniaLocator.Current - .GetService() - .CreateRenderer(window.Handle); - } - public static IDisposable DesignerMode() { s_designerMode = true; diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index 47660b27e8..2190c04456 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -45,11 +45,11 @@ namespace Avalonia.Controls public static readonly StyledProperty PointerOverElementProperty = AvaloniaProperty.Register(nameof(IInputRoot.PointerOverElement)); - private readonly IRenderQueueManager _renderQueueManager; private readonly IInputManager _inputManager; private readonly IAccessKeyHandler _accessKeyHandler; private readonly IKeyboardNavigationHandler _keyboardNavigationHandler; private readonly IApplicationLifecycle _applicationLifecycle; + private readonly IPlatformRenderInterface _renderInterface; private Size _clientSize; private bool _isActive; @@ -86,23 +86,26 @@ namespace Avalonia.Controls } PlatformImpl = impl; - dependencyResolver = dependencyResolver ?? AvaloniaLocator.Current; - var renderInterface = TryGetService(dependencyResolver); + var styler = TryGetService(dependencyResolver); + _accessKeyHandler = TryGetService(dependencyResolver); _inputManager = TryGetService(dependencyResolver); _keyboardNavigationHandler = TryGetService(dependencyResolver); - _renderQueueManager = TryGetService(dependencyResolver); _applicationLifecycle = TryGetService(dependencyResolver); + _renderInterface = TryGetService(dependencyResolver); - (dependencyResolver.GetService() ?? new DefaultTopLevelRenderer()).Attach(this); + var renderLoop = TryGetService(dependencyResolver); + Renderer = TryGetService(dependencyResolver); + Renderer?.Attach(this, renderLoop); PlatformImpl.SetInputRoot(this); PlatformImpl.Activated = HandleActivated; PlatformImpl.Deactivated = HandleDeactivated; PlatformImpl.Closed = HandleClosed; PlatformImpl.Input = HandleInput; + PlatformImpl.Paint = Renderer != null ? (Action)Renderer.Render : null; PlatformImpl.Resized = HandleResized; PlatformImpl.ScalingChanged = HandleScalingChanged; PlatformImpl.PositionChanged = HandlePositionChanged; @@ -180,9 +183,9 @@ namespace Avalonia.Controls } /// - /// Gets the window render manager. + /// Gets the renderer for the window. /// - IRenderQueueManager IRenderRoot.RenderQueueManager => _renderQueueManager; + public IRenderer Renderer { get; } /// /// Gets the access key handler for the window. @@ -232,6 +235,18 @@ namespace Avalonia.Controls private set; } + /// + IRenderTarget IRenderRoot.CreateRenderTarget() + { + return _renderInterface.CreateRenderer(PlatformImpl.Handle); + } + + /// + void IRenderRoot.Invalidate(Rect rect) + { + PlatformImpl.Invalidate(rect); + } + /// Point IRenderRoot.PointToClient(Point p) { @@ -322,8 +337,8 @@ namespace Avalonia.Controls } /// - /// Tries to get a service from an , throwing an - /// exception if not found. + /// Tries to get a service from an , logging a + /// warning if not found. /// /// The service type. /// The resolver. diff --git a/src/Avalonia.SceneGraph/Avalonia.SceneGraph.csproj b/src/Avalonia.SceneGraph/Avalonia.SceneGraph.csproj index 1f2734b2e9..39527813b0 100644 --- a/src/Avalonia.SceneGraph/Avalonia.SceneGraph.csproj +++ b/src/Avalonia.SceneGraph/Avalonia.SceneGraph.csproj @@ -101,6 +101,11 @@ + + + + + @@ -138,9 +143,6 @@ - - - diff --git a/src/Avalonia.SceneGraph/Rendering/IRenderLoop.cs b/src/Avalonia.SceneGraph/Rendering/IRenderLoop.cs new file mode 100644 index 0000000000..504dc185a2 --- /dev/null +++ b/src/Avalonia.SceneGraph/Rendering/IRenderLoop.cs @@ -0,0 +1,9 @@ +using System; + +namespace Avalonia.Rendering +{ + public interface IRenderLoop + { + event EventHandler Tick; + } +} \ No newline at end of file diff --git a/src/Avalonia.SceneGraph/Rendering/IRenderQueueManager.cs b/src/Avalonia.SceneGraph/Rendering/IRenderQueueManager.cs deleted file mode 100644 index 580e8b3046..0000000000 --- a/src/Avalonia.SceneGraph/Rendering/IRenderQueueManager.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) The Avalonia Project. All rights reserved. -// Licensed under the MIT license. See licence.md file in the project root for full license information. - -using System; -using System.Reactive; -using Avalonia.VisualTree; - -namespace Avalonia.Rendering -{ - /// - /// Defines the interface for a . - /// - public interface IRenderQueueManager - { - /// - /// Gets an observable that is fired whenever a render is required. - /// - IObservable RenderNeeded { get; } - - /// - /// Invalidates the render for the specified visual and raises . - /// - /// The visual. - void InvalidateRender(IVisual visual); - - /// - /// Called when rendering is finished. - /// - void RenderFinished(); - } -} diff --git a/src/Avalonia.SceneGraph/Rendering/IRenderRoot.cs b/src/Avalonia.SceneGraph/Rendering/IRenderRoot.cs index 254cb5bc1b..50cda1b1b8 100644 --- a/src/Avalonia.SceneGraph/Rendering/IRenderRoot.cs +++ b/src/Avalonia.SceneGraph/Rendering/IRenderRoot.cs @@ -1,19 +1,38 @@ // Copyright (c) The Avalonia Project. All rights reserved. // Licensed under the MIT license. See licence.md file in the project root for full license information. +using System; using Avalonia.Platform; +using Avalonia.VisualTree; namespace Avalonia.Rendering { /// /// Represents the root of a renderable tree. /// - public interface IRenderRoot + public interface IRenderRoot : IVisual { /// - /// Gets the render manager which schedules renders. + /// Gets the client size of the window. /// - IRenderQueueManager RenderQueueManager { get; } + Size ClientSize { get; } + + /// + /// Gets the renderer for the window. + /// + IRenderer Renderer { get; } + + /// + /// Creates a render target for the window. + /// + /// An . + IRenderTarget CreateRenderTarget(); + + /// + /// Adds a rectangle to the window's dirty region. + /// + /// The rectangle. + void Invalidate(Rect rect); /// /// Converts a point from screen to client coordinates. diff --git a/src/Avalonia.SceneGraph/Rendering/IRenderer.cs b/src/Avalonia.SceneGraph/Rendering/IRenderer.cs new file mode 100644 index 0000000000..864dfd9ae3 --- /dev/null +++ b/src/Avalonia.SceneGraph/Rendering/IRenderer.cs @@ -0,0 +1,17 @@ +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using System; +using Avalonia.VisualTree; + +namespace Avalonia.Rendering +{ + public interface IRenderer : IDisposable + { + void AddDirty(IVisual visual); + + void Attach(IRenderRoot root, IRenderLoop renderLoop); + + void Render(Rect rect); + } +} \ No newline at end of file diff --git a/src/Avalonia.SceneGraph/Rendering/RenderLoop.cs b/src/Avalonia.SceneGraph/Rendering/RenderLoop.cs new file mode 100644 index 0000000000..a7ba01b1bc --- /dev/null +++ b/src/Avalonia.SceneGraph/Rendering/RenderLoop.cs @@ -0,0 +1,66 @@ +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using System; +using Avalonia.Platform; + +namespace Avalonia.Rendering +{ + public class RenderLoop : IRenderLoop + { + private readonly int _fps; + private IPlatformThreadingInterface _threading; + private int _subscriberCount; + private EventHandler _tick; + private IDisposable _subscription; + + public RenderLoop(int fps) + { + _fps = fps; + } + + public event EventHandler Tick + { + add + { + if (_subscriberCount++ == 0) + { + Start(); + } + + _tick += value; + } + + remove + { + if (--_subscriberCount == 0) + { + Stop(); + } + + _tick -= value; + } + } + + protected void Start() + { + if (_threading == null) + { + _threading = AvaloniaLocator.Current.GetService(); + } + + _subscription = _threading.StartTimer(TimeSpan.FromSeconds(1.0 / _fps), InternalTick); + } + + protected void Stop() + { + _subscription.Dispose(); + _subscription = null; + } + + private void InternalTick() + { + _tick(this, EventArgs.Empty); + } + } +} diff --git a/src/Avalonia.SceneGraph/Rendering/RenderQueueManager.cs b/src/Avalonia.SceneGraph/Rendering/RenderQueueManager.cs deleted file mode 100644 index 8b64788c16..0000000000 --- a/src/Avalonia.SceneGraph/Rendering/RenderQueueManager.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) The Avalonia Project. All rights reserved. -// Licensed under the MIT license. See licence.md file in the project root for full license information. - -using System; -using System.Reactive; -using System.Reactive.Subjects; -using Avalonia.VisualTree; - -namespace Avalonia.Rendering -{ - /// - /// Schedules the rendering of a tree. - /// - public class RenderQueueManager : IRenderQueueManager - { - private readonly Subject _renderNeeded = new Subject(); - - private bool _renderQueued; - - /// - /// Gets an observable that is fired whenever a render is required. - /// - public IObservable RenderNeeded => _renderNeeded; - - /// - /// Gets a value indicating whether a render is queued. - /// - public bool RenderQueued => _renderQueued; - - /// - /// Invalidates the render for the specified visual and raises . - /// - /// The visual. - public void InvalidateRender(IVisual visual) - { - if (!_renderQueued) - { - _renderQueued = true; - _renderNeeded.OnNext(Unit.Default); - } - } - - /// - /// Called when rendering is finished. - /// - public void RenderFinished() - { - _renderQueued = false; - } - } -} diff --git a/src/Avalonia.SceneGraph/Rendering/Renderer.cs b/src/Avalonia.SceneGraph/Rendering/Renderer.cs new file mode 100644 index 0000000000..bacef30e48 --- /dev/null +++ b/src/Avalonia.SceneGraph/Rendering/Renderer.cs @@ -0,0 +1,63 @@ +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using System; +using Avalonia.Platform; +using Avalonia.VisualTree; + +namespace Avalonia.Rendering +{ + public class Renderer : IDisposable, IRenderer + { + private IRenderLoop _renderLoop; + private IRenderRoot _root; + private IRenderTarget _renderTarget; + private bool _dirty; + + public void Attach(IRenderRoot root, IRenderLoop renderLoop) + { + Contract.Requires(root != null); + + _root = root; + _renderLoop = renderLoop; + _renderLoop.Tick += OnRenderLoopTick; + } + + public void AddDirty(IVisual visual) + { + _dirty = true; + } + + public void Dispose() + { + _renderLoop.Tick -= OnRenderLoopTick; + } + + public void Render(Rect rect) + { + if (_renderTarget == null) + { + _renderTarget = _root.CreateRenderTarget(); + } + + try + { + _renderTarget.Render(_root); + } + catch (RenderTargetCorruptedException ex) + { + Logging.Logger.Information("Renderer", this, "Render target was corrupted. Exception: {0}", ex); + _renderTarget.Dispose(); + _renderTarget = null; + } + } + + private void OnRenderLoopTick(object sender, EventArgs e) + { + if (_dirty) + { + _root.Invalidate(new Rect(_root.ClientSize)); + } + } + } +} diff --git a/src/Avalonia.SceneGraph/Rendering/RendererMixin.cs b/src/Avalonia.SceneGraph/Rendering/RendererMixin.cs index 416cdb9855..3c4f14046d 100644 --- a/src/Avalonia.SceneGraph/Rendering/RendererMixin.cs +++ b/src/Avalonia.SceneGraph/Rendering/RendererMixin.cs @@ -1,4 +1,4 @@ -// Copyright (c) The Avalonia Project. All rights reserved. +// Copyright (c) The Avalonia Project. All rights reserved. // Licensed under the MIT license. See licence.md file in the project root for full license information. using System; diff --git a/src/Avalonia.SceneGraph/Visual.cs b/src/Avalonia.SceneGraph/Visual.cs index 54786ac85a..dbc678eee5 100644 --- a/src/Avalonia.SceneGraph/Visual.cs +++ b/src/Avalonia.SceneGraph/Visual.cs @@ -259,7 +259,7 @@ namespace Avalonia /// public void InvalidateVisual() { - VisualRoot?.RenderQueueManager?.InvalidateRender(this); + VisualRoot?.Renderer?.AddDirty(this); } /// diff --git a/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization.cs b/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization.cs index 02dffdead6..0942b43f86 100644 --- a/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization.cs +++ b/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization.cs @@ -10,6 +10,7 @@ using Avalonia.Controls.Presenters; using Avalonia.Controls.Primitives; using Avalonia.Controls.Templates; using Avalonia.Layout; +using Avalonia.Platform; using Avalonia.Rendering; using Avalonia.UnitTests; using Xunit; @@ -315,7 +316,18 @@ namespace Avalonia.Controls.UnitTests.Presenters private class TestScroller : ScrollContentPresenter, IRenderRoot { - public IRenderQueueManager RenderQueueManager { get; } + public IRenderer Renderer { get; } + public Size ClientSize { get; } + + public IRenderTarget CreateRenderTarget() + { + throw new NotImplementedException(); + } + + public void Invalidate(Rect rect) + { + throw new NotImplementedException(); + } public Point PointToClient(Point point) { diff --git a/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs b/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs index 2a59227b52..417af4a6e6 100644 --- a/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs +++ b/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs @@ -12,6 +12,7 @@ using Avalonia.Controls.Presenters; using Avalonia.Controls.Primitives; using Avalonia.Controls.Templates; using Avalonia.Input; +using Avalonia.Platform; using Avalonia.Rendering; using Avalonia.UnitTests; using Xunit; @@ -977,7 +978,18 @@ namespace Avalonia.Controls.UnitTests.Presenters private class TestScroller : ScrollContentPresenter, IRenderRoot { - public IRenderQueueManager RenderQueueManager { get; } + public IRenderer Renderer { get; } + public Size ClientSize { get; } + + public IRenderTarget CreateRenderTarget() + { + throw new NotImplementedException(); + } + + public void Invalidate(Rect rect) + { + throw new NotImplementedException(); + } public Point PointToClient(Point point) { diff --git a/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs b/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs index 54338a773e..367070b37a 100644 --- a/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs @@ -268,7 +268,6 @@ namespace Avalonia.Controls.UnitTests.Primitives globalStyles.Setup(x => x.Styles).Returns(styles); var renderInterface = new Mock(); - renderInterface.Setup(x => x.CreateRenderer(It.IsAny())).Returns(() => new Mock().Object); AvaloniaLocator.CurrentMutable .Bind().ToTransient() diff --git a/tests/Avalonia.Layout.UnitTests/FullLayoutTests.cs b/tests/Avalonia.Layout.UnitTests/FullLayoutTests.cs index b1f39673c4..b3e9b981a5 100644 --- a/tests/Avalonia.Layout.UnitTests/FullLayoutTests.cs +++ b/tests/Avalonia.Layout.UnitTests/FullLayoutTests.cs @@ -137,7 +137,6 @@ namespace Avalonia.Layout.UnitTests var formattedText = fixture.Create(); var globalStyles = new Mock(); var renderInterface = fixture.Create(); - var renderManager = fixture.Create(); var windowImpl = new Mock(); windowImpl.SetupProperty(x => x.ClientSize); @@ -151,7 +150,6 @@ namespace Avalonia.Layout.UnitTests .Bind().ToConstant(new LayoutManager()) .Bind().ToConstant(new AppBuilder().RuntimePlatform) .Bind().ToConstant(renderInterface) - .Bind().ToConstant(renderManager) .Bind().ToConstant(new Styler()) .Bind().ToConstant(new WindowingPlatformMock(() => windowImpl.Object)); diff --git a/tests/Avalonia.SceneGraph.UnitTests/TestRoot.cs b/tests/Avalonia.SceneGraph.UnitTests/TestRoot.cs index 7ac49c4b89..aa5eb64691 100644 --- a/tests/Avalonia.SceneGraph.UnitTests/TestRoot.cs +++ b/tests/Avalonia.SceneGraph.UnitTests/TestRoot.cs @@ -9,12 +9,19 @@ namespace Avalonia.SceneGraph.UnitTests { public class TestRoot : TestVisual, IRenderRoot { - public IRenderTarget RenderTarget + public Size ClientSize { get; } + + public IRenderTarget CreateRenderTarget() { - get { throw new NotImplementedException(); } + throw new NotImplementedException(); + } + + public void Invalidate(Rect rect) + { + throw new NotImplementedException(); } - public IRenderQueueManager RenderQueueManager + public IRenderer Renderer { get { throw new NotImplementedException(); } } diff --git a/tests/Avalonia.UnitTests/TestRoot.cs b/tests/Avalonia.UnitTests/TestRoot.cs index 769d00b3b6..064d5d36d3 100644 --- a/tests/Avalonia.UnitTests/TestRoot.cs +++ b/tests/Avalonia.UnitTests/TestRoot.cs @@ -41,7 +41,17 @@ namespace Avalonia.UnitTests public IRenderTarget RenderTarget => null; - public IRenderQueueManager RenderQueueManager => null; + public IRenderer Renderer => null; + + public IRenderTarget CreateRenderTarget() + { + throw new NotImplementedException(); + } + + public void Invalidate(Rect rect) + { + throw new NotImplementedException(); + } public Point PointToClient(Point p) => p; diff --git a/tests/Avalonia.UnitTests/TestServices.cs b/tests/Avalonia.UnitTests/TestServices.cs index d322a6dbbc..8dc838163f 100644 --- a/tests/Avalonia.UnitTests/TestServices.cs +++ b/tests/Avalonia.UnitTests/TestServices.cs @@ -11,6 +11,7 @@ using Avalonia.Platform; using Avalonia.Shared.PlatformSupport; using Avalonia.Styling; using Avalonia.Themes.Default; +using Avalonia.Rendering; namespace Avalonia.UnitTests { @@ -20,7 +21,9 @@ namespace Avalonia.UnitTests assetLoader: new AssetLoader(), layoutManager: new LayoutManager(), platform: new AppBuilder().RuntimePlatform, + renderer: Mock.Of(), renderInterface: CreateRenderInterfaceMock(), + renderLoop: Mock.Of(), standardCursorFactory: Mock.Of(), styler: new Styler(), theme: () => CreateDefaultTheme(), @@ -57,7 +60,9 @@ namespace Avalonia.UnitTests Func keyboardDevice = null, ILayoutManager layoutManager = null, IRuntimePlatform platform = null, + IRenderer renderer = null, IPlatformRenderInterface renderInterface = null, + IRenderLoop renderLoop = null, IStandardCursorFactory standardCursorFactory = null, IStyler styler = null, Func theme = null, @@ -71,7 +76,9 @@ namespace Avalonia.UnitTests KeyboardDevice = keyboardDevice; LayoutManager = layoutManager; Platform = platform; + Renderer = renderer; RenderInterface = renderInterface; + RenderLoop = renderLoop; StandardCursorFactory = standardCursorFactory; Styler = styler; Theme = theme; @@ -86,7 +93,9 @@ namespace Avalonia.UnitTests public Func KeyboardDevice { get; } public ILayoutManager LayoutManager { get; } public IRuntimePlatform Platform { get; } + public IRenderer Renderer { get; } public IPlatformRenderInterface RenderInterface { get; } + public IRenderLoop RenderLoop { get; } public IStandardCursorFactory StandardCursorFactory { get; } public IStyler Styler { get; } public Func Theme { get; } @@ -101,7 +110,9 @@ namespace Avalonia.UnitTests Func keyboardDevice = null, ILayoutManager layoutManager = null, IRuntimePlatform platform = null, + IRenderer renderer = null, IPlatformRenderInterface renderInterface = null, + IRenderLoop renderLoop = null, IStandardCursorFactory standardCursorFactory = null, IStyler styler = null, Func theme = null, @@ -116,7 +127,9 @@ namespace Avalonia.UnitTests keyboardDevice: keyboardDevice ?? KeyboardDevice, layoutManager: layoutManager ?? LayoutManager, platform: platform ?? Platform, + renderer: renderer ?? Renderer, renderInterface: renderInterface ?? RenderInterface, + renderLoop: renderLoop ?? RenderLoop, standardCursorFactory: standardCursorFactory ?? StandardCursorFactory, styler: styler ?? Styler, theme: theme ?? Theme, @@ -152,8 +165,7 @@ namespace Avalonia.UnitTests It.IsAny(), It.IsAny()) == Mock.Of() && x.CreateStreamGeometry() == Mock.Of( - y => y.Open() == Mock.Of()) && - x.CreateRenderer(It.IsAny()) == Mock.Of()); + y => y.Open() == Mock.Of())); } } } diff --git a/tests/Avalonia.UnitTests/TestTemplatedRoot.cs b/tests/Avalonia.UnitTests/TestTemplatedRoot.cs index 35ff32d721..73c9f370d6 100644 --- a/tests/Avalonia.UnitTests/TestTemplatedRoot.cs +++ b/tests/Avalonia.UnitTests/TestTemplatedRoot.cs @@ -43,7 +43,17 @@ namespace Avalonia.UnitTests public IRenderTarget RenderTarget => null; - public IRenderQueueManager RenderQueueManager => null; + public IRenderer Renderer => null; + + public IRenderTarget CreateRenderTarget() + { + throw new NotImplementedException(); + } + + public void Invalidate(Rect rect) + { + throw new NotImplementedException(); + } public Point PointToClient(Point p) => p; diff --git a/tests/Avalonia.UnitTests/UnitTestApplication.cs b/tests/Avalonia.UnitTests/UnitTestApplication.cs index d76139c809..0dec218432 100644 --- a/tests/Avalonia.UnitTests/UnitTestApplication.cs +++ b/tests/Avalonia.UnitTests/UnitTestApplication.cs @@ -7,6 +7,7 @@ using Avalonia.Layout; using Avalonia.Platform; using Avalonia.Styling; using Avalonia.Controls; +using Avalonia.Rendering; namespace Avalonia.UnitTests { @@ -42,7 +43,9 @@ namespace Avalonia.UnitTests .Bind().ToConstant(Services.KeyboardDevice?.Invoke()) .Bind().ToConstant(Services.LayoutManager) .Bind().ToConstant(Services.Platform) + .Bind().ToConstant(Services.Renderer) .Bind().ToConstant(Services.RenderInterface) + .Bind().ToConstant(Services.RenderLoop) .Bind().ToConstant(Services.ThreadingInterface) .Bind().ToConstant(Services.StandardCursorFactory) .Bind().ToConstant(Services.Styler)