using VideoTimer in Desktop and iOS version. stopping it, when the pause is longer than 60 cycles. refactored WindowHandle. implemented QtVideoTimer. closes #356

This commit is contained in:
rachytski 2011-10-24 19:15:40 +03:00 committed by Alex Zolotarev
parent 9906d541f6
commit 943d893105
15 changed files with 288 additions and 147 deletions

View file

@ -9,7 +9,8 @@
#include "../../map/drawer_yg.hpp"
#include "../../map/framework.hpp"
#include "../../map/feature_vec_model.hpp"
#include "RenderBuffer.hpp"
#include "../../platform/video_timer.hpp"
#include"RenderBuffer.hpp"
namespace iphone
{
@ -41,17 +42,15 @@ typedef Framework<model::FeaturesFetcher> framework_t;
@public
shared_ptr<iphone::WindowHandle> windowHandle;
shared_ptr<WindowHandle> windowHandle;
shared_ptr<VideoTimer> videoTimer;
shared_ptr<DrawerYG> drawer;
shared_ptr<iphone::RenderBuffer> renderBuffer;
}
// Called as a result of invalidate on iphone::WindowHandle
- (void)drawViewOnMainThread;
@property (nonatomic, assign) CADisplayLink * displayLink;
- (void) drawFrame;
@property (nonatomic, assign) framework_t * framework;
@property (nonatomic, assign) shared_ptr<iphone::WindowHandle> windowHandle;
@property (nonatomic, assign) shared_ptr<WindowHandle> windowHandle;
@property (nonatomic, assign) shared_ptr<DrawerYG> drawer;
@property (nonatomic, assign) shared_ptr<iphone::RenderContext> renderContext;
@property (nonatomic, assign) shared_ptr<iphone::RenderBuffer> renderBuffer;

View file

@ -2,7 +2,6 @@
#import <OpenGLES/EAGLDrawable.h>
#import "EAGLView.h"
#import "WindowHandle.h"
#include "../../yg/screen.hpp"
#include "../../yg/texture.hpp"
@ -13,18 +12,15 @@
#include "RenderBuffer.hpp"
#include "RenderContext.hpp"
bool _doRepaint = true;
bool _inRepaint = false;
@implementation EAGLView
@synthesize framework;
@synthesize windowHandle;
@synthesize videoTimer;
@synthesize drawer;
@synthesize renderContext;
@synthesize renderBuffer;
@synthesize resourceManager;
@synthesize displayLink;
// You must implement this method
+ (Class)layerClass
@ -143,13 +139,19 @@ bool _inRepaint = false;
drawer = shared_ptr<DrawerYG>(new DrawerYG(p));
windowHandle = shared_ptr<iphone::WindowHandle>(new iphone::WindowHandle(_doRepaint));
windowHandle.reset(new WindowHandle());
windowHandle->setUpdatesEnabled(false);
typedef void (*drawFrameFn)(id, SEL);
SEL drawFrameSel = @selector(drawFrame);
drawFrameFn drawFrameImpl = (drawFrameFn)[self methodForSelector:drawFrameSel];
videoTimer.reset(CreateIOSVideoTimer(bind(drawFrameImpl, self, drawFrameSel)));
windowHandle->setVideoTimer(videoTimer);
windowHandle->setRenderContext(renderContext);
displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(drawView)];
displayLink.frameInterval = 1;
[displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}
return self;
@ -174,7 +176,7 @@ bool _inRepaint = false;
drawer->screen()->endFrame();
}
- (void)drawView
- (void)drawFrame
{
shared_ptr<PaintEvent> pe(new PaintEvent(drawer.get()));
if (windowHandle->needRedraw())
@ -187,16 +189,6 @@ bool _inRepaint = false;
}
}
- (void)drawViewThunk:(id)obj
{
[self drawView];
}
- (void)drawViewOnMainThread
{
[self performSelectorOnMainThread:@selector(drawViewThunk:) withObject:nil waitUntilDone:NO];
}
- (void)layoutSubviews
{
CGFloat const scale = self.contentScaleFactor;
@ -206,8 +198,7 @@ bool _inRepaint = false;
- (void)dealloc
{
[displayLink invalidate];
[displayLink release];
videoTimer.reset();
[EAGLContext setCurrentContext:nil];
[super dealloc];
}

View file

@ -2,7 +2,6 @@
#import "SearchVC.h"
#import "MapsAppDelegate.h"
#import "EAGLView.h"
#import "WindowHandle.h"
#import "../Settings/SettingsManager.h"
#include "RenderContext.hpp"
@ -122,7 +121,7 @@ storage::Storage m_storage;
// Here we're creating view and window handle in it, and later we should pass framework to the view
EAGLView * v = (EAGLView *)self.view;
shared_ptr<iphone::WindowHandle> windowHandle = [(EAGLView*)self.view windowHandle];
shared_ptr<WindowHandle> windowHandle = [(EAGLView*)self.view windowHandle];
shared_ptr<yg::ResourceManager> resourceManager = [(EAGLView*)self.view resourceManager];
m_framework = FrameworkFactory<model::FeaturesFetcher>::CreateFramework(windowHandle, 40);

View file

@ -1,17 +0,0 @@
#import "RenderContext.hpp"
#include "../../../map/window_handle.hpp"
@class EAGLView;
namespace iphone
{
class WindowHandle : public ::WindowHandle
{
bool * m_doRepaint;
public:
WindowHandle(bool & doRepaint);
virtual void invalidateImpl();
};
}

View file

@ -1,15 +0,0 @@
#import "WindowHandle.h"
#import "EAGLView.h"
namespace iphone
{
WindowHandle::WindowHandle(bool & doRepaint)
{
m_doRepaint = &doRepaint;
}
void WindowHandle::invalidateImpl()
{
*m_doRepaint = true;
}
}

View file

@ -40,7 +40,6 @@
EE583CBB12F773F00042CBE3 /* unicode_blocks.txt in Resources */ = {isa = PBXBuildFile; fileRef = EE583CBA12F773F00042CBE3 /* unicode_blocks.txt */; };
EE7F29811219ECA300EB67A9 /* RenderBuffer.mm in Sources */ = {isa = PBXBuildFile; fileRef = EE7F297D1219ECA300EB67A9 /* RenderBuffer.mm */; };
EE7F29821219ECA300EB67A9 /* RenderContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = EE7F297E1219ECA300EB67A9 /* RenderContext.mm */; };
EE7F29831219ECA300EB67A9 /* WindowHandle.mm in Sources */ = {isa = PBXBuildFile; fileRef = EE7F29801219ECA300EB67A9 /* WindowHandle.mm */; };
EEA61601134C496A003A9827 /* 01_dejavusans.ttf in Resources */ = {isa = PBXBuildFile; fileRef = EEA615E5134C4968003A9827 /* 01_dejavusans.ttf */; };
EEA61602134C496A003A9827 /* 02_wqy-microhei.ttf in Resources */ = {isa = PBXBuildFile; fileRef = EEA615E6134C4968003A9827 /* 02_wqy-microhei.ttf */; };
EEA61603134C496A003A9827 /* 03_jomolhari-id-a3d.ttf in Resources */ = {isa = PBXBuildFile; fileRef = EEA615E7134C4968003A9827 /* 03_jomolhari-id-a3d.ttf */; };
@ -649,8 +648,6 @@
EE7F297C1219ECA300EB67A9 /* RenderBuffer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; name = RenderBuffer.hpp; path = Classes/RenderBuffer.hpp; sourceTree = SOURCE_ROOT; };
EE7F297D1219ECA300EB67A9 /* RenderBuffer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; name = RenderBuffer.mm; path = Classes/RenderBuffer.mm; sourceTree = SOURCE_ROOT; };
EE7F297E1219ECA300EB67A9 /* RenderContext.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; name = RenderContext.mm; path = Classes/RenderContext.mm; sourceTree = SOURCE_ROOT; };
EE7F297F1219ECA300EB67A9 /* WindowHandle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = WindowHandle.h; path = Classes/WindowHandle.h; sourceTree = SOURCE_ROOT; };
EE7F29801219ECA300EB67A9 /* WindowHandle.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; name = WindowHandle.mm; path = Classes/WindowHandle.mm; sourceTree = SOURCE_ROOT; };
EEA615E5134C4968003A9827 /* 01_dejavusans.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = 01_dejavusans.ttf; path = ../../data/01_dejavusans.ttf; sourceTree = SOURCE_ROOT; };
EEA615E6134C4968003A9827 /* 02_wqy-microhei.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "02_wqy-microhei.ttf"; path = "../../data/02_wqy-microhei.ttf"; sourceTree = SOURCE_ROOT; };
EEA615E7134C4968003A9827 /* 03_jomolhari-id-a3d.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "03_jomolhari-id-a3d.ttf"; path = "../../data/03_jomolhari-id-a3d.ttf"; sourceTree = SOURCE_ROOT; };
@ -1271,8 +1268,6 @@
EE7F297D1219ECA300EB67A9 /* RenderBuffer.mm */,
EE16192B126E374500622BD0 /* RenderContext.hpp */,
EE7F297E1219ECA300EB67A9 /* RenderContext.mm */,
EE7F297F1219ECA300EB67A9 /* WindowHandle.h */,
EE7F29801219ECA300EB67A9 /* WindowHandle.mm */,
46F26CD610F623BA00ECCA39 /* EAGLView.h */,
46F26CD710F623BA00ECCA39 /* EAGLView.mm */,
1D3623240D0F684500981E51 /* MapsAppDelegate.h */,
@ -2609,7 +2604,6 @@
FA4135ED120A263C0062D5B4 /* SettingsManager.mm in Sources */,
EE7F29811219ECA300EB67A9 /* RenderBuffer.mm in Sources */,
EE7F29821219ECA300EB67A9 /* RenderContext.mm in Sources */,
EE7F29831219ECA300EB67A9 /* WindowHandle.mm in Sources */,
FAF37EFF126DCE6F005EA154 /* IPhoneDownload.mm in Sources */,
FAF37F00126DCE6F005EA154 /* IPhoneDownloadManager.mm in Sources */,
FAFCB63613366E78001A5C59 /* WebViewController.mm in Sources */,

View file

@ -69,6 +69,7 @@ SOURCES += \
benchmark_render_policy_mt.cpp \
ruler.cpp \
measurement_utils.cpp \
window_handle.cpp
!iphone*:!bada*:!android* {
HEADERS += qgl_render_context.hpp

98
map/window_handle.cpp Normal file
View file

@ -0,0 +1,98 @@
#include "window_handle.hpp"
WindowHandle::WindowHandle() :
m_hasPendingUpdates(false),
m_isUpdatesEnabled(true),
m_needRedraw(true),
m_stallsCount(0)
{
}
void WindowHandle::setVideoTimer(shared_ptr<VideoTimer> const & videoTimer)
{
m_videoTimer = videoTimer;
m_frameFn = videoTimer->frameFn();
m_videoTimer->setFrameFn(bind(&WindowHandle::checkedFrameFn, this));
m_stallsCount = 0;
}
void WindowHandle::checkedFrameFn()
{
if (needRedraw())
m_stallsCount = 0;
else
++m_stallsCount;
if (m_stallsCount >= 60)
{
// LOG(LINFO, ("PausedDOWN"));
m_videoTimer->pause();
}
else
m_frameFn();
}
WindowHandle::~WindowHandle() {}
bool WindowHandle::needRedraw() const
{
return m_isUpdatesEnabled && m_needRedraw;
}
void WindowHandle::checkTimer()
{
switch (m_videoTimer->state())
{
case VideoTimer::EStopped:
m_videoTimer->start();
break;
case VideoTimer::EPaused:
// LOG(LINFO, ("WokenUP"));
m_videoTimer->resume();
break;
default:
break;
}
}
void WindowHandle::setNeedRedraw(bool flag)
{
m_needRedraw = flag;
if (m_needRedraw && m_isUpdatesEnabled)
checkTimer();
}
shared_ptr<yg::gl::RenderContext> const & WindowHandle::renderContext()
{
return m_renderContext;
}
void WindowHandle::setRenderContext(shared_ptr<yg::gl::RenderContext> const & renderContext)
{
m_renderContext = renderContext;
}
bool WindowHandle::setUpdatesEnabled(bool doEnable)
{
bool res = false;
bool wasUpdatesEnabled = m_isUpdatesEnabled;
m_isUpdatesEnabled = doEnable;
if ((!wasUpdatesEnabled) && (doEnable) && (m_hasPendingUpdates))
{
setNeedRedraw(true);
m_hasPendingUpdates = false;
res = true;
}
return res;
}
void WindowHandle::invalidate()
{
if (m_isUpdatesEnabled)
setNeedRedraw(true);
else
m_hasPendingUpdates = true;
}

View file

@ -1,6 +1,9 @@
#pragma once
#include "../platform/video_timer.hpp"
#include "../std/shared_ptr.hpp"
#include "../std/bind.hpp"
#include "events.hpp"
#include "drawer_yg.hpp"
#include "../base/logging.hpp"
@ -21,52 +24,30 @@ class WindowHandle
bool m_isUpdatesEnabled;
bool m_needRedraw;
shared_ptr<VideoTimer> m_videoTimer;
VideoTimer::TFrameFn m_frameFn;
int m_stallsCount;
public:
WindowHandle() :
m_hasPendingUpdates(false),
m_isUpdatesEnabled(true),
m_needRedraw(true)
{}
virtual ~WindowHandle() {}
bool needRedraw() const
{
return m_isUpdatesEnabled && m_needRedraw;
}
WindowHandle();
virtual ~WindowHandle();
void setNeedRedraw(bool flag)
{
m_needRedraw = flag;
}
void setVideoTimer(shared_ptr<VideoTimer> const & videoTimer);
shared_ptr<yg::gl::RenderContext> const & renderContext()
{
return m_renderContext;
}
void checkedFrameFn();
void setRenderContext(shared_ptr<yg::gl::RenderContext> const & renderContext)
{
m_renderContext = renderContext;
}
bool needRedraw() const;
bool setUpdatesEnabled(bool doEnable)
{
bool res = false;
if ((!m_isUpdatesEnabled) && (doEnable) && (m_hasPendingUpdates))
{
setNeedRedraw(true);
m_hasPendingUpdates = false;
res = true;
}
m_isUpdatesEnabled = doEnable;
return res;
}
void checkTimer();
void invalidate()
{
if (m_isUpdatesEnabled)
setNeedRedraw(true);
else
m_hasPendingUpdates = true;
}
void setNeedRedraw(bool flag);
shared_ptr<yg::gl::RenderContext> const & renderContext();
void setRenderContext(shared_ptr<yg::gl::RenderContext> const & renderContext);
bool setUpdatesEnabled(bool doEnable);
void invalidate();
};

View file

@ -20,23 +20,13 @@ public:
stop();
}
void start()
{
if (m_displayLink == 0)
{
CVDisplayLinkCreateWithActiveCGDisplays(&m_displayLink);
CVDisplayLinkSetOutputCallback(m_displayLink, &displayLinkCallback, (void*)this);
CVDisplayLinkStart(m_displayLink);
}
}
static CVReturn displayLinkCallback(
CVDisplayLinkRef displayLink,
const CVTimeStamp *inNow,
const CVTimeStamp *inOutputTime,
CVOptionFlags flagsIn,
CVOptionFlags *flagsOut,
void *displayLinkContext
CVDisplayLinkRef /*displayLink*/,
const CVTimeStamp * /*inNow*/,
const CVTimeStamp * /*inOutputTime*/,
CVOptionFlags /*flagsIn*/,
CVOptionFlags * /*flagsOut*/,
void * displayLinkContext
)
{
AppleVideoTimer * t = reinterpret_cast<AppleVideoTimer*>(displayLinkContext);
@ -45,13 +35,37 @@ public:
return kCVReturnSuccess;
}
void start()
{
if (m_displayLink == 0)
{
CVDisplayLinkCreateWithActiveCGDisplays(&m_displayLink);
CVDisplayLinkSetOutputCallback(m_displayLink, &displayLinkCallback, (void*)this);
resume();
}
}
void resume()
{
CVDisplayLinkStart(m_displayLink);
m_state = ERunning;
}
void pause()
{
CVDisplayLinkStop(m_displayLink);
m_state = EPaused;
}
void stop()
{
if (m_displayLink)
{
CVDisplayLinkStop(m_displayLink);
if (state() == ERunning)
pause();
CVDisplayLinkRelease(m_displayLink);
m_displayLink = 0;
m_state = EStopped;
}
}

View file

@ -38,7 +38,9 @@ public:
m_objCppWrapper = [[VideoTimerWrapper alloc] initWithTimer:this];
m_displayLink = [CADisplayLink displayLinkWithTarget:m_objCppWrapper selector:@selector(perform)];
m_displayLink.frameInterval = 1;
m_displayLink.paused = true;
[m_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
resume();
}
}
@ -49,9 +51,22 @@ public:
[m_displayLink invalidate];
[m_objCppWrapper release];
m_displayLink = 0;
m_state = EStopped;
}
}
void pause()
{
m_displayLink.paused = true;
m_state = EPaused;
}
void resume()
{
m_displayLink.paused = false;
m_state = ERunning;
}
void perform()
{
m_frameFn();

View file

@ -1,4 +1,22 @@
#include "video_timer.hpp"
VideoTimer::VideoTimer(TFrameFn fn) : m_frameFn(fn)
VideoTimer::VideoTimer(TFrameFn fn) : m_frameFn(fn), m_state(EStopped)
{}
VideoTimer::EState VideoTimer::state() const
{
return m_state;
}
VideoTimer::~VideoTimer()
{}
VideoTimer::TFrameFn VideoTimer::frameFn() const
{
return m_frameFn;
}
void VideoTimer::setFrameFn(TFrameFn fn)
{
m_frameFn = fn;
}

View file

@ -9,13 +9,29 @@ public:
typedef function<void()> TFrameFn;
enum EState
{
EStopped,
EPaused,
ERunning
};
protected:
TFrameFn m_frameFn;
EState m_state;
public:
VideoTimer(TFrameFn fn);
virtual ~VideoTimer() {}
virtual ~VideoTimer();
TFrameFn frameFn() const;
void setFrameFn(TFrameFn fn);
EState state() const;
virtual void resume() = 0;
virtual void pause() = 0;
virtual void start() = 0;
virtual void stop() = 0;

View file

@ -15,6 +15,37 @@ using namespace storage;
namespace qt
{
QtVideoTimer::QtVideoTimer(DrawWidget * w, TFrameFn frameFn)
: ::VideoTimer(frameFn), m_widget(w)
{}
void QtVideoTimer::start()
{
m_timer = new QTimer();
m_widget->connect(m_timer, SIGNAL(timeout()), m_widget, SLOT(AnimTimerElapsed()));
resume();
}
void QtVideoTimer::pause()
{
m_timer->stop();
m_state = EPaused;
}
void QtVideoTimer::resume()
{
m_timer->start(1000 / 60);
m_state = ERunning;
}
void QtVideoTimer::stop()
{
pause();
delete m_timer;
m_timer = 0;
m_state = EStopped;
}
DrawWidget::DrawWidget(QWidget * pParent, Storage & storage)
: base_type(pParent),
m_handle(new WindowHandle()),
@ -28,22 +59,21 @@ namespace qt
{
m_framework->InitStorage(storage);
m_timer = new QTimer(this);
//#ifdef OMIM_OS_MAC
// m_videoTimer.reset(CreateAppleVideoTimer(bind(&DrawWidget::DrawFrame, this)));
//#else
m_animTimer = new QTimer(this);
connect(m_animTimer, SIGNAL(timeout()), this, SLOT(AnimTimerElapsed()));
//#endif
m_handle->setUpdatesEnabled(false);
#ifdef OMIM_OS_MAC
m_videoTimer.reset(CreateAppleVideoTimer(bind(&DrawWidget::DrawFrame, this)));
#else
m_videoTimer.reset(new QtVideoTimer(this, bind(&DrawWidget::DrawFrame, this)));
#endif
m_handle->setVideoTimer(m_videoTimer);
connect(m_timer, SIGNAL(timeout()), this, SLOT(ScaleTimerElapsed()));
}
void DrawWidget::PrepareShutdown()
{
//#ifdef OMIM_OS_MAC
// m_videoTimer->stop();
//#else
m_animTimer->stop();
//#endif
m_videoTimer->stop();
m_framework->PrepareToShutdown();
}
@ -200,11 +230,8 @@ namespace qt
/// timer should be started upon the first repaint
/// request to fully initialized GLWidget.
m_isTimerStarted = true;
//#ifdef OMIM_OS_MAC
// m_videoTimer->start();
//#else
m_animTimer->start(1000 / 60);
//#endif
m_handle->setUpdatesEnabled(true);
m_handle->invalidate();
}
m_framework->Invalidate();

View file

@ -26,6 +26,26 @@ namespace qt
/// Replace this to set a draw widget kernel.
typedef GLDrawWidget widget_type;
class DrawWidget;
class QtVideoTimer : public ::VideoTimer
{
private:
QTimer * m_timer;
DrawWidget * m_widget;
public:
QtVideoTimer(DrawWidget * w, ::VideoTimer::TFrameFn frameFn);
void resume();
void pause();
void start();
void stop();
};
class DrawWidget : public widget_type
{
typedef widget_type base_type;
@ -40,7 +60,7 @@ namespace qt
scoped_ptr<Framework<model_t> > m_framework;
scoped_ptr<VideoTimer> m_videoTimer;
shared_ptr<VideoTimer> m_videoTimer;
bool m_isDrag;
bool m_isRotate;