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

Commit dde3ebf

Browse files
authored
[Windows] Refactor logic when window resize completes (#49872)
Changes: 1. Moves surface buffer swapping from `FlutterWindowsView` to `CompositorOpenGL` 1. Renames `FlutterWindowsView::SwapBuffers` to `FlutterWindowsView::OnFramePresented` 2. Previously, if a resize was pending and the window was not visible Windows would unblock the platform thread before swapping buffers. This trick aimed to reduce the time the platform thread was blocked as swapping buffers previously waited until the v-blank. This logic was removed as swapping buffers no longer waits until the v-blank. [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
1 parent a7a02cc commit dde3ebf

12 files changed

+36
-76
lines changed

shell/platform/windows/angle_surface_manager.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ bool AngleSurfaceManager::MakeResourceCurrent() {
329329
egl_resource_context_) == EGL_TRUE);
330330
}
331331

332-
EGLBoolean AngleSurfaceManager::SwapBuffers() {
332+
bool AngleSurfaceManager::SwapBuffers() {
333333
return (eglSwapBuffers(egl_display_, render_surface_));
334334
}
335335

shell/platform/windows/angle_surface_manager.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ class AngleSurfaceManager {
7777

7878
// Swaps the front and back buffers of the DX11 swapchain backing surface if
7979
// not null.
80-
EGLBoolean SwapBuffers();
80+
virtual bool SwapBuffers();
8181

8282
// Creates a |EGLSurface| from the provided handle.
8383
EGLSurface CreateSurfaceFromHandle(EGLenum handle_type,

shell/platform/windows/compositor_opengl.cc

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,12 @@ bool CompositorOpenGL::Present(const FlutterLayer** layers,
154154
GL_NEAREST // filter
155155
);
156156

157-
return engine_->view()->SwapBuffers();
157+
if (!engine_->surface_manager()->SwapBuffers()) {
158+
return false;
159+
}
160+
161+
engine_->view()->OnFramePresented();
162+
return true;
158163
}
159164

160165
bool CompositorOpenGL::Initialize() {
@@ -188,7 +193,12 @@ bool CompositorOpenGL::ClearSurface() {
188193
gl_->ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
189194
gl_->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
190195

191-
return engine_->view()->SwapBuffers();
196+
if (!engine_->surface_manager()->SwapBuffers()) {
197+
return false;
198+
}
199+
200+
engine_->view()->OnFramePresented();
201+
return true;
192202
}
193203

194204
} // namespace flutter

shell/platform/windows/compositor_opengl_unittests.cc

Lines changed: 5 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "flutter/shell/platform/windows/flutter_windows_view.h"
1212
#include "flutter/shell/platform/windows/testing/engine_modifier.h"
1313
#include "flutter/shell/platform/windows/testing/flutter_windows_engine_builder.h"
14+
#include "flutter/shell/platform/windows/testing/mock_angle_surface_manager.h"
1415
#include "flutter/shell/platform/windows/testing/mock_window_binding_handler.h"
1516
#include "flutter/shell/platform/windows/testing/windows_test.h"
1617
#include "gmock/gmock.h"
@@ -56,36 +57,13 @@ const impeller::ProcTableGLES::Resolver kMockResolver = [](const char* name) {
5657
}
5758
};
5859

59-
class MockAngleSurfaceManager : public AngleSurfaceManager {
60-
public:
61-
MockAngleSurfaceManager() : AngleSurfaceManager(false) {}
62-
63-
MOCK_METHOD(bool, MakeCurrent, (), (override));
64-
65-
private:
66-
FML_DISALLOW_COPY_AND_ASSIGN(MockAngleSurfaceManager);
67-
};
68-
69-
class MockFlutterWindowsView : public FlutterWindowsView {
70-
public:
71-
MockFlutterWindowsView(std::unique_ptr<WindowBindingHandler> window)
72-
: FlutterWindowsView(std::move(window)) {}
73-
virtual ~MockFlutterWindowsView() = default;
74-
75-
MOCK_METHOD(bool, SwapBuffers, (), (override));
76-
77-
private:
78-
FML_DISALLOW_COPY_AND_ASSIGN(MockFlutterWindowsView);
79-
};
80-
8160
class CompositorOpenGLTest : public WindowsTest {
8261
public:
8362
CompositorOpenGLTest() = default;
8463
virtual ~CompositorOpenGLTest() = default;
8564

8665
protected:
8766
FlutterWindowsEngine* engine() { return engine_.get(); }
88-
MockFlutterWindowsView* view() { return view_.get(); }
8967
MockAngleSurfaceManager* surface_manager() { return surface_manager_; }
9068

9169
void UseHeadlessEngine() {
@@ -106,14 +84,14 @@ class CompositorOpenGLTest : public WindowsTest {
10684
EXPECT_CALL(*window.get(), SetView).Times(1);
10785
EXPECT_CALL(*window.get(), GetWindowHandle).WillRepeatedly(Return(nullptr));
10886

109-
view_ = std::make_unique<MockFlutterWindowsView>(std::move(window));
87+
view_ = std::make_unique<FlutterWindowsView>(std::move(window));
11088

11189
engine_->SetView(view_.get());
11290
}
11391

11492
private:
11593
std::unique_ptr<FlutterWindowsEngine> engine_;
116-
std::unique_ptr<MockFlutterWindowsView> view_;
94+
std::unique_ptr<FlutterWindowsView> view_;
11795
MockAngleSurfaceManager* surface_manager_;
11896

11997
FML_DISALLOW_COPY_AND_ASSIGN(CompositorOpenGLTest);
@@ -163,7 +141,7 @@ TEST_F(CompositorOpenGLTest, Present) {
163141
const FlutterLayer* layer_ptr = &layer;
164142

165143
EXPECT_CALL(*surface_manager(), MakeCurrent).WillOnce(Return(true));
166-
EXPECT_CALL(*view(), SwapBuffers).WillOnce(Return(true));
144+
EXPECT_CALL(*surface_manager(), SwapBuffers).WillOnce(Return(true));
167145
EXPECT_TRUE(compositor.Present(&layer_ptr, 1));
168146

169147
ASSERT_TRUE(compositor.CollectBackingStore(&backing_store));
@@ -179,7 +157,7 @@ TEST_F(CompositorOpenGLTest, PresentEmpty) {
179157
EXPECT_CALL(*surface_manager(), MakeCurrent)
180158
.Times(2)
181159
.WillRepeatedly(Return(true));
182-
EXPECT_CALL(*view(), SwapBuffers).WillOnce(Return(true));
160+
EXPECT_CALL(*surface_manager(), SwapBuffers).WillOnce(Return(true));
183161
EXPECT_TRUE(compositor.Present(nullptr, 0));
184162
}
185163

shell/platform/windows/flutter_window.cc

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,10 +168,6 @@ float FlutterWindow::GetDpiScale() {
168168
return static_cast<float>(GetCurrentDPI()) / static_cast<float>(base_dpi);
169169
}
170170

171-
bool FlutterWindow::IsVisible() {
172-
return IsWindowVisible(GetWindowHandle());
173-
}
174-
175171
PhysicalWindowBounds FlutterWindow::GetPhysicalWindowBounds() {
176172
return {GetCurrentWidth(), GetCurrentHeight()};
177173
}

shell/platform/windows/flutter_window.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,6 @@ class FlutterWindow : public KeyboardManager::WindowDelegate,
158158
// |FlutterWindowBindingHandler|
159159
virtual float GetDpiScale() override;
160160

161-
// |FlutterWindowBindingHandler|
162-
virtual bool IsVisible() override;
163-
164161
// |FlutterWindowBindingHandler|
165162
virtual PhysicalWindowBounds GetPhysicalWindowBounds() override;
166163

shell/platform/windows/flutter_window_unittests.cc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ class MockFlutterWindow : public FlutterWindow {
6666
MOCK_METHOD(void, OnSetCursor, (), (override));
6767
MOCK_METHOD(float, GetScrollOffsetMultiplier, (), (override));
6868
MOCK_METHOD(float, GetDpiScale, (), (override));
69-
MOCK_METHOD(bool, IsVisible, (), (override));
7069
MOCK_METHOD(void, UpdateCursorRect, (const Rect&), (override));
7170
MOCK_METHOD(void, OnResetImeComposing, (), (override));
7271
MOCK_METHOD(UINT, Win32DispatchMessage, (UINT, WPARAM, LPARAM), (override));

shell/platform/windows/flutter_windows_view.cc

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -590,42 +590,30 @@ void FlutterWindowsView::SendPointerEventWithData(
590590
}
591591
}
592592

593-
bool FlutterWindowsView::SwapBuffers() {
594-
// Called on an engine-controlled (non-platform) thread.
593+
void FlutterWindowsView::OnFramePresented() {
594+
// Called on the engine's raster thread.
595595
std::unique_lock<std::mutex> lock(resize_mutex_);
596596

597597
switch (resize_status_) {
598-
// SwapBuffer requests during resize are ignored until the frame with the
599-
// right dimensions has been generated. This is marked with
600-
// kFrameGenerated resize status.
601598
case ResizeState::kResizeStarted:
602-
return false;
599+
// The caller must first call |OnFrameGenerated| or
600+
// |OnEmptyFrameGenerated| before calling this method. This status
601+
// indicates the caller did not call these methods or ignored their
602+
// result.
603+
FML_UNREACHABLE();
603604
case ResizeState::kFrameGenerated: {
604-
bool visible = binding_handler_->IsVisible();
605-
bool swap_buffers_result;
606-
// For visible windows swap the buffers while resize handler is waiting.
607-
// For invisible windows unblock the handler first and then swap buffers.
608-
// SwapBuffers waits for vsync and there's no point doing that for
609-
// invisible windows.
610-
if (visible) {
611-
swap_buffers_result = engine_->surface_manager()->SwapBuffers();
612-
}
605+
// A frame was generated for a pending resize.
606+
// Unblock the platform thread.
613607
resize_status_ = ResizeState::kDone;
614608
lock.unlock();
615609
resize_cv_.notify_all();
616610

617611
// Blocking the raster thread until DWM flushes alleviates glitches where
618612
// previous size surface is stretched over current size view.
619613
windows_proc_table_->DwmFlush();
620-
621-
if (!visible) {
622-
swap_buffers_result = engine_->surface_manager()->SwapBuffers();
623-
}
624-
return swap_buffers_result;
625614
}
626615
case ResizeState::kDone:
627-
default:
628-
return engine_->surface_manager()->SwapBuffers();
616+
return;
629617
}
630618
}
631619

shell/platform/windows/flutter_windows_view.h

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,17 +62,6 @@ class FlutterWindowsView : public WindowBindingHandlerDelegate {
6262
// Tells the engine to generate a new frame
6363
void ForceRedraw();
6464

65-
// Swap the view's surface buffers. Must be called on the engine's raster
66-
// thread. Returns true if the buffers were swapped.
67-
//
68-
// |OnFrameGenerated| or |OnEmptyFrameGenerated| must be called before this
69-
// method.
70-
//
71-
// If the view is resizing, this returns false if the frame is not the target
72-
// size. Otherwise, it unblocks the platform thread and blocks the raster
73-
// thread until the v-blank.
74-
virtual bool SwapBuffers();
75-
7665
// Callback to clear a previously presented software bitmap.
7766
virtual bool ClearSoftwareBitmap();
7867

@@ -103,6 +92,11 @@ class FlutterWindowsView : public WindowBindingHandlerDelegate {
10392
// |height| match the target size.
10493
bool OnFrameGenerated(size_t width, size_t height);
10594

95+
// Called on the raster thread after |CompositorOpenGL| presents a frame.
96+
//
97+
// This completes a view resize if one is pending.
98+
virtual void OnFramePresented();
99+
106100
// Sets the cursor that should be used when the mouse is over the Flutter
107101
// content. See mouse_cursor.dart for the values and meanings of cursor_name.
108102
void UpdateFlutterCursor(const std::string& cursor_name);

shell/platform/windows/testing/mock_angle_surface_manager.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ class MockAngleSurfaceManager : public AngleSurfaceManager {
2525
MOCK_METHOD(bool, ClearCurrent, (), (override));
2626
MOCK_METHOD(void, SetVSyncEnabled, (bool), (override));
2727

28+
MOCK_METHOD(bool, SwapBuffers, (), (override));
29+
2830
private:
2931
FML_DISALLOW_COPY_AND_ASSIGN(MockAngleSurfaceManager);
3032
};

0 commit comments

Comments
 (0)