Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance rendering framework with new RenderNode architecture #1196

Merged
merged 36 commits into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
b390a16
feat: add RenderNode, RenderNodeContext, and RenderNodeOperation clas…
yuto-trd Dec 7, 2024
8bfccdd
feat: add various RenderNode implementations for enhanced rendering c…
yuto-trd Dec 7, 2024
a7ddf50
feat: implement IPopable interface and update PushedState to use it
yuto-trd Dec 7, 2024
75a4d76
feat: Implement GraphicsContext2D class for recording RenderNodes.
yuto-trd Dec 7, 2024
ed6ed55
feat: mark CombinedFilterEffect and MultiTransform as obsolete, sugge…
yuto-trd Dec 7, 2024
d60229b
feat: add OnUntracked callback and improve node disposal in GraphicsC…
yuto-trd Dec 7, 2024
98ffbb1
feat: add RenderNodeCache and RenderNodeProcessor for enhanced render…
yuto-trd Dec 7, 2024
02840bb
feat: add unit tests for GraphicsContext2D to validate rendering beha…
yuto-trd Dec 7, 2024
380f10e
feat: mark multiple rendering classes as obsolete to suggest alternat…
yuto-trd Dec 7, 2024
e3a298f
feat: update rendering methods to use GraphicsContext2D and mark Defe…
yuto-trd Dec 7, 2024
47c17ab
feat: mark DeferradCanvas as obsolete and comment out rendering logic
yuto-trd Dec 7, 2024
47bdf57
feat: refactor rendering cache to use RenderNodeCacheContext and upda…
yuto-trd Dec 7, 2024
fb733b1
feat: update RenderLayer to use DrawableRenderNode and GraphicsContex…
yuto-trd Dec 7, 2024
9007049
feat: update ImmediateCanvas to use RenderNodeCacheContext and commen…
yuto-trd Dec 7, 2024
f908a04
feat: refactor PlayerViewModel to use DrawableRenderNode and Graphics…
yuto-trd Dec 7, 2024
40c340e
fix: build error
yuto-trd Dec 7, 2024
54a2942
fix: Fixed possible memory leak code
yuto-trd Dec 7, 2024
54ef03c
feat: Add TODO for supporting multiple EffectTargets in TransformEffect
yuto-trd Dec 7, 2024
c0c5f48
feat: Implement DrawDrawable method in ImmediateCanvas
yuto-trd Dec 7, 2024
af96e69
refactor: Replace Render calls with DrawDrawable in unit tests
yuto-trd Dec 7, 2024
8e93486
refactor: Remove DeferradCanvasTests and update GraphicsContext2DTest…
yuto-trd Dec 7, 2024
9499210
fix: correct behavior of PushLayer
yuto-trd Dec 7, 2024
ae75457
feat: Add TODO to disable caching when context.IsCacheEnabled is fals…
yuto-trd Dec 7, 2024
c870404
refactor: Remove obsolete rendering nodes and interfaces
yuto-trd Dec 7, 2024
1d308d8
refactor: Remove obsolete Cache references and update rendering logic
yuto-trd Dec 7, 2024
a6d89f7
change: relocate files previously moved temporarily under Rendering.V2
yuto-trd Dec 7, 2024
46c9398
feat: implement logic for creating cache
yuto-trd Dec 7, 2024
ed6503e
change: move cache ownership from RenderNodeCacheContext to RenderNode
yuto-trd Dec 7, 2024
85e4e23
feat: add bounds calculation for RenderLayer
yuto-trd Dec 7, 2024
5c728dc
change: refactor HitTest implementation to use RenderNode
yuto-trd Dec 7, 2024
65696f5
test: reorganize rendering tests and add new test cases for render nodes
yuto-trd Dec 7, 2024
241b454
fix: correct processing in RenderNodeProcessor.Rasterize
yuto-trd Dec 7, 2024
4f8be4e
test: add unit tests for EllipseRenderNode, RectClipRenderNode, Recta…
yuto-trd Dec 8, 2024
35e9ab5
feat: simplify FilterEffectActivator
yuto-trd Dec 9, 2024
1fc4db9
fix: resolve exception occurring in RenderNode caching
yuto-trd Dec 9, 2024
1ccb01e
refactor: streamline FilterEffectActivator by removing unnecessary fi…
yuto-trd Dec 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions src/Beutl.Engine/Graphics/Drawable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -194,11 +194,11 @@ internal Matrix GetTransformMatrix(Size availableSize, Size coreBounds)
}
}

public virtual void Render(ICanvas canvas)
public virtual void Render(GraphicsContext2D context)
{
if (IsVisible)
{
Size availableSize = canvas.Size.ToSize(1);
Size availableSize = context.Size.ToSize(1);
Size size = MeasureCore(availableSize);
var rect = new Rect(size);
if (_filterEffect != null && !rect.IsInvalid)
Expand All @@ -208,13 +208,13 @@ public virtual void Render(ICanvas canvas)

Matrix transform = GetTransformMatrix(availableSize, size);
Rect transformedBounds = rect.IsInvalid ? Rect.Invalid : rect.TransformToAABB(transform);
using (canvas.PushBlendMode(BlendMode))
using (canvas.PushTransform(transform))
using (canvas.PushOpacity(Opacity / 100f))
using (_filterEffect == null ? new() : canvas.PushFilterEffect(_filterEffect))
using (OpacityMask == null ? new() : canvas.PushOpacityMask(OpacityMask, new Rect(size)))
using (context.PushBlendMode(BlendMode))
using (context.PushTransform(transform))
using (context.PushOpacity(Opacity / 100f))
using (_filterEffect == null ? new() : context.PushFilterEffect(_filterEffect))
using (OpacityMask == null ? new() : context.PushOpacityMask(OpacityMask, new Rect(size)))
{
OnDraw(canvas);
OnDraw(context);
}

Bounds = transformedBounds;
Expand All @@ -230,7 +230,7 @@ public override void ApplyAnimations(IClock clock)
(OpacityMask as Animatable)?.ApplyAnimations(clock);
}

protected abstract void OnDraw(ICanvas canvas);
protected abstract void OnDraw(GraphicsContext2D context);

private Point CalculateTranslate(Size bounds, Size canvasSize)
{
Expand Down
19 changes: 10 additions & 9 deletions src/Beutl.Engine/Graphics/DrawableDecorator.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.ComponentModel;
using Beutl.Graphics.Effects;
using Beutl.Graphics.Rendering;
using Beutl.Media;
using Beutl.Media.Immutable;

Expand Down Expand Up @@ -60,11 +61,11 @@ private Rect PrivateMeasureCore(Size availableSize)
}
}

public override void Render(ICanvas canvas)
public override void Render(GraphicsContext2D context)
{
if (IsVisible)
{
Size availableSize = canvas.Size.ToSize(1);
Size availableSize = context.Size.ToSize(1);
Rect rect = PrivateMeasureCore(availableSize);
if (FilterEffect != null && !rect.IsInvalid)
{
Expand All @@ -73,23 +74,23 @@ public override void Render(ICanvas canvas)

Matrix transform = GetTransformMatrix(availableSize);
Rect transformedBounds = rect.IsInvalid ? Rect.Invalid : rect.TransformToAABB(transform);
using (canvas.PushBlendMode(BlendMode))
using (canvas.PushTransform(transform))
using (FilterEffect == null ? new() : canvas.PushFilterEffect(FilterEffect))
using (OpacityMask == null ? new() : canvas.PushOpacityMask(OpacityMask, new Rect(rect.Size)))
using (context.PushBlendMode(BlendMode))
using (context.PushTransform(transform))
using (FilterEffect == null ? new() : context.PushFilterEffect(FilterEffect))
using (OpacityMask == null ? new() : context.PushOpacityMask(OpacityMask, new Rect(rect.Size)))
{
OnDraw(canvas);
OnDraw(context);
}

Bounds = transformedBounds;
}
}

protected override void OnDraw(ICanvas canvas)
protected override void OnDraw(GraphicsContext2D context)
{
if (Child != null)
{
canvas.DrawDrawable(Child);
context.DrawDrawable(Child);
}
}

Expand Down
23 changes: 12 additions & 11 deletions src/Beutl.Engine/Graphics/DrawableGroup.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Text.Json.Nodes;
using Beutl.Graphics.Effects;
using Beutl.Graphics.Rendering;
using Beutl.Serialization;

namespace Beutl.Graphics;
Expand Down Expand Up @@ -70,11 +71,11 @@ private Rect PrivateMeasureCore(Size availableSize)
return rect;
}

public override void Render(ICanvas canvas)
public override void Render(GraphicsContext2D context)
{
if (IsVisible)
{
Size availableSize = canvas.Size.ToSize(1);
Size availableSize = context.Size.ToSize(1);
Rect rect = PrivateMeasureCore(availableSize);
if (FilterEffect != null && !rect.IsInvalid)
{
Expand All @@ -84,25 +85,25 @@ public override void Render(ICanvas canvas)
Matrix transform = GetTransformMatrix(availableSize);
Rect transformedBounds = rect.IsInvalid ? Rect.Invalid : rect.TransformToAABB(transform);

using (canvas.PushBlendMode(BlendMode))
using (canvas.PushLayer(transformedBounds.IsInvalid ? default : transformedBounds))
using (canvas.PushTransform(transform))
using (FilterEffect == null ? new() : canvas.PushFilterEffect(FilterEffect))
using (OpacityMask == null ? new() : canvas.PushOpacityMask(OpacityMask, new Rect(rect.Size)))
using (canvas.PushLayer())
using (context.PushBlendMode(BlendMode))
using (context.PushLayer(transformedBounds.IsInvalid ? default : transformedBounds))
using (context.PushTransform(transform))
using (FilterEffect == null ? new() : context.PushFilterEffect(FilterEffect))
using (OpacityMask == null ? new() : context.PushOpacityMask(OpacityMask, new Rect(rect.Size)))
using (context.PushLayer())
{
OnDraw(canvas);
OnDraw(context);
}

Bounds = transformedBounds;
}
}

protected override void OnDraw(ICanvas canvas)
protected override void OnDraw(GraphicsContext2D context)
{
foreach (Drawable item in _children.GetMarshal().Value)
{
canvas.DrawDrawable(item);
context.DrawDrawable(item);
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/Beutl.Engine/Graphics/DummyDrawable.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Nodes;

using Beutl.Graphics.Rendering;
using Beutl.Serialization;

namespace Beutl.Graphics;
Expand Down Expand Up @@ -29,7 +29,7 @@ protected override Size MeasureCore(Size availableSize)
return Size.Empty;
}

protected override void OnDraw(ICanvas canvas)
protected override void OnDraw(GraphicsContext2D context)
{
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using System.ComponentModel;
using Beutl.Animation;
using Beutl.Animation;

namespace Beutl.Graphics.Effects;

[Obsolete("Use FilterEffectGroup instead.")]
public sealed class CombinedFilterEffect : FilterEffect
{
public static readonly CoreProperty<FilterEffect?> FirstProperty;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,16 @@
using System.Collections.Immutable;

using Beutl.Media.Source;

using Beutl.Media.Source;
using SkiaSharp;

namespace Beutl.Graphics.Effects;

public class CustomFilterEffectContext
{
internal readonly IImmediateCanvasFactory _factory;
internal readonly ImmutableArray<FEItemWrapper> _history;

internal CustomFilterEffectContext(
IImmediateCanvasFactory canvas,
EffectTargets targets,
ImmutableArray<FEItemWrapper> history)
internal CustomFilterEffectContext(IImmediateCanvasFactory canvas, EffectTargets targets)
{
Targets = targets;
_factory = canvas;
_history = history;
}

public EffectTargets Targets { get; }
Expand Down Expand Up @@ -65,17 +57,11 @@ public EffectTarget CreateTarget(Rect bounds)
if (surface != null)
{
using var surfaceRef = Ref<SKSurface>.Create(surface);
var obj = new EffectTarget(surfaceRef, bounds);

obj._history.AddRange(_history);
return obj;
return new EffectTarget(surfaceRef, bounds);
}
else
{
var obj = new EffectTarget();

obj._history.AddRange(_history);
return obj;
return new EffectTarget();
}
}

Expand Down
33 changes: 10 additions & 23 deletions src/Beutl.Engine/Graphics/FilterEffects/EffectTarget.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
using System.ComponentModel;

using Beutl.Collections.Pooled;
using Beutl.Graphics.Rendering;
using Beutl.Media.Source;

using SkiaSharp;

namespace Beutl.Graphics.Effects;
Expand All @@ -15,9 +13,7 @@ public sealed class EffectTarget : IDisposable

private object? _target;

internal readonly PooledList<FEItemWrapper> _history = [];

public EffectTarget(IGraphicNode node)
public EffectTarget(RenderNodeOperation node)
{
_target = node;
OriginalBounds = node.Bounds;
Expand All @@ -39,30 +35,21 @@ public EffectTarget()

public Rect Bounds { get; set; }

[Obsolete()]
[Obsolete]
[EditorBrowsable(EditorBrowsableState.Never)]
public Size Size => Bounds.Size;

public IGraphicNode? Node => _target as IGraphicNode;
public RenderNodeOperation? NodeOperation => _target as RenderNodeOperation;

public Ref<SKSurface>? Surface => _target as Ref<SKSurface>;

public bool IsEmpty => _target == null;

public EffectTarget Clone()
{
if (Node != null)
{
return this;
}
else if (Surface != null)
if (Surface != null)
{
var obj = new EffectTarget(Surface, OriginalBounds)
{
Bounds = Bounds
};
obj._history.AddRange(_history.Select(v => v.Inherit()));
return obj;
return new EffectTarget(Surface, OriginalBounds) { Bounds = Bounds };
}
else
{
Expand All @@ -73,20 +60,20 @@ public EffectTarget Clone()
public void Dispose()
{
Surface?.Dispose();
NodeOperation?.Dispose();
_target = null;
OriginalBounds = default;
_history.Dispose();
}

public void Draw(ImmediateCanvas canvas)
{
if (Node != null)
if (Surface != null)
{
canvas.DrawNode(Node);
canvas.DrawSurface(Surface.Value, default);
}
else if (Surface != null)
else if (NodeOperation != null)
{
canvas.DrawSurface(Surface.Value, default);
NodeOperation.Render(canvas);
}
}
}
6 changes: 2 additions & 4 deletions src/Beutl.Engine/Graphics/FilterEffects/FEImpl.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System.Collections.Immutable;

using SkiaSharp;
using SkiaSharp;

namespace Beutl.Graphics.Effects;

Expand Down Expand Up @@ -53,7 +51,7 @@ public void Accepts(CustomFilterEffectContext context)
{
using (target)
{
var innerContext = new FilterEffectCustomOperationContext(context._factory, target, [.. target._history]);
var innerContext = new FilterEffectCustomOperationContext(context._factory, target);
Action.Invoke(Data, innerContext);

innerContext.Target.Bounds = TransformBounds!(Data, innerContext.Target.Bounds);
Expand Down
Loading
Loading