Skip to content

Commit

Permalink
Add OpenGL rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
dedmen committed Mar 23, 2021
1 parent 69fef6d commit a90164a
Show file tree
Hide file tree
Showing 4 changed files with 427 additions and 8 deletions.
68 changes: 63 additions & 5 deletions src/DesktopClient/Misc/MapControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,23 @@ public enum RenderMode
Wpf
}


public interface ISkiaCanvas
{

[Category("Appearance")]
event EventHandler<SKPaintSurfaceEventArgs> PaintSurface;

[Category("Appearance")]
event EventHandler<SKPaintGLSurfaceEventArgs> PaintSurfaceGL;

Visibility Visibility{ get; set; }

void InvalidateVisual();


}

public partial class MapControl : Grid, IMapControl
{
//https://github.com/Mapsui/Mapsui/blob/af2bf64d3f45c0a3a7b91d2d58cc2a4fff3d13d3/Mapsui.UI.Shared/MapControl.cs
Expand Down Expand Up @@ -521,14 +538,32 @@ public void Clear()
/// </summary>
public event EventHandler<SwipedEventArgs> Fling;

static private bool GLRunning = false;

public MapControl()
{
Children.Add(WpfCanvas);
Children.Add(SkiaCanvas);
Children.Add(_selectRectangle);

if (!GLRunning)
{
SkiaCanvas = CreateSkiaGLRenderElement(); CreateSkiaRenderElement();
GLRunning = true;

Children.Add(SkiaCanvas as SKGLWpfControl);
}
else
{
SkiaCanvas = CreateSkiaRenderElement();

Children.Add(SkiaCanvas as SKElement);
}

SkiaCanvas.PaintSurfaceGL += SKGLElementOnPaintSurface;
SkiaCanvas.PaintSurface += SKElementOnPaintSurface;



Children.Add(_selectRectangle);

Map = new Map();

Loaded += MapControlLoaded;
Expand Down Expand Up @@ -578,7 +613,7 @@ private static Rectangle CreateSelectRectangle()

public Canvas WpfCanvas { get; } = CreateWpfRenderCanvas();

private SKElement SkiaCanvas { get; } = CreateSkiaRenderElement();
private ISkiaCanvas SkiaCanvas { get; }

public RenderMode RenderMode
{
Expand Down Expand Up @@ -613,6 +648,13 @@ private static Canvas CreateWpfRenderCanvas()
};
}

private static SKGLWpfControl CreateSkiaGLRenderElement()
{

return new SKGLWpfControl();
}


private static SKElement CreateSkiaRenderElement()
{
return new SKElement
Expand All @@ -622,6 +664,8 @@ private static SKElement CreateSkiaRenderElement()
};
}



public event EventHandler<FeatureInfoEventArgs> FeatureInfo; // todo: Remove and add sample for alternative

public void RefreshGraphics()
Expand Down Expand Up @@ -957,7 +1001,21 @@ private void OnManipulationCompleted(object sender, ManipulationCompletedEventAr
Refresh();
}

private void SKElementOnPaintSurface(object sender, SKPaintSurfaceEventArgs args)
private void SKElementOnPaintSurface(object sender, SKPaintSurfaceEventArgs args) //
{
if (Renderer == null) return;
if (_map == null) return;
if (PixelDensity <= 0) return;

args.Surface.Canvas.Scale(PixelDensity, PixelDensity);

Navigator.UpdateAnimations();
Renderer.Render(args.Surface.Canvas, new Viewport(Viewport), Map.Layers, Map.Widgets, Map.BackColor);
}



private void SKGLElementOnPaintSurface(object sender, SKPaintGLSurfaceEventArgs args) // SKPaintSurfaceEventArgs
{
if (Renderer == null) return;
if (_map == null) return;
Expand Down
126 changes: 126 additions & 0 deletions src/DesktopClient/Misc/SKElement.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using SkiaSharp;
using SkiaSharp.Views.Desktop;

namespace TacControl.Misc
{
[DefaultEvent("PaintSurface")]
[DefaultProperty("Name")]
public class SKElement : FrameworkElement, ISkiaCanvas
{
private readonly bool designMode;

private WriteableBitmap bitmap;
private bool ignorePixelScaling;

public SKElement()
{
designMode = DesignerProperties.GetIsInDesignMode(this);
}

[Bindable(false)]
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[EditorBrowsable(EditorBrowsableState.Never)]
public SKSize CanvasSize => bitmap == null ? SKSize.Empty : new SKSize(bitmap.PixelWidth, bitmap.PixelHeight);

public bool IgnorePixelScaling
{
get { return ignorePixelScaling; }
set
{
ignorePixelScaling = value;
InvalidateVisual();
}
}

// fake, for interface
[Category("Appearance")]
public event EventHandler<SKPaintGLSurfaceEventArgs> PaintSurfaceGL;

[Category("Appearance")]
public event EventHandler<SKPaintSurfaceEventArgs> PaintSurface;

protected override void OnRender(DrawingContext drawingContext)
{
base.OnRender(drawingContext);

if (designMode)
return;

if (Visibility != Visibility.Visible || PresentationSource.FromVisual(this) == null)
return;

var size = CreateSize(out var scaleX, out var scaleY);
if (size.Width <= 0 || size.Height <= 0)
return;

var info = new SKImageInfo(size.Width, size.Height, SKImageInfo.PlatformColorType, SKAlphaType.Premul);

// reset the bitmap if the size has changed
if (bitmap == null || info.Width != bitmap.PixelWidth || info.Height != bitmap.PixelHeight)
{
bitmap = new WriteableBitmap(info.Width, size.Height, 96 * scaleX, 96 * scaleY, PixelFormats.Pbgra32, null);
}

// draw on the bitmap
bitmap.Lock();
using (var surface = SKSurface.Create(info, bitmap.BackBuffer, bitmap.BackBufferStride))
{
OnPaintSurface(new SKPaintSurfaceEventArgs(surface, info));
}

// draw the bitmap to the screen
bitmap.AddDirtyRect(new Int32Rect(0, 0, info.Width, size.Height));
bitmap.Unlock();
drawingContext.DrawImage(bitmap, new Rect(0, 0, ActualWidth, ActualHeight));
}

protected virtual void OnPaintSurface(SKPaintSurfaceEventArgs e)
{
// invoke the event
PaintSurface?.Invoke(this, e);
}

protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
{
base.OnRenderSizeChanged(sizeInfo);

InvalidateVisual();
}

private SKSizeI CreateSize(out double scaleX, out double scaleY)
{
scaleX = 1.0;
scaleY = 1.0;

var w = ActualWidth;
var h = ActualHeight;

if (!IsPositive(w) || !IsPositive(h))
return SKSizeI.Empty;

if (IgnorePixelScaling)
return new SKSizeI((int)w, (int)h);

var m = PresentationSource.FromVisual(this).CompositionTarget.TransformToDevice;
scaleX = m.M11;
scaleY = m.M22;
return new SKSizeI((int)(w * scaleX), (int)(h * scaleY));

bool IsPositive(double value)
{
return !double.IsNaN(value) && !double.IsInfinity(value) && value > 0;
}
}
}
}
Loading

0 comments on commit a90164a

Please sign in to comment.