diff --git a/tests/SkiaSharp.Desktop.Tests/SkiaSharp.Desktop.Tests.csproj b/tests/SkiaSharp.Desktop.Tests/SkiaSharp.Desktop.Tests.csproj
index dc2671e7..4f70b09b 100644
--- a/tests/SkiaSharp.Desktop.Tests/SkiaSharp.Desktop.Tests.csproj
+++ b/tests/SkiaSharp.Desktop.Tests/SkiaSharp.Desktop.Tests.csproj
@@ -101,14 +101,65 @@
-
- CglContext.cs
+
+ GlContexts\Cgl\Cgl.cs
-
- GlxContext.cs
+
+ GlContexts\Cgl\CglContext.cs
-
- SKCodecTest.cs
+
+ GlContexts\Cgl\CGLError.cs
+
+
+ GlContexts\Cgl\CGLOpenGLProfile.cs
+
+
+ GlContexts\Cgl\CGLPixelFormatAttribute.cs
+
+
+ GlContexts\GlContext.cs
+
+
+ GlContexts\Glx\Glx.cs
+
+
+ GlContexts\Glx\GlxContext.cs
+
+
+ GlContexts\Glx\Xlib.cs
+
+
+ GlContexts\Glx\XVisualClass.cs
+
+
+ GlContexts\Glx\XVisualInfo.cs
+
+
+ GlContexts\Wgl\Gdi32.cs
+
+
+ GlContexts\Wgl\Kernel32.cs
+
+
+ GlContexts\Wgl\PIXELFORMATDESCRIPTOR.cs
+
+
+ GlContexts\Wgl\RECT.cs
+
+
+ GlContexts\Wgl\User32.cs
+
+
+ GlContexts\Wgl\Wgl.cs
+
+
+ GlContexts\Wgl\WglContext.cs
+
+
+ GlContexts\Wgl\WindowStyles.cs
+
+
+ GlContexts\Wgl\WNDCLASS.cs
GRContextTest.cs
@@ -116,46 +167,49 @@
GRGlInterfaceTest.cs
-
- SKStringTest.cs
+
+ SKBasicTypesTest.cs
+
+
+ SKBitmapTest.cs
+
+
+ SKCodecTest.cs
+
+
+ SKColorTableTest.cs
+
+
+ SKColorTest.cs
+
+
+ SKDataTest.cs
-
SKManagedStreamTest.cs
-
- SKSurfaceTest.cs
-
-
- SKTest.cs
-
-
- SKTypefaceTest.cs
-
SKPaintTest.cs
SKPathTest.cs
-
- SKColorTest.cs
+
+ SKStringTest.cs
-
- SKBasicTypesTest.cs
-
-
- SKBitmapTest.cs
-
-
- SKDataTest.cs
-
-
- SKColorTableTest.cs
+
+ SKSurfaceTest.cs
SKSvgTest.cs
+
+ SKTest.cs
+
+
+ SKTypefaceTest.cs
+
+
diff --git a/tests/SkiaSharp.NetCore.Tests/project.json b/tests/SkiaSharp.NetCore.Tests/project.json
index 300b8a09..7b6ba824 100644
--- a/tests/SkiaSharp.NetCore.Tests/project.json
+++ b/tests/SkiaSharp.NetCore.Tests/project.json
@@ -7,7 +7,7 @@
],
"allowUnsafe": true,
"compile": {
- "include": "../Tests/*.cs",
+ "include": "../Tests/**/*.cs",
"excludeFiles":[
"../Tests/SKSurfaceTest.cs"
]
diff --git a/tests/Tests/CglContext.cs b/tests/Tests/CglContext.cs
deleted file mode 100644
index 6520a635..00000000
--- a/tests/Tests/CglContext.cs
+++ /dev/null
@@ -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);
- }
-}
diff --git a/tests/Tests/GlContexts/Cgl/CGLError.cs b/tests/Tests/GlContexts/Cgl/CGLError.cs
new file mode 100644
index 00000000..83cbc317
--- /dev/null
+++ b/tests/Tests/GlContexts/Cgl/CGLError.cs
@@ -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,
+ }
+}
diff --git a/tests/Tests/GlContexts/Cgl/CGLOpenGLProfile.cs b/tests/Tests/GlContexts/Cgl/CGLOpenGLProfile.cs
new file mode 100644
index 00000000..0071d89c
--- /dev/null
+++ b/tests/Tests/GlContexts/Cgl/CGLOpenGLProfile.cs
@@ -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,
+ }
+}
diff --git a/tests/Tests/GlContexts/Cgl/CGLPixelFormatAttribute.cs b/tests/Tests/GlContexts/Cgl/CGLPixelFormatAttribute.cs
new file mode 100644
index 00000000..19bf8004
--- /dev/null
+++ b/tests/Tests/GlContexts/Cgl/CGLPixelFormatAttribute.cs
@@ -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,
+ }
+}
diff --git a/tests/Tests/GlContexts/Cgl/Cgl.cs b/tests/Tests/GlContexts/Cgl/Cgl.cs
new file mode 100644
index 00000000..a7f15239
--- /dev/null
+++ b/tests/Tests/GlContexts/Cgl/Cgl.cs
@@ -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);
+ }
+}
diff --git a/tests/Tests/GlContexts/Cgl/CglContext.cs b/tests/Tests/GlContexts/Cgl/CglContext.cs
new file mode 100644
index 00000000..a8697cd4
--- /dev/null
+++ b/tests/Tests/GlContexts/Cgl/CglContext.cs
@@ -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;
+ }
+ }
+ }
+}
diff --git a/tests/Tests/GlContexts/GlContext.cs b/tests/Tests/GlContexts/GlContext.cs
new file mode 100644
index 00000000..61206f12
--- /dev/null
+++ b/tests/Tests/GlContexts/GlContext.cs
@@ -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();
+ }
+}
diff --git a/tests/Tests/GlContexts/Glx/Glx.cs b/tests/Tests/GlContexts/Glx/Glx.cs
new file mode 100644
index 00000000..cad02ac4
--- /dev/null
+++ b/tests/Tests/GlContexts/Glx/Glx.cs
@@ -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);
+ }
+}
diff --git a/tests/Tests/GlContexts/Glx/GlxContext.cs b/tests/Tests/GlContexts/Glx/GlxContext.cs
new file mode 100644
index 00000000..b46aa358
--- /dev/null
+++ b/tests/Tests/GlContexts/Glx/GlxContext.cs
@@ -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 {
+ 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;
+ }
+ }
+ }
+}
diff --git a/tests/Tests/GlContexts/Glx/XVisualClass.cs b/tests/Tests/GlContexts/Glx/XVisualClass.cs
new file mode 100644
index 00000000..85dd6681
--- /dev/null
+++ b/tests/Tests/GlContexts/Glx/XVisualClass.cs
@@ -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
+ }
+}
diff --git a/tests/Tests/GlContexts/Glx/XVisualInfo.cs b/tests/Tests/GlContexts/Glx/XVisualInfo.cs
new file mode 100644
index 00000000..b1ed544a
--- /dev/null
+++ b/tests/Tests/GlContexts/Glx/XVisualInfo.cs
@@ -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;
+ }
+}
diff --git a/tests/Tests/GlContexts/Glx/Xlib.cs b/tests/Tests/GlContexts/Glx/Xlib.cs
new file mode 100644
index 00000000..b7511360
--- /dev/null
+++ b/tests/Tests/GlContexts/Glx/Xlib.cs
@@ -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);
+ }
+}
diff --git a/tests/Tests/GlContexts/Wgl/Gdi32.cs b/tests/Tests/GlContexts/Wgl/Gdi32.cs
new file mode 100644
index 00000000..7708a65e
--- /dev/null
+++ b/tests/Tests/GlContexts/Wgl/Gdi32.cs
@@ -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);
+ }
+}
diff --git a/tests/Tests/GlContexts/Wgl/Kernel32.cs b/tests/Tests/GlContexts/Wgl/Kernel32.cs
new file mode 100644
index 00000000..4e2849b4
--- /dev/null
+++ b/tests/Tests/GlContexts/Wgl/Kernel32.cs
@@ -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);
+ }
+}
diff --git a/tests/Tests/GlContexts/Wgl/PIXELFORMATDESCRIPTOR.cs b/tests/Tests/GlContexts/Wgl/PIXELFORMATDESCRIPTOR.cs
new file mode 100644
index 00000000..2a024c3c
--- /dev/null
+++ b/tests/Tests/GlContexts/Wgl/PIXELFORMATDESCRIPTOR.cs
@@ -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;
+ }
+}
diff --git a/tests/Tests/GlContexts/Wgl/RECT.cs b/tests/Tests/GlContexts/Wgl/RECT.cs
new file mode 100644
index 00000000..5915e4fc
--- /dev/null
+++ b/tests/Tests/GlContexts/Wgl/RECT.cs
@@ -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;
+ }
+}
diff --git a/tests/Tests/GlContexts/Wgl/User32.cs b/tests/Tests/GlContexts/Wgl/User32.cs
new file mode 100644
index 00000000..0eec6d92
--- /dev/null
+++ b/tests/Tests/GlContexts/Wgl/User32.cs
@@ -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);
+ }
+}
diff --git a/tests/Tests/GlContexts/Wgl/WNDCLASS.cs b/tests/Tests/GlContexts/Wgl/WNDCLASS.cs
new file mode 100644
index 00000000..a08db544
--- /dev/null
+++ b/tests/Tests/GlContexts/Wgl/WNDCLASS.cs
@@ -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;
+ }
+}
diff --git a/tests/Tests/GlContexts/Wgl/Wgl.cs b/tests/Tests/GlContexts/Wgl/Wgl.cs
new file mode 100644
index 00000000..c601df8b
--- /dev/null
+++ b/tests/Tests/GlContexts/Wgl/Wgl.cs
@@ -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("wglGetExtensionsStringARB");
+ wglChoosePixelFormatARB = Wgl.wglGetProcAddress("wglChoosePixelFormatARB");
+ wglCreatePbufferARB = Wgl.wglGetProcAddress("wglCreatePbufferARB");
+ wglDestroyPbufferARB = Wgl.wglGetProcAddress("wglDestroyPbufferARB");
+ wglGetPbufferDCARB = Wgl.wglGetProcAddress("wglGetPbufferDCARB");
+ wglReleasePbufferDCARB = Wgl.wglGetProcAddress("wglReleasePbufferDCARB");
+ wglSwapIntervalEXT = Wgl.wglGetProcAddress("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(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);
+}
diff --git a/tests/Tests/GlContexts/Wgl/WglContext.cs b/tests/Tests/GlContexts/Wgl/WglContext.cs
new file mode 100644
index 00000000..3a3e5889
--- /dev/null
+++ b/tests/Tests/GlContexts/Wgl/WglContext.cs
@@ -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);
+ }
+ }
+}
diff --git a/tests/Tests/GlContexts/Wgl/WindowStyles.cs b/tests/Tests/GlContexts/Wgl/WindowStyles.cs
new file mode 100644
index 00000000..a8f02cbb
--- /dev/null
+++ b/tests/Tests/GlContexts/Wgl/WindowStyles.cs
@@ -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
+ }
+}
diff --git a/tests/Tests/GlxContext.cs b/tests/Tests/GlxContext.cs
deleted file mode 100644
index f03184ec..00000000
--- a/tests/Tests/GlxContext.cs
+++ /dev/null
@@ -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 {
- 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);
- }
-}
diff --git a/tests/Tests/SKTest.cs b/tests/Tests/SKTest.cs
index 8e39f13a..129bf751 100644
--- a/tests/Tests/SKTest.cs
+++ b/tests/Tests/SKTest.cs
@@ -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();
- }
}