Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrachytski <siarhei.rachytski@gmail.com>2011-09-22 19:58:39 +0400
committerAlex Zolotarev <alex@maps.me>2015-09-23 01:24:16 +0300
commita032f7e6b612e2f1ad0d774067fbb973091897ad (patch)
tree0112898798f6189c27a71c97df3d45323a181d26
parent11c675cd56f1ac7ddef3414bd000575fe2fd9cd9 (diff)
introduced VideoTimer, refactored rendering loop to use Timers, as on iOS.
-rw-r--r--iphone/Maps/Classes/EAGLView.h4
-rw-r--r--iphone/Maps/Classes/EAGLView.mm20
-rw-r--r--iphone/Maps/Classes/MapViewController.mm4
-rw-r--r--map/framework.cpp12
-rw-r--r--map/framework.hpp3
-rw-r--r--map/window_handle.hpp31
-rw-r--r--platform/apple_video_timer.mm67
-rw-r--r--platform/ios_video_timer.mm89
-rw-r--r--platform/platform.pro13
-rw-r--r--platform/video_timer.cpp4
-rw-r--r--platform/video_timer.hpp26
-rw-r--r--qt/draw_widget.cpp63
-rw-r--r--qt/draw_widget.hpp18
-rw-r--r--qt/qt.pro3
-rw-r--r--qt/widgets.cpp5
-rw-r--r--qt/widgets.hpp2
16 files changed, 314 insertions, 50 deletions
diff --git a/iphone/Maps/Classes/EAGLView.h b/iphone/Maps/Classes/EAGLView.h
index af17102255..873874a650 100644
--- a/iphone/Maps/Classes/EAGLView.h
+++ b/iphone/Maps/Classes/EAGLView.h
@@ -34,12 +34,11 @@ namespace yg
shared_ptr<iphone::RenderContext> renderContext;
shared_ptr<iphone::RenderBuffer> renderBuffer;
shared_ptr<yg::gl::FrameBuffer> frameBuffer;
- shared_ptr<DrawerYG> drawer;
@public
shared_ptr<iphone::WindowHandle> windowHandle;
- shared_ptr<yg::ResourceManager> textureManager;
+ shared_ptr<DrawerYG> drawer;
MapViewController * controller;
}
@@ -50,6 +49,7 @@ namespace yg
@property (nonatomic, assign) CADisplayLink * displayLink;
@property (nonatomic, assign) MapViewController * controller;
@property (nonatomic, assign) shared_ptr<iphone::WindowHandle> windowHandle;
+@property (nonatomic, assign) shared_ptr<DrawerYG> drawer;
@property (nonatomic, assign) shared_ptr<iphone::RenderContext> renderContext;
@property (nonatomic, assign) shared_ptr<yg::ResourceManager> resourceManager;
diff --git a/iphone/Maps/Classes/EAGLView.mm b/iphone/Maps/Classes/EAGLView.mm
index b1f711bd1d..6136a3a379 100644
--- a/iphone/Maps/Classes/EAGLView.mm
+++ b/iphone/Maps/Classes/EAGLView.mm
@@ -20,6 +20,7 @@ bool _inRepaint = false;
@synthesize controller;
@synthesize windowHandle;
+@synthesize drawer;
@synthesize renderContext;
@synthesize resourceManager;
@synthesize displayLink;
@@ -143,7 +144,6 @@ bool _inRepaint = false;
windowHandle = shared_ptr<iphone::WindowHandle>(new iphone::WindowHandle(_doRepaint));
- windowHandle->setDrawer(drawer);
windowHandle->setRenderContext(renderContext);
displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(drawView)];
@@ -174,19 +174,13 @@ bool _inRepaint = false;
- (void)drawView
{
- if (!_inRepaint)
+ if (windowHandle->needRedraw())
{
- _inRepaint = true;
-
- if (_doRepaint)
- {
- _doRepaint = false;
- [controller beginPaint];
- [controller doPaint];
- renderBuffer->present();
- [controller endPaint];
- }
- _inRepaint = false;
+ windowHandle->setNeedRedraw(false);
+ [controller beginPaint];
+ [controller doPaint];
+ renderBuffer->present();
+ [controller endPaint];
}
}
diff --git a/iphone/Maps/Classes/MapViewController.mm b/iphone/Maps/Classes/MapViewController.mm
index 5a549f14ec..3162c5015c 100644
--- a/iphone/Maps/Classes/MapViewController.mm
+++ b/iphone/Maps/Classes/MapViewController.mm
@@ -289,8 +289,8 @@ NSInteger compareAddress(id l, id r, void * context)
- (void)doPaint
{
- shared_ptr<iphone::WindowHandle> windowHandle = [(EAGLView*)self.view windowHandle];
- shared_ptr<PaintEvent> paintEvent(new PaintEvent(windowHandle->drawer().get()));
+ shared_ptr<DrawerYG> drawer = [(EAGLView*)self.view drawer];
+ shared_ptr<PaintEvent> paintEvent(new PaintEvent(drawer.get()));
m_framework->DoPaint(paintEvent);
}
diff --git a/map/framework.cpp b/map/framework.cpp
index a2172f3f9a..568de21cc0 100644
--- a/map/framework.cpp
+++ b/map/framework.cpp
@@ -235,6 +235,18 @@ void Framework<TModel>::SetMaxWorldRect()
}
template <typename TModel>
+bool Framework<TModel>::NeedRedraw() const
+{
+ return m_windowHandle->needRedraw();
+}
+
+template <typename TModel>
+void Framework<TModel>::SetNeedRedraw(bool flag)
+{
+ m_windowHandle->setNeedRedraw(false);
+}
+
+template <typename TModel>
void Framework<TModel>::Invalidate()
{
m_windowHandle->invalidate();
diff --git a/map/framework.hpp b/map/framework.hpp
index 0331dd9327..ec58117589 100644
--- a/map/framework.hpp
+++ b/map/framework.hpp
@@ -208,6 +208,9 @@ public:
double GetCurrentScale() const;
+ bool NeedRedraw() const;
+ void SetNeedRedraw(bool flag);
+
virtual void BeginPaint();
/// Function for calling from platform dependent-paint function.
virtual void DoPaint(shared_ptr<PaintEvent> e);
diff --git a/map/window_handle.hpp b/map/window_handle.hpp
index 7b606697c0..f1062ba57c 100644
--- a/map/window_handle.hpp
+++ b/map/window_handle.hpp
@@ -15,22 +15,28 @@ namespace yg
class WindowHandle
{
- // iOS implementation needs this parameter.
- // Desktop realization holds DrawerYG in draw_widget.hpp.
- shared_ptr<DrawerYG> m_drawer;
-
shared_ptr<yg::gl::RenderContext> m_renderContext;
bool m_hasPendingUpdates;
bool m_isUpdatesEnabled;
+ bool m_needRedraw;
public:
- WindowHandle() : m_hasPendingUpdates(false), m_isUpdatesEnabled(true) {}
+ WindowHandle() :
+ m_hasPendingUpdates(false),
+ m_isUpdatesEnabled(true),
+ m_needRedraw(true)
+ {}
virtual ~WindowHandle() {}
- shared_ptr<DrawerYG> const & drawer()
+ bool needRedraw() const
+ {
+ return m_isUpdatesEnabled && m_needRedraw;
+ }
+
+ void setNeedRedraw(bool flag)
{
- return m_drawer;
+ m_needRedraw = flag;
}
shared_ptr<yg::gl::RenderContext> const & renderContext()
@@ -43,17 +49,12 @@ public:
m_renderContext = renderContext;
}
- void setDrawer(shared_ptr<DrawerYG> const & drawer)
- {
- m_drawer = drawer;
- }
-
bool setUpdatesEnabled(bool doEnable)
{
bool res = false;
if ((!m_isUpdatesEnabled) && (doEnable) && (m_hasPendingUpdates))
{
- invalidateImpl();
+ setNeedRedraw(true);
m_hasPendingUpdates = false;
res = true;
}
@@ -64,10 +65,8 @@ public:
void invalidate()
{
if (m_isUpdatesEnabled)
- invalidateImpl();
+ setNeedRedraw(true);
else
m_hasPendingUpdates = true;
}
-
- virtual void invalidateImpl() = 0;
};
diff --git a/platform/apple_video_timer.mm b/platform/apple_video_timer.mm
new file mode 100644
index 0000000000..6092d33901
--- /dev/null
+++ b/platform/apple_video_timer.mm
@@ -0,0 +1,67 @@
+#include "video_timer.hpp"
+
+#include "../std/target_os.hpp"
+
+#include <CoreVideo/CVDisplayLink.h>
+
+class AppleVideoTimer : public VideoTimer
+{
+
+ CVDisplayLinkRef m_displayLink;
+
+public:
+
+ AppleVideoTimer(VideoTimer::TFrameFn frameFn)
+ : VideoTimer(frameFn), m_displayLink(0)
+ {}
+
+ ~AppleVideoTimer()
+ {
+ 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
+ )
+ {
+ AppleVideoTimer * t = reinterpret_cast<AppleVideoTimer*>(displayLinkContext);
+ t->perform();
+
+ return kCVReturnSuccess;
+ }
+
+ void stop()
+ {
+ if (m_displayLink)
+ {
+ CVDisplayLinkStop(m_displayLink);
+ CVDisplayLinkRelease(m_displayLink);
+ m_displayLink = 0;
+ }
+ }
+
+ void perform()
+ {
+ m_frameFn();
+ }
+};
+
+VideoTimer * CreateAppleVideoTimer(VideoTimer::TFrameFn frameFn)
+{
+ return new AppleVideoTimer(frameFn);
+}
diff --git a/platform/ios_video_timer.mm b/platform/ios_video_timer.mm
new file mode 100644
index 0000000000..4a80809ac5
--- /dev/null
+++ b/platform/ios_video_timer.mm
@@ -0,0 +1,89 @@
+#include "video_timer.hpp"
+
+#include "../std/target_os.hpp"
+
+#import <QuartzCore/CADisplayLink.h>
+#import <Foundation/NSRunLoop.h>
+
+class IOSVideoTimer;
+
+@interface VideoTimerWrapper : NSObject {
+@private
+ IOSVideoTimer * m_timer;
+}
+- (id)initWithTimer:(IOSVideoTimer *) timer;
+- (void)perform;
+@end
+
+class IOSVideoTimer : public VideoTimer
+{
+
+ VideoTimerWrapper * m_objCppWrapper;
+ CADisplayLink * m_displayLink;
+
+public:
+
+ IOSVideoTimer(VideoTimer::TFrameFn frameFn) : VideoTimer(frameFn), m_objCppWrapper(0), m_displayLink(0)
+ {}
+
+ ~IOSVideoTimer()
+ {
+ stop();
+ }
+
+ void start()
+ {
+ if (m_displayLink == 0)
+ {
+ m_objCppWrapper = [[VideoTimerWrapper alloc] initWithTimer:this];
+ m_displayLink = [CADisplayLink displayLinkWithTarget:m_objCppWrapper selector:@selector(perform)];
+ m_displayLink.frameInterval = 1;
+ [m_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
+ }
+ }
+
+ void stop()
+ {
+ if (m_displayLink)
+ {
+ [m_displayLink invalidate];
+ [m_objCppWrapper release];
+ m_displayLink = 0;
+ }
+ }
+
+ void perform()
+ {
+ m_frameFn();
+ }
+};
+
+@implementation VideoTimerWrapper
+
+- (id)initWithTimer:(IOSVideoTimer*) timer
+{
+ self = [super init];
+ if (self) {
+ m_timer = timer;
+ }
+ return self;
+}
+
+- (void)dealloc
+{
+ [super dealloc];
+}
+
+- (void)perform
+{
+ m_timer->perform();
+}
+
+@end
+
+VideoTimer * CreateIOSVideoTimer(VideoTimer::TFrameFn frameFn)
+{
+ return new IOSVideoTimer(frameFn);
+}
+
+
diff --git a/platform/platform.pro b/platform/platform.pro
index 2889e7ab9f..bcf2fcf510 100644
--- a/platform/platform.pro
+++ b/platform/platform.pro
@@ -35,8 +35,15 @@ macx|iphone* {
}
macx:!iphone* {
- OBJECTIVE_SOURCES += wifi_info_mac.mm
- LIBS += -framework CoreWLAN
+ OBJECTIVE_SOURCES += wifi_info_mac.mm \
+ apple_video_timer.mm
+
+ LIBS += -framework CoreWLAN -framework QuartzCore
+}
+
+iphone* {
+ OBJECTIVE_SOURCES += ios_video_timer.mm
+ LIBS += -framework QuartzCore
}
win32 {
@@ -52,9 +59,11 @@ HEADERS += \
concurrent_runner.hpp \
preferred_languages.hpp \
settings.hpp \
+ video_timer.hpp
SOURCES += \
location_manager.cpp \
preferred_languages.cpp \
settings.cpp \
platform.cpp \
+ video_timer.cpp
diff --git a/platform/video_timer.cpp b/platform/video_timer.cpp
new file mode 100644
index 0000000000..288534d04a
--- /dev/null
+++ b/platform/video_timer.cpp
@@ -0,0 +1,4 @@
+#include "video_timer.hpp"
+
+VideoTimer::VideoTimer(TFrameFn fn) : m_frameFn(fn)
+{}
diff --git a/platform/video_timer.hpp b/platform/video_timer.hpp
new file mode 100644
index 0000000000..a93bfee31a
--- /dev/null
+++ b/platform/video_timer.hpp
@@ -0,0 +1,26 @@
+#pragma once
+
+#include "../std/function.hpp"
+
+/// Timer, synchronized to Vertical Sync
+class VideoTimer
+{
+public:
+
+ typedef function<void()> TFrameFn;
+
+protected:
+
+ TFrameFn m_frameFn;
+
+public:
+
+ VideoTimer(TFrameFn fn);
+
+ virtual void start() = 0;
+ virtual void stop() = 0;
+};
+
+extern "C" VideoTimer * CreateIOSVideoTimer(VideoTimer::TFrameFn frameFn);
+extern "C" VideoTimer * CreateAppleVideoTimer(VideoTimer::TFrameFn frameFn);
+extern "C" VideoTimer * CreateWin32VideoTimer(VideoTimer::TFrameFn frameFn);
diff --git a/qt/draw_widget.cpp b/qt/draw_widget.cpp
index 169486f1e1..aa6a2aeaca 100644
--- a/qt/draw_widget.cpp
+++ b/qt/draw_widget.cpp
@@ -17,19 +17,32 @@ namespace qt
{
DrawWidget::DrawWidget(QWidget * pParent, Storage & storage)
: base_type(pParent),
- m_handle(new qt::WindowHandle(this)),
+ m_handle(new WindowHandle()),
m_framework(FrameworkFactory<model_t>::CreateFramework(m_handle, 0)),
m_isDrag(false),
m_redrawInterval(100),
- m_pScale(0)
+ m_pScale(0),
+ m_isInitialized(false),
+ m_isTimerStarted(false)
{
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
connect(m_timer, SIGNAL(timeout()), this, SLOT(ScaleTimerElapsed()));
}
void DrawWidget::PrepareShutdown()
{
+//#ifdef OMIM_OS_MAC
+// m_videoTimer->stop();
+//#else
+ m_animTimer->stop();
+//#endif
m_framework->PrepareToShutdown();
}
@@ -165,26 +178,51 @@ namespace qt
{
widget_type::initializeGL();
m_handle->setRenderContext(renderContext());
- //m_handle->setDrawer(GetDrawer());
m_framework->InitializeGL(renderContext(), resourceManager());
+ m_isInitialized = true;
}
- void DrawWidget::DoDraw(shared_ptr<drawer_t> p)
+ void DrawWidget::DrawFrame()
{
- m_framework->BeginPaint();
- shared_ptr<PaintEvent> paintEvent(new PaintEvent(p.get()));
- m_framework->DoPaint(paintEvent);
+ if (m_framework->NeedRedraw())
+ {
+ makeCurrent();
+ m_framework->SetNeedRedraw(false);
+ m_framework->BeginPaint();
+ shared_ptr<PaintEvent> paintEvent(new PaintEvent(GetDrawer().get()));
+ m_framework->DoPaint(paintEvent);
+
+ /// swapping buffers before ending the frame, see issue #333
+ swapBuffers();
+
+ m_framework->EndPaint();
+ doneCurrent();
+ }
+ }
- /// swapping buffers before ending the frame, see issue #333
- swapBuffers();
+ void DrawWidget::DoDraw(shared_ptr<screen_t> p)
+ {
+ if ((m_isInitialized) && (!m_isTimerStarted))
+ {
+ /// 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_framework->EndPaint();
+ m_framework->Invalidate();
}
void DrawWidget::DoResize(int w, int h)
{
m_framework->OnSize(w, h);
m_framework->Invalidate();
+ if (m_isInitialized && m_isTimerStarted)
+ DrawFrame();
UpdateScaleControl();
emit ViewportChanged();
}
@@ -258,6 +296,11 @@ namespace qt
m_timer->stop();
}
+ void DrawWidget::AnimTimerElapsed()
+ {
+ DrawFrame();
+ }
+
void DrawWidget::wheelEvent(QWheelEvent * e)
{
if (!m_isDrag)
diff --git a/qt/draw_widget.hpp b/qt/draw_widget.hpp
index 40daa385ac..254a7235f9 100644
--- a/qt/draw_widget.hpp
+++ b/qt/draw_widget.hpp
@@ -1,12 +1,14 @@
#pragma once
-#include "qt_window_handle.hpp"
#include "widgets.hpp"
+#include "../map/window_handle.hpp"
#include "../map/feature_vec_model.hpp"
#include "../map/framework.hpp"
#include "../map/navigator.hpp"
+#include "../platform/video_timer.hpp"
+
#include "../std/auto_ptr.hpp"
#include <QtCore/QTimer>
@@ -28,15 +30,22 @@ namespace qt
{
typedef widget_type base_type;
- shared_ptr<qt::WindowHandle> m_handle;
+ shared_ptr<WindowHandle> m_handle;
+
+ shared_ptr<drawer_t> m_drawer;
+ bool m_isInitialized;
+ bool m_isTimerStarted;
typedef model::FeaturesFetcher model_t;
auto_ptr<Framework<model_t> > m_framework;
+ auto_ptr<VideoTimer> m_videoTimer;
+
bool m_isDrag;
QTimer * m_timer;
+ QTimer * m_animTimer;
size_t m_redrawInterval;
Q_OBJECT
@@ -59,6 +68,7 @@ namespace qt
void Repaint();
void ScaleChanged(int action);
void ScaleTimerElapsed();
+ void AnimTimerElapsed();
public:
DrawWidget(QWidget * pParent, storage::Storage & storage);
@@ -86,10 +96,12 @@ namespace qt
/// @name Overriden from base_type.
//@{
virtual void initializeGL();
- virtual void DoDraw(shared_ptr<drawer_t> p);
+ virtual void DoDraw(shared_ptr<screen_t> p);
virtual void DoResize(int w, int h);
//@}
+ void DrawFrame();
+
/// @name Overriden from QWidget.
//@{
virtual void mousePressEvent(QMouseEvent * e);
diff --git a/qt/qt.pro b/qt/qt.pro
index 4186995953..9c21aca280 100644
--- a/qt/qt.pro
+++ b/qt/qt.pro
@@ -19,7 +19,7 @@ win32-msvc* {
}
macx {
- LIBS += -framework CoreLocation -framework Foundation -framework CoreWLAN
+ LIBS += -framework CoreLocation -framework Foundation -framework CoreWLAN -framework QuartzCore
ICON = res/mac.icns
PLIST_FILE = Info.plist
@@ -77,7 +77,6 @@ HEADERS += \
mainwindow.hpp \
widgets.hpp \
draw_widget.hpp \
- qt_window_handle.hpp \
proxystyle.hpp \
slider_ctrl.hpp \
about.hpp \
diff --git a/qt/widgets.cpp b/qt/widgets.cpp
index ad366ac129..7e733174f4 100644
--- a/qt/widgets.cpp
+++ b/qt/widgets.cpp
@@ -22,6 +22,11 @@ namespace qt
{
}
+ shared_ptr<GLDrawWidget::drawer_t> const & GLDrawWidget::GetDrawer() const
+ {
+ return m_p;
+ }
+
void GLDrawWidget::initializeGL()
{
/// we'll perform swap by ourselves, see issue #333
diff --git a/qt/widgets.hpp b/qt/widgets.hpp
index c70af3c3a9..cc8fc98aa6 100644
--- a/qt/widgets.hpp
+++ b/qt/widgets.hpp
@@ -33,6 +33,8 @@ namespace qt
shared_ptr<yg::gl::RenderContext> const & renderContext();
shared_ptr<yg::ResourceManager> const & resourceManager();
+ shared_ptr<drawer_t> const & GetDrawer() const;
+
protected:
virtual void initializeGL();
};