Skip to content

Commit

Permalink
Merge pull request #131 from NogginBops/fix-integrated-graphics
Browse files Browse the repository at this point in the history
Try to fix integrated graphics
  • Loading branch information
NogginBops authored Aug 8, 2024
2 parents a4706a8 + f4f5a82 commit 5649081
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 21 deletions.
8 changes: 5 additions & 3 deletions src/GLWpfControl/DXGLContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,15 @@ public DxGlContext(GLWpfControlSettings settings)
ref deviceParameters,
IntPtr.Zero,
out DXInterop.IDirect3DDevice9Ex dxDevice);

DxDevice = dxDevice;

// if the graphics context is null, we use the shared context.
if (settings.ContextToUse != null) {
if (settings.ContextToUse != null)
{
GraphicsContext = settings.ContextToUse;
}
else {
else
{
NativeWindowSettings nws = NativeWindowSettings.Default;
nws.StartFocused = false;
nws.StartVisible = false;
Expand All @@ -102,6 +103,7 @@ public DxGlContext(GLWpfControlSettings settings)
#endif
}


GLDeviceHandle = Wgl.DXOpenDeviceNV(dxDevice.Handle);
if (GLDeviceHandle == IntPtr.Zero)
{
Expand Down
40 changes: 33 additions & 7 deletions src/GLWpfControl/GLWpfControlRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,19 +75,22 @@ public void ReallocateFramebufferIfNeeded(double width, double height, double dp
int newWidth = (int)Math.Ceiling(width * dpiScaleX);
int newHeight = (int)Math.Ceiling(height * dpiScaleY);

// FIXME: It seems we can't use this function to detect if MSAA will work with NV_DX_interop or not...
int result = _context.DxContext.CheckDeviceMultiSampleType(0, DeviceType.HAL, format, true, msaaType, out uint qualityLevels);

if (D3dImage == null || FramebufferWidth != newWidth || FramebufferHeight != newHeight || MultisampleType != msaaType)
{
_context.GraphicsContext.MakeCurrent();

if (D3dImage != null)
{
GL.DeleteFramebuffer(GLFramebufferHandle);
GL.DeleteRenderbuffer(GLSharedDepthRenderRenderbufferHandle);
GL.DeleteRenderbuffer(GLSharedColorRenderbufferHandle);
Wgl.DXUnregisterObjectNV(_context.GLDeviceHandle, DxInteropColorRenderTargetRegisteredHandle);
Wgl.DXUnregisterObjectNV(_context.GLDeviceHandle, DxInteropDepthStencilRenderTargetRegisteredHandle);
DxColorRenderTarget.Release();
DxDepthStencilRenderTarget.Release();
GL.DeleteFramebuffer(GLFramebufferHandle);
GL.DeleteRenderbuffer(GLSharedDepthRenderRenderbufferHandle);
GL.DeleteRenderbuffer(GLSharedColorRenderbufferHandle);
}
D3dImage = null;

Expand All @@ -97,6 +100,7 @@ public void ReallocateFramebufferIfNeeded(double width, double height, double dp
FramebufferHeight = newHeight;
MultisampleType = msaaType;

IntPtr dxColorRenderTargetShareHandle = IntPtr.Zero;
_context.DxDevice.CreateRenderTarget(
FramebufferWidth,
FramebufferHeight,
Expand All @@ -105,9 +109,17 @@ public void ReallocateFramebufferIfNeeded(double width, double height, double dp
0,
false,
out DXInterop.IDirect3DSurface9 dxColorRenderTarget,
ref Unsafe.NullRef<IntPtr>());
ref dxColorRenderTargetShareHandle);
DxColorRenderTarget = dxColorRenderTarget;

bool success;
success = Wgl.DXSetResourceShareHandleNV(DxColorRenderTarget.Handle, dxColorRenderTargetShareHandle);
if (success == false)
{
Debug.WriteLine("Failed to set resource share handle for color render target.");
}

IntPtr dxDepthStencilRenderTargetShareHandle = IntPtr.Zero;
_context.DxDevice.CreateDepthStencilSurface(
FramebufferWidth,
FramebufferHeight,
Expand All @@ -116,9 +128,15 @@ public void ReallocateFramebufferIfNeeded(double width, double height, double dp
0,
false,
out DXInterop.IDirect3DSurface9 dxDepthStencilRenderTarget,
ref Unsafe.NullRef<IntPtr>());
ref dxDepthStencilRenderTargetShareHandle);
DxDepthStencilRenderTarget = dxDepthStencilRenderTarget;

success = Wgl.DXSetResourceShareHandleNV(dxDepthStencilRenderTarget.Handle, dxDepthStencilRenderTargetShareHandle);
if (success == false)
{
Debug.WriteLine("Failed to set resource share handle for depth stencil render target.");
}

#if DEBUG
{
DxColorRenderTarget.GetDesc(out DXInterop.D3DSURFACE_DESC desc);
Expand All @@ -140,18 +158,26 @@ public void ReallocateFramebufferIfNeeded(double width, double height, double dp
GLSharedColorRenderbufferHandle = GL.GenRenderbuffer();
DxInteropColorRenderTargetRegisteredHandle = Wgl.DXRegisterObjectNV(
_context.GLDeviceHandle,
dxColorRenderTarget.Handle,
DxColorRenderTarget.Handle,
(uint)GLSharedColorRenderbufferHandle,
(uint)RenderbufferTarget.Renderbuffer,
WGL_NV_DX_interop.AccessReadWrite);
if (DxInteropColorRenderTargetRegisteredHandle == IntPtr.Zero)
{
Debug.WriteLine($"Could not register color render target. 0x{DXInterop.GetLastError():X8}");
}

GLSharedDepthRenderRenderbufferHandle = GL.GenRenderbuffer();
DxInteropDepthStencilRenderTargetRegisteredHandle = Wgl.DXRegisterObjectNV(
_context.GLDeviceHandle,
dxDepthStencilRenderTarget.Handle,
DxDepthStencilRenderTarget.Handle,
(uint)GLSharedDepthRenderRenderbufferHandle,
(uint)RenderbufferTarget.Renderbuffer,
WGL_NV_DX_interop.AccessReadWrite);
if (DxInteropDepthStencilRenderTargetRegisteredHandle == IntPtr.Zero)
{
Debug.WriteLine($"Could not register depth stencil render target. 0x{DXInterop.GetLastError():X8}");
}

GL.BindFramebuffer(FramebufferTarget.Framebuffer, GLFramebufferHandle);

Expand Down
32 changes: 21 additions & 11 deletions src/GLWpfControl/Interop/DXInterop.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
using OpenTK.Graphics.OpenGL;
using System;
using System.Reflection.Metadata;
using System.Runtime.CompilerServices;
using System.Runtime.ConstrainedExecution;
using System;
using System.Runtime.InteropServices;
using System.Windows.Media.Media3D;
using System.Windows.Media;
using System.Windows;
using System.Windows.Interop;

namespace OpenTK.Wpf.Interop
{
Expand All @@ -30,12 +22,14 @@ public static void Direct3DCreate9Ex(uint SdkVersion, out IDirect3D9Ex context)
static extern int Direct3DCreate9Ex(uint SdkVersion, out IDirect3D9Ex ctx);
}

private delegate uint NativeGetAdapterCount(IDirect3D9Ex contextHandle);
private delegate int NativeCheckDeviceMultiSampleType(IDirect3D9Ex contextHandle, uint Adapter, DeviceType DeviceType, Format SurfaceFormat, bool Windowed, MultisampleType MultiSampleType, out uint pQualityLevels);
private delegate int NativeCreateDeviceEx(IDirect3D9Ex contextHandle, int adapter, DeviceType deviceType, IntPtr focusWindowHandle, CreateFlags behaviorFlags, ref PresentationParameters presentationParameters, IntPtr fullscreenDisplayMode, out IDirect3DDevice9Ex deviceHandle);
private delegate int NativeCreateRenderTarget(IDirect3DDevice9Ex deviceHandle, int width, int height, Format format, MultisampleType multisample, int multisampleQuality, bool lockable, out IDirect3DSurface9 surfaceHandle, ref IntPtr sharedHandle);
private delegate int NativeCreateDepthStencilSurface(IDirect3DDevice9Ex deviceHandle, int width, int height, Format format, MultisampleType multisample, int multisampleQuality, bool discard, out IDirect3DSurface9 surfaceHandle, ref IntPtr sharedHandle);
private delegate uint NativeRelease(IntPtr resourceHandle);

private delegate uint NativeGetDesc(IDirect3DSurface9 surfaceHandle, out D3DSURFACE_DESC pDesc);
private delegate uint NativeDirect3DSurface9_GetDesc(IDirect3DSurface9 surfaceHandle, out D3DSURFACE_DESC pDesc);

public static void CheckHResult(int hresult)
{
Expand Down Expand Up @@ -113,6 +107,22 @@ public uint Release()
return method((IntPtr)VTable);
}

public int CheckDeviceMultiSampleType(uint Adapter, DeviceType DeviceType, Format SurfaceFormat, bool Windowed, MultisampleType MultiSampleType, out uint pQualityLevels)
{
NativeCheckDeviceMultiSampleType method = Marshal.GetDelegateForFunctionPointer<NativeCheckDeviceMultiSampleType>((*VTable)->CheckDeviceMultiSampleType);

int result = method(this, Adapter, DeviceType, SurfaceFormat, Windowed, MultiSampleType, out pQualityLevels);

return result;
}

public uint GetAdapterCount()
{
NativeGetAdapterCount method = Marshal.GetDelegateForFunctionPointer<NativeGetAdapterCount>((*VTable)->GetAdapterCount);

return method(this);
}

public void CreateDeviceEx(int adapter, DeviceType deviceType, IntPtr focusWindowHandle, CreateFlags behaviorFlags, ref PresentationParameters presentationParameters, IntPtr fullscreenDisplayMode, out IDirect3DDevice9Ex deviceHandle)
{
NativeCreateDeviceEx method = Marshal.GetDelegateForFunctionPointer<NativeCreateDeviceEx>((*VTable)->CreateDeviceEx);
Expand Down Expand Up @@ -346,7 +356,7 @@ public struct _VTable

public uint GetDesc(out D3DSURFACE_DESC pDesc)
{
NativeGetDesc method = Marshal.GetDelegateForFunctionPointer<NativeGetDesc>((*VTable)->GetDesc);
NativeDirect3DSurface9_GetDesc method = Marshal.GetDelegateForFunctionPointer<NativeDirect3DSurface9_GetDesc>((*VTable)->GetDesc);

return method(this, out pDesc);
}
Expand Down

0 comments on commit 5649081

Please sign in to comment.