예제 #1
0
        public GlSkiaGpu(IPlatformOpenGlInterface openGl, long?maxResourceBytes)
        {
            var context = openGl.PrimaryContext;

            _glContext = context;
            using (context.MakeCurrent())
            {
                using (var iface = context.Version.Type == GlProfileType.OpenGL ?
                                   GRGlInterface.CreateOpenGl(proc => context.GlInterface.GetProcAddress(proc)) :
                                   GRGlInterface.CreateGles(proc => context.GlInterface.GetProcAddress(proc)))
                {
                    _grContext = GRContext.CreateGl(iface, new GRContextOptions {
                        AvoidStencilBuffers = true
                    });
                    if (maxResourceBytes.HasValue)
                    {
                        _grContext.SetResourceCacheLimit(maxResourceBytes.Value);
                    }
                }
            }
        }
예제 #2
0
        private void DrawGpuTextureWithOldDesc(Action <SKSurface, GRBackendTextureDesc> draw)
        {
            using (var ctx = CreateGlContext())
            {
                ctx.MakeCurrent();

                // create the texture
                var textureInfo = ctx.CreateTexture(new SKSizeI(100, 100));

                var oldInfo = new GRTextureInfoOld
                {
                    Id     = textureInfo.Id,
                    Target = textureInfo.Target
                };
                var textureHandle = GCHandle.Alloc(oldInfo, GCHandleType.Pinned);
                var textureDesc   = new GRBackendTextureDesc
                {
                    Width         = 100,
                    Height        = 100,
                    Config        = GRPixelConfig.Rgba8888,
                    Flags         = GRBackendTextureDescFlags.RenderTarget,
                    Origin        = GRSurfaceOrigin.BottomLeft,
                    SampleCount   = 0,
                    TextureHandle = textureHandle.AddrOfPinnedObject(),
                };

                // create the surface
                using (var grContext = GRContext.CreateGl())
                    using (var surface = SKSurface.CreateAsRenderTarget(grContext, textureDesc))
                    {
                        Assert.NotNull(surface);

                        draw(surface, textureDesc);
                    }

                // clean up
                textureHandle.Free();
                ctx.DestroyTexture(textureInfo.Id);
            }
        }
예제 #3
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();
        }
예제 #4
0
        public void CanvasCanRestoreOnGpu()
        {
            using (var ctx = CreateGlContext())
            {
                ctx.MakeCurrent();

                using (var grContext = GRContext.CreateGl())
                    using (var surface = SKSurface.Create(grContext, true, new SKImageInfo(100, 100)))
                    {
                        var canvas = surface.Canvas;

                        Assert.Equal(SKMatrix.Identity, canvas.TotalMatrix);

                        using (new SKAutoCanvasRestore(canvas))
                        {
                            canvas.Translate(10, 10);
                            Assert.Equal(SKMatrix.CreateTranslation(10, 10), canvas.TotalMatrix);
                        }

                        Assert.Equal(SKMatrix.Identity, canvas.TotalMatrix);
                    }
            }
        }
예제 #5
0
        private void DrawGpuTexture(Action <SKSurface, GRBackendTexture> draw)
        {
            using (var ctx = CreateGlContext())
            {
                ctx.MakeCurrent();

                // create the texture
                var textureInfo = ctx.CreateTexture(new SKSizeI(100, 100));
                var texture     = new GRBackendTexture(100, 100, false, textureInfo);

                // create the surface
                using (var grContext = GRContext.CreateGl())
                    using (var surface = SKSurface.CreateAsRenderTarget(grContext, texture, SKColorType.Rgba8888))
                    {
                        Assert.NotNull(surface);

                        draw(surface, texture);
                    }

                // clean up
                ctx.DestroyTexture(textureInfo.Id);
            }
        }
예제 #6
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();
        }
예제 #7
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();
        }
예제 #8
0
        public void ImageCanClearBackground(float threshold, float exponent, uint backgroundColor, uint shirtColor)
        {
            using var ctx = CreateGlContext();
            ctx.MakeCurrent();
            using var grContext = GRContext.CreateGl();

            var info = new SKImageInfo(500, 500, SKColorType.Rgba8888);

            using var surface = SKSurface.Create(grContext, false, info);
            var canvas = surface.Canvas;

            canvas.Clear(SKColors.Black);

            using var blueShirt     = SKImage.FromEncodedData(Path.Combine(PathToImages, "blue-shirt.jpg"));
            using var textureShader = blueShirt.ToShader();

            var src = @"
uniform shader color_map;
uniform float scale;
uniform half exp;
uniform float3 in_colors0;
half4 main(float2 p) {
    half4 texColor = sample(color_map, p);
    if (length(abs(in_colors0 - pow(texColor.rgb, half3(exp)))) < scale)
        discard;
    return texColor;
}";

            using var effect = SKRuntimeEffect.Create(src, out var errorText);
            Assert.Null(errorText);
            Assert.NotNull(effect);

            var uniformSize = effect.UniformSize;

            Assert.Equal(5 * sizeof(float), uniformSize);

            var uniforms = new SKRuntimeEffectUniforms(effect)
            {
                ["scale"]      = threshold,
                ["exp"]        = exponent,
                ["in_colors0"] = new[] { 1f, 1f, 1f },
            };

            var children = new SKRuntimeEffectChildren(effect)
            {
                ["color_map"] = textureShader
            };

            using var shader = effect.ToShader(true, uniforms, children);

            using var paint = new SKPaint { Shader = shader };
            canvas.DrawRect(SKRect.Create(400, 400), paint);

            var actual = new SKColor[500 * 500];

            fixed(void *a = actual)
            Assert.True(surface.ReadPixels(info, (IntPtr)a, info.RowBytes, 0, 0));

            Assert.Equal(backgroundColor, actual[100 * info.Width + 100]);
            Assert.Equal(shirtColor, actual[230 * info.Width + 300]);
        }
예제 #9
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();
        }