Browse Source

Merge pull request #3713 from AvaloniaUI/x11-immediate-renderer-shim

Immediate rendering support for X11 platform via render loop
Steven Kirk 5 years ago
parent
commit
73884046d8

+ 107 - 0
src/Avalonia.X11/X11ImmediateRendererProxy.cs

@@ -0,0 +1,107 @@
+using System;
+using System.Collections.Generic;
+using Avalonia.Rendering;
+using Avalonia.Threading;
+using Avalonia.VisualTree;
+
+namespace Avalonia.X11
+{
+    public class X11ImmediateRendererProxy : IRenderer, IRenderLoopTask
+    {
+        private readonly IRenderLoop _loop;
+        private ImmediateRenderer _renderer;
+        private bool _invalidated;
+        private object _lock = new object();
+
+        public X11ImmediateRendererProxy(IVisual root, IRenderLoop loop)
+        {
+            _loop = loop;
+            _renderer = new ImmediateRenderer(root);
+            
+        }
+
+        public void Dispose()
+        {
+            _renderer.Dispose();
+        }
+
+        public bool DrawFps
+        {
+            get => _renderer.DrawFps;
+            set => _renderer.DrawFps = value;
+        }
+
+        public bool DrawDirtyRects
+        {
+            get => _renderer.DrawDirtyRects;
+            set => _renderer.DrawDirtyRects = value;
+        }
+
+        public event EventHandler<SceneInvalidatedEventArgs> SceneInvalidated
+        {
+            add => _renderer.SceneInvalidated += value;
+            remove => _renderer.SceneInvalidated -= value;
+        }
+
+        public void AddDirty(IVisual visual)
+        {
+            lock (_lock)
+                _invalidated = true;
+            _renderer.AddDirty(visual);
+        }
+
+        public IEnumerable<IVisual> HitTest(Point p, IVisual root, Func<IVisual, bool> filter)
+        {
+            return _renderer.HitTest(p, root, filter);
+        }
+
+        public IVisual HitTestFirst(Point p, IVisual root, Func<IVisual, bool> filter)
+        {
+            return _renderer.HitTestFirst(p, root, filter);
+        }
+
+        public void RecalculateChildren(IVisual visual)
+        {
+            _renderer.RecalculateChildren(visual);
+        }
+
+        public void Resized(Size size)
+        {
+            _renderer.Resized(size);
+        }
+
+        public void Paint(Rect rect)
+        {
+            _invalidated = false;
+            _renderer.Paint(rect);
+        }
+
+        public void Start()
+        {
+            _loop.Add(this);
+            _renderer.Start();
+        }
+
+        public void Stop()
+        {
+            _loop.Remove(this);
+            _renderer.Stop();
+        }
+
+        public bool NeedsUpdate => false;
+        public void Update(TimeSpan time)
+        {
+            
+        }
+
+        public void Render()
+        {
+            if (_invalidated)
+            {
+                lock (_lock)
+                    _invalidated = false;
+                Dispatcher.UIThread.Post(() => Paint(new Rect(0, 0, 100000, 100000)));
+            }
+        }
+    }
+}

+ 1 - 0
src/Avalonia.X11/X11Platform.cs

@@ -96,6 +96,7 @@ namespace Avalonia
         public bool UseGpu { get; set; } = true;
         public bool OverlayPopups { get; set; }
         public bool UseDBusMenu { get; set; }
+        public bool UseDeferredRendering { get; set; } = true;
 
         public List<string> GlxRendererBlacklist { get; set; } = new List<string>
         {

+ 8 - 12
src/Avalonia.X11/X11Window.cs

@@ -27,7 +27,6 @@ namespace Avalonia.X11
         private readonly IWindowImpl _popupParent;
         private readonly bool _popup;
         private readonly X11Info _x11;
-        private bool _invalidated;
         private XConfigureEvent? _configure;
         private PixelPoint? _configurePoint;
         private bool _triggeredExpose;
@@ -309,8 +308,13 @@ namespace Avalonia.X11
         public Action Closed { get; set; }
         public Action<PixelPoint> PositionChanged { get; set; }
 
-        public IRenderer CreateRenderer(IRenderRoot root) =>
-            new DeferredRenderer(root, AvaloniaLocator.Current.GetService<IRenderLoop>());
+        public IRenderer CreateRenderer(IRenderRoot root)
+        {
+            var loop = AvaloniaLocator.Current.GetService<IRenderLoop>();
+            return _platform.Options.UseDeferredRendering ?
+                new DeferredRenderer(root, loop) :
+                (IRenderer)new X11ImmediateRendererProxy(root, loop);
+        }
 
         void OnEvent(XEvent ev)
         {
@@ -684,20 +688,12 @@ namespace Avalonia.X11
 
         void DoPaint()
         {
-            _invalidated = false;
             Paint?.Invoke(new Rect());
         }
         
         public void Invalidate(Rect rect)
         {
-            if(_invalidated)
-                return;
-            _invalidated = true;
-            Dispatcher.UIThread.InvokeAsync(() =>
-            {
-                if (_mapped)
-                    DoPaint();
-            });
+
         }
 
         public IInputRoot InputRoot => _inputRoot;