Skip to content

Commit

Permalink
Merge pull request #2364 from MarchingCube/feature/skia-renderinterface
Browse files Browse the repository at this point in the history
Allow for modifying Skia PlatformRenderInterface behavior.
  • Loading branch information
kekekeks authored Apr 12, 2019
2 parents 03076a4 + ac97dec commit 55efd41
Show file tree
Hide file tree
Showing 8 changed files with 171 additions and 9 deletions.
42 changes: 42 additions & 0 deletions src/Skia/Avalonia.Skia/CustomRenderTarget.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.

using Avalonia.Platform;
using Avalonia.Rendering;

namespace Avalonia.Skia
{
/// <summary>
/// Adapts <see cref="ICustomSkiaRenderTarget"/> to be used within Skia rendering pipeline.
/// </summary>
internal class CustomRenderTarget : IRenderTarget
{
private readonly ICustomSkiaRenderTarget _renderTarget;

public CustomRenderTarget(ICustomSkiaRenderTarget renderTarget)
{
_renderTarget = renderTarget;
}

public void Dispose()
{
_renderTarget.Dispose();
}

public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer)
{
ICustomSkiaRenderSession session = _renderTarget.BeginRendering();

var nfo = new DrawingContextImpl.CreateInfo
{
GrContext = session.GrContext,
Canvas = session.Canvas,
Dpi = SkiaPlatform.DefaultDpi * session.ScaleFactor,
VisualBrushRenderer = visualBrushRenderer,
DisableTextLcdRendering = true
};

return new DrawingContextImpl(nfo, session);
}
}
}
26 changes: 26 additions & 0 deletions src/Skia/Avalonia.Skia/ICustomSkiaGpu.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.

using System.Collections.Generic;
using SkiaSharp;

namespace Avalonia.Skia
{
/// <summary>
/// Custom Skia gpu instance.
/// </summary>
public interface ICustomSkiaGpu
{
/// <summary>
/// Skia GrContext used.
/// </summary>
GRContext GrContext { get; }

/// <summary>
/// Attempts to create custom render target from given surfaces.
/// </summary>
/// <param name="surfaces">Surfaces.</param>
/// <returns>Created render target or <see langword="null"/> if it fails.</returns>
ICustomSkiaRenderTarget TryCreateRenderTarget(IEnumerable<object> surfaces);
}
}
29 changes: 29 additions & 0 deletions src/Skia/Avalonia.Skia/ICustomSkiaRenderSession.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.

using System;
using SkiaSharp;

namespace Avalonia.Skia
{
/// <summary>
/// Custom render session for Skia render target.
/// </summary>
public interface ICustomSkiaRenderSession : IDisposable
{
/// <summary>
/// GrContext used by this session.
/// </summary>
GRContext GrContext { get; }

/// <summary>
/// Canvas that will be used to render.
/// </summary>
SKCanvas Canvas { get; }

/// <summary>
/// Scaling factor.
/// </summary>
double ScaleFactor { get; }
}
}
19 changes: 19 additions & 0 deletions src/Skia/Avalonia.Skia/ICustomSkiaRenderTarget.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.

using System;

namespace Avalonia.Skia
{
/// <summary>
/// Custom Skia render target.
/// </summary>
public interface ICustomSkiaRenderTarget : IDisposable
{
/// <summary>
/// Start rendering to this render target.
/// </summary>
/// <returns></returns>
ICustomSkiaRenderSession BeginRendering();
}
}
30 changes: 25 additions & 5 deletions src/Skia/Avalonia.Skia/PlatformRenderInterface.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,23 @@ namespace Avalonia.Skia
/// </summary>
internal class PlatformRenderInterface : IPlatformRenderInterface
{
private readonly ICustomSkiaGpu _customSkiaGpu;

private GRContext GrContext { get; }

public IEnumerable<string> InstalledFontNames => SKFontManager.Default.FontFamilies;

public PlatformRenderInterface()
public PlatformRenderInterface(ICustomSkiaGpu customSkiaGpu)
{
if (customSkiaGpu != null)
{
_customSkiaGpu = customSkiaGpu;

GrContext = _customSkiaGpu.GrContext;

return;
}

var gl = AvaloniaLocator.Current.GetService<IWindowingPlatformGlFeature>();
if (gl != null)
{
Expand All @@ -32,12 +43,11 @@ public PlatformRenderInterface()
? GRGlInterface.AssembleGlInterface((_, proc) => display.GlInterface.GetProcAddress(proc))
: GRGlInterface.AssembleGlesInterface((_, proc) => display.GlInterface.GetProcAddress(proc)))
{

GrContext = GRContext.Create(GRBackend.OpenGL, iface);
}
}
}

/// <inheritdoc />
public IFormattedTextImpl CreateFormattedText(
string text,
Expand Down Expand Up @@ -98,13 +108,23 @@ public IRenderTargetBitmapImpl CreateRenderTargetBitmap(PixelSize size, Vector d
DisableTextLcdRendering = false,
GrContext = GrContext
};

return new SurfaceRenderTarget(createInfo);
}

/// <inheritdoc />
public virtual IRenderTarget CreateRenderTarget(IEnumerable<object> surfaces)
public IRenderTarget CreateRenderTarget(IEnumerable<object> surfaces)
{
if (_customSkiaGpu != null)
{
ICustomSkiaRenderTarget customRenderTarget = _customSkiaGpu.TryCreateRenderTarget(surfaces);

if (customRenderTarget != null)
{
return new CustomRenderTarget(customRenderTarget);
}
}

foreach (var surface in surfaces)
{
if (surface is IGlPlatformSurface glSurface && GrContext != null)
Expand Down
5 changes: 3 additions & 2 deletions src/Skia/Avalonia.Skia/SkiaApplicationExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ public static class SkiaApplicationExtensions
/// <returns>Configure builder.</returns>
public static T UseSkia<T>(this T builder) where T : AppBuilderBase<T>, new()
{
builder.UseRenderingSubsystem(() => SkiaPlatform.Initialize(), "Skia");
return builder;
return builder.UseRenderingSubsystem(() => SkiaPlatform.Initialize(
AvaloniaLocator.Current.GetService<SkiaOptions>() ?? new SkiaOptions()),
"Skia");
}
}
}
19 changes: 19 additions & 0 deletions src/Skia/Avalonia.Skia/SkiaOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.

using System;
using Avalonia.Skia;

namespace Avalonia
{
/// <summary>
/// Options for Skia rendering subsystem.
/// </summary>
public class SkiaOptions
{
/// <summary>
/// Custom gpu factory to use. Can be used to customize behavior of Skia renderer.
/// </summary>
public Func<ICustomSkiaGpu> CustomGpuFactory { get; set; }
}
}
10 changes: 8 additions & 2 deletions src/Skia/Avalonia.Skia/SkiaPlatform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,14 @@ public static class SkiaPlatform
/// </summary>
public static void Initialize()
{
var renderInterface = new PlatformRenderInterface();

Initialize(new SkiaOptions());
}

public static void Initialize(SkiaOptions options)
{
var customGpu = options.CustomGpuFactory?.Invoke();
var renderInterface = new PlatformRenderInterface(customGpu);

AvaloniaLocator.CurrentMutable
.Bind<IPlatformRenderInterface>().ToConstant(renderInterface);
}
Expand Down

0 comments on commit 55efd41

Please sign in to comment.