Example #1
0
        private void PrepareGLContexts()
        {
            // create GL context
            glContext = new EAGLContext(EAGLRenderingAPI.OpenGLES2);
            EAGLContext.SetCurrentContext(glContext);

            // create render buffer
            Gles.glGenRenderbuffers(1, ref renderBuffer);
            Gles.glBindRenderbuffer(Gles.GL_RENDERBUFFER, renderBuffer);
            glContext.RenderBufferStorage(Gles.GL_RENDERBUFFER, this);

            // create frame buffer
            Gles.glGenFramebuffers(1, ref framebuffer);
            Gles.glBindFramebuffer(Gles.GL_FRAMEBUFFER, framebuffer);
            Gles.glFramebufferRenderbuffer(Gles.GL_FRAMEBUFFER, Gles.GL_COLOR_ATTACHMENT0, Gles.GL_RENDERBUFFER, renderBuffer);

            // get the bits for SkiaSharp
            var glInterface = GRGlInterface.Create();

            context = GRContext.CreateGl(glInterface);

            // finished
            EAGLContext.SetCurrentContext(null);

            recreateSurface = true;
        }
Example #2
0
        protected override void OnRenderFrame(Rect rect)
        {
            // clear everything
            Gles.glClear(Gles.GL_COLOR_BUFFER_BIT | Gles.GL_DEPTH_BUFFER_BIT | Gles.GL_STENCIL_BUFFER_BIT);

            // create the SkiaSharp context
            if (context == null)
            {
                glInterface = GRGlInterface.Create();
                context     = GRContext.CreateGl(glInterface);
            }

            // get the new surface size
            var newSize = new SKSizeI((int)rect.Width, (int)rect.Height);

            // manage the drawing surface
            if (renderTarget == null || lastSize != newSize || !renderTarget.IsValid)
            {
                // create or update the dimensions
                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;
                }

                glInfo = new GRGlFramebufferInfo((uint)framebuffer, colorType.ToGlSizedFormat());

                // 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(canvas, true))
            {
                // start drawing
                OnPaintSurface(new SKPaintGLSurfaceEventArgs(surface, renderTarget, surfaceOrigin, colorType, glInfo));
            }

            // update the control
            canvas.Flush();
            context.Flush();
        }
Example #3
0
        private void InitSkia()
        {
            if (grContext == null)
            {
                var glInterface = GRGlInterface.Create();
                grContext = GRContext.CreateGl(glInterface);
            }

            // define the surface properties
            // create or update the dimensions
            renderTarget?.Dispose();
            GL.GetInteger(GetPName.FramebufferBinding, out var framebuffer);
            var stencil = 0;

            GL.GetInteger(GetPName.Samples, out var samples);
            var maxSamples = grContext.GetMaxSurfaceSampleCount(ColorType);

            if (samples > maxSamples)
            {
                samples = maxSamples;
            }
            var glInfo = new GRGlFramebufferInfo((uint)framebuffer, ColorType.ToGlSizedFormat());

            renderTarget = new GRBackendRenderTarget(CurrentSize.X, CurrentSize.Y, 0, 0, glInfo);

            // create the surface
            surface?.Dispose();
            surface = SKSurface.Create(grContext, renderTarget, SurfaceOrigin, ColorType);

            Paint = new SKPaint {
                Color = new SKColor(0, 128, 0), IsAntialias = true
            };
        }
Example #4
0
        public override void PrepareOpenGL()
        {
            base.PrepareOpenGL();

            // create the context
            var glInterface = GRGlInterface.Create();

            context = GRContext.CreateGl(glInterface);
        }
