Skip to content

Add vsync wayland support #140

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

Merged
merged 7 commits into from
May 26, 2021
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
7 changes: 7 additions & 0 deletions cmake/build.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,17 @@ else()
CODE_FILE ${_wayland_protocols_src_dir}/text-input-unstable-v3-protocol.c
HEADER_FILE ${_wayland_protocols_src_dir}/text-input-unstable-v3-client-protocol.h)

generate_wayland_client_protocol(
PROTOCOL_FILE ${_wayland_protocols_xml_dir}/stable/presentation-time/presentation-time.xml
CODE_FILE ${_wayland_protocols_src_dir}/presentation-time-protocol.c
HEADER_FILE ${_wayland_protocols_src_dir}/presentation-time-protocol.h)

add_definitions(-DDISPLAY_BACKEND_TYPE_WAYLAND)
set(DISPLAY_BACKEND_SRC
${_wayland_protocols_src_dir}/xdg-shell-protocol.c
${_wayland_protocols_src_dir}/text-input-unstable-v1-protocol.c
${_wayland_protocols_src_dir}/text-input-unstable-v3-protocol.c
${_wayland_protocols_src_dir}/presentation-time-protocol.c
src/flutter/shell/platform/linux_embedded/window/linuxes_window_wayland.cc
src/flutter/shell/platform/linux_embedded/window/native_window_wayland.cc)
endif()
Expand Down Expand Up @@ -105,6 +111,7 @@ add_executable(${TARGET}
src/flutter/shell/platform/linux_embedded/system_utils.cc
src/flutter/shell/platform/linux_embedded/logger.cc
src/flutter/shell/platform/linux_embedded/external_texture_gl.cc
src/flutter/shell/platform/linux_embedded/vsync_waiter.cc
src/flutter/shell/platform/linux_embedded/flutter_linuxes_texture_registrar.cc
src/flutter/shell/platform/linux_embedded/plugin/key_event_plugin.cc
src/flutter/shell/platform/linux_embedded/plugin/keyboard_glfw_util.cc
Expand Down
14 changes: 9 additions & 5 deletions examples/flutter-drm-eglstream-backend/flutter_window.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include "flutter_window.h"

#include <chrono>
#include <cmath>
#include <iostream>
#include <thread>

#include "generated_plugin_registrant.h"
Expand Down Expand Up @@ -61,11 +63,13 @@ void FlutterWindow::Run() {
std::chrono::steady_clock::time_point::clock::now() +
wait_duration);
} else {
// Wait 1/60 [sec] = 13 [msec] if no events.
next_event_time =
std::min(next_event_time,
std::chrono::steady_clock::time_point::clock::now() +
std::chrono::milliseconds(13));
// Wait for the next frame if no events.
auto frame_rate = flutter_view_controller_->view()->GetFrameRate();
next_event_time = std::min(
next_event_time,
std::chrono::steady_clock::time_point::clock::now() +
std::chrono::milliseconds(
static_cast<int>(std::trunc(1000000.0 / frame_rate))));
}
next_flutter_event_time =
std::max(next_flutter_event_time, next_event_time);
Expand Down
14 changes: 9 additions & 5 deletions examples/flutter-drm-gbm-backend/flutter_window.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include "flutter_window.h"

#include <chrono>
#include <cmath>
#include <iostream>
#include <thread>

#include "generated_plugin_registrant.h"
Expand Down Expand Up @@ -61,11 +63,13 @@ void FlutterWindow::Run() {
std::chrono::steady_clock::time_point::clock::now() +
wait_duration);
} else {
// Wait 1/60 [sec] = 13 [msec] if no events.
next_event_time =
std::min(next_event_time,
std::chrono::steady_clock::time_point::clock::now() +
std::chrono::milliseconds(13));
// Wait for the next frame if no events.
auto frame_rate = flutter_view_controller_->view()->GetFrameRate();
next_event_time = std::min(
next_event_time,
std::chrono::steady_clock::time_point::clock::now() +
std::chrono::milliseconds(
static_cast<int>(std::trunc(1000000.0 / frame_rate))));
}
next_flutter_event_time =
std::max(next_flutter_event_time, next_event_time);
Expand Down
14 changes: 9 additions & 5 deletions examples/flutter-external-texture-plugin/flutter_window.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include "flutter_window.h"

