public void Refresh() { lock (_lockRender) { try { FinalBuffer.RenderToScreen(); } catch (Exception ex) { Platform.Log(LogLevel.Error, ex, "Buffer Refresh Exception"); } } }
private void Render(bool fullQuality, UpdateOverlayCallback updateOverlayCallback) { lock (_lockRender) { try { var mirrored = false; var mTime = -1; if (_sceneGraphRoot != null) { _sceneGraphRoot.UpdateSceneGraph(_vtkRenderer); mirrored = _sceneGraphRoot.ViewPortSpatialTransform.FlipX ^ _sceneGraphRoot.ViewPortSpatialTransform.FlipY; mTime = _sceneGraphRoot.GetMTime(); } _vtkRenderWindow.SetDesiredUpdateRate(fullQuality ? _stillFrameRate : _dynamicFrameRate); // decide whether or not to render the VTK layer of the image based on the last modification time of the scene graph // do not use the renderer or renderwindow's MTime because they are affected by the update rate change above var renderTime = -1f; if (mTime > _lastRenderTime) { var renderClock = _renderClock ?? (_renderClock = new CodeClock()); renderClock.Clear(); renderClock.Start(); var bmpData = ImageBuffer.Bitmap.LockBits(new Rectangle(0, 0, _clientRectangle.Width, _clientRectangle.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppRgb); try { _vtkRenderWindow.Render(); // since we just rendered, the correct OpenGL context is still 'current' on this thread so we don't need to makeCurrent glReadBuffer(GL_FRONT_LEFT); // select the front buffer glDisable(GL_TEXTURE_2D); // according to VTK code, some video drivers have issues with this feature glPixelStorei(GL_PACK_ALIGNMENT, 4); // align to 4 byte boundaries (since we're copying 32-bit pixels anyway) // now read from the OpenGL buffer directly into our surface buffer var pData = bmpData.Stride > 0 ? bmpData.Scan0 : bmpData.Scan0 + (bmpData.Height - 1) * bmpData.Stride; glReadPixels(0, 0, _clientRectangle.Width, _clientRectangle.Height, GL_BGRA, OpenGlImplementation.ReadPixelsTypeBgra, pData); // OpenGL buffer data is a bottom-up image, and the GDI+ memory bitmap might be top-bottom, so we flip the scan lines here if (bmpData.Stride > 0) { FlipImage(bmpData.Scan0, bmpData.Height, bmpData.Stride); } } finally { ImageBuffer.Bitmap.UnlockBits(bmpData); // only record the last render time for full quality renders only if (fullQuality) { _lastRenderTime = mTime; } } renderClock.Stop(); renderTime = renderClock.Seconds; // perform a single horizontal flip here if necessary, since the VTK camera does not support a mirrorred view port ImageBuffer.Bitmap.RotateFlip(mirrored ? RotateFlipType.RotateNoneFlipX : RotateFlipType.RotateNoneFlipNone); } if (renderTime >= 0) { if (VtkPresentationImageRenderer.ShowFps) { var font = _gdiFont ?? (_gdiFont = new Font(FontFamily.GenericMonospace, 12, FontStyle.Bold, GraphicsUnit.Point)); var msg = string.Format("FPS: {0,6}", renderTime >= 0.000001 ? (1 / renderTime).ToString("f1") : "------"); ImageBuffer.Graphics.DrawString(msg, font, Brushes.Black, 11, 11); ImageBuffer.Graphics.DrawString(msg, font, Brushes.White, 10, 10); if (fullQuality) { msg = string.Format("TTI: {0,6} ms", renderTime >= 0.000001 ? (renderTime * 1000).ToString("f1") : "------"); ImageBuffer.Graphics.DrawString(msg, font, Brushes.Black, 11, 15 + 11); ImageBuffer.Graphics.DrawString(msg, font, Brushes.White, 10, 15 + 10); } } } if (fullQuality) { if (_reportRenderingPerformance && _statRenderFrameCount > 0 && _statRenderDuration > 0.000001) { var avgLowFrameRate = _statRenderFrameCount / _statRenderDuration; Platform.Log(LogLevel.Info, "VTKRenderer: LOD FPS: {0:f1} ({1} frame(s) in {2:f1} ms); FINAL: {3:f1} ms", avgLowFrameRate, _statRenderFrameCount, _statRenderDuration * 1000, renderTime * 1000); } _statRenderFrameCount = 0; _statRenderDuration = 0; } else { _statRenderDuration += renderTime; ++_statRenderFrameCount; } if (updateOverlayCallback != null) { updateOverlayCallback.Invoke(); } FinalBuffer.RenderImage(ImageBuffer); FinalBuffer.RenderImage(OverlayBuffer); FinalBuffer.RenderToScreen(); EventsHelper.Fire(_invalidated, this, new EventArgs()); } catch (Exception ex) { Platform.Log(LogLevel.Error, ex, "VTK Rendering Exception"); } } }