Skip to content

Commit b5bfdef

Browse files
committed
Add Lazy Rendering (#689)
1 parent b2549b3 commit b5bfdef

File tree

101 files changed

+642
-501
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

101 files changed

+642
-501
lines changed

src.csharp/AlphaTab.Test/VisualTests/VisualTestHelper.cs

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -186,27 +186,12 @@ private static void CompareVisualResult(double totalWidth, double totalHeight,
186186
(int) totalHeight,
187187
SKImageInfo.PlatformColorType, SKAlphaType.Premul)))
188188
{
189-
var point = new SKPoint();
190-
var rowHeight = 0;
191189
foreach (var partialResult in result)
192190
{
193191
var partialCanvas = partialResult.RenderResult;
194192
if (partialCanvas is SKImage img)
195193
{
196-
finalImageSurface.Canvas.DrawImage(img, point);
197-
if (partialResult.Height > rowHeight)
198-
{
199-
rowHeight = img.Height;
200-
}
201-
202-
point.X += img.Width;
203-
204-
if (point.X >= totalWidth)
205-
{
206-
point.X = 0;
207-
point.Y += rowHeight;
208-
rowHeight = 0;
209-
}
194+
finalImageSurface.Canvas.DrawImage(img, (float)partialResult.X, (float)partialResult.Y);
210195
}
211196
}
212197

src.csharp/AlphaTab.Windows/WinForms/AlphaTabLayoutPanel.cs

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -6,51 +6,10 @@ namespace AlphaTab.WinForms
66
{
77
internal class AlphaTabLayoutPanel : Panel
88
{
9-
private AlphaTabLayoutEngine? _laoyutEngine;
10-
11-
public override LayoutEngine LayoutEngine =>
12-
_laoyutEngine ??= new AlphaTabLayoutEngine();
13-
149
public AlphaTabLayoutPanel()
1510
{
1611
base.DoubleBuffered = true;
1712
ResizeRedraw = true;
1813
}
19-
20-
private class AlphaTabLayoutEngine : LayoutEngine
21-
{
22-
public override bool Layout(object container, LayoutEventArgs layoutEventArgs)
23-
{
24-
var parent = (Control) container;
25-
26-
var xChild = 0;
27-
var yChild = 0;
28-
29-
var rowHeight = 0;
30-
31-
foreach (Control? child in parent.Controls)
32-
{
33-
if (child != null)
34-
{
35-
child.Location = new Point(xChild, yChild);
36-
37-
xChild += child.Width;
38-
if (child.Height > rowHeight)
39-
{
40-
rowHeight = child.Height;
41-
}
42-
43-
if (xChild >= parent.Width)
44-
{
45-
xChild = 0;
46-
yChild += rowHeight;
47-
rowHeight = 0;
48-
}
49-
}
50-
}
51-
52-
return false;
53-
}
54-
}
5514
}
5615
}

src.csharp/AlphaTab.Windows/WinForms/WinFormsUiFacade.cs

Lines changed: 78 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Drawing;
34
using System.IO;
45
using System.Windows.Forms;
@@ -14,6 +15,10 @@ namespace AlphaTab.WinForms
1415
internal class WinFormsUiFacade : ManagedUiFacade<AlphaTabControl>
1516
{
1617
private readonly AlphaTabLayoutPanel _layoutPanel;
18+
19+
private readonly Dictionary<string, PictureBox> _resultIdToElementLookup =
20+
new Dictionary<string, PictureBox>();
21+
1722
private event Action? InternalRootContainerBecameVisible;
1823

1924
public override IContainer RootContainer { get; }
@@ -67,7 +72,7 @@ void OnVisibilityChanged(object? sender, EventArgs e)
6772
protected override Stream? OpenDefaultSoundFont()
6873
{
6974
return typeof(NAudioSynthOutput).Assembly.GetManifestResourceStream(
70-
typeof(NAudioSynthOutput), "default.sf2");
75+
typeof(NAudioSynthOutput), "default.sf2");
7176
}
7277

7378
public override void Initialize(AlphaTabApiBase<AlphaTabControl> api,
@@ -106,14 +111,57 @@ public override IContainer CreateCanvasElement()
106111
return new ControlContainer(_layoutPanel);
107112
}
108113

114+
public override void InitialRender()
115+
{
116+
Api.Renderer.PreRender.On(_ => { _resultIdToElementLookup.Clear(); });
117+
base.InitialRender();
118+
}
119+
109120
public override void TriggerEvent(IContainer container, string eventName,
110121
object? details = null, IMouseEventArgs? originalEvent = null)
111122
{
112123
}
113124

125+
public override void BeginUpdateRenderResults(RenderFinishedEventArgs? r)
126+
{
127+
SettingsContainer.BeginInvoke((Action<RenderFinishedEventArgs?>)(renderResult =>
128+
{
129+
130+
if (renderResult == null ||
131+
!_resultIdToElementLookup.TryGetValue(renderResult.Id, out var placeholder))
132+
{
133+
return;
134+
}
135+
136+
var body = renderResult.RenderResult;
137+
138+
Bitmap? source = null;
139+
switch (body)
140+
{
141+
case string _:
142+
// TODO: svg support
143+
return;
144+
case SKImage skiaImage:
145+
using (skiaImage)
146+
{
147+
source = SkiaUtil.ToBitmap(skiaImage);
148+
}
149+
150+
break;
151+
case Bitmap image:
152+
source = image;
153+
break;
154+
}
155+
156+
var oldImage = placeholder.Image;
157+
placeholder.Image = source;
158+
oldImage?.Dispose();
159+
}), r);
160+
}
161+
114162
public override void BeginAppendRenderResults(RenderFinishedEventArgs? r)
115163
{
116-
SettingsContainer.BeginInvoke((Action<RenderFinishedEventArgs>) (renderResult =>
164+
SettingsContainer.BeginInvoke((Action<RenderFinishedEventArgs?>)(renderResult =>
117165
{
118166
var panel = _layoutPanel;
119167

@@ -134,58 +182,35 @@ public override void BeginAppendRenderResults(RenderFinishedEventArgs? r)
134182
// NOTE: here we try to replace existing children
135183
else
136184
{
137-
var body = renderResult.RenderResult;
138-
139-
Bitmap? source = null;
140-
if (body is string)
141-
{
142-
// TODO: svg support
143-
return;
144-
}
145-
146-
if (body is SKImage skiaImage)
185+
if (TotalResultCount.TryPeek(out var counter))
147186
{
148-
using (skiaImage)
187+
PictureBox placeholder;
188+
if (counter.Count < panel.Controls.Count)
149189
{
150-
source = SkiaUtil.ToBitmap(skiaImage);
190+
placeholder = (PictureBox)panel.Controls[counter.Count];
151191
}
152-
}
153-
else if (body is Bitmap image)
154-
{
155-
source = image;
156-
}
157-
158-
if (source != null)
159-
{
160-
if (TotalResultCount.TryPeek(out var counter))
192+
else
161193
{
162-
if (counter.Count < panel.Controls.Count)
163-
{
164-
var img = (PictureBox) panel.Controls[counter.Count];
165-
img.Width = (int) renderResult.Width;
166-
img.Height = (int) renderResult.Height;
167-
var oldImg = img.Image;
168-
img.Image = source;
169-
oldImg?.Dispose();
170-
}
171-
else
194+
placeholder = new PictureBox
172195
{
173-
var img = new PictureBox
174-
{
175-
AutoSize = false,
176-
BackColor = _layoutPanel.ForeColor,
177-
Width = (int) renderResult.Width,
178-
Height = (int) renderResult.Height,
179-
Image = source,
180-
Padding = Padding.Empty,
181-
Margin = Padding.Empty,
182-
BorderStyle = BorderStyle.None
183-
};
184-
panel.Controls.Add(img);
185-
}
186-
187-
counter.Count++;
196+
AutoSize = false,
197+
BackColor = _layoutPanel.ForeColor,
198+
Padding = Padding.Empty,
199+
Margin = Padding.Empty,
200+
BorderStyle = BorderStyle.None
201+
};
202+
panel.Controls.Add(placeholder);
188203
}
204+
205+
placeholder.Left = (int)renderResult.X;
206+
placeholder.Top = (int)renderResult.Y;
207+
placeholder.Width = (int)renderResult.Width;
208+
placeholder.Height = (int)renderResult.Height;
209+
210+
_resultIdToElementLookup[renderResult.Id] = placeholder;
211+
Api.Renderer.RenderResult(renderResult.Id);
212+
213+
counter.Count++;
189214
}
190215
}
191216
}), r);
@@ -228,7 +253,7 @@ public override IContainer GetScrollContainer()
228253

229254
public override Bounds GetOffset(IContainer? relativeTo, IContainer container)
230255
{
231-
var containerWinForms = ((ControlContainer) container).Control;
256+
var containerWinForms = ((ControlContainer)container).Control;
232257

233258
var left = 0;
234259
var top = 0;
@@ -252,14 +277,14 @@ public override Bounds GetOffset(IContainer? relativeTo, IContainer container)
252277

253278
public override void ScrollToY(IContainer scrollElement, double offset, double speed)
254279
{
255-
var c = ((ControlContainer) scrollElement).Control;
256-
c.AutoScrollOffset = new Point(c.AutoScrollOffset.X, (int) offset);
280+
var c = ((ControlContainer)scrollElement).Control;
281+
c.AutoScrollOffset = new Point(c.AutoScrollOffset.X, (int)offset);
257282
}
258283

259284
public override void ScrollToX(IContainer scrollElement, double offset, double speed)
260285
{
261-
var c = ((ControlContainer) scrollElement).Control;
262-
c.AutoScrollOffset = new Point((int) offset, c.AutoScrollOffset.Y);
286+
var c = ((ControlContainer)scrollElement).Control;
287+
c.AutoScrollOffset = new Point((int)offset, c.AutoScrollOffset.Y);
263288
}
264289
}
265290
}

src.csharp/AlphaTab.Windows/Wpf/AlphaTabLayoutPanel.cs

Lines changed: 0 additions & 53 deletions
This file was deleted.

src.csharp/AlphaTab.Windows/Wpf/GdiImageSource.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,16 @@ internal static class GdiImageSource
99
{
1010
public static BitmapSource Create(Bitmap image)
1111
{
12-
var bitmapData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadOnly,
12+
var bitmapData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height),
13+
ImageLockMode.ReadOnly,
1314
image.PixelFormat);
1415

1516
var bitmapSource = BitmapSource.Create(
1617
bitmapData.Width, bitmapData.Height, 96, 96, PixelFormats.Pbgra32, null,
1718
bitmapData.Scan0, bitmapData.Stride * bitmapData.Height, bitmapData.Stride);
1819

1920
image.UnlockBits(bitmapData);
20-
21+
bitmapSource.Freeze();
2122
return bitmapSource;
2223
}
2324
}

src.csharp/AlphaTab.Windows/Wpf/SkImageSource.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ public static BitmapSource Create(object data)
2020
}
2121
bitmap.AddDirtyRect(new Int32Rect(0, 0, info.Width, info.Height));
2222
bitmap.Unlock();
23+
bitmap.Freeze();
2324
return bitmap;
2425
}
2526
}

0 commit comments

Comments
 (0)