summaryrefslogtreecommitdiff
path: root/slideshow/source
diff options
context:
space:
mode:
authorAndre Fischer <af@openoffice.org>2009-04-27 11:25:13 +0000
committerAndre Fischer <af@openoffice.org>2009-04-27 11:25:13 +0000
commitaa02f1da390cb9b1225de978f8e2965c34e3a45f (patch)
tree069813bebb495be1d7714d388a9587b2786bf068 /slideshow/source
parent881043d1f01fad663c0a17f11cbe2dab79e31217 (diff)
#i98792# Synchronize frame rate during animations.
Diffstat (limited to 'slideshow/source')
-rw-r--r--slideshow/source/engine/slideshowimpl.cxx130
1 files changed, 128 insertions, 2 deletions
diff --git a/slideshow/source/engine/slideshowimpl.cxx b/slideshow/source/engine/slideshowimpl.cxx
index 8fd1cb07ca48..5ace44acda65 100644
--- a/slideshow/source/engine/slideshowimpl.cxx
+++ b/slideshow/source/engine/slideshowimpl.cxx
@@ -110,6 +110,65 @@ using namespace ::slideshow::internal;
namespace {
+/** During animations the update() method tells its caller to call it as
+ soon as possible. This gives us more time to render the next frame and
+ still maintain a steady frame rate. This class is responsible for
+ synchronizing the display of new frames and thus keeping the frame rate
+ steady.
+*/
+class FrameSynchronization
+{
+public:
+ /** Create new object with a predefined duration between two frames.
+ @param nFrameDuration
+ The preferred duration between the display of two frames in
+ seconds.
+ */
+ FrameSynchronization (const double nFrameDuration);
+
+ /** Set the current time as the time at which the current frame is
+ displayed. From this the target time of the next frame is derived.
+ */
+ void MarkCurrentFrame (void);
+
+ /** When there is time left until the next frame is due then wait.
+ Otherwise return without delay.
+ */
+ void Synchronize (void);
+
+ /** Activate frame synchronization when an animation is active and
+ frames are to be displayed in a steady rate. While active
+ Synchronize() will wait until the frame duration time has passed.
+ */
+ void Activate (void);
+
+ /** Deactivate frame sychronization when no animation is active and the
+ time between frames depends on user actions and other external
+ sources. While deactivated Synchronize() will return without delay.
+ */
+ void Deactivate (void);
+
+private:
+ /** The timer that is used for synchronization is independent from the
+ one used by SlideShowImpl: it is not paused or modified by
+ animations.
+ */
+ canvas::tools::ElapsedTime maTimer;
+ /** Time between the display of frames. Enforced only when mbIsActive
+ is <TRUE/>.
+ */
+ const double mnFrameDuration;
+ /** Time (of maTimer) when the next frame shall be displayed.
+ Synchronize() will wait until this time.
+ */
+ double mnNextFrameTargetTime;
+ /** Synchronize() will wait only when this flag is <TRUE/>. Otherwise
+ it returns immediately.
+ */
+ bool mbIsActive;
+};
+
+
/******************************************************************************
SlideShowImpl
@@ -407,6 +466,7 @@ private:
bool mbDisableAnimationZOrder;
EffectRewinder maEffectRewinder;
+ FrameSynchronization maFrameSynchronization;
};
@@ -507,7 +567,9 @@ SlideShowImpl::SlideShowImpl(
mbShowPaused( false ),
mbSlideShowIdle( true ),
mbDisableAnimationZOrder( false ),
- maEffectRewinder(maEventMultiplexer, maEventQueue, maUserEventQueue)
+ maEffectRewinder(maEventMultiplexer, maEventQueue, maUserEventQueue),
+ maFrameSynchronization(1.0 / FrameRate::PreferredFramesPerSecond)
+
{
// keep care not constructing any UNO references to this inside ctor,
// shift that code to create()!
@@ -1686,6 +1748,7 @@ sal_Bool SlideShowImpl::update( double & nNextTimeout )
maActivitiesQueue.process();
// commit frame to screen
+ maFrameSynchronization.Synchronize();
maScreenUpdater.commitUpdates();
// TODO(Q3): remove need to call dequeued() from
@@ -1729,7 +1792,13 @@ sal_Bool SlideShowImpl::update( double & nNextTimeout )
{
// Activity queue is not empty. Tell caller that we would
// like to render another frame.
- nNextTimeout = 1.0 / FrameRate::PreferredFramesPerSecond;
+
+ // Return a zero time-out to signal our caller to call us
+ // back as soon as possible. The actual timing, waiting the
+ // appropriate amount of time between frames, is then done
+ // by the maFrameSynchronization object.
+ nNextTimeout = 0;
+ maFrameSynchronization.Activate();
}
else
{
@@ -1743,6 +1812,10 @@ sal_Bool SlideShowImpl::update( double & nNextTimeout )
// ensure positive value:
nNextTimeout = std::max( 0.0, maEventQueue.nextTimeout() );
+
+ // There is no active animation so the frame rate does not
+ // need to be synchronized.
+ maFrameSynchronization.Deactivate();
}
mbSlideShowIdle = false;
@@ -2038,6 +2111,59 @@ bool SlideShowImpl::handleAnimationEvent( const AnimationNodeSharedPtr& rNode )
return true;
}
+
+//===== FrameSynchronization ==================================================
+
+FrameSynchronization::FrameSynchronization (const double nFrameDuration)
+ : maTimer(),
+ mnFrameDuration(nFrameDuration),
+ mnNextFrameTargetTime(0),
+ mbIsActive(false)
+{
+ MarkCurrentFrame();
+}
+
+
+
+
+void FrameSynchronization::MarkCurrentFrame (void)
+{
+ mnNextFrameTargetTime = maTimer.getElapsedTime() + mnFrameDuration;
+}
+
+
+
+
+void FrameSynchronization::Synchronize (void)
+{
+ if (mbIsActive)
+ {
+ // Do busy waiting for now.
+ while (maTimer.getElapsedTime() < mnNextFrameTargetTime)
+ ;
+ }
+
+ MarkCurrentFrame();
+}
+
+
+
+
+void FrameSynchronization::Activate (void)
+{
+ mbIsActive = true;
+}
+
+
+
+
+void FrameSynchronization::Deactivate (void)
+{
+ mbIsActive = false;
+}
+
+
+
} // anon namespace
namespace sdecl = comphelper::service_decl;