Browse Source

Implemented pixel format converter for framebuffer render target

pull/879/head
Nikita Tsukanov 9 years ago
parent
commit
9d64f9ddb0
  1. 7
      src/Skia/Avalonia.Skia/DrawingContextImpl.cs
  2. 72
      src/Skia/Avalonia.Skia/FramebufferRenderTarget.cs

7
src/Skia/Avalonia.Skia/DrawingContextImpl.cs

@ -10,12 +10,14 @@ namespace Avalonia.Skia
{ {
internal class DrawingContextImpl : IDrawingContextImpl internal class DrawingContextImpl : IDrawingContextImpl
{ {
private readonly IDisposable[] _disposables;
private Stack<PaintWrapper> maskStack = new Stack<PaintWrapper>(); private Stack<PaintWrapper> maskStack = new Stack<PaintWrapper>();
public SKCanvas Canvas { get; private set; } public SKCanvas Canvas { get; private set; }
public DrawingContextImpl(SKCanvas canvas) public DrawingContextImpl(SKCanvas canvas, params IDisposable[] disposables)
{ {
_disposables = disposables;
Canvas = canvas; Canvas = canvas;
Canvas.Clear(); Canvas.Clear();
} }
@ -314,6 +316,9 @@ namespace Avalonia.Skia
public virtual void Dispose() public virtual void Dispose()
{ {
if(_disposables!=null)
foreach (var disposable in _disposables)
disposable?.Dispose();
} }
public void PushGeometryClip(Geometry clip) public void PushGeometryClip(Geometry clip)

72
src/Skia/Avalonia.Skia/FramebufferRenderTarget.cs

@ -22,27 +22,6 @@ namespace Avalonia.Skia
//Nothing to do here, since we don't own framebuffer //Nothing to do here, since we don't own framebuffer
} }
class FramebufferDrawingContextImpl : DrawingContextImpl
{
private readonly SKCanvas _canvas;
private readonly SKSurface _surface;
private readonly ILockedFramebuffer _framebuffer;
public FramebufferDrawingContextImpl(SKCanvas canvas, SKSurface surface, ILockedFramebuffer framebuffer) : base(canvas)
{
_canvas = canvas;
_surface = surface;
_framebuffer = framebuffer;
}
public override void Dispose()
{
_canvas.Dispose();
_surface.Dispose();
_framebuffer.Dispose();
base.Dispose();
}
}
SKColorType TranslatePixelFormat(PixelFormat fmt) SKColorType TranslatePixelFormat(PixelFormat fmt)
{ {
@ -55,22 +34,63 @@ namespace Avalonia.Skia
throw new ArgumentException("Unknown pixel format: " + fmt); throw new ArgumentException("Unknown pixel format: " + fmt);
} }
class PixelFormatShim : IDisposable
{
private readonly SKImageInfo _nfo;
private readonly IntPtr _fb;
private readonly int _rowBytes;
private SKBitmap _bitmap;
public PixelFormatShim(SKImageInfo nfo, IntPtr fb, int rowBytes)
{
_nfo = nfo;
_fb = fb;
_rowBytes = rowBytes;
_bitmap = new SKBitmap(nfo.Width, nfo.Height);
if (!_bitmap.CanCopyTo(nfo.ColorType))
{
_bitmap.Dispose();
throw new Exception(
$"Unable to create pixel format shim for conversion from {_bitmap.ColorType} to {nfo.ColorType}");
}
}
public SKSurface CreateSurface() => SKSurface.Create(_bitmap.Info, _bitmap.GetPixels(), _bitmap.RowBytes);
public void Dispose()
{
using (var tmp = _bitmap.Copy(_nfo.ColorType))
tmp.CopyPixelsTo(_fb, _nfo.BytesPerPixel * _nfo.Height * _rowBytes, _rowBytes);
_bitmap.Dispose();
}
}
public DrawingContext CreateDrawingContext() public DrawingContext CreateDrawingContext()
{ {
var fb = _surface.Lock(); var fb = _surface.Lock();
PixelFormatShim shim = null;
SKImageInfo nfo = new SKImageInfo(fb.Width, fb.Height, TranslatePixelFormat(fb.Format), SKImageInfo framebuffer = new SKImageInfo(fb.Width, fb.Height, TranslatePixelFormat(fb.Format),
SKAlphaType.Opaque); SKAlphaType.Opaque);
var surface = SKSurface.Create(nfo, fb.Address, fb.RowBytes); var surface = SKSurface.Create(framebuffer, fb.Address, fb.RowBytes) ??
(shim = new PixelFormatShim(framebuffer, fb.Address, fb.RowBytes))
.CreateSurface();
if (surface == null) if (surface == null)
throw new Exception("Unable to create a surface for pixel format " + fb.Format); throw new Exception("Unable to create a surface for pixel format " + fb.Format +
" or pixel format translator");
var canvas = surface.Canvas; var canvas = surface.Canvas;
canvas.RestoreToCount(0); canvas.RestoreToCount(0);
canvas.Save(); canvas.Save();
canvas.Clear(SKColors.Red); canvas.Clear(SKColors.Red);
canvas.ResetMatrix(); canvas.ResetMatrix();
return new DrawingContext(new FramebufferDrawingContextImpl(canvas, surface, fb), return new DrawingContext(new DrawingContextImpl(canvas, canvas, surface, shim, fb),
Matrix.CreateScale(fb.Dpi.Width / 96, fb.Dpi.Height / 96)); Matrix.CreateScale(fb.Dpi.Width / 96, fb.Dpi.Height / 96));
} }
} }

Loading…
Cancel
Save