From: Jonas Boesch Date: Tue, 21 Apr 2015 14:09:29 +0000 (+0200) Subject: Added AngleWindowInfo and AnglePlatformFactory X-Git-Tag: v3.0.0~113^2~3^2~4 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9d29c8c19bbfa6cc5231c7f82f1333f36b2724c9;p=platform%2Fcore%2Fcsapi%2Fopentk.git Added AngleWindowInfo and AnglePlatformFactory Both WindowInfo and PlatformFactory wrap the actual platform-specific WindowInfo and PlatformFactory. For offscreen rendering, AngleWindowInfo can be used with a DummyWindowInfo. The API to add additional surfaces was added to IAngleWindowInfo, since all those calls need the Display parameter that is only available on EglWindowInfo (which is not exposed to users). --- diff --git a/Source/OpenTK/Platform/Egl/AngleWindowInfo.cs b/Source/OpenTK/Platform/Egl/AngleWindowInfo.cs new file mode 100644 index 0000000..f062a2d --- /dev/null +++ b/Source/OpenTK/Platform/Egl/AngleWindowInfo.cs @@ -0,0 +1,183 @@ +using System; +using OpenTK.Graphics; +using OpenTK.Platform.Windows; + +namespace OpenTK.Platform.Egl +{ + using EGLSurface = IntPtr; + /// + /// A window info for angle. + /// + public interface IAngleWindowInfo : IWindowInfo + { + /// + /// Query the underlying platform pointer / handle for this window's + /// default surface or IntPtr.Zero + /// + IntPtr QuerySurfacePointer(); + /// + /// Create an additional rendering surface that shares the display + /// of this window. + /// + /// width in pixels + /// height in pixels + /// A reference to the new surface + EGLSurface CreateSurface(int width, int height); + /// + /// Destroy a surface created with CreateSurface and clears the passed reference. + /// + /// Reference to the surface. + void DestroySurface(ref EGLSurface surface); + /// + /// MakeCurrent the custom surface created with CreateSurface. + /// + /// Reference to the surface. + void MakeCurrent(EGLSurface surface); + /// + /// Query the underlying platform pointer / handle for an EGLSurface + /// created with CreateSurface. + /// + /// + IntPtr QuerySurfacePointer(EGLSurface surface); + } + + internal interface IAngleWindowInfoInternal : IAngleWindowInfo + { + IWindowInfo PlatformWindow { get; } + IntPtr Display { get; } + IntPtr Surface { get; } + EglContext EglContext { get; set; } + EglWindowInfo EglWindowInfo { get; set; } + IntPtr DeviceContext { get; } + } + + internal class AngleWindowInfo : IAngleWindowInfoInternal + { + private readonly IWindowInfo _platform_window; + private bool _disposed; + + public AngleWindowInfo(IWindowInfo platform_window) + { + _platform_window = platform_window; + } + + public IWindowInfo PlatformWindow + { + get { return _platform_window; } + } + + public IWindowInfo WindowInfo + { + get { return EglWindowInfo; } + } + + public IntPtr DeviceContext + { + get + { + var win_win = _platform_window as WinWindowInfo; + if (win_win != null) + { + return win_win.DeviceContext; + } + return IntPtr.Zero; + } + } + + public EglContext EglContext { get; set; } + public EglWindowInfo EglWindowInfo { get; set; } + + public IntPtr Display + { + get { return EglWindowInfo.Display; } + } + + public IntPtr Surface + { + get { return EglWindowInfo.Surface; } + } + + public void Dispose() + { + Dispose(false); + } + + public IntPtr Handle + { + get { return _platform_window.Handle; } + } + + ~AngleWindowInfo() + { + Dispose(true); + } + + private void Dispose(bool called_from_finalizer) + { + if (_disposed) + { + return; + } + if (!called_from_finalizer) + { + _platform_window.Dispose(); + } + // dispose unmanaged + + _disposed = true; + GC.SuppressFinalize(this); + } + + public IntPtr QuerySurfacePointer() + { + return QuerySurfacePointer(Surface); + } + + public EGLSurface CreateSurface(int width, int height) + { + IntPtr surface; + EglWindowInfo.CreatePbufferSurface( + EglContext.GraphicsMode.Index.Value, + width, height, + out surface); + return surface; + } + + public void DestroySurface(ref EGLSurface surface) + { + EglWindowInfo.DestroySurface(ref surface); + } + + public void MakeCurrent(EGLSurface surface) + { + Egl.MakeCurrent(Display, surface, surface, EglContext.HandleAsEGLContext); + } + + public IntPtr QuerySurfacePointer(IntPtr surface) + { + if (UsesDirect3DBackend()) + { + return QuerySurfacePointer(surface, + Egl.EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE); + } + return IntPtr.Zero; + } + + private IntPtr QuerySurfacePointer(IntPtr surface, int attrib) + { + IntPtr surface_pointer; + if (Egl.QuerySurfacePointerANGLE( + Display, surface, attrib, out surface_pointer)) + { + return surface_pointer; + } + return IntPtr.Zero; + } + + private bool UsesDirect3DBackend() + { + var d3d_flags = GraphicsContextFlags.AngleD3D9 | GraphicsContextFlags.AngleD3D11; + return ((EglContext.GraphicsContextFlags & d3d_flags) != 0); + } + } +} \ No newline at end of file diff --git a/Source/OpenTK/Platform/Egl/EglAnglePlatformFactory.cs b/Source/OpenTK/Platform/Egl/EglAnglePlatformFactory.cs new file mode 100644 index 0000000..6d5f694 --- /dev/null +++ b/Source/OpenTK/Platform/Egl/EglAnglePlatformFactory.cs @@ -0,0 +1,172 @@ +#region License + +// +// The Open Toolkit Library License +// +// Copyright (c) 2006 - 2015 the Open Toolkit library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#endregion + +using System; +using OpenTK.Graphics; +using OpenTK.Input; + +namespace OpenTK.Platform.Egl +{ + internal class EglAnglePlatformFactory : PlatformFactoryBase + { + private readonly IPlatformFactory _platform_factory; + #region Public Members + + public EglAnglePlatformFactory(IPlatformFactory platform_factory) + { + _platform_factory = platform_factory; + } + + public override INativeWindow CreateNativeWindow(int x, int y, int width, int height, string title, GraphicsMode mode, + GameWindowFlags options, DisplayDevice device) + { + return _platform_factory.CreateNativeWindow(x, y, width, height, title, + mode, options, device); + } + + public override IDisplayDeviceDriver CreateDisplayDeviceDriver() + { + return _platform_factory.CreateDisplayDeviceDriver(); + } + + public override IGraphicsContext CreateGLContext(GraphicsMode mode, IWindowInfo window, + IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags) + { + var angle_window = (IAngleWindowInfoInternal) window; + var egl_window = CreateWindowInfo(angle_window, major, flags); + var egl_context = new EglWinContext(mode, egl_window, shareContext, major, minor, flags); + angle_window.EglContext = egl_context; + return egl_context; + } + + public override IGraphicsContext CreateGLContext(ContextHandle handle, IWindowInfo window, + IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags) + { + var angle_window = (IAngleWindowInfoInternal) window; + var egl_window = CreateWindowInfo(angle_window, major, flags); + var egl_context = new EglWinContext(handle, egl_window, shareContext, major, minor, flags); + angle_window.EglContext = egl_context; + return egl_context; + } + + public override GraphicsContext.GetCurrentContextDelegate CreateGetCurrentGraphicsContext() + { + return (GraphicsContext.GetCurrentContextDelegate)delegate + { + return new ContextHandle(Platform.Egl.Egl.GetCurrentContext()); + }; + } + + public override IKeyboardDriver2 CreateKeyboardDriver() + { + return _platform_factory.CreateKeyboardDriver(); + } + + public override IMouseDriver2 CreateMouseDriver() + { + return _platform_factory.CreateMouseDriver(); + } + + public override IJoystickDriver2 CreateJoystickDriver() + { + return _platform_factory.CreateJoystickDriver(); + } + + #endregion + + #region Private Members + + private static bool FlagEnabled(GraphicsContextFlags flags, GraphicsContextFlags flag) + { + return (flags & flag) != 0; + } + + private EglWindowInfo CreateWindowInfo(IAngleWindowInfoInternal window_info, + int major, GraphicsContextFlags flags) + { + var egl_display = GetAngleDisplay(window_info.DeviceContext, flags, major); + var egl_window = new EglWindowInfo(window_info.Handle, egl_display); + window_info.EglWindowInfo = egl_window; + return egl_window; + } + + private IntPtr GetAngleDisplay(IntPtr dc, GraphicsContextFlags flags, int major) + { + // default to D3D9 for ES2, but use D3D11 for ES3 as required by Angle. + var platform_type = major == 2 + ? Platform.Egl.Egl.PLATFORM_ANGLE_TYPE_D3D9 + : Platform.Egl.Egl.PLATFORM_ANGLE_TYPE_D3D11; + if (FlagEnabled(flags, GraphicsContextFlags.AngleD3D11)) + { + platform_type = Platform.Egl.Egl.PLATFORM_ANGLE_TYPE_D3D11; + } + else if (FlagEnabled(flags, GraphicsContextFlags.AngleD3D9)) + { + platform_type = Platform.Egl.Egl.PLATFORM_ANGLE_TYPE_D3D9; + } + else if (FlagEnabled(flags, GraphicsContextFlags.AngleOpenGL)) + { + platform_type = Platform.Egl.Egl.PLATFORM_ANGLE_TYPE_OPENGL; + } + else + { + // make sure the correct flag is set. + switch (platform_type) + { + case Platform.Egl.Egl.PLATFORM_ANGLE_TYPE_D3D9: + flags |= GraphicsContextFlags.AngleD3D9; + break; + case Platform.Egl.Egl.PLATFORM_ANGLE_TYPE_D3D11: + flags |= GraphicsContextFlags.AngleD3D11; + break; + case Platform.Egl.Egl.PLATFORM_ANGLE_TYPE_OPENGL: + flags |= GraphicsContextFlags.AngleOpenGL; + break; + } + } + + var attribs = new[] + { + Platform.Egl.Egl.PLATFORM_ANGLE_TYPE, platform_type, + Platform.Egl.Egl.PLATFORM_ANGLE_MAX_VERSION_MAJOR, Platform.Egl.Egl.DONT_CARE, + Platform.Egl.Egl.PLATFORM_ANGLE_MAX_VERSION_MINOR, Platform.Egl.Egl.DONT_CARE, + Platform.Egl.Egl.PLATFORM_ANGLE_DEVICE_TYPE, Platform.Egl.Egl.PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE, + Platform.Egl.Egl.NONE + }; + + return Platform.Egl.Egl.GetPlatformDisplay( + Platform.Egl.Egl.PLATFORM_ANGLE, + dc, + attribs + ); + } + + #endregion + } +} \ No newline at end of file diff --git a/src/OpenTK/Graphics/GraphicsContext.cs b/src/OpenTK/Graphics/GraphicsContext.cs index 35a5d35..da3c9f6 100644 --- a/src/OpenTK/Graphics/GraphicsContext.cs +++ b/src/OpenTK/Graphics/GraphicsContext.cs @@ -145,8 +145,12 @@ namespace OpenTK.Graphics IPlatformFactory factory = null; switch ((flags & GraphicsContextFlags.Embedded) == GraphicsContextFlags.Embedded) { - case false: factory = Factory.Default; break; - case true: factory = Factory.Embedded; break; + case false: + factory = Factory.Default; + break; + case true: + factory = use_angle ? Factory.Angle : Factory.Embedded; + break; } // Note: this approach does not allow us to mix native and EGL contexts in the same process. diff --git a/src/OpenTK/OpenTK.csproj b/src/OpenTK/OpenTK.csproj index 1476054..758e53a 100644 --- a/src/OpenTK/OpenTK.csproj +++ b/src/OpenTK/OpenTK.csproj @@ -133,10 +133,12 @@ + + diff --git a/src/OpenTK/Platform/Factory.cs b/src/OpenTK/Platform/Factory.cs index 9e5eb66..35839e0 100644 --- a/src/OpenTK/Platform/Factory.cs +++ b/src/OpenTK/Platform/Factory.cs @@ -29,6 +29,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Text; +using OpenTK.Platform.Egl; namespace OpenTK.Platform { @@ -40,7 +41,7 @@ namespace OpenTK.Platform #region Fields bool disposed; - static IPlatformFactory default_implementation, embedded_implementation; + static IPlatformFactory default_implementation, embedded_implementation, angle_implementation; #endregion @@ -102,11 +103,13 @@ namespace OpenTK.Platform else if (Configuration.RunningOnAndroid) Embedded = new Android.AndroidFactory(); #endif else Embedded = new UnsupportedPlatform(); + Angle = new EglAnglePlatformFactory(Embedded); } #endif else { Embedded = new UnsupportedPlatform(); + Angle = Embedded; } if (Default is UnsupportedPlatform && !(Embedded is UnsupportedPlatform)) @@ -129,6 +132,12 @@ namespace OpenTK.Platform private set { embedded_implementation = value; } } + public static IPlatformFactory Angle + { + get { return angle_implementation; } + private set { angle_implementation = value; } + } + #endregion #region IPlatformFactory Members diff --git a/src/OpenTK/Platform/Utilities.cs b/src/OpenTK/Platform/Utilities.cs index 2a531f6..6746b39 100644 --- a/src/OpenTK/Platform/Utilities.cs +++ b/src/OpenTK/Platform/Utilities.cs @@ -13,6 +13,7 @@ using System.Runtime.InteropServices; using System.Reflection; using System.Diagnostics; using OpenTK.Graphics; +using OpenTK.Platform.Egl; #endregion @@ -393,6 +394,22 @@ namespace OpenTK.Platform #endregion + #region + + /// + /// Creates an IWindowInfo instance for Angle rendering, based on + /// supplied platform window (e.g. a window created with + /// CreateWindowsWindowInfo, or CreateDummyWindowInfo). + /// + /// + /// + public static IAngleWindowInfo CreateAngleWindowInfo(IWindowInfo platform_window) + { + return new AngleWindowInfo(platform_window); + } + + #endregion + #endregion #region RelaxGraphicsMode