Browse Source

Various changes

feature/integer-clip-bak-1
Nikita Tsukanov 2 years ago
parent
commit
f4f4fc3494
  1. 1
      src/Avalonia.Base/Platform/IPlatformRenderInterfaceRegion.cs
  2. 32
      src/Avalonia.Base/Rendering/Composition/CompositionCustomVisual.cs
  3. 41
      src/Avalonia.Base/Rendering/Composition/CompositionCustomVisualHandler.cs
  4. 4
      src/Avalonia.Base/Rendering/Composition/Server/DirtyRectTracker.cs
  5. 8
      src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.DirtyRects.cs
  6. 18
      src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs
  7. 13
      src/Avalonia.Base/Rendering/Composition/Server/ServerCustomCompositionVisual.cs
  8. 1
      src/Skia/Avalonia.Skia/SkiaRegionImpl.cs

1
src/Avalonia.Base/Platform/IPlatformRenderInterfaceRegion.cs

@ -13,4 +13,5 @@ public interface IPlatformRenderInterfaceRegion : IDisposable
PixelRect Bounds { get; }
IList<PixelRect> Rects { get; }
bool Intersects(Rect rect);
bool Contains(Point pt);
}

32
src/Avalonia.Base/Rendering/Composition/CompositionCustomVisual.cs

@ -1,12 +1,15 @@
using System.Collections.Generic;
using System.Numerics;
using Avalonia.Media;
using Avalonia.Rendering.Composition.Server;
using Avalonia.Rendering.Composition.Transport;
using Avalonia.Threading;
namespace Avalonia.Rendering.Composition;
public sealed class CompositionCustomVisual : CompositionContainerVisual
{
private static readonly ThreadSafeObjectPool<List<object>> s_messageListPool = new();
private List<object>? _messages;
internal CompositionCustomVisual(Compositor compositor, CompositionCustomVisualHandler handler)
@ -17,21 +20,26 @@ public sealed class CompositionCustomVisual : CompositionContainerVisual
public void SendHandlerMessage(object message)
{
(_messages ??= new()).Add(message);
RegisterForSerialization();
if (_messages == null)
{
_messages = s_messageListPool.Get();
Compositor.RequestCompositionUpdate(OnCompositionUpdate);
}
_messages.Add(message);
}
private protected override void SerializeChangesCore(BatchStreamWriter writer)
private void OnCompositionUpdate()
{
base.SerializeChangesCore(writer);
if (_messages == null || _messages.Count == 0)
writer.Write(0);
else
if(_messages == null)
return;
var messages = _messages;
_messages = null;
Compositor.PostServerJob(()=>
{
writer.Write(_messages.Count);
foreach (var m in _messages)
writer.WriteObject(m);
_messages.Clear();
}
((ServerCompositionCustomVisual)Server).DispatchMessages(messages);
messages.Clear();
s_messageListPool.ReturnAndSetNull(ref messages);
});
}
}

41
src/Avalonia.Base/Rendering/Composition/CompositionCustomVisualHandler.cs

