0030939: Draw Harness, ViewerTest - AIS_ViewCube animation does not work on Linux...
[occt.git] / src / ViewerTest / ViewerTest_ContinuousRedrawer.cxx
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
21 // =======================================================================
22 // function : Instance
23 // purpose  :
24 // =======================================================================
25 ViewerTest_ContinuousRedrawer& ViewerTest_ContinuousRedrawer::Instance()
26 {
27   static ViewerTest_ContinuousRedrawer aRedrawer;
28   return aRedrawer;
29 }
30
31 // =======================================================================
32 // function : ViewerTest_ContinuousRedrawer
33 // purpose  :
34 // =======================================================================
35 ViewerTest_ContinuousRedrawer::ViewerTest_ContinuousRedrawer()
36 : myThread (doThreadWrapper),
37   myWakeEvent (false),
38   myTargetFps (0.0),
39   myToStop (false),
40   myToPause (false)
41 {
42   //
43 }
44
45 // =======================================================================
46 // function : ~ViewerTest_ContinuousRedrawer
47 // purpose  :
48 // =======================================================================
49 ViewerTest_ContinuousRedrawer::~ViewerTest_ContinuousRedrawer()
50 {
51   Stop();
52 }
53
54 // =======================================================================
55 // function : Start
56 // purpose  :
57 // =======================================================================
58 void ViewerTest_ContinuousRedrawer::Start (const Handle(Aspect_Window)& theWindow,
59                                            Standard_Real theTargetFps)
60 {
61   if (myWindow != theWindow
62    || myTargetFps != theTargetFps)
63   {
64     Stop();
65     myWindow = theWindow;
66     myTargetFps = theTargetFps;
67   }
68
69   if (myThread.GetId() == 0)
70   {
71     myToStop = false;
72     myToPause = false;
73     myThread.Run (this);
74   }
75   else
76   {
77     {
78       Standard_Mutex::Sentry aLock (myMutex);
79       myToStop = false;
80       myToPause = false;
81     }
82     myWakeEvent.Set();
83   }
84 }
85
86 // =======================================================================
87 // function : Start
88 // purpose  :
89 // =======================================================================
90 void ViewerTest_ContinuousRedrawer::Stop (const Handle(Aspect_Window)& theWindow)
91 {
92   if (!theWindow.IsNull()
93     && myWindow != theWindow)
94   {
95     return;
96   }
97
98   {
99     Standard_Mutex::Sentry aLock (myMutex);
100     myToStop = true;
101     myToPause = false;
102   }
103   myWakeEvent.Set();
104   myThread.Wait();
105   myToStop = false;
106   myWindow.Nullify();
107 }
108
109 // =======================================================================
110 // function : doThreadLoop
111 // purpose  :
112 // =======================================================================
113 void ViewerTest_ContinuousRedrawer::Pause()
114 {
115   if (!myToPause)
116   {
117     Standard_Mutex::Sentry aLock (myMutex);
118     myToPause = true;
119   }
120 }
121
122 // =======================================================================
123 // function : doThreadLoop
124 // purpose  :
125 // =======================================================================
126 void ViewerTest_ContinuousRedrawer::doThreadLoop()
127 {
128   Handle(Aspect_DisplayConnection) aDisp = new Aspect_DisplayConnection();
129   OSD_Timer aTimer;
130   aTimer.Start();
131   Standard_Real aTimeOld = 0.0;
132   const Standard_Real aTargetDur = myTargetFps > 0.0 ? 1.0 / myTargetFps : -1.0;
133   for (;;)
134   {
135     bool toPause = false;
136     {
137       Standard_Mutex::Sentry aLock (myMutex);
138       if (myToStop)
139       {
140         return;
141       }
142       toPause = myToPause;
143     }
144     if (toPause)
145     {
146       myWakeEvent.Wait();
147       myWakeEvent.Reset();
148     }
149
150     if (myTargetFps > 0.0)
151     {
152       const Standard_Real aTimeNew  = aTimer.ElapsedTime();
153       const Standard_Real aDuration = aTimeNew - aTimeOld;
154       if (aDuration >= aTargetDur)
155       {
156         myWindow->InvalidateContent (aDisp);
157         aTimeOld = aTimeNew;
158       }
159     }
160     else
161     {
162       myWindow->InvalidateContent (aDisp);
163     }
164
165     OSD::MilliSecSleep (1);
166   }
167 }