Skip to content

Commit 7738144

Browse files
committed
Merge pull request capstone-engine#3 from mparaniak/linux-timer
Merging mparaniak changes into fork.
2 parents cc8967d + 861aa59 commit 7738144

File tree

7 files changed

+220
-9
lines changed

7 files changed

+220
-9
lines changed

.gitignore

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,29 @@ DemoAndroid/assets/font
3939
DemoAndroid/assets/language
4040
DemoAndroid/assets/skin
4141
Demo.exe
42+
build
43+
TurboBadgerDemo
44+
accuracy
45+
boing
46+
clipboard
47+
defaults
48+
events
49+
fsaa
50+
gamma
51+
gears
52+
glfwinfo
53+
heightmap
54+
iconify
55+
joysticks
56+
modes
57+
peter
58+
reopen
59+
sharing
60+
simple
61+
splitview
62+
tearing
63+
threads
64+
title
65+
wave
66+
windows
67+

Demo/platform/Application.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "animation/tb_widget_animation.h"
22
#include "Application.h"
3-
3+
#include "tb_system.h"
4+
#include <stdio.h>
45
using namespace tb;
56

67
void Application::Run()
@@ -10,7 +11,9 @@ void Application::Run()
1011

1112
bool Application::Init()
1213
{
14+
1315
TBWidgetsAnimationManager::Init();
16+
1417
return true;
1518
}
1619

@@ -26,6 +29,7 @@ void Application::Process()
2629
TBAnimationManager::Update();
2730
GetRoot()->InvokeProcessStates();
2831
GetRoot()->InvokeProcess();
32+
2933
}
3034

3135
void Application::RenderFrame(int window_w, int window_h)
@@ -34,6 +38,7 @@ void Application::RenderFrame(int window_w, int window_h)
3438
GetRoot()->InvokePaint(TBWidget::PaintProps());
3539
g_renderer->EndPaint();
3640

41+
3742
// If animations are running, reinvalidate immediately
3843
if (TBAnimationManager::HasAnimationsRunning())
3944
GetRoot()->Invalidate();

Demo/platform/glfw_extra_linux.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424

2525
GLFWtimerfun timerCallback;
2626

27+
#ifndef TB_TARGET_LINUX
28+
2729
void glfwWakeUpMsgLoop(GLFWwindow *window)
2830
{
2931
}
@@ -52,7 +54,10 @@ void glfwKillTimer()
5254

5355
void glfwSetTimerCallback(GLFWtimerfun cbfun)
5456
{
57+
5558
timerCallback = cbfun;
5659
}
5760

61+
#endif /* TB_TARGET_LINUX */
62+
5863
#endif // defined(TB_TARGET_LINUX) || defined(TB_TARGET_MACOSX)

Demo/platform/port_glfw.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ void RootWidget::OnInvalid()
7676
if (!m_backend->has_pending_update)
7777
{
7878
m_backend->has_pending_update = true;
79-
glfwWakeUpMsgLoop(m_backend->mainWindow);
8079
}
8180
}
8281

@@ -312,6 +311,8 @@ static void scroll_callback(GLFWwindow *window, double x, double y)
312311
If fire_time is 0, it should be fired ASAP.
313312
If force is true, it will ask the platform to schedule it again, even if
314313
the fire_time is the same as last time. */
314+
315+
#ifndef TB_TARGET_LINUX
315316
static void ReschedulePlatformTimer(double fire_time, bool force)
316317
{
317318
static double set_fire_time = -1;
@@ -329,6 +330,7 @@ static void ReschedulePlatformTimer(double fire_time, bool force)
329330
}
330331
}
331332