#include <chrono>
#include <cmath>
#include <iostream>
#include <thread>

#include "generated_plugin_registrant.h"
Expand Down Expand Up @@ -61,11 +63,13 @@ void FlutterWindow::Run() {
std::chrono::steady_clock::time_point::clock::now() +
wait_duration);
} else {
// Wait 1/60 [sec] = 13 [msec] if no events.
next_event_time =
std::min(next_event_time,
std::chrono::steady_clock::time_point::clock::now() +
std::chrono::milliseconds(13));
// Wait for the next frame if no events.
auto frame_rate = flutter_view_controller_->view()->GetFrameRate();
next_event_time = std::min(
next_event_time,
std::chrono::steady_clock::time_point::clock::now() +
std::chrono::milliseconds(
static_cast<int>(std::trunc(1000000.0 / frame_rate))));
}
next_flutter_event_time =
std::max(next_flutter_event_time, next_event_time);
Expand Down
14 changes: 9 additions & 5 deletions examples/flutter-wayland-client/flutter_window.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include "flutter_window.h"

#include <chrono>
#include <cmath>
#include <iostream>
#include <thread>

#include "generated_plugin_registrant.h"
Expand Down Expand Up @@ -61,11 +63,13 @@ void FlutterWindow::Run() {
std::chrono::steady_clock::time_point::clock::now() +
wait_duration);
} else {
// Wait 1/60 [sec] = 13 [msec] if no events.
next_event_time =
std::min(next_event_time,
std::chrono::steady_clock::time_point::clock::now() +
std::chrono::milliseconds(13));
// Wait for the next frame if no events.
auto frame_rate = flutter_view_controller_->view()->GetFrameRate();
next_event_time = std::min(
next_event_time,
std::chrono::steady_clock::time_point::clock::now() +
std::chrono::milliseconds(
static_cast<int>(std::trunc(1000000.0 / frame_rate))));
}
next_flutter_event_time =
std::max(next_flutter_event_time, next_event_time);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include "flutter_window.h"

#include <chrono>
#include <cmath>
#include <iostream>
#include <thread>

#include "generated_plugin_registrant.h"
Expand Down Expand Up @@ -61,11 +63,13 @@ void FlutterWindow::Run() {
std::chrono::steady_clock::time_point::clock::now() +
wait_duration);
} else {
// Wait 1/60 [sec] = 13 [msec] if no events.
next_event_time =
std::min(next_event_time,
std::chrono::steady_clock::time_point::clock::now() +
std::chrono::milliseconds(13));
// Wait for the next frame if no events.
auto frame_rate = flutter_view_controller_->view()->GetFrameRate();
next_event_time = std::min(
next_event_time,
std::chrono::steady_clock::time_point::clock::now() +
std::chrono::milliseconds(
static_cast<int>(std::trunc(1000000.0 / frame_rate))));
}
next_flutter_event_time =
std::max(next_flutter_event_time, next_event_time);
Expand Down
14 changes: 9 additions & 5 deletions examples/flutter-weston-desktop-shell/flutter_window.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include "flutter_window.h"

#include <chrono>
#include <cmath>
#include <iostream>
#include <thread>

#include "generated_plugin_registrant.h"
Expand Down Expand Up @@ -61,11 +63,13 @@ void FlutterWindow::Run() {
std::chrono::steady_clock::time_point::clock::now() +
wait_duration);
} else {
// Wait 1/60 [sec] = 13 [msec] if no events.
next_event_time =
std::min(next_event_time,
std::chrono::steady_clock::time_point::clock::now() +
std::chrono::milliseconds(13));
// Wait for the next frame if no events.
auto frame_rate = flutter_view_controller_->view()->GetFrameRate();
next_event_time = std::min(
next_event_time,
std::chrono::steady_clock::time_point::clock::now() +
std::chrono::milliseconds(
static_cast<int>(std::trunc(1000000.0 / frame_rate))));
}
next_flutter_event_time =
std::max(next_flutter_event_time, next_event_time);
Expand Down
14 changes: 9 additions & 5 deletions examples/flutter-x11-client/flutter_window.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include "flutter_window.h"

