Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compile Skia with Direct3D on Windows platform #2823

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
15 changes: 15 additions & 0 deletions binding/SkiaSharp/GRBackendRenderTarget.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ public GRBackendRenderTarget (int width, int height, int sampleCount, GRVkImageI
CreateVulkan (width, height, sampleCount, vkImageInfo);
}

public GRBackendRenderTarget (int width, int height, GRD3dTextureinfo d3dTextureInfo)
: this (IntPtr.Zero, true)
{
CreateDirect3D (width, height, d3dTextureInfo);
}

#if __IOS__ || __MACOS__

public GRBackendRenderTarget (int width, int height, int sampleCount, GRMtlTextureInfo mtlInfo)
Expand Down Expand Up @@ -57,6 +63,15 @@ private void CreateVulkan (int width, int height, int sampleCount, GRVkImageInfo
}
}

private void CreateDirect3D (int width, int height, GRD3dTextureinfo d3dTextureInfo)
{
Handle = SkiaApi.gr_backendrendertarget_new_direct3d (width, height, &d3dTextureInfo);

if (Handle == IntPtr.Zero) {
throw new InvalidOperationException ("Unable to create a new GRBackendRenderTarget instance.");
}
}

protected override void Dispose (bool disposing) =>
base.Dispose (disposing);

Expand Down
15 changes: 15 additions & 0 deletions binding/SkiaSharp/GRBackendTexture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ public GRBackendTexture (int width, int height, GRVkImageInfo vkInfo)
CreateVulkan (width, height, vkInfo);
}

public GRBackendTexture (int width, int height, GRD3dTextureinfo d3dTextureInfo)
: this (IntPtr.Zero, true)
{
CreateDirect3D (width, height, d3dTextureInfo);
}

public GRBackendTexture (int width, int height, bool mipmapped, GRMtlTextureInfo mtlInfo)
: this (IntPtr.Zero, true)
{
Expand Down Expand Up @@ -54,6 +60,15 @@ private void CreateVulkan (int width, int height, GRVkImageInfo vkInfo)
}
}

private void CreateDirect3D (int width, int height, GRD3dTextureinfo d3dTextureInfo)
{
Handle = SkiaApi.gr_backendtexture_new_direct3d (width, height, &d3dTextureInfo);

if (Handle == IntPtr.Zero) {
throw new InvalidOperationException ("Unable to create a new GRBackendTexture instance.");
}
}

protected override void Dispose (bool disposing) =>
base.Dispose (disposing);

Expand Down
12 changes: 12 additions & 0 deletions binding/SkiaSharp/GRContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,18 @@ public static GRContext CreateVulkan (GRVkBackendContext backendContext, GRConte
}
}

public static GRContext CreateDirect3D (GRD3dBackendcontext backendContext, GRContextOptions options)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hate myself so much... But this may need to be 3d with a lowercase d for consistency. So yuck to look at and I have no idea what I was thinking at the time. Sorry universe.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw that every Direct3D library use uppercase D, so I'm doing same with that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, but sadly if you look at my OpenGl members I must have lost my mind. Everywhere it is uppercase-G-lowercase-l 😭

{
if (backendContext == null)
throw new ArgumentNullException (nameof (backendContext));
if (options == null) {
return GetObject (SkiaApi.gr_direct_context_make_direct3d (backendContext));
} else {
var opts = options.ToNative ();
return GetObject (SkiaApi.gr_direct_context_make_direct3d_with_options (backendContext, &opts));
}
}

// CreateMetal

public static GRContext CreateMetal (GRMtlBackendContext backendContext) =>
Expand Down
214 changes: 213 additions & 1 deletion binding/SkiaSharp/SkiaApi.generated.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Runtime.InteropServices;

#region Namespaces
Expand All @@ -8,6 +8,12 @@

#region Class declarations

