Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement message queue to handle vblank request #32

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions shell/platform/tizen/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ source_set("flutter_tizen") {
"ecore",
"ecore_imf",
"ecore_input",
"eina",
"EGL",
"evas",
"flutter_engine",
Expand Down
98 changes: 81 additions & 17 deletions shell/platform/tizen/tizen_vsync_waiter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,102 @@

#include "tizen_vsync_waiter.h"

#include <eina_thread_queue.h>

#include "flutter/shell/platform/tizen/tizen_embedder_engine.h"
#include "flutter/shell/platform/tizen/tizen_log.h"

void TizenVsyncWaiter::RequestVblank(void* data, Ecore_Thread* thread) {
TizenVsyncWaiter* tizen_vsync_waiter =
reinterpret_cast<TizenVsyncWaiter*>(data);
if (!ecore_thread_check(thread)) {
tdm_error error = tdm_client_vblank_wait(tizen_vsync_waiter->vblank_, 1,
TdmClientVblankCallback, data);
if (error != TDM_ERROR_NONE) {
FT_LOGE("tdm_client_vblank_wait error %d", error);
return;
}
tdm_client_handle_events(tizen_vsync_waiter->client_);
}
}
static const int QUEUE_QUIT = -1;
static const int QUEUE_REQUEST_VBLANK = 0;

typedef struct {
Eina_Thread_Queue_Msg head;
int value;
} Msg;

static Eina_Thread_Queue* vblank_thread_queue{nullptr};

TizenVsyncWaiter::TizenVsyncWaiter(TizenEmbedderEngine* engine)
: engine_(engine) {
if (!CreateTDMVblank()) {
FT_LOGE("Failed to create TDM vblank");
DestoryTDMVblank();
} else {
vblank_thread_queue = eina_thread_queue_new();
vblank_thread_ =
ecore_thread_feedback_run(RequestVblankLoop, NULL, VblankLoopFinish,
VblankLoopFinish, this, EINA_TRUE);
}
}

TizenVsyncWaiter::~TizenVsyncWaiter() { DestoryTDMVblank(); }
TizenVsyncWaiter::~TizenVsyncWaiter() {
SendMessage(QUEUE_QUIT);
if (vblank_thread_) {
ecore_thread_cancel(vblank_thread_);
vblank_thread_ = nullptr;
}
DestoryTDMVblank();
}

void TizenVsyncWaiter::AsyncWaitForVsync(intptr_t baton) {
baton_ = baton;
if (TDMValid()) {
ecore_thread_run(RequestVblank, NULL, NULL, this);
SendMessage(QUEUE_REQUEST_VBLANK);
}
}

void TizenVsyncWaiter::SendMessage(int val) {
if (!vblank_thread_queue || !vblank_thread_) {
FT_LOGE("vblank thread or vblank thread queue not valid");
return;
}
Msg* msg;
void* ref;
msg = (Msg*)eina_thread_queue_send(vblank_thread_queue, sizeof(Msg), &ref);
msg->value = val;
eina_thread_queue_send_done(vblank_thread_queue, ref);
}

void TizenVsyncWaiter::RequestVblankLoop(void* data, Ecore_Thread* thread) {
TizenVsyncWaiter* tizen_vsync_waiter =
reinterpret_cast<TizenVsyncWaiter*>(data);
void* ref;
Msg* msg;
while (!ecore_thread_check(thread)) {
if (!vblank_thread_queue) {
FT_LOGE("Vblank thread queue is not valid");
return;
}
msg = (Msg*)eina_thread_queue_wait(vblank_thread_queue, &ref);
if (msg) {
eina_thread_queue_wait_done(vblank_thread_queue, ref);
} else {
FT_LOGE("Message is null");
continue;
}
if (msg->value == QUEUE_QUIT) {
FT_LOGD("Message queue quit");
bbrto21 marked this conversation as resolved.
Show resolved Hide resolved
return;
}
if (!tizen_vsync_waiter->TDMValid()) {
FT_LOGE("TDM not valid");
return;
}
tdm_error error = tdm_client_vblank_wait(tizen_vsync_waiter->vblank_, 1,
TdmClientVblankCallback, data);
if (error != TDM_ERROR_NONE) {
FT_LOGE("tdm_client_vblank_wait error %d", error);
continue;
}
tdm_client_handle_events(tizen_vsync_waiter->client_);
}
}

void TizenVsyncWaiter::VblankLoopFinish(void* data, Ecore_Thread* thread) {
FT_LOGD("VblankLoopFinish.");
if (vblank_thread_queue) {
eina_thread_queue_free(vblank_thread_queue);
vblank_thread_queue = nullptr;
}
}

Expand Down Expand Up @@ -67,6 +132,7 @@ void TizenVsyncWaiter::DestoryTDMVblank() {
tdm_client_vblank_destroy(vblank_);
vblank_ = nullptr;
}
output_ = nullptr;
if (client_) {
tdm_client_destroy(client_);
client_ = nullptr;
Expand All @@ -80,11 +146,9 @@ void TizenVsyncWaiter::TdmClientVblankCallback(
unsigned int tv_sec, unsigned int tv_usec, void* user_data) {
TizenVsyncWaiter* tizen_vsync_waiter =
reinterpret_cast<TizenVsyncWaiter*>(user_data);

FT_ASSERT(tizen_vsync_waiter != nullptr);
FT_ASSERT(tizen_vsync_waiter->engine_ != nullptr);
FT_ASSERT(tizen_vsync_waiter->engine_->flutter_engine != nullptr);

uint64_t frame_start_time_nanos = tv_sec * 1e9 + tv_usec * 1e3;
uint64_t frame_target_time_nanos = 16.6 * 1e6 + frame_start_time_nanos;
FlutterEngineOnVsync(tizen_vsync_waiter->engine_->flutter_engine,
Expand Down
6 changes: 5 additions & 1 deletion shell/platform/tizen/tizen_vsync_waiter.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <Ecore.h>
#include <tdm_client.h>

#include "flutter/shell/platform/embedder/embedder.h"

class TizenEmbedderEngine;
Expand All @@ -21,16 +22,19 @@ class TizenVsyncWaiter {
bool CreateTDMVblank();
void DestoryTDMVblank();
bool TDMValid();
void SendMessage(int val);
static void TdmClientVblankCallback(tdm_client_vblank* vblank,
tdm_error error, unsigned int sequence,
unsigned int tv_sec, unsigned int tv_usec,
void* user_data);
static void RequestVblank(void* data, Ecore_Thread* thread);
static void RequestVblankLoop(void* data, Ecore_Thread* thread);
static void VblankLoopFinish(void* data, Ecore_Thread* thread);
tdm_client* client_{nullptr};
tdm_client_output* output_{nullptr};
tdm_client_vblank* vblank_{nullptr};
TizenEmbedderEngine* engine_{nullptr};
intptr_t baton_{0};
Ecore_Thread* vblank_thread_{nullptr};
};

#endif // EMBEDDER_TIZEN_VSYNC_WAITER_H_