Example #5
0
        internal void RenderFrame()
        {
            if (!jsInfo.IsValid)
            {
                return;
            }

            // create the SkiaSharp context
            if (context == null)
            {
                glInterface = GRGlInterface.Create();
                context     = GRContext.CreateGl(glInterface);

                // bump the default resource cache limit
                context.SetResourceCacheLimit(ResourceCacheBytes);
            }

            // get the new surface size
            var newSize = new SKSizeI((int)(ActualWidth * ContentsScale), (int)(ActualHeight * ContentsScale));

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

                glInfo = new GRGlFramebufferInfo(jsInfo.FboId, colorType.ToGlSizedFormat());

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

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

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

            using (new SKAutoCanvasRestore(canvas, true))
            {
                // start drawing
#pragma warning disable CS0612 // Type or member is obsolete
                OnPaintSurface(new SKPaintGLSurfaceEventArgs(surface, renderTarget, surfaceOrigin, colorType, glInfo));
#pragma warning restore CS0612 // Type or member is obsolete
            }

            // update the control
            canvas.Flush();
            context.Flush();
        }
Example #6
0
        protected override void OnAfterRender(bool firstRender)
        {
            if (firstRender)
            {
                Threading.Dispatcher.UIThread.Post(async() =>
                {
                    _inputHelper  = await InputHelperInterop.ImportAsync(Js, _inputElement);
                    _canvasHelper = await InputHelperInterop.ImportAsync(Js, _htmlCanvas);

                    _inputHelper.Hide();
                    _canvasHelper.SetCursor("default");
                    _topLevelImpl.SetCssCursor = x =>
                    {
                        _inputHelper.SetCursor(x);  //macOS
                        _canvasHelper.SetCursor(x); //windows
                    };

                    Console.WriteLine("starting html canvas setup");
                    _interop = await SKHtmlCanvasInterop.ImportAsync(Js, _htmlCanvas, OnRenderFrame);

                    Console.WriteLine("Interop created");
                    _jsGlInfo = _interop.InitGL();

                    Console.WriteLine("jsglinfo created - init gl");

                    _sizeWatcher = await SizeWatcherInterop.ImportAsync(Js, _htmlCanvas, OnSizeChanged);
                    _dpiWatcher  = await DpiWatcherInterop.ImportAsync(Js, OnDpiChanged);

                    Console.WriteLine("watchers created.");

                    // create the SkiaSharp context
                    if (_context == null)
                    {
                        Console.WriteLine("create glcontext");
                        _glInterface = GRGlInterface.Create();
                        _context     = GRContext.CreateGl(_glInterface);

                        var options = AvaloniaLocator.Current.GetService <SkiaOptions>();
                        // bump the default resource cache limit
                        _context.SetResourceCacheLimit(options?.MaxGpuResourceSizeBytes ?? 32 * 1024 * 1024);
                        Console.WriteLine("glcontext created and resource limit set");
                    }

                    _topLevelImpl.SetSurface(_context, _jsGlInfo, ColorType,
                                             new PixelSize((int)_canvasSize.Width, (int)_canvasSize.Height), _dpi);

                    _initialised = true;

                    _topLevel.Prepare();

                    _topLevel.Renderer.Start();
                    Invalidate();
                });
            }
        }
Example #7
0
        protected override GRContext TryBuildGRContext()
        {
            var glInterface = GRGlInterface.Create();

            if (glInterface == null)
            {
                throw new NotSupportedException($"OpenGL is not supported in this system");
            }

            return(GRContext.CreateGl(glInterface));
        }
Example #8
0
        public void CreateDefaultInterfaceIsValid()
        {
            using (var ctx = CreateGlContext()) {
                ctx.MakeCurrent();

                var glInterface = GRGlInterface.Create();

                Assert.NotNull(glInterface);
                Assert.True(glInterface.Validate());
            }
        }
