diff --git a/shell/gpu/gpu_surface_gl.cc b/shell/gpu/gpu_surface_gl.cc index 5d2ef8d4deec5..bb2350b8ee327 100644 --- a/shell/gpu/gpu_surface_gl.cc +++ b/shell/gpu/gpu_surface_gl.cc @@ -234,7 +234,25 @@ bool GPUSurfaceGL::PresentSurface(SkCanvas* canvas) { onscreen_surface_->getCanvas()->flush(); } - delegate_->GLContextPresent(); + if (!delegate_->GLContextPresent()) { + return false; + } + + if (delegate_->GLContextFBOResetAfterPresent()) { + auto current_size = + SkISize::Make(onscreen_surface_->width(), onscreen_surface_->height()); + + // The FBO has changed, ask the delegate for the new FBO and do a surface + // re-wrap. + auto new_onscreen_surface = WrapOnscreenSurface( + context_.get(), current_size, delegate_->GLContextFBO()); + + if (!new_onscreen_surface) { + return false; + } + + onscreen_surface_ = std::move(new_onscreen_surface); + } return true; } diff --git a/shell/gpu/gpu_surface_gl.h b/shell/gpu/gpu_surface_gl.h index aa1cfd3cd590e..0eb42dcaeab4c 100644 --- a/shell/gpu/gpu_surface_gl.h +++ b/shell/gpu/gpu_surface_gl.h @@ -22,6 +22,8 @@ class GPUSurfaceGLDelegate { virtual intptr_t GLContextFBO() const = 0; + virtual bool GLContextFBOResetAfterPresent() const { return false; } + virtual bool UseOffscreenSurface() const { return false; } }; diff --git a/shell/platform/embedder/embedder.cc b/shell/platform/embedder/embedder.cc index c1fb53fab0603..553350931d50b 100644 --- a/shell/platform/embedder/embedder.cc +++ b/shell/platform/embedder/embedder.cc @@ -128,6 +128,9 @@ FlutterResult FlutterEngineRun(size_t version, user_data]() { return ptr(user_data); }; } + bool fbo_reset_after_present = + SAFE_ACCESS(open_gl_config, fbo_reset_after_present, false); + std::string icu_data_path; if (SAFE_ACCESS(args, icu_data_path, nullptr) != nullptr) { icu_data_path = SAFE_ACCESS(args, icu_data_path, nullptr); @@ -194,11 +197,12 @@ FlutterResult FlutterEngineRun(size_t version, }; shell::Shell::CreateCallback on_create_platform_view = - [dispatch_table](shell::Shell& shell) { + [dispatch_table, fbo_reset_after_present](shell::Shell& shell) { return std::make_unique( shell, // delegate shell.GetTaskRunners(), // task runners - dispatch_table // embedder dispatch table + dispatch_table, // embedder dispatch table + fbo_reset_after_present // fbo reset after present ); }; diff --git a/shell/platform/embedder/embedder.h b/shell/platform/embedder/embedder.h index a4c6d7fa39ea0..fa5bb7ba3934e 100644 --- a/shell/platform/embedder/embedder.h +++ b/shell/platform/embedder/embedder.h @@ -42,6 +42,11 @@ typedef struct { BoolCallback present; UIntCallback fbo_callback; BoolCallback make_resource_current; + // By default, the renderer config assumes that the FBO does not change for + // the duration of the engine run. If this argument is true, the + // engine will ask the embedder for an updated FBO target (via an fbo_callback + // invocation) after a present call. + bool fbo_reset_after_present; } FlutterOpenGLRendererConfig; typedef struct { diff --git a/shell/platform/embedder/platform_view_embedder.cc b/shell/platform/embedder/platform_view_embedder.cc index 51012f3460b1e..a4dea939df97c 100644 --- a/shell/platform/embedder/platform_view_embedder.cc +++ b/shell/platform/embedder/platform_view_embedder.cc @@ -10,28 +10,39 @@ namespace shell { PlatformViewEmbedder::PlatformViewEmbedder(PlatformView::Delegate& delegate, blink::TaskRunners task_runners, - DispatchTable dispatch_table) + DispatchTable dispatch_table, + bool fbo_reset_after_present) : PlatformView(delegate, std::move(task_runners)), - dispatch_table_(dispatch_table) {} + dispatch_table_(dispatch_table), + fbo_reset_after_present_(fbo_reset_after_present) {} PlatformViewEmbedder::~PlatformViewEmbedder() = default; +// |shell::GPUSurfaceGLDelegate| bool PlatformViewEmbedder::GLContextMakeCurrent() { return dispatch_table_.gl_make_current_callback(); } +// |shell::GPUSurfaceGLDelegate| bool PlatformViewEmbedder::GLContextClearCurrent() { return dispatch_table_.gl_clear_current_callback(); } +// |shell::GPUSurfaceGLDelegate| bool PlatformViewEmbedder::GLContextPresent() { return dispatch_table_.gl_present_callback(); } +// |shell::GPUSurfaceGLDelegate| intptr_t PlatformViewEmbedder::GLContextFBO() const { return dispatch_table_.gl_fbo_callback(); } +// |shell::GPUSurfaceGLDelegate| +bool PlatformViewEmbedder::GLContextFBOResetAfterPresent() const { + return fbo_reset_after_present_; +} + void PlatformViewEmbedder::HandlePlatformMessage( fml::RefPtr message) { if (!message) { diff --git a/shell/platform/embedder/platform_view_embedder.h b/shell/platform/embedder/platform_view_embedder.h index ecc0b3d977887..ae1b19787bbdd 100644 --- a/shell/platform/embedder/platform_view_embedder.h +++ b/shell/platform/embedder/platform_view_embedder.h @@ -29,7 +29,8 @@ class PlatformViewEmbedder final : public PlatformView, PlatformViewEmbedder(PlatformView::Delegate& delegate, blink::TaskRunners task_runners, - DispatchTable dispatch_table); + DispatchTable dispatch_table, + bool fbo_reset_after_present); ~PlatformViewEmbedder() override; @@ -45,12 +46,16 @@ class PlatformViewEmbedder final : public PlatformView, // |shell::GPUSurfaceGLDelegate| intptr_t GLContextFBO() const override; + // |shell::GPUSurfaceGLDelegate| + bool GLContextFBOResetAfterPresent() const override; + // |shell::PlatformView| void HandlePlatformMessage( fml::RefPtr message) override; private: DispatchTable dispatch_table_; + bool fbo_reset_after_present_; // |shell::PlatformView| std::unique_ptr CreateRenderingSurface() override;