@ -10,8 +10,8 @@ namespace Avalonia.Rendering.Composition;
public abstract class CompositionCustomVisualHandler
{
private ServerCompositionCustomVisual? _host;
private PooledList<Rect>? _dirtyRects;
private bool _inRender;
private Rect _currentTransformedClip;
public virtual void OnMessage(object message)
{
@ -23,9 +23,10 @@ public abstract class CompositionCustomVisualHandler
}
internal void Render(ImmediateDrawingContext drawingContext)
internal void Render(ImmediateDrawingContext drawingContext, Rect currentTransformedClip)
{
_inRender = true;
_currentTransformedClip = currentTransformedClip;
try
{
OnRender(drawingContext);
@ -34,11 +35,8 @@ public abstract class CompositionCustomVisualHandler
{
_inRender = false;
}
_dirtyRects?.Dispose();
_dirtyRects = null;
}
public abstract void OnRender(ImmediateDrawingContext drawingContext);
void VerifyAccess()
@ -96,26 +94,17 @@ public abstract class CompositionCustomVisualHandler
_host!.HandlerRegisterForNextAnimationFrameUpdate();
}
protected IList<Rect> DirtyRects
protected bool RenderClipContains(Point pt)
{
get
{
VerifyInRender();
if (_host?.Root == null)
return Array.Empty<Rect>();
if (_dirtyRects == null)
{
if (!_host.GlobalTransformMatrix.TryInvert(out var inverted))
return Array.Empty<Rect>();
_dirtyRects = new();
foreach (var r in _host.Root.ThisFrameDirtyRects)
{
_dirtyRects.Add(r.ToRectWithDpi(1).TransformToAABB(inverted));
}
}
return _dirtyRects;
}
VerifyInRender();
pt *= _host.GlobalTransformMatrix;
return _currentTransformedClip.Contains(pt) && _host.Root.DirtyRects.Contains(pt);
}
protected bool RenderClipIntersectes(Rect rc)
{
VerifyInRender();
rc = rc.TransformToAABB(_host.GlobalTransformMatrix);
return _currentTransformedClip.Intersects(rc) && _host.Root.DirtyRects.Intersects(rc);
}
}

4
src/Avalonia.Base/Rendering/Composition/Server/DirtyRectTracker.cs

@ -14,6 +14,7 @@ internal interface IDirtyRectTracker
IDisposable BeginDraw(IDrawingContextImpl ctx);
bool IsEmpty { get; }
bool Intersects(Rect rect);
bool Contains(Point pt);
void Reset();
void Visualize(IDrawingContextImpl context);
PixelRect CombinedRect { get; }
@ -40,6 +41,8 @@ internal class DirtyRectTracker : IDirtyRectTracker
public bool IsEmpty => _rect.Width == 0 | _rect.Height == 0;
public bool Intersects(Rect rect) => _doubleRect.Intersects(rect);
public bool Contains(Point pt) => _rect.Contains(PixelPoint.FromPoint(pt, 1));
public void Reset() => _rect = default;
public void Visualize(IDrawingContextImpl context)
{
@ -83,6 +86,7 @@ internal class RegionDirtyRectTracker : IDirtyRectTracker
public bool IsEmpty => _region.IsEmpty;
public bool Intersects(Rect rect) => _region.Intersects(rect);
public bool Contains(Point pt) => _region.Contains(pt);
public void Reset() => _region.Reset();

8
src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.DirtyRects.cs

@ -6,7 +6,7 @@ namespace Avalonia.Rendering.Composition.Server;
internal partial class ServerCompositionTarget
{
private readonly IDirtyRectTracker _dirtyRect;
public readonly IDirtyRectTracker DirtyRects;
public void AddDirtyRect(Rect rect)
{
@ -14,7 +14,7 @@ internal partial class ServerCompositionTarget
return;
var snapped = PixelRect.FromRect(SnapToDevicePixels(rect, Scaling), 1);
DebugEvents?.RectInvalidated(rect);
_dirtyRect.AddRect(snapped);
DirtyRects.AddRect(snapped);
_redrawRequested = true;
}
@ -30,6 +30,6 @@ internal partial class ServerCompositionTarget
Math.Ceiling(rect.Right * scale) / scale,
Math.Ceiling(rect.Bottom * scale) / scale));
}
public IList<PixelRect> ThisFrameDirtyRects => _dirtyRect.Rects;
}

18
src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs

@ -57,7 +57,7 @@ namespace Avalonia.Rendering.Composition.Server
_surfaces = surfaces;
_diagnosticTextRenderer = diagnosticTextRenderer;
var platformRender = AvaloniaLocator.Current.GetService<IPlatformRenderInterface>();
_dirtyRect = compositor.Options.UseRegionDirtyRectClipping == true &&
DirtyRects = compositor.Options.UseRegionDirtyRectClipping == true &&
platformRender?.SupportsRegions == true
? new RegionDirtyRectTracker(platformRender)
: new DirtyRectTracker();
@ -151,7 +151,7 @@ namespace Avalonia.Rendering.Composition.Server
return;
}
if (_dirtyRect.IsEmpty && !_redrawRequested && !_updateRequested)
if (DirtyRects.IsEmpty && !_redrawRequested && !_updateRequested)
return;
Revision++;
@ -183,23 +183,23 @@ namespace Avalonia.Rendering.Composition.Server
_layer = null;
_layer = targetContext.CreateLayer(PixelSize);
_layerSize = PixelSize;
_dirtyRect.AddRect(new PixelRect(_layerSize));
DirtyRects.AddRect(new PixelRect(_layerSize));
}
if (!_dirtyRect.IsEmpty)
if (!DirtyRects.IsEmpty)
{
var useLayerClip = Compositor.Options.UseSaveLayerRootClip ??
Compositor.RenderInterface.GpuContext != null;
using (var context = _layer.CreateDrawingContext(false))
{
using (_dirtyRect.BeginDraw(context))
using (DirtyRects.BeginDraw(context))
{
context.Clear(Colors.Transparent);
if (useLayerClip)
context.PushLayer(_dirtyRect.CombinedRect.ToRect(1));
context.PushLayer(DirtyRects.CombinedRect.ToRect(1));
Root.Render(new CompositorDrawingContextProxy(context), null, _dirtyRect);
Root.Render(new CompositorDrawingContextProxy(context), null, DirtyRects);
if (useLayerClip)
context.PopLayer();
@ -230,14 +230,14 @@ namespace Avalonia.Rendering.Composition.Server
RenderedVisuals = 0;
_dirtyRect.Reset();
DirtyRects.Reset();
}
}
private void DrawOverlays(IDrawingContextImpl targetContext, Size logicalSize)
{
if ((DebugOverlays & RendererDebugOverlays.DirtyRects) != 0)
_dirtyRect.Visualize(targetContext);
DirtyRects.Visualize(targetContext);
targetContext.Transform = Matrix.CreateScale(Scaling, Scaling);

13
src/Avalonia.Base/Rendering/Composition/Server/ServerCustomCompositionVisual.cs

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Numerics;
using Avalonia.Logging;
using Avalonia.Media;
@ -16,15 +17,13 @@ internal sealed class ServerCompositionCustomVisual : ServerCompositionContainer
_handler.Attach(this);
}
protected override void DeserializeChangesCore(BatchStreamReader reader, TimeSpan committedAt)
public void DispatchMessages(List<object> messages)
{
base.DeserializeChangesCore(reader, committedAt);
var count = reader.Read<int>();
for (var c = 0; c < count; c++)
foreach(var message in messages)
{
try
{
_handler.OnMessage(reader.ReadObject()!);
_handler.OnMessage(message);
}
catch (Exception e)
{
@ -33,7 +32,7 @@ internal sealed class ServerCompositionCustomVisual : ServerCompositionContainer
}
}
}
public void OnTick()
{
_wantsNextAnimationFrameAfterTick = false;
@ -77,7 +76,7 @@ internal sealed class ServerCompositionCustomVisual : ServerCompositionContainer
using var context = new ImmediateDrawingContext(canvas, false);
try
{
_handler.Render(context);
_handler.Render(context, currentTransformedClip);
}
catch (Exception e)
{

1
src/Skia/Avalonia.Skia/SkiaRegionImpl.cs

@ -49,4 +49,5 @@ internal class SkiaRegionImpl : IPlatformRenderInterfaceRegion
}
public bool Intersects(Rect rect) => Region.Intersects(PixelRect.FromRect(rect, 1).ToSKRectI());
public bool Contains(Point pt) => Region.Contains((int)pt.X, (int)pt.Y);
}
Loading…
Cancel
Save