private static IntPtr ChoosePixelFormat(IntPtr display, int configId)
        {
            List <int> configAttribs = new List <int>();

            int[]    configCount = new int[1];
            IntPtr[] configs     = new IntPtr[8];

            configAttribs.AddRange(new int[] { Egl.CONFIG_ID, configId });
            configAttribs.Add(Egl.NONE);

            if (Egl.ChooseConfig(display, configAttribs.ToArray(), configs, configs.Length, configCount) == false)
            {
                throw new InvalidOperationException("unable to choose configuration");
            }
            if (configCount[0] == 0)
            {
                throw new InvalidOperationException("no available configuration");
            }

            return(configs[0]);
        }
示例#2
0
        /// <summary>
        /// Initialize LTS information for the calling thread.
        /// </summary>
        public static void InitializeThread()
        {
#if !MONODROID
            if (Egl.IsRequired == false)
            {
                switch (Platform.CurrentPlatformId)
                {
                case Platform.Id.WindowsNT:
                    Wgl.BindAPI();
                    break;

                case Platform.Id.Linux:
                    Glx.BindAPI();
                    break;

                case Platform.Id.MacOS:
                    if (Glx.IsRequired)
                    {
                        Glx.BindAPI();
                    }
                    else
                    {
                        throw new NotSupportedException("platform MacOS not supported without Glx.IsRequired=true");
                    }
                    break;

                case Platform.Id.Android:
                    Egl.BindAPI();
                    break;

                default:
                    throw new NotSupportedException(String.Format("platform {0} not supported", Platform.CurrentPlatformId));
                }
            }
            else
#endif
            Egl.BindAPI();
        }
示例#3
0
        /// <summary>
        /// Set the device pixel format.
        /// </summary>
        /// <param name="pixelFormat">
        /// A <see cref="DevicePixelFormat"/> that specifies the pixel format to set.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// Exception thrown if <paramref name="pixelFormat"/> is null.
        /// </exception>
        public override void SetPixelFormat(DevicePixelFormat pixelFormat)
        {
            if (pixelFormat == null)
            {
                throw new ArgumentNullException("pixelFormat");
            }
            if (_NativeSurface.Handle != IntPtr.Zero)
            {
                throw new InvalidOperationException("pixel format already set");
            }

            List <int> configAttribs = new List <int>();

            if (Version >= Egl.Version_120)
            {
                configAttribs.AddRange(new int[] { Egl.RENDERABLE_TYPE, Egl.OPENGL_ES2_BIT });
            }
            configAttribs.AddRange(new int[] {
                Egl.CONFIG_ID, pixelFormat.FormatIndex,
            });
            configAttribs.Add(Egl.NONE);

            int[]    configCount = new int[1];
            IntPtr[] configs     = new IntPtr[1];

            if (Egl.ChooseConfig(Display, configAttribs.ToArray(), configs, 1, configCount) == false)
            {
                throw new InvalidOperationException("unable to choose configuration");
            }
            if (configCount[0] == 0)
            {
                throw new InvalidOperationException("no available configuration");
            }

            _Config = configs[0];
        }
示例#4
0
 /// <summary>
 /// Control the the buffers swap of a device.
 /// </summary>
 /// <param name="interval">
 /// A <see cref="Int32"/> that specifies the minimum number of video frames that are displayed
 /// before a buffer swap will occur.
 /// </param>
 /// <returns>
 /// It returns a boolean value indicating whether the operation was successful.
 /// </returns>
 public override bool SwapInterval(int interval)
 {
     return(Egl.SwapInterval(Display, interval));
 }
示例#5
0
 /// <summary>
 /// Swap the buffers of a device.
 /// </summary>
 public override void SwapBuffers()
 {
     Egl.SwapBuffers(Display, EglSurface);
 }
