0

I'm doing off-screen rendering using SkiaSharp in .NET 5 (better cross-platform), and GPU acceleration is required. Note: C++ version of Skia is also acceptable if it works.

The development is on Windows. I'm not using SkiaSharp.View since the program is a command-line tool. I just created a hidden window. The window is created using OpenTk since I saw Matthew's examples on GitHub, and I made the window's context the default context. Then, I created a framebuffer and renderbuffer as described in this SO solution. Finally, I attempted to create the surface, yet only got a null from SKSurface.Create.

// GL below is all OpenTK.Graphics.ES30.GL!
var window = new GameWindow(
    GameWindowSettings.Default,
    new NativeWindowSettings { 
        Size = new Vector2i(1, 1),
        StartVisible = false, 
        Flags = OpenTK.Windowing.Common.ContextFlags.Offscreen, 
        APIVersion = new Version(3, 2) });
window.Context.MakeCurrent();

var gpuInterface = GRGlInterface.Create(); // Q: Is this interface correctly linked to the one OpenTk uses?
var grContext = GRContext.CreateGl(gpuInterface);

uint fbo = (uint)GL.GenFramebuffer();
uint rbo = (uint)GL.GenRenderbuffer();
GL.BindRenderbuffer(OpenTK.Graphics.ES30.RenderbufferTarget.Renderbuffer, rbo);
GL.RenderbufferStorage(OpenTK.Graphics.ES30.RenderbufferTarget.Renderbuffer, OpenTK.Graphics.ES30.RenderbufferInternalFormat.Rgba8, 800, 700);
GL.BindFramebuffer(OpenTK.Graphics.ES30.FramebufferTarget.DrawFramebuffer, fbo);
GL.FramebufferRenderbuffer(
    OpenTK.Graphics.ES30.FramebufferTarget.DrawFramebuffer, 
    OpenTK.Graphics.ES30.FramebufferAttachment.ColorAttachment0,
    OpenTK.Graphics.ES30.RenderbufferTarget.Renderbuffer, 
    rbo);

var sampleCounts = GL.GetInteger(OpenTK.Graphics.ES30.GetPName.Samples);
int stencilBits;
GL.GetFramebufferAttachmentParameter(
    OpenTK.Graphics.ES30.FramebufferTarget.DrawFramebuffer, 
    OpenTK.Graphics.ES30.FramebufferAttachment.ColorAttachment0, 
    OpenTK.Graphics.ES30.FramebufferParameterName.FramebufferAttachmentStencilSize, 
    out stencilBits);
var target = new GRBackendRenderTarget(800, 700, sampleCounts, stencilBits, new GRGlFramebufferInfo(fbo, SKColorType.Bgra8888.ToGlSizedFormat()));
var surface = SKSurface.Create(grContext, target, GRSurfaceOrigin.TopLeft, SKColorType.Bgra8888);
// surface == null ?

Also, no error is given using GL.GetError.

Any help would be appreciated.

Charlie Jiang
  • 31
  • 1
  • 8
  • you do window.Context.MakeCurrent();then later on you create the context again: var grContext = GRContext.CreateGl(gpuInterface); . I am not very familiar with Skia API but make sure first you have the last created context valid and current. have you checked your FBO handles too? – Michael IV Jun 18 '21 at 16:17
  • Michael GRContext.createGl() only creates a link for Skia to OpenGL API, and skia's OpenGL support is designed to have an OpenGL context created before the creation of GrContext. – Charlie Jiang Jun 19 '21 at 06:21

1 Answers1

1

OK I finally got it to work.

The point is the mismatch of the pixel format between SkSurface's GRBackendRenderTarget and the RBO. I don't know why OpenTk.Graphics.ES30.RenderbufferInternalFormat don't contains 'Bgra8888'. Therefore the SKColorType.Bgra8888 later caused the problem.

Due to the absence of BGRA in the RenderbufferInternalFormat enum, I had to switch the whole thing to RGBA, so the last lines are changed to:

var target = new GRBackendRenderTarget(800, 700, 0, 0, new GRGlFramebufferInfo(0, SKColorType.Rgba8888.ToGlSizedFormat()));
var surface = SKSurface.Create(grContext, target, GRSurfaceOrigin.TopLeft, SKColorType.Rgba8888);

And it works.

But I wonder how to switch to Bgra when creating the RBO storage.

Charlie Jiang
  • 31
  • 1
  • 8