Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re-work views to avoid incorrect disposal #1180

Merged
merged 6 commits into from
Mar 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion binding/Binding/SKSurface.cs
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ public static SKSurface CreateNull (int width, int height) =>
//

public SKCanvas Canvas =>
GetObject<SKCanvas> (SkiaApi.sk_surface_get_canvas (Handle), false);
GetObject<SKCanvas> (SkiaApi.sk_surface_get_canvas (Handle), false, unrefExisting: false);

[EditorBrowsable (EditorBrowsableState.Never)]
[Obsolete ("Use SurfaceProperties instead.")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@ public abstract class SKGLSurfaceViewRenderer : Java.Lang.Object, GLSurfaceView.
private const GRSurfaceOrigin surfaceOrigin = GRSurfaceOrigin.BottomLeft;

private GRContext context;
private GRGlFramebufferInfo glInfo;
private GRBackendRenderTarget renderTarget;
private SKSurface surface;
private int surfaceWidth;
private int surfaceHeight;
private SKCanvas canvas;

public SKSize CanvasSize => renderTarget.Size;
private SKSizeI lastSize;
private SKSizeI newSize;

public SKSize CanvasSize => lastSize;

public GRContext GRContext => context;

Expand All @@ -44,10 +47,12 @@ public void OnDrawFrame(IGL10 gl)
}

// manage the drawing surface
if (renderTarget == null || surface == null || renderTarget.Width != surfaceWidth || renderTarget.Height != surfaceHeight)
if (renderTarget == null || lastSize != newSize || !renderTarget.IsValid)
{
// create or update the dimensions
renderTarget?.Dispose();
lastSize = newSize;

// read the info from the buffer
var buffer = new int[3];
GLES20.GlGetIntegerv(GLES20.GlFramebufferBinding, buffer, 0);
GLES20.GlGetIntegerv(GLES20.GlStencilBits, buffer, 1);
Expand All @@ -56,35 +61,46 @@ public void OnDrawFrame(IGL10 gl)
var maxSamples = context.GetMaxSurfaceSampleCount(colorType);
if (samples > maxSamples)
samples = maxSamples;
var glInfo = new GRGlFramebufferInfo((uint)buffer[0], colorType.ToGlSizedFormat());
renderTarget = new GRBackendRenderTarget(surfaceWidth, surfaceHeight, samples, buffer[1], glInfo);
glInfo = new GRGlFramebufferInfo((uint)buffer[0], colorType.ToGlSizedFormat());

// create the surface
// destroy the old surface
surface?.Dispose();
surface = null;
canvas = null;

// re-create the render target
renderTarget?.Dispose();
renderTarget = new GRBackendRenderTarget(newSize.Width, newSize.Height, samples, buffer[1], glInfo);
}

// create the surface
if (surface == null)
{
surface = SKSurface.Create(context, renderTarget, surfaceOrigin, colorType);
canvas = surface.Canvas;
}

using (new SKAutoCanvasRestore(surface.Canvas, true))
using (new SKAutoCanvasRestore(canvas, true))
{
// start drawing
var e = new SKPaintGLSurfaceEventArgs(surface, renderTarget, surfaceOrigin, colorType);
var e = new SKPaintGLSurfaceEventArgs(surface, renderTarget, surfaceOrigin, colorType, glInfo);
OnPaintSurface(e);
#pragma warning disable CS0618 // Type or member is obsolete
OnDrawFrame(e.Surface, e.RenderTarget);
#pragma warning restore CS0618 // Type or member is obsolete
}

// flush the SkiaSharp contents to GL
surface.Canvas.Flush();
canvas.Flush();
context.Flush();
}

public void OnSurfaceChanged(IGL10 gl, int width, int height)
{
GLES20.GlViewport(0, 0, width, height);

surfaceWidth = width;
surfaceHeight = height;
// get the new surface size
newSize = new SKSizeI(width, height);
}

public void OnSurfaceCreated(IGL10 gl, EGLConfig config)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@ public abstract class SKGLTextureViewRenderer : Java.Lang.Object, GLTextureView.
private const GRSurfaceOrigin surfaceOrigin = GRSurfaceOrigin.BottomLeft;