示例#6
0
        /// <summary>
        /// Creates a context, specifying attributes.
        /// </summary>
        /// <param name="sharedContext">
        /// A <see cref="IntPtr"/> that specify a context that will share objects with the returned one. If
        /// it is IntPtr.Zero, no sharing is performed.
        /// </param>
        /// <param name="attribsList">
        /// A <see cref="T:Int32[]"/> that specifies the attributes list.
        /// </param>
        /// <param name="api">
        /// A <see cref="KhronosVersion"/> that specifies the API to be implemented by the returned context. It can be null indicating the
        /// default API for this DeviceContext implementation. If it is possible, try to determine the API version also.
        /// </param>
        /// <returns>
        /// A <see cref="IntPtr"/> that represents the handle of the created context. If the context cannot be
        /// created, it returns IntPtr.Zero.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// Exception thrown if <paramref name="attribsList"/> is null.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// Exception thrown if <paramref name="attribsList"/> length is zero or if the last item of <paramref name="attribsList"/>
        /// is not zero.
        /// </exception>
        public override IntPtr CreateContextAttrib(IntPtr sharedContext, int[] attribsList, KhronosVersion api)
        {
            if (attribsList == null)
            {
                throw new ArgumentNullException(nameof(attribsList));
            }
            if (attribsList.Length == 0)
            {
                throw new ArgumentException("zero length array", nameof(attribsList));
            }
            if (attribsList[attribsList.Length - 1] != Egl.NONE)
            {
                throw new ArgumentException("not EGL_NONE-terminated array", nameof(attribsList));
            }

            IntPtr context;

            // Select surface pixel format automatically
            if (_NativeSurface != null && _NativeSurface.Handle != IntPtr.Zero)
            {
                int[] configId = new int[1];

                if (Egl.QuerySurface(Display, EglSurface, Egl.CONFIG_ID, configId) == false)
                {
                    throw new InvalidOperationException("unable to query EGL surface config ID");
                }

                _Config = ChoosePixelFormat(Display, configId[0]);
            }

            // Bind API
            if (Version >= Egl.Version_120)
            {
                uint apiEnum;

                switch (api.Api)
                {
                case KhronosVersion.ApiGles2:
                case KhronosVersion.ApiGles1:
                case null:
                    // Default
                    apiEnum = Egl.OPENGL_ES_API;
                    break;

                case KhronosVersion.ApiGl:
                    apiEnum = Egl.OPENGL_API;
                    break;

                case KhronosVersion.ApiVg:
                    apiEnum = Egl.OPENVG_API;
                    break;

                default:
                    throw new InvalidOperationException($"'{api}' API not available");
                }
                if (Egl.BindAPI(apiEnum) == false)
                {
                    throw new InvalidOperationException("no ES API");
                }
            }
            else if (api != null && api.Api != KhronosVersion.ApiGles2 && api.Api != KhronosVersion.ApiGles1)
            {
                throw new InvalidOperationException($"'{api}' API not available");
            }

            // Create context
            if ((context = Egl.CreateContext(Display, _Config, sharedContext, attribsList)) == IntPtr.Zero)
            {
                throw new EglException(Egl.GetError());
            }

            // Create native surface (pixel format pending)
            // @todo Back-buffer?
            if (_NativeSurface != null && _NativeSurface.Handle == IntPtr.Zero)
            {
                _NativeSurface.CreateHandle(_Config, new[] { Egl.NONE });
            }

            return(context);
        }
示例#7
0
        /// <summary>
        /// Set the device pixel format.
        /// </summary>
        /// <param name="pixelFormat">
        /// A <see cref="DevicePixelFormat"/> that specifies the pixel format to set.
        /// </param>
        private static IntPtr ChoosePixelFormat(IntPtr display, KhronosVersion version, DevicePixelFormat pixelFormat)
        {
            if (version == null)
            {
                throw new ArgumentNullException(nameof(version));
            }
            if (pixelFormat == null)
            {
                throw new ArgumentNullException(nameof(pixelFormat));
            }

            List <int> configAttribs = new List <int>();

            int[]    configCount = new int[1];
            IntPtr[] configs     = new IntPtr[8];
            int      surfaceType = 0;

            if (version >= Egl.Version_120)
            {
                configAttribs.AddRange(new[] { Egl.RENDERABLE_TYPE, Egl.OPENGL_ES2_BIT });
            }

            if (pixelFormat.RenderWindow)
            {
                surfaceType |= Egl.WINDOW_BIT;
            }
            if (pixelFormat.RenderPBuffer)
            {
                surfaceType |= Egl.PBUFFER_BIT;
            }
            if (surfaceType != 0)
            {
                configAttribs.AddRange(new[] { Egl.SURFACE_TYPE, surfaceType });
            }

            switch (pixelFormat.ColorBits)
            {
            case 24:
                configAttribs.AddRange(new[] { Egl.RED_SIZE, 8, Egl.GREEN_SIZE, 8, Egl.BLUE_SIZE, 8 });
                break;

            case 32:
                configAttribs.AddRange(new[] { Egl.RED_SIZE, 8, Egl.GREEN_SIZE, 8, Egl.BLUE_SIZE, 8, Egl.ALPHA_SIZE, 8 });
                break;

            default:
                configAttribs.AddRange(new[] { Egl.BUFFER_SIZE, pixelFormat.ColorBits });
                break;
            }
            if (pixelFormat.DepthBits > 0)
            {
                configAttribs.AddRange(new[] { Egl.DEPTH_SIZE, pixelFormat.DepthBits });
            }
            if (pixelFormat.StencilBits > 0)
            {
                configAttribs.AddRange(new[] { Egl.STENCIL_SIZE, pixelFormat.StencilBits });
            }

            configAttribs.Add(Egl.NONE);

            if (Egl.ChooseConfig(display, configAttribs.ToArray(), configs, configs.Length, configCount) == false)
            {
                throw new InvalidOperationException("unable to choose configuration");
            }
            if (configCount[0] == 0)
            {
                throw new InvalidOperationException("no available configuration");
            }

            return(configs[0]);
        }
示例#8
0
        /// <summary>
        /// Initialize OpenGL namespace static environment. This method shall be called before any other classes methods.
        /// </summary>
        public static void Initialize()
        {
            if (_Initialized == true)
            {
                return;                 // Already initialized
            }
            _Initialized = true;

            // Before linking procedures, append ANGLE directory in path
            string assemblyPath = GetAssemblyLocation();
            string anglePath    = null;

            switch (Platform.CurrentPlatformId)
            {
            case Platform.Id.WindowsNT:
                if (assemblyPath != null)
                {
#if DEBUG
                    if (IntPtr.Size == 8)
                    {
                        anglePath = Path.Combine(assemblyPath, @"ANGLE\winrt10d\x64");
                    }
                    else
                    {
                        anglePath = Path.Combine(assemblyPath, @"ANGLE\winrt10d\x86");
                    }
#else
                    if (IntPtr.Size == 8)
                    {
                        anglePath = Path.Combine(assemblyPath, @"ANGLE\winrt10\x64");
                    }
                    else
                    {
                        anglePath = Path.Combine(assemblyPath, @"ANGLE\winrt10\x86");
                    }
#endif
                }
                break;

            case Platform.Id.Linux:
                // Note: on RPi libEGL.so depends on libGLESv2.so, so it's required to pre-load the shared library
                // Note: maybe a configurable and generic method for pre-loading assemblies may be introduced
                GetProcAddressLinux.GetLibraryHandle("libGLESv2.so", false);
                break;
            }

            // Include ANGLE path, if any
#if NETSTANDARD1_1
            if (anglePath != String.Empty)
            {
                OpenGL.GetProcAddressOS.AddLibraryDirectory(Path.Combine(assemblyPath, anglePath));
            }
#else
            if (anglePath != null && Directory.Exists(anglePath))
            {
                OpenGL.GetProcAddressOS.AddLibraryDirectory(Path.Combine(assemblyPath, anglePath));
            }
#endif

            // Load procedures
            BindAPI();

            if (IsAvailable == false)
            {
                return;
            }

#if DEBUG
            string envEglInit = Environment.GetEnvironmentVariable("EGL_INIT");

            if (envEglInit != null && envEglInit == "NO")
            {
                return;
            }
#endif

            // Platform initialization
            EglEventArgs args = new EglEventArgs();

            RaiseEglInitializing(args);

            // Get EGL information
            IntPtr eglDisplay = Egl.GetDisplay(args.Display);

            try {
                if (Initialize(eglDisplay, null, null) == false)
                {
                    throw new InvalidOperationException("unable to initialize EGL");
                }

                // Query EGL version
                string eglVersionString = QueryString(eglDisplay, VERSION);
                _CurrentVersion = KhronosVersion.Parse(eglVersionString, KhronosVersion.ApiEgl);
                // Query EGL vendor
                _Vendor = QueryString(eglDisplay, VENDOR);
                // Client APIs
                List <string> clientApis = new List <string>();

                if (_CurrentVersion >= Version_120)
                {
                    string   clientApisString = QueryString(eglDisplay, CLIENT_APIS);
                    string[] clientApiTokens  = System.Text.RegularExpressions.Regex.Split(clientApisString, " ");

                    foreach (string api in DeviceContextEGL.ConvertApiNames(clientApiTokens))
                    {
                        clientApis.Add(api);
                    }
                }

                _AvailableApis = clientApis.ToArray();

                // Null device context for querying extensions
                using (DeviceContextEGL deviceContext = new DeviceContextEGL(args.Display, IntPtr.Zero)) {
                    _CurrentExtensions = new Extensions();
                    _CurrentExtensions.Query(deviceContext);
                }
            } finally {
                Terminate(eglDisplay);
            }
        }
示例#9
0
 /// <summary>
 /// Swap the buffers of a device.
 /// </summary>
 public override void SwapBuffers()
 {
     Egl.SwapBuffers(_Display, IntPtr.Zero);
 }
