From df66598182e4a24e4d9f68a6218dcd95e070d605 Mon Sep 17 00:00:00 2001 From: Jonas Boesch Date: Tue, 21 Apr 2015 16:08:50 +0200 Subject: [PATCH] Added Angle-related enums and definitions + GraphicsContextFlags now has Angle and Offscreen flags. + Egl now has PLATFORM_ANGLE related const ints. + Added eglGetPlatformDisplayEXT p/invoke definition + Added eglQuerySurfacePointerANGLE p/invoke definition + EglWindowInfo.CreatePbufferSurface was commented out. Enabled and fixed it. + GraphicsContextFlags.Offscreen will make the context create a PbufferSurface instead of a WindowSurface in EglContext + SurfaceType enum to select surface type for SelectGraphicsMode --- Source/OpenTK/Platform/Egl/EglAngle.cs | 42 ++++++++++++++++++++ src/OpenTK/Graphics/GraphicsContext.cs | 12 ++++++ src/OpenTK/Graphics/GraphicsContextFlags.cs | 26 ++++++++++++- src/OpenTK/OpenTK.csproj | 1 + src/OpenTK/Platform/Egl/Egl.cs | 11 ++++++ src/OpenTK/Platform/Egl/EglContext.cs | 41 ++++++++++++++++---- src/OpenTK/Platform/Egl/EglGraphicsMode.cs | 17 ++++++-- src/OpenTK/Platform/Egl/EglWindowInfo.cs | 60 +++++++++++++++++++++++++---- 8 files changed, 191 insertions(+), 19 deletions(-) create mode 100644 Source/OpenTK/Platform/Egl/EglAngle.cs diff --git a/Source/OpenTK/Platform/Egl/EglAngle.cs b/Source/OpenTK/Platform/Egl/EglAngle.cs new file mode 100644 index 0000000..9cf708e --- /dev/null +++ b/Source/OpenTK/Platform/Egl/EglAngle.cs @@ -0,0 +1,42 @@ +using System; +using System.Runtime.InteropServices; + +namespace OpenTK.Platform.Egl +{ + using EGLDisplay = IntPtr; + using EGLNativeDisplayType = IntPtr; + using EGLSurface = IntPtr; + using ShareHandle = IntPtr; + + static partial class Egl + { + // See + // - ANGLE_platform_angle + // - ANGLE_platform_angle_d3d + // - ANGLE_platform_angle_opengl + public const int PLATFORM_ANGLE = 0x3202; + public const int PLATFORM_ANGLE_TYPE = 0x3203; + public const int PLATFORM_ANGLE_MAX_VERSION_MAJOR = 0x3204; + public const int PLATFORM_ANGLE_MAX_VERSION_MINOR = 0x3205; + public const int PLATFORM_ANGLE_TYPE_DEFAULT = 0x3206; + public const int PLATFORM_ANGLE_TYPE_D3D9 = 0x3207; + public const int PLATFORM_ANGLE_TYPE_D3D11 = 0x3208; + public const int PLATFORM_ANGLE_DEVICE_TYPE = 0x3209; + public const int PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE = 0x320A; + public const int PLATFORM_ANGLE_DEVICE_TYPE_WARP = 0x320B; + public const int PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE = 0x320C; + public const int PLATFORM_ANGLE_TYPE_OPENGL = 0x320D; + public const int PLATFORM_ANGLE_TYPE_OPENGLES = 0x320E; + // See EGL_ANGLE_surface_d3d_texture_2d_share_handle + public const int EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE = 0x3200; + + [DllImport("libEGL.dll", EntryPoint = "eglGetPlatformDisplayEXT")] + public static extern EGLDisplay GetPlatformDisplay(int platform, EGLNativeDisplayType display_id, + int[] attrib_list); + + [DllImport("libEGL.dll", EntryPoint = "eglQuerySurfacePointerANGLE")] + public static extern bool QuerySurfacePointerANGLE(EGLDisplay display, EGLSurface surface, + int attribute, out IntPtr value); + + } +} \ No newline at end of file diff --git a/src/OpenTK/Graphics/GraphicsContext.cs b/src/OpenTK/Graphics/GraphicsContext.cs index d12e360..35a5d35 100644 --- a/src/OpenTK/Graphics/GraphicsContext.cs +++ b/src/OpenTK/Graphics/GraphicsContext.cs @@ -112,6 +112,18 @@ namespace OpenTK.Graphics if (minor < 0) minor = 0; + // Angle needs an embedded context + var use_angle_flag = GraphicsContextFlags.Angle + | GraphicsContextFlags.AngleD3D9 + | GraphicsContextFlags.AngleD3D11 + | GraphicsContextFlags.AngleOpenGL; + var use_angle = false; + if ((flags & use_angle_flag) != 0) + { + flags |= GraphicsContextFlags.Embedded; + use_angle = true; + } + Debug.Print("Creating GraphicsContext."); try { diff --git a/src/OpenTK/Graphics/GraphicsContextFlags.cs b/src/OpenTK/Graphics/GraphicsContextFlags.cs index a7ee2f5..a7df6e1 100644 --- a/src/OpenTK/Graphics/GraphicsContextFlags.cs +++ b/src/OpenTK/Graphics/GraphicsContextFlags.cs @@ -56,6 +56,30 @@ namespace OpenTK.Graphics /// /// Indicates that this GraphicsContext is targeting OpenGL|ES. /// - Embedded = 0x0004 + Embedded = 0x0004, + /// + /// Indicates that this GraphicsContext is intended for offscreen rendering. + /// + Offscreen = 0x0008, + /// + /// Indicates that this GraphicsContext is targeting OpenGL|ES via Angle + /// and that angle-specific extensions are available. + /// + Angle = 0x0010, + /// + /// Indicates that this GraphicsContext is targeting OpenGL|ES via Angle + /// and uses Direct3D9 as rendering backend. + /// + AngleD3D9 = 0x0020, + /// + /// Indicates that this GraphicsContext is targeting OpenGL|ES via Angle + /// and uses Direct3D11 as rendering backend. + /// + AngleD3D11 = 0x0040, + /// + /// Indicates that this GraphicsContext is targeting OpenGL|ES via Angle + /// and uses OpenGL as rendering backend. + /// + AngleOpenGL = 0x0080, } } diff --git a/src/OpenTK/OpenTK.csproj b/src/OpenTK/OpenTK.csproj index aaa0989..1476054 100644 --- a/src/OpenTK/OpenTK.csproj +++ b/src/OpenTK/OpenTK.csproj @@ -134,6 +134,7 @@ + diff --git a/src/OpenTK/Platform/Egl/Egl.cs b/src/OpenTK/Platform/Egl/Egl.cs index 118054d..df39581 100644 --- a/src/OpenTK/Platform/Egl/Egl.cs +++ b/src/OpenTK/Platform/Egl/Egl.cs @@ -78,6 +78,17 @@ namespace OpenTK.Platform.Egl CONTEXT_LOST = 12302, } + enum SurfaceType + { + PBUFFER_BIT = 0x0001, + PIXMAP_BIT = 0x0002, + WINDOW_BIT = 0x0004, + VG_COLORSPACE_LINEAR_BIT = 0x0020, + VG_ALPHA_FORMAT_PRE_BIT = 0x0040, + MULTISAMPLE_RESOLVE_BOX_BIT = 0x0200, + SWAP_BEHAVIOR_PRESERVED_BIT = 0x0400, + } + static partial class Egl { public const int VERSION_1_0 = 1; diff --git a/src/OpenTK/Platform/Egl/EglContext.cs b/src/OpenTK/Platform/Egl/EglContext.cs index 2844686..76992c9 100644 --- a/src/OpenTK/Platform/Egl/EglContext.cs +++ b/src/OpenTK/Platform/Egl/EglContext.cs @@ -28,6 +28,7 @@ using System; using System.Diagnostics; using OpenTK.Graphics; +using OpenTK.Graphics.ES20; namespace OpenTK.Platform.Egl { @@ -36,9 +37,11 @@ namespace OpenTK.Platform.Egl #region Fields protected readonly RenderableFlags Renderable; - protected EglWindowInfo WindowInfo; + internal EglWindowInfo WindowInfo; - IntPtr HandleAsEGLContext { get { return Handle.Handle; } set { Handle = new ContextHandle(value); } } + internal GraphicsContextFlags GraphicsContextFlags { get; set; } + + internal IntPtr HandleAsEGLContext { get { return Handle.Handle; } set { Handle = new ContextHandle(value); } } int swap_interval = 1; // Default interval is defined as 1 in EGL. #endregion @@ -85,19 +88,38 @@ namespace OpenTK.Platform.Egl Debug.Print("[EGL] Failed to bind rendering API. Error: {0}", Egl.GetError()); } - Mode = new EglGraphicsMode().SelectGraphicsMode(window, - mode.ColorFormat, mode.Depth, mode.Stencil, mode.Samples, - mode.AccumulatorFormat, mode.Buffers, mode.Stereo, - Renderable); + bool offscreen = (flags & GraphicsContextFlags.Offscreen) != 0; + + SurfaceType surface_type = offscreen + ? SurfaceType.PBUFFER_BIT + : SurfaceType.WINDOW_BIT; + + Mode = new EglGraphicsMode().SelectGraphicsMode(surface_type, + window.Display, mode.ColorFormat, mode.Depth, mode.Stencil, + mode.Samples, mode.AccumulatorFormat, mode.Buffers, mode.Stereo, + Renderable); + if (!Mode.Index.HasValue) throw new GraphicsModeException("Invalid or unsupported GraphicsMode."); IntPtr config = Mode.Index.Value; if (window.Surface == IntPtr.Zero) - window.CreateWindowSurface(config); + { + if (!offscreen) + { + window.CreateWindowSurface(config); + } + else + { + window.CreatePbufferSurface(config); + } + } int[] attrib_list = new int[] { Egl.CONTEXT_CLIENT_VERSION, major, Egl.NONE }; - HandleAsEGLContext = Egl.CreateContext(window.Display, config, sharedContext != null ? (sharedContext as IGraphicsContextInternal).Context.Handle : IntPtr.Zero, attrib_list); + var share_context = shared != null ? shared.HandleAsEGLContext : IntPtr.Zero; + HandleAsEGLContext = Egl.CreateContext(window.Display, config, share_context, attrib_list); + + GraphicsContextFlags = flags; } public EglContext(ContextHandle handle, EglWindowInfo window, IGraphicsContext sharedContext, @@ -133,6 +155,9 @@ namespace OpenTK.Platform.Egl { if (window is EglWindowInfo) WindowInfo = (EglWindowInfo) window; + else if (window is IAngleWindowInfoInternal) + WindowInfo = ((IAngleWindowInfoInternal) window).EglWindowInfo; + if (!Egl.MakeCurrent(WindowInfo.Display, WindowInfo.Surface, WindowInfo.Surface, HandleAsEGLContext)) { throw new GraphicsContextException(string.Format("Failed to make context {0} current. Error: {1}", Handle, Egl.GetError())); diff --git a/src/OpenTK/Platform/Egl/EglGraphicsMode.cs b/src/OpenTK/Platform/Egl/EglGraphicsMode.cs index 779e8ff..682caf3 100644 --- a/src/OpenTK/Platform/Egl/EglGraphicsMode.cs +++ b/src/OpenTK/Platform/Egl/EglGraphicsMode.cs @@ -48,10 +48,22 @@ namespace OpenTK.Platform.Egl int samples, ColorFormat accum, int buffers, bool stereo, RenderableFlags renderable_flags) { + return SelectGraphicsMode( + SurfaceType.WINDOW_BIT, + window.Display, + color, depth, stencil, samples, accum, buffers, stereo, renderable_flags + ); + } + + public GraphicsMode SelectGraphicsMode(SurfaceType surface_type, + IntPtr display, ColorFormat color, int depth, int stencil, + int samples, ColorFormat accum, int buffers, bool stereo, + RenderableFlags renderable_flags) + { IntPtr[] configs = new IntPtr[1]; int[] attribList = new int[] { - Egl.SURFACE_TYPE, Egl.WINDOW_BIT, + Egl.SURFACE_TYPE, (int) surface_type, Egl.RENDERABLE_TYPE, (int)renderable_flags, Egl.RED_SIZE, color.Red, @@ -68,8 +80,6 @@ namespace OpenTK.Platform.Egl Egl.NONE, }; - IntPtr display = window.Display; - int num_configs; if (!Egl.ChooseConfig(display, attribList, configs, configs.Length, out num_configs) || num_configs == 0) { @@ -92,5 +102,6 @@ namespace OpenTK.Platform.Egl return new GraphicsMode(active_config, new ColorFormat(r, g, b, a), d, s, sample_buffers > 0 ? samples : 0, 0, 2, false); } + } } diff --git a/src/OpenTK/Platform/Egl/EglWindowInfo.cs b/src/OpenTK/Platform/Egl/EglWindowInfo.cs index 10f495b..db73aa3 100644 --- a/src/OpenTK/Platform/Egl/EglWindowInfo.cs +++ b/src/OpenTK/Platform/Egl/EglWindowInfo.cs @@ -98,20 +98,66 @@ namespace OpenTK.Platform.Egl public void CreatePbufferSurface(IntPtr config) { - Surface = Egl.CreatePbufferSurface(Display, config, null); + int[] attribs = new int[]{Egl.NONE}; + Surface = Egl.CreatePbufferSurface(Display, config, attribs); + if (Surface == IntPtr.Zero) + { + throw new GraphicsContextException(String.Format( + "[EGL] Failed to create pbuffer surface, error {0}.", Egl.GetError())); + } + } + + public void CreatePbufferSurface(IntPtr config, int width, int height) + { + if (surface != IntPtr.Zero) + { + DestroySurface(); + } + CreatePbufferSurface(config, width, height, out surface); + } + + public void CreatePbufferSurface(IntPtr config, int width, int height, out IntPtr surface_) + { + int[] attribs = new int[] + { + Egl.WIDTH, width, + Egl.HEIGHT, height, + Egl.TEXTURE_TARGET, Egl.TEXTURE_2D, + Egl.TEXTURE_FORMAT, Egl.TEXTURE_RGBA, + Egl.NONE + }; + surface_ = Egl.CreatePbufferSurface(Display, config, attribs); + if (surface_ == IntPtr.Zero) + { + throw new GraphicsContextException(String.Format( + "[EGL] Failed to create pbuffer surface, error {0}.", Egl.GetError())); + } + } public void DestroySurface() { - if (Surface != IntPtr.Zero) + DestroySurface(ref surface); + } + + public void DestroySurface(ref IntPtr surface_) + { + if (surface_ == IntPtr.Zero) { - if (Egl.GetCurrentSurface(Egl.DRAW) == Surface) - Egl.MakeCurrent(Display, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); + return; + } - if (!Egl.DestroySurface(Display, Surface)) - Debug.Print("[Warning] Failed to destroy {0}:{1}.", Surface.GetType().Name, Surface); - Surface = IntPtr.Zero; + if (Egl.GetCurrentSurface(Egl.DRAW) == Surface) + Egl.MakeCurrent(Display, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); + + if (Egl.DestroySurface(Display, surface_)) + { + surface_ = IntPtr.Zero; + return; } + + Debug.Print("[Warning] Failed to destroy {0}:{1}.", Surface.GetType().Name, Surface); + Surface = IntPtr.Zero; } public void TerminateDisplay() -- 2.7.4