Skip to content
Open
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
2 changes: 2 additions & 0 deletions flutter/shell/platform/tizen/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ template("embedder") {
"ecore_input",
"ecore_wl2",
"eina",
"glib-2.0",
"gio-2.0",
"feedback",
"flutter_engine",
Expand Down Expand Up @@ -236,6 +237,7 @@ executable("flutter_tizen_unittests") {
"flutter_tizen_engine_unittest.cc",
"flutter_tizen_texture_registrar_unittests.cc",
"flutter_tizen_view_unittests.cc",
"tizen_event_loop_unittests.cc",
]

ldflags = [ "-Wl,--unresolved-symbols=ignore-in-shared-libs" ]
Expand Down
1 change: 0 additions & 1 deletion flutter/shell/platform/tizen/channels/window_channel.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
#include "flutter/shell/platform/tizen/channels/encodable_value_holder.h"
#include "flutter/shell/platform/tizen/logger.h"
#include "flutter/shell/platform/tizen/tizen_window.h"
#include "flutter/shell/platform/tizen/tizen_window_ecore_wl2.h"

namespace flutter {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <Ecore.h>
#include <system_info.h>

#include "flutter/shell/platform/tizen/flutter_tizen_display_monitor.h"
Expand All @@ -29,12 +28,7 @@ void FlutterTizenDisplayMonitor::UpdateDisplays() {
display.display_id = 0;
display.single_display = true;

double fps = ecore_animator_frametime_get();
if (fps <= 0.0) {
display.refresh_rate = 0.0;
} else {
display.refresh_rate = 1 / fps;
}
display.refresh_rate = 60.0;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Linux embedder (fl_display_monitor.cc) gets the real per-monitor refresh_rate via gdk_monitor_get_refresh_rate() and updates it on hotplug. GDK isn't available on Tizen, but the same value is obtainable by directly parsing the refresh field from the wl_output.mode event - no Ecore needed. Could you at least file a follow-up issue for the hardcoded 60.0 instead of leaving it silent?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ecore_animator_frametime_get() returns the default value of 1 / 60.0f unless otherwise set. Therefore, apply 60.0 to match existing behavior.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right that ecore_animator_frametime_get() defaults to 60, but it doesn't actually reflect the real monitor's frame rate, so this will need to be fixed eventually. Even if not right now, could we at least leave a follow-up issue for it?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

um... #193 I have made an issue. However, I am not sure if we will be able to resolve it.


int32_t width = 0, height = 0, dpi = 0;
FlutterTizenView* view = engine_->view();
Expand Down
5 changes: 0 additions & 5 deletions flutter/shell/platform/tizen/flutter_tizen_engine_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

#include "flutter/shell/platform/tizen/flutter_tizen_engine.h"

#include <Ecore.h>

#include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
#include "flutter/shell/platform/tizen/testing/engine_modifier.h"
#include "gtest/gtest.h"
Expand All @@ -14,9 +12,6 @@ namespace flutter {
namespace testing {

class FlutterTizenEngineTest : public ::testing::Test {
public:
FlutterTizenEngineTest() { ecore_init(); }

protected:
void SetUp() {
FlutterDesktopEngineProperties engine_prop = {};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

#include "flutter/shell/platform/tizen/flutter_tizen_texture_registrar.h"

#include <Ecore.h>

#include <iostream>

#include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
Expand All @@ -17,9 +15,6 @@ namespace flutter {
namespace testing {

class FlutterTizenTextureRegistrarTest : public ::testing::Test {
public:
FlutterTizenTextureRegistrarTest() { ecore_init(); }

protected:
void SetUp() {
FlutterDesktopEngineProperties engine_prop = {};
Expand Down
4 changes: 0 additions & 4 deletions flutter/shell/platform/tizen/flutter_tizen_view_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

#include "flutter/shell/platform/tizen/flutter_tizen_view.h"

#include <Ecore.h>

#include <vector>

#include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
Expand Down Expand Up @@ -47,7 +45,6 @@ class TestTizenView : public TizenWindow {
};

TEST(FlutterTizenViewTest, SendsAndRequestsViewFocus) {
ecore_init();
{
FlutterDesktopEngineProperties properties = {};
properties.assets_path = "/foo/flutter_assets";
Expand Down Expand Up @@ -110,7 +107,6 @@ TEST(FlutterTizenViewTest, SendsAndRequestsViewFocus) {
view.OnFocusChangeRequest(request);
EXPECT_FALSE(tizen_view_ptr->activated);
}
ecore_shutdown();
}

} // namespace
Expand Down
140 changes: 73 additions & 67 deletions flutter/shell/platform/tizen/tizen_event_loop.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,109 +6,115 @@
#include "tizen_event_loop.h"

#include <utility>
#include <vector>

namespace flutter {

namespace {

GSourceFuncs kTaskSourceFuncs = {
nullptr,
nullptr,
[](GSource*, GSourceFunc callback, gpointer user_data) -> gboolean {
return callback(user_data);
},
nullptr,
nullptr,
nullptr,
};

} // namespace

TizenEventLoop::TizenEventLoop(std::thread::id main_thread_id,
CurrentTimeProc get_current_time,
TaskExpiredCallback on_task_expired)
: main_thread_id_(main_thread_id),
get_current_time_(get_current_time),
on_task_expired_(std::move(on_task_expired)) {
ecore_pipe_ = ecore_pipe_add(
[](void* data, void* buffer, unsigned int nbyte) -> void {
auto* self = static_cast<TizenEventLoop*>(data);
self->ExecuteTaskEvents();
on_task_expired_(std::move(on_task_expired)),
task_source_(g_source_new(&kTaskSourceFuncs, sizeof(GSource))) {
g_source_set_callback(
task_source_,
[](gpointer data) -> gboolean {
static_cast<TizenEventLoop*>(data)->ExecuteTaskEvents();
return G_SOURCE_CONTINUE;
},
this);
this, nullptr);

g_source_set_can_recurse(task_source_, TRUE);
g_source_attach(task_source_, nullptr);
}

TizenEventLoop::~TizenEventLoop() {
if (ecore_pipe_) {
ecore_pipe_del(ecore_pipe_);
}
*alive_ = false;
g_source_destroy(task_source_);
g_source_unref(task_source_);
}

bool TizenEventLoop::RunsTasksOnCurrentThread() const {
return std::this_thread::get_id() == main_thread_id_;
}

void TizenEventLoop::PostTask(FlutterTask flutter_task,
uint64_t flutter_target_time_nanos) {
std::lock_guard<std::mutex> lock(task_queue_mutex_);
const bool should_reschedule =
task_queue_.empty() ||
flutter_target_time_nanos < task_queue_.top().target_time_nanos;
task_queue_.push({flutter_target_time_nanos, task_order_++, flutter_task});
if (should_reschedule) {
UpdateSourceReadyTimeLocked(get_current_time_());
}
}

void TizenEventLoop::ExecuteTaskEvents() {
const TaskTimePoint now = TaskTimePoint::clock::now();
std::vector<FlutterTask> expired_tasks;
{
std::lock_guard<std::mutex> lock1(task_queue_mutex_);
std::lock_guard<std::mutex> lock2(expired_tasks_mutex_);
while (!task_queue_.empty()) {
const Task& top = task_queue_.top();

if (top.fire_time > now) {
break;
}

expired_tasks_.push_back(task_queue_.top());
std::lock_guard<std::mutex> lock(task_queue_mutex_);
const uint64_t now = get_current_time_();
while (!task_queue_.empty() && task_queue_.top().target_time_nanos <= now) {
expired_tasks.push_back(task_queue_.top().task);
task_queue_.pop();
}
UpdateSourceReadyTimeLocked(now);
}
OnTaskExpired();
}

TizenEventLoop::TaskTimePoint TizenEventLoop::TimePointFromFlutterTime(
uint64_t flutter_target_time_nanos) {
const TaskTimePoint now = TaskTimePoint::clock::now();
const uint64_t flutter_duration =
flutter_target_time_nanos - get_current_time_();
return now + std::chrono::nanoseconds(flutter_duration);
std::shared_ptr<bool> alive = alive_;
for (const FlutterTask& task : expired_tasks) {
OnTaskExpired(&task);
if (!*alive) {
return;
}
}
}

void TizenEventLoop::PostTask(FlutterTask flutter_task,
uint64_t flutter_target_time_nanos) {
Task task;
task.order = ++task_order_;
task.fire_time = TimePointFromFlutterTime(flutter_target_time_nanos);
task.task = flutter_task;
{
std::lock_guard<std::mutex> lock(task_queue_mutex_);
task_queue_.push(task);
void TizenEventLoop::UpdateSourceReadyTimeLocked(uint64_t now) {
if (task_queue_.empty()) {
g_source_set_ready_time(task_source_, -1);
return;
}

const double flutter_duration =
static_cast<double>(flutter_target_time_nanos) - get_current_time_();
if (flutter_duration > 0) {
ecore_timer_add(
flutter_duration / 1000000000.0,
[](void* data) -> Eina_Bool {
auto* self = static_cast<TizenEventLoop*>(data);
if (self->ecore_pipe_) {
ecore_pipe_write(self->ecore_pipe_, nullptr, 0);
}
return ECORE_CALLBACK_CANCEL;
},
this);
} else {
if (ecore_pipe_) {
ecore_pipe_write(ecore_pipe_, nullptr, 0);
}
const uint64_t target_time_nanos = task_queue_.top().target_time_nanos;
if (target_time_nanos <= now) {
g_source_set_ready_time(task_source_, 0);
return;
}

const uint64_t delay_nanos = target_time_nanos - now;
const uint64_t delay_micros = delay_nanos / 1000 + (delay_nanos % 1000 != 0);
g_source_set_ready_time(
task_source_, g_get_monotonic_time() + static_cast<gint64>(delay_micros));
}

TizenPlatformEventLoop::TizenPlatformEventLoop(
std::thread::id main_thread_id,
CurrentTimeProc get_current_time,
TaskExpiredCallback on_task_expired)
: TizenEventLoop(main_thread_id, get_current_time, on_task_expired) {}

TizenPlatformEventLoop::~TizenPlatformEventLoop() {}

void TizenPlatformEventLoop::OnTaskExpired() {
std::vector<Task> local_expired_tasks;
{
std::lock_guard<std::mutex> lock(expired_tasks_mutex_);
local_expired_tasks = std::move(expired_tasks_);
}
: TizenEventLoop(main_thread_id,
get_current_time,
std::move(on_task_expired)) {}

for (const Task& task : local_expired_tasks) {
on_task_expired_(&task.task);
}
void TizenPlatformEventLoop::OnTaskExpired(const FlutterTask* task) {
on_task_expired_(task);
}

} // namespace flutter
Loading
Loading