void StartRenderLoop() { // If the render loop is already running then do not start another thread. if (mRenderLoopWorker != null && mRenderLoopWorker.Status == AsyncStatus.Started) { return; } //var throttler = new Helpers.EventThrottler<TextChangedEventArgs>(Constants.TypingTimeout, handler => SearchField.TextChanged += new TextChangedEventHandler(handler)); //throttler.Invoked += (s, args) => //{ // // s is SearchField // // args is TextChangedEventArgs //}; // Create a task for rendering that will be run on a background thread. var workItemHandler = new Windows.System.Threading.WorkItemHandler(action => { lock (mRenderSurfaceCriticalSection) { mOpenGLES.MakeCurrent(mRenderSurface); //var renderer = new RendererBase(); var renderer = RendererInit(); while (action.Status == AsyncStatus.Started) { int panelWidth = 0; int panelHeight = 0; mOpenGLES.GetSurfaceDimensions(mRenderSurface, ref panelWidth, ref panelHeight); // Logic to update the scene could go here renderer.UpdateWindowSize(panelWidth, panelHeight); renderer.Draw(); // The call to eglSwapBuffers might not be successful (i.e. due to Device Lost) // If the call fails, then we must reinitialize EGL and the GL resources. if (mOpenGLES.SwapBuffers(mRenderSurface) != EGL.TRUE) { // XAML objects like the SwapChainPanel must only be manipulated on the UI thread. #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed swapChainPanel.Dispatcher.RunAsync(CoreDispatcherPriority.High, new DispatchedHandler(() => { RecoverFromLostDevice(); })); #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed return; } } } }); // Run task on a dedicated high priority background thread. mRenderLoopWorker = Windows.System.Threading.ThreadPool.RunAsync(workItemHandler, Windows.System.Threading.WorkItemPriority.High, Windows.System.Threading.WorkItemOptions.TimeSliced); }
void StartRenderLoop() { // If the render loop is already running then do not start another thread. if (_renderLoopWorker != null && _renderLoopWorker.Status == Windows.Foundation.AsyncStatus.Started) { return; } // Create a task for rendering that will be run on a background thread. var workItemHandler = new Windows.System.Threading.WorkItemHandler((Windows.Foundation.IAsyncAction action) => { lock (_renderSurfaceLock) { _eglContext.MakeCurrent(_renderSurface); int oldPanelWidth = -1; int oldPanelHeight = -1; while (action.Status == Windows.Foundation.AsyncStatus.Started) { int panelWidth = 0; int panelHeight = 0; GetSwapChainPanelSize(out panelWidth, out panelHeight); if (panelWidth != oldPanelWidth || panelHeight != oldPanelHeight) { _baseMapView.OnSurfaceChanged(panelWidth, panelHeight); oldPanelWidth = panelWidth; oldPanelHeight = panelHeight; } _baseMapView.OnDrawFrame(); // The call to eglSwapBuffers might not be successful (i.e. due to Device Lost) // If the call fails, then we must reinitialize EGL and the GL resources. if (!_eglContext.SwapBuffers(_renderSurface)) { // XAML objects like the SwapChainPanel must only be manipulated on the UI thread. var worker = _swapChainPanel.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, new Windows.UI.Core.DispatchedHandler(() => { RecoverFromLostDevice(); })); worker.Close(); return; } _swapChainEvent.WaitOne(); _swapChainEvent.Reset(); } } }); // Run task on a dedicated high priority background thread. _renderLoopWorker = Windows.System.Threading.ThreadPool.RunAsync(workItemHandler, Windows.System.Threading.WorkItemPriority.Normal, Windows.System.Threading.WorkItemOptions.TimeSliced); }
void StartRenderLoop() { // If the render loop is already running then do not start another thread. if (mRenderLoopWorker != null && mRenderLoopWorker.Status == Windows.Foundation.AsyncStatus.Started) { return; } // Create a task for rendering that will be run on a background thread. var workItemHandler = new Windows.System.Threading.WorkItemHandler(action => { lock (mRenderSurfaceCriticalSection) { mOpenGLES.MakeCurrent(mRenderSurface); // ANGLE seems to take a few frames to get itself up and running. This manifests as // calls to glGenTextures returning 0 as a texture name. I don't know why this is, // but we wait until glGenTextures gives us a nonzero texture name before declaring // ANGLE initialized, and only then do we continue onto the main draw loop, meaning // that the user can remain blissfully unaware of this wrinkle. while (action.Status == AsyncStatus.Started) { var tex = GL.GenTexture(); if (tex != 0) { GL.DeleteTexture(tex); break; } } while (action.Status == AsyncStatus.Started) { int panelWidth = 0; int panelHeight = 0; mOpenGLES.GetSurfaceDimensions(mRenderSurface, ref panelWidth, ref panelHeight); GL.Viewport(0, 0, panelWidth, panelHeight); try { OnDraw(EventArgs.Empty); } catch (Exception e) { Debug.WriteLine($"Exception during OnDraw: {e}"); } // The call to eglSwapBuffers might not be successful (i.e. due to Device Lost) // If the call fails, then we must reinitialize EGL and the GL resources. if (mOpenGLES.SwapBuffers(mRenderSurface) != EGL.TRUE) { // XAML objects like the SwapChainPanel must only be manipulated on the UI thread. _ = Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.High, new Windows.UI.Core.DispatchedHandler(() => { RecoverFromLostDevice(); })); return; } } } }); // Run task on a dedicated high priority background thread. mRenderLoopWorker = Windows.System.Threading.ThreadPool.RunAsync(workItemHandler, Windows.System.Threading.WorkItemPriority.High, Windows.System.Threading.WorkItemOptions.TimeSliced); }