Browse Source

Dispose GL drawing session if we were unable to create a drawing context

Nikita Tsukanov 6 years ago
parent
commit
e5943a3523
1 changed files with 51 additions and 38 deletions
  1. 51 38
      src/Skia/Avalonia.Skia/GlRenderTarget.cs

+ 51 - 38
src/Skia/Avalonia.Skia/GlRenderTarget.cs

@@ -26,51 +26,64 @@ namespace Avalonia.Skia
         public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer)
         {
             var session = _surface.BeginDraw();
-            var disp = session.Display;
-            var gl = disp.GlInterface;
-            gl.GetIntegerv(GL_FRAMEBUFFER_BINDING, out var fb);
-
-            var size = session.Size;
-            var scaling = session.Scaling;
-            if (size.Width <= 0 || size.Height <= 0 || scaling < 0)
-            {
-                throw new InvalidOperationException(
-                    $"Can't create drawing context for surface with {size} size and {scaling} scaling");
-            }
-
-            gl.Viewport(0, 0, size.Width, size.Height);
-            gl.ClearStencil(0);
-            gl.ClearColor(0, 0, 0, 0);
-            gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-            lock (_grContext)
+            bool success = false;
+            try
             {
-                _grContext.ResetContext();
-
-                GRBackendRenderTarget renderTarget =
-                    new GRBackendRenderTarget(size.Width, size.Height, disp.SampleCount, disp.StencilSize,
-                        new GRGlFramebufferInfo((uint)fb, GRPixelConfig.Rgba8888.ToGlSizedFormat()));
-                var surface = SKSurface.Create(_grContext, renderTarget,
-                    GRSurfaceOrigin.BottomLeft,
-                    GRPixelConfig.Rgba8888.ToColorType());
+                var disp = session.Display;
+                var gl = disp.GlInterface;
+                gl.GetIntegerv(GL_FRAMEBUFFER_BINDING, out var fb);
 
-                var nfo = new DrawingContextImpl.CreateInfo
+                var size = session.Size;
+                var scaling = session.Scaling;
+                if (size.Width <= 0 || size.Height <= 0 || scaling < 0)
                 {
-                    GrContext = _grContext,
-                    Canvas = surface.Canvas,
-                    Dpi = SkiaPlatform.DefaultDpi * scaling,
-                    VisualBrushRenderer = visualBrushRenderer,
-                    DisableTextLcdRendering = true
-                };
+                    session.Dispose();
+                    throw new InvalidOperationException(
+                        $"Can't create drawing context for surface with {size} size and {scaling} scaling");
+                }
 
-                return new DrawingContextImpl(nfo, Disposable.Create(() =>
+                gl.Viewport(0, 0, size.Width, size.Height);
+                gl.ClearStencil(0);
+                gl.ClearColor(0, 0, 0, 0);
+                gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+                lock (_grContext)
                 {
+                    _grContext.ResetContext();
+
+                    GRBackendRenderTarget renderTarget =
+                        new GRBackendRenderTarget(size.Width, size.Height, disp.SampleCount, disp.StencilSize,
+                            new GRGlFramebufferInfo((uint)fb, GRPixelConfig.Rgba8888.ToGlSizedFormat()));
+                    var surface = SKSurface.Create(_grContext, renderTarget,
+                        GRSurfaceOrigin.BottomLeft,
+                        GRPixelConfig.Rgba8888.ToColorType());
+
+                    var nfo = new DrawingContextImpl.CreateInfo
+                    {
+                        GrContext = _grContext,
+                        Canvas = surface.Canvas,
+                        Dpi = SkiaPlatform.DefaultDpi * scaling,
+                        VisualBrushRenderer = visualBrushRenderer,
+                        DisableTextLcdRendering = true
+                    };
+
                     
-                    surface.Canvas.Flush();
-                    surface.Dispose();
-                    renderTarget.Dispose();
-                    _grContext.Flush();
+                    var ctx = new DrawingContextImpl(nfo, Disposable.Create(() =>
+                    {
+
+                        surface.Canvas.Flush();
+                        surface.Dispose();
+                        renderTarget.Dispose();
+                        _grContext.Flush();
+                        session.Dispose();
+                    }));
+                    success = true;
+                    return ctx;
+                }
+            }
+            finally
+            {
+                if(!success)
                     session.Dispose();
-                }));
             }
         }
     }