Example #9
0
        public void AssembleInterfaceIsValid()
        {
            using (var ctx = CreateGlContext()) {
                ctx.MakeCurrent();

                if (IsMac)
                {
                    var lib = MacDynamicLibraries.dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib", 1);

                    var glInterface = GRGlInterface.Create(name => {
                        return(MacDynamicLibraries.dlsym(lib, name));
                    });

                    Assert.NotNull(glInterface);
                    Assert.True(glInterface.Validate());

                    MacDynamicLibraries.dlclose(lib);
                }
                else if (IsWindows)
                {
                    var lib = WindowsDynamicLibraries.LoadLibrary("opengl32.dll");

                    var glInterface = GRGlInterface.Create(name => {
                        var ptr = WindowsDynamicLibraries.GetProcAddress(lib, name);
                        if (ptr == IntPtr.Zero)
                        {
                            ptr = wglGetProcAddress(name);
                        }
                        return(ptr);
                    });

                    Assert.NotNull(glInterface);
                    Assert.True(glInterface.Validate());

                    WindowsDynamicLibraries.FreeLibrary(lib);
                }
                else if (IsLinux)
                {
                    var glInterface = GRGlInterface.Create(name => {
                        return(glXGetProcAddress(name));
                    });

                    Assert.NotNull(glInterface);
                    Assert.True(glInterface.Validate());
                }
                else
                {
                    // more platforms !!!
                    throw new Exception("Some strange platform that is not Windows, macOS nor Linux...");
                }
            }
        }
Example #10
0
        public void CreateSpecificContextWithOptionsIsValid()
        {
            using var ctx = CreateGlContext();
            ctx.MakeCurrent();

            var glInterface = GRGlInterface.Create();

            Assert.True(glInterface.Validate());

            var options   = new GRContextOptions();
            var grContext = GRContext.CreateGl(glInterface, options);

            Assert.NotNull(grContext);
        }
Example #11
0
        public void CreateSpecificContextIsValid()
        {
            using (var ctx = CreateGlContext()) {
                ctx.MakeCurrent();

                var glInterface = GRGlInterface.Create();

                Assert.True(glInterface.Validate());

                var grContext = GRContext.CreateGl(glInterface);

                Assert.NotNull(grContext);
            }
        }
Example #12
0
        protected override void OnRenderFrame()
        {
            // create the contexts if not done already
            if (grContext == null)
            {
                var glInterface = GRGlInterface.Create();
                grContext = GRContext.CreateGl(glInterface);
            }
            // manage the drawing surface
            var alloc = Allocation;
            var res   = (int)Math.Max(1.0, Gdk.Screen.Default.Resolution / 96.0);
            var w     = Math.Max(0, alloc.Width * res);
            var h     = Math.Max(0, alloc.Height * res);

            if (renderTarget == null || surface == null || renderTarget.Width != w || renderTarget.Height != h)
            {
                // create or update the dimensions
                renderTarget?.Dispose();
                GL.GetInteger(GetPName.FramebufferBinding, out var framebuffer);
                GL.GetInteger(GetPName.StencilBits, out var stencil);
                GL.GetInteger(GetPName.Samples, out var samples);
                var maxSamples = grContext.GetMaxSurfaceSampleCount(COLOR_TYPE);
                if (samples > maxSamples)
                {
                    samples = maxSamples;
                }
                var glInfo = new GRGlFramebufferInfo((uint)framebuffer, COLOR_TYPE.ToGlSizedFormat());
                renderTarget = new GRBackendRenderTarget(w, h, samples, stencil, glInfo);
                // create the surface
                surface?.Dispose();
                surface = SKSurface.Create(grContext, renderTarget, SURFACE_ORIGIN, COLOR_TYPE);
            }
            using (new SKAutoCanvasRestore(surface.Canvas, true))
            {
                RenderFrame?.Invoke(this, surface);
            }
            // update the control
            surface.Canvas.Flush();
            grContext.Flush();
        }
Example #13
0
        public void OnDrawFrame(IGL10 gl)
        {
            GLES10.GlClear(GLES10.GlColorBufferBit | GLES10.GlDepthBufferBit | GLES10.GlStencilBufferBit);

            // create the contexts if not done already
            if (context == null)
            {
                var glInterface = GRGlInterface.Create();
                context = GRContext.CreateGl(glInterface);
            }

            // manage the drawing surface
            if (renderTarget == null || lastSize != newSize || !renderTarget.IsValid)
            {
                // create or update the dimensions
                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);
                GLES20.GlGetIntegerv(GLES20.GlSamples, buffer, 2);
                var samples    = buffer[2];
                var maxSamples = context.GetMaxSurfaceSampleCount(colorType);
                if (samples > maxSamples)
                {
                    samples = maxSamples;
                }
                glInfo = new GRGlFramebufferInfo((uint)buffer[0], colorType.ToGlSizedFormat());

                // 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(canvas, true))
            {
                // start drawing
#pragma warning disable CS0618 // Type or member is obsolete
                var e = new SKPaintGLSurfaceEventArgs(surface, renderTarget, surfaceOrigin, colorType, glInfo);
                OnPaintSurface(e);
                OnDrawFrame(e.Surface, e.RenderTarget);
#pragma warning restore CS0618 // Type or member is obsolete
            }

            // flush the SkiaSharp contents to GL
            canvas.Flush();
            context.Flush();
        }
