/// <summary> /// Initializes a new instance of the <see cref="InputGathererThread"/> class. /// </summary> internal InputGathererThread() : base("Input Gatherer", 1000 / Constants.INPUT_FRAMES_PER_SECOND) { m_commandQueue = new ThreadSaveQueue <Action>(); m_gatheredInputFrames = new ThreadSaveQueue <InputFrame>(); m_recoveredInputFrames = new ThreadSaveQueue <InputFrame>(); //m_globalInputHandlers = new List<IInputHandler>(); m_viewInputHandlers = new Dictionary <IInputEnabledView, List <IInputHandler> >(); }
/// <summary> /// Initializes a new instance of the <see cref="ResourceDictionary"/> class. /// </summary> internal ResourceDictionary(EngineDevice device) { m_device = device; this.DeviceIndex = m_device.DeviceIndex; m_lastRenderBlockID = -1; m_renderableResources = new List <IRenderableResource>(); m_renderableResourcesPublic = new ReadOnlyCollection <IRenderableResource>(m_renderableResources); m_resources = new Dictionary <NamedOrGenericKey, ResourceInfo>(); m_resourcesMarkedForUnloading = new ThreadSaveQueue <Resource>(); }
/// <summary> /// Initializes a new instance of the <see cref="Scene" /> class. /// </summary> /// <param name="name">The global name of this scene.</param> /// <param name="registerOnMessenger"> /// Do register this scene for application messaging? /// If true, then the caller has to ensure that the name is only used once /// across the currently executed application. /// </param> public Scene( string name = "", bool registerOnMessenger = false) { if (string.IsNullOrEmpty(name)) { name = DEFAULT_SCENE_NAME; } this.Name = name; m_perFrameData = new CBPerFrame(); m_transformMode2D = Graphics2DTransformMode.Custom; m_customTransform2D = Matrix3x2.Identity; m_virtualScreenSize2D = new Size2F(); m_sceneLayers = new List <SceneLayer>(); m_sceneLayers.Add(new SceneLayer(DEFAULT_LAYER_NAME, this)); m_sceneLayersPublic = new ReadOnlyCollection <SceneLayer>(m_sceneLayers); m_drawing2DLayers = new List <Custom2DDrawingLayer>(); m_sceneComponents = new SceneComponentFlyweight(this); m_asyncInvokesBeforeUpdate = new ThreadSaveQueue <Action>(); m_asyncInvokesUpdateBesideRendering = new ThreadSaveQueue <Action>(); m_registeredResourceDicts = new IndexBasedDynamicCollection <ResourceDictionary>(); m_registeredViews = new IndexBasedDynamicCollection <ViewInformation>(); m_renderParameters = new IndexBasedDynamicCollection <SceneRenderParameters>(); this.CachedUpdateState = new SceneRelatedUpdateState(this); // Try to initialize this scene object InitializeResourceDictionaries(false); // Register the scene for ApplicationMessaging if (registerOnMessenger) { m_syncContext = new SceneSynchronizationContext(this); m_messenger = new SeeingSharpMessenger(); m_messenger.ApplyForGlobalSynchronization( SeeingSharpMessageThreadingBehavior.EnsureMainSyncContextOnSyncCalls, this.Name, m_syncContext); } }
/// <summary> /// Initializes a new instance of the <see cref="MemoryRenderTarget" /> class. /// </summary> /// <param name="pixelHeight">Height of the offline render target in pixels.</param> /// <param name="pixelWidth">Width of the offline render target in pixels.</param> /// <param name="syncContext">Sets the SynchronizationContext which should be used by default.</param> public MemoryRenderTarget(int pixelWidth, int pixelHeight, SynchronizationContext syncContext = null) { //Set confiugration m_pixelWidth = pixelWidth; m_pixelHeight = pixelHeight; m_renderAwaitors = new ThreadSaveQueue <TaskCompletionSource <object> >(); if (syncContext == null) { syncContext = new SynchronizationContext(); } //Create the RenderLoop object GraphicsCore.Touch(); m_renderLoop = new RenderLoop(syncContext, this); m_renderLoop.Camera.SetScreenSize(pixelWidth, pixelHeight); m_renderLoop.RegisterRenderLoop(); }
/// <summary> /// Initializes a new instance of the <see cref="FullscreenRenderTarget" /> class. /// </summary> /// <param name="outputInfo">The target output monitor.</param> /// <param name="initialMode">The initial view mode.</param> public FullscreenRenderTarget(EngineOutputInfo outputInfo, EngineOutputModeInfo initialMode = default(EngineOutputModeInfo)) { outputInfo.EnsureNotNull(nameof(outputInfo)); // Check whether we are inside a win.forms application System.Windows.Forms.WindowsFormsSynchronizationContext syncContext = SynchronizationContext.Current as System.Windows.Forms.WindowsFormsSynchronizationContext; if (syncContext == null) { throw new SeeingSharpException($"{nameof(FullscreenRenderTarget)} muss be created inside a Windows.Forms application context!"); } m_syncContext = syncContext; //Set confiugration m_targetOutput = outputInfo; m_targetOutputMode = initialMode; if (m_targetOutputMode.HostOutput != outputInfo) { m_targetOutputMode = m_targetOutput.DefaultMode; } m_renderAwaitors = new ThreadSaveQueue <TaskCompletionSource <object> >(); // Ensure that graphics is initialized GraphicsCore.Touch(); // Create the dummy form m_dummyForm = new DummyForm(); m_dummyForm.SetStyleCustom(ControlStyles.AllPaintingInWmPaint, true); m_dummyForm.SetStyleCustom(ControlStyles.ResizeRedraw, true); m_dummyForm.SetStyleCustom(ControlStyles.OptimizedDoubleBuffer, false); m_dummyForm.SetStyleCustom(ControlStyles.Opaque, true); m_dummyForm.SetStyleCustom(ControlStyles.Selectable, true); m_dummyForm.SetDoubleBuffered(false); m_dummyForm.MouseEnter += (sender, eArgs) => Cursor.Hide(); m_dummyForm.MouseLeave += (sender, eArgs) => Cursor.Show(); m_dummyForm.HandleDestroyed += OnDummyForm_HandleDestroyed; m_dummyForm.GotFocus += OnDummyForm_GotFocus; m_dummyForm.CreateControl(); // Create and start the renderloop m_renderLoop = new RenderLoop(syncContext, this); m_renderLoop.Camera.SetScreenSize(m_targetOutputMode.PixelWidth, m_targetOutputMode.PixelHeight); m_renderLoop.RegisterRenderLoop(); }
/// <summary> /// Initializes a new instance of the <see cref="SceneComponentFlyweight"/> class. /// </summary> internal SceneComponentFlyweight(Scene owner) { m_owner = owner; m_componentRequests = new ThreadSaveQueue <SceneComponentRequest>(); m_attachedComponents = new List <SceneComponentInfo>(); }
/// <summary> /// Renders all given scenes using the different devices and performs "UpdateBesideRendering" step. /// </summary> /// <param name="registeredRenderLoops">The registered render loops on the current pass.</param> /// <param name="scenesToRender">All scenes to be updated / rendered.</param> /// <param name="devicesInUse">The rendering devices that are in use.</param> /// <param name="updateState">Current global update state.</param> private void RenderAndUpdateBeside( List <RenderLoop> registeredRenderLoops, List <Scene> scenesToRender, List <EngineDevice> devicesInUse, UpdateState updateState) { using (var perfToken = m_host.BeginMeasureActivityDuration(Constants.PERF_GLOBAL_RENDER_AND_UPDATE_BESIDE)) { ThreadSaveQueue <RenderLoop> invalidRenderLoops = new ThreadSaveQueue <RenderLoop>(); // Trigger all tasks for 'Update' pass Parallel.For(0, devicesInUse.Count + scenesToRender.Count, (actTaskIndex) => { if (actTaskIndex < devicesInUse.Count) { // Render all targets for the current device EngineDevice actDevice = devicesInUse[actTaskIndex]; using (var perfTokenInner = m_host.BeginMeasureActivityDuration(string.Format(Constants.PERF_GLOBAL_RENDER_DEVICE, actDevice.AdapterDescription))) { for (int loop = 0; loop < registeredRenderLoops.Count; loop++) { RenderLoop actRenderLoop = registeredRenderLoops[loop]; try { if (actRenderLoop.Device == actDevice) { actRenderLoop.Render(); } } catch (Exception) { // Mark this renderloop as invalid invalidRenderLoops.Enqueue(actRenderLoop); } } } } else { // Perform updates beside rendering for the current scene int sceneIndex = actTaskIndex - devicesInUse.Count; using (var perfTokenInner = m_host.BeginMeasureActivityDuration(string.Format(Constants.PERF_GLOBAL_UPDATE_BESIDE, sceneIndex))) { Scene actScene = scenesToRender[sceneIndex]; SceneRelatedUpdateState actUpdateState = actScene.CachedUpdateState; actUpdateState.OnStartSceneUpdate(actScene, updateState, null); actScene.UpdateBesideRender(actUpdateState); } } }); // Handle all invalid render loops if (invalidRenderLoops.HasAny()) { foreach (var actRenderLoop in invalidRenderLoops.DequeueAll()) { DeregisterRenderLoop(actRenderLoop); } } // Reset camera changed flags foreach (RenderLoop actRenderLoop in registeredRenderLoops) { actRenderLoop.Camera.StateChanged = false; } } }
/// <summary> /// Updates the scene's and prepares all views for rendering. /// </summary> /// <param name="renderingRenderLoops">The registered render loops on the current pass.</param> /// <param name="scenesToRender">All scenes to be updated / rendered.</param> /// <param name="devicesInUse">The rendering devices that are in use.</param> /// <param name="inputFrames">All InputFrames gathered during last render.</param> /// <param name="updateState">Current global update state.</param> private async Task UpdateAndPrepareRendering(List <RenderLoop> renderingRenderLoops, List <Scene> scenesToRender, List <EngineDevice> devicesInUse, IEnumerable <InputFrame> inputFrames, UpdateState updateState) { using (var perfToken = m_host.BeginMeasureActivityDuration(Constants.PERF_GLOBAL_UPDATE_AND_PREPARE)) { List <Action> additionalContinuationActions = new List <Action>(); object additionalContinuationActionsLock = new object(); // Trigger all tasks for preparing views List <Task <List <Action> > > prepareRenderTasks = new List <Task <List <Action> > >(renderingRenderLoops.Count); for (int actDeviceIndex = 0; actDeviceIndex < devicesInUse.Count; actDeviceIndex++) { EngineDevice actDevice = devicesInUse[actDeviceIndex]; for (int loop = 0; loop < renderingRenderLoops.Count; loop++) { RenderLoop actRenderLoop = renderingRenderLoops[loop]; if (actRenderLoop.Device == actDevice) { // Call prepare render and wait for the answer // => Error handling is a bit tricky.. // Errors are catched by the continuation action var actTask = actRenderLoop.PrepareRenderAsync(); prepareRenderTasks.Add(actTask.ContinueWith((givenTask) => { if (!givenTask.IsFaulted) { return(givenTask.Result); } else { // Deregister this RenderLoop lock (additionalContinuationActionsLock) { additionalContinuationActions.Add(() => { this.DeregisterRenderLoop(actRenderLoop); renderingRenderLoops.Remove(actRenderLoop); }); } return(new List <Action>()); } })); } } } // Handle initial configuration of render loops (=> No current device) for (int loop = 0; loop < renderingRenderLoops.Count; loop++) { RenderLoop actRenderLoop = renderingRenderLoops[loop]; if (actRenderLoop.Device == null) { try { Task <List <Action> > actPrepareRenderTask = actRenderLoop.PrepareRenderAsync(); await actPrepareRenderTask; lock (additionalContinuationActionsLock) { additionalContinuationActions.AddRange(actPrepareRenderTask.Result); } } catch (Exception) { // Deregister this RenderLoop lock (additionalContinuationActionsLock) { additionalContinuationActions.Add(() => { this.DeregisterRenderLoop(actRenderLoop); renderingRenderLoops.Remove(actRenderLoop); }); } } } } // Update all scenes ThreadSaveQueue <Exception> exceptionsDuringUpdate = new ThreadSaveQueue <Exception>(); Parallel.For(0, scenesToRender.Count, (actTaskIndex) => { try { using (var perfToken2 = m_host.BeginMeasureActivityDuration( string.Format(Constants.PERF_GLOBAL_UPDATE_SCENE, actTaskIndex))) { Scene actScene = scenesToRender[actTaskIndex]; SceneRelatedUpdateState actUpdateState = actScene.CachedUpdateState; actUpdateState.OnStartSceneUpdate(actScene, updateState, inputFrames); actScene.Update(actUpdateState); } } catch (Exception ex) { exceptionsDuringUpdate.Enqueue(ex); } }); // Await synchronizations with the view(s) if (prepareRenderTasks.Count > 0) { await Task.WhenAll(prepareRenderTasks.ToArray()); } // Throw exceptions if any occurred during scene update // => This would be a fatal exception, so throw up to main loop if (exceptionsDuringUpdate.HasAny()) { throw new AggregateException("Error(s) during Scene update!", exceptionsDuringUpdate.DequeueAll().ToArray()); } // Trigger all continuation actions returned by the previously executed prepare tasks foreach (var actPrepareTasks in prepareRenderTasks) { if (actPrepareTasks.IsFaulted || actPrepareTasks.IsCanceled) { continue; } foreach (Action actContinuationAction in actPrepareTasks.Result) { actContinuationAction(); } } foreach (var actAction in additionalContinuationActions) { actAction(); } // Reset all dummy flags before rendering foreach (var actRenderLoop in renderingRenderLoops) { actRenderLoop.ResetFlagsBeforeRendering(); } // Unload all derigistered RenderLoops await UpdateRenderLoopRegistrationsAsync(renderingRenderLoops); } }