csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
118 lines
3.9 KiB
118 lines
3.9 KiB
using System;
|
|
using Avalonia;
|
|
using Avalonia.Logging;
|
|
using Avalonia.OpenGL;
|
|
using SkiaSharp;
|
|
using static Avalonia.OpenGL.GlConsts;
|
|
namespace ControlCatalog.Pages.OpenGl;
|
|
|
|
internal class OpenGlFbo : IDisposable
|
|
{
|
|
private readonly GRContext _grContext;
|
|
private int _fbo;
|
|
private int _depthBuffer;
|
|
private int _texture;
|
|
private PixelSize _size;
|
|
public PixelSize Size => _size;
|
|
public GlInterface Gl => Context.GlInterface;
|
|
public IGlContext Context { get; }
|
|
|
|
public OpenGlFbo(IGlContext context, GRContext grContext)
|
|
{
|
|
_grContext = grContext;
|
|
Context = context;
|
|
_fbo = Gl.GenFramebuffer();
|
|
}
|
|
|
|
public void Resize(PixelSize size)
|
|
{
|
|
if(_size == size)
|
|
return;
|
|
|
|
if (_texture != 0)
|
|
Gl.DeleteTexture(_texture);
|
|
_texture = 0;
|
|
if(_depthBuffer != 0)
|
|
Gl.DeleteRenderbuffer(_depthBuffer);
|
|
_depthBuffer = 0;
|
|
Gl.BindFramebuffer(GL_FRAMEBUFFER, _fbo);
|
|
|
|
_texture = Gl.GenTexture();
|
|
|
|
var textureFormat = Context.Version.Type == GlProfileType.OpenGLES && Context.Version.Major == 2
|
|
? GL_RGBA
|
|
: GL_RGBA8;
|
|
|
|
Gl.BindTexture(GL_TEXTURE_2D, _texture);
|
|
Gl.TexImage2D(GL_TEXTURE_2D, 0, textureFormat, size.Width, size.Height, 0, GL_RGBA,
|
|
GL_UNSIGNED_BYTE, IntPtr.Zero);
|
|
Gl.FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture, 0);
|
|
|
|
_depthBuffer = Gl.GenRenderbuffer();
|
|
var depthFormat = Context.Version.Type == GlProfileType.OpenGLES
|
|
? GL_DEPTH_COMPONENT16
|
|
: GL_DEPTH_COMPONENT;
|
|
Gl.BindRenderbuffer(GL_RENDERBUFFER, _depthBuffer);
|
|
Gl.RenderbufferStorage(GL_RENDERBUFFER, depthFormat, size.Width, size.Height);
|
|
Gl.FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthBuffer);
|
|
|
|
var status = Gl.CheckFramebufferStatus(GL_FRAMEBUFFER);
|
|
IsValid = (status == GL_FRAMEBUFFER_COMPLETE);
|
|
if(!IsValid)
|
|
{
|
|
int code = Gl.GetError();
|
|
Console.WriteLine("Unable to configure OpenGL FBO: " + code);
|
|
}
|
|
|
|
_size = size;
|
|
}
|
|
|
|
public bool IsValid { get; private set; }
|
|
|
|
public int Fbo => _fbo;
|
|
|
|
public SKImage? Snapshot()
|
|
{
|
|
Gl.Flush();
|
|
_grContext.ResetContext();
|
|
|
|
using var texture = new GRBackendTexture(_size.Width, _size.Height, false,
|
|
new GRGlTextureInfo(GlConsts.GL_TEXTURE_2D, (uint)_texture, SKColorType.Rgba8888.ToGlSizedFormat()));
|
|
|
|
var surf = SKSurface.Create(_grContext, texture, GRSurfaceOrigin.BottomLeft, SKColorType.Rgba8888);
|
|
if (surf == null)
|
|
{
|
|
using var unformatted = new GRBackendTexture(_size.Width, _size.Height, false,
|
|
new GRGlTextureInfo(GlConsts.GL_TEXTURE_2D, (uint)_texture));
|
|
|
|
surf = SKSurface.Create(_grContext, unformatted, GRSurfaceOrigin.BottomLeft, SKColorType.Rgba8888);
|
|
}
|
|
|
|
SKImage? rv;
|
|
using (surf)
|
|
rv = surf?.Snapshot();
|
|
_grContext.Flush();
|
|
return rv;
|
|
/*
|
|
var target = new GRBackendRenderTarget(_size.Width, _size.Height, 0, 0,
|
|
new GRGlFramebufferInfo((uint)_fbo, SKColorType.Rgba8888.ToGlSizedFormat()));
|
|
SKImage rv;
|
|
using (var surface = SKSurface.Create(_grContext, target,
|
|
GRSurfaceOrigin.BottomLeft, SKColorType.Rgba8888,
|
|
new SKSurfaceProperties(SKPixelGeometry.RgbHorizontal)))
|
|
rv = surface.Snapshot();
|
|
_grContext.Flush();
|
|
return rv;*/
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if(_fbo != 0)
|
|
Gl.DeleteFramebuffer(_fbo);
|
|
_fbo = 0;
|
|
if (_depthBuffer != 0)
|
|
Gl.DeleteRenderbuffer(_depthBuffer);
|
|
if(_texture != 0)
|
|
Gl.DeleteTexture(_texture);
|
|
}
|
|
}
|