Skip to content

Commit

Permalink
Refactor TizenVsyncWaiter (#317)
Browse files Browse the repository at this point in the history
  • Loading branch information
swift-kim authored Jul 25, 2022
1 parent 3d21ac7 commit 6c699b2
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 115 deletions.
7 changes: 4 additions & 3 deletions shell/platform/tizen/external_texture.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ struct ExternalTextureGLState {
ExternalTextureExtensionType gl_extension;
};

static std::atomic_long next_texture_id = {1};
static std::atomic<int64_t> next_texture_id = {1};

class ExternalTexture {
public:
Expand All @@ -30,18 +30,19 @@ class ExternalTexture {
texture_id_(next_texture_id++) {
state_->gl_extension = gl_extension;
}

virtual ~ExternalTexture() = default;

// Returns the unique id for the ExternalTextureGL instance.
int64_t TextureId() { return (int64_t)texture_id_; }
int64_t TextureId() { return texture_id_; }

virtual bool PopulateTexture(size_t width,
size_t height,
FlutterOpenGLTexture* opengl_texture) = 0;

protected:
std::unique_ptr<ExternalTextureGLState> state_;
const long texture_id_{0};
const int64_t texture_id_ = 0;
};

} // namespace flutter
Expand Down
10 changes: 5 additions & 5 deletions shell/platform/tizen/tizen_view_elementary.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@
#include "flutter/shell/platform/tizen/logger.h"
#include "flutter/shell/platform/tizen/tizen_view_event_handler_delegate.h"

namespace flutter {

namespace {

static const int kScrollDirectionVertical = 0;
static const int kScrollDirectionHorizontal = 1;
static const int kScrollOffsetMultiplier = 20;
constexpr int kScrollDirectionVertical = 0;
constexpr int kScrollDirectionHorizontal = 1;
constexpr int kScrollOffsetMultiplier = 20;

uint32_t EvasModifierToEcoreEventModifiers(const Evas_Modifier* evas_modifier) {
uint32_t modifiers = 0;
Expand All @@ -40,8 +42,6 @@ void EvasObjectResizeWithMinMaxHint(Evas_Object* object,

} // namespace

namespace flutter {

TizenViewElementary::TizenViewElementary(int32_t width,
int32_t height,
Evas_Object* parent)
Expand Down
151 changes: 71 additions & 80 deletions shell/platform/tizen/tizen_vsync_waiter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,43 +9,44 @@
#include "flutter/shell/platform/tizen/flutter_tizen_engine.h"
#include "flutter/shell/platform/tizen/logger.h"

static const int kMessageQuit = -1;
static const int kMessageRequestVblank = 0;

namespace flutter {

typedef struct {
namespace {

constexpr int kMessageQuit = -1;
constexpr int kMessageRequestVblank = 0;

struct Message {
Eina_Thread_Queue_Msg head;
int event;
intptr_t baton;
} Msg;
};

TizenVsyncWaiter::TizenVsyncWaiter(FlutterTizenEngine* engine)
: engine_(engine) {
vblank_thread_ = ecore_thread_feedback_run(RequestVblankLoop, nullptr,
nullptr, nullptr, this, EINA_TRUE);
} // namespace

TizenVsyncWaiter::TizenVsyncWaiter(FlutterTizenEngine* engine) {
tdm_client_ = std::make_shared<TdmClient>(engine);

vblank_thread_ = ecore_thread_feedback_run(RunVblankLoop, nullptr, nullptr,
nullptr, this, EINA_TRUE);
}

TizenVsyncWaiter::~TizenVsyncWaiter() {
if (tdm_client_) {
tdm_client_->OnEngineStop();
}
Send(kMessageQuit, 0);
tdm_client_.reset();

SendMessage(kMessageQuit, 0);

if (vblank_thread_) {
ecore_thread_cancel(vblank_thread_);
vblank_thread_ = nullptr;
}
}

void TizenVsyncWaiter::SetTdmClient(TdmClient* tdm_client) {
tdm_client_ = tdm_client;
}

void TizenVsyncWaiter::AsyncWaitForVsync(intptr_t baton) {
Send(kMessageRequestVblank, baton);
SendMessage(kMessageRequestVblank, baton);
}

void TizenVsyncWaiter::Send(int event, intptr_t baton) {
void TizenVsyncWaiter::SendMessage(int event, intptr_t baton) {
if (!vblank_thread_ || ecore_thread_check(vblank_thread_)) {
FT_LOG(Error) << "Invalid vblank thread.";
return;
Expand All @@ -56,104 +57,83 @@ void TizenVsyncWaiter::Send(int event, intptr_t baton) {
return;
}

Msg* msg;
void* ref;
msg = static_cast<Msg*>(
eina_thread_queue_send(vblank_thread_queue_, sizeof(Msg), &ref));
msg->event = event;
msg->baton = baton;
Message* message = static_cast<Message*>(
eina_thread_queue_send(vblank_thread_queue_, sizeof(Message), &ref));
message->event = event;
message->baton = baton;
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);
TdmClient tdm_client(tizen_vsync_waiter->engine_);
tizen_vsync_waiter->SetTdmClient(&tdm_client);
if (!tdm_client.IsValid()) {
void TizenVsyncWaiter::RunVblankLoop(void* data, Ecore_Thread* thread) {
auto* self = reinterpret_cast<TizenVsyncWaiter*>(data);

std::weak_ptr<TdmClient> tdm_client = self->tdm_client_;
if (!tdm_client.lock()->IsValid()) {
FT_LOG(Error) << "Invalid tdm_client.";
ecore_thread_cancel(thread);
return;
}

Eina_Thread_Queue* vblank_thread_queue = eina_thread_queue_new();
if (!vblank_thread_queue) {
FT_LOG(Error) << "Invalid vblank thread queue.";
ecore_thread_cancel(thread);
return;
}
self->vblank_thread_queue_ = vblank_thread_queue;

tizen_vsync_waiter->vblank_thread_queue_ = vblank_thread_queue;
while (!ecore_thread_check(thread)) {
void* ref;
Msg* msg;
msg = static_cast<Msg*>(eina_thread_queue_wait(vblank_thread_queue, &ref));
if (msg) {
Message* message = static_cast<Message*>(
eina_thread_queue_wait(vblank_thread_queue, &ref));
if (message->event == kMessageQuit) {
eina_thread_queue_wait_done(vblank_thread_queue, ref);
} else {
FT_LOG(Error) << "Received a null message.";
continue;
break;
}
if (msg->event == kMessageQuit) {
intptr_t baton = message->baton;
eina_thread_queue_wait_done(vblank_thread_queue, ref);

if (tdm_client.expired()) {
break;
}
tdm_client.WaitVblank(msg->baton);
tdm_client.lock()->AwaitVblank(baton);
}

if (vblank_thread_queue) {
eina_thread_queue_free(vblank_thread_queue);
}
}

TdmClient::TdmClient(FlutterTizenEngine* engine) {
if (!CreateTdm()) {
FT_LOG(Error) << "CreateTdm() failed.";
}
engine_ = engine;
}

TdmClient::~TdmClient() {
DestroyTdm();
}

void TdmClient::OnEngineStop() {
std::lock_guard<std::mutex> lock(engine_mutex_);
engine_ = nullptr;
}

void TdmClient::WaitVblank(intptr_t baton) {
baton_ = baton;
tdm_error error = tdm_client_vblank_wait(vblank_, 1, VblankCallback, this);
if (error != TDM_ERROR_NONE) {
FT_LOG(Error) << "tdm_client_vblank_wait() failed.";
return;
}
tdm_client_handle_events(client_);
}

bool TdmClient::CreateTdm() {
tdm_error ret;
client_ = tdm_client_create(&ret);
if (ret != TDM_ERROR_NONE && client_ != NULL) {
if (ret != TDM_ERROR_NONE) {
FT_LOG(Error) << "Failed to create a TDM client.";
return false;
return;
}

output_ = tdm_client_get_output(client_, const_cast<char*>("default"), &ret);
if (ret != TDM_ERROR_NONE && output_ != NULL) {
if (ret != TDM_ERROR_NONE) {
FT_LOG(Error) << "Could not obtain the default client output.";
return false;
return;
}

vblank_ = tdm_client_output_create_vblank(output_, &ret);
if (ret != TDM_ERROR_NONE && vblank_ != NULL) {
if (ret != TDM_ERROR_NONE) {
FT_LOG(Error) << "Failed to create a vblank object.";
return false;
return;
}

tdm_client_vblank_set_enable_fake(vblank_, 1);
return true;

engine_ = engine;
}

void TdmClient::DestroyTdm() {
TdmClient::~TdmClient() {
{
std::lock_guard<std::mutex> lock(engine_mutex_);
engine_ = nullptr;
}
if (vblank_) {
tdm_client_vblank_destroy(vblank_);
vblank_ = nullptr;
Expand All @@ -165,6 +145,16 @@ void TdmClient::DestroyTdm() {
}
}

void TdmClient::AwaitVblank(intptr_t baton) {
baton_ = baton;
tdm_error ret = tdm_client_vblank_wait(vblank_, 1, VblankCallback, this);
if (ret != TDM_ERROR_NONE) {
FT_LOG(Error) << "tdm_client_vblank_wait failed with error: " << ret;
return;
}
tdm_client_handle_events(client_);
}

bool TdmClient::IsValid() {
return vblank_ && client_;
}
Expand All @@ -175,14 +165,15 @@ void TdmClient::VblankCallback(tdm_client_vblank* vblank,
unsigned int tv_sec,
unsigned int tv_usec,
void* user_data) {
TdmClient* client = reinterpret_cast<TdmClient*>(user_data);
FT_ASSERT(client != nullptr);
std::lock_guard<std::mutex> lock(client->engine_mutex_);
if (client->engine_) {
auto* self = reinterpret_cast<TdmClient*>(user_data);
FT_ASSERT(self != nullptr);

std::lock_guard<std::mutex> lock(self->engine_mutex_);
if (self->engine_) {
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;
client->engine_->OnVsync(client->baton_, frame_start_time_nanos,
frame_target_time_nanos);
self->engine_->OnVsync(self->baton_, frame_start_time_nanos,
frame_target_time_nanos);
}
}

Expand Down
38 changes: 21 additions & 17 deletions shell/platform/tizen/tizen_vsync_waiter.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

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

#include <memory>
#include <mutex>

#include "flutter/shell/platform/embedder/embedder.h"
Expand All @@ -19,41 +21,43 @@ class TdmClient {
public:
TdmClient(FlutterTizenEngine* engine);
virtual ~TdmClient();
bool CreateTdm();
void DestroyTdm();

bool IsValid();
void WaitVblank(intptr_t baton);
void OnEngineStop();
void AwaitVblank(intptr_t baton);

private:
static void VblankCallback(tdm_client_vblank* vblank,
tdm_error error,
unsigned int sequence,
unsigned int tv_sec,
unsigned int tv_usec,
void* user_data);

private:
FlutterTizenEngine* engine_ = nullptr;
std::mutex engine_mutex_;
tdm_client* client_{nullptr};
tdm_client_output* output_{nullptr};
tdm_client_vblank* vblank_{nullptr};
FlutterTizenEngine* engine_{nullptr};
intptr_t baton_{0};

tdm_client* client_ = nullptr;
tdm_client_output* output_ = nullptr;
tdm_client_vblank* vblank_ = nullptr;

intptr_t baton_ = 0;
};

class TizenVsyncWaiter {
public:
TizenVsyncWaiter(FlutterTizenEngine* engine);
virtual ~TizenVsyncWaiter();

void AsyncWaitForVsync(intptr_t baton);
void SetTdmClient(TdmClient* tdm_client);

private:
void Send(int event, intptr_t baton);
static void RequestVblankLoop(void* data, Ecore_Thread* thread);
Ecore_Thread* vblank_thread_{nullptr};
Eina_Thread_Queue* vblank_thread_queue_{nullptr};
FlutterTizenEngine* engine_{nullptr};
TdmClient* tdm_client_{nullptr};
void SendMessage(int event, intptr_t baton);

static void RunVblankLoop(void* data, Ecore_Thread* thread);

std::shared_ptr<TdmClient> tdm_client_;
Ecore_Thread* vblank_thread_ = nullptr;
Eina_Thread_Queue* vblank_thread_queue_ = nullptr;
};

} // namespace flutter
Expand Down
10 changes: 5 additions & 5 deletions shell/platform/tizen/tizen_window_ecore_wl2.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@
#include "flutter/shell/platform/tizen/logger.h"
#include "flutter/shell/platform/tizen/tizen_view_event_handler_delegate.h"

namespace flutter {

namespace {

static const int kScrollDirectionVertical = 0;
static const int kScrollDirectionHorizontal = 1;
static const int kScrollOffsetMultiplier = 20;
constexpr int kScrollDirectionVertical = 0;
constexpr int kScrollDirectionHorizontal = 1;
constexpr int kScrollOffsetMultiplier = 20;

} // namespace

namespace flutter {

TizenWindowEcoreWl2::TizenWindowEcoreWl2(TizenGeometry geometry,
bool transparent,
bool focusable,
Expand Down
Loading

0 comments on commit 6c699b2

Please sign in to comment.