// Copyright (c) 2019-2020 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // // This library is free software; you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License version 2.1 as published // by the Free Software Foundation, with special exception defined in the file // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT // distribution for complete text of the license and disclaimer of any warranty. // // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. #include #include #include #include #include // ======================================================================= // function : Instance // purpose : // ======================================================================= ViewerTest_ContinuousRedrawer& ViewerTest_ContinuousRedrawer::Instance() { static ViewerTest_ContinuousRedrawer aRedrawer; return aRedrawer; } // ======================================================================= // function : ViewerTest_ContinuousRedrawer // purpose : // ======================================================================= ViewerTest_ContinuousRedrawer::ViewerTest_ContinuousRedrawer() : myThread (doThreadWrapper), myWakeEvent (false), myTargetFps (0.0), myToStop (false), myToPause (false) { // } // ======================================================================= // function : ~ViewerTest_ContinuousRedrawer // purpose : // ======================================================================= ViewerTest_ContinuousRedrawer::~ViewerTest_ContinuousRedrawer() { Stop(); } // ======================================================================= // function : Start // purpose : // ======================================================================= void ViewerTest_ContinuousRedrawer::Start (const Handle(Aspect_Window)& theWindow, Standard_Real theTargetFps) { if (myWindow != theWindow || myTargetFps != theTargetFps) { Stop(); myWindow = theWindow; myTargetFps = theTargetFps; } if (myThread.GetId() == 0) { myToStop = false; myToPause = false; myThread.Run (this); } else { { Standard_Mutex::Sentry aLock (myMutex); myToStop = false; myToPause = false; } myWakeEvent.Set(); } } // ======================================================================= // function : Start // purpose : // ======================================================================= void ViewerTest_ContinuousRedrawer::Stop (const Handle(Aspect_Window)& theWindow) { if (!theWindow.IsNull() && myWindow != theWindow) { return; } { Standard_Mutex::Sentry aLock (myMutex); myToStop = true; myToPause = false; } myWakeEvent.Set(); myThread.Wait(); myToStop = false; myWindow.Nullify(); } // ======================================================================= // function : doThreadLoop // purpose : // ======================================================================= void ViewerTest_ContinuousRedrawer::Pause() { if (!myToPause) { Standard_Mutex::Sentry aLock (myMutex); myToPause = true; } } // ======================================================================= // function : doThreadLoop // purpose : // ======================================================================= void ViewerTest_ContinuousRedrawer::doThreadLoop() { Handle(Aspect_DisplayConnection) aDisp = new Aspect_DisplayConnection(); OSD_Timer aTimer; aTimer.Start(); Standard_Real aTimeOld = 0.0; const Standard_Real aTargetDur = myTargetFps > 0.0 ? 1.0 / myTargetFps : -1.0; for (;;) { bool toPause = false; { Standard_Mutex::Sentry aLock (myMutex); if (myToStop) { return; } toPause = myToPause; } if (toPause) { myWakeEvent.Wait(); myWakeEvent.Reset(); } if (myTargetFps > 0.0) { const Standard_Real aTimeNew = aTimer.ElapsedTime(); const Standard_Real aDuration = aTimeNew - aTimeOld; if (aDuration >= aTargetDur) { myWindow->InvalidateContent (aDisp); aTimeOld = aTimeNew; } } else { myWindow->InvalidateContent (aDisp); } OSD::MilliSecSleep (1); } }