199 lines
6.6 KiB
C#
199 lines
6.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Runtime.CompilerServices;
|
|
using Windows.Win32.Foundation;
|
|
using System.Runtime.InteropServices;
|
|
using System.Reflection;
|
|
using StgSharpDebug.Environment;
|
|
using StgSharp.Math;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if Windows
|
|
#pragma warning disable CA1416 // 验证平台兼容性
|
|
using Microsoft.Win32.SafeHandles;
|
|
using StgSharp.Envitronment.Win32;
|
|
using Windows.Win32;
|
|
using Windows.Win32.Graphics.OpenGL;
|
|
using Windows.Win32.Graphics.Gdi;
|
|
using Windows.Win32.UI.WindowsAndMessaging;
|
|
|
|
|
|
namespace StgSharp
|
|
{
|
|
public unsafe static partial class Platform
|
|
{
|
|
|
|
internal static unsafe void CreatDummyContext()
|
|
{
|
|
string winclass_name = "Dummy_WGL_context";
|
|
WNDCLASSW window_class = new WNDCLASSW()
|
|
{
|
|
style = WNDCLASS_STYLES.CS_HREDRAW | WNDCLASS_STYLES.CS_VREDRAW | WNDCLASS_STYLES.CS_OWNDC,
|
|
lpfnWndProc = PInvoke.DefWindowProc,
|
|
hInstance = new HINSTANCE(PInvoke.GetModuleHandle("").DangerousGetHandle()),
|
|
lpszClassName = new PCWSTR((char*)Marshal.StringToHGlobalUni(winclass_name))
|
|
};
|
|
|
|
if (PInvoke.RegisterClass(window_class) != 0)
|
|
{
|
|
throw new Exception("Failed in registing OpenGL window.");
|
|
}
|
|
|
|
HWND h = PInvoke.CreateWindowEx(
|
|
Windows.Win32.UI.WindowsAndMessaging.WINDOW_EX_STYLE.WS_EX_LTRREADING,
|
|
winclass_name,
|
|
"Dummy OpenGL window",
|
|
Windows.Win32.UI.WindowsAndMessaging.WINDOW_STYLE.WS_OVERLAPPED,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
default,
|
|
default,
|
|
new LibHandle(window_class.hInstance.Value, false),
|
|
default
|
|
);
|
|
if (h == default)
|
|
{
|
|
throw new Exception("Failed in registing OpenGL window.");
|
|
}
|
|
HDC hdc = PInvoke.GetDC(h);
|
|
|
|
PIXELFORMATDESCRIPTOR pfd = new PIXELFORMATDESCRIPTOR();
|
|
pfd.nSize = (ushort)Marshal.SizeOf(pfd);
|
|
pfd.nVersion = 1;
|
|
pfd.dwFlags = PFD_FLAGS.PFD_DRAW_TO_WINDOW | PFD_FLAGS.PFD_SUPPORT_OPENGL
|
|
| PFD_FLAGS.PFD_DOUBLEBUFFER;
|
|
pfd.iPixelType = PFD_PIXEL_TYPE.PFD_TYPE_RGBA;
|
|
pfd.cColorBits = 32;
|
|
pfd.cDepthBits = 24;
|
|
pfd.cStencilBits = 8;
|
|
pfd.iLayerType = PFD_LAYER_TYPE.PFD_MAIN_PLANE;
|
|
|
|
int pixelFormat = PInvoke.ChoosePixelFormat(hdc, &pfd);
|
|
|
|
if (pixelFormat == 0)
|
|
{
|
|
throw new Exception("Failed in registing OpenGL window.");
|
|
}
|
|
if (PInvoke.SetPixelFormat(hdc, pixelFormat, &pfd))
|
|
{
|
|
throw new Exception("Failed in registing OpenGL window.");
|
|
}
|
|
HGLRC hglrc = PInvoke.wglCreateContext(hdc);
|
|
|
|
PInvoke.wglMakeCurrent(hdc, hglrc);
|
|
|
|
wglEx.LoadWGLex();
|
|
|
|
PInvoke.wglMakeCurrent(hdc, HGLRC.Null);
|
|
PInvoke.wglDeleteContext(hglrc);
|
|
PInvoke.ReleaseDC(h, hdc);
|
|
PInvoke.DestroyWindow(h);
|
|
|
|
}
|
|
|
|
internal static unsafe HGLRC InitGL(HDC realHDC)
|
|
{
|
|
CreatDummyContext();
|
|
|
|
int[] pixelFormatAttribute = new int[] {
|
|
WGLconst.DRAW_TO_WINDOW_ARB, 1,
|
|
WGLconst.SUPPORT_OPENGL_ARB, 1,
|
|
WGLconst.DOUBLE_BUFFER_ARB, 1,
|
|
WGLconst.ACCELERATION_ARB, WGLconst.FULL_ACCELERATION_ARB,
|
|
WGLconst.PIXEL_TYPE_ARB, WGLconst.TYPE_RGBA_ARB,
|
|
WGLconst.COLOR_BITS_ARB, 32,
|
|
WGLconst.DEPTH_BITS_ARB, 24,
|
|
WGLconst.STENCIL_BITS_ARB,8
|
|
};
|
|
|
|
int piFormat;
|
|
uint length;
|
|
|
|
wglEx.glChoosePixelFormatARB(new DeviceContextHandle(realHDC), pixelFormatAttribute, out piFormat, out length);
|
|
if (length == 0)
|
|
{
|
|
throw new Exception("Failed in creating OpenGL core profile.");
|
|
}
|
|
PIXELFORMATDESCRIPTOR pfd = default;
|
|
PInvoke.DescribePixelFormat(realHDC, piFormat, (uint)Marshal.SizeOf(pfd), &pfd);
|
|
if (PInvoke.SetPixelFormat(realHDC, piFormat, in pfd))
|
|
{
|
|
throw new Exception("Failed in creating OpenGL core profile.");
|
|
}
|
|
int[] glVersionAttribute = new int[] {
|
|
WGLconst.CONTEXT_MAJOR_VERSION_ARB,4,
|
|
WGLconst.CONTEXT_MINOR_VERSION_ARB,6,
|
|
WGLconst.CONTEXT_PROFILE_MASK_ARB, WGLconst.CONTEXT_CORE_PROFILE_BIT_ARB
|
|
};
|
|
|
|
HGLRC coreGL = new(wglEx.wglCreateContextAttribsARB(
|
|
new DeviceContextHandle(realHDC), GlRenderContextHandle.Null, glVersionAttribute).Value);
|
|
if (coreGL.Value == IntPtr.Zero)
|
|
{
|
|
throw new Exception("Failed in creating OpenGL core profile.");
|
|
}
|
|
|
|
return coreGL;
|
|
|
|
}
|
|
|
|
internal static unsafe LRESULT window_callback(
|
|
HWND window, uint msg, WPARAM wparam, LPARAM lparam)
|
|
{
|
|
LRESULT ret = new LRESULT(0);
|
|
switch (msg)
|
|
{
|
|
case 0x0010: break;
|
|
case 0x0002:
|
|
PInvoke.PostQuitMessage(0);
|
|
break;
|
|
default:
|
|
ret = PInvoke.DefWindowProc(window, msg, wparam, lparam);
|
|
break;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
internal static unsafe IntPtr CreateForm(HINSTANCE inst)
|
|
{
|
|
string formName = "Hello Stg#!";
|
|
|
|
WNDCLASSW window_class = new WNDCLASSW()
|
|
{
|
|
style = WNDCLASS_STYLES.CS_VREDRAW | WNDCLASS_STYLES.CS_HREDRAW | WNDCLASS_STYLES.CS_OWNDC,
|
|
lpfnWndProc = window_callback,
|
|
hInstance = inst,
|
|
hCursor = new HCURSOR(PInvoke.LoadCursor(default, "IDC_ARROW").DangerousGetHandle()),
|
|
hbrBackground = HBRUSH.Null,
|
|
lpszClassName = new PCWSTR((char*)Marshal.StringToHGlobalUni(formName))
|
|
};
|
|
|
|
if (PInvoke.RegisterClass(in window_class) == 0)
|
|
{
|
|
throw new Exception("Failed to create window instace.");
|
|
}
|
|
|
|
RECT rect = default;
|
|
rect.right = 1024;
|
|
rect.bottom = 576;
|
|
|
|
uint window_style = WGLconst.WS_OVERLAPPEDWINDOW;
|
|
PInvoke.AdjustWindowRect(ref rect, (WINDOW_STYLE)window_style, false);
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#pragma warning restore CA1416 // 验证平台兼容性
|
|
#endif |