Many improvements to the iOS/tvOS/macOS views and layers

This commit is contained in:
Matthew Leibowitz 2016-09-09 01:21:16 +02:00
Родитель 7f8a09e946
Коммит 9f022eb461
10 изменённых файлов: 174 добавлений и 92 удалений

Просмотреть файл

@ -0,0 +1,38 @@
using System;
#if __IOS__ || __TVOS__
using OpenTK.Graphics.ES20;
#elif __MAC__
using OpenTK.Graphics.OpenGL;
#endif
namespace SkiaSharp.Views
{
internal static class SKGLDrawable
{
public static GRBackendRenderTargetDesc CreateRenderTarget()
{
int framebuffer, stencil, samples;
GL.GetInteger(GetPName.FramebufferBinding, out framebuffer);
GL.GetInteger(GetPName.StencilBits, out stencil);
GL.GetInteger(GetPName.Samples, out samples);
int bufferWidth = 0;
int bufferHeight = 0;
#if __IOS__ || __TVOS__
GL.GetRenderbufferParameter(RenderbufferTarget.Renderbuffer, RenderbufferParameterName.RenderbufferWidth, out bufferWidth);
GL.GetRenderbufferParameter(RenderbufferTarget.Renderbuffer, RenderbufferParameterName.RenderbufferHeight, out bufferHeight);
#endif
return new GRBackendRenderTargetDesc
{
Width = bufferWidth,
Height = bufferHeight,
Config = GRPixelConfig.Rgba8888,
Origin = GRSurfaceOrigin.TopLeft,
SampleCount = samples,
StencilBits = stencil,
RenderTargetHandle = (IntPtr)framebuffer,
};
}
}
}

Просмотреть файл

@ -12,6 +12,7 @@ namespace SkiaSharp.Views
drawable = new SKDrawable();
SetNeedsDisplay();
NeedsDisplayOnBoundsChange = true;
}
public ISKLayerDelegate SKDelegate { get; set; }
@ -36,13 +37,6 @@ namespace SkiaSharp.Views
{
}
public override void LayoutSublayers()
{
base.LayoutSublayers();
SetNeedsDisplay();
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);

Просмотреть файл

@ -14,5 +14,7 @@
<Compile Include="$(MSBuildThisFileDirectory)SKDrawable.cs">
<Link>SKDrawable.cs</Link>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)ISKGLLayerDelegate.cs" />
<Compile Include="$(MSBuildThisFileDirectory)SKGLDrawable.cs" />
</ItemGroup>
</Project>

Просмотреть файл

