mirror of
https://github.com/Ryujinx/Opentk.git
synced 2025-02-02 11:01:07 +00:00
Implemented SDL2 platform using sdl2-cs
This is a new platform that can be used then sdl2 is installed on the target system. SDL2 is commercially supported by Valve and provides better support for MacOS compared to our current implementation (Cocoa vs Carbon). It will also help us introduce faster support for new platforms. Existing platforms remain as a fallback and will be automatically used if sdl2 is not installed. Please note that this is still a work in progress. The new mouse and keyboard API is not supported yet. Due to limitations of sdl2, multiple mice/keyboards are also not supported.
This commit is contained in:
parent
89845d5ff9
commit
6d0b5eb49f
|
@ -155,6 +155,33 @@ namespace OpenTK
|
|||
[DllImport("libc")]
|
||||
private static extern void uname(out utsname uname_struct);
|
||||
|
||||
private static bool DetectSdl2()
|
||||
{
|
||||
bool supported = false;
|
||||
|
||||
// Detect whether SDL2 is supported
|
||||
try
|
||||
{
|
||||
var flags = OpenTK.Platform.SDL2.SDL.SDL_INIT_EVERYTHING;
|
||||
flags &= ~OpenTK.Platform.SDL2.SDL.SDL_INIT_AUDIO;
|
||||
if (OpenTK.Platform.SDL2.SDL.SDL_Init((uint)flags) == 0)
|
||||
{
|
||||
supported = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Print("SDL2 init failed with error: {0}", OpenTK.Platform.SDL2.SDL.SDL_GetError());
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Print("SDL2 init failed with exception: {0}", e);
|
||||
}
|
||||
Debug.Print("SDL2 is {0}", supported ? "supported" : "not supported");
|
||||
|
||||
return supported;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
@ -163,14 +190,14 @@ namespace OpenTK
|
|||
|
||||
#region Internal Methods
|
||||
|
||||
internal static bool Sdl2Supported { get; private set; }
|
||||
|
||||
internal static void Init()
|
||||
{
|
||||
lock (InitLock)
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
initialized = true;
|
||||
|
||||
if (System.Environment.OSVersion.Platform == PlatformID.Win32NT ||
|
||||
System.Environment.OSVersion.Platform == PlatformID.Win32S ||
|
||||
System.Environment.OSVersion.Platform == PlatformID.Win32Windows ||
|
||||
|
@ -179,7 +206,7 @@ namespace OpenTK
|
|||
runningOnWindows = true;
|
||||
}
|
||||
else if (System.Environment.OSVersion.Platform == PlatformID.Unix ||
|
||||
System.Environment.OSVersion.Platform == (PlatformID)4)
|
||||
System.Environment.OSVersion.Platform == (PlatformID)4)
|
||||
{
|
||||
// Distinguish between Linux, Mac OS X and other Unix operating systems.
|
||||
string kernel_name = DetectUnixKernel();
|
||||
|
@ -204,7 +231,9 @@ namespace OpenTK
|
|||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new PlatformNotSupportedException("Unknown platform. Please report this error at http://www.opentk.com.");
|
||||
}
|
||||
|
||||
// Detect whether X is present.
|
||||
// Hack: it seems that this check will cause X to initialize itself on Mac OS X Leopard and newer.
|
||||
|
@ -225,6 +254,10 @@ namespace OpenTK
|
|||
RunningOnWindows ? "Windows" : RunningOnLinux ? "Linux" : RunningOnMacOS ? "MacOS" :
|
||||
runningOnUnix ? "Unix" : RunningOnX11 ? "X11" : "Unknown Platform",
|
||||
RunningOnMono ? "Mono" : ".Net");
|
||||
|
||||
Sdl2Supported = DetectSdl2();
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -399,7 +399,7 @@ namespace OpenTK
|
|||
// On some platforms, ProcessEvents() does not return while the user is resizing or moving
|
||||
// the window. We can avoid this issue by raising UpdateFrame and RenderFrame events
|
||||
// whenever we encounter a size or move event.
|
||||
// Note: hack disabled. Threaded rendering isprovides a better solution to this issue.
|
||||
// Note: hack disabled. Threaded rendering provides a better solution to this issue.
|
||||
//Move += DispatchUpdateAndRenderFrame;
|
||||
//Resize += DispatchUpdateAndRenderFrame;
|
||||
|
||||
|
@ -519,24 +519,6 @@ namespace OpenTK
|
|||
|
||||
if (time > 0)
|
||||
{
|
||||
// Todo: revisit this code. Maybe check average framerate instead?
|
||||
// Note: VSyncMode.Adaptive enables vsync by default. The code below
|
||||
// is supposed to disable vsync if framerate becomes too low (half of target
|
||||
// framerate in the current approach) and reenable once the framerate
|
||||
// rises again.
|
||||
// Note 2: calling Context.VSync = true repeatedly seems to cause jitter on
|
||||
// some configurations. If possible, we should avoid repeated calls.
|
||||
// Note 3: we may not read/write the VSync property without a current context.
|
||||
// This may come to pass if the user has moved rendering to his own thread.
|
||||
if (Context.IsCurrent && VSync == VSyncMode.Adaptive && TargetRenderPeriod != 0)
|
||||
{
|
||||
// Check if we have enough time for a vsync
|
||||
if (RenderTime > 2.0 * TargetRenderPeriod)
|
||||
Context.SwapInterval = 0;
|
||||
else
|
||||
Context.SwapInterval = 1;
|
||||
}
|
||||
|
||||
render_period = render_args.Time = time;
|
||||
OnRenderFrameInternal(render_args);
|
||||
render_time = render_watch.Elapsed.TotalSeconds;
|
||||
|
@ -908,7 +890,21 @@ namespace OpenTK
|
|||
{
|
||||
EnsureUndisposed();
|
||||
GraphicsContext.Assert();
|
||||
Context.VSync = (vsync = value) != VSyncMode.Off;
|
||||
switch (value)
|
||||
{
|
||||
case VSyncMode.On:
|
||||
Context.SwapInterval = 1;
|
||||
break;
|
||||
|
||||
case VSyncMode.Off:
|
||||
Context.SwapInterval = 0;
|
||||
break;
|
||||
|
||||
case VSyncMode.Adaptive:
|
||||
Context.SwapInterval = -1;
|
||||
break;
|
||||
}
|
||||
vsync = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -786,6 +786,18 @@
|
|||
<None Include="Platform\SDL2\sdl2-cs\README" />
|
||||
<Compile Include="Platform\SDL2\sdl2-cs\src\LPUtf8StrMarshaler.cs" />
|
||||
<Compile Include="Platform\SDL2\sdl2-cs\src\SDL2.cs" />
|
||||
<Compile Include="Platform\SDL2\Sdl2DisplayDeviceDriver.cs" />
|
||||
<Compile Include="Platform\SDL2\Sdl2Factory.cs" />
|
||||
<Compile Include="Platform\SDL2\Sdl2GraphicsContext.cs" />
|
||||
<Compile Include="Platform\SDL2\Sdl2GraphicsMode.cs" />
|
||||
<Compile Include="Platform\SDL2\Sdl2InputBase.cs" />
|
||||
<Compile Include="Platform\SDL2\Sdl2Joystick.cs" />
|
||||
<Compile Include="Platform\SDL2\Sdl2KeyMap.cs" />
|
||||
<Compile Include="Platform\SDL2\Sdl2Keyboard.cs" />
|
||||
<Compile Include="Platform\SDL2\Sdl2Mouse.cs" />
|
||||
<Compile Include="Platform\SDL2\Sdl2NativeWindow.cs" />
|
||||
<Compile Include="Platform\SDL2\Sdl2WindowInfo.cs" />
|
||||
<Compile Include="Platform\MacOS\Cgl.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
|
|
|
@ -5,9 +5,11 @@
|
|||
<dllmap os="linux" dll="alut.dll" target="libalut.so.0"/>
|
||||
<dllmap os="linux" dll="opencl.dll" target="libOpenCL.so"/>
|
||||
<dllmap os="linux" dll="libX11" target="libX11.so.6"/>
|
||||
<dllmap os="linux" dll="SDL2.dll" target="libSDL2-2.0.so.0"/>
|
||||
<dllmap os="osx" dll="openal32.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
|
||||
<dllmap os="osx" dll="alut.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
|
||||
<dllmap os="osx" dll="libGLES.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||
<dllmap os="osx" dll="libGLESv2.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||
<dllmap os="osx" dll="opencl.dll" target="/System/Library/Frameworks/OpenCL.framework/OpenCL"/>
|
||||
<dllmap os="osx" dll="SDL2.dll" target="libSDL2.dylib"/>
|
||||
</configuration>
|
||||
|
|
|
@ -45,7 +45,8 @@ namespace OpenTK.Platform
|
|||
|
||||
static Factory()
|
||||
{
|
||||
if (Configuration.RunningOnWindows) Default = new Windows.WinFactory();
|
||||
if (Configuration.Sdl2Supported) Default = new SDL2.Sdl2Factory();
|
||||
else if (Configuration.RunningOnWindows) Default = new Windows.WinFactory();
|
||||
else if (Configuration.RunningOnMacOS) Default = new MacOS.MacOSFactory();
|
||||
else if (Configuration.RunningOnX11) Default = new X11.X11Factory();
|
||||
else Default = new UnsupportedPlatform();
|
||||
|
|
16
Source/OpenTK/Platform/MacOS/Cgl.cs
Normal file
16
Source/OpenTK/Platform/MacOS/Cgl.cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace OpenTK.Platform.MacOS
|
||||
{
|
||||
using CGLContextObj = IntPtr;
|
||||
|
||||
static class Cgl
|
||||
{
|
||||
const string lib = "/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL";
|
||||
|
||||
[DllImport(lib, EntryPoint = "CGLGetCurrentContext")]
|
||||
public static extern CGLContextObj GetCurrentContext();
|
||||
}
|
||||
}
|
||||
|
93
Source/OpenTK/Platform/SDL2/Sdl2DisplayDeviceDriver.cs
Normal file
93
Source/OpenTK/Platform/SDL2/Sdl2DisplayDeviceDriver.cs
Normal file
|
@ -0,0 +1,93 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
|
||||
namespace OpenTK.Platform.SDL2
|
||||
{
|
||||
class Sdl2DisplayDeviceDriver : DisplayDeviceBase
|
||||
{
|
||||
public Sdl2DisplayDeviceDriver()
|
||||
{
|
||||
int displays = SDL.SDL_GetNumVideoDisplays();
|
||||
for (int d = 0; d < displays; d++)
|
||||
{
|
||||
SDL.SDL_Rect bounds;
|
||||
SDL.SDL_GetDisplayBounds(d, out bounds);
|
||||
|
||||
SDL.SDL_DisplayMode current_mode;
|
||||
SDL.SDL_GetCurrentDisplayMode(d, out current_mode);
|
||||
|
||||
var mode_list = new List<DisplayResolution>();
|
||||
int num_modes = SDL.SDL_GetNumDisplayModes(d);
|
||||
for (int m = 0; m < num_modes; m++)
|
||||
{
|
||||
SDL.SDL_DisplayMode sdl_mode;
|
||||
SDL.SDL_GetDisplayMode(d, m, out sdl_mode);
|
||||
mode_list.Add(new DisplayResolution(
|
||||
bounds.x, bounds.y,
|
||||
sdl_mode.w, sdl_mode.h,
|
||||
TranslateFormat(sdl_mode.format),
|
||||
sdl_mode.refresh_rate));
|
||||
}
|
||||
|
||||
var current_resolution = new DisplayResolution(
|
||||
bounds.x, bounds.y,
|
||||
current_mode.w, current_mode.h,
|
||||
TranslateFormat(current_mode.format),
|
||||
current_mode.refresh_rate);
|
||||
|
||||
var device = new DisplayDevice(
|
||||
current_resolution, d == 0, mode_list, TranslateBounds(bounds), d);
|
||||
|
||||
AvailableDevices.Add(device);
|
||||
if (d == 0)
|
||||
Primary = device;
|
||||
}
|
||||
}
|
||||
|
||||
#region Private Members
|
||||
|
||||
int TranslateFormat(uint format)
|
||||
{
|
||||
int bpp;
|
||||
uint a, r, g, b;
|
||||
SDL.SDL_PixelFormatEnumToMasks(format, out bpp, out r, out g, out b, out a);
|
||||
return bpp;
|
||||
}
|
||||
|
||||
Rectangle TranslateBounds(SDL.SDL_Rect rect)
|
||||
{
|
||||
return new Rectangle(rect.x, rect.y, rect.w, rect.h);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region DisplayDeviceBase Members
|
||||
|
||||
public override bool TryChangeResolution(DisplayDevice device, DisplayResolution resolution)
|
||||
{
|
||||
// Todo: we need a temporary window to change resolutions, most probably
|
||||
Trace.WriteLine("SDL2 driver does not implement TryChangeResolution");
|
||||
return true;
|
||||
|
||||
//SDL2.SDL_DisplayMode desired, closest;
|
||||
//desired.w = resolution.Width;
|
||||
//desired.h = resolution.Height;
|
||||
//desired.format = SDL.SDL_PIXELFORMAT_BGRA8888;
|
||||
|
||||
//SDL2.SDL_GetClosestDisplayMode((int)device.Id, ref desired, out closest);
|
||||
//SDL2.SDL_SetWindowDisplayMode(IntPtr.Zero, ref closest);
|
||||
}
|
||||
|
||||
public override bool TryRestoreResolution(DisplayDevice device)
|
||||
{
|
||||
Trace.WriteLine("SDL2 driver does not support TryRestoreResolution");
|
||||
return true;
|
||||
//throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
78
Source/OpenTK/Platform/SDL2/Sdl2Factory.cs
Normal file
78
Source/OpenTK/Platform/SDL2/Sdl2Factory.cs
Normal file
|
@ -0,0 +1,78 @@
|
|||
using System;
|
||||
using OpenTK.Graphics;
|
||||
using OpenTK.Input;
|
||||
|
||||
namespace OpenTK.Platform.SDL2
|
||||
{
|
||||
class Sdl2Factory : IPlatformFactory
|
||||
{
|
||||
public Sdl2Factory()
|
||||
{
|
||||
}
|
||||
|
||||
#region IPlatformFactory implementation
|
||||
|
||||
public INativeWindow CreateNativeWindow(int x, int y, int width, int height, string title, GraphicsMode mode, GameWindowFlags options, DisplayDevice device)
|
||||
{
|
||||
return new Sdl2NativeWindow(x, y, width, height, title, options, device);
|
||||
}
|
||||
|
||||
public IDisplayDeviceDriver CreateDisplayDeviceDriver()
|
||||
{
|
||||
return new Sdl2DisplayDeviceDriver();
|
||||
}
|
||||
|
||||
public IGraphicsContext CreateGLContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags)
|
||||
{
|
||||
return new Sdl2GraphicsContext(mode, (Sdl2WindowInfo)window, shareContext, major, minor, flags);
|
||||
}
|
||||
|
||||
public IGraphicsContext CreateGLContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public GraphicsContext.GetCurrentContextDelegate CreateGetCurrentGraphicsContext()
|
||||
{
|
||||
// Unfortunately, SDL does not provide a GetContext function
|
||||
// so we need to implement our own.
|
||||
return (GraphicsContext.GetCurrentContextDelegate)delegate
|
||||
{
|
||||
IntPtr current;
|
||||
if (Configuration.RunningOnWindows)
|
||||
current = OpenTK.Platform.Windows.Wgl.GetCurrentContext();
|
||||
else if (Configuration.RunningOnX11)
|
||||
current = OpenTK.Platform.X11.Glx.GetCurrentContext();
|
||||
else if (Configuration.RunningOnMacOS)
|
||||
current = OpenTK.Platform.MacOS.Cgl.GetCurrentContext();
|
||||
else
|
||||
throw new NotSupportedException("Unknown platform, please report to http://www.opentk.com");
|
||||
|
||||
return new ContextHandle(current);
|
||||
};
|
||||
}
|
||||
|
||||
public IGraphicsMode CreateGraphicsMode()
|
||||
{
|
||||
return new Sdl2GraphicsMode();
|
||||
}
|
||||
|
||||
public IKeyboardDriver2 CreateKeyboardDriver()
|
||||
{
|
||||
return new Sdl2Keyboard();
|
||||
}
|
||||
|
||||
public IMouseDriver2 CreateMouseDriver()
|
||||
{
|
||||
return new Sdl2Mouse();
|
||||
}
|
||||
|
||||
public IGamePadDriver CreateGamePadDriver()
|
||||
{
|
||||
return new Sdl2Joystick();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
205
Source/OpenTK/Platform/SDL2/Sdl2GraphicsContext.cs
Normal file
205
Source/OpenTK/Platform/SDL2/Sdl2GraphicsContext.cs
Normal file
|
@ -0,0 +1,205 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace OpenTK.Platform.SDL2
|
||||
{
|
||||
class Sdl2GraphicsContext : DesktopGraphicsContext
|
||||
{
|
||||
Sdl2WindowInfo Window { get; set; }
|
||||
ContextHandle SdlContext { get; set; }
|
||||
|
||||
public Sdl2GraphicsContext(Sdl2WindowInfo window)
|
||||
{
|
||||
Window = window;
|
||||
}
|
||||
|
||||
public Sdl2GraphicsContext(GraphicsMode mode,
|
||||
Sdl2WindowInfo window, IGraphicsContext shareContext,
|
||||
int major, int minor,
|
||||
OpenTK.Graphics.GraphicsContextFlags flags)
|
||||
: this(window)
|
||||
{
|
||||
SetGLAttributes(mode, shareContext, major, minor, flags);
|
||||
SdlContext = new ContextHandle(SDL.SDL_GL_CreateContext(window.Handle));
|
||||
Handle = GraphicsContext.GetCurrentContext();
|
||||
}
|
||||
|
||||
#region Private Members
|
||||
|
||||
void SetGLAttributes(GraphicsMode mode,
|
||||
IGraphicsContext shareContext,
|
||||
int major, int minor,
|
||||
GraphicsContextFlags flags)
|
||||
{
|
||||
if (mode.AccumulatorFormat.BitsPerPixel > 0)
|
||||
{
|
||||
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_ACCUM_ALPHA_SIZE, mode.AccumulatorFormat.Alpha);
|
||||
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_ACCUM_RED_SIZE, mode.AccumulatorFormat.Red);
|
||||
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_ACCUM_GREEN_SIZE, mode.AccumulatorFormat.Green);
|
||||
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_ACCUM_BLUE_SIZE, mode.AccumulatorFormat.Blue);
|
||||
}
|
||||
|
||||
if (mode.Buffers > 0)
|
||||
{
|
||||
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_DOUBLEBUFFER, mode.Buffers > 1 ? 1 : 0);
|
||||
}
|
||||
|
||||
if (mode.ColorFormat > 0)
|
||||
{
|
||||
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_ALPHA_SIZE, mode.ColorFormat.Alpha);
|
||||
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_RED_SIZE, mode.ColorFormat.Red);
|
||||
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_GREEN_SIZE, mode.ColorFormat.Green);
|
||||
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_BLUE_SIZE, mode.ColorFormat.Blue);
|
||||
}
|
||||
|
||||
if (mode.Depth > 0)
|
||||
{
|
||||
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_DEPTH_SIZE, mode.Depth);
|
||||
}
|
||||
|
||||
if (mode.Samples > 0)
|
||||
{
|
||||
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_MULTISAMPLEBUFFERS, 1);
|
||||
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_MULTISAMPLESAMPLES, mode.Samples);
|
||||
}
|
||||
|
||||
if (mode.Stencil > 0)
|
||||
{
|
||||
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_STENCIL_SIZE, mode.Stereo ? 1 : 0);
|
||||
}
|
||||
|
||||
if (mode.Stereo)
|
||||
{
|
||||
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_STEREO, 1);
|
||||
}
|
||||
|
||||
if (major > 0)
|
||||
{
|
||||
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_CONTEXT_MAJOR_VERSION, major);
|
||||
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_CONTEXT_MINOR_VERSION, minor);
|
||||
}
|
||||
|
||||
if ((flags & GraphicsContextFlags.Debug) != 0)
|
||||
{
|
||||
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_CONTEXT_FLAGS, (int)SDL.SDL_GLcontext.SDL_GL_CONTEXT_DEBUG_FLAG);
|
||||
}
|
||||
|
||||
if ((flags & GraphicsContextFlags.Embedded) != 0)
|
||||
{
|
||||
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_CONTEXT_EGL, 1);
|
||||
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_CONTEXT_PROFILE_MASK, (int)SDL.SDL_GLprofile.SDL_GL_CONTEXT_PROFILE_ES);
|
||||
}
|
||||
|
||||
if ((flags & GraphicsContextFlags.ForwardCompatible) != 0)
|
||||
{
|
||||
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_CONTEXT_PROFILE_MASK, (int)SDL.SDL_GLprofile.SDL_GL_CONTEXT_PROFILE_CORE);
|
||||
}
|
||||
|
||||
/*
|
||||
if ((flags & GraphicsContextFlags.Robust) != 0)
|
||||
{
|
||||
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_CONTEXT_FLAGS, (int)SDL.SDL_GLcontext.SDL_GL_CONTEXT_ROBUST_ACCESS_FLAG);
|
||||
}
|
||||
|
||||
if ((flags & GraphicsContextFlags.ResetIsolation) != 0)
|
||||
{
|
||||
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_CONTEXT_FLAGS, (int)SDL.SDL_GLcontext.SDL_GL_CONTEXT_RESET_ISOLATION_FLAG);
|
||||
}
|
||||
*/
|
||||
|
||||
if (shareContext != null)
|
||||
{
|
||||
if (shareContext.IsCurrent)
|
||||
{
|
||||
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Trace.WriteLine("Warning: SDL2 requires a shared context to be current before sharing. Sharing failed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GraphicsContextBase Members
|
||||
|
||||
public override void SwapBuffers()
|
||||
{
|
||||
SDL.SDL_GL_SwapWindow(Window.Handle);
|
||||
}
|
||||
|
||||
public override void MakeCurrent(IWindowInfo window)
|
||||
{
|
||||
var sdl_window = window as Sdl2WindowInfo;
|
||||
if (SDL.SDL_GL_MakeCurrent(sdl_window.Handle, SdlContext.Handle) < 0)
|
||||
{
|
||||
Debug.Print("SDL2 MakeCurrent failed with: {0}", SDL.SDL_GetError());
|
||||
}
|
||||
}
|
||||
|
||||
public override IntPtr GetAddress(string function)
|
||||
{
|
||||
return SDL.SDL_GL_GetProcAddress(function);
|
||||
}
|
||||
|
||||
public override bool IsCurrent
|
||||
{
|
||||
get
|
||||
{
|
||||
return GraphicsContext.GetCurrentContext() == Context;
|
||||
}
|
||||
}
|
||||
|
||||
public override int SwapInterval
|
||||
{
|
||||
get
|
||||
{
|
||||
return SDL.SDL_GL_GetSwapInterval();
|
||||
}
|
||||
set
|
||||
{
|
||||
if (SDL.SDL_GL_SetSwapInterval(value) < 0)
|
||||
{
|
||||
Debug.Print("SDL2 failed to set swap interval: {0}", SDL.SDL_GetError());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
void Dispose(bool manual)
|
||||
{
|
||||
if (IsDisposed)
|
||||
{
|
||||
if (manual)
|
||||
{
|
||||
SDL.SDL_GL_DeleteContext(SdlContext.Handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Print("[Warning] IGraphicsContext leaked ({0}). Did you forget to call IGraphicsContext.Dispose()?", this);
|
||||
}
|
||||
IsDisposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~Sdl2GraphicsContext()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
22
Source/OpenTK/Platform/SDL2/Sdl2GraphicsMode.cs
Normal file
22
Source/OpenTK/Platform/SDL2/Sdl2GraphicsMode.cs
Normal file
|
@ -0,0 +1,22 @@
|
|||
using System;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace OpenTK.Platform.SDL2
|
||||
{
|
||||
class Sdl2GraphicsMode : IGraphicsMode
|
||||
{
|
||||
public Sdl2GraphicsMode()
|
||||
{
|
||||
}
|
||||
|
||||
#region IGraphicsMode implementation
|
||||
|
||||
public GraphicsMode SelectGraphicsMode(ColorFormat color, int depth, int stencil, int samples, ColorFormat accum, int buffers, bool stereo)
|
||||
{
|
||||
return new GraphicsMode(new IntPtr(1), new ColorFormat(32), 24, 8, 0, ColorFormat.Empty, 2, false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
63
Source/OpenTK/Platform/SDL2/Sdl2InputBase.cs
Normal file
63
Source/OpenTK/Platform/SDL2/Sdl2InputBase.cs
Normal file
|
@ -0,0 +1,63 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using OpenTK.Input;
|
||||
|
||||
namespace OpenTK.Platform.SDL2
|
||||
{
|
||||
class Sdl2InputBase : IInputDriver2
|
||||
{
|
||||
Sdl2WindowInfo window;
|
||||
readonly Thread thread;
|
||||
readonly AutoResetEvent ready = new AutoResetEvent(false);
|
||||
|
||||
public Sdl2InputBase()
|
||||
{
|
||||
window = new Sdl2WindowInfo(
|
||||
SDL.SDL_CreateWindow("Hidden Input Window", 0, 0, 1, 1,
|
||||
SDL.SDL_WindowFlags.SDL_WINDOW_HIDDEN),
|
||||
null);
|
||||
}
|
||||
|
||||
#region Private Members
|
||||
|
||||
void ProcessEvents()
|
||||
{
|
||||
SDL.SDL_Event e;
|
||||
while (SDL.SDL_WaitEvent(out e) != 0)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IInputDriver2 Members
|
||||
|
||||
public IMouseDriver2 MouseDriver
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public IKeyboardDriver2 KeyboardDriver
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public IGamePadDriver GamePadDriver
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
49
Source/OpenTK/Platform/SDL2/Sdl2Joystick.cs
Normal file
49
Source/OpenTK/Platform/SDL2/Sdl2Joystick.cs
Normal file
|
@ -0,0 +1,49 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenTK.Input;
|
||||
|
||||
namespace OpenTK.Platform.SDL2
|
||||
{
|
||||
class Sdl2Joystick : IJoystickDriver, IGamePadDriver
|
||||
{
|
||||
readonly List<JoystickDevice> joysticks = new List<JoystickDevice>();
|
||||
IList<JoystickDevice> joysticks_readonly;
|
||||
|
||||
public Sdl2Joystick()
|
||||
{
|
||||
joysticks_readonly = joysticks.AsReadOnly();
|
||||
}
|
||||
|
||||
#region IJoystickDriver Members
|
||||
|
||||
public IList<JoystickDevice> Joysticks
|
||||
{
|
||||
get
|
||||
{
|
||||
return joysticks_readonly;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IGamePadDriver Members
|
||||
|
||||
public GamePadState GetState()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public GamePadState GetState(int index)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string GetDeviceName(int index)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
96
Source/OpenTK/Platform/SDL2/Sdl2KeyMap.cs
Normal file
96
Source/OpenTK/Platform/SDL2/Sdl2KeyMap.cs
Normal file
|
@ -0,0 +1,96 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenTK.Input;
|
||||
|
||||
namespace OpenTK.Platform.SDL2
|
||||
{
|
||||
using Code = SDL.SDL_Keycode;
|
||||
|
||||
class Sdl2KeyMap : Dictionary<SDL.SDL_Keycode, Key>
|
||||
{
|
||||
public Sdl2KeyMap()
|
||||
{
|
||||
Add(Code.SDLK_ESCAPE, Key.Escape);
|
||||
|
||||
// Function keys
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
Add(Code.SDLK_F1 + i, Key.F1 + i);
|
||||
}
|
||||
|
||||
// Number keys (0-9)
|
||||
for (int i = 0; i <= 9; i++)
|
||||
{
|
||||
Add(Code.SDLK_0 + i, Key.Number0 + i);
|
||||
}
|
||||
|
||||
// Letters (A-Z)
|
||||
for (int i = 0; i < 26; i++)
|
||||
{
|
||||
Add(Code.SDLK_a + i, Key.A + i);
|
||||
}
|
||||
|
||||
Add(Code.SDLK_TAB, Key.Tab);
|
||||
Add(Code.SDLK_CAPSLOCK, Key.CapsLock);
|
||||
Add(Code.SDLK_LCTRL, Key.ControlLeft);
|
||||
Add(Code.SDLK_LSHIFT, Key.ShiftLeft);
|
||||
Add(Code.SDLK_LALT, Key.WinLeft);
|
||||
Add(Code.SDLK_MENU, Key.AltLeft);
|
||||
Add(Code.SDLK_SPACE, Key.Space);
|
||||
Add(Code.SDLK_RALT, Key.AltRight);
|
||||
//Add(Code., Key.WinRight);
|
||||
Add(Code.SDLK_APPLICATION, Key.Menu);
|
||||
Add(Code.SDLK_RCTRL, Key.ControlRight);
|
||||
Add(Code.SDLK_RSHIFT, Key.ShiftRight);
|
||||
Add(Code.SDLK_RETURN, Key.Enter);
|
||||
Add(Code.SDLK_BACKSPACE, Key.BackSpace);
|
||||
|
||||
Add(Code.SDLK_SEMICOLON, Key.Semicolon); // Varies by keyboard, ;: on Win2K/US
|
||||
Add(Code.SDLK_SLASH, Key.Slash); // Varies by keyboard, /? on Win2K/US
|
||||
//Add(Code., Key.Tilde); // Varies by keyboard, `~ on Win2K/US
|
||||
Add(Code.SDLK_LEFTBRACKET, Key.BracketLeft); // Varies by keyboard, [{ on Win2K/US
|
||||
Add(Code.SDLK_BACKSLASH, Key.BackSlash); // Varies by keyboard, \| on Win2K/US
|
||||
Add(Code.SDLK_RIGHTBRACKET, Key.BracketRight); // Varies by keyboard, ]} on Win2K/US
|
||||
Add(Code.SDLK_QUOTE, Key.Quote); // Varies by keyboard, '" on Win2K/US
|
||||
Add(Code.SDLK_PLUS, Key.Plus); // Invariant: +
|
||||
Add(Code.SDLK_COMMA, Key.Comma); // Invariant: ,
|
||||
Add(Code.SDLK_MINUS, Key.Minus); // Invariant: -
|
||||
Add(Code.SDLK_PERIOD, Key.Period); // Invariant: .
|
||||
|
||||
Add(Code.SDLK_HOME, Key.Home);
|
||||
Add(Code.SDLK_END, Key.End);
|
||||
Add(Code.SDLK_DELETE, Key.Delete);
|
||||
Add(Code.SDLK_PAGEUP, Key.PageUp);
|
||||
Add(Code.SDLK_PAGEDOWN, Key.PageDown);
|
||||
Add(Code.SDLK_PAUSE, Key.Pause);
|
||||
Add(Code.SDLK_NUMLOCKCLEAR, Key.NumLock);
|
||||
|
||||
Add(Code.SDLK_SCROLLLOCK, Key.ScrollLock);
|
||||
Add(Code.SDLK_PRINTSCREEN, Key.PrintScreen);
|
||||
Add(Code.SDLK_CLEAR, Key.Clear);
|
||||
Add(Code.SDLK_INSERT, Key.Insert);
|
||||
|
||||
Add(Code.SDLK_SLEEP, Key.Sleep);
|
||||
|
||||
// Keypad
|
||||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
Add(Code.SDLK_KP_1 + i, Key.Keypad1 + i);
|
||||
}
|
||||
Add(Code.SDLK_KP_0, Key.Keypad0); // Note: SDL2 goes KP_1..KP_9, then KP_0
|
||||
|
||||
Add(Code.SDLK_KP_DECIMAL, Key.KeypadDecimal);
|
||||
Add(Code.SDLK_KP_PLUS, Key.KeypadAdd);
|
||||
Add(Code.SDLK_KP_MINUS, Key.KeypadSubtract);
|
||||
Add(Code.SDLK_KP_DIVIDE, Key.KeypadDivide);
|
||||
Add(Code.SDLK_KP_MULTIPLY, Key.KeypadMultiply);
|
||||
|
||||
// Navigation
|
||||
Add(Code.SDLK_UP, Key.Up);
|
||||
Add(Code.SDLK_DOWN, Key.Down);
|
||||
Add(Code.SDLK_LEFT, Key.Left);
|
||||
Add(Code.SDLK_RIGHT, Key.Right);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
32
Source/OpenTK/Platform/SDL2/Sdl2Keyboard.cs
Normal file
32
Source/OpenTK/Platform/SDL2/Sdl2Keyboard.cs
Normal file
|
@ -0,0 +1,32 @@
|
|||
using System;
|
||||
using OpenTK.Input;
|
||||
|
||||
namespace OpenTK.Platform.SDL2
|
||||
{
|
||||
class Sdl2Keyboard : IKeyboardDriver2
|
||||
{
|
||||
public Sdl2Keyboard()
|
||||
{
|
||||
}
|
||||
|
||||
#region IKeyboardDriver2 Members
|
||||
|
||||
public KeyboardState GetState()
|
||||
{
|
||||
return new KeyboardState();
|
||||
}
|
||||
|
||||
public KeyboardState GetState(int index)
|
||||
{
|
||||
return new KeyboardState();
|
||||
}
|
||||
|
||||
public string GetDeviceName(int index)
|
||||
{
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
34
Source/OpenTK/Platform/SDL2/Sdl2Mouse.cs
Normal file
34
Source/OpenTK/Platform/SDL2/Sdl2Mouse.cs
Normal file
|
@ -0,0 +1,34 @@
|
|||
using System;
|
||||
using OpenTK.Input;
|
||||
|
||||
namespace OpenTK.Platform.SDL2
|
||||
{
|
||||
class Sdl2Mouse : IMouseDriver2
|
||||
{
|
||||
public Sdl2Mouse()
|
||||
{
|
||||
}
|
||||
|
||||
#region IMouseDriver2 Members
|
||||
|
||||
public MouseState GetState()
|
||||
{
|
||||
int x, y;
|
||||
uint b = SDL.SDL_GetMouseState(out x, out y);
|
||||
return new MouseState();
|
||||
}
|
||||
|
||||
public MouseState GetState(int index)
|
||||
{
|
||||
return new MouseState();
|
||||
}
|
||||
|
||||
public void SetPosition(double x, double y)
|
||||
{
|
||||
//SDL2.mouse
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
637
Source/OpenTK/Platform/SDL2/Sdl2NativeWindow.cs
Normal file
637
Source/OpenTK/Platform/SDL2/Sdl2NativeWindow.cs
Normal file
|
@ -0,0 +1,637 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using OpenTK.Input;
|
||||
|
||||
namespace OpenTK.Platform.SDL2
|
||||
{
|
||||
class Sdl2NativeWindow : INativeWindow, IInputDriver
|
||||
{
|
||||
Sdl2WindowInfo window;
|
||||
bool is_visible;
|
||||
bool is_focused;
|
||||
bool is_cursor_visible = true;
|
||||
bool exists;
|
||||
bool disposed;
|
||||
Icon icon;
|
||||
|
||||
KeyboardDevice keyboard = new KeyboardDevice();
|
||||
MouseDevice mouse = new MouseDevice();
|
||||
IList<KeyboardDevice> keyboards = new List<KeyboardDevice>(1);
|
||||
IList<MouseDevice> mice = new List<MouseDevice>(1);
|
||||
|
||||
static Sdl2KeyMap map = new Sdl2KeyMap();
|
||||
|
||||
public Sdl2NativeWindow(int x, int y, int width, int height, string title, GameWindowFlags options, DisplayDevice device)
|
||||
{
|
||||
var bounds = device.Bounds;
|
||||
var flags = TranslateFlags(options);
|
||||
IntPtr handle = SDL.SDL_CreateWindow(title, bounds.Left + x, bounds.Right + y, width, height, flags);
|
||||
window = new Sdl2WindowInfo(handle, null);
|
||||
|
||||
keyboard.Description = "Standard Windows keyboard";
|
||||
keyboard.NumberOfFunctionKeys = 12;
|
||||
keyboard.NumberOfKeys = 101;
|
||||
keyboard.NumberOfLeds = 3;
|
||||
|
||||
mouse.Description = "Standard Windows mouse";
|
||||
mouse.NumberOfButtons = 3;
|
||||
mouse.NumberOfWheels = 1;
|
||||
|
||||
keyboards.Add(keyboard);
|
||||
mice.Add(mouse);
|
||||
|
||||
exists = true;
|
||||
}
|
||||
|
||||
#region Private Members
|
||||
|
||||
static SDL.SDL_WindowFlags TranslateFlags(GameWindowFlags flags)
|
||||
{
|
||||
switch (flags)
|
||||
{
|
||||
case GameWindowFlags.Fullscreen:
|
||||
return SDL.SDL_WindowFlags.SDL_WINDOW_FULLSCREEN;
|
||||
|
||||
default:
|
||||
return (SDL.SDL_WindowFlags)0;
|
||||
}
|
||||
}
|
||||
|
||||
static Key TranslateKey(SDL.SDL_Keycode key)
|
||||
{
|
||||
Key result = Key.Unknown;
|
||||
if (map.ContainsKey(key))
|
||||
{
|
||||
result = map[key];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ProcessWindowEvent(SDL.SDL_WindowEvent e)
|
||||
{
|
||||
switch (e.windowEvent)
|
||||
{
|
||||
case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_CLOSE:
|
||||
Closed(this, EventArgs.Empty);
|
||||
break;
|
||||
|
||||
case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_ENTER:
|
||||
MouseEnter(this, EventArgs.Empty);
|
||||
break;
|
||||
|
||||
case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_LEAVE:
|
||||
MouseLeave(this, EventArgs.Empty);
|
||||
break;
|
||||
|
||||
case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_EXPOSED:
|
||||
// do nothing
|
||||
break;
|
||||
|
||||
case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_FOCUS_GAINED:
|
||||
is_focused = true;
|
||||
FocusedChanged(this, EventArgs.Empty);
|
||||
break;
|
||||
|
||||
case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_FOCUS_LOST:
|
||||
is_focused = false;
|
||||
FocusedChanged(this, EventArgs.Empty);
|
||||
break;
|
||||
|
||||
case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_HIDDEN:
|
||||
is_visible = false;
|
||||
VisibleChanged(this, EventArgs.Empty);
|
||||
break;
|
||||
|
||||
case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_SHOWN:
|
||||
is_visible = true;
|
||||
VisibleChanged(this, EventArgs.Empty);
|
||||
break;
|
||||
|
||||
case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_MAXIMIZED:
|
||||
case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_MINIMIZED:
|
||||
case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_RESTORED:
|
||||
WindowStateChanged(this, EventArgs.Empty);
|
||||
break;
|
||||
|
||||
case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_MOVED:
|
||||
Move(this, EventArgs.Empty);
|
||||
break;
|
||||
|
||||
case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_RESIZED:
|
||||
case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_SIZE_CHANGED:
|
||||
Resize(this, EventArgs.Empty);
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug.Print("SDL2 unhandled event: {0}", e.type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region INativeWindow Members
|
||||
|
||||
public event EventHandler<EventArgs> Move = delegate { };
|
||||
public event EventHandler<EventArgs> Resize = delegate { };
|
||||
public event EventHandler<System.ComponentModel.CancelEventArgs> Closing = delegate { };
|
||||
public event EventHandler<EventArgs> Closed = delegate { };
|
||||
public event EventHandler<EventArgs> Disposed = delegate { };
|
||||
public event EventHandler<EventArgs> IconChanged = delegate { };
|
||||
public event EventHandler<EventArgs> TitleChanged = delegate { };
|
||||
public event EventHandler<EventArgs> VisibleChanged = delegate { };
|
||||
public event EventHandler<EventArgs> FocusedChanged = delegate { };
|
||||
public event EventHandler<EventArgs> WindowBorderChanged = delegate { };
|
||||
public event EventHandler<EventArgs> WindowStateChanged = delegate { };
|
||||
public event EventHandler<KeyboardKeyEventArgs> KeyDown = delegate { };
|
||||
public event EventHandler<KeyPressEventArgs> KeyPress = delegate { };
|
||||
public event EventHandler<KeyboardKeyEventArgs> KeyUp = delegate { };
|
||||
public event EventHandler<EventArgs> MouseEnter = delegate { };
|
||||
public event EventHandler<EventArgs> MouseLeave = delegate { };
|
||||
|
||||
public void Close()
|
||||
{
|
||||
if (Exists)
|
||||
{
|
||||
Debug.Print("SDL2 destroying window {0}", window.Handle);
|
||||
SDL.SDL_Event e = new SDL.SDL_Event();
|
||||
e.type = SDL.SDL_EventType.SDL_QUIT;
|
||||
SDL.SDL_PushEvent(ref e);
|
||||
SDL.SDL_PumpEvents();
|
||||
}
|
||||
}
|
||||
|
||||
public void ProcessEvents()
|
||||
{
|
||||
SDL.SDL_Event e;
|
||||
while (SDL.SDL_PollEvent(out e) != 0)
|
||||
{
|
||||
switch (e.type)
|
||||
{
|
||||
case SDL.SDL_EventType.SDL_KEYDOWN:
|
||||
case SDL.SDL_EventType.SDL_KEYUP:
|
||||
bool key_pressed = e.key.state == SDL.SDL_PRESSED;
|
||||
var key = e.key.keysym;
|
||||
keyboard.SetKey(TranslateKey(key.sym), (uint)key.scancode, key_pressed);
|
||||
break;
|
||||
|
||||
case SDL.SDL_EventType.SDL_MOUSEBUTTONDOWN:
|
||||
case SDL.SDL_EventType.SDL_MOUSEBUTTONUP:
|
||||
bool button_pressed = e.button.state == SDL.SDL_PRESSED;
|
||||
switch (e.button.button)
|
||||
{
|
||||
case (byte)SDL.SDL_BUTTON_LEFT:
|
||||
mouse[MouseButton.Left] = button_pressed;
|
||||
break;
|
||||
|
||||
case (byte)SDL.SDL_BUTTON_MIDDLE:
|
||||
mouse[MouseButton.Middle] = button_pressed;
|
||||
break;
|
||||
|
||||
case (byte)SDL.SDL_BUTTON_RIGHT:
|
||||
mouse[MouseButton.Right] = button_pressed;
|
||||
break;
|
||||
|
||||
case (byte)SDL.SDL_BUTTON_X1:
|
||||
mouse[MouseButton.Button1] = button_pressed;
|
||||
break;
|
||||
|
||||
case (byte)SDL.SDL_BUTTON_X2:
|
||||
mouse[MouseButton.Button2] = button_pressed;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case SDL.SDL_EventType.SDL_MOUSEMOTION:
|
||||
if (CursorVisible)
|
||||
{
|
||||
mouse.Position = new Point(e.motion.x, e.motion.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
mouse.Position = new Point(mouse.X + e.motion.x, mouse.Y + e.motion.y);
|
||||
}
|
||||
break;
|
||||
|
||||
case SDL.SDL_EventType.SDL_MOUSEWHEEL:
|
||||
mouse.Wheel += e.wheel.y;
|
||||
break;
|
||||
|
||||
case SDL.SDL_EventType.SDL_QUIT:
|
||||
var close_args = new System.ComponentModel.CancelEventArgs();
|
||||
Closing(this, close_args);
|
||||
if (!close_args.Cancel)
|
||||
{
|
||||
exists = false;
|
||||
SDL.SDL_DestroyWindow(window.Handle);
|
||||
window.Handle = IntPtr.Zero;
|
||||
}
|
||||
break;
|
||||
|
||||
case SDL.SDL_EventType.SDL_WINDOWEVENT:
|
||||
ProcessWindowEvent(e.window);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Point PointToClient(Point point)
|
||||
{
|
||||
var origin = DisplayDevice.Default.Bounds.Location;
|
||||
var client = Location;
|
||||
return new Point(point.X + client.X - origin.X, point.Y + client.Y - origin.Y);
|
||||
}
|
||||
|
||||
public Point PointToScreen(Point point)
|
||||
{
|
||||
var origin = DisplayDevice.Default.Bounds.Location;
|
||||
var client = Location;
|
||||
return new Point(point.X + origin.X - client.X, point.Y + origin.Y - client.Y);
|
||||
}
|
||||
|
||||
public Icon Icon
|
||||
{
|
||||
get
|
||||
{
|
||||
return icon;
|
||||
}
|
||||
set
|
||||
{
|
||||
IntPtr surface = IntPtr.Zero;
|
||||
if (value != null)
|
||||
{
|
||||
using (Bitmap bmp = value.ToBitmap())
|
||||
{
|
||||
var data = bmp.LockBits(
|
||||
new Rectangle(0, 0, value.Width, value.Height),
|
||||
ImageLockMode.ReadWrite,
|
||||
PixelFormat.Format32bppArgb);
|
||||
|
||||
surface = SDL.SDL_CreateRGBSurfaceFrom(
|
||||
data.Scan0, data.Width, data.Height, 32, data.Height,
|
||||
0x0000ff00u, 0x00ff0000u, 0xff000000u, 0x000000ffu);
|
||||
|
||||
bmp.UnlockBits(data);
|
||||
}
|
||||
}
|
||||
SDL.SDL_SetWindowIcon(window.Handle, surface);
|
||||
icon = value;
|
||||
IconChanged(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
public string Title
|
||||
{
|
||||
get
|
||||
{
|
||||
return SDL.SDL_GetWindowTitle(window.Handle);
|
||||
}
|
||||
set
|
||||
{
|
||||
SDL.SDL_SetWindowTitle(window.Handle, value);
|
||||
}
|
||||
}
|
||||
|
||||
public bool Focused
|
||||
{
|
||||
get
|
||||
{
|
||||
return is_focused;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Visible
|
||||
{
|
||||
get
|
||||
{
|
||||
return is_visible;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
SDL.SDL_ShowWindow(window.Handle);
|
||||
else
|
||||
SDL.SDL_HideWindow(window.Handle);
|
||||
}
|
||||
}
|
||||
|
||||
public bool Exists
|
||||
{
|
||||
get
|
||||
{
|
||||
return exists;
|
||||
}
|
||||
}
|
||||
|
||||
public IWindowInfo WindowInfo
|
||||
{
|
||||
get
|
||||
{
|
||||
return window;
|
||||
}
|
||||
}
|
||||
|
||||
public WindowState WindowState
|
||||
{
|
||||
get
|
||||
{
|
||||
var flags = (SDL.SDL_WindowFlags)SDL.SDL_GetWindowFlags(window.Handle);
|
||||
switch (flags)
|
||||
{
|
||||
case SDL.SDL_WindowFlags.SDL_WINDOW_FULLSCREEN:
|
||||
case SDL.SDL_WindowFlags.SDL_WINDOW_FULLSCREEN_DESKTOP:
|
||||
return WindowState.Fullscreen;
|
||||
|
||||
case SDL.SDL_WindowFlags.SDL_WINDOW_MAXIMIZED:
|
||||
return WindowState.Maximized;
|
||||
|
||||
case SDL.SDL_WindowFlags.SDL_WINDOW_MINIMIZED:
|
||||
return WindowState.Minimized;
|
||||
|
||||
default:
|
||||
return WindowState.Normal;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case WindowState.Fullscreen:
|
||||
if (SDL.SDL_SetWindowFullscreen(window.Handle, (uint)SDL.SDL_WindowFlags.SDL_WINDOW_FULLSCREEN) < 0)
|
||||
{
|
||||
SDL.SDL_SetWindowFullscreen(window.Handle, (uint)SDL.SDL_WindowFlags.SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
}
|
||||
break;
|
||||
|
||||
case WindowState.Maximized:
|
||||
SDL.SDL_MaximizeWindow(window.Handle);
|
||||
break;
|
||||
|
||||
case WindowState.Minimized:
|
||||
SDL.SDL_MinimizeWindow(window.Handle);
|
||||
break;
|
||||
|
||||
case WindowState.Normal:
|
||||
SDL.SDL_RestoreWindow(window.Handle);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public WindowBorder WindowBorder
|
||||
{
|
||||
get
|
||||
{
|
||||
var flags = (SDL.SDL_WindowFlags)SDL.SDL_GetWindowFlags(window.Handle);
|
||||
switch (flags)
|
||||
{
|
||||
case SDL.SDL_WindowFlags.SDL_WINDOW_BORDERLESS:
|
||||
return WindowBorder.Hidden;
|
||||
|
||||
case SDL.SDL_WindowFlags.SDL_WINDOW_RESIZABLE:
|
||||
return WindowBorder.Resizable;
|
||||
|
||||
default:
|
||||
return WindowBorder.Fixed;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case WindowBorder.Resizable:
|
||||
SDL.SDL_SetWindowBordered(window.Handle, SDL.SDL_bool.SDL_TRUE);
|
||||
break;
|
||||
|
||||
case WindowBorder.Hidden:
|
||||
SDL.SDL_SetWindowBordered(window.Handle, SDL.SDL_bool.SDL_TRUE);
|
||||
break;
|
||||
|
||||
case WindowBorder.Fixed:
|
||||
Trace.WriteLine("SDL2 cannot change to fixed-size windows at runtime.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Rectangle Bounds
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Rectangle(Location, Size);
|
||||
}
|
||||
set
|
||||
{
|
||||
Size = value.Size;
|
||||
Location = value.Location;
|
||||
}
|
||||
}
|
||||
|
||||
public Point Location
|
||||
{
|
||||
get
|
||||
{
|
||||
int x, y;
|
||||
SDL.SDL_GetWindowPosition(window.Handle, out x, out y);
|
||||
return new Point(x, y);
|
||||
}
|
||||
set
|
||||
{
|
||||
SDL.SDL_SetWindowPosition(window.Handle, value.X, value.Y);
|
||||
}
|
||||
}
|
||||
|
||||
public Size Size
|
||||
{
|
||||
get
|
||||
{
|
||||
int w, h;
|
||||
SDL.SDL_GetWindowSize(window.Handle, out w, out h);
|
||||
return new Size(w, h);
|
||||
}
|
||||
set
|
||||
{
|
||||
SDL.SDL_SetWindowSize(window.Handle, value.Width, value.Height);
|
||||
}
|
||||
}
|
||||
|
||||
public int X
|
||||
{
|
||||
get
|
||||
{
|
||||
return Location.X;
|
||||
}
|
||||
set
|
||||
{
|
||||
Location = new Point(value, Y);
|
||||
}
|
||||
}
|
||||
|
||||
public int Y
|
||||
{
|
||||
get
|
||||
{
|
||||
return Location.Y;
|
||||
}
|
||||
set
|
||||
{
|
||||
Location = new Point(X, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int Width
|
||||
{
|
||||
get
|
||||
{
|
||||
return Size.Width;
|
||||
}
|
||||
set
|
||||
{
|
||||
Size = new Size(value, Height);
|
||||
}
|
||||
}
|
||||
|
||||
public int Height
|
||||
{
|
||||
get
|
||||
{
|
||||
return Size.Height;
|
||||
}
|
||||
set
|
||||
{
|
||||
Size = new Size(Width, value);
|
||||
}
|
||||
}
|
||||
|
||||
public Rectangle ClientRectangle
|
||||
{
|
||||
get
|
||||
{
|
||||
// Todo: SDL2 does not have any APIs to get
|
||||
// the border size or the bounds of the window
|
||||
// (everything is defined in terms of the client
|
||||
// area)
|
||||
return Bounds;
|
||||
}
|
||||
set
|
||||
{
|
||||
Bounds = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Size ClientSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return Size;
|
||||
}
|
||||
set
|
||||
{
|
||||
Size = value;
|
||||
}
|
||||
}
|
||||
|
||||
public IInputDriver InputDriver
|
||||
{
|
||||
get
|
||||
{
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public bool CursorVisible
|
||||
{
|
||||
get
|
||||
{
|
||||
return is_cursor_visible;
|
||||
}
|
||||
set
|
||||
{
|
||||
SDL.SDL_ShowCursor(value ? 1 : 0);
|
||||
is_cursor_visible = value;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IInputDriver Members
|
||||
|
||||
public void Poll()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IJoystickDriver Members
|
||||
|
||||
public IList<JoystickDevice> Joysticks
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IMouseDriver Members
|
||||
|
||||
public IList<MouseDevice> Mouse
|
||||
{
|
||||
get
|
||||
{
|
||||
return mice;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IKeyboardDriver Members
|
||||
|
||||
public IList<KeyboardDevice> Keyboard
|
||||
{
|
||||
get
|
||||
{
|
||||
return keyboards;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable implementation
|
||||
|
||||
void Dispose(bool manual)
|
||||
{
|
||||
if (manual)
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Print("[Warning] INativeWindow leaked ({0}). Did you forget to call INativeWindow.Dispose()?", this);
|
||||
}
|
||||
disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~Sdl2NativeWindow()
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
29
Source/OpenTK/Platform/SDL2/Sdl2WindowInfo.cs
Normal file
29
Source/OpenTK/Platform/SDL2/Sdl2WindowInfo.cs
Normal file
|
@ -0,0 +1,29 @@
|
|||
using System;
|
||||
|
||||
namespace OpenTK.Platform.SDL2
|
||||
{
|
||||
class Sdl2WindowInfo : IWindowInfo
|
||||
{
|
||||
public IntPtr Handle { get; set; }
|
||||
public Sdl2WindowInfo Parent { get; set; }
|
||||
|
||||
public Sdl2WindowInfo()
|
||||
{
|
||||
}
|
||||
|
||||
public Sdl2WindowInfo(IntPtr handle, Sdl2WindowInfo parent)
|
||||
{
|
||||
Handle = handle;
|
||||
Parent = parent;
|
||||
}
|
||||
|
||||
#region IDisposable implementation
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in a new issue