Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
96 changes: 79 additions & 17 deletions shell/platform/tizen/tizen_vsync_waiter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,103 @@

#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_VBLNAK = 0;

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

static Eina_Thread_Queue* vblankThreadQueue{nullptr};

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

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

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

void TizenVsyncWaiter::SendMessage(int val) {
if (!vblankThreadQueue || !vblankThread_) {
FT_LOGE("vblank thread or vblank thread queue not valid");
return;
}
Msg* msg;
void* ref;
msg = (Msg*)eina_thread_queue_send(vblankThreadQueue, sizeof(Msg), &ref);
msg->value = val;
eina_thread_queue_send_done(vblankThreadQueue, 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 (!vblankThreadQueue) {
FT_LOGE("Vblank thread queue is not valid");
return;
}
msg = (Msg*)eina_thread_queue_wait(vblankThreadQueue, &ref);
if (msg) {
eina_thread_queue_wait_done(vblankThreadQueue, ref);
} else {
FT_LOGE("Message is null");
continue;
}
if (msg->value == QUEUE_QUIT) {
FT_LOGD("Message queue quit");
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);
tizen_vsync_waiter->DestoryTDMVblank();
return;
}
tdm_client_handle_events(tizen_vsync_waiter->client_);
}
}

void TizenVsyncWaiter::VblankLoopFinish(void* data, Ecore_Thread* thread) {
FT_LOGD("VblankLoopFinish!!!!!!");
eina_thread_queue_free(vblankThreadQueue);
}

bool TizenVsyncWaiter::CreateTDMVblank() {
tdm_error ret;
client_ = tdm_client_create(&ret);
Expand Down Expand Up @@ -67,6 +130,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 +144,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* vblankThread_{nullptr};
};

#endif // EMBEDDER_TIZEN_VSYNC_WAITER_H_