#include <chrono>
#include <cmath>
#include <iostream>
#include <thread>

#include "generated_plugin_registrant.h"
Expand Down Expand Up @@ -61,11 +63,13 @@ void FlutterWindow::Run() {
std::chrono::steady_clock::time_point::clock::now() +
wait_duration);
} else {
// Wait 1/60 [sec] = 13 [msec] if no events.
next_event_time =
std::min(next_event_time,
std::chrono::steady_clock::time_point::clock::now() +
std::chrono::milliseconds(13));
// Wait for the next frame if no events.
auto frame_rate = flutter_view_controller_->view()->GetFrameRate();
next_event_time = std::min(
next_event_time,
std::chrono::steady_clock::time_point::clock::now() +
std::chrono::milliseconds(
static_cast<int>(std::trunc(1000000.0 / frame_rate))));
}
next_flutter_event_time =
std::max(next_flutter_event_time, next_event_time);
Expand Down
3 changes: 3 additions & 0 deletions src/client_wrapper/include/flutter/flutter_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ class FlutterView {
// you have to call this every time in the main loop.
bool DispatchEvent() { return FlutterDesktopViewDispatchEvent(view_); }

// Returns the display frame rate.
int32_t GetFrameRate() { return FlutterDesktopViewGetFrameRate(view_); }

private:
// Handle for interacting with the C API's view.
FlutterDesktopViewRef view_ = nullptr;
Expand Down
4 changes: 4 additions & 0 deletions src/flutter/shell/platform/linux_embedded/flutter_linuxes.cc
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ bool FlutterDesktopViewDispatchEvent(FlutterDesktopViewRef view) {
return ViewFromHandle(view)->DispatchEvent();
}

int32_t FlutterDesktopViewGetFrameRate(FlutterDesktopViewRef view) {
return ViewFromHandle(view)->GetFrameRate();
}

FlutterDesktopEngineRef FlutterDesktopEngineCreate(
const FlutterDesktopEngineProperties& engine_properties) {
flutter::FlutterProjectBundle project(engine_properties);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ FlutterLinuxesEngine::FlutterLinuxesEngine(const FlutterProjectBundle& project)
std::make_unique<BasicMessageChannel<rapidjson::Document>>(
messenger_wrapper_.get(), "flutter/settings",
&JsonMessageCodec::GetInstance());

vsync_waiter_ = std::make_unique<VsyncWaiter>();
}

FlutterLinuxesEngine::~FlutterLinuxesEngine() { Stop(); }
Expand Down Expand Up @@ -204,7 +206,15 @@ bool FlutterLinuxesEngine::RunWithEntrypoint(const char* entrypoint) {
auto host = static_cast<FlutterLinuxesEngine*>(user_data);
return host->HandlePlatformMessage(engine_message);
};

// todo: add drm/x11 support.
// https://github.com/sony/flutter-embedded-linux/issues/136
// https://github.com/sony/flutter-embedded-linux/issues/137
#if defined(DISPLAY_BACKEND_TYPE_WAYLAND)
args.vsync_callback = [](void* user_data, intptr_t baton) -> void {
auto host = static_cast<FlutterLinuxesEngine*>(user_data);
host->vsync_waiter_->NotifyWaitForVsync(baton);
};
#endif
args.custom_task_runners = &custom_task_runners;

if (aot_data_) {
Expand Down Expand Up @@ -362,4 +372,19 @@ bool FlutterLinuxesEngine::MarkExternalTextureFrameAvailable(
engine_, texture_id) == kSuccess);
}

void FlutterLinuxesEngine::OnVsync(uint64_t last_frame_time_nanos,
uint64_t vsync_interval_time_nanos) {
uint64_t current_time_nanos = embedder_api_.GetCurrentTime();
uint64_t after_vsync_passed_time_nanos =
(current_time_nanos - last_frame_time_nanos) % vsync_interval_time_nanos;
uint64_t frame_start_time_nanos =
current_time_nanos +
(vsync_interval_time_nanos - after_vsync_passed_time_nanos);
uint64_t frame_target_time_nanos =
frame_start_time_nanos + vsync_interval_time_nanos;

vsync_waiter_->NotifyVsync(engine_, &embedder_api_, frame_start_time_nanos,
frame_target_time_nanos);
}

} // namespace flutter
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "flutter/shell/platform/linux_embedded/flutter_project_bundle.h"
#include "flutter/shell/platform/linux_embedded/public/flutter_linuxes.h"
#include "flutter/shell/platform/linux_embedded/task_runner.h"
#include "flutter/shell/platform/linux_embedded/vsync_waiter.h"

namespace flutter {

Expand Down Expand Up @@ -110,6 +111,10 @@ class FlutterLinuxesEngine {
// given |texture_id|.
bool MarkExternalTextureFrameAvailable(int64_t texture_id);

// Notifies the engine about the vsync event.
void OnVsync(uint64_t last_frame_time_nanos,
uint64_t vsync_interval_time_nanos);

private:
// Allows swapping out embedder_api_ calls in tests.
friend class EngineEmbedderApiModifier;
Expand Down Expand Up @@ -158,6 +163,9 @@ class FlutterLinuxesEngine {
// is being destroyed.
FlutterDesktopOnPluginRegistrarDestroyed
plugin_registrar_destruction_callback_ = nullptr;

// The vsync waiter.
std::unique_ptr<VsyncWaiter> vsync_waiter_;
};

} // namespace flutter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,11 @@ void FlutterLinuxesView::OnScroll(double x, double y, double delta_x,
SendScroll(x, y, delta_x, delta_y, scroll_offset_multiplier);
}

void FlutterLinuxesView::OnVsync(uint64_t last_frame_time_nanos,
uint64_t vsync_interval_time_nanos) {
engine_->OnVsync(last_frame_time_nanos, vsync_interval_time_nanos);
}

FlutterLinuxesView::touch_point* FlutterLinuxesView::GgeTouchPoint(int32_t id) {
const size_t nmemb = sizeof(touch_event_) / sizeof(struct touch_point);
int invalid = -1;
Expand Down Expand Up @@ -381,4 +386,8 @@ LinuxesRenderSurfaceTarget* FlutterLinuxesView::GetRenderSurfaceTarget() const {

FlutterLinuxesEngine* FlutterLinuxesView::GetEngine() { return engine_.get(); }

int32_t FlutterLinuxesView::GetFrameRate() {
return binding_handler_->GetFrameRate();
}

} // namespace flutter
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ class FlutterLinuxesView : public WindowBindingHandlerDelegate {
// Returns the engine backing this view.
FlutterLinuxesEngine* GetEngine();

// Returns the frame rate of the display.
int32_t GetFrameRate();

// Callbacks for clearing context, settings context and swapping buffers.
void* ProcResolver(const char* name);
bool MakeCurrent();
Expand Down Expand Up @@ -115,6 +118,10 @@ class FlutterLinuxesView : public WindowBindingHandlerDelegate {
void OnScroll(double x, double y, double delta_x, double delta_y,
int scroll_offset_multiplier) override;

// |WindowBindingHandlerDelegate|
void OnVsync(uint64_t frame_start_time_nanos,
uint64_t frame_target_time_nanos) override;

private:
// Struct holding the mouse state. The engine doesn't keep track of which
// mouse buttons have been pressed, so it's the embedding's responsibility.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,16 @@ FLUTTER_EXPORT void FlutterDesktopViewControllerDestroy(
// Its lifetime is the same as the |controller|'s.
FLUTTER_EXPORT FlutterDesktopEngineRef FlutterDesktopViewControllerGetEngine(
FlutterDesktopViewControllerRef controller);
// Returns the view managed by the given controller.

// Returns the view managed by the given controller.
FLUTTER_EXPORT FlutterDesktopViewRef
FlutterDesktopViewControllerGetView(FlutterDesktopViewControllerRef controller);

FLUTTER_EXPORT bool FlutterDesktopViewDispatchEvent(FlutterDesktopViewRef view);

// Returns the display frame rate by the given controller.
FLUTTER_EXPORT int32_t FlutterDesktopViewGetFrameRate(FlutterDesktopViewRef view);

// ========== Engine ==========

// Creates a Flutter engine with the given properties.
Expand Down
Loading