private GRContext context;
private GRGlFramebufferInfo glInfo;
private GRBackendRenderTarget renderTarget;
private SKSurface surface;
private int surfaceWidth;
private int surfaceHeight;
private SKCanvas canvas;

public SKSize CanvasSize => renderTarget.Size;
private SKSizeI lastSize;
private SKSizeI newSize;

public SKSize CanvasSize => lastSize;

public GRContext GRContext => context;

Expand All @@ -44,10 +47,12 @@ public void OnDrawFrame(IGL10 gl)
}

// manage the drawing surface
if (renderTarget == null || surface == null || renderTarget.Width != surfaceWidth || renderTarget.Height != surfaceHeight)
if (renderTarget == null || lastSize != newSize || !renderTarget.IsValid)
{
// create or update the dimensions
renderTarget?.Dispose();
lastSize = newSize;

// read the info from the buffer
var buffer = new int[3];
GLES20.GlGetIntegerv(GLES20.GlFramebufferBinding, buffer, 0);
GLES20.GlGetIntegerv(GLES20.GlStencilBits, buffer, 1);
Expand All @@ -56,35 +61,46 @@ public void OnDrawFrame(IGL10 gl)
var maxSamples = context.GetMaxSurfaceSampleCount(colorType);
if (samples > maxSamples)
samples = maxSamples;
var glInfo = new GRGlFramebufferInfo((uint)buffer[0], colorType.ToGlSizedFormat());
renderTarget = new GRBackendRenderTarget(surfaceWidth, surfaceHeight, samples, buffer[1], glInfo);
glInfo = new GRGlFramebufferInfo((uint)buffer[0], colorType.ToGlSizedFormat());

// create the surface
// destroy the old surface
surface?.Dispose();
surface = null;
canvas = null;

// re-create the render target
renderTarget?.Dispose();
renderTarget = new GRBackendRenderTarget(newSize.Width, newSize.Height, samples, buffer[1], glInfo);
}

// create the surface
if (surface == null)
{
surface = SKSurface.Create(context, renderTarget, surfaceOrigin, colorType);
canvas = surface.Canvas;
}

using (new SKAutoCanvasRestore(surface.Canvas, true))
using (new SKAutoCanvasRestore(canvas, true))
{
// start drawing
var e = new SKPaintGLSurfaceEventArgs(surface, renderTarget, surfaceOrigin, colorType);
var e = new SKPaintGLSurfaceEventArgs(surface, renderTarget, surfaceOrigin, colorType, glInfo);
OnPaintSurface(e);
#pragma warning disable CS0618 // Type or member is obsolete
OnDrawFrame(e.Surface, e.RenderTarget);
#pragma warning restore CS0618 // Type or member is obsolete
}

// flush the SkiaSharp contents to GL
surface.Canvas.Flush();
canvas.Flush();
context.Flush();
}

public void OnSurfaceChanged(IGL10 gl, int width, int height)
{
GLES20.GlViewport(0, 0, width, height);

surfaceWidth = width;
surfaceHeight = height;
// get the new surface size
newSize = new SKSizeI(width, height);
}

public void OnSurfaceCreated(IGL10 gl, EGLConfig config)
Expand Down
61 changes: 44 additions & 17 deletions source/SkiaSharp.Views/SkiaSharp.Views.AppleiOS/SKGLLayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,24 @@ public class SKGLLayer : CAEAGLLayer
private uint framebuffer;

private GRContext context;
private GRGlFramebufferInfo glInfo;
private GRBackendRenderTarget renderTarget;
private SKSurface surface;
private SKCanvas canvas;

private SKSizeI lastSize;
private bool recreateSurface = true;

public SKGLLayer()
{
Opaque = true;
}

[EditorBrowsable (EditorBrowsableState.Never)]
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("Use PaintSurface instead.")]
public ISKGLLayerDelegate SKDelegate { get; set; }

public SKSize CanvasSize => renderTarget.Size;
public SKSize CanvasSize => lastSize;

public GRContext GRContext => context;

Expand All @@ -48,31 +53,51 @@ public virtual void Render()

EAGLContext.SetCurrentContext(glContext);

