protected override void Dispose(bool manual) { if (egl_display != IntPtr.Zero) { Debug.Print("[KMS] Terminating EGL."); Egl.Terminate(egl_display); egl_display = IntPtr.Zero; } if (gbm_device != IntPtr.Zero) { Debug.Print("[KMS] Destroying GBM device."); Gbm.DestroyDevice(gbm_device); gbm_device = IntPtr.Zero; } if (_fd >= 0) { Debug.Print("[KMS] Closing GPU fd."); Libc.close(_fd); } base.Dispose(manual); }
private static EGLDisplay InitializeDisplay() { int[] defaultDisplayAttributes = { // These are the default display attributes, used to request ANGLE's D3D11 renderer. // eglInitialize will only succeed with these attributes if the hardware supports D3D11 Feature Level 10_0+. Egl.EGL_PLATFORM_ANGLE_TYPE_ANGLE, Egl.EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, // Egl.EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER is an optimization that can have large performance benefits on mobile devices. // Its syntax is subject to change, though. Please update your Visual Studio templates if you experience compilation issues with it. Egl.EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, Egl.EGL_TRUE, // Egl.EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE is an option that enables ANGLE to automatically call // the IDXGIDevice3.Trim method on behalf of the application when it gets suspended. // Calling IDXGIDevice3.Trim when an application is suspended is a Windows Store application certification requirement. Egl.EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, Egl.EGL_TRUE, Egl.EGL_NONE, }; int[] fl9_3DisplayAttributes = { // These can be used to request ANGLE's D3D11 renderer, with D3D11 Feature Level 9_3. // These attributes are used if the call to eglInitialize fails with the default display attributes. Egl.EGL_PLATFORM_ANGLE_TYPE_ANGLE, Egl.EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, Egl.EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, 9, Egl.EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, 3, Egl.EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, Egl.EGL_TRUE, Egl.EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, Egl.EGL_TRUE, Egl.EGL_NONE, }; int[] warpDisplayAttributes = { // These attributes can be used to request D3D11 WARP. // They are used if eglInitialize fails with both the default display attributes and the 9_3 display attributes. Egl.EGL_PLATFORM_ANGLE_TYPE_ANGLE, Egl.EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, Egl.EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, Egl.EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE, Egl.EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, Egl.EGL_TRUE, Egl.EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, Egl.EGL_TRUE, Egl.EGL_NONE, }; // // To initialize the display, we make three sets of calls to eglGetPlatformDisplayEXT and eglInitialize, with varying // parameters passed to eglGetPlatformDisplayEXT: // 1) The first calls uses "defaultDisplayAttributes" as a parameter. This corresponds to D3D11 Feature Level 10_0+. // 2) If eglInitialize fails for step 1 (e.g. because 10_0+ isn't supported by the default GPU), then we try again // using "fl9_3DisplayAttributes". This corresponds to D3D11 Feature Level 9_3. // 3) If eglInitialize fails for step 2 (e.g. because 9_3+ isn't supported by the default GPU), then we try again // using "warpDisplayAttributes". This corresponds to D3D11 Feature Level 11_0 on WARP, a D3D11 software rasterizer. // // This tries to initialize EGL to D3D11 Feature Level 10_0+. See above comment for details. var display = Egl.eglGetPlatformDisplayEXT(Egl.EGL_PLATFORM_ANGLE_ANGLE, Egl.EGL_DEFAULT_DISPLAY, defaultDisplayAttributes); if (display == Egl.EGL_NO_DISPLAY) { throw new Exception("Failed to get EGL display (D3D11 10.0+)."); } int major, minor; if (Egl.eglInitialize(display, out major, out minor) == Egl.EGL_FALSE) { // This tries to initialize EGL to D3D11 Feature Level 9_3, if 10_0+ is unavailable (e.g. on some mobile devices). display = Egl.eglGetPlatformDisplayEXT(Egl.EGL_PLATFORM_ANGLE_ANGLE, Egl.EGL_DEFAULT_DISPLAY, fl9_3DisplayAttributes); if (display == Egl.EGL_NO_DISPLAY) { throw new Exception("Failed to get EGL display (D3D11 9.3)."); } if (Egl.eglInitialize(display, out major, out minor) == Egl.EGL_FALSE) { // This initializes EGL to D3D11 Feature Level 11_0 on WARP, if 9_3+ is unavailable on the default GPU. display = Egl.eglGetPlatformDisplayEXT(Egl.EGL_PLATFORM_ANGLE_ANGLE, Egl.EGL_DEFAULT_DISPLAY, warpDisplayAttributes); if (display == Egl.EGL_NO_DISPLAY) { throw new Exception("Failed to get EGL display (D3D11 11.0 WARP)"); } if (Egl.eglInitialize(display, out major, out minor) == Egl.EGL_FALSE) { // If all of the calls to eglInitialize returned Egl.EGL_FALSE then an error has occurred. throw new Exception("Failed to initialize EGL"); } } } Egl.eglBindAPI(Egl.EGL_OPENGL_ES_API); if (Egl.eglGetError() != Egl.EGL_SUCCESS) { throw new Exception("Failed to bind API"); } return(display); }
static SurfaceFormat GetSurfaceFormat(IntPtr display, GraphicsMode mode) { // Use EGL 1.4 EGL_NATIVE_VISUAL_ID to retrieve // the corresponding surface format. If that fails // fall back to a manual algorithm. int format; Egl.GetConfigAttrib(display, mode.Index.Value, Egl.NATIVE_VISUAL_ID, out format); if ((SurfaceFormat)format != 0) { return((SurfaceFormat)format); } Debug.Print("[KMS] Failed to retrieve EGL visual from GBM surface. Error: {0}", Egl.GetError()); Debug.Print("[KMS] Falling back to hardcoded formats."); int r = mode.ColorFormat.Red; int g = mode.ColorFormat.Green; int b = mode.ColorFormat.Blue; int a = mode.ColorFormat.Alpha; if (mode.ColorFormat.IsIndexed) { return(SurfaceFormat.C8); } if (r == 3 && g == 3 && b == 2 && a == 0) { return(SurfaceFormat.RGB332); } if (r == 5 && g == 6 && b == 5 && a == 0) { return(SurfaceFormat.RGB565); } if (r == 5 && g == 6 && b == 5 && a == 0) { return(SurfaceFormat.RGB565); } if (r == 8 && g == 8 && b == 8 && a == 0) { return(SurfaceFormat.RGB888); } if (r == 5 && g == 5 && b == 5 && a == 1) { return(SurfaceFormat.RGBA5551); } if (r == 10 && g == 10 && b == 10 && a == 2) { return(SurfaceFormat.RGBA1010102); } if (r == 4 && g == 4 && b == 4 && a == 4) { return(SurfaceFormat.RGBA4444); } if (r == 8 && g == 8 && b == 8 && a == 8) { return(SurfaceFormat.RGBA8888); } return(SurfaceFormat.RGBA8888); }
//~CanvasRenderingContextHolographicSpace() //{ // deviceContext.MakeCurrent(IntPtr.Zero); // deviceContext.DeleteContext(context); //} private IntPtr CreateEglContext(HolographicSpace holographicSpace, SpatialStationaryFrameOfReference stationaryReferenceFrame) { IntPtr context; int[] configAttribs = new int[] { Egl.RED_SIZE, 8, Egl.GREEN_SIZE, 8, Egl.BLUE_SIZE, 8, Egl.ALPHA_SIZE, 8, Egl.DEPTH_SIZE, 8, Egl.STENCIL_SIZE, 8, Egl.NONE }; int[] contextAttribs = new int[] { Egl.CONTEXT_CLIENT_VERSION, 2, Egl.NONE }; int[] surfaceAttribs = new int[] { EGL_ANGLE_SURFACE_RENDER_TO_BACK_BUFFER, Egl.TRUE, Egl.NONE }; int[] defaultDisplayAttribs = new int[] { EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, Egl.TRUE, EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, Egl.TRUE, Egl.NONE }; int[] fl9_3DisplayAttributes = new int[] { // These can be used to request ANGLE's D3D11 renderer, with D3D11 Feature Level 9_3. // These attributes are used if the call to eglInitialize fails with the default display attributes. EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, 9, EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, 3, EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, Egl.TRUE, EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, Egl.TRUE, Egl.NONE }; int[] warpDisplayAttributes = new int[] { // These attributes can be used to request D3D11 WARP. // They are used if eglInitialize fails with both the default display attributes and the 9_3 display attributes. EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE, EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, Egl.TRUE, EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, Egl.TRUE, Egl.NONE }; int[] configCount = new int[1]; IntPtr[] configs = new IntPtr[8]; if (Egl.BindAPI(Egl.OPENGL_ES_API) == false) { throw new InvalidOperationException("No OpenGL ES API"); } if ((display = Egl.GetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, IntPtr.Zero, defaultDisplayAttribs)) == IntPtr.Zero) { throw new InvalidOperationException("Unable to get EGL display"); } if (!Egl.Initialize(display, null, null)) { if ((display = Egl.GetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, IntPtr.Zero, fl9_3DisplayAttributes)) == IntPtr.Zero) { throw new InvalidOperationException("Unable to get EGL display"); } if (!Egl.Initialize(display, null, null)) { if ((display = Egl.GetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, IntPtr.Zero, warpDisplayAttributes)) == IntPtr.Zero) { throw new InvalidOperationException("Unable to get EGL display"); } if (!Egl.Initialize(display, null, null)) { throw new InvalidOperationException("Unable to initialize EGL"); } } } if (!Egl.ChooseConfig(display, configAttribs, configs, 1, configCount)) { throw new InvalidOperationException("Unable to choose configuration"); } holographicSpaceHandle = GCHandle.Alloc(holographicSpace); IntPtr holographicSpacePointer = Marshal.GetIUnknownForObject(holographicSpace); //PropertySet surfaceCreationProperties = new PropertySet //{ // { "EGLNativeWindowTypeProperty", (IntPtr)holographicSpaceHandle } //}; PropertySet surfaceCreationProperties = new PropertySet(); surfaceCreationProperties.Add("EGLNativeWindowTypeProperty", holographicSpacePointer); //if (stationaryReferenceFrame != null) //{ // stationaryReferenceFrameHandle = GCHandle.Alloc(stationaryReferenceFrame); // surfaceCreationProperties.Add("EGLBaseCoordinateSystemProperty", (IntPtr)stationaryReferenceFrameHandle); //} GCHandle surfaceCreationPropertiesHandle = GCHandle.Alloc(surfaceCreationProperties); IntPtr surfaceCreationPropertiesPointer = Marshal.GetIUnknownForObject(surfaceCreationProperties); if ((surface = Egl.CreateWindowSurface(display, configs[0], surfaceCreationPropertiesPointer, surfaceAttribs)) == IntPtr.Zero) { throw new InvalidOperationException("Unable to create EGL fullscreen surface"); } if ((context = Egl.CreateContext(display, configs[0], IntPtr.Zero, contextAttribs)) == IntPtr.Zero) { throw new InvalidOperationException("Unable to create context"); } return(context); }
static void GetCurrentContext(int eventId) { currentContext = Egl.getCurrentContext(); }
public override void SwapBuffers() { Egl.SwapBuffers(_display, _surface); }
static void GetCurrentContext(int eventId) { currentContext = Egl.getCurrentContext(); isContextInitialized = true; }
public override void MakeCurrent() { Egl.MakeCurrent(_display, _surface, _surface, _context); }
protected override void SetSwapIntervalPlatform(int interval) { Egl.SwapInterval(_display, interval); }
public void Init(IntPtr nativeDeviceHandle, IntPtr nativeWindowHandle, PlatformBase platform) { _platform = platform; _eglLib = platform.LoadLibrary("libEGL"); if (_eglLib == IntPtr.Zero) { Engine.Log.Error("Couldn't load EGL.", MessageSource.Egl); return; } IntPtr gles = platform.LoadLibrary("libGLESv2"); if (gles == IntPtr.Zero) { Engine.Log.Error("Couldn't load GLES.", MessageSource.Egl); return; } string extensions = Egl.QueryString(IntPtr.Zero, Egl.Query.EGL_EXTENSIONS); Egl.Error err = Egl.GetError(); if (extensions == null || err != Egl.Error.Success) { Engine.Log.Error($"Couldn't load extensions. {err}", MessageSource.Egl); extensions = ""; } _display = Egl.GetDisplay(nativeDeviceHandle); if (_display == IntPtr.Zero) { Engine.Log.Error($"Couldn't initialize display. {Egl.GetError()}", MessageSource.Egl); return; } var majorVersion = 3; int majorVer = majorVersion; var minorVer = 0; if (RenderDoc.Loaded) { minorVer = 1; } if (!Egl.Init(_display, ref majorVer, ref minorVer)) { Engine.Log.Error($"Couldn't initialize Egl. {Egl.GetError()}", MessageSource.Egl); return; } // Pick config var totalConfigs = 0; Egl.GetConfigs(_display, null, 0, ref totalConfigs); if (totalConfigs == 0) { Engine.Log.Error($"No configs for current display. {Egl.GetError()}", MessageSource.Egl); return; } var configs = new IntPtr[totalConfigs]; Egl.GetConfigs(_display, configs, totalConfigs, ref totalConfigs); if (totalConfigs == 0) { Engine.Log.Error($"No configs for current display. {Egl.GetError()}", MessageSource.Egl); return; } int configHandle = SupportedPixelFormat(configs); if (configHandle == 0) { Engine.Log.Error("No valid config found.", MessageSource.Egl); return; } IntPtr config = configs[configHandle - 1]; if (!Egl.BindAPI(Egl.API.EGL_OPENGL_ES_API)) { Engine.Log.Error($"Couldn't bind EGL API. {Egl.GetError()}", MessageSource.Egl); return; } int[] attributes = { (int)Egl.ContextAttribute.EGL_CONTEXT_CLIENT_VERSION, majorVersion, 0x3038 // EGL_NONE }; _context = Egl.CreateContext(_display, config, IntPtr.Zero, attributes); if (_context == IntPtr.Zero) { Engine.Log.Error($"Context creation failed. {Egl.GetError()}", MessageSource.Egl); return; } _surface = Egl.CreateWindowSurface(_display, config, nativeWindowHandle, null); if (_surface == IntPtr.Zero) { Engine.Log.Error($"Surface creation failed. {Egl.GetError()}", MessageSource.Egl); return; } Valid = true; }
/// <summary> /// Finds the index of the supported pixel format closest to the requested pixel format. /// </summary> /// <returns>The index of the pixel format to use.</returns> private int SupportedPixelFormat(IntPtr[] configs) { var usableConfigs = new List <FramebufferConfig>(); var attributeValue = 0; for (var i = 0; i < configs.Length; i++) { IntPtr currentConfig = configs[i]; // We only want RGB buffers. if (!Egl.GetConfigAttribute(_display, currentConfig, Egl.ConfigAttribute.EGL_COLOR_BUFFER_TYPE, ref attributeValue)) { continue; } if (attributeValue != (int)Egl.ConfigValue.EGL_RGB_BUFFER) { continue; } // We only want window type configs. // EGL_WINDOW_BIT 0x0004 Egl.GetConfigAttribute(_display, currentConfig, Egl.ConfigAttribute.EGL_SURFACE_TYPE, ref attributeValue); if ((attributeValue & 0x0004) == 0) { continue; } // We want configs that support ES2 (We actually want ES3, but there's no such bit) // EGL_OPENGL_ES2_BIT 0x0004 Egl.GetConfigAttribute(_display, currentConfig, Egl.ConfigAttribute.EGL_RENDERABLE_TYPE, ref attributeValue); if ((attributeValue & 0x0004) == 0) { continue; } var fbConfig = new FramebufferConfig(); Egl.GetConfigAttribute(_display, currentConfig, Egl.ConfigAttribute.EGL_RED_SIZE, ref attributeValue); fbConfig.RedBits = attributeValue; Egl.GetConfigAttribute(_display, currentConfig, Egl.ConfigAttribute.EGL_GREEN_SIZE, ref attributeValue); fbConfig.GreenBits = attributeValue; Egl.GetConfigAttribute(_display, currentConfig, Egl.ConfigAttribute.EGL_BLUE_SIZE, ref attributeValue); fbConfig.BlueBits = attributeValue; Egl.GetConfigAttribute(_display, currentConfig, Egl.ConfigAttribute.EGL_ALPHA_SIZE, ref attributeValue); fbConfig.AlphaBits = attributeValue; Egl.GetConfigAttribute(_display, currentConfig, Egl.ConfigAttribute.EGL_DEPTH_SIZE, ref attributeValue); fbConfig.DepthBits = attributeValue; Egl.GetConfigAttribute(_display, currentConfig, Egl.ConfigAttribute.EGL_STENCIL_SIZE, ref attributeValue); fbConfig.StencilBits = attributeValue; Egl.GetConfigAttribute(_display, currentConfig, Egl.ConfigAttribute.EGL_SAMPLES, ref attributeValue); fbConfig.Samples = attributeValue; fbConfig.Doublebuffer = true; fbConfig.Handle = i + 1; usableConfigs.Add(fbConfig); } if (usableConfigs.Count == 0) { Engine.Log.Error("The driver doesn't seem to support OpenGL.", MessageSource.WGallium); return(0); } FramebufferConfig closestConfig = ChoosePixelFormat(usableConfigs); if (closestConfig != null) { return(closestConfig.Handle); } Engine.Log.Error("Couldn't find suitable pixel format.", MessageSource.WGallium); return(0); }
private static void GetCurrentContext(int eventId) { _CurrentContext = Egl.GetCurrentContext(); _IsContextInitialized = true; }