using d3d_alloc_t = System.IntPtr;
using d3d_d12_command_queue_t = System.IntPtr;
using d3d_d12_device_t = System.IntPtr;
using d3d_d12_resource_t = System.IntPtr;
using d3d_dxgi_adapter_t = System.IntPtr;
using d3d_memory_allocator_t = System.IntPtr;
using gr_backendrendertarget_t = System.IntPtr;
using gr_backendtexture_t = System.IntPtr;
using gr_direct_context_t = System.IntPtr;
Expand Down Expand Up @@ -222,6 +228,20 @@ internal static bool gr_backendrendertarget_is_valid (gr_backendrendertarget_t r
(gr_backendrendertarget_is_valid_delegate ??= GetSymbol<Delegates.gr_backendrendertarget_is_valid> ("gr_backendrendertarget_is_valid")).Invoke (rendertarget);
#endif

// gr_backendrendertarget_t* gr_backendrendertarget_new_direct3d(int width, int height, const gr_d3d_textureinfo_t* d3dInfo)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
internal static extern gr_backendrendertarget_t gr_backendrendertarget_new_direct3d (Int32 width, Int32 height, GRD3dTextureinfo* d3dInfo);
#else
private partial class Delegates {
[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
internal delegate gr_backendrendertarget_t gr_backendrendertarget_new_direct3d (Int32 width, Int32 height, GRD3dTextureinfo* d3dInfo);
}
private static Delegates.gr_backendrendertarget_new_direct3d gr_backendrendertarget_new_direct3d_delegate;
internal static gr_backendrendertarget_t gr_backendrendertarget_new_direct3d (Int32 width, Int32 height, GRD3dTextureinfo* d3dInfo) =>
(gr_backendrendertarget_new_direct3d_delegate ??= GetSymbol<Delegates.gr_backendrendertarget_new_direct3d> ("gr_backendrendertarget_new_direct3d")).Invoke (width, height, d3dInfo);
#endif

// gr_backendrendertarget_t* gr_backendrendertarget_new_gl(int width, int height, int samples, int stencils, const gr_gl_framebufferinfo_t* glInfo)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
Expand Down Expand Up @@ -368,6 +388,20 @@ internal static bool gr_backendtexture_is_valid (gr_backendtexture_t texture) =>
(gr_backendtexture_is_valid_delegate ??= GetSymbol<Delegates.gr_backendtexture_is_valid> ("gr_backendtexture_is_valid")).Invoke (texture);
#endif

// gr_backendtexture_t* gr_backendtexture_new_direct3d(int width, int height, const gr_d3d_textureinfo_t* d3dInfo)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
internal static extern gr_backendtexture_t gr_backendtexture_new_direct3d (Int32 width, Int32 height, GRD3dTextureinfo* d3dInfo);
#else
private partial class Delegates {
[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
internal delegate gr_backendtexture_t gr_backendtexture_new_direct3d (Int32 width, Int32 height, GRD3dTextureinfo* d3dInfo);
}
private static Delegates.gr_backendtexture_new_direct3d gr_backendtexture_new_direct3d_delegate;
internal static gr_backendtexture_t gr_backendtexture_new_direct3d (Int32 width, Int32 height, GRD3dTextureinfo* d3dInfo) =>
(gr_backendtexture_new_direct3d_delegate ??= GetSymbol<Delegates.gr_backendtexture_new_direct3d> ("gr_backendtexture_new_direct3d")).Invoke (width, height, d3dInfo);
#endif

// gr_backendtexture_t* gr_backendtexture_new_gl(int width, int height, bool mipmapped, const gr_gl_textureinfo_t* glInfo)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
Expand Down Expand Up @@ -524,6 +558,34 @@ internal static bool gr_direct_context_is_abandoned (gr_direct_context_t context
(gr_direct_context_is_abandoned_delegate ??= GetSymbol<Delegates.gr_direct_context_is_abandoned> ("gr_direct_context_is_abandoned")).Invoke (context);
#endif

// gr_direct_context_t* gr_direct_context_make_direct3d(const gr_d3d_backendcontext_t d3dBackendContext)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
internal static extern gr_direct_context_t gr_direct_context_make_direct3d (GRD3dBackendcontext d3dBackendContext);
#else
private partial class Delegates {
[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
internal delegate gr_direct_context_t gr_direct_context_make_direct3d (GRD3dBackendcontext d3dBackendContext);
}
private static Delegates.gr_direct_context_make_direct3d gr_direct_context_make_direct3d_delegate;
internal static gr_direct_context_t gr_direct_context_make_direct3d (GRD3dBackendcontext d3dBackendContext) =>
(gr_direct_context_make_direct3d_delegate ??= GetSymbol<Delegates.gr_direct_context_make_direct3d> ("gr_direct_context_make_direct3d")).Invoke (d3dBackendContext);
#endif

// gr_direct_context_t* gr_direct_context_make_direct3d_with_options(const gr_d3d_backendcontext_t d3dBackendContext, const gr_context_options_t* options)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
internal static extern gr_direct_context_t gr_direct_context_make_direct3d_with_options (GRD3dBackendcontext d3dBackendContext, GRContextOptionsNative* options);
#else
private partial class Delegates {
[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
internal delegate gr_direct_context_t gr_direct_context_make_direct3d_with_options (GRD3dBackendcontext d3dBackendContext, GRContextOptionsNative* options);
}
private static Delegates.gr_direct_context_make_direct3d_with_options gr_direct_context_make_direct3d_with_options_delegate;
internal static gr_direct_context_t gr_direct_context_make_direct3d_with_options (GRD3dBackendcontext d3dBackendContext, GRContextOptionsNative* options) =>
(gr_direct_context_make_direct3d_with_options_delegate ??= GetSymbol<Delegates.gr_direct_context_make_direct3d_with_options> ("gr_direct_context_make_direct3d_with_options")).Invoke (d3dBackendContext, options);
#endif

// gr_direct_context_t* gr_direct_context_make_gl(const gr_glinterface_t* glInterface)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
Expand Down Expand Up @@ -12638,6 +12700,156 @@ public readonly override int GetHashCode ()

}

// gr_d3d_backendcontext_t
[StructLayout (LayoutKind.Sequential)]
public unsafe partial struct GRD3dBackendcontext : IEquatable<GRD3dBackendcontext> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note about the names of the 2 new types - the info and context need to start with an uppercase letter. I added a comment on how to do this in the json mapper file here: mono/skia#121 (review)

// public d3d_dxgi_adapter_t* fAdapter
private d3d_dxgi_adapter_t fAdapter;
public d3d_dxgi_adapter_t Adapter {
readonly get => fAdapter;
set => fAdapter = value;
}

// public d3d_d12_device_t* fDevice
private d3d_d12_device_t fDevice;
public d3d_d12_device_t Device {
readonly get => fDevice;
set => fDevice = value;
}

// public d3d_d12_command_queue_t* fQueue
private d3d_d12_command_queue_t fQueue;
public d3d_d12_command_queue_t Queue {
readonly get => fQueue;
set => fQueue = value;
}

// public d3d_memory_allocator_t* fMemoryAllocator
private d3d_memory_allocator_t fMemoryAllocator;
public d3d_memory_allocator_t MemoryAllocator {
readonly get => fMemoryAllocator;
set => fMemoryAllocator = value;
}

// public bool fProtectedContext
private Byte fProtectedContext;
public bool ProtectedContext {
readonly get => fProtectedContext > 0;
set => fProtectedContext = value ? (byte)1 : (byte)0;
}

public readonly bool Equals (GRD3dBackendcontext obj) =>
fAdapter == obj.fAdapter && fDevice == obj.fDevice && fQueue == obj.fQueue && fMemoryAllocator == obj.fMemoryAllocator && fProtectedContext == obj.fProtectedContext;

public readonly override bool Equals (object obj) =>
obj is GRD3dBackendcontext f && Equals (f);

public static bool operator == (GRD3dBackendcontext left, GRD3dBackendcontext right) =>
left.Equals (right);

public static bool operator != (GRD3dBackendcontext left, GRD3dBackendcontext right) =>
!left.Equals (right);

public readonly override int GetHashCode ()
{
var hash = new HashCode ();
hash.Add (fAdapter);
hash.Add (fDevice);
hash.Add (fQueue);
hash.Add (fMemoryAllocator);
hash.Add (fProtectedContext);
return hash.ToHashCode ();
}

}

// gr_d3d_textureinfo_t
[StructLayout (LayoutKind.Sequential)]
public unsafe partial struct GRD3dTextureinfo : IEquatable<GRD3dTextureinfo> {
// public d3d_d12_resource_t* fResource
private d3d_d12_resource_t fResource;
public d3d_d12_resource_t Resource {
readonly get => fResource;
set => fResource = value;
}

// public d3d_alloc_t* fAlloc
private d3d_alloc_t fAlloc;
public d3d_alloc_t Alloc {
readonly get => fAlloc;
set => fAlloc = value;
}

// public uint32_t fResourceState
private UInt32 fResourceState;
public UInt32 ResourceState {
readonly get => fResourceState;
set => fResourceState = value;
}

// public uint32_t fFormat
private UInt32 fFormat;
public UInt32 Format {
readonly get => fFormat;
set => fFormat = value;
}

// public uint32_t fSampleCount
private UInt32 fSampleCount;
public UInt32 SampleCount {
readonly get => fSampleCount;
set => fSampleCount = value;
}

// public uint32_t fLevelCount
private UInt32 fLevelCount;
public UInt32 LevelCount {
readonly get => fLevelCount;
set => fLevelCount = value;
}

// public unsigned int fSampleQualityPattern
private UInt32 fSampleQualityPattern;
public UInt32 SampleQualityPattern {
readonly get => fSampleQualityPattern;
set => fSampleQualityPattern = value;
}

// public bool fProtected
private Byte fProtected;
public bool Protected {
readonly get => fProtected > 0;
set => fProtected = value ? (byte)1 : (byte)0;
}

public readonly bool Equals (GRD3dTextureinfo obj) =>
fResource == obj.fResource && fAlloc == obj.fAlloc && fResourceState == obj.fResourceState && fFormat == obj.fFormat && fSampleCount == obj.fSampleCount && fLevelCount == obj.fLevelCount && fSampleQualityPattern == obj.fSampleQualityPattern && fProtected == obj.fProtected;

public readonly override bool Equals (object obj) =>
obj is GRD3dTextureinfo f && Equals (f);

public static bool operator == (GRD3dTextureinfo left, GRD3dTextureinfo right) =>
left.Equals (right);

public static bool operator != (GRD3dTextureinfo left, GRD3dTextureinfo right) =>
!left.Equals (right);

public readonly override int GetHashCode ()
{
var hash = new HashCode ();
hash.Add (fResource);
hash.Add (fAlloc);
hash.Add (fResourceState);
hash.Add (fFormat);
hash.Add (fSampleCount);
hash.Add (fLevelCount);
hash.Add (fSampleQualityPattern);
hash.Add (fProtected);
return hash.ToHashCode ();
}

}

// gr_gl_framebufferinfo_t
[StructLayout (LayoutKind.Sequential)]
public unsafe partial struct GRGlFramebufferInfo : IEquatable<GRGlFramebufferInfo> {
Expand Down
1 change: 1 addition & 0 deletions native/windows/build.cake
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ Task("libSkiaSharp")
$"skia_use_system_zlib=false " +
$"skia_enable_skottie=true " +
$"skia_use_vulkan={SUPPORT_VULKAN} ".ToLower () +
$"skia_use_direct3d=true " +
clang +
win_vcvars_version +
$"extra_cflags=[ '-DSKIA_C_DLL', '/MT{d}', '/EHsc', '/Z7', '-D_HAS_AUTO_PTR_ETC=1' ] " +
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Vortice.Direct3D12;
using Vortice.DXGI;

namespace SkiaSharp
{
public class GRDirect3DBackendContext
{
public IDXGIAdapter1 Adapter { get; set; }

public ID3D12Device2 Device { get; set; }

public ID3D12CommandQueue Queue { get; set; }

public bool ProtectedContext { get; set; }

public static implicit operator GRD3dBackendcontext(GRDirect3DBackendContext context)
{
return new GRD3dBackendcontext
{
Adapter = context.Adapter.NativePointer,
Device = context.Device.NativePointer,
Queue = context.Queue.NativePointer,
ProtectedContext = context.ProtectedContext
};
}
}
}
Loading