Added WGL test context
Organized GL test contexts
This commit is contained in:
Родитель
8444644b8e
Коммит
1dbb79b2af
|
@ -101,14 +101,65 @@
|
||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="..\Tests\CglContext.cs">
|
<Compile Include="..\Tests\GlContexts\Cgl\Cgl.cs">
|
||||||
<Link>CglContext.cs</Link>
|
<Link>GlContexts\Cgl\Cgl.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\Tests\GlxContext.cs">
|
<Compile Include="..\Tests\GlContexts\Cgl\CglContext.cs">
|
||||||
<Link>GlxContext.cs</Link>
|
<Link>GlContexts\Cgl\CglContext.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\Tests\SKCodecTest.cs">
|
<Compile Include="..\Tests\GlContexts\Cgl\CGLError.cs">
|
||||||
<Link>SKCodecTest.cs</Link>
|
<Link>GlContexts\Cgl\CGLError.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\Tests\GlContexts\Cgl\CGLOpenGLProfile.cs">
|
||||||
|
<Link>GlContexts\Cgl\CGLOpenGLProfile.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\Tests\GlContexts\Cgl\CGLPixelFormatAttribute.cs">
|
||||||
|
<Link>GlContexts\Cgl\CGLPixelFormatAttribute.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\Tests\GlContexts\GlContext.cs">
|
||||||
|
<Link>GlContexts\GlContext.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\Tests\GlContexts\Glx\Glx.cs">
|
||||||
|
<Link>GlContexts\Glx\Glx.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\Tests\GlContexts\Glx\GlxContext.cs">
|
||||||
|
<Link>GlContexts\Glx\GlxContext.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\Tests\GlContexts\Glx\Xlib.cs">
|
||||||
|
<Link>GlContexts\Glx\Xlib.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\Tests\GlContexts\Glx\XVisualClass.cs">
|
||||||
|
<Link>GlContexts\Glx\XVisualClass.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\Tests\GlContexts\Glx\XVisualInfo.cs">
|
||||||
|
<Link>GlContexts\Glx\XVisualInfo.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\Tests\GlContexts\Wgl\Gdi32.cs">
|
||||||
|
<Link>GlContexts\Wgl\Gdi32.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\Tests\GlContexts\Wgl\Kernel32.cs">
|
||||||
|
<Link>GlContexts\Wgl\Kernel32.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\Tests\GlContexts\Wgl\PIXELFORMATDESCRIPTOR.cs">
|
||||||
|
<Link>GlContexts\Wgl\PIXELFORMATDESCRIPTOR.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\Tests\GlContexts\Wgl\RECT.cs">
|
||||||
|
<Link>GlContexts\Wgl\RECT.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\Tests\GlContexts\Wgl\User32.cs">
|
||||||
|
<Link>GlContexts\Wgl\User32.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\Tests\GlContexts\Wgl\Wgl.cs">
|
||||||
|
<Link>GlContexts\Wgl\Wgl.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\Tests\GlContexts\Wgl\WglContext.cs">
|
||||||
|
<Link>GlContexts\Wgl\WglContext.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\Tests\GlContexts\Wgl\WindowStyles.cs">
|
||||||
|
<Link>GlContexts\Wgl\WindowStyles.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\Tests\GlContexts\Wgl\WNDCLASS.cs">
|
||||||
|
<Link>GlContexts\Wgl\WNDCLASS.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\Tests\GRContextTest.cs">
|
<Compile Include="..\Tests\GRContextTest.cs">
|
||||||
<Link>GRContextTest.cs</Link>
|
<Link>GRContextTest.cs</Link>
|
||||||
|
@ -116,46 +167,49 @@
|
||||||
<Compile Include="..\Tests\GRGlInterfaceTest.cs">
|
<Compile Include="..\Tests\GRGlInterfaceTest.cs">
|
||||||
<Link>GRGlInterfaceTest.cs</Link>
|
<Link>GRGlInterfaceTest.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\Tests\SKStringTest.cs">
|
<Compile Include="..\Tests\SKBasicTypesTest.cs">
|
||||||
<Link>SKStringTest.cs</Link>
|
<Link>SKBasicTypesTest.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\Tests\SKBitmapTest.cs">
|
||||||
|
<Link>SKBitmapTest.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\Tests\SKCodecTest.cs">
|
||||||
|
<Link>SKCodecTest.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\Tests\SKColorTableTest.cs">
|
||||||
|
<Link>SKColorTableTest.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\Tests\SKColorTest.cs">
|
||||||
|
<Link>SKColorTest.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\Tests\SKDataTest.cs">
|
||||||
|
<Link>SKDataTest.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
|
||||||
<Compile Include="..\Tests\SKManagedStreamTest.cs">
|
<Compile Include="..\Tests\SKManagedStreamTest.cs">
|
||||||
<Link>SKManagedStreamTest.cs</Link>
|
<Link>SKManagedStreamTest.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\Tests\SKSurfaceTest.cs">
|
|
||||||
<Link>SKSurfaceTest.cs</Link>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="..\Tests\SKTest.cs">
|
|
||||||
<Link>SKTest.cs</Link>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="..\Tests\SKTypefaceTest.cs">
|
|
||||||
<Link>SKTypefaceTest.cs</Link>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="..\Tests\SKPaintTest.cs">
|
<Compile Include="..\Tests\SKPaintTest.cs">
|
||||||
<Link>SKPaintTest.cs</Link>
|
<Link>SKPaintTest.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\Tests\SKPathTest.cs">
|
<Compile Include="..\Tests\SKPathTest.cs">
|
||||||
<Link>SKPathTest.cs</Link>
|
<Link>SKPathTest.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\Tests\SKColorTest.cs">
|
<Compile Include="..\Tests\SKStringTest.cs">
|
||||||
<Link>SKColorTest.cs</Link>
|
<Link>SKStringTest.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\Tests\SKBasicTypesTest.cs">
|
<Compile Include="..\Tests\SKSurfaceTest.cs">
|
||||||
<Link>SKBasicTypesTest.cs</Link>
|
<Link>SKSurfaceTest.cs</Link>
|
||||||
</Compile>
|
|
||||||
<Compile Include="..\Tests\SKBitmapTest.cs">
|
|
||||||
<Link>SKBitmapTest.cs</Link>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="..\Tests\SKDataTest.cs">
|
|
||||||
<Link>SKDataTest.cs</Link>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="..\Tests\SKColorTableTest.cs">
|
|
||||||
<Link>SKColorTableTest.cs</Link>
|
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\Tests\SKSvgTest.cs">
|
<Compile Include="..\Tests\SKSvgTest.cs">
|
||||||
<Link>SKSvgTest.cs</Link>
|
<Link>SKSvgTest.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\Tests\SKTest.cs">
|
||||||
|
<Link>SKTest.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\Tests\SKTypefaceTest.cs">
|
||||||
|
<Link>SKTypefaceTest.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="..\Content\fonts\content-font.ttf">
|
<Content Include="..\Content\fonts\content-font.ttf">
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
],
|
],
|
||||||
"allowUnsafe": true,
|
"allowUnsafe": true,
|
||||||
"compile": {
|
"compile": {
|
||||||
"include": "../Tests/*.cs",
|
"include": "../Tests/**/*.cs",
|
||||||
"excludeFiles":[
|
"excludeFiles":[
|
||||||
"../Tests/SKSurfaceTest.cs"
|
"../Tests/SKSurfaceTest.cs"
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,134 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace SkiaSharp.Tests
|
|
||||||
{
|
|
||||||
internal class CglContext : GlContext
|
|
||||||
{
|
|
||||||
private IntPtr fContext;
|
|
||||||
|
|
||||||
public CglContext()
|
|
||||||
{
|
|
||||||
var attributes = new [] {
|
|
||||||
CGLPixelFormatAttribute.kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute)CGLOpenGLProfile.kCGLOGLPVersion_3_2_Core,
|
|
||||||
CGLPixelFormatAttribute.kCGLPFADoubleBuffer,
|
|
||||||
CGLPixelFormatAttribute.kCGLPFANone
|
|
||||||
};
|
|
||||||
|
|
||||||
IntPtr pixFormat;
|
|
||||||
int npix;
|
|
||||||
|
|
||||||
Cgl.CGLChoosePixelFormat(attributes, out pixFormat, out npix);
|
|
||||||
|
|
||||||
if (pixFormat == IntPtr.Zero) {
|
|
||||||
throw new Exception("CGLChoosePixelFormat failed.");
|
|
||||||
}
|
|
||||||
|
|
||||||
Cgl.CGLCreateContext(pixFormat, IntPtr.Zero, out fContext);
|
|
||||||
Cgl.CGLReleasePixelFormat(pixFormat);
|
|
||||||
|
|
||||||
if (fContext == IntPtr.Zero) {
|
|
||||||
throw new Exception("CGLCreateContext failed.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void MakeCurrent()
|
|
||||||
{
|
|
||||||
Cgl.CGLSetCurrentContext(fContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void SwapBuffers()
|
|
||||||
{
|
|
||||||
Cgl.CGLFlushDrawable(fContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Destroy()
|
|
||||||
{
|
|
||||||
if (fContext != IntPtr.Zero) {
|
|
||||||
Cgl.CGLReleaseContext(fContext);
|
|
||||||
fContext = IntPtr.Zero;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal enum CGLOpenGLProfile {
|
|
||||||
kCGLOGLPVersion_Legacy = 0x1000,
|
|
||||||
kCGLOGLPVersion_3_2_Core = 0x3200,
|
|
||||||
kCGLOGLPVersion_GL3_Core = 0x3200,
|
|
||||||
kCGLOGLPVersion_GL4_Core = 0x4100,
|
|
||||||
}
|
|
||||||
|
|
||||||
internal enum CGLPixelFormatAttribute {
|
|
||||||
kCGLPFANone = 0,
|
|
||||||
kCGLPFAAllRenderers = 1,
|
|
||||||
kCGLPFATripleBuffer = 3,
|
|
||||||
kCGLPFADoubleBuffer = 5,
|
|
||||||
kCGLPFAColorSize = 8,
|
|
||||||
kCGLPFAAlphaSize = 11,
|
|
||||||
kCGLPFADepthSize = 12,
|
|
||||||
kCGLPFAStencilSize = 13,
|
|
||||||
kCGLPFAMinimumPolicy = 51,
|
|
||||||
kCGLPFAMaximumPolicy = 52,
|
|
||||||
kCGLPFASampleBuffers = 55,
|
|
||||||
kCGLPFASamples = 56,
|
|
||||||
kCGLPFAColorFloat = 58,
|
|
||||||
kCGLPFAMultisample = 59,
|
|
||||||
kCGLPFASupersample = 60,
|
|
||||||
kCGLPFASampleAlpha = 61,
|
|
||||||
kCGLPFARendererID = 70,
|
|
||||||
kCGLPFANoRecovery = 72,
|
|
||||||
kCGLPFAAccelerated = 73,
|
|
||||||
kCGLPFAClosestPolicy = 74,
|
|
||||||
kCGLPFABackingStore = 76,
|
|
||||||
kCGLPFABackingVolatile = 77,
|
|
||||||
kCGLPFADisplayMask = 84,
|
|
||||||
kCGLPFAAllowOfflineRenderers = 96,
|
|
||||||
kCGLPFAAcceleratedCompute = 97,
|
|
||||||
kCGLPFAOpenGLProfile = 99,
|
|
||||||
kCGLPFASupportsAutomaticGraphicsSwitching = 101,
|
|
||||||
kCGLPFAVirtualScreenCount = 128,
|
|
||||||
}
|
|
||||||
|
|
||||||
internal enum CGLError {
|
|
||||||
kCGLNoError = 0,
|
|
||||||
kCGLBadAttribute = 10000,
|
|
||||||
kCGLBadProperty = 10001,
|
|
||||||
kCGLBadPixelFormat = 10002,
|
|
||||||
kCGLBadRendererInfo = 10003,
|
|
||||||
kCGLBadContext = 10004,
|
|
||||||
kCGLBadDrawable = 10005,
|
|
||||||
kCGLBadDisplay = 10006,
|
|
||||||
kCGLBadState = 10007,
|
|
||||||
kCGLBadValue = 10008,
|
|
||||||
kCGLBadMatch = 10009,
|
|
||||||
kCGLBadEnumeration = 10010,
|
|
||||||
kCGLBadOffScreen = 10011,
|
|
||||||
kCGLBadFullScreen = 10012,
|
|
||||||
kCGLBadWindow = 10013,
|
|
||||||
kCGLBadAddress = 10014,
|
|
||||||
kCGLBadCodeModule = 10015,
|
|
||||||
kCGLBadAlloc = 10016,
|
|
||||||
kCGLBadConnection = 10017,
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class Cgl
|
|
||||||
{
|
|
||||||
private const string libGL = "/System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL";
|
|
||||||
|
|
||||||
[DllImport(libGL)]
|
|
||||||
public extern static void CGLGetVersion(out int majorvers, out int minorvers);
|
|
||||||
[DllImport(libGL)]
|
|
||||||
public extern static CGLError CGLChoosePixelFormat([In] CGLPixelFormatAttribute[] attribs, out IntPtr pix, out int npix);
|
|
||||||
[DllImport(libGL)]
|
|
||||||
public extern static CGLError CGLCreateContext(IntPtr pix, IntPtr share, out IntPtr ctx);
|
|
||||||
[DllImport(libGL)]
|
|
||||||
public extern static CGLError CGLReleasePixelFormat(IntPtr pix);
|
|
||||||
[DllImport(libGL)]
|
|
||||||
public extern static CGLError CGLSetCurrentContext(IntPtr ctx);
|
|
||||||
[DllImport(libGL)]
|
|
||||||
public extern static void CGLReleaseContext(IntPtr ctx);
|
|
||||||
[DllImport(libGL)]
|
|
||||||
public extern static CGLError CGLFlushDrawable(IntPtr ctx);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace SkiaSharp.Tests
|
||||||
|
{
|
||||||
|
internal enum CGLError {
|
||||||
|
kCGLNoError = 0,
|
||||||
|
kCGLBadAttribute = 10000,
|
||||||
|
kCGLBadProperty = 10001,
|
||||||
|
kCGLBadPixelFormat = 10002,
|
||||||
|
kCGLBadRendererInfo = 10003,
|
||||||
|
kCGLBadContext = 10004,
|
||||||
|
kCGLBadDrawable = 10005,
|
||||||
|
kCGLBadDisplay = 10006,
|
||||||
|
kCGLBadState = 10007,
|
||||||
|
kCGLBadValue = 10008,
|
||||||
|
kCGLBadMatch = 10009,
|
||||||
|
kCGLBadEnumeration = 10010,
|
||||||
|
kCGLBadOffScreen = 10011,
|
||||||
|
kCGLBadFullScreen = 10012,
|
||||||
|
kCGLBadWindow = 10013,
|
||||||
|
kCGLBadAddress = 10014,
|
||||||
|
kCGLBadCodeModule = 10015,
|
||||||
|
kCGLBadAlloc = 10016,
|
||||||
|
kCGLBadConnection = 10017,
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace SkiaSharp.Tests
|
||||||
|
{
|
||||||
|
internal enum CGLOpenGLProfile {
|
||||||
|
kCGLOGLPVersion_Legacy = 0x1000,
|
||||||
|
kCGLOGLPVersion_3_2_Core = 0x3200,
|
||||||
|
kCGLOGLPVersion_GL3_Core = 0x3200,
|
||||||
|
kCGLOGLPVersion_GL4_Core = 0x4100,
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace SkiaSharp.Tests
|
||||||
|
{
|
||||||
|
internal enum CGLPixelFormatAttribute {
|
||||||
|
kCGLPFANone = 0,
|
||||||
|
kCGLPFAAllRenderers = 1,
|
||||||
|
kCGLPFATripleBuffer = 3,
|
||||||
|
kCGLPFADoubleBuffer = 5,
|
||||||
|
kCGLPFAColorSize = 8,
|
||||||
|
kCGLPFAAlphaSize = 11,
|
||||||
|
kCGLPFADepthSize = 12,
|
||||||
|
kCGLPFAStencilSize = 13,
|
||||||
|
kCGLPFAMinimumPolicy = 51,
|
||||||
|
kCGLPFAMaximumPolicy = 52,
|
||||||
|
kCGLPFASampleBuffers = 55,
|
||||||
|
kCGLPFASamples = 56,
|
||||||
|
kCGLPFAColorFloat = 58,
|
||||||
|
kCGLPFAMultisample = 59,
|
||||||
|
kCGLPFASupersample = 60,
|
||||||
|
kCGLPFASampleAlpha = 61,
|
||||||
|
kCGLPFARendererID = 70,
|
||||||
|
kCGLPFANoRecovery = 72,
|
||||||
|
kCGLPFAAccelerated = 73,
|
||||||
|
kCGLPFAClosestPolicy = 74,
|
||||||
|
kCGLPFABackingStore = 76,
|
||||||
|
kCGLPFABackingVolatile = 77,
|
||||||
|
kCGLPFADisplayMask = 84,
|
||||||
|
kCGLPFAAllowOfflineRenderers = 96,
|
||||||
|
kCGLPFAAcceleratedCompute = 97,
|
||||||
|
kCGLPFAOpenGLProfile = 99,
|
||||||
|
kCGLPFASupportsAutomaticGraphicsSwitching = 101,
|
||||||
|
kCGLPFAVirtualScreenCount = 128,
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace SkiaSharp.Tests
|
||||||
|
{
|
||||||
|
internal class Cgl
|
||||||
|
{
|
||||||
|
private const string libGL = "/System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL";
|
||||||
|
|
||||||
|
[DllImport(libGL)]
|
||||||
|
public extern static void CGLGetVersion(out int majorvers, out int minorvers);
|
||||||
|
[DllImport(libGL)]
|
||||||
|
public extern static CGLError CGLChoosePixelFormat([In] CGLPixelFormatAttribute[] attribs, out IntPtr pix, out int npix);
|
||||||
|
[DllImport(libGL)]
|
||||||
|
public extern static CGLError CGLCreateContext(IntPtr pix, IntPtr share, out IntPtr ctx);
|
||||||
|
[DllImport(libGL)]
|
||||||
|
public extern static CGLError CGLReleasePixelFormat(IntPtr pix);
|
||||||
|
[DllImport(libGL)]
|
||||||
|
public extern static CGLError CGLSetCurrentContext(IntPtr ctx);
|
||||||
|
[DllImport(libGL)]
|
||||||
|
public extern static void CGLReleaseContext(IntPtr ctx);
|
||||||
|
[DllImport(libGL)]
|
||||||
|
public extern static CGLError CGLFlushDrawable(IntPtr ctx);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace SkiaSharp.Tests
|
||||||
|
{
|
||||||
|
internal class CglContext : GlContext
|
||||||
|
{
|
||||||
|
private IntPtr fContext;
|
||||||
|
|
||||||
|
public CglContext()
|
||||||
|
{
|
||||||
|
var attributes = new [] {
|
||||||
|
CGLPixelFormatAttribute.kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute)CGLOpenGLProfile.kCGLOGLPVersion_3_2_Core,
|
||||||
|
CGLPixelFormatAttribute.kCGLPFADoubleBuffer,
|
||||||
|
CGLPixelFormatAttribute.kCGLPFANone
|
||||||
|
};
|
||||||
|
|
||||||
|
IntPtr pixFormat;
|
||||||
|
int npix;
|
||||||
|
|
||||||
|
Cgl.CGLChoosePixelFormat(attributes, out pixFormat, out npix);
|
||||||
|
|
||||||
|
if (pixFormat == IntPtr.Zero) {
|
||||||
|
throw new Exception("CGLChoosePixelFormat failed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Cgl.CGLCreateContext(pixFormat, IntPtr.Zero, out fContext);
|
||||||
|
Cgl.CGLReleasePixelFormat(pixFormat);
|
||||||
|
|
||||||
|
if (fContext == IntPtr.Zero) {
|
||||||
|
throw new Exception("CGLCreateContext failed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void MakeCurrent()
|
||||||
|
{
|
||||||
|
Cgl.CGLSetCurrentContext(fContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SwapBuffers()
|
||||||
|
{
|
||||||
|
Cgl.CGLFlushDrawable(fContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Destroy()
|
||||||
|
{
|
||||||
|
if (fContext != IntPtr.Zero) {
|
||||||
|
Cgl.CGLReleaseContext(fContext);
|
||||||
|
fContext = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace SkiaSharp.Tests
|
||||||
|
{
|
||||||
|
public abstract class GlContext : IDisposable
|
||||||
|
{
|
||||||
|
public abstract void MakeCurrent();
|
||||||
|
public abstract void SwapBuffers();
|
||||||
|
public abstract void Destroy();
|
||||||
|
|
||||||
|
void IDisposable.Dispose() => Destroy();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,126 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace SkiaSharp.Tests
|
||||||
|
{
|
||||||
|
internal class Glx
|
||||||
|
{
|
||||||
|
private const string libGL = "libGL";
|
||||||
|
|
||||||
|
public const int GLX_USE_GL = 1;
|
||||||
|
public const int GLX_BUFFER_SIZE = 2;
|
||||||
|
public const int GLX_LEVEL = 3;
|
||||||
|
public const int GLX_RGBA = 4;
|
||||||
|
public const int GLX_DOUBLEBUFFER = 5;
|
||||||
|
public const int GLX_STEREO = 6;
|
||||||
|
public const int GLX_AUX_BUFFERS = 7;
|
||||||
|
public const int GLX_RED_SIZE = 8;
|
||||||
|
public const int GLX_GREEN_SIZE = 9;
|
||||||
|
public const int GLX_BLUE_SIZE = 10;
|
||||||
|
public const int GLX_ALPHA_SIZE = 11;
|
||||||
|
public const int GLX_DEPTH_SIZE = 12;
|
||||||
|
public const int GLX_STENCIL_SIZE = 13;
|
||||||
|
public const int GLX_ACCUM_RED_SIZE = 14;
|
||||||
|
public const int GLX_ACCUM_GREEN_SIZE = 15;
|
||||||
|
public const int GLX_ACCUM_BLUE_SIZE = 16;
|
||||||
|
public const int GLX_ACCUM_ALPHA_SIZE = 17;
|
||||||
|
|
||||||
|
public const int GLX_DRAWABLE_TYPE = 0x8010;
|
||||||
|
public const int GLX_RENDER_TYPE = 0x8011;
|
||||||
|
public const int GLX_X_RENDERABLE = 0x8012;
|
||||||
|
public const int GLX_RGBA_TYPE = 0x8014;
|
||||||
|
public const int GLX_COLOR_INDEX_TYPE = 0x8015;
|
||||||
|
|
||||||
|
public const int GLX_PIXMAP_BIT = 0x00000002;
|
||||||
|
|
||||||
|
public const int GLX_RGBA_BIT = 0x00000001;
|
||||||
|
|
||||||
|
public const int GLX_SAMPLE_BUFFERS = 0x186a0;
|
||||||
|
public const int GLX_SAMPLES = 0x186a1;
|
||||||
|
|
||||||
|
public const int GLX_CONTEXT_DEBUG_BIT_ARB = 0x00000001;
|
||||||
|
public const int GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB = 0x00000002;
|
||||||
|
public const int GLX_CONTEXT_MAJOR_VERSION_ARB = 0x2091;
|
||||||
|
public const int GLX_CONTEXT_MINOR_VERSION_ARB = 0x2092;
|
||||||
|
public const int GLX_CONTEXT_FLAGS_ARB = 0x2094;
|
||||||
|
|
||||||
|
public const int GLX_CONTEXT_CORE_PROFILE_BIT_ARB = 0x00000001;
|
||||||
|
public const int GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB = 0x00000002;
|
||||||
|
public const int GLX_CONTEXT_PROFILE_MASK_ARB = 0x9126;
|
||||||
|
|
||||||
|
static Glx()
|
||||||
|
{
|
||||||
|
var ptr = glXGetProcAddressARB("glXCreateContextAttribsARB");
|
||||||
|
if (ptr != IntPtr.Zero) {
|
||||||
|
glXCreateContextAttribsARB = (glXCreateContextAttribsARBDelegate)Marshal.GetDelegateForFunctionPointer(ptr, typeof(glXCreateContextAttribsARBDelegate));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport(libGL)]
|
||||||
|
public extern static bool glXQueryVersion(IntPtr dpy, out int maj, out int min);
|
||||||
|
[DllImport(libGL)]
|
||||||
|
public extern static IntPtr glXChooseFBConfig(IntPtr dpy, int screen, [In] int[] attribList, out int nitems);
|
||||||
|
public static IntPtr[] ChooseFBConfig(IntPtr dpy, int screen, int[] attribList)
|
||||||
|
{
|
||||||
|
int nitems;
|
||||||
|
var fbcArrayPtr = glXChooseFBConfig(dpy, screen, attribList, out nitems);
|
||||||
|
|
||||||
|
var fbcArray = new IntPtr[nitems];
|
||||||
|
Marshal.Copy(fbcArrayPtr, fbcArray, 0, nitems);
|
||||||
|
|
||||||
|
Xlib.XFree(fbcArrayPtr);
|
||||||
|
|
||||||
|
return fbcArray;
|
||||||
|
}
|
||||||
|
[DllImport(libGL)]
|
||||||
|
public extern static IntPtr glXGetVisualFromFBConfig(IntPtr dpy, IntPtr config);
|
||||||
|
public static XVisualInfo GetVisualFromFBConfig(IntPtr dpy, IntPtr config)
|
||||||
|
{
|
||||||
|
var visualPtr = glXGetVisualFromFBConfig(dpy, config);
|
||||||
|
if (visualPtr == IntPtr.Zero) {
|
||||||
|
throw new Exception("Failed to retrieve visual from framebuffer config.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var visual = (XVisualInfo) Marshal.PtrToStructure(visualPtr, typeof(XVisualInfo));
|
||||||
|
|
||||||
|
Xlib.XFree(visualPtr);
|
||||||
|
|
||||||
|
return visual;
|
||||||
|
}
|
||||||
|
[DllImport(libGL)]
|
||||||
|
public extern static bool glXMakeCurrent(IntPtr dpy, IntPtr drawable, IntPtr ctx);
|
||||||
|
[DllImport(libGL)]
|
||||||
|
public extern static bool glXSwapBuffers(IntPtr dpy, IntPtr drawable);
|
||||||
|
[DllImport(libGL)]
|
||||||
|
public extern static bool glXIsDirect(IntPtr dpy, IntPtr ctx);
|
||||||
|
[DllImport(libGL)]
|
||||||
|
public extern static int glXGetFBConfigAttrib(IntPtr dpy, IntPtr config, int attribute, out int value);
|
||||||
|
[DllImport(libGL)]
|
||||||
|
public extern static IntPtr glXCreateGLXPixmap(IntPtr dpy, ref XVisualInfo visual, IntPtr pixmap);
|
||||||
|
[DllImport(libGL)]
|
||||||
|
public extern static void glXDestroyGLXPixmap(IntPtr dpy, IntPtr pixmap);
|
||||||
|
[DllImport(libGL)]
|
||||||
|
public extern static void glXDestroyContext(IntPtr dpy, IntPtr ctx);
|
||||||
|
[DllImport(libGL)]
|
||||||
|
public extern static IntPtr glXQueryExtensionsString(IntPtr dpy, int screen);
|
||||||
|
public static string QueryExtensionsString(IntPtr dpy, int screen)
|
||||||
|
{
|
||||||
|
return Marshal.PtrToStringAnsi(glXQueryExtensionsString(dpy, screen));
|
||||||
|
}
|
||||||
|
public static string[] QueryExtensions(IntPtr dpy, int screen)
|
||||||
|
{
|
||||||
|
var str = QueryExtensionsString(dpy, screen);
|
||||||
|
if (string.IsNullOrEmpty(str)) {
|
||||||
|
return new string[0];
|
||||||
|
}
|
||||||
|
return str.Split(' ');
|
||||||
|
}
|
||||||
|
[DllImport(libGL)]
|
||||||
|
public extern static IntPtr glXGetProcAddressARB(string procname);
|
||||||
|
[DllImport(libGL)]
|
||||||
|
public extern static IntPtr glXCreateNewContext(IntPtr dpy, IntPtr config, int renderType, IntPtr shareList, int direct);
|
||||||
|
public static readonly glXCreateContextAttribsARBDelegate glXCreateContextAttribsARB;
|
||||||
|
public delegate IntPtr glXCreateContextAttribsARBDelegate(IntPtr dpy, IntPtr config, IntPtr share_context, int direct, int[] attrib_list);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,144 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace SkiaSharp.Tests
|
||||||
|
{
|
||||||
|
internal class GlxContext : GlContext
|
||||||
|
{
|
||||||
|
private IntPtr fDisplay;
|
||||||
|
private IntPtr fPixmap;
|
||||||
|
private IntPtr fGlxPixmap;
|
||||||
|
private IntPtr fContext;
|
||||||
|
|
||||||
|
public GlxContext()
|
||||||
|
{
|
||||||
|
fDisplay = Xlib.XOpenDisplay(null);
|
||||||
|
if (fDisplay == IntPtr.Zero) {
|
||||||
|
Destroy();
|
||||||
|
throw new Exception("Failed to open X display.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var visualAttribs = new [] {
|
||||||
|
Glx.GLX_X_RENDERABLE, Xlib.True,
|
||||||
|
Glx.GLX_DRAWABLE_TYPE, Glx.GLX_PIXMAP_BIT,
|
||||||
|
Glx.GLX_RENDER_TYPE, Glx.GLX_RGBA_BIT,
|
||||||
|
// Glx.GLX_DOUBLEBUFFER, Xlib.True,
|
||||||
|
Glx.GLX_RED_SIZE, 8,
|
||||||
|
Glx.GLX_GREEN_SIZE, 8,
|
||||||
|
Glx.GLX_BLUE_SIZE, 8,
|
||||||
|
Glx.GLX_ALPHA_SIZE, 8,
|
||||||
|
Glx.GLX_DEPTH_SIZE, 24,
|
||||||
|
Glx.GLX_STENCIL_SIZE, 8,
|
||||||
|
// Glx.GLX_SAMPLE_BUFFERS, 1,
|
||||||
|
// Glx.GLX_SAMPLES, 4,
|
||||||
|
Xlib.None
|
||||||
|
};
|
||||||
|
|
||||||
|
int glxMajor, glxMinor;
|
||||||
|
|
||||||
|
if (!Glx.glXQueryVersion(fDisplay, out glxMajor, out glxMinor) ||
|
||||||
|
(glxMajor < 1) ||
|
||||||
|
(glxMajor == 1 && glxMinor < 3)) {
|
||||||
|
Destroy();
|
||||||
|
throw new Exception("GLX version 1.3 or higher required.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var fbc = Glx.ChooseFBConfig(fDisplay, Xlib.XDefaultScreen(fDisplay), visualAttribs);
|
||||||
|
if (fbc.Length == 0) {
|
||||||
|
Destroy();
|
||||||
|
throw new Exception("Failed to retrieve a framebuffer config.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var bestFBC = IntPtr.Zero;
|
||||||
|
var bestNumSamp = -1;
|
||||||
|
for (int i = 0; i < fbc.Length; i++) {
|
||||||
|
|
||||||
|
int sampleBuf, samples;
|
||||||
|
Glx.glXGetFBConfigAttrib(fDisplay, fbc[i], Glx.GLX_SAMPLE_BUFFERS, out sampleBuf);
|
||||||
|
Glx.glXGetFBConfigAttrib(fDisplay, fbc[i], Glx.GLX_SAMPLES, out samples);
|
||||||
|
|
||||||
|
if (bestFBC == IntPtr.Zero || (sampleBuf > 0 && samples > bestNumSamp)) {
|
||||||
|
bestFBC = fbc[i];
|
||||||
|
bestNumSamp = samples;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var vi = Glx.GetVisualFromFBConfig(fDisplay, bestFBC);
|
||||||
|
|
||||||
|
fPixmap = Xlib.XCreatePixmap(fDisplay, Xlib.XRootWindow(fDisplay, vi.screen), 10, 10, (uint)vi.depth);
|
||||||
|
if (fPixmap == IntPtr.Zero) {
|
||||||
|
Destroy();
|
||||||
|
throw new Exception("Failed to create pixmap.");
|
||||||
|
}
|
||||||
|
|
||||||
|
fGlxPixmap = Glx.glXCreateGLXPixmap(fDisplay, ref vi, fPixmap);
|
||||||
|
|
||||||
|
var glxExts = Glx.QueryExtensions(fDisplay, Xlib.XDefaultScreen(fDisplay));
|
||||||
|
if (Array.IndexOf(glxExts, "GLX_ARB_create_context") == -1 ||
|
||||||
|
Glx.glXCreateContextAttribsARB == null) {
|
||||||
|
Console.WriteLine("OpenGL 3.0 doesn't seem to be available.");
|
||||||
|
fContext = Glx.glXCreateNewContext(fDisplay, bestFBC, Glx.GLX_RGBA_TYPE, IntPtr.Zero, Xlib.True);
|
||||||
|
} else {
|
||||||
|
// Let's just use OpenGL 3.0, but we could try find the highest
|
||||||
|
int major = 3, minor = 0;
|
||||||
|
var flags = new List<int> {
|
||||||
|
Glx.GLX_CONTEXT_MAJOR_VERSION_ARB, major,
|
||||||
|
Glx.GLX_CONTEXT_MINOR_VERSION_ARB, minor,
|
||||||
|
};
|
||||||
|
if (major > 2) {
|
||||||
|
flags.AddRange(new[] {
|
||||||
|
Glx.GLX_CONTEXT_PROFILE_MASK_ARB, Glx.GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
flags.Add(Xlib.None);
|
||||||
|
|
||||||
|
fContext = Glx.glXCreateContextAttribsARB(fDisplay, bestFBC, IntPtr.Zero, Xlib.True, flags.ToArray());
|
||||||
|
}
|
||||||
|
if (fContext == IntPtr.Zero) {
|
||||||
|
Destroy();
|
||||||
|
throw new Exception("Failed to create an OpenGL context.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Glx.glXIsDirect(fDisplay, fContext)) {
|
||||||
|
Console.WriteLine("Obtained indirect GLX rendering context.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void MakeCurrent()
|
||||||
|
{
|
||||||
|
if (!Glx.glXMakeCurrent(fDisplay, fGlxPixmap, fContext)) {
|
||||||
|
Destroy();
|
||||||
|
throw new Exception("Failed to set the context.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SwapBuffers()
|
||||||
|
{
|
||||||
|
Glx.glXSwapBuffers(fDisplay, fGlxPixmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Destroy()
|
||||||
|
{
|
||||||
|
if (fDisplay != IntPtr.Zero) {
|
||||||
|
Glx.glXMakeCurrent(fDisplay, IntPtr.Zero, IntPtr.Zero);
|
||||||
|
|
||||||
|
if (fContext != IntPtr.Zero) {
|
||||||
|
Glx.glXDestroyContext(fDisplay, fContext);
|
||||||
|
fContext = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fGlxPixmap != IntPtr.Zero) {
|
||||||
|
Glx.glXDestroyGLXPixmap(fDisplay, fGlxPixmap);
|
||||||
|
fGlxPixmap = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fPixmap != IntPtr.Zero) {
|
||||||
|
Xlib.XFreePixmap(fDisplay, fPixmap);
|
||||||
|
fPixmap = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
fDisplay = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace SkiaSharp.Tests
|
||||||
|
{
|
||||||
|
internal enum XVisualClass : int {
|
||||||
|
StaticGray = 0,
|
||||||
|
GrayScale = 1,
|
||||||
|
StaticColor = 2,
|
||||||
|
PseudoColor = 3,
|
||||||
|
TrueColor = 4,
|
||||||
|
DirectColor = 5
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace SkiaSharp.Tests
|
||||||
|
{
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct XVisualInfo
|
||||||
|
{
|
||||||
|
public IntPtr visual;
|
||||||
|
public IntPtr visualid;
|
||||||
|
public int screen;
|
||||||
|
public int depth;
|
||||||
|
public XVisualClass c_class;
|
||||||
|
public ulong red_mask;
|
||||||
|
public ulong green_mask;
|
||||||
|
public ulong blue_mask;
|
||||||
|
public int colormap_size;
|
||||||
|
public int bits_per_rgb;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace SkiaSharp.Tests
|
||||||
|
{
|
||||||
|
internal class Xlib
|
||||||
|
{
|
||||||
|
private const string libX11 = "libX11";
|
||||||
|
|
||||||
|
public const int None = 0;
|
||||||
|
public const int True = 1;
|
||||||
|
public const int False = 0;
|
||||||
|
|
||||||
|
[DllImport(libX11)]
|
||||||
|
public extern static IntPtr XOpenDisplay(string display_name);
|
||||||
|
[DllImport(libX11)]
|
||||||
|
public extern static int XFree(IntPtr data);
|
||||||
|
[DllImport(libX11)]
|
||||||
|
public extern static int XDefaultScreen(IntPtr display);
|
||||||
|
[DllImport(libX11)]
|
||||||
|
public extern static IntPtr XRootWindow(IntPtr display, int screen);
|
||||||
|
[DllImport(libX11)]
|
||||||
|
public extern static IntPtr XCreatePixmap(IntPtr display, IntPtr d, uint width, uint height, uint depth);
|
||||||
|
[DllImport(libX11)]
|
||||||
|
public extern static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace SkiaSharp.Tests
|
||||||
|
{
|
||||||
|
internal class Gdi32
|
||||||
|
{
|
||||||
|
private const string gdi32 = "gdi32.dll";
|
||||||
|
|
||||||
|
public const byte PFD_TYPE_RGBA = 0;
|
||||||
|
|
||||||
|
public const byte PFD_MAIN_PLANE = 0;
|
||||||
|
|
||||||
|
public const uint PFD_DRAW_TO_WINDOW = 0x00000004;
|
||||||
|
public const uint PFD_SUPPORT_OPENGL = 0x00000020;
|
||||||
|
|
||||||
|
[DllImport(gdi32, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
public static extern bool SetPixelFormat(IntPtr hdc, int iPixelFormat, [In] ref PIXELFORMATDESCRIPTOR ppfd);
|
||||||
|
|
||||||
|
[DllImport(gdi32, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
|
||||||
|
public static extern int ChoosePixelFormat(IntPtr hdc, [In] ref PIXELFORMATDESCRIPTOR ppfd);
|
||||||
|
|
||||||
|
[DllImport(gdi32, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
public static extern bool SwapBuffers(IntPtr hdc);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace SkiaSharp.Tests
|
||||||
|
{
|
||||||
|
internal class Kernel32
|
||||||
|
{
|
||||||
|
private const string kernel32 = "kernel32.dll";
|
||||||
|
|
||||||
|
static Kernel32()
|
||||||
|
{
|
||||||
|
CurrentModuleHandle = Kernel32.GetModuleHandle(null);
|
||||||
|
if (CurrentModuleHandle == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
throw new Exception("Could not get module handle.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IntPtr CurrentModuleHandle { get; }
|
||||||
|
|
||||||
|
[DllImport(kernel32, CallingConvention = CallingConvention.Winapi, BestFitMapping = false, ThrowOnUnmappableChar = true)]
|
||||||
|
public static extern IntPtr GetModuleHandle([MarshalAs(UnmanagedType.LPTStr)] string lpModuleName);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace SkiaSharp.Tests
|
||||||
|
{
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct PIXELFORMATDESCRIPTOR
|
||||||
|
{
|
||||||
|
public ushort nSize;
|
||||||
|
public ushort nVersion;
|
||||||
|
public uint dwFlags;
|
||||||
|
public byte iPixelType;
|
||||||
|
public byte cColorBits;
|
||||||
|
public byte cRedBits;
|
||||||
|
public byte cRedShift;
|
||||||
|
public byte cGreenBits;
|
||||||
|
public byte cGreenShift;
|
||||||
|
public byte cBlueBits;
|
||||||
|
public byte cBlueShift;
|
||||||
|
public byte cAlphaBits;
|
||||||
|
public byte cAlphaShift;
|
||||||
|
public byte cAccumBits;
|
||||||
|
public byte cAccumRedBits;
|
||||||
|
public byte cAccumGreenBits;
|
||||||
|
public byte cAccumBlueBits;
|
||||||
|
public byte cAccumAlphaBits;
|
||||||
|
public byte cDepthBits;
|
||||||
|
public byte cStencilBits;
|
||||||
|
public byte cAuxBuffers;
|
||||||
|
public byte iLayerType;
|
||||||
|
public byte bReserved;
|
||||||
|
public int dwLayerMask;
|
||||||
|
public int dwVisibleMask;
|
||||||
|
public int dwDamageMask;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace SkiaSharp.Tests
|
||||||
|
{
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct RECT
|
||||||
|
{
|
||||||
|
public int left;
|
||||||
|
public int top;
|
||||||
|
public int right;
|
||||||
|
public int bottom;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace SkiaSharp.Tests
|
||||||
|
{
|
||||||
|
internal class User32
|
||||||
|
{
|
||||||
|
private const string user32 = "user32.dll";
|
||||||
|
|
||||||
|
public const uint IDC_ARROW = 32512;
|
||||||
|
|
||||||
|
public const uint IDI_APPLICATION = 32512;
|
||||||
|
public const uint IDI_WINLOGO = 32517;
|
||||||
|
|
||||||
|
public const int SW_HIDE = 0;
|
||||||
|
|
||||||
|
public const uint CS_VREDRAW = 0x1;
|
||||||
|
public const uint CS_HREDRAW = 0x2;
|
||||||
|
public const uint CS_OWNDC = 0x20;
|
||||||
|
|
||||||
|
public const uint WS_EX_CLIENTEDGE = 0x00000200;
|
||||||
|
|
||||||
|
[DllImport(user32, CallingConvention = CallingConvention.Winapi, SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
|
||||||
|
public static extern ushort RegisterClass(ref WNDCLASS lpWndClass);
|
||||||
|
|
||||||
|
[DllImport(user32, CallingConvention = CallingConvention.Winapi, SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
|
||||||
|
public static extern ushort UnregisterClass([MarshalAs(UnmanagedType.LPTStr)] string lpClassName, IntPtr hInstance);
|
||||||
|
|
||||||
|
[DllImport(user32, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
|
||||||
|
public static extern IntPtr LoadCursor(IntPtr hInstance, int lpCursorName);
|
||||||
|
|
||||||
|
[DllImport(user32, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
|
||||||
|
public static extern IntPtr LoadIcon(IntPtr hInstance, IntPtr lpIconName);
|
||||||
|
|
||||||
|
[DllImport(user32, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
public static extern IntPtr DefWindowProc(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam);
|
||||||
|
|
||||||
|
[DllImport(user32, CallingConvention = CallingConvention.Winapi, SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
|
||||||
|
public static extern IntPtr CreateWindowEx(uint dwExStyle, [MarshalAs(UnmanagedType.LPTStr)] string lpClassName, [MarshalAs(UnmanagedType.LPTStr)] string lpWindowName, WindowStyles dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu, IntPtr hInstance, IntPtr lpParam);
|
||||||
|
|
||||||
|
public static IntPtr CreateWindow(string lpClassName, string lpWindowName, WindowStyles dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu, IntPtr hInstance, IntPtr lpParam)
|
||||||
|
{
|
||||||
|
return CreateWindowEx(0, lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport(user32, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
|
||||||
|
public static extern IntPtr GetDC(IntPtr hWnd);
|
||||||
|
|
||||||
|
[DllImport(user32, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
public static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDC);
|
||||||
|
|
||||||
|
[DllImport(user32, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
public static extern bool DestroyWindow(IntPtr hWnd);
|
||||||
|
|
||||||
|
[DllImport(user32, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
public static extern bool IsWindow(IntPtr hWnd);
|
||||||
|
|
||||||
|
[DllImport(user32, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
|
||||||
|
public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
|
||||||
|
|
||||||
|
[DllImport(user32, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
public static extern bool AdjustWindowRectEx(ref RECT lpRect, WindowStyles dwStyle, bool bMenu, uint dwExStyle);
|
||||||
|
|
||||||
|
[DllImport(user32, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
public static extern bool ShowWindow(IntPtr hWnd, uint nCmdShow);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace SkiaSharp.Tests
|
||||||
|
{
|
||||||
|
internal delegate IntPtr WNDPROC(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct WNDCLASS
|
||||||
|
{
|
||||||
|
public uint style;
|
||||||
|
[MarshalAs(UnmanagedType.FunctionPtr)]
|
||||||
|
public WNDPROC lpfnWndProc;
|
||||||
|
public int cbClsExtra;
|
||||||
|
public int cbWndExtra;
|
||||||
|
public IntPtr hInstance;
|
||||||
|
public IntPtr hIcon;
|
||||||
|
public IntPtr hCursor;
|
||||||
|
public IntPtr hbrBackground;
|
||||||
|
[MarshalAs(UnmanagedType.LPTStr)]
|
||||||
|
public string lpszMenuName;
|
||||||
|
[MarshalAs(UnmanagedType.LPTStr)]
|
||||||
|
public string lpszClassName;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,249 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace SkiaSharp.Tests
|
||||||
|
{
|
||||||
|
internal class Wgl
|
||||||
|
{
|
||||||
|
private const string opengl32 = "opengl32.dll";
|
||||||
|
|
||||||
|
public const int NONE = 0;
|
||||||
|
public const int FALSE = 0;
|
||||||
|
public const int TRUE = 1;
|
||||||
|
|
||||||
|
public const int WGL_NUMBER_PIXEL_FORMATS_ARB = 0x2000;
|
||||||
|
public const int WGL_DRAW_TO_WINDOW_ARB = 0x2001;
|
||||||
|
public const int WGL_DRAW_TO_BITMAP_ARB = 0x2002;
|
||||||
|
public const int WGL_ACCELERATION_ARB = 0x2003;
|
||||||
|
public const int WGL_NEED_PALETTE_ARB = 0x2004;
|
||||||
|
public const int WGL_NEED_SYSTEM_PALETTE_ARB = 0x2005;
|
||||||
|
public const int WGL_SWAP_LAYER_BUFFERS_ARB = 0x2006;
|
||||||
|
public const int WGL_SWAP_METHOD_ARB = 0x2007;
|
||||||
|
public const int WGL_NUMBER_OVERLAYS_ARB = 0x2008;
|
||||||
|
public const int WGL_NUMBER_UNDERLAYS_ARB = 0x2009;
|
||||||
|
public const int WGL_TRANSPARENT_ARB = 0x200A;
|
||||||
|
public const int WGL_TRANSPARENT_RED_VALUE_ARB = 0x2037;
|
||||||
|
public const int WGL_TRANSPARENT_GREEN_VALUE_ARB = 0x2038;
|
||||||
|
public const int WGL_TRANSPARENT_BLUE_VALUE_ARB = 0x2039;
|
||||||
|
public const int WGL_TRANSPARENT_ALPHA_VALUE_ARB = 0x203A;
|
||||||
|
public const int WGL_TRANSPARENT_INDEX_VALUE_ARB = 0x203B;
|
||||||
|
public const int WGL_SHARE_DEPTH_ARB = 0x200C;
|
||||||
|
public const int WGL_SHARE_STENCIL_ARB = 0x200D;
|
||||||
|
public const int WGL_SHARE_ACCUM_ARB = 0x200E;
|
||||||
|
public const int WGL_SUPPORT_GDI_ARB = 0x200F;
|
||||||
|
public const int WGL_SUPPORT_OPENGL_ARB = 0x2010;
|
||||||
|
public const int WGL_DOUBLE_BUFFER_ARB = 0x2011;
|
||||||
|
public const int WGL_STEREO_ARB = 0x2012;
|
||||||
|
public const int WGL_PIXEL_TYPE_ARB = 0x2013;
|
||||||
|
public const int WGL_COLOR_BITS_ARB = 0x2014;
|
||||||
|
public const int WGL_RED_BITS_ARB = 0x2015;
|
||||||
|
public const int WGL_RED_SHIFT_ARB = 0x2016;
|
||||||
|
public const int WGL_GREEN_BITS_ARB = 0x2017;
|
||||||
|
public const int WGL_GREEN_SHIFT_ARB = 0x2018;
|
||||||
|
public const int WGL_BLUE_BITS_ARB = 0x2019;
|
||||||
|
public const int WGL_BLUE_SHIFT_ARB = 0x201A;
|
||||||
|
public const int WGL_ALPHA_BITS_ARB = 0x201B;
|
||||||
|
public const int WGL_ALPHA_SHIFT_ARB = 0x201C;
|
||||||
|
public const int WGL_ACCUM_BITS_ARB = 0x201D;
|
||||||
|
public const int WGL_ACCUM_RED_BITS_ARB = 0x201E;
|
||||||
|
public const int WGL_ACCUM_GREEN_BITS_ARB = 0x201F;
|
||||||
|
public const int WGL_ACCUM_BLUE_BITS_ARB = 0x2020;
|
||||||
|
public const int WGL_ACCUM_ALPHA_BITS_ARB = 0x2021;
|
||||||
|
public const int WGL_DEPTH_BITS_ARB = 0x2022;
|
||||||
|
public const int WGL_STENCIL_BITS_ARB = 0x2023;
|
||||||
|
public const int WGL_AUX_BUFFERS_ARB = 0x2024;
|
||||||
|
public const int WGL_NO_ACCELERATION_ARB = 0x2025;
|
||||||
|
public const int WGL_GENERIC_ACCELERATION_ARB = 0x2026;
|
||||||
|
public const int WGL_FULL_ACCELERATION_ARB = 0x2027;
|
||||||
|
public const int WGL_SWAP_EXCHANGE_ARB = 0x2028;
|
||||||
|
public const int WGL_SWAP_COPY_ARB = 0x2029;
|
||||||
|
public const int WGL_SWAP_UNDEFINED_ARB = 0x202A;
|
||||||
|
public const int WGL_TYPE_RGBA_ARB = 0x202B;
|
||||||
|
public const int WGL_TYPE_COLORINDEX_ARB = 0x202C;
|
||||||
|
|
||||||
|
static Wgl()
|
||||||
|
{
|
||||||
|
// save the current GL context
|
||||||
|
var prevDC = Wgl.wglGetCurrentDC();
|
||||||
|
var prevGLRC = Wgl.wglGetCurrentContext();
|
||||||
|
|
||||||
|
// register the dummy window class
|
||||||
|
var wc = new WNDCLASS
|
||||||
|
{
|
||||||
|
style = (User32.CS_HREDRAW | User32.CS_VREDRAW | User32.CS_OWNDC),
|
||||||
|
lpfnWndProc = (WNDPROC)User32.DefWindowProc,
|
||||||
|
cbClsExtra = 0,
|
||||||
|
cbWndExtra = 0,
|
||||||
|
hInstance = Kernel32.CurrentModuleHandle,
|
||||||
|
hCursor = User32.LoadCursor(IntPtr.Zero, (int)User32.IDC_ARROW),
|
||||||
|
hIcon = User32.LoadIcon(IntPtr.Zero, (IntPtr)User32.IDI_WINLOGO),
|
||||||
|
hbrBackground = IntPtr.Zero,
|
||||||
|
lpszMenuName = null,
|
||||||
|
lpszClassName = "DummyClass"
|
||||||
|
};
|
||||||
|
if (User32.RegisterClass(ref wc) == 0)
|
||||||
|
{
|
||||||
|
throw new Exception("Could not register dummy class.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the the dummy window bounds
|
||||||
|
var windowRect = new RECT { left = 0, right = 8, top = 0, bottom = 8 };
|
||||||
|
User32.AdjustWindowRectEx(ref windowRect, WindowStyles.WS_SYSMENU, false, User32.WS_EX_CLIENTEDGE);
|
||||||
|
|
||||||
|
// create the dummy window
|
||||||
|
var dummyWND = User32.CreateWindowEx(
|
||||||
|
User32.WS_EX_CLIENTEDGE,
|
||||||
|
"DummyClass",
|
||||||
|
"DummyWindow",
|
||||||
|
WindowStyles.WS_CLIPSIBLINGS | WindowStyles.WS_CLIPCHILDREN | WindowStyles.WS_SYSMENU,
|
||||||
|
0, 0,
|
||||||
|
windowRect.right - windowRect.left, windowRect.bottom - windowRect.top,
|
||||||
|
IntPtr.Zero, IntPtr.Zero, Kernel32.CurrentModuleHandle, IntPtr.Zero);
|
||||||
|
if (dummyWND == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
User32.UnregisterClass("DummyClass", Kernel32.CurrentModuleHandle);
|
||||||
|
throw new Exception("Could not create dummy window.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the dummy DC
|
||||||
|
var dummyDC = User32.GetDC(dummyWND);
|
||||||
|
|
||||||
|
// get the dummy pixel format
|
||||||
|
var dummyPFD = new PIXELFORMATDESCRIPTOR();
|
||||||
|
dummyPFD.nSize = (ushort)Marshal.SizeOf(dummyPFD);
|
||||||
|
dummyPFD.nVersion = 1;
|
||||||
|
dummyPFD.dwFlags = Gdi32.PFD_DRAW_TO_WINDOW | Gdi32.PFD_SUPPORT_OPENGL;
|
||||||
|
dummyPFD.iPixelType = Gdi32.PFD_TYPE_RGBA;
|
||||||
|
dummyPFD.cColorBits = 32;
|
||||||
|
dummyPFD.cDepthBits = 24;
|
||||||
|
dummyPFD.cStencilBits = 8;
|
||||||
|
dummyPFD.iLayerType = Gdi32.PFD_MAIN_PLANE;
|
||||||
|
var dummyFormat = Gdi32.ChoosePixelFormat(dummyDC, ref dummyPFD);
|
||||||
|
Gdi32.SetPixelFormat(dummyDC, dummyFormat, ref dummyPFD);
|
||||||
|
|
||||||
|
// get the dummy GL context
|
||||||
|
var dummyGLRC = Wgl.wglCreateContext(dummyDC);
|
||||||
|
if (dummyGLRC == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
throw new Exception("Could not create dummy GL context.");
|
||||||
|
}
|
||||||
|
Wgl.wglMakeCurrent(dummyDC, dummyGLRC);
|
||||||
|
|
||||||
|
// get the extension methods using the dummy context
|
||||||
|
wglGetExtensionsStringARB = Wgl.wglGetProcAddress<wglGetExtensionsStringARBDelegate>("wglGetExtensionsStringARB");
|
||||||
|
wglChoosePixelFormatARB = Wgl.wglGetProcAddress<wglChoosePixelFormatARBDelegate>("wglChoosePixelFormatARB");
|
||||||
|
wglCreatePbufferARB = Wgl.wglGetProcAddress<wglCreatePbufferARBDelegate>("wglCreatePbufferARB");
|
||||||
|
wglDestroyPbufferARB = Wgl.wglGetProcAddress<wglDestroyPbufferARBDelegate>("wglDestroyPbufferARB");
|
||||||
|
wglGetPbufferDCARB = Wgl.wglGetProcAddress<wglGetPbufferDCARBDelegate>("wglGetPbufferDCARB");
|
||||||
|
wglReleasePbufferDCARB = Wgl.wglGetProcAddress<wglReleasePbufferDCARBDelegate>("wglReleasePbufferDCARB");
|
||||||
|
wglSwapIntervalEXT = Wgl.wglGetProcAddress<wglSwapIntervalEXTDelegate>("wglSwapIntervalEXT");
|
||||||
|
// GET_PROC(ChoosePixelFormat, ARB);
|
||||||
|
// GET_PROC(GetPixelFormatAttribiv, ARB);
|
||||||
|
// GET_PROC(GetPixelFormatAttribfv, ARB);
|
||||||
|
// GET_PROC(CreateContextAttribs, ARB);
|
||||||
|
|
||||||
|
// destroy the dummy GL context
|
||||||
|
Wgl.wglMakeCurrent(dummyDC, IntPtr.Zero);
|
||||||
|
Wgl.wglDeleteContext(dummyGLRC);
|
||||||
|
|
||||||
|
// destroy the dummy window
|
||||||
|
User32.DestroyWindow(dummyWND);
|
||||||
|
User32.UnregisterClass("DummyClass", Kernel32.CurrentModuleHandle);
|
||||||
|
|
||||||
|
// reset the initial GL context
|
||||||
|
Wgl.wglMakeCurrent(prevDC, prevGLRC);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool HasExtension(IntPtr dc, string ext)
|
||||||
|
{
|
||||||
|
if (ext == "WGL_ARB_extensions_string")
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Array.IndexOf(GetExtensionsARB(dc), ext) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetExtensionsStringARB(IntPtr dc)
|
||||||
|
{
|
||||||
|
return Marshal.PtrToStringAnsi(wglGetExtensionsStringARB(dc));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string[] GetExtensionsARB(IntPtr dc)
|
||||||
|
{
|
||||||
|
var str = GetExtensionsStringARB(dc);
|
||||||
|
if (string.IsNullOrEmpty(str))
|
||||||
|
{
|
||||||
|
return new string[0];
|
||||||
|
}
|
||||||
|
return str.Split(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly wglGetExtensionsStringARBDelegate wglGetExtensionsStringARB;
|
||||||
|
public static readonly wglChoosePixelFormatARBDelegate wglChoosePixelFormatARB;
|
||||||
|
public static readonly wglCreatePbufferARBDelegate wglCreatePbufferARB;
|
||||||
|
public static readonly wglDestroyPbufferARBDelegate wglDestroyPbufferARB;
|
||||||
|
public static readonly wglGetPbufferDCARBDelegate wglGetPbufferDCARB;
|
||||||
|
public static readonly wglReleasePbufferDCARBDelegate wglReleasePbufferDCARB;
|
||||||
|
public static readonly wglSwapIntervalEXTDelegate wglSwapIntervalEXT;
|
||||||
|
|
||||||
|
[DllImport(opengl32, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
public static extern IntPtr wglGetCurrentDC();
|
||||||
|
|
||||||
|
[DllImport(opengl32, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
public static extern IntPtr wglGetCurrentContext();
|
||||||
|
|
||||||
|
[DllImport(opengl32, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
public static extern IntPtr wglCreateContext(IntPtr hDC);
|
||||||
|
|
||||||
|
[DllImport(opengl32, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
public static extern bool wglMakeCurrent(IntPtr hDC, IntPtr hRC);
|
||||||
|
|
||||||
|
[DllImport(opengl32, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
public static extern bool wglDeleteContext(IntPtr hRC);
|
||||||
|
|
||||||
|
[DllImport(opengl32, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
public static extern IntPtr wglGetProcAddress([MarshalAs(UnmanagedType.LPStr)] string lpszProc);
|
||||||
|
|
||||||
|
public static T wglGetProcAddress<T>(string lpszProc)
|
||||||
|
{
|
||||||
|
var ptr = wglGetProcAddress(lpszProc);
|
||||||
|
if (ptr == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
throw new Exception("Unable to load proc: " + lpszProc);
|
||||||
|
}
|
||||||
|
return (T)(object)Marshal.GetDelegateForFunctionPointer(ptr, typeof(T));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||||
|
public delegate IntPtr wglGetExtensionsStringARBDelegate(IntPtr dc);
|
||||||
|
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
public delegate bool wglChoosePixelFormatARBDelegate(
|
||||||
|
IntPtr dc,
|
||||||
|
[In] int[] attribIList,
|
||||||
|
[In] float[] attribFList,
|
||||||
|
uint maxFormats,
|
||||||
|
[Out] int[] pixelFormats,
|
||||||
|
out uint numFormats);
|
||||||
|
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||||
|
public delegate IntPtr wglCreatePbufferARBDelegate(IntPtr dc, int pixelFormat, int width, int height, [In] int[] attribList);
|
||||||
|
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
public delegate bool wglDestroyPbufferARBDelegate(IntPtr pbuffer);
|
||||||
|
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||||
|
public delegate IntPtr wglGetPbufferDCARBDelegate(IntPtr pbuffer);
|
||||||
|
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||||
|
public delegate int wglReleasePbufferDCARBDelegate(IntPtr pbuffer, IntPtr dc);
|
||||||
|
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
public delegate bool wglSwapIntervalEXTDelegate(int interval);
|
||||||
|
}
|
|
@ -0,0 +1,163 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace SkiaSharp.Tests
|
||||||
|
{
|
||||||
|
internal class WglContext : GlContext
|
||||||
|
{
|
||||||
|
private ushort gWC;
|
||||||
|
|
||||||
|
private IntPtr fWindow;
|
||||||
|
private IntPtr fDeviceContext;
|
||||||
|
|
||||||
|
private IntPtr fPbuffer;
|
||||||
|
private IntPtr fPbufferDC;
|
||||||
|
private IntPtr fPbufferGlContext;
|
||||||
|
|
||||||
|
public WglContext()
|
||||||
|
{
|
||||||
|
var wc = new WNDCLASS
|
||||||
|
{
|
||||||
|
cbClsExtra = 0,
|
||||||
|
cbWndExtra = 0,
|
||||||
|
hbrBackground = IntPtr.Zero,
|
||||||
|
hCursor = User32.LoadCursor(IntPtr.Zero, (int)User32.IDC_ARROW),
|
||||||
|
hIcon = User32.LoadIcon(IntPtr.Zero, (IntPtr)User32.IDI_APPLICATION),
|
||||||
|
hInstance = Kernel32.CurrentModuleHandle,
|
||||||
|
lpfnWndProc = (WNDPROC)User32.DefWindowProc,
|
||||||
|
lpszClassName = "Griffin",
|
||||||
|
lpszMenuName = null,
|
||||||
|
style = User32.CS_HREDRAW | User32.CS_VREDRAW | User32.CS_OWNDC
|
||||||
|
};
|
||||||
|
|
||||||
|
gWC = User32.RegisterClass(ref wc);
|
||||||
|
if (gWC == 0)
|
||||||
|
{
|
||||||
|
throw new Exception("Could not register window class.");
|
||||||
|
}
|
||||||
|
|
||||||
|
fWindow = User32.CreateWindow(
|
||||||
|
"Griffin",
|
||||||
|
"The Invisible Man",
|
||||||
|
WindowStyles.WS_OVERLAPPEDWINDOW,
|
||||||
|
0, 0,
|
||||||
|
1, 1,
|
||||||
|
IntPtr.Zero, IntPtr.Zero, Kernel32.CurrentModuleHandle, IntPtr.Zero);
|
||||||
|
if (fWindow == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
throw new Exception($"Could not create window.");
|
||||||
|
}
|
||||||
|
|
||||||
|
fDeviceContext = User32.GetDC(fWindow);
|
||||||
|
if (fDeviceContext == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
throw new Exception("Could not get device context.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Wgl.HasExtension(fDeviceContext, "WGL_ARB_pixel_format") ||
|
||||||
|
!Wgl.HasExtension(fDeviceContext, "WGL_ARB_pbuffer"))
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
throw new Exception("DC does not have extensions.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var iAttrs = new int[]
|
||||||
|
{
|
||||||
|
Wgl.WGL_ACCELERATION_ARB, Wgl.WGL_FULL_ACCELERATION_ARB,
|
||||||
|
Wgl.WGL_DRAW_TO_WINDOW_ARB, Wgl.TRUE,
|
||||||
|
//Wgl.WGL_DOUBLE_BUFFER_ARB, (doubleBuffered ? TRUE : FALSE),
|
||||||
|
Wgl.WGL_SUPPORT_OPENGL_ARB, Wgl.TRUE,
|
||||||
|
Wgl.WGL_RED_BITS_ARB, 8,
|
||||||
|
Wgl.WGL_GREEN_BITS_ARB, 8,
|
||||||
|
Wgl.WGL_BLUE_BITS_ARB, 8,
|
||||||
|
Wgl.WGL_ALPHA_BITS_ARB, 8,
|
||||||
|
Wgl.WGL_STENCIL_BITS_ARB, 8,
|
||||||
|
Wgl.NONE, Wgl.NONE
|
||||||
|
};
|
||||||
|
var piFormats = new int[1];
|
||||||
|
uint nFormats;
|
||||||
|
Wgl.wglChoosePixelFormatARB(fDeviceContext, iAttrs, null, (uint)piFormats.Length, piFormats, out nFormats);
|
||||||
|
if (nFormats == 0)
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
throw new Exception("Could not get pixel formats.");
|
||||||
|
}
|
||||||
|
|
||||||
|
fPbuffer = Wgl.wglCreatePbufferARB(fDeviceContext, piFormats[0], 1, 1, null);
|
||||||
|
if (fPbuffer == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
throw new Exception("Could not create Pbuffer.");
|
||||||
|
}
|
||||||
|
|
||||||
|
fPbufferDC = Wgl.wglGetPbufferDCARB(fPbuffer);
|
||||||
|
if (fPbufferDC == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
throw new Exception("Could not get Pbuffer DC.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var prevDC = Wgl.wglGetCurrentDC();
|
||||||
|
var prevGLRC = Wgl.wglGetCurrentContext();
|
||||||
|
|
||||||
|
fPbufferGlContext = Wgl.wglCreateContext(fPbufferDC);
|
||||||
|
|
||||||
|
Wgl.wglMakeCurrent(prevDC, prevGLRC);
|
||||||
|
|
||||||
|
if (fPbufferGlContext == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
throw new Exception("Could not creeate Pbuffer GL context.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void MakeCurrent()
|
||||||
|
{
|
||||||
|
if (!Wgl.wglMakeCurrent(fPbufferDC, fPbufferGlContext))
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
throw new Exception("Could not set the context.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SwapBuffers()
|
||||||
|
{
|
||||||
|
if (!Gdi32.SwapBuffers(fPbufferDC))
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
throw new Exception("Could not complete SwapBuffers.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Destroy()
|
||||||
|
{
|
||||||
|
if (!Wgl.HasExtension(fPbufferDC, "WGL_ARB_pbuffer"))
|
||||||
|
{
|
||||||
|
// ASSERT
|
||||||
|
}
|
||||||
|
|
||||||
|
Wgl.wglDeleteContext(fPbufferGlContext);
|
||||||
|
|
||||||
|
Wgl.wglReleasePbufferDCARB(fPbuffer, fPbufferDC);
|
||||||
|
|
||||||
|
Wgl.wglDestroyPbufferARB(fPbuffer);
|
||||||
|
|
||||||
|
if (fWindow != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
if (fDeviceContext != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
User32.ReleaseDC(fWindow, fDeviceContext);
|
||||||
|
fDeviceContext = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
User32.DestroyWindow(fWindow);
|
||||||
|
fWindow = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
User32.UnregisterClass("Griffin", Kernel32.CurrentModuleHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace SkiaSharp.Tests
|
||||||
|
{
|
||||||
|
[Flags]
|
||||||
|
internal enum WindowStyles : uint
|
||||||
|
{
|
||||||
|
WS_BORDER = 0x800000,
|
||||||
|
WS_CAPTION = 0xc00000,
|
||||||
|
WS_CHILD = 0x40000000,
|
||||||
|
WS_CLIPCHILDREN = 0x2000000,
|
||||||
|
WS_CLIPSIBLINGS = 0x4000000,
|
||||||
|
WS_DISABLED = 0x8000000,
|
||||||
|
WS_DLGFRAME = 0x400000,
|
||||||
|
WS_GROUP = 0x20000,
|
||||||
|
WS_HSCROLL = 0x100000,
|
||||||
|
WS_MAXIMIZE = 0x1000000,
|
||||||
|
WS_MAXIMIZEBOX = 0x10000,
|
||||||
|
WS_MINIMIZE = 0x20000000,
|
||||||
|
WS_MINIMIZEBOX = 0x20000,
|
||||||
|
WS_OVERLAPPED = 0x0,
|
||||||
|
WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_SIZEFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
|
||||||
|
WS_POPUP = 0x80000000u,
|
||||||
|
WS_POPUPWINDOW = WS_POPUP | WS_BORDER | WS_SYSMENU,
|
||||||
|
WS_SIZEFRAME = 0x40000,
|
||||||
|
WS_SYSMENU = 0x80000,
|
||||||
|
WS_TABSTOP = 0x10000,
|
||||||
|
WS_VISIBLE = 0x10000000,
|
||||||
|
WS_VSCROLL = 0x200000
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,327 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace SkiaSharp.Tests
|
|
||||||
{
|
|
||||||
internal class GlxContext : GlContext
|
|
||||||
{
|
|
||||||
private IntPtr fDisplay;
|
|
||||||
private IntPtr fPixmap;
|
|
||||||
private IntPtr fGlxPixmap;
|
|
||||||
private IntPtr fContext;
|
|
||||||
|
|
||||||
public GlxContext()
|
|
||||||
{
|
|
||||||
fDisplay = Xlib.XOpenDisplay(null);
|
|
||||||
if (fDisplay == IntPtr.Zero) {
|
|
||||||
Destroy();
|
|
||||||
throw new Exception("Failed to open X display.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var visualAttribs = new [] {
|
|
||||||
Glx.GLX_X_RENDERABLE, Xlib.True,
|
|
||||||
Glx.GLX_DRAWABLE_TYPE, Glx.GLX_PIXMAP_BIT,
|
|
||||||
Glx.GLX_RENDER_TYPE, Glx.GLX_RGBA_BIT,
|
|
||||||
// Glx.GLX_DOUBLEBUFFER, Xlib.True,
|
|
||||||
Glx.GLX_RED_SIZE, 8,
|
|
||||||
Glx.GLX_GREEN_SIZE, 8,
|
|
||||||
Glx.GLX_BLUE_SIZE, 8,
|
|
||||||
Glx.GLX_ALPHA_SIZE, 8,
|
|
||||||
Glx.GLX_DEPTH_SIZE, 24,
|
|
||||||
Glx.GLX_STENCIL_SIZE, 8,
|
|
||||||
// Glx.GLX_SAMPLE_BUFFERS, 1,
|
|
||||||
// Glx.GLX_SAMPLES, 4,
|
|
||||||
Xlib.None
|
|
||||||
};
|
|
||||||
|
|
||||||
int glxMajor, glxMinor;
|
|
||||||
|
|
||||||
if (!Glx.glXQueryVersion(fDisplay, out glxMajor, out glxMinor) ||
|
|
||||||
(glxMajor < 1) ||
|
|
||||||
(glxMajor == 1 && glxMinor < 3)) {
|
|
||||||
Destroy();
|
|
||||||
throw new Exception("GLX version 1.3 or higher required.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var fbc = Glx.ChooseFBConfig(fDisplay, Xlib.XDefaultScreen(fDisplay), visualAttribs);
|
|
||||||
if (fbc.Length == 0) {
|
|
||||||
Destroy();
|
|
||||||
throw new Exception("Failed to retrieve a framebuffer config.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var bestFBC = IntPtr.Zero;
|
|
||||||
var bestNumSamp = -1;
|
|
||||||
for (int i = 0; i < fbc.Length; i++) {
|
|
||||||
|
|
||||||
int sampleBuf, samples;
|
|
||||||
Glx.glXGetFBConfigAttrib(fDisplay, fbc[i], Glx.GLX_SAMPLE_BUFFERS, out sampleBuf);
|
|
||||||
Glx.glXGetFBConfigAttrib(fDisplay, fbc[i], Glx.GLX_SAMPLES, out samples);
|
|
||||||
|
|
||||||
if (bestFBC == IntPtr.Zero || (sampleBuf > 0 && samples > bestNumSamp)) {
|
|
||||||
bestFBC = fbc[i];
|
|
||||||
bestNumSamp = samples;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var vi = Glx.GetVisualFromFBConfig(fDisplay, bestFBC);
|
|
||||||
|
|
||||||
fPixmap = Xlib.XCreatePixmap(fDisplay, Xlib.XRootWindow(fDisplay, vi.screen), 10, 10, (uint)vi.depth);
|
|
||||||
if (fPixmap == IntPtr.Zero) {
|
|
||||||
Destroy();
|
|
||||||
throw new Exception("Failed to create pixmap.");
|
|
||||||
}
|
|
||||||
|
|
||||||
fGlxPixmap = Glx.glXCreateGLXPixmap(fDisplay, ref vi, fPixmap);
|
|
||||||
|
|
||||||
var glxExts = Glx.QueryExtensions(fDisplay, Xlib.XDefaultScreen(fDisplay));
|
|
||||||
if (Array.IndexOf(glxExts, "GLX_ARB_create_context") == -1 ||
|
|
||||||
Glx.glXCreateContextAttribsARB == null) {
|
|
||||||
Console.WriteLine("OpenGL 3.0 doesn't seem to be available.");
|
|
||||||
fContext = Glx.glXCreateNewContext(fDisplay, bestFBC, Glx.GLX_RGBA_TYPE, IntPtr.Zero, Xlib.True);
|
|
||||||
} else {
|
|
||||||
// Let's just use OpenGL 3.0, but we could try find the highest
|
|
||||||
int major = 3, minor = 0;
|
|
||||||
var flags = new List<int> {
|
|
||||||
Glx.GLX_CONTEXT_MAJOR_VERSION_ARB, major,
|
|
||||||
Glx.GLX_CONTEXT_MINOR_VERSION_ARB, minor,
|
|
||||||
};
|
|
||||||
if (major > 2) {
|
|
||||||
flags.AddRange(new[] {
|
|
||||||
Glx.GLX_CONTEXT_PROFILE_MASK_ARB, Glx.GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
flags.Add(Xlib.None);
|
|
||||||
|
|
||||||
fContext = Glx.glXCreateContextAttribsARB(fDisplay, bestFBC, IntPtr.Zero, Xlib.True, flags.ToArray());
|
|
||||||
}
|
|
||||||
if (fContext == IntPtr.Zero) {
|
|
||||||
Destroy();
|
|
||||||
throw new Exception("Failed to create an OpenGL context.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Glx.glXIsDirect(fDisplay, fContext)) {
|
|
||||||
Console.WriteLine("Obtained indirect GLX rendering context.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void MakeCurrent()
|
|
||||||
{
|
|
||||||
if (!Glx.glXMakeCurrent(fDisplay, fGlxPixmap, fContext)) {
|
|
||||||
Destroy();
|
|
||||||
throw new Exception("Failed to set the context.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void SwapBuffers()
|
|
||||||
{
|
|
||||||
Glx.glXSwapBuffers(fDisplay, fGlxPixmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Destroy()
|
|
||||||
{
|
|
||||||
if (fDisplay != IntPtr.Zero) {
|
|
||||||
Glx.glXMakeCurrent(fDisplay, IntPtr.Zero, IntPtr.Zero);
|
|
||||||
|
|
||||||
if (fContext != IntPtr.Zero) {
|
|
||||||
Glx.glXDestroyContext(fDisplay, fContext);
|
|
||||||
fContext = IntPtr.Zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fGlxPixmap != IntPtr.Zero) {
|
|
||||||
Glx.glXDestroyGLXPixmap(fDisplay, fGlxPixmap);
|
|
||||||
fGlxPixmap = IntPtr.Zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fPixmap != IntPtr.Zero) {
|
|
||||||
Xlib.XFreePixmap(fDisplay, fPixmap);
|
|
||||||
fPixmap = IntPtr.Zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
fDisplay = IntPtr.Zero;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class Xlib
|
|
||||||
{
|
|
||||||
private const string libX11 = "libX11";
|
|
||||||
|
|
||||||
public const int None = 0;
|
|
||||||
public const int True = 1;
|
|
||||||
public const int False = 0;
|
|
||||||
|
|
||||||
[DllImport(libX11)]
|
|
||||||
public extern static IntPtr XOpenDisplay(string display_name);
|
|
||||||
[DllImport(libX11)]
|
|
||||||
public extern static int XFree(IntPtr data);
|
|
||||||
[DllImport(libX11)]
|
|
||||||
public extern static int XDefaultScreen(IntPtr display);
|
|
||||||
[DllImport(libX11)]
|
|
||||||
public extern static IntPtr XRootWindow(IntPtr display, int screen);
|
|
||||||
[DllImport(libX11)]
|
|
||||||
public extern static IntPtr XCreatePixmap(IntPtr display, IntPtr d, uint width, uint height, uint depth);
|
|
||||||
[DllImport(libX11)]
|
|
||||||
public extern static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap);
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public struct XVisualInfo
|
|
||||||
{
|
|
||||||
public IntPtr visual;
|
|
||||||
public IntPtr visualid;
|
|
||||||
public int screen;
|
|
||||||
public int depth;
|
|
||||||
public XVisualClass c_class;
|
|
||||||
public ulong red_mask;
|
|
||||||
public ulong green_mask;
|
|
||||||
public ulong blue_mask;
|
|
||||||
public int colormap_size;
|
|
||||||
public int bits_per_rgb;
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return
|
|
||||||
"{XVisualInfo " +
|
|
||||||
$", visual={visual}" +
|
|
||||||
$", visualid={visualid}" +
|
|
||||||
$", screen={screen}" +
|
|
||||||
$", depth={depth}" +
|
|
||||||
$", c_class={c_class}" +
|
|
||||||
$", red_mask={red_mask}" +
|
|
||||||
$", green_mask={green_mask}" +
|
|
||||||
$", blue_mask={blue_mask}" +
|
|
||||||
$", colormap_size={colormap_size}" +
|
|
||||||
$", bits_per_rgb={bits_per_rgb}" +
|
|
||||||
"}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal enum XVisualClass : int {
|
|
||||||
StaticGray = 0,
|
|
||||||
GrayScale = 1,
|
|
||||||
StaticColor = 2,
|
|
||||||
PseudoColor = 3,
|
|
||||||
TrueColor = 4,
|
|
||||||
DirectColor = 5
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class Glx
|
|
||||||
{
|
|
||||||
private const string libGL = "libGL";
|
|
||||||
|
|
||||||
public const int GLX_USE_GL = 1;
|
|
||||||
public const int GLX_BUFFER_SIZE = 2;
|
|
||||||
public const int GLX_LEVEL = 3;
|
|
||||||
public const int GLX_RGBA = 4;
|
|
||||||
public const int GLX_DOUBLEBUFFER = 5;
|
|
||||||
public const int GLX_STEREO = 6;
|
|
||||||
public const int GLX_AUX_BUFFERS = 7;
|
|
||||||
public const int GLX_RED_SIZE = 8;
|
|
||||||
public const int GLX_GREEN_SIZE = 9;
|
|
||||||
public const int GLX_BLUE_SIZE = 10;
|
|
||||||
public const int GLX_ALPHA_SIZE = 11;
|
|
||||||
public const int GLX_DEPTH_SIZE = 12;
|
|
||||||
public const int GLX_STENCIL_SIZE = 13;
|
|
||||||
public const int GLX_ACCUM_RED_SIZE = 14;
|
|
||||||
public const int GLX_ACCUM_GREEN_SIZE = 15;
|
|
||||||
public const int GLX_ACCUM_BLUE_SIZE = 16;
|
|
||||||
public const int GLX_ACCUM_ALPHA_SIZE = 17;
|
|
||||||
|
|
||||||
public const int GLX_DRAWABLE_TYPE = 0x8010;
|
|
||||||
public const int GLX_RENDER_TYPE = 0x8011;
|
|
||||||
public const int GLX_X_RENDERABLE = 0x8012;
|
|
||||||
public const int GLX_RGBA_TYPE = 0x8014;
|
|
||||||
public const int GLX_COLOR_INDEX_TYPE = 0x8015;
|
|
||||||
|
|
||||||
public const int GLX_PIXMAP_BIT = 0x00000002;
|
|
||||||
|
|
||||||
public const int GLX_RGBA_BIT = 0x00000001;
|
|
||||||
|
|
||||||
public const int GLX_SAMPLE_BUFFERS = 0x186a0;
|
|
||||||
public const int GLX_SAMPLES = 0x186a1;
|
|
||||||
|
|
||||||
public const int GLX_CONTEXT_DEBUG_BIT_ARB = 0x00000001;
|
|
||||||
public const int GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB = 0x00000002;
|
|
||||||
public const int GLX_CONTEXT_MAJOR_VERSION_ARB = 0x2091;
|
|
||||||
public const int GLX_CONTEXT_MINOR_VERSION_ARB = 0x2092;
|
|
||||||
public const int GLX_CONTEXT_FLAGS_ARB = 0x2094;
|
|
||||||
|
|
||||||
public const int GLX_CONTEXT_CORE_PROFILE_BIT_ARB = 0x00000001;
|
|
||||||
public const int GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB = 0x00000002;
|
|
||||||
public const int GLX_CONTEXT_PROFILE_MASK_ARB = 0x9126;
|
|
||||||
|
|
||||||
static Glx()
|
|
||||||
{
|
|
||||||
var ptr = glXGetProcAddressARB("glXCreateContextAttribsARB");
|
|
||||||
if (ptr != IntPtr.Zero) {
|
|
||||||
glXCreateContextAttribsARB = (glXCreateContextAttribsARBDelegate)Marshal.GetDelegateForFunctionPointer(ptr, typeof(glXCreateContextAttribsARBDelegate));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[DllImport(libGL)]
|
|
||||||
public extern static bool glXQueryVersion(IntPtr dpy, out int maj, out int min);
|
|
||||||
[DllImport(libGL)]
|
|
||||||
public extern static IntPtr glXChooseFBConfig(IntPtr dpy, int screen, [In] int[] attribList, out int nitems);
|
|
||||||
public static IntPtr[] ChooseFBConfig(IntPtr dpy, int screen, int[] attribList)
|
|
||||||
{
|
|
||||||
int nitems;
|
|
||||||
var fbcArrayPtr = glXChooseFBConfig(dpy, screen, attribList, out nitems);
|
|
||||||
|
|
||||||
var fbcArray = new IntPtr[nitems];
|
|
||||||
Marshal.Copy(fbcArrayPtr, fbcArray, 0, nitems);
|
|
||||||
|
|
||||||
Xlib.XFree(fbcArrayPtr);
|
|
||||||
|
|
||||||
return fbcArray;
|
|
||||||
}
|
|
||||||
[DllImport(libGL)]
|
|
||||||
public extern static IntPtr glXGetVisualFromFBConfig(IntPtr dpy, IntPtr config);
|
|
||||||
public static Xlib.XVisualInfo GetVisualFromFBConfig(IntPtr dpy, IntPtr config)
|
|
||||||
{
|
|
||||||
var visualPtr = glXGetVisualFromFBConfig(dpy, config);
|
|
||||||
if (visualPtr == IntPtr.Zero) {
|
|
||||||
throw new Exception("Failed to retrieve visual from framebuffer config.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var visual = (Xlib.XVisualInfo) Marshal.PtrToStructure(visualPtr, typeof(Xlib.XVisualInfo));
|
|
||||||
|
|
||||||
Xlib.XFree(visualPtr);
|
|
||||||
|
|
||||||
return visual;
|
|
||||||
}
|
|
||||||
[DllImport(libGL)]
|
|
||||||
public extern static bool glXMakeCurrent(IntPtr dpy, IntPtr drawable, IntPtr ctx);
|
|
||||||
[DllImport(libGL)]
|
|
||||||
public extern static bool glXSwapBuffers(IntPtr dpy, IntPtr drawable);
|
|
||||||
[DllImport(libGL)]
|
|
||||||
public extern static bool glXIsDirect(IntPtr dpy, IntPtr ctx);
|
|
||||||
[DllImport(libGL)]
|
|
||||||
public extern static int glXGetFBConfigAttrib(IntPtr dpy, IntPtr config, int attribute, out int value);
|
|
||||||
[DllImport(libGL)]
|
|
||||||
public extern static IntPtr glXCreateGLXPixmap(IntPtr dpy, ref Xlib.XVisualInfo visual, IntPtr pixmap);
|
|
||||||
[DllImport(libGL)]
|
|
||||||
public extern static void glXDestroyGLXPixmap(IntPtr dpy, IntPtr pixmap);
|
|
||||||
[DllImport(libGL)]
|
|
||||||
public extern static void glXDestroyContext(IntPtr dpy, IntPtr ctx);
|
|
||||||
[DllImport(libGL)]
|
|
||||||
public extern static IntPtr glXQueryExtensionsString(IntPtr dpy, int screen);
|
|
||||||
public static string QueryExtensionsString(IntPtr dpy, int screen)
|
|
||||||
{
|
|
||||||
return Marshal.PtrToStringAnsi(glXQueryExtensionsString(dpy, screen));
|
|
||||||
}
|
|
||||||
public static string[] QueryExtensions(IntPtr dpy, int screen)
|
|
||||||
{
|
|
||||||
var str = QueryExtensionsString(dpy, screen);
|
|
||||||
if (string.IsNullOrEmpty(str)) {
|
|
||||||
return new string[0];
|
|
||||||
}
|
|
||||||
return str.Split(' ');
|
|
||||||
}
|
|
||||||
[DllImport(libGL)]
|
|
||||||
public extern static IntPtr glXGetProcAddressARB(string procname);
|
|
||||||
[DllImport(libGL)]
|
|
||||||
public extern static IntPtr glXCreateNewContext(IntPtr dpy, IntPtr config, int renderType, IntPtr shareList, int direct);
|
|
||||||
public static readonly glXCreateContextAttribsARBDelegate glXCreateContextAttribsARB;
|
|
||||||
public delegate IntPtr glXCreateContextAttribsARBDelegate(IntPtr dpy, IntPtr config, IntPtr share_context, int direct, int[] attrib_list);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -61,19 +61,10 @@ namespace SkiaSharp.Tests
|
||||||
} else if (IsMac) {
|
} else if (IsMac) {
|
||||||
return new CglContext();
|
return new CglContext();
|
||||||
} else if (IsWindows) {
|
} else if (IsWindows) {
|
||||||
return null;
|
return new WglContext();
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class GlContext : IDisposable
|
|
||||||
{
|
|
||||||
public abstract void MakeCurrent();
|
|
||||||
public abstract void SwapBuffers();
|
|
||||||
public abstract void Destroy();
|
|
||||||
|
|
||||||
void IDisposable.Dispose() => Destroy();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче