1 // Copyright (c) 2019-2020 OPEN CASCADE SAS 2 // 3 // This file is part of Open CASCADE Technology software library. 4 // 5 // This library is free software; you can redistribute it and/or modify it under 6 // the terms of the GNU Lesser General Public License version 2.1 as published 7 // by the Free Software Foundation, with special exception defined in the file 8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT 9 // distribution for complete text of the license and disclaimer of any warranty. 10 // 11 // Alternatively, this file may be used under the terms of Open CASCADE 12 // commercial license or contractual agreement. 13 14 #include <ViewerTest_ContinuousRedrawer.hxx> 15 16 #include <Aspect_DisplayConnection.hxx> 17 #include <Aspect_Window.hxx> 18 #include <OSD.hxx> 19 #include <OSD_Timer.hxx> 20 #include <V3d_View.hxx> 21 22 // ======================================================================= 23 // function : Instance 24 // purpose : 25 // ======================================================================= Instance()26ViewerTest_ContinuousRedrawer& ViewerTest_ContinuousRedrawer::Instance() 27 { 28 static ViewerTest_ContinuousRedrawer aRedrawer; 29 return aRedrawer; 30 } 31 32 // ======================================================================= 33 // function : ViewerTest_ContinuousRedrawer 34 // purpose : 35 // ======================================================================= ViewerTest_ContinuousRedrawer()36ViewerTest_ContinuousRedrawer::ViewerTest_ContinuousRedrawer() 37 : myThread (doThreadWrapper), 38 myWakeEvent (false), 39 myTargetFps (0.0), 40 myToStop (false), 41 myToPause (false) 42 { 43 // 44 } 45 46 // ======================================================================= 47 // function : ~ViewerTest_ContinuousRedrawer 48 // purpose : 49 // ======================================================================= ~ViewerTest_ContinuousRedrawer()50ViewerTest_ContinuousRedrawer::~ViewerTest_ContinuousRedrawer() 51 { 52 Stop(); 53 } 54 55 // ======================================================================= 56 // function : Start 57 // purpose : 58 // ======================================================================= Start(const Handle (V3d_View)& theView,Standard_Real theTargetFps)59void ViewerTest_ContinuousRedrawer::Start (const Handle(V3d_View)& theView, 60 Standard_Real theTargetFps) 61 { 62 if (myView != theView 63 || myTargetFps != theTargetFps) 64 { 65 Stop(); 66 myView = theView; 67 myTargetFps = theTargetFps; 68 } 69 70 if (myThread.GetId() == 0) 71 { 72 myToStop = false; 73 myToPause = false; 74 myThread.Run (this); 75 } 76 else 77 { 78 { 79 Standard_Mutex::Sentry aLock (myMutex); 80 myToStop = false; 81 myToPause = false; 82 } 83 myWakeEvent.Set(); 84 } 85 } 86 87 // ======================================================================= 88 // function : Stop 89 // purpose : 90 // ======================================================================= Stop(const Handle (V3d_View)& theView)91void ViewerTest_ContinuousRedrawer::Stop (const Handle(V3d_View)& theView) 92 { 93 if (!theView.IsNull() 94 && myView != theView) 95 { 96 return; 97 } 98 99 { 100 Standard_Mutex::Sentry aLock (myMutex); 101 myToStop = true; 102 myToPause = false; 103 } 104 myWakeEvent.Set(); 105 myThread.Wait(); 106 myToStop = false; 107 myView.Nullify(); 108 } 109 110 // ======================================================================= 111 // function : Pause 112 // purpose : 113 // ======================================================================= Pause()114void ViewerTest_ContinuousRedrawer::Pause() 115 { 116 if (!myToPause) 117 { 118 Standard_Mutex::Sentry aLock (myMutex); 119 myToPause = true; 120 } 121 } 122 123 // ======================================================================= 124 // function : doThreadLoop 125 // purpose : 126 // ======================================================================= doThreadLoop()127void ViewerTest_ContinuousRedrawer::doThreadLoop() 128 { 129 Handle(Aspect_DisplayConnection) aDisp = new Aspect_DisplayConnection(); 130 OSD_Timer aTimer; 131 aTimer.Start(); 132 Standard_Real aTimeOld = 0.0; 133 const Standard_Real aTargetDur = myTargetFps > 0.0 ? 1.0 / myTargetFps : -1.0; 134 for (;;) 135 { 136 bool toPause = false; 137 { 138 Standard_Mutex::Sentry aLock (myMutex); 139 if (myToStop) 140 { 141 return; 142 } 143 toPause = myToPause; 144 } 145 if (toPause) 146 { 147 myWakeEvent.Wait(); 148 myWakeEvent.Reset(); 149 } 150 151 if (myTargetFps > 0.0) 152 { 153 const Standard_Real aTimeNew = aTimer.ElapsedTime(); 154 const Standard_Real aDuration = aTimeNew - aTimeOld; 155 if (aDuration >= aTargetDur) 156 { 157 myView->Invalidate(); 158 myView->Window()->InvalidateContent (aDisp); 159 aTimeOld = aTimeNew; 160 } 161 } 162 else 163 { 164 myView->Invalidate(); 165 myView->Window()->InvalidateContent (aDisp); 166 } 167 168 OSD::MilliSecSleep (1); 169 } 170 } 171