示例#10
0
        /// <summary>
        /// Initialize OpenGL namespace static environment. This method shall be called before any other classes methods.
        /// </summary>
        public static void Initialize()
        {
            if (_Initialized == true)
            {
                return;                 // Already initialized
            }
            _Initialized = true;

            // Before linking procedures, append ANGLE directory in path
            string assemblyPath = Path.GetDirectoryName(Assembly.GetAssembly(typeof(Egl)).Location);
            string anglePath    = null;

            switch (Platform.CurrentPlatformId)
            {
            case Platform.Id.WindowsNT:
#if DEBUG
                if (IntPtr.Size == 8)
                {
                    anglePath = Path.Combine(assemblyPath, @"ANGLE\winrt10d\x64");
                }
                else
                {
                    anglePath = Path.Combine(assemblyPath, @"ANGLE\winrt10d\x86");
                }
#else
                if (IntPtr.Size == 8)
                {
                    anglePath = Path.Combine(assemblyPath, @"ANGLE\winrt10\x64");
                }
                else
                {
                    anglePath = Path.Combine(assemblyPath, @"ANGLE\winrt10\x86");
                }
#endif
                break;

            case Platform.Id.Linux:
                // Note: on RPi libEGL.so depends on libGLESv2.so, so it's required to pre-load the shared library
                GetProcAddressX11.GetLibraryHandle("libGLESv2.so", false);
                break;
            }

            // Include ANGLE path, if any
            if (anglePath != null && Directory.Exists(anglePath))
            {
                OpenGL.GetProcAddress.GetProcAddressOS.AddLibraryDirectory(Path.Combine(assemblyPath, anglePath));
            }

            // Load procedures
            string platformLibrary = GetPlatformLibrary();
            try {
                LogComment("Querying EGL from {0}", platformLibrary);
                BindAPI <Egl>(platformLibrary, OpenGL.GetProcAddress.GetProcAddressOS);
                LogComment("EGL availability: {0}", IsAvailable);
            } catch (Exception exception) {
                /* Fail-safe (it may fail due Egl access) */
                LogComment("EGL not available:\n{0}", exception.ToString());
            }

            if (IsAvailable == false)
            {
                return;
            }

#if DEBUG
            string envEglInit = Environment.GetEnvironmentVariable("EGL_INIT");

            if (envEglInit != null && envEglInit == "NO")
            {
                return;
            }
#endif

            // Platform initialization
            EglEventArgs args = new EglEventArgs();

            RaiseEglInitializing(args);

            // Get EGL information
            IntPtr eglDisplay = Egl.GetDisplay(args.Display);

            try {
                if (Initialize(eglDisplay, null, null) == false)
                {
                    throw new InvalidOperationException("unable to initialize EGL");
                }

                // Query EGL version
                string eglVersionString = QueryString(eglDisplay, VERSION);
                _CurrentVersion = KhronosVersion.Parse(eglVersionString, KhronosVersion.ApiEgl);
                // Query EGL vendor
                _Vendor = QueryString(eglDisplay, VENDOR);
                // Client APIs
                if (_CurrentVersion >= Version_120)
                {
                    string clientApisString = QueryString(eglDisplay, CLIENT_APIS);
                    _AvailableApis = System.Text.RegularExpressions.Regex.Split(clientApisString, " ");
                }
            } finally {
                Terminate(eglDisplay);
            }
        }
示例#11
0
 /// <summary>
 /// Control the the buffers swap of a device.
 /// </summary>
 /// <param name="interval">
 /// A <see cref="System.Int32"/> that specifies the minimum number of video frames that are displayed
 /// before a buffer swap will occur.
 /// </param>
 /// <returns>
 /// It returns a boolean value indicating whether the operation was successful.
 /// </returns>
 public override bool SwapInterval(int interval)
 {
     return(Egl.SwapInterval(_Display, interval) != IntPtr.Zero);
 }
示例#12
0
 /// <summary>
 /// Makes the context current on the calling thread.
 /// </summary>
 /// <param name="ctx">
 /// A <see cref="IntPtr"/> that specify the context to be current on the calling thread, bound to
 /// thise device context. It can be IntPtr.Zero indicating that no context will be current.
 /// </param>
 /// <returns>
 /// It returns a boolean value indicating whether the operation was successful.
 /// </returns>
 /// <exception cref="NotSupportedException">
 /// Exception thrown if the current platform is not supported.
 /// </exception>
 public override bool MakeCurrent(IntPtr ctx)
 {
     return(Egl.MakeCurrent(_Display, IntPtr.Zero, IntPtr.Zero, ctx) != IntPtr.Zero);
 }
示例#13
0
 /// <summary>
 /// Creates a context.
 /// </summary>
 /// <param name="sharedContext">
 /// A <see cref="IntPtr"/> that specify a context that will share objects with the returned one. If
 /// it is IntPtr.Zero, no sharing is performed.
 /// </param>
 /// <returns>
 /// A <see cref="IntPtr"/> that represents the handle of the created context. If the context cannot be
 /// created, it returns IntPtr.Zero.
 /// </returns>
 /// <exception cref="InvalidOperationException">
 /// Exception thrown in the case <paramref name="sharedContext"/> is different from IntPtr.Zero, and the objects
 /// cannot be shared with it.
 /// </exception>
 public override IntPtr CreateContext(IntPtr sharedContext)
 {
     return(Egl.CreateContext(_Display, _Config, sharedContext, null));
 }