Skip to content

Commit 677661c

Browse files
authored
Implement message queue to handle vblank request (#32)
* Implement message queue to handle vblank request The previous implementation with ecore_thread_run caused would cause a new thread to be recreated every time. The current implementation with ecore_thread_feedback_run and eina_thread_queue,only create one thread. * Replace -1 with QUEUE_QUIT We have defined QUEUE_QUIT = -1, use QUEUE_QUIT, make the code more readable. * Check vblank thread queue whether valid before release it. * Rename vblank thread and vblank thread queue * Do nothing when vblank wait Requesting again may cause an infinite loop or queue overflow. Do nothing is a better way.
1 parent dbdb082 commit 677661c

File tree

3 files changed

+87
-18
lines changed

3 files changed

+87
-18
lines changed

shell/platform/tizen/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ source_set("flutter_tizen") {
105105
"ecore",
106106
"ecore_imf",
107107
"ecore_input",
108+
"eina",
108109
"EGL",
109110
"evas",
110111
"flutter_engine",

shell/platform/tizen/tizen_vsync_waiter.cc

Lines changed: 81 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,37 +4,102 @@
44

55
#include "tizen_vsync_waiter.h"
66

7+
#include <eina_thread_queue.h>
8+
79
#include "flutter/shell/platform/tizen/tizen_embedder_engine.h"
810
#include "flutter/shell/platform/tizen/tizen_log.h"
911

10-
void TizenVsyncWaiter::RequestVblank(void* data, Ecore_Thread* thread) {
11-
TizenVsyncWaiter* tizen_vsync_waiter =
12-
reinterpret_cast<TizenVsyncWaiter*>(data);
13-
if (!ecore_thread_check(thread)) {
14-
tdm_error error = tdm_client_vblank_wait(tizen_vsync_waiter->vblank_, 1,
15-
TdmClientVblankCallback, data);
16-
if (error != TDM_ERROR_NONE) {
17-
FT_LOGE("tdm_client_vblank_wait error %d", error);
18-
return;
19-
}
20-
tdm_client_handle_events(tizen_vsync_waiter->client_);
21-
}
22-
}
12+
static const int QUEUE_QUIT = -1;
13+
static const int QUEUE_REQUEST_VBLANK = 0;
14+
15+
typedef struct {
16+
Eina_Thread_Queue_Msg head;
17+
int value;
18+
} Msg;
19+
20+
static Eina_Thread_Queue* vblank_thread_queue{nullptr};
2321

2422
TizenVsyncWaiter::TizenVsyncWaiter(TizenEmbedderEngine* engine)
2523
: engine_(engine) {
2624
if (!CreateTDMVblank()) {
2725
FT_LOGE("Failed to create TDM vblank");
2826
DestoryTDMVblank();
27+
} else {
28+
vblank_thread_queue = eina_thread_queue_new();
29+
vblank_thread_ =
30+
ecore_thread_feedback_run(RequestVblankLoop, NULL, VblankLoopFinish,
31+
VblankLoopFinish, this, EINA_TRUE);
2932
}
3033
}
3134

32-
TizenVsyncWaiter::~TizenVsyncWaiter() { DestoryTDMVblank(); }
35+
TizenVsyncWaiter::~TizenVsyncWaiter() {
36+
SendMessage(QUEUE_QUIT);
37+
if (vblank_thread_) {
38+
ecore_thread_cancel(vblank_thread_);
39+
vblank_thread_ = nullptr;
40+
}
41+
DestoryTDMVblank();
42+
}
3343

3444
void TizenVsyncWaiter::AsyncWaitForVsync(intptr_t baton) {
3545
baton_ = baton;
3646
if (TDMValid()) {
37-
ecore_thread_run(RequestVblank, NULL, NULL, this);
47+
SendMessage(QUEUE_REQUEST_VBLANK);
48+
}
49+
}
50+
51+
void TizenVsyncWaiter::SendMessage(int val) {
52+
if (!vblank_thread_queue || !vblank_thread_) {
53+
FT_LOGE("vblank thread or vblank thread queue not valid");
54+
return;
55+
}
56+
Msg* msg;
57+
void* ref;
58+
msg = (Msg*)eina_thread_queue_send(vblank_thread_queue, sizeof(Msg), &ref);
59+
msg->value = val;
60+
eina_thread_queue_send_done(vblank_thread_queue, ref);
61+
}
62+
63+
void TizenVsyncWaiter::RequestVblankLoop(void* data, Ecore_Thread* thread) {
64+
TizenVsyncWaiter* tizen_vsync_waiter =
65+
reinterpret_cast<TizenVsyncWaiter*>(data);
66+
void* ref;
67+
Msg* msg;
68+
while (!ecore_thread_check(thread)) {
69+
if (!vblank_thread_queue) {
70+
FT_LOGE("Vblank thread queue is not valid");
71+
return;
72+
}
73+
msg = (Msg*)eina_thread_queue_wait(vblank_thread_queue, &ref);
74+
if (msg) {
75+
eina_thread_queue_wait_done(vblank_thread_queue, ref);
76+
} else {
77+
FT_LOGE("Message is null");
78+
continue;
79+
}
80+
if (msg->value == QUEUE_QUIT) {
81+
FT_LOGD("Message queue quit");
82+
return;
83+
}
84+
if (!tizen_vsync_waiter->TDMValid()) {
85+
FT_LOGE("TDM not valid");
86+
return;
87+
}
88+
tdm_error error = tdm_client_vblank_wait(tizen_vsync_waiter->vblank_, 1,
89+
TdmClientVblankCallback, data);
90+
if (error != TDM_ERROR_NONE) {
91+
FT_LOGE("tdm_client_vblank_wait error %d", error);
92+
continue;
93+
}
94+
tdm_client_handle_events(tizen_vsync_waiter->client_);
95+
}
96+
}
97+
98+
void TizenVsyncWaiter::VblankLoopFinish(void* data, Ecore_Thread* thread) {
99+
FT_LOGD("VblankLoopFinish.");
100+
if (vblank_thread_queue) {
101+
eina_thread_queue_free(vblank_thread_queue);
102+
vblank_thread_queue = nullptr;
38103
}
39104
}
40105

@@ -67,6 +132,7 @@ void TizenVsyncWaiter::DestoryTDMVblank() {
67132
tdm_client_vblank_destroy(vblank_);
68133
vblank_ = nullptr;
69134
}
135+
output_ = nullptr;
70136
if (client_) {
71137
tdm_client_destroy(client_);
72138
client_ = nullptr;
@@ -80,11 +146,9 @@ void TizenVsyncWaiter::TdmClientVblankCallback(
80146
unsigned int tv_sec, unsigned int tv_usec, void* user_data) {
81147
TizenVsyncWaiter* tizen_vsync_waiter =
82148
reinterpret_cast<TizenVsyncWaiter*>(user_data);
83-
84149
FT_ASSERT(tizen_vsync_waiter != nullptr);
85150
FT_ASSERT(tizen_vsync_waiter->engine_ != nullptr);
86151
FT_ASSERT(tizen_vsync_waiter->engine_->flutter_engine != nullptr);
87-
88152
uint64_t frame_start_time_nanos = tv_sec * 1e9 + tv_usec * 1e3;
89153
uint64_t frame_target_time_nanos = 16.6 * 1e6 + frame_start_time_nanos;
90154
FlutterEngineOnVsync(tizen_vsync_waiter->engine_->flutter_engine,

shell/platform/tizen/tizen_vsync_waiter.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include <Ecore.h>
99
#include <tdm_client.h>
10+
1011
#include "flutter/shell/platform/embedder/embedder.h"
1112

1213
class TizenEmbedderEngine;
@@ -21,16 +22,19 @@ class TizenVsyncWaiter {
2122
bool CreateTDMVblank();
2223
void DestoryTDMVblank();
2324
bool TDMValid();
25+
void SendMessage(int val);
2426
static void TdmClientVblankCallback(tdm_client_vblank* vblank,
2527
tdm_error error, unsigned int sequence,
2628
unsigned int tv_sec, unsigned int tv_usec,
2729
void* user_data);
28-
static void RequestVblank(void* data, Ecore_Thread* thread);
30+
static void RequestVblankLoop(void* data, Ecore_Thread* thread);
31+
static void VblankLoopFinish(void* data, Ecore_Thread* thread);
2932
tdm_client* client_{nullptr};
3033
tdm_client_output* output_{nullptr};
3134
tdm_client_vblank* vblank_{nullptr};
3235
TizenEmbedderEngine* engine_{nullptr};
3336
intptr_t baton_{0};
37+
Ecore_Thread* vblank_thread_{nullptr};
3438
};
3539

3640
#endif // EMBEDDER_TIZEN_VSYNC_WAITER_H_

0 commit comments

Comments
 (0)