/// <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> protected override bool MakeCurrentCore(IntPtr ctx) { if (ctx != IntPtr.Zero) { // Ensure correct API bound if (Version >= Egl.Version_120) { int[] contextClientType = new int[1]; if (Egl.QueryContext(Display, ctx, Egl.CONTEXT_CLIENT_TYPE, contextClientType)) { if (Egl.BindAPI((uint)contextClientType[0]) == false) { throw new InvalidOperationException("no ES API"); } } } return(Egl.MakeCurrent(Display, EglSurface, EglSurface, ctx)); } else { return(Egl.MakeCurrent(Display, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero)); } }
/// <summary> /// Creates an OpenGL context from a Unix/Linux platform. /// </summary> /// <returns> /// A <see cref="IDeviceContext"/> that specify the device context. /// </returns> private static IntPtr CreateEglSimpleContext(IDeviceContext rDevice) { NativeDeviceContext eglDeviceCtx = (NativeDeviceContext)rDevice; IntPtr ctx; List <int> configAttribs = new List <int>(); if (eglDeviceCtx.Version >= Egl.Version_120) { configAttribs.AddRange(new int[] { Egl.RENDERABLE_TYPE, Egl.OPENGL_ES2_BIT }); } configAttribs.AddRange(new int[] { Egl.RED_SIZE, 8, Egl.GREEN_SIZE, 8, Egl.BLUE_SIZE, 8, }); configAttribs.Add(Egl.NONE); int[] configCount = new int[1]; IntPtr[] configs = new IntPtr[8]; if (Egl.BindAPI(Egl.OPENGL_ES_API) == false) { throw new InvalidOperationException("no ES API"); } if (Egl.ChooseConfig(eglDeviceCtx.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"); } List <int> contextAttribs = new List <int>(); if (eglDeviceCtx.Version >= Egl.Version_130) { contextAttribs.AddRange(new int[] { Egl.CONTEXT_CLIENT_VERSION, 2 }); } contextAttribs.Add(Egl.NONE); if ((ctx = Egl.CreateContext(eglDeviceCtx.Display, configs[configs.Length - 1], IntPtr.Zero, contextAttribs.ToArray())) == IntPtr.Zero) { throw new InvalidOperationException("unable to create context"); } List <int> surfaceAttribs = new List <int>(); surfaceAttribs.Add(Egl.NONE); // Egl.RENDER_BUFFER, Egl.BACK_BUFFER, eglDeviceCtx.Surface = Egl.CreateWindowSurface(eglDeviceCtx.Display, configs[configs.Length - 1], eglDeviceCtx.NativeWindow, surfaceAttribs.ToArray()); return(ctx); }
/// <summary> /// Create a simple context. /// </summary> /// <returns> /// A <see cref="IntPtr"/> that represents the handle of the created context. If the context cannot be /// created, it returns IntPtr.Zero. /// </returns> internal override IntPtr CreateSimpleContext() { IntPtr ctx; int[] configAttribs = DefaultConfigAttribs; int[] configCount = new int[1]; IntPtr[] configs = new IntPtr[8]; if (Egl.ChooseConfig(Display, configAttribs, configs, configs.Length, configCount) == false) { throw new InvalidOperationException("unable to choose configuration"); } if (configCount[0] == 0) { throw new InvalidOperationException("no available configuration"); } int[] contextAttribs = DefaultContextAttribs; int[] surfaceAttribs = { Egl.NONE }; if (Version >= Egl.Version_120) { if (Egl.BindAPI(Egl.OPENGL_ES_API) == false) { throw new InvalidOperationException("no ES API"); } } if ((ctx = Egl.CreateContext(Display, configs[0], IntPtr.Zero, contextAttribs)) == IntPtr.Zero) { throw new InvalidOperationException("unable to create context"); } if (_NativeSurface.Handle == IntPtr.Zero) { List <int> pbufferAttribs = new List <int>(surfaceAttribs); pbufferAttribs.RemoveAt(pbufferAttribs.Count - 1); pbufferAttribs.AddRange(new[] { Egl.WIDTH, 1, Egl.HEIGHT, 1 }); pbufferAttribs.Add(Egl.NONE); _NativeSurface.CreateHandle(configs[0], pbufferAttribs.ToArray()); } return(ctx); }
/// <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(); }
/// <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); }