Added Angle-related enums and definitions
authorJonas Boesch <jonas.boesch@phonak.com>
Tue, 21 Apr 2015 14:08:50 +0000 (16:08 +0200)
committerManuel Zanin <manuel.zanin@sonova.com>
Mon, 28 Nov 2016 11:20:59 +0000 (12:20 +0100)
+ 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 [new file with mode: 0644]
src/OpenTK/Graphics/GraphicsContext.cs
src/OpenTK/Graphics/GraphicsContextFlags.cs
src/OpenTK/OpenTK.csproj
src/OpenTK/Platform/Egl/Egl.cs
src/OpenTK/Platform/Egl/EglContext.cs
src/OpenTK/Platform/Egl/EglGraphicsMode.cs
src/OpenTK/Platform/Egl/EglWindowInfo.cs

diff --git a/Source/OpenTK/Platform/Egl/EglAngle.cs b/Source/OpenTK/Platform/Egl/EglAngle.cs
new file mode 100644 (file)
index 0000000..9cf708e
--- /dev/null
@@ -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
index d12e360..35a5d35 100644 (file)
@@ -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
                 {
index a7ee2f5..a7df6e1 100644 (file)
@@ -56,6 +56,30 @@ namespace OpenTK.Graphics
         /// <summary>
         /// Indicates that this GraphicsContext is targeting OpenGL|ES.
         /// </summary>
-        Embedded = 0x0004
+        Embedded = 0x0004,
+        /// <summary>
+        /// Indicates that this GraphicsContext is intended for offscreen rendering.
+        /// </summary>
+        Offscreen = 0x0008,
+        /// <summary>
+        /// Indicates that this GraphicsContext is targeting OpenGL|ES via Angle 
+        /// and that angle-specific extensions are available.
+        /// </summary>
+        Angle = 0x0010,
+        /// <summary>
+        /// Indicates that this GraphicsContext is targeting OpenGL|ES via Angle 
+        /// and uses Direct3D9 as rendering backend.
+        /// </summary>
+        AngleD3D9 = 0x0020,
+        /// <summary>
+        /// Indicates that this GraphicsContext is targeting OpenGL|ES via Angle 
+        /// and uses Direct3D11 as rendering backend.
+        /// </summary>
+        AngleD3D11 = 0x0040,
+        /// <summary>
+        /// Indicates that this GraphicsContext is targeting OpenGL|ES via Angle 
+        /// and uses OpenGL as rendering backend.
+        /// </summary>
+        AngleOpenGL = 0x0080,
     }
 }
index aaa0989..1476054 100644 (file)
     <Compile Include="Platform\Common\Hid.cs" />
     <Compile Include="Platform\DisplayDeviceBase.cs" />
     <Compile Include="Platform\Egl\EglException.cs" />
+    <Compile Include="Platform\Egl\EglAngle.cs" />
     <Compile Include="Platform\Egl\EglUnixContext.cs" />
     <Compile Include="Platform\Egl\EglWinContext.cs" />
     <Compile Include="Platform\MappedGamePadDriver.cs" />
index 118054d..df39581 100644 (file)
@@ -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;
index 2844686..76992c9 100644 (file)
@@ -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()));
index 779e8ff..682caf3 100644 (file)
@@ -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);
         }
+
     }
 }
index 10f495b..db73aa3 100644 (file)
@@ -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()