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