Added WGL test context
Organized GL test contexts
This commit is contained in:
Родитель
8444644b8e
Коммит
1dbb79b2af
|
@ -101,14 +101,65 @@
|
|||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Tests\CglContext.cs">
|
||||
<Link>CglContext.cs</Link>
|
||||
<Compile Include="..\Tests\GlContexts\Cgl\Cgl.cs">
|
||||
<Link>GlContexts\Cgl\Cgl.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Tests\GlxContext.cs">
|
||||
<Link>GlxContext.cs</Link>
|
||||
<Compile Include="..\Tests\GlContexts\Cgl\CglContext.cs">
|
||||
<Link>GlContexts\Cgl\CglContext.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Tests\SKCodecTest.cs">
|
||||
<Link>SKCodecTest.cs</Link>
|
||||
<Compile Include="..\Tests\GlContexts\Cgl\CGLError.cs">
|
||||
<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 Include="..\Tests\GRContextTest.cs">
|
||||
<Link>GRContextTest.cs</Link>
|
||||
|
@ -116,46 +167,49 @@
|
|||
<Compile Include="..\Tests\GRGlInterfaceTest.cs">
|
||||
<Link>GRGlInterfaceTest.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Tests\SKStringTest.cs">
|
||||
<Link>SKStringTest.cs</Link>
|
||||
<Compile Include="..\Tests\SKBasicTypesTest.cs">
|
||||
<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 Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="..\Tests\SKManagedStreamTest.cs">
|
||||
<Link>SKManagedStreamTest.cs</Link>
|
||||
</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">
|
||||
<Link>SKPaintTest.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Tests\SKPathTest.cs">
|
||||
<Link>SKPathTest.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Tests\SKColorTest.cs">
|
||||
<Link>SKColorTest.cs</Link>
|
||||
<Compile Include="..\Tests\SKStringTest.cs">
|
||||
<Link>SKStringTest.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Tests\SKBasicTypesTest.cs">
|
||||
<Link>SKBasicTypesTest.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 Include="..\Tests\SKSurfaceTest.cs">
|
||||
<Link>SKSurfaceTest.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Tests\SKSvgTest.cs">
|
||||
<Link>SKSvgTest.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="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="..\Content\fonts\content-font.ttf">
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
],
|
||||
"allowUnsafe": true,
|
||||
"compile": {
|
||||
"include": "../Tests/*.cs",
|
||||
"include": "../Tests/**/*.cs",
|
||||
"excludeFiles":[
|
||||
"../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) {
|
||||
return new CglContext();
|
||||
} else if (IsWindows) {
|
||||
return null;
|
||||
return new WglContext();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class GlContext : IDisposable
|
||||
{
|
||||
public abstract void MakeCurrent();
|
||||
public abstract void SwapBuffers();
|
||||
public abstract void Destroy();
|
||||
|
||||
void IDisposable.Dispose() => Destroy();
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче