Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Windows: Prevent platform thread from deadlocking during window resize #33478

Merged
merged 1 commit into from
May 19, 2022
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
21 changes: 14 additions & 7 deletions shell/platform/windows/flutter_windows_view.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,29 @@

namespace flutter {

namespace {
// The maximum duration to block the platform thread for while waiting
// for a window resize operation to complete.
constexpr std::chrono::milliseconds kWindowResizeTimeout{100};

/// Returns true if the surface will be updated as part of the resize process.
///
/// This is called on window resize to determine if the platform thread needs
/// to be blocked until the frame with the right size has been rendered. It
/// should be kept in-sync with how the engine deals with a new surface request
/// as seen in `CreateOrUpdateSurface` in `GPUSurfaceGL`.
static bool SurfaceWillUpdate(size_t cur_width,
size_t cur_height,
size_t target_width,
size_t target_height) {
bool SurfaceWillUpdate(size_t cur_width,
size_t cur_height,
size_t target_width,
size_t target_height) {
// TODO (https://github.com/flutter/flutter/issues/65061) : Avoid special
// handling for zero dimensions.
bool non_zero_target_dims = target_height > 0 && target_width > 0;
bool not_same_size =
(cur_height != target_height) || (cur_width != target_width);
return non_zero_target_dims && not_same_size;
}
} // namespace

FlutterWindowsView::FlutterWindowsView(
std::unique_ptr<WindowBindingHandler> window_binding) {
Expand Down Expand Up @@ -150,9 +156,10 @@ void FlutterWindowsView::OnWindowSizeChanged(size_t width, size_t height) {
// Block the platform thread until:
// 1. GetFrameBufferId is called with the right frame size.
// 2. Any pending SwapBuffers calls have been invoked.
resize_cv_.wait(lock, [&resize_status = resize_status_] {
return resize_status == ResizeState::kDone;
});
resize_cv_.wait_for(lock, kWindowResizeTimeout,
[&resize_status = resize_status_] {
return resize_status == ResizeState::kDone;
});
}
}

Expand Down
31 changes: 31 additions & 0 deletions shell/platform/windows/flutter_windows_view_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <comutil.h>
#include <oleacc.h>

#include <future>
#include <iostream>
#include <vector>

Expand Down Expand Up @@ -546,5 +547,35 @@ TEST(FlutterWindowsViewTest, AccessibilityHitTesting) {
EXPECT_EQ(varchild.pdispVal, node3_delegate->GetNativeViewAccessible());
}

TEST(FlutterWindowsViewTest, WindowResizeTests) {
std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
EngineModifier modifier(engine.get());

auto window_binding_handler =
std::make_unique<::testing::NiceMock<MockWindowBindingHandler>>();

FlutterWindowsView view(std::move(window_binding_handler));
view.SetEngine(std::move(engine));

bool send_window_metrics_event_called = false;
modifier.embedder_api().SendWindowMetricsEvent = MOCK_ENGINE_PROC(
SendWindowMetricsEvent,
([&send_window_metrics_event_called](
auto engine, const FlutterWindowMetricsEvent* even) {
send_window_metrics_event_called = true;
return kSuccess;
}));

std::promise<bool> resize_completed;
std::thread([&resize_completed, &view]() {
view.OnWindowSizeChanged(500, 500);
resize_completed.set_value(true);
}).detach();

auto result = resize_completed.get_future().wait_for(std::chrono::seconds(1));
EXPECT_EQ(std::future_status::ready, result);
EXPECT_TRUE(send_window_metrics_event_called);
}

} // namespace testing
} // namespace flutter