Browse Source

Merge pull request #879 from AvaloniaUI/pixel-format-shim

Implemented pixel format converter for framebuffer render target
pull/880/head
Nikita Tsukanov 9 years ago
committed by GitHub
parent
commit
cf1c4102c8
  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
{
private readonly IDisposable[] _disposables;
private Stack<PaintWrapper> maskStack = new Stack<PaintWrapper>();
public SKCanvas Canvas { get; private set; }
public DrawingContextImpl(SKCanvas canvas)
public DrawingContextImpl(SKCanvas canvas, params IDisposable[] disposables)
{
_disposables = disposables;
Canvas = canvas;
Canvas.Clear();
}
@ -314,6 +316,9 @@ namespace Avalonia.Skia
public virtual void Dispose()
{
if(_disposables!=null)
foreach (var disposable in _disposables)
disposable?.Dispose();
}
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
}
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)
{
@ -55,22 +34,63 @@ namespace Avalonia.Skia
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()
{
var fb = _surface.Lock();
SKImageInfo nfo = new SKImageInfo(fb.Width, fb.Height, TranslatePixelFormat(fb.Format),
PixelFormatShim shim = null;
SKImageInfo framebuffer = new SKImageInfo(fb.Width, fb.Height, TranslatePixelFormat(fb.Format),
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)
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;
canvas.RestoreToCount(0);
canvas.Save();
canvas.Clear(SKColors.Red);
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));
}
}

Loading…
Cancel
Save