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()26 ViewerTest_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()36 ViewerTest_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()50 ViewerTest_ContinuousRedrawer::~ViewerTest_ContinuousRedrawer()
51 {
52   Stop();
53 }
54 
55 // =======================================================================
56 // function : Start
57 // purpose  :
58 // =======================================================================
Start(const Handle (V3d_View)& theView,Standard_Real theTargetFps)59 void 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)91 void 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()114 void 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()127 void 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