Fix flutter#40068 Redraw issues on resize/minimize/maximize on Windows and startup in release (flutter/engine#20357)

* Fix redraw issues

* Address CR feedback.

* Fix build

* CR feedback
This commit is contained in:
James Clarke 2020-08-19 16:19:09 -07:00 committed by GitHub
parent 1b949f741f
commit a1d268a61b
5 changed files with 64 additions and 7 deletions

View File

@ -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;

View File

@ -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.

View File

@ -65,6 +65,9 @@ FlutterDesktopViewControllerRef FlutterDesktopViewControllerCreate(
return nullptr;
}
}
// Must happen after engine is running.
state->view->SendInitialBounds();
return state.release();
}

View File

@ -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();
}

View File

@ -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;