3 changed files with 76 additions and 47 deletions
@ -1,46 +0,0 @@ |
|||
using System; |
|||
using System.Runtime.InteropServices; |
|||
using Avalonia.Platform; |
|||
|
|||
namespace Avalonia.LinuxFramebuffer |
|||
{ |
|||
unsafe class LockedFramebuffer : ILockedFramebuffer |
|||
{ |
|||
private readonly int _fb; |
|||
private readonly fb_fix_screeninfo _fixedInfo; |
|||
private fb_var_screeninfo _varInfo; |
|||
private readonly IntPtr _address; |
|||
|
|||
public LockedFramebuffer(int fb, fb_fix_screeninfo fixedInfo, fb_var_screeninfo varInfo, IntPtr address, Vector dpi) |
|||
{ |
|||
_fb = fb; |
|||
_fixedInfo = fixedInfo; |
|||
_varInfo = varInfo; |
|||
_address = address; |
|||
Dpi = dpi; |
|||
//Use double buffering to avoid flicker
|
|||
Address = Marshal.AllocHGlobal(RowBytes * Size.Height); |
|||
} |
|||
|
|||
|
|||
void VSync() |
|||
{ |
|||
NativeUnsafeMethods.ioctl(_fb, FbIoCtl.FBIO_WAITFORVSYNC, null); |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
VSync(); |
|||
NativeUnsafeMethods.memcpy(_address, Address, new IntPtr(RowBytes * Size.Height)); |
|||
|
|||
Marshal.FreeHGlobal(Address); |
|||
Address = IntPtr.Zero; |
|||
} |
|||
|
|||
public IntPtr Address { get; private set; } |
|||
public PixelSize Size => new PixelSize((int)_varInfo.xres, (int) _varInfo.yres); |
|||
public int RowBytes => (int) _fixedInfo.line_length; |
|||
public Vector Dpi { get; } |
|||
public PixelFormat Format => _varInfo.bits_per_pixel == 16 ? PixelFormat.Rgb565 : _varInfo.blue.offset == 16 ? PixelFormat.Rgba8888 : PixelFormat.Bgra8888; |
|||
} |
|||
} |
|||
@ -0,0 +1,70 @@ |
|||
using System; |
|||
using System.Runtime.InteropServices; |
|||
using System.Threading; |
|||
using Avalonia.Platform; |
|||
|
|||
namespace Avalonia.LinuxFramebuffer.Output |
|||
{ |
|||
internal unsafe class FbDevBackBuffer : IDisposable |
|||
{ |
|||
private readonly int _fb; |
|||
private readonly fb_fix_screeninfo _fixedInfo; |
|||
private readonly fb_var_screeninfo _varInfo; |
|||
private readonly IntPtr _targetAddress; |
|||
private readonly object _lock = new object(); |
|||
|
|||
public FbDevBackBuffer(int fb, fb_fix_screeninfo fixedInfo, fb_var_screeninfo varInfo, IntPtr targetAddress) |
|||
{ |
|||
_fb = fb; |
|||
_fixedInfo = fixedInfo; |
|||
_varInfo = varInfo; |
|||
_targetAddress = targetAddress; |
|||
Address = Marshal.AllocHGlobal(RowBytes * Size.Height); |
|||
} |
|||
|
|||
|
|||
public void Dispose() |
|||
{ |
|||
if (Address != IntPtr.Zero) |
|||
{ |
|||
Marshal.FreeHGlobal(Address); |
|||
Address = IntPtr.Zero; |
|||
} |
|||
} |
|||
|
|||
public ILockedFramebuffer Lock(Vector dpi) |
|||
{ |
|||
Monitor.Enter(_lock); |
|||
try |
|||
{ |
|||
return new LockedFramebuffer(Address, |
|||
new PixelSize((int)_varInfo.xres, (int)_varInfo.yres), |
|||
(int)_fixedInfo.line_length, dpi, |
|||
_varInfo.bits_per_pixel == 16 ? PixelFormat.Rgb565 |
|||
: _varInfo.blue.offset == 16 ? PixelFormat.Rgba8888 |
|||
: PixelFormat.Bgra8888, |
|||
() => |
|||
{ |
|||
try |
|||
{ |
|||
NativeUnsafeMethods.ioctl(_fb, FbIoCtl.FBIO_WAITFORVSYNC, null); |
|||
NativeUnsafeMethods.memcpy(_targetAddress, Address, new IntPtr(RowBytes * Size.Height)); |
|||
} |
|||
finally |
|||
{ |
|||
Monitor.Exit(_lock); |
|||
} |
|||
}); |
|||
} |
|||
catch |
|||
{ |
|||
Monitor.Exit(_lock); |
|||
throw; |
|||
} |
|||
} |
|||
|
|||
public IntPtr Address { get; private set; } |
|||
public PixelSize Size => new PixelSize((int)_varInfo.xres, (int) _varInfo.yres); |
|||
public int RowBytes => (int) _fixedInfo.line_length; |
|||
} |
|||
} |
|||
Loading…
Reference in new issue