diff --git a/engine/src/flutter/shell/platform/windows/angle_surface_manager.cc b/engine/src/flutter/shell/platform/windows/angle_surface_manager.cc index cc046281e81..eda082c7c86 100644 --- a/engine/src/flutter/shell/platform/windows/angle_surface_manager.cc +++ b/engine/src/flutter/shell/platform/windows/angle_surface_manager.cc @@ -169,14 +169,22 @@ void AngleSurfaceManager::CleanUp() { } } -bool AngleSurfaceManager::CreateSurface(WindowsRenderTarget* render_target) { +bool AngleSurfaceManager::CreateSurface(WindowsRenderTarget* render_target, + EGLint width, + EGLint height) { if (!render_target || !initialize_succeeded_) { return false; } EGLSurface surface = EGL_NO_SURFACE; - const EGLint surfaceAttributes[] = {EGL_NONE}; + // Disable Angle's automatic surface sizing logic and provide and exlicit + // size. AngleSurfaceManager is responsible for initiating Angle surface size + // changes to avoid race conditions with rendering when automatic mode is + // used. + const EGLint surfaceAttributes[] = { + EGL_FIXED_SIZE_ANGLE, EGL_TRUE, EGL_WIDTH, width, + EGL_HEIGHT, height, EGL_NONE}; surface = eglCreateWindowSurface( egl_display_, egl_config_, @@ -190,6 +198,26 @@ bool AngleSurfaceManager::CreateSurface(WindowsRenderTarget* render_target) { return true; } +void AngleSurfaceManager::ResizeSurface(WindowsRenderTarget* render_target, + EGLint width, + EGLint height) { + EGLint existing_width, existing_height; + GetSurfaceDimensions(&existing_width, &existing_height); + if (width != existing_width || height != existing_height) { + // Destroy existing surface with previous stale dimensions and create new + // surface at new size. Since the Windows compositor retains the front + // buffer until the new surface has been presented, no need to manually + // preserve the previous surface contents. This resize approach could be + // further optimized if Angle exposed a public entrypoint for + // SwapChain11::reset or SwapChain11::resize. + DestroySurface(); + if (!CreateSurface(render_target, width, height)) { + std::cerr << "AngleSurfaceManager::ResizeSurface failed to create surface" + << std::endl; + } + } +} + void AngleSurfaceManager::GetSurfaceDimensions(EGLint* width, EGLint* height) { if (render_surface_ == EGL_NO_SURFACE || !initialize_succeeded_) { width = 0; diff --git a/engine/src/flutter/shell/platform/windows/angle_surface_manager.h b/engine/src/flutter/shell/platform/windows/angle_surface_manager.h index a6a5fc213c3..60754c37cc5 100644 --- a/engine/src/flutter/shell/platform/windows/angle_surface_manager.h +++ b/engine/src/flutter/shell/platform/windows/angle_surface_manager.h @@ -23,6 +23,8 @@ namespace flutter { // destroy surfaces class AngleSurfaceManager { public: + // Creates a new surface manager retaining reference to the passed-in target + // for the lifetime of the manager. AngleSurfaceManager(); ~AngleSurfaceManager(); @@ -32,8 +34,19 @@ class AngleSurfaceManager { // Creates an EGLSurface wrapper and backing DirectX 11 SwapChain // asociated with window, in the appropriate format for display. - // Target represents the visual entity to bind to. - bool CreateSurface(WindowsRenderTarget* render_target); + // Target represents the visual entity to bind to. Width and + // height represent dimensions surface is created at. + bool CreateSurface(WindowsRenderTarget* render_target, + EGLint width, + EGLint height); + + // Resizes backing surface from current size to newly requested size + // based on width and height for the specific case when width and height do + // not match current surface dimensions. Target represents the visual entity + // to bind to. + void ResizeSurface(WindowsRenderTarget* render_target, + EGLint width, + EGLint height); // queries EGL for the dimensions of surface in physical // pixels returning width and height as out params. diff --git a/engine/src/flutter/shell/platform/windows/flutter_windows.cc b/engine/src/flutter/shell/platform/windows/flutter_windows.cc index f35a4c163ea..1e997da80d6 100644 --- a/engine/src/flutter/shell/platform/windows/flutter_windows.cc +++ b/engine/src/flutter/shell/platform/windows/flutter_windows.cc @@ -65,6 +65,9 @@ FlutterDesktopViewControllerRef FlutterDesktopViewControllerCreate( return nullptr; } } + + // Must happen after engine is running. + state->view->SendInitialBounds(); return state.release(); } diff --git a/engine/src/flutter/shell/platform/windows/flutter_windows_view.cc b/engine/src/flutter/shell/platform/windows/flutter_windows_view.cc index 9c463c367b9..5736ce988f5 100644 --- a/engine/src/flutter/shell/platform/windows/flutter_windows_view.cc +++ b/engine/src/flutter/shell/platform/windows/flutter_windows_view.cc @@ -52,6 +52,7 @@ void FlutterWindowsView::SetEngine( void FlutterWindowsView::OnWindowSizeChanged(size_t width, size_t height) const { + surface_manager_->ResizeSurface(GetRenderTarget(), width, height); SendWindowMetrics(width, height, binding_handler_->GetDpiScale()); } @@ -127,6 +128,13 @@ void FlutterWindowsView::SendWindowMetrics(size_t width, auto result = FlutterEngineSendWindowMetricsEvent(engine_->engine(), &event); } +void FlutterWindowsView::SendInitialBounds() { + PhysicalWindowBounds bounds = binding_handler_->GetPhysicalWindowBounds(); + + SendWindowMetrics(bounds.width, bounds.height, + binding_handler_->GetDpiScale()); +} + // Set's |event_data|'s phase to either kMove or kHover depending on the current // primary mouse button state. void FlutterWindowsView::SetEventPhaseFromCursorButtonState( @@ -263,7 +271,9 @@ bool FlutterWindowsView::SwapBuffers() { } void FlutterWindowsView::CreateRenderSurface() { - surface_manager_->CreateSurface(render_target_.get()); + PhysicalWindowBounds bounds = binding_handler_->GetPhysicalWindowBounds(); + surface_manager_->CreateSurface(GetRenderTarget(), bounds.width, + bounds.height); } void FlutterWindowsView::DestroyRenderSurface() { @@ -272,7 +282,7 @@ void FlutterWindowsView::DestroyRenderSurface() { } } -WindowsRenderTarget* FlutterWindowsView::GetRenderTarget() { +WindowsRenderTarget* FlutterWindowsView::GetRenderTarget() const { return render_target_.get(); } diff --git a/engine/src/flutter/shell/platform/windows/flutter_windows_view.h b/engine/src/flutter/shell/platform/windows/flutter_windows_view.h index 13ff056f67f..5df86e47629 100644 --- a/engine/src/flutter/shell/platform/windows/flutter_windows_view.h +++ b/engine/src/flutter/shell/platform/windows/flutter_windows_view.h @@ -52,7 +52,7 @@ class FlutterWindowsView : public WindowBindingHandlerDelegate { void DestroyRenderSurface(); // Return the currently configured WindowsRenderTarget. - WindowsRenderTarget* GetRenderTarget(); + WindowsRenderTarget* GetRenderTarget() const; // Returns the engine backing this view. FlutterWindowsEngine* GetEngine(); @@ -63,6 +63,9 @@ class FlutterWindowsView : public WindowBindingHandlerDelegate { bool MakeResourceCurrent(); bool SwapBuffers(); + // Send initial bounds to embedder. Must occur after engine has initialized. + void SendInitialBounds(); + // |WindowBindingHandlerDelegate| void OnWindowSizeChanged(size_t width, size_t height) const override;