Browse Source

Merge pull request #2364 from MarchingCube/feature/skia-renderinterface

Allow for modifying Skia PlatformRenderInterface behavior.
pull/2449/head
Nikita Tsukanov 7 years ago
committed by GitHub
parent
commit
55efd41bdb
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 42
      src/Skia/Avalonia.Skia/CustomRenderTarget.cs
  2. 26
      src/Skia/Avalonia.Skia/ICustomSkiaGpu.cs
  3. 29
      src/Skia/Avalonia.Skia/ICustomSkiaRenderSession.cs
  4. 19
      src/Skia/Avalonia.Skia/ICustomSkiaRenderTarget.cs
  5. 30
      src/Skia/Avalonia.Skia/PlatformRenderInterface.cs
  6. 5
      src/Skia/Avalonia.Skia/SkiaApplicationExtensions.cs
  7. 19
      src/Skia/Avalonia.Skia/SkiaOptions.cs
  8. 10
      src/Skia/Avalonia.Skia/SkiaPlatform.cs

42
src/Skia/Avalonia.Skia/CustomRenderTarget.cs

@ -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
src/Skia/Avalonia.Skia/ICustomSkiaGpu.cs

@ -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
src/Skia/Avalonia.Skia/ICustomSkiaRenderSession.cs

@ -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
src/Skia/Avalonia.Skia/ICustomSkiaRenderTarget.cs

@ -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
src/Skia/Avalonia.Skia/PlatformRenderInterface.cs

@ -17,12 +17,23 @@ namespace Avalonia.Skia
/// </summary> /// </summary>
internal class PlatformRenderInterface : IPlatformRenderInterface internal class PlatformRenderInterface : IPlatformRenderInterface
{ {
private readonly ICustomSkiaGpu _customSkiaGpu;
private GRContext GrContext { get; } private GRContext GrContext { get; }
public IEnumerable<string> InstalledFontNames => SKFontManager.Default.FontFamilies; 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>(); var gl = AvaloniaLocator.Current.GetService<IWindowingPlatformGlFeature>();
if (gl != null) if (gl != null)
{ {
@ -32,12 +43,11 @@ namespace Avalonia.Skia
? GRGlInterface.AssembleGlInterface((_, proc) => display.GlInterface.GetProcAddress(proc)) ? GRGlInterface.AssembleGlInterface((_, proc) => display.GlInterface.GetProcAddress(proc))
: GRGlInterface.AssembleGlesInterface((_, proc) => display.GlInterface.GetProcAddress(proc))) : GRGlInterface.AssembleGlesInterface((_, proc) => display.GlInterface.GetProcAddress(proc)))
{ {
GrContext = GRContext.Create(GRBackend.OpenGL, iface); GrContext = GRContext.Create(GRBackend.OpenGL, iface);
} }
} }
} }
/// <inheritdoc /> /// <inheritdoc />
public IFormattedTextImpl CreateFormattedText( public IFormattedTextImpl CreateFormattedText(
string text, string text,
@ -98,13 +108,23 @@ namespace Avalonia.Skia
DisableTextLcdRendering = false, DisableTextLcdRendering = false,
GrContext = GrContext GrContext = GrContext
}; };
return new SurfaceRenderTarget(createInfo); return new SurfaceRenderTarget(createInfo);
} }
/// <inheritdoc /> /// <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) foreach (var surface in surfaces)
{ {
if (surface is IGlPlatformSurface glSurface && GrContext != null) if (surface is IGlPlatformSurface glSurface && GrContext != null)

5
src/Skia/Avalonia.Skia/SkiaApplicationExtensions.cs

@ -20,8 +20,9 @@ namespace Avalonia
/// <returns>Configure builder.</returns> /// <returns>Configure builder.</returns>
public static T UseSkia<T>(this T builder) where T : AppBuilderBase<T>, new() public static T UseSkia<T>(this T builder) where T : AppBuilderBase<T>, new()
{ {
builder.UseRenderingSubsystem(() => SkiaPlatform.Initialize(), "Skia"); return builder.UseRenderingSubsystem(() => SkiaPlatform.Initialize(
return builder; AvaloniaLocator.Current.GetService<SkiaOptions>() ?? new SkiaOptions()),
"Skia");
} }
} }
} }

19
src/Skia/Avalonia.Skia/SkiaOptions.cs

@ -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
src/Skia/Avalonia.Skia/SkiaPlatform.cs

@ -15,8 +15,14 @@ namespace Avalonia.Skia
/// </summary> /// </summary>
public static void Initialize() 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 AvaloniaLocator.CurrentMutable
.Bind<IPlatformRenderInterface>().ToConstant(renderInterface); .Bind<IPlatformRenderInterface>().ToConstant(renderInterface);
} }

Loading…
Cancel
Save