CPF/CPF.Windows/OpenGL/WglContext.cs
2023-12-19 22:11:21 +08:00

170 lines
5.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using CPF.Drawing;
using CPF.OpenGL;
namespace CPF.Windows.OpenGL
{
public class WglContext : CPF.OpenGL.IGlContext
{
public const int WGL_CONTEXT_MAJOR_VERSION_ARB = 0x2091;
public const int WGL_CONTEXT_MINOR_VERSION_ARB = 0x2092;
public const int WGL_CONTEXT_LAYER_PLANE_ARB = 0x2093;
public const int WGL_CONTEXT_PROFILE_MASK_ARB = 0x9126;
public const int GL_FRAMEBUFFER_BINDING = 0x8CA6;
private IntPtr dc;
private IntPtr rc;
IntPtr handle;
public WglContext(IntPtr handle)
{
this.handle = handle;
dc = UnmanagedMethods.GetDC(handle);
var pfd = new PIXELFORMATDESCRIPTOR();
pfd.nSize = (ushort)Marshal.SizeOf(pfd);
pfd.nVersion = 1;
pfd.dwFlags = Wgl.PFD_DRAW_TO_WINDOW | Wgl.PFD_SUPPORT_OPENGL | Wgl.PFD_SUPPORT_COMPOSITION;
pfd.iPixelType = Wgl.PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 24;
pfd.cStencilBits = 8;
pfd.cAlphaBits = 8;
pfd.iLayerType = Wgl.PFD_MAIN_PLANE;
var format = Wgl.ChoosePixelFormat(dc, ref pfd);
Wgl.SetPixelFormat(dc, format, ref pfd);
rc = Wgl.wglCreateContext(dc);
//var nPixelFormat = new int[] { -1 };
//var r = Wgl.wglChoosePixelFormatARB(dc, new int[] {
//Wgl.WGL_SUPPORT_OPENGL_ARB, 1, // Must support OGL rendering
//Wgl.WGL_DRAW_TO_WINDOW_ARB, 1, // pf that can run a window
//Wgl.WGL_ACCELERATION_ARB, Wgl.WGL_FULL_ACCELERATION_ARB, // must be HW accelerated
//Wgl.WGL_PIXEL_TYPE_ARB, Wgl.WGL_TYPE_RGBA_ARB,
//Wgl.WGL_COLOR_BITS_ARB, 32, // 8 bits of each R, G and B
//Wgl. WGL_DEPTH_BITS_ARB, 24, // 24 bits of depth precision for window
//Wgl.WGL_STENCIL_BITS_ARB, 8, // 开启模板缓冲区,模板缓冲区位数=8
//Wgl.WGL_ALPHA_BITS_ARB, 8,
////Wgl.WGL_SAMPLE_BUFFERS_ARB, 1, // MSAA on,开启多重采样
////Wgl.WGL_SAMPLES_ARB, 4, // 4x MSAA ,多重采样样本数量为4
//0, 0
//}, new float[] { 0, 0 }, 1, nPixelFormat, out var f);
//r= Wgl.SetPixelFormat(dc, nPixelFormat[0], ref pfd);
//rc = Wgl.WglCreateContextAttribsArb(dc, IntPtr.Zero,
//new[]
//{
// // major
// WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
// // minor
// WGL_CONTEXT_MINOR_VERSION_ARB, 3,
// // core profile
// //WGL_CONTEXT_PROFILE_MASK_ARB, 0,
// // debug
// // WGL_CONTEXT_FLAGS_ARB, 1,
// // end
// 0, 0
//});
if (rc == IntPtr.Zero)
{
Console.WriteLine("无法创建OpenGLContext DC:" + dc + " Handle:" + handle);
System.Diagnostics.Debug.WriteLine("无法创建OpenGLContext DC:" + dc + " Handle:" + handle);
}
else
{
System.Diagnostics.Debug.WriteLine("OpenGL Context创建成功");
Console.WriteLine("OpenGL Context创建成功");
}
}
public IntPtr RC
{
get { return rc; }
}
public IDisposable GRContext { get; set; }
public IntPtr GetProcAddress(string name)
{
var ptr = Wgl.wglGetProcAddress(name);
if (ptr == IntPtr.Zero)
{
ptr = UnmanagedMethods.GetProcAddress(OpenGl32Handle, name);
}
return ptr;
}
public static IntPtr OpenGl32Handle = UnmanagedMethods.LoadLibrary("opengl32");
IntPtr oldRc;
IntPtr oldDc;
public void MakeCurrent()
{
if (rc != IntPtr.Zero)
{
oldDc = Wgl.wglGetCurrentDC();
oldRc = Wgl.wglGetCurrentContext();
if (!Wgl.wglMakeCurrent(dc, rc))
{
throw new Exception("Could not set the context.");
}
}
}
public void SwapBuffers()
{
if (rc != IntPtr.Zero)
{
if (!Wgl.SwapBuffers(dc))
{
throw new Exception("Could not complete SwapBuffers.");
}
Wgl.wglMakeCurrent(oldDc, oldRc);
}
}
public void Dispose()
{
UnmanagedMethods.ReleaseDC(handle, dc);
if (rc != IntPtr.Zero)
{
Wgl.wglDeleteContext(rc);
}
GRContext?.Dispose();
}
//public override GRGlTextureInfo CreateTexture(SKSizeI textureSize)
//{
// var textures = new uint[1];
// Wgl.glGenTextures(textures.Length, textures);
// var textureId = textures[0];
// Wgl.glBindTexture(Wgl.GL_TEXTURE_2D, textureId);
// Wgl.glTexImage2D(Wgl.GL_TEXTURE_2D, 0, Wgl.GL_RGBA, textureSize.Width, textureSize.Height, 0, Wgl.GL_RGBA, Wgl.GL_UNSIGNED_BYTE, IntPtr.Zero);
// Wgl.glBindTexture(Wgl.GL_TEXTURE_2D, 0);
// return new GRGlTextureInfo
// {
// Id = textureId,
// Target = Wgl.GL_TEXTURE_2D,
// Format = Wgl.GL_RGBA8
// };
//}
//public override void DestroyTexture(uint texture)
//{
// Wgl.glDeleteTextures(1, new[] { texture });
//}
public void GetFramebufferInfo(out int framebuffer, out int samples, out int stencil)
{
Wgl.glGetIntegerv(GL_FRAMEBUFFER_BINDING, out framebuffer);
Wgl.glGetIntegerv(3415, out stencil);
Wgl.glGetIntegerv(32937, out samples);
}
}
}