Example #14
0
        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.Create();
                context = GRContext.CreateGl(glInterface);
            }

            // manage the drawing surface
            var surfaceWidth  = (int)(Bounds.Width * ContentsScale);
            var surfaceHeight = (int)(Bounds.Height * ContentsScale);
            var newSize       = new SKSizeI(surfaceWidth, surfaceHeight);

            if (renderTarget == null || lastSize != newSize || !renderTarget.IsValid)
            {
                // create or update the dimensions
                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;
                }
                glInfo = new GRGlFramebufferInfo((uint)framebuffer, colorType.ToGlSizedFormat());

                // 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(canvas, true))
            {
                // start drawing
#pragma warning disable CS0618 // Type or member is obsolete
                var e = new SKPaintGLSurfaceEventArgs(surface, renderTarget, surfaceOrigin, colorType, glInfo);
                OnPaintSurface(e);
                DrawInSurface(e.Surface, e.RenderTarget);
                SKDelegate?.DrawInSurface(e.Surface, e.RenderTarget);
#pragma warning restore CS0618 // Type or member is obsolete
            }

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

            base.DrawInCGLContext(glContext, pixelFormat, timeInterval, ref timeStamp);
        }
Example #15
0
        protected void TkRender(TimeSpan delta)
        {
            if (designMode || disposed)
            {
                return;
            }

            if (this.Visibility != Visibility.Visible)
            {
                return;
            }

            var size = CreateSize();

            if (size.Width <= 0 || size.Height <= 0)
            {
                return;
            }

            // create the contexts if not done already
            if (grContext == null)
            {
                var glInterface = GRGlInterface.Create();
                grContext = GRContext.CreateGl(glInterface);
            }

            // get the new surface size
            var newSize = new SKSizeI(size.Width, size.Height);

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

                GL.GetInteger(GetPName.FramebufferBinding, out var framebuffer);
                GL.GetInteger(GetPName.StencilBits, out var stencil);
                GL.GetInteger(GetPName.Samples, out var samples);
                var maxSamples = grContext.GetMaxSurfaceSampleCount(colorType);
                if (samples > maxSamples)
                {
                    samples = maxSamples;
                }
                glInfo = new GRGlFramebufferInfo((uint)framebuffer, colorType.ToGlSizedFormat());

                // 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(grContext, renderTarget, surfaceOrigin, colorType);
                canvas  = surface.Canvas;
            }

            using (new SKAutoCanvasRestore(canvas, true))
            {
                // start drawing
                OnPaintSurface(new SKPaintGLSurfaceEventArgs(surface, renderTarget, surfaceOrigin, colorType, glInfo));
            }

            // update the control
            canvas.Flush();
        }
Example #16
0
        public void InterfaceConstructionWithoutContextDoesNotCrash()
        {
            var glInterface = GRGlInterface.Create();

            Assert.Null(glInterface);
        }