// get the new surface size
var newSize = lastSize;
if (recreateSurface)
{
Gles.glGetRenderbufferParameteriv(Gles.GL_RENDERBUFFER, Gles.GL_RENDERBUFFER_WIDTH, out var bufferWidth);
Gles.glGetRenderbufferParameteriv(Gles.GL_RENDERBUFFER, Gles.GL_RENDERBUFFER_HEIGHT, out var bufferHeight);
newSize = new SKSizeI(bufferWidth, bufferHeight);
}

// manage the drawing surface
if (renderTarget == null || surface == null)
if (recreateSurface || renderTarget == null || lastSize != newSize || !renderTarget.IsValid)
{
// create or update the dimensions
renderTarget?.Dispose();
lastSize = newSize;

// read the info from the buffer
Gles.glGetIntegerv(Gles.GL_FRAMEBUFFER_BINDING, out var framebuffer);
Gles.glGetIntegerv(Gles.GL_STENCIL_BITS, out var stencil);
Gles.glGetIntegerv(Gles.GL_SAMPLES, out var samples);
var maxSamples = context.GetMaxSurfaceSampleCount(colorType);
if (samples > maxSamples)
samples = maxSamples;
Gles.glGetRenderbufferParameteriv(Gles.GL_RENDERBUFFER, Gles.GL_RENDERBUFFER_WIDTH, out var bufferWidth);
Gles.glGetRenderbufferParameteriv(Gles.GL_RENDERBUFFER, Gles.GL_RENDERBUFFER_HEIGHT, out var bufferHeight);
var glInfo = new GRGlFramebufferInfo((uint)framebuffer, colorType.ToGlSizedFormat());
renderTarget = new GRBackendRenderTarget(bufferWidth, bufferHeight, samples, stencil, glInfo);
glInfo = new GRGlFramebufferInfo((uint)framebuffer, colorType.ToGlSizedFormat());

// create the surface
// destroy the old surface
surface?.Dispose();
surface = null;
canvas = null;

// re-create the render target
renderTarget?.Dispose();
renderTarget = new GRBackendRenderTarget(newSize.Width, newSize.Height, samples, stencil, glInfo);
}

// create the surface
if (surface == null)
{
surface = SKSurface.Create(context, renderTarget, surfaceOrigin, colorType);
canvas = surface.Canvas;
}

using (new SKAutoCanvasRestore(surface.Canvas, true))
using (new SKAutoCanvasRestore(canvas, true))
{
// start drawing
var e = new SKPaintGLSurfaceEventArgs(surface, renderTarget, surfaceOrigin, colorType);
var e = new SKPaintGLSurfaceEventArgs(surface, renderTarget, surfaceOrigin, colorType, glInfo);
OnPaintSurface(e);
#pragma warning disable CS0618 // Type or member is obsolete
DrawInSurface(e.Surface, e.RenderTarget);
Expand All @@ -81,7 +106,7 @@ public virtual void Render()
}

// flush the SkiaSharp context to the GL context
surface.Canvas.Flush();
canvas.Flush();
context.Flush();

// present the GL buffers
Expand All @@ -98,8 +123,6 @@ public override CGRect Frame
if (glContext != null)
{
ResizeGLContexts();
renderTarget?.Dispose();
renderTarget = null;
}
Render();
}
Expand All @@ -112,7 +135,7 @@ protected virtual void OnPaintSurface(SKPaintGLSurfaceEventArgs e)
PaintSurface?.Invoke(this, e);
}

[EditorBrowsable (EditorBrowsableState.Never)]
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("Use OnPaintSurface(SKPaintGLSurfaceEventArgs) instead.")]
public virtual void DrawInSurface(SKSurface surface, GRBackendRenderTargetDesc renderTarget)
{
Expand Down Expand Up @@ -140,6 +163,8 @@ private void PrepareGLContexts()

// finished
EAGLContext.SetCurrentContext(null);

recreateSurface = true;
}

private void ResizeGLContexts()
Expand All @@ -154,14 +179,16 @@ private void ResizeGLContexts()

// re-link
Gles.glFramebufferRenderbuffer(Gles.GL_FRAMEBUFFER, Gles.GL_COLOR_ATTACHMENT0, Gles.GL_RENDERBUFFER, renderBuffer);

recreateSurface = true;
}

protected override void Dispose(bool disposing)
{
base.Dispose(disposing);

context.Dispose();
glContext.Dispose();
context?.Dispose();
glContext?.Dispose();
}
}
}
Expand Down
Loading