333+
332334
static void timer_callback()
333335
{
334336
double next_fire_time = TBMessageHandler::GetNextMessageFireTime();
@@ -355,6 +357,7 @@ void TBSystem::RescheduleTimer(double fire_time)
355357
{
356358
ReschedulePlatformTimer(fire_time, false);
357359
}
360+
#endif /* TB_TARGET_LINUX */
358361

359362
static void window_refresh_callback(GLFWwindow *window)
360363
{
@@ -436,7 +439,11 @@ bool ApplicationBackendGLFW::Init(Application *app, int width, int height, const
436439
glfwSetScrollCallback(mainWindow, scroll_callback);
437440
glfwSetKeyCallback(mainWindow, key_callback);
438441
glfwSetCharCallback(mainWindow, char_callback);
442+
443+
#ifndef TB_SYSTEM_LINUX
439444
glfwSetTimerCallback(timer_callback);
445+
#endif
446+
440447
#if (GLFW_VERSION_MAJOR >= 3 && GLFW_VERSION_MINOR >= 1)
441448
glfwSetDropCallback(mainWindow, drop_callback);
442449
#endif
@@ -445,6 +452,7 @@ bool ApplicationBackendGLFW::Init(Application *app, int width, int height, const
445452
m_root.SetRect(TBRect(0, 0, width, height));
446453

447454
// Create the application object for our demo
455+
448456
m_application = app;
449457
m_application->OnBackendAttached(this);
450458

@@ -472,9 +480,15 @@ void ApplicationBackendGLFW::Run()
472480
{
473481
do
474482
{
483+
#ifdef TB_TARGET_LINUX
484+
TBSystem::PollEvents();
485+
486+
#endif
487+
glfwPollEvents();
488+
475489
if (has_pending_update)
476490
window_refresh_callback(mainWindow);
477-
glfwWaitMsgLoop(mainWindow);
491+
478492
} while (!glfwWindowShouldClose(mainWindow));
479493
}
480494

src/tb/tb_core.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// == See tb_core.h for more information. ==
44
// ================================================================================
55

6+
#include "tb_config.h"
67
#include "tb_core.h"
78
#include "tb_skin.h"
89
#include "tb_widgets_reader.h"
@@ -33,6 +34,11 @@ bool tb_core_init(TBRenderer *renderer, const char *lng_file)
3334
#ifdef TB_IMAGE
3435
g_image_manager = new TBImageManager();
3536
#endif
37+
38+
#ifdef TB_SYSTEM_LINUX
39+
TBSystem::Init();
40+
#endif
41+
3642
return TBInitAddons();
3743
}
3844

@@ -47,6 +53,10 @@ void tb_core_shutdown()
4753
delete g_tb_skin;
4854
delete g_font_manager;
4955
delete g_tb_lng;
56+
57+
#ifdef TB_SYSTEM_LINUX
58+
TBSystem::Shutdown();
59+
#endif
5060
}
5161

5262
bool tb_core_is_initialized()

src/tb/tb_system.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,29 @@ namespace tb {
2424
/** TBSystem is porting interface for the underlaying OS. */
2525
class TBSystem
2626
{
27+
28+
/* Linux specific timer implementation */
29+
#ifdef TB_SYSTEM_LINUX
30+
31+
private:
32+
static int timer_fd;
33+
34+
/* True if since last reschedule timer has fired. Is false if and only
35+
there was no expiration since last reschedule */
36+
static bool timer_state;
37+
public:
38+
39+
/** Initialize timer descriptor. Return 0 on success, errno otherwise **/
40+
static int Init();
41+
42+
/** Close timer descriptor. Return 0 on success, errno otherwise **/
43+
static int Shutdown();
44+
45+
/** Check for timer expiration. Return 0 on success
46+
(it does NOT imply timer fired; Check timer_state) and errno otherwise **/
47+
static int PollEvents();
48+
49+
#endif /* TB_SYSTEM_LINUX */
2750
public:
2851
/** Get the system time in milliseconds since some undefined epoch. */
2952
static double GetTimeMS();
@@ -47,6 +70,18 @@ class TBSystem
4770

4871
/** Get Dots Per Inch for the main screen. */
4972
static int GetDPI();
73+
74+
75+
#ifdef TB_TARGET_LINUX
76+
77+
/** Check whether timer has fired. For now only
78+
does work on Linux. On other platforms it defaults to true **/
79+
inline static bool GetTimerState(){return timer_state;}
80+
81+
#else
82+
inline static bool GetTimerState(){return true;}
83+
#endif /* TB_TARGET_LINUX */
84+
5085
};
5186

5287
/** TBClipboard is a porting interface for the clipboard. */

src/tb/tb_system_linux.cpp

Lines changed: 122 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,23 @@
44
// ================================================================================
55

66
#include "tb_system.h"
7+
#include "tb_msg.h"
78

89
#ifdef TB_SYSTEM_LINUX
910

10-
#include <sys/time.h>
11+
#include <errno.h>
12+
#include <fcntl.h>
13+
#include <stdint.h>
1114
#include <stdio.h>
15+
#include <stdlib.h>
16+
#include <string.h>
17+
#include <sys/time.h>
18+
#include <sys/timerfd.h>
19+
#include <unistd.h>
1220

1321
#ifdef TB_RUNTIME_DEBUG_INFO
1422

23+
1524
void TBDebugOut(const char *str)
1625
{
1726
printf("%s", str);
@@ -30,11 +39,118 @@ double TBSystem::GetTimeMS()
3039
return now.tv_usec/1000 + now.tv_sec*1000;
3140
}
3241

33-
// Implementation currently done in port_glut.cpp.
34-
// FIX: Implement here for linux-desktop/android/macos?
35-
//void TBSystem::RescheduleTimer(double fire_time)
36-
//{
37-
//}
42+
43+
/** FIXME: Timer facility only available in Linux **/
44+
#ifdef TB_SYSTEM_LINUX
45+
46+
int TBSystem::timer_fd;
47+
bool TBSystem::timer_state;
48+
49+
int TBSystem::Init()
50+
{
51+
52+
timer_fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK);
53+
54+
errno = 0;
55+
56+
if(timer_fd < 0){
57+
TBDebugOut("Failed to obtain timer descriptor!");
58+
return errno;
59+
}
60+
61+
return 0;
62+
}
63+
64+
int TBSystem::Shutdown()
65+
{
66+
67+
timer_state = false;
68+
69+
errno = 0;
70+
71+
if(timer_fd >= 0)
72+
close(timer_fd);
73+
74+
if(timer_fd < 0){
75+
76+
TBDebugOut("Failed to close timer descriptor!");
77+
return errno;
78+
}
79+
80+
return 0;
81+
}
82+
83+
void TBSystem::RescheduleTimer(double fire_time)
84+
{
85+
86+
if(fire_time == TB_NOT_SOON)
87+
return;
88+
89+
if(fire_time == 0){
90+
timer_state = true;
91+
return;
92+
}
93+
int status = 0;
94+
95+
struct timespec fire_spec;
96+
97+
fire_time /= 1000;
98+
fire_spec.tv_sec = fire_time;
99+
fire_spec.tv_nsec = (fire_time - fire_spec.tv_sec)*1e9;
100+
101+
struct timespec zero_spec = {0,0};
102+
struct itimerspec timer_spec = { .it_interval = zero_spec,
103+
.it_value = fire_spec };
104+
105+
timer_state = false;
106+
107+
errno = 0;
108+
status = timerfd_settime(timer_fd,TFD_TIMER_ABSTIME,
109+
&timer_spec, NULL);
110+
if(status < 0)
111+
TBDebugOut("Failed to arm timer!");
112+
}
113+
114+
int TBSystem::PollEvents()
115+
{
116+
117+
if(!timer_state){
118+
119+
ssize_t rc = 0;
120+
uint64_t count = 0;
121+
122+
errno = 0;
123+
rc = read(timer_fd, &count, sizeof(count));
124+
125+
if(rc > 0 && count > 0)
126+
timer_state = true;
127+
128+
else{
129+
130+
if(errno == EAGAIN || errno == EWOULDBLOCK);
131+
132+
else{
133+
TBDebugPrint("Failed to read from timer file!:%s", strerror(errno));
134+
return errno;
135+
}
136+
}
137+
}
138+
139+
if(timer_state){
140+
141+
timer_state = false;
142+
143+
TBMessageHandler::ProcessMessages();
144+
// If we still have things to do (because we didn't process all messages,
145+
// or because there are new messages), we need to rescedule, so call RescheduleTimer.
146+
TBSystem::RescheduleTimer(TBMessageHandler::GetNextMessageFireTime());
147+
148+
}
149+
150+
151+
return 0;
152+
}
153+
#endif /* TB_SYSTEM_LINUX */
38154

39155
int TBSystem::GetLongClickDelayMS()
40156
{

0 commit comments

Comments
 (0)