Example #17
0
        private void UnoGLDrawingArea_Render(object o, RenderArgs args)
        {
            args.Context.MakeCurrent();

            // create the contexts if not done already
            if (_grContext == null)
            {
                var glInterface = GRGlInterface.Create();
                _grContext = GRContext.CreateGl(glInterface);
            }

            // manage the drawing surface
            var res = (int)Math.Max(1.0, Screen.Resolution / 96.0);
            var w   = Math.Max(0, AllocatedWidth * res);
            var h   = Math.Max(0, AllocatedHeight * res);

            if (_renderTarget == null || _surface == null || _renderTarget.Width != w || _renderTarget.Height != h)
            {
                // create or update the dimensions
                _renderTarget?.Dispose();

                _gl.GetInteger(GLEnum.FramebufferBinding, out var framebuffer);
                _gl.GetInteger(GLEnum.Stencil, out var stencil);
                _gl.GetInteger(GLEnum.Samples, out var samples);
                var maxSamples = _grContext.GetMaxSurfaceSampleCount(colorType);

                if (samples > maxSamples)
                {
                    samples = maxSamples;
                }

                var glInfo = new GRGlFramebufferInfo((uint)framebuffer, colorType.ToGlSizedFormat());

                _renderTarget = new GRBackendRenderTarget(w + GuardBand, h + GuardBand, samples, stencil, glInfo);

                // create the surface
                _surface?.Dispose();
                _surface = SKSurface.Create(_grContext, _renderTarget, surfaceOrigin, colorType);

                if (this.Log().IsEnabled(LogLevel.Trace))
                {
                    this.Log().Trace($"Recreate render surface {w}x{h} colorType:{colorType} sample:{samples}");
                }
            }

            _gl.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.StencilBufferBit | ClearBufferMask.DepthBufferBit);
            _gl.ClearColor(1.0f, 1.0f, 1.0f, 1.0f);

            var canvas = _surface.Canvas;

            using (new SKAutoCanvasRestore(canvas, true))
            {
                canvas.Clear(SKColors.White);
                canvas.Translate(new SKPoint(0, GuardBand));

                WUX.Window.Current.Compositor.Render(_surface);
            }

            // update the control
            canvas.Flush();

            _gl.Flush();
        }
Example #18
0
        public new void DrawInRect(GLKView view, CGRect rect)
        {
            if (designMode)
            {
                return;
            }

            // create the contexts if not done already
            if (context == null)
            {
                var glInterface = GRGlInterface.Create();
                context = GRContext.CreateGl(glInterface);
            }

            // get the new surface size
            var newSize = new SKSizeI((int)DrawableWidth, (int)DrawableHeight);

            // manage the drawing surface
            if (renderTarget == null || lastSize != newSize || !renderTarget.IsValid)
            {
                // create or update the dimensions
                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;
                }
                glInfo = new GRGlFramebufferInfo((uint)framebuffer, colorType.ToGlSizedFormat());

                // 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(canvas, true))
            {
                // start drawing
                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);
#pragma warning restore CS0618 // Type or member is obsolete
            }

            // flush the SkiaSharp contents to GL
            canvas.Flush();
            context.Flush();
        }
Example #19
0
        protected override void OnPaint(PaintEventArgs e)
        {
            if (designMode)
            {
                e.Graphics.Clear(BackColor);
                return;
            }

            base.OnPaint(e);

            MakeCurrent();

            // create the contexts if not done already
            if (grContext == null)
            {
                var glInterface = GRGlInterface.Create();
                grContext = GRContext.CreateGl(glInterface);
            }

            // get the new surface size
            var newSize = new SKSizeI(Width, Height);

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

                GL.GetInteger(GetPName.FramebufferBinding, out var framebuffer);
                GL.GetInteger(GetPName.StencilBits, out var stencil);
                GL.GetInteger(GetPName.Samples, out var samples);
                var maxSamples = grContext.GetMaxSurfaceSampleCount(colorType);
                if (samples > maxSamples)
                {
                    samples = maxSamples;
                }
                glInfo = new GRGlFramebufferInfo((uint)framebuffer, colorType.ToGlSizedFormat());

                // 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(grContext, renderTarget, surfaceOrigin, colorType);
                canvas  = surface.Canvas;
            }

            using (new SKAutoCanvasRestore(canvas, true))
            {
                // start drawing
#pragma warning disable CS0612 // Type or member is obsolete
                OnPaintSurface(new SKPaintGLSurfaceEventArgs(surface, renderTarget, surfaceOrigin, colorType, glInfo));
#pragma warning restore CS0612 // Type or member is obsolete
            }

            // update the control
            canvas.Flush();
            SwapBuffers();
        }