Browse Source

[D2D1] Implement support for IFramebufferPlatformSurface

pull/1202/head
Nikita Tsukanov 8 years ago
parent
commit
3e09457e10
  1. 2
      src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs
  2. 84
      src/Windows/Avalonia.Direct2D1/FramebufferShimRenderTarget.cs
  3. 13
      src/Windows/Avalonia.Direct2D1/Media/Imaging/RenderTargetBitmapImpl.cs
  4. 1
      src/Windows/Avalonia.Direct2D1/Media/Imaging/WicBitmapImpl.cs
  5. 11
      tests/Avalonia.RenderTests/Media/BitmapTests.cs
  6. BIN
      tests/TestFiles/Direct2D1/Media/Bitmap/FramebufferRenderResultsShouldBeUsableAsBitmap_Bgra8888.expected.png
  7. BIN
      tests/TestFiles/Direct2D1/Media/Bitmap/FramebufferRenderResultsShouldBeUsableAsBitmap_Rgb565.expected.png
  8. BIN
      tests/TestFiles/Direct2D1/Media/Bitmap/FramebufferRenderResultsShouldBeUsableAsBitmap_Rgba8888.expected.png

2
src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs

@ -146,6 +146,8 @@ namespace Avalonia.Direct2D1
}
if (s is IExternalDirect2DRenderTargetSurface external)
return new ExternalRenderTarget(external, s_dwfactory);
if (s is IFramebufferPlatformSurface fb)
return new FramebufferShimRenderTarget(fb, s_imagingFactory, s_d2D1Factory, s_dwfactory);
}
throw new NotSupportedException("Don't know how to create a Direct2D1 renderer from any of provided surfaces");
}

84
src/Windows/Avalonia.Direct2D1/FramebufferShimRenderTarget.cs

@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.Text;
using Avalonia.Controls.Platform.Surfaces;
using Avalonia.Direct2D1.Media;
using Avalonia.Direct2D1.Media.Imaging;
using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Win32.Interop;
using SharpDX.Direct2D1;
using SharpDX.WIC;
using PixelFormat = Avalonia.Platform.PixelFormat;
namespace Avalonia.Direct2D1
{
class FramebufferShimRenderTarget : IRenderTarget
{
private readonly IFramebufferPlatformSurface _surface;
private readonly ImagingFactory _imagingFactory;
private readonly Factory _d2DFactory;
private readonly SharpDX.DirectWrite.Factory _dwriteFactory;
public FramebufferShimRenderTarget(IFramebufferPlatformSurface surface,
ImagingFactory imagingFactory, Factory d2dFactory, SharpDX.DirectWrite.Factory dwriteFactory)
{
_surface = surface;
_imagingFactory = imagingFactory;
_d2DFactory = d2dFactory;
_dwriteFactory = dwriteFactory;
}
public void Dispose()
{
}
public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer)
{
var locked = _surface.Lock();
if (locked.Format == PixelFormat.Rgb565)
{
locked.Dispose();
throw new ArgumentException("Unsupported pixel format: " + locked.Format);
}
return new FramebufferShim(locked, _imagingFactory, _d2DFactory, _dwriteFactory)
.CreateDrawingContext(visualBrushRenderer);
}
class FramebufferShim : RenderTargetBitmapImpl
{
private readonly ILockedFramebuffer _target;
public FramebufferShim(ILockedFramebuffer target,
ImagingFactory imagingFactory, Factory d2dFactory, SharpDX.DirectWrite.Factory dwriteFactory
) : base(imagingFactory, d2dFactory, dwriteFactory,
target.Width, target.Height, target.Dpi.X, target.Dpi.Y, target.Format)
{
_target = target;
}
public override IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer)
{
return base.CreateDrawingContext(visualBrushRenderer, () =>
{
using (var l = WicImpl.Lock(BitmapLockFlags.Read))
{
for (var y = 0; y < _target.Height; y++)
{
UnmanagedMethods.CopyMemory(
_target.Address + _target.RowBytes * y,
l.Data.DataPointer + l.Stride * y,
(uint) Math.Min(l.Stride, _target.RowBytes));
}
}
Dispose();
_target.Dispose();
});
}
}
}
}

13
src/Windows/Avalonia.Direct2D1/Media/Imaging/RenderTargetBitmapImpl.cs

@ -22,8 +22,9 @@ namespace Avalonia.Direct2D1.Media
int width,
int height,
double dpiX,
double dpiY)
: base(imagingFactory, width, height)
double dpiY,
Platform.PixelFormat? pixelFormat = null)
: base(imagingFactory, width, height, pixelFormat)
{
var props = new RenderTargetProperties
{
@ -45,9 +46,13 @@ namespace Avalonia.Direct2D1.Media
base.Dispose();
}
public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer)
public virtual IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer)
=> CreateDrawingContext(visualBrushRenderer, null);
public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer, Action finishedCallback)
{
return new DrawingContextImpl(visualBrushRenderer, _target, _dwriteFactory);
return new DrawingContextImpl(visualBrushRenderer, _target, _dwriteFactory,
finishedCallback: finishedCallback);
}
}
}

1
src/Windows/Avalonia.Direct2D1/Media/Imaging/WicBitmapImpl.cs

@ -74,6 +74,7 @@ namespace Avalonia.Direct2D1.Media
public WicBitmapImpl(ImagingFactory factory, Platform.PixelFormat format, IntPtr data, int width, int height, int stride)
{
WicImpl = new Bitmap(factory, width, height, format.ToWic(), BitmapCreateCacheOption.CacheOnDemand);
_factory = factory;
PixelFormat = format;
using (var l = WicImpl.Lock(BitmapLockFlags.Write))
{

11
tests/Avalonia.RenderTests/Media/BitmapTests.cs

@ -64,13 +64,13 @@ namespace Avalonia.Direct2D1.RenderTests.Media
public void Deallocate() => Marshal.FreeHGlobal(Address);
}
#if AVALONIA_SKIA
[Theory]
#else
[Theory(Skip = "Framebuffer not supported")]
[InlineData(PixelFormat.Rgba8888), InlineData(PixelFormat.Bgra8888),
#if SKIA
InlineData(PixelFormat.Rgb565)
#endif
[InlineData(PixelFormat.Rgba8888), InlineData(PixelFormat.Bgra8888), InlineData(PixelFormat.Rgb565)]
]
public void FramebufferRenderResultsShouldBeUsableAsBitmap(PixelFormat fmt)
{
var testName = nameof(FramebufferRenderResultsShouldBeUsableAsBitmap) + "_" + fmt;
@ -84,6 +84,7 @@ namespace Avalonia.Direct2D1.RenderTests.Media
ctx.FillRectangle(Brushes.Chartreuse, new Rect(0, 0, 20, 100));
ctx.FillRectangle(Brushes.Crimson, new Rect(20, 0, 20, 100));
ctx.FillRectangle(Brushes.Gold, new Rect(40, 0, 20, 100));
ctx.PopOpacity();
}
var bmp = new Bitmap(fmt, fb.Address, fb.Width, fb.Height, fb.RowBytes);

BIN
tests/TestFiles/Direct2D1/Media/Bitmap/FramebufferRenderResultsShouldBeUsableAsBitmap_Bgra8888.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 800 B

BIN
tests/TestFiles/Direct2D1/Media/Bitmap/FramebufferRenderResultsShouldBeUsableAsBitmap_Rgb565.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 786 B

BIN
tests/TestFiles/Direct2D1/Media/Bitmap/FramebufferRenderResultsShouldBeUsableAsBitmap_Rgba8888.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 800 B

Loading…
Cancel
Save