Browse Source

Merge remote-tracking branch 'origin/master' into feature/ImePreeditText

feature/ImePreeditText
Dan Walmsley 4 years ago
parent
commit
1bfaa6f29c
  1. 22
      src/Avalonia.Base/Rendering/Composition/CompositingRenderer.cs
  2. 33
      src/Avalonia.Base/Rendering/DirtyVisuals.cs
  3. 3
      src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs
  4. 9
      src/Linux/Avalonia.LinuxFramebuffer/LinuxFramebufferPlatform.cs
  5. 5
      src/iOS/Avalonia.iOS/AvaloniaView.cs
  6. 7
      src/iOS/Avalonia.iOS/Platform.cs

22
src/Avalonia.Base/Rendering/Composition/CompositingRenderer.cs

@ -29,6 +29,7 @@ public class CompositingRenderer : IRendererWithCompositor
private bool _queuedUpdate; private bool _queuedUpdate;
private Action _update; private Action _update;
private Action _invalidateScene; private Action _invalidateScene;
private bool _updating;
internal CompositionTarget CompositionTarget; internal CompositionTarget CompositionTarget;
@ -77,6 +78,8 @@ public class CompositingRenderer : IRendererWithCompositor
/// <inheritdoc/> /// <inheritdoc/>
public void AddDirty(IVisual visual) public void AddDirty(IVisual visual)
{ {
if (_updating)
throw new InvalidOperationException("Visual was invalidated during the render pass");
_dirty.Add((Visual)visual); _dirty.Add((Visual)visual);
QueueUpdate(); QueueUpdate();
} }
@ -107,6 +110,8 @@ public class CompositingRenderer : IRendererWithCompositor
/// <inheritdoc/> /// <inheritdoc/>
public void RecalculateChildren(IVisual visual) public void RecalculateChildren(IVisual visual)
{ {
if (_updating)
throw new InvalidOperationException("Visual was invalidated during the render pass");
_recalculateChildren.Add((Visual)visual); _recalculateChildren.Add((Visual)visual);
QueueUpdate(); QueueUpdate();
} }
@ -191,7 +196,7 @@ public class CompositingRenderer : IRendererWithCompositor
private void InvalidateScene() => private void InvalidateScene() =>
SceneInvalidated?.Invoke(this, new SceneInvalidatedEventArgs(_root, new Rect(_root.ClientSize))); SceneInvalidated?.Invoke(this, new SceneInvalidatedEventArgs(_root, new Rect(_root.ClientSize)));
private void Update() private void UpdateCore()
{ {
_queuedUpdate = false; _queuedUpdate = false;
foreach (var visual in _dirty) foreach (var visual in _dirty)
@ -240,6 +245,21 @@ public class CompositingRenderer : IRendererWithCompositor
CompositionTarget.Scaling = _root.RenderScaling; CompositionTarget.Scaling = _root.RenderScaling;
Compositor.InvokeOnNextCommit(_invalidateScene); Compositor.InvokeOnNextCommit(_invalidateScene);
} }
private void Update()
{
if(_updating)
return;
_updating = true;
try
{
UpdateCore();
}
finally
{
_updating = false;
}
}
public void Resized(Size size) public void Resized(Size size)
{ {

33
src/Avalonia.Base/Rendering/DirtyVisuals.cs

@ -17,8 +17,7 @@ namespace Avalonia.Rendering
{ {
private SortedDictionary<int, List<IVisual>> _inner = new SortedDictionary<int, List<IVisual>>(); private SortedDictionary<int, List<IVisual>> _inner = new SortedDictionary<int, List<IVisual>>();
private Dictionary<IVisual, int> _index = new Dictionary<IVisual, int>(); private Dictionary<IVisual, int> _index = new Dictionary<IVisual, int>();
private List<IVisual> _deferredChanges = new List<IVisual>(); private int _enumerating;
private int _deferring;
/// <summary> /// <summary>
/// Gets the number of dirty visuals. /// Gets the number of dirty visuals.
@ -31,10 +30,9 @@ namespace Avalonia.Rendering
/// <param name="visual">The dirty visual.</param> /// <param name="visual">The dirty visual.</param>
public void Add(IVisual visual) public void Add(IVisual visual)
{ {
if (_deferring > 0) if (_enumerating > 0)
{ {
_deferredChanges.Add(visual); throw new InvalidOperationException("Visual was invalidated during a render pass");
return;
} }
var distance = visual.CalculateDistanceFromAncestor(visual.VisualRoot); var distance = visual.CalculateDistanceFromAncestor(visual.VisualRoot);
@ -65,7 +63,7 @@ namespace Avalonia.Rendering
/// </summary> /// </summary>
public void Clear() public void Clear()
{ {
if (_deferring > 0) if (_enumerating > 0)
{ {
throw new InvalidOperationException("Cannot clear while enumerating"); throw new InvalidOperationException("Cannot clear while enumerating");
} }
@ -80,7 +78,7 @@ namespace Avalonia.Rendering
/// <returns>A collection of visuals.</returns> /// <returns>A collection of visuals.</returns>
public IEnumerator<IVisual> GetEnumerator() public IEnumerator<IVisual> GetEnumerator()
{ {
BeginDefer(); _enumerating++;
try try
{ {
foreach (var i in _inner) foreach (var i in _inner)
@ -93,27 +91,10 @@ namespace Avalonia.Rendering
} }
finally finally
{ {
EndDefer(); _enumerating--;
} }
} }
private void BeginDefer()
{
++_deferring;
}
private void EndDefer()
{
if (--_deferring > 0) return;
foreach (var visual in _deferredChanges)
{
Add(visual);
}
_deferredChanges.Clear();
}
/// <summary> /// <summary>
/// Gets the dirty visuals, in ascending order of distance to their root. /// Gets the dirty visuals, in ascending order of distance to their root.
/// </summary> /// </summary>

3
src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs

@ -7,6 +7,7 @@ using Avalonia.LinuxFramebuffer.Input;
using Avalonia.LinuxFramebuffer.Output; using Avalonia.LinuxFramebuffer.Output;
using Avalonia.Platform; using Avalonia.Platform;
using Avalonia.Rendering; using Avalonia.Rendering;
using Avalonia.Rendering.Composition;
namespace Avalonia.LinuxFramebuffer namespace Avalonia.LinuxFramebuffer
{ {
@ -32,7 +33,7 @@ namespace Avalonia.LinuxFramebuffer
{ {
var factory = AvaloniaLocator.Current.GetService<IRendererFactory>(); var factory = AvaloniaLocator.Current.GetService<IRendererFactory>();
var renderLoop = AvaloniaLocator.Current.GetService<IRenderLoop>(); var renderLoop = AvaloniaLocator.Current.GetService<IRenderLoop>();
return factory?.Create(root, renderLoop) ?? new DeferredRenderer(root, renderLoop); return factory?.Create(root, renderLoop) ?? new CompositingRenderer(root, LinuxFramebufferPlatform.Compositor);
} }
public void Dispose() public void Dispose()

9
src/Linux/Avalonia.LinuxFramebuffer/LinuxFramebufferPlatform.cs

@ -15,6 +15,7 @@ using Avalonia.LinuxFramebuffer.Output;
using Avalonia.OpenGL; using Avalonia.OpenGL;
using Avalonia.Platform; using Avalonia.Platform;
using Avalonia.Rendering; using Avalonia.Rendering;
using Avalonia.Rendering.Composition;
using Avalonia.Threading; using Avalonia.Threading;
using JetBrains.Annotations; using JetBrains.Annotations;
@ -26,6 +27,10 @@ namespace Avalonia.LinuxFramebuffer
private static readonly Stopwatch St = Stopwatch.StartNew(); private static readonly Stopwatch St = Stopwatch.StartNew();
internal static uint Timestamp => (uint)St.ElapsedTicks; internal static uint Timestamp => (uint)St.ElapsedTicks;
public static InternalPlatformThreadingInterface Threading; public static InternalPlatformThreadingInterface Threading;
internal static Compositor Compositor { get; private set; }
LinuxFramebufferPlatform(IOutputBackend backend) LinuxFramebufferPlatform(IOutputBackend backend)
{ {
_fb = backend; _fb = backend;
@ -48,6 +53,10 @@ namespace Avalonia.LinuxFramebuffer
.Bind<IKeyboardDevice>().ToConstant(new KeyboardDevice()) .Bind<IKeyboardDevice>().ToConstant(new KeyboardDevice())
.Bind<IPlatformSettings>().ToSingleton<PlatformSettings>() .Bind<IPlatformSettings>().ToSingleton<PlatformSettings>()
.Bind<PlatformHotkeyConfiguration>().ToSingleton<PlatformHotkeyConfiguration>(); .Bind<PlatformHotkeyConfiguration>().ToSingleton<PlatformHotkeyConfiguration>();
Compositor = new Compositor(
AvaloniaLocator.Current.GetRequiredService<IRenderLoop>(),
AvaloniaLocator.Current.GetService<IPlatformOpenGlInterface>());
} }

5
src/iOS/Avalonia.iOS/AvaloniaView.cs

@ -10,6 +10,7 @@ using Avalonia.iOS.Storage;
using Avalonia.Platform; using Avalonia.Platform;
using Avalonia.Platform.Storage; using Avalonia.Platform.Storage;
using Avalonia.Rendering; using Avalonia.Rendering;
using Avalonia.Rendering.Composition;
using CoreAnimation; using CoreAnimation;
using Foundation; using Foundation;
using ObjCRuntime; using ObjCRuntime;
@ -65,8 +66,8 @@ namespace Avalonia.iOS
// No-op // No-op
} }
public IRenderer CreateRenderer(IRenderRoot root) => new DeferredRenderer(root, public IRenderer CreateRenderer(IRenderRoot root) => new CompositingRenderer(root, Platform.Compositor);
AvaloniaLocator.Current.GetService<IRenderLoop>());
public void Invalidate(Rect rect) public void Invalidate(Rect rect)
{ {

7
src/iOS/Avalonia.iOS/Platform.cs

@ -6,6 +6,7 @@ using Avalonia.Input.Platform;
using Avalonia.OpenGL; using Avalonia.OpenGL;
using Avalonia.Platform; using Avalonia.Platform;
using Avalonia.Rendering; using Avalonia.Rendering;
using Avalonia.Rendering.Composition;
namespace Avalonia namespace Avalonia
{ {
@ -26,6 +27,8 @@ namespace Avalonia.iOS
{ {
public static EaglFeature GlFeature; public static EaglFeature GlFeature;
public static DisplayLinkTimer Timer; public static DisplayLinkTimer Timer;
internal static Compositor Compositor { get; private set; }
class PlatformSettings : IPlatformSettings class PlatformSettings : IPlatformSettings
{ {
/// <inheritdoc cref="IPlatformSettings.TouchDoubleClickSize"/> /// <inheritdoc cref="IPlatformSettings.TouchDoubleClickSize"/>
@ -57,6 +60,10 @@ namespace Avalonia.iOS
.Bind<IRenderTimer>().ToConstant(Timer) .Bind<IRenderTimer>().ToConstant(Timer)
.Bind<IPlatformThreadingInterface>().ToConstant(new PlatformThreadingInterface()) .Bind<IPlatformThreadingInterface>().ToConstant(new PlatformThreadingInterface())
.Bind<IKeyboardDevice>().ToConstant(keyboard); .Bind<IKeyboardDevice>().ToConstant(keyboard);
Compositor = new Compositor(
AvaloniaLocator.Current.GetRequiredService<IRenderLoop>(),
AvaloniaLocator.Current.GetService<IPlatformOpenGlInterface>());
} }

Loading…
Cancel
Save