@ -1,5 +1,5 @@
using System;
using CoreAnimation;
using CoreGraphics;
using OpenGLES;
using OpenTK.Graphics.ES20;
@ -8,50 +8,38 @@ namespace SkiaSharp.Views
public class SKGLLayer : CAEAGLLayer
{
private EAGLContext glContext;
private uint colorRenderBuffer;
private int renderBuffer;
private int framebuffer;
private GRContext context;
private int framebuffer;
private int bufferWidth;
private int bufferHeight;
private GRBackendRenderTargetDesc renderTarget;
public SKGLLayer()
{
Opaque = true;
}
public ISKGLLayerDelegate SKDelegate { get; set; }
public virtual void DrawInSurface(SKSurface surface, GRBackendRenderTargetDesc renderTarget)
public virtual void Render()
{
}
public override void LayoutSublayers()
{
base.LayoutSublayers();
if (glContext == null)
CreateGlContext();
if (context == null)
CreateSkiaContext();
{
PrepareGLContexts();
}
EAGLContext.SetCurrentContext(glContext);
// create the surface
var renderTarget = new GRBackendRenderTargetDesc
if (renderTarget.Width == 0 || renderTarget.Height == 0)
{
Width = bufferWidth,
Height = bufferHeight,
Config = GRPixelConfig.Rgba8888,
Origin = GRSurfaceOrigin.TopLeft,
SampleCount = 0,
StencilBits = 8,
RenderTargetHandle = (IntPtr)framebuffer,
};
renderTarget = SKGLDrawable.CreateRenderTarget();
}
using (var surface = SKSurface.Create(context, renderTarget))
{
// draw on the surface
DrawInSurface(surface, renderTarget);
SKDelegate.DrawInSurface(surface, renderTarget);
SKDelegate?.DrawInSurface(surface, renderTarget);
surface.Canvas.Flush();
}
@ -61,36 +49,64 @@ namespace SkiaSharp.Views
// present the GL buffers
glContext.PresentRenderBuffer((uint)RenderbufferTarget.Renderbuffer);
EAGLContext.SetCurrentContext(null);
}
private void CreateSkiaContext()
public override CGRect Frame
{
EAGLContext.SetCurrentContext(glContext);
// get the bits for SkiaSharp
var glInterface = GRGlInterface.CreateNativeInterface();
context = GRContext.Create(GRBackend.OpenGL, glInterface);
get { return base.Frame; }
set
{
base.Frame = value;
if (glContext != null)
{
ResizeGLContexts();
renderTarget = default(GRBackendRenderTargetDesc);
}
Render();
}
}
private void CreateGlContext()
public virtual void DrawInSurface(SKSurface surface, GRBackendRenderTargetDesc renderTarget)
{
}
public virtual void PrepareGLContexts()
{
// create GL context
glContext = new EAGLContext(EAGLRenderingAPI.OpenGLES2);
EAGLContext.SetCurrentContext(glContext);
// create render buffer
GL.GenRenderbuffers(1, out colorRenderBuffer);
GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, colorRenderBuffer);
GL.GenRenderbuffers(1, out renderBuffer);
GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, renderBuffer);
glContext.RenderBufferStorage((uint)RenderbufferTarget.Renderbuffer, this);
// get dimensions from buffer
GL.GetRenderbufferParameter(RenderbufferTarget.Renderbuffer, RenderbufferParameterName.RenderbufferWidth, out bufferWidth);
GL.GetRenderbufferParameter(RenderbufferTarget.Renderbuffer, RenderbufferParameterName.RenderbufferHeight, out bufferHeight);
// create frame buffer
GL.GenFramebuffers(1, out framebuffer);
GL.BindFramebuffer(FramebufferTarget.Framebuffer, framebuffer);
GL.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, FramebufferSlot.ColorAttachment0, RenderbufferTarget.Renderbuffer, colorRenderBuffer);
GL.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, FramebufferSlot.ColorAttachment0, RenderbufferTarget.Renderbuffer, renderBuffer);
// get the bits for SkiaSharp
var glInterface = GRGlInterface.CreateNativeInterface();
context = GRContext.Create(GRBackend.OpenGL, glInterface);
// finished
EAGLContext.SetCurrentContext(null);
}
public virtual void ResizeGLContexts()
{
// nuke old buffers
GL.DeleteRenderbuffers(1, ref renderBuffer);
// re-create render buffer
GL.GenRenderbuffers(1, out renderBuffer);
GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, renderBuffer);
glContext.RenderBufferStorage((uint)RenderbufferTarget.Renderbuffer, this);
// re-link
GL.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, FramebufferSlot.ColorAttachment0, RenderbufferTarget.Renderbuffer, renderBuffer);
}
protected override void Dispose(bool disposing)

Просмотреть файл

@ -1,9 +1,7 @@
using System;
using System.ComponentModel;
using CoreGraphics;
using GLKit;
using OpenGLES;
using OpenTK.Graphics.ES20;
namespace SkiaSharp.Views
{
@ -11,7 +9,7 @@ namespace SkiaSharp.Views
public class SKGLView : GLKView, IGLKViewDelegate
{
private GRContext context;
private int framebuffer;
private GRBackendRenderTargetDesc renderTarget;
public SKGLView()
{
@ -33,28 +31,20 @@ namespace SkiaSharp.Views
public new void DrawInRect(GLKView view, CGRect rect)
{
// get the bits for SkiaSharp
if (context == null)
{
// create the context
var glInterface = GRGlInterface.CreateNativeInterface();
context = GRContext.Create(GRBackend.OpenGL, glInterface);
// get the current frame buffer
GL.GetInteger(GetPName.FramebufferBinding, out framebuffer);
// get the initial details
renderTarget = SKGLDrawable.CreateRenderTarget();
}
// set the dimensions as they might have changed
renderTarget.Width = (int)DrawableWidth;
renderTarget.Height = (int)DrawableHeight;
// create the surface
var renderTarget = new GRBackendRenderTargetDesc
{
Width = (int)DrawableWidth,
Height = (int)DrawableHeight,
Config = GRPixelConfig.Rgba8888,
Origin = GRSurfaceOrigin.TopLeft,
SampleCount = 0,
StencilBits = 8,
RenderTargetHandle = (IntPtr)framebuffer,
};
using (var surface = SKSurface.Create(context, renderTarget))
{
// draw on the surface
@ -71,11 +61,14 @@ namespace SkiaSharp.Views
{
}
public override void LayoutSubviews()
public override CGRect Frame
{
base.LayoutSubviews();
SetNeedsDisplay();
get { return base.Frame; }
set
{
base.Frame = value;
SetNeedsDisplay();
}
}
}
}

Просмотреть файл

@ -12,6 +12,5 @@
<Compile Include="$(MSBuildThisFileDirectory)SKView.cs" />
<Compile Include="$(MSBuildThisFileDirectory)SKGLLayer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)SKGLView.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ISKGLLayerDelegate.cs" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,61 @@
using CoreAnimation;
using CoreVideo;
using OpenGL;
namespace SkiaSharp.Views
{
public class SKGLLayer : CAOpenGLLayer
{
private GRContext context;
private GRBackendRenderTargetDesc renderTarget;
public SKGLLayer()
{
Opaque = true;
NeedsDisplayOnBoundsChange = true;
}
public ISKGLLayerDelegate SKDelegate { get; set; }
public virtual void DrawInSurface(SKSurface surface, GRBackendRenderTargetDesc renderTarget)
{
}
public override void DrawInCGLContext(CGLContext glContext, CGLPixelFormat pixelFormat, double timeInterval, ref CVTimeStamp timeStamp)
{
CGLContext.CurrentContext = glContext;
if (context == null)
{
// get the bits for SkiaSharp
var glInterface = GRGlInterface.CreateNativeInterface();
context = GRContext.Create(GRBackend.OpenGL, glInterface);
}
// create the surface
renderTarget = SKGLDrawable.CreateRenderTarget();
renderTarget.Width = (int)(Bounds.Width * ContentsScale);
renderTarget.Height = (int)(Bounds.Height * ContentsScale);
using (var surface = SKSurface.Create(context, renderTarget))
{
// draw on the surface
DrawInSurface(surface, renderTarget);
SKDelegate?.DrawInSurface(surface, renderTarget);
surface.Canvas.Flush();
}
// flush the SkiaSharp context to the GL context
context.Flush();
base.DrawInCGLContext(glContext, pixelFormat, timeInterval, ref timeStamp);
}
public override void Release(CGLContext glContext)
{
context.Dispose();
base.Release(glContext);
}
}
}

Просмотреть файл

@ -1,4 +1,3 @@
using System;
using System.ComponentModel;
using AppKit;
using CoreGraphics;
@ -30,28 +29,7 @@ namespace SkiaSharp.Views
var glInterface = GRGlInterface.CreateNativeInterface();
context = GRContext.Create(GRBackend.OpenGL, glInterface);
// get the current frame buffer
int framebuffer;
GL.GetInteger(GetPName.FramebufferBinding, out framebuffer);
// get samples
var screen = OpenGLContext.CurrentVirtualScreen;
int samples = 0;
OpenGLContext.PixelFormat.GetValue(ref samples, NSOpenGLPixelFormatAttribute.Samples, screen);
int stencils = 0;
OpenGLContext.PixelFormat.GetValue(ref stencils, NSOpenGLPixelFormatAttribute.StencilSize, screen);
// create the surface
renderTarget = new GRBackendRenderTargetDesc
{
Width = 0, // set later
Height = 0, // set later
Config = GRPixelConfig.Rgba8888,
Origin = GRSurfaceOrigin.TopLeft,
SampleCount = samples,
StencilBits = stencils,
RenderTargetHandle = (IntPtr)framebuffer,
};
renderTarget = SKGLDrawable.CreateRenderTarget();
}
public override void DrawRect(CGRect dirtyRect)

Просмотреть файл

@ -59,6 +59,7 @@
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SKView.cs" />
<Compile Include="SKGLView.cs" />
<Compile Include="SKGLLayer.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />