diff --git a/Reload b/Reload new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/examples/glfw/FlutterEmbedderGLFW.cc b/examples/glfw/FlutterEmbedderGLFW.cc index 8b17b25958fc1..a3d3c5ab8e676 100644 --- a/examples/glfw/FlutterEmbedderGLFW.cc +++ b/examples/glfw/FlutterEmbedderGLFW.cc @@ -96,8 +96,16 @@ bool RunFlutter(GLFWwindow* window, glfwMakeContextCurrent(nullptr); // is this even a thing? return true; }; - config.open_gl.present = [](void* userdata) -> bool { - glfwSwapBuffers(static_cast(userdata)); + config.open_gl.present_with_info = [](void* userdata, FlutterPresentInfo* present_info) -> bool { + // Check if damage exists + if (present_info->fbo_damage.empty()) { + // Render only damaged regions + // TODO(btrevisan): verify extensions. + eglSwapBuffersWithDamageKHR(static_cast(userdata), present_info->fbo_damage); + } else { + // Otherwise, render the entire screen + glfwSwapBuffers(static_cast(userdata)); + } return true; }; config.open_gl.fbo_callback = [](void*) -> uint32_t { diff --git a/shell/gpu/gpu_surface_gl_delegate.cc b/shell/gpu/gpu_surface_gl_delegate.cc index 2aea45cf21d52..d4640a9b52b96 100644 --- a/shell/gpu/gpu_surface_gl_delegate.cc +++ b/shell/gpu/gpu_surface_gl_delegate.cc @@ -20,6 +20,12 @@ SurfaceFrame::FramebufferInfo GPUSurfaceGLDelegate::GLContextFramebufferInfo() const { SurfaceFrame::FramebufferInfo res; res.supports_readback = true; + // By default, partial repaint is enabled for every frame. + // TODO(btrevisan): Implement deactivation of partial repaint in cases that + // do not benefit from it (e.g. when damage takes over most of the frame). + res.supports_partial_repaint = true; + // TODO(btrevisan): make sure that when there is existing damage, it is set. + res.existing_damage = SkIRect::MakeEmpty(); return res; } diff --git a/shell/gpu/gpu_surface_gl_skia.cc b/shell/gpu/gpu_surface_gl_skia.cc index 66bb6636d95d8..ba530007c9af7 100644 --- a/shell/gpu/gpu_surface_gl_skia.cc +++ b/shell/gpu/gpu_surface_gl_skia.cc @@ -248,6 +248,10 @@ std::unique_ptr GPUSurfaceGLSkia::AcquireFrame( }; framebuffer_info = delegate_->GLContextFramebufferInfo(); + // CHECK IF PARTIAL REPAINT IS ENABLED + // CALCULATE ACCUMULATED DAMAGE (I.E. ARE IN CURRENT FBO THAT LAGS BEHIND FRONT BUFFER) + // SET ACCUMULATED DAMAGE TO FBO_INFO EXISTING_DAMAGE + // SET SUPPORTS_PARTIAL_REPAINT TO TRUE return std::make_unique(surface, std::move(framebuffer_info), submit_callback, std::move(context_switch)); diff --git a/shell/platform/embedder/embedder.cc b/shell/platform/embedder/embedder.cc index 9d606cfbbb1ea..6e23d3c488d69 100644 --- a/shell/platform/embedder/embedder.cc +++ b/shell/platform/embedder/embedder.cc @@ -240,15 +240,25 @@ InferOpenGLPlatformViewCreationCallback( auto gl_clear_current = [ptr = config->open_gl.clear_current, user_data]() -> bool { return ptr(user_data); }; - auto gl_present = [present = config->open_gl.present, - present_with_info = config->open_gl.present_with_info, - user_data](uint32_t fbo_id) -> bool { + auto gl_present = + [present = config->open_gl.present, + present_with_info = config->open_gl.present_with_info, + user_data](flutter::GLPresentInfo gl_present_info) -> bool { if (present) { return present(user_data); } else { FlutterPresentInfo present_info = {}; present_info.struct_size = sizeof(FlutterPresentInfo); - present_info.fbo_id = fbo_id; + present_info.fbo_id = gl_present_info.fbo_id; + + FlutterDamage fbo_damage = {}; + fbo_damage.struct_size = sizeof(FlutterDamage); + fbo_damage.damage = std::vector{ + FlutterRect{static_cast(gl_present_info.damage->fLeft), + static_cast(gl_present_info.damage->fRight), + static_cast(gl_present_info.damage->fTop), + static_cast(gl_present_info.damage->fBottom)}}; + present_info.fbo_damage = fbo_damage; return present_with_info(user_data, &present_info); } }; diff --git a/shell/platform/embedder/embedder.h b/shell/platform/embedder/embedder.h index 66a25c7f30c5b..daadc0cc80591 100644 --- a/shell/platform/embedder/embedder.h +++ b/shell/platform/embedder/embedder.h @@ -8,6 +8,7 @@ #include #include #include +#include // This file defines an Application Binary Interface (ABI), which requires more // stability than regular code to remain functional for exchanging messages @@ -377,6 +378,14 @@ typedef struct { FlutterSize lower_left_corner_radius; } FlutterRoundedRect; +/// A strucutre to represent damage as rectangles. +typedef struct { + /// The size of this struct. Must be sizeof(FlutterDamage). + size_t struct_size; + // Vector of rectangles representing the areas that need to be repainted. + std::vector damage; +} FlutterDamage; + /// This information is passed to the embedder when requesting a frame buffer /// object. /// @@ -401,6 +410,8 @@ typedef struct { size_t struct_size; /// Id of the fbo backing the surface that was presented. uint32_t fbo_id; + // A vector of rectangles representing the areas that need to be repainted. + FlutterDamage fbo_damage; } FlutterPresentInfo; /// Callback for when a surface is presented. diff --git a/shell/platform/embedder/embedder_surface_gl.cc b/shell/platform/embedder/embedder_surface_gl.cc index e406ee9ed10fa..b4eae40ce8f9d 100644 --- a/shell/platform/embedder/embedder_surface_gl.cc +++ b/shell/platform/embedder/embedder_surface_gl.cc @@ -24,6 +24,11 @@ EmbedderSurfaceGL::EmbedderSurfaceGL( } valid_ = true; + + // if (HasExtension(extensions, "EGL_KHR_partial_update")) { + // set_damage_region_ = reinterpret_cast( + // eglGetProcAddress("eglSetDamageRegionKHR")); + // } } EmbedderSurfaceGL::~EmbedderSurfaceGL() = default; @@ -46,7 +51,7 @@ bool EmbedderSurfaceGL::GLContextClearCurrent() { // |GPUSurfaceGLDelegate| bool EmbedderSurfaceGL::GLContextPresent(const GLPresentInfo& present_info) { - return gl_dispatch_table_.gl_present_callback(present_info.fbo_id); + return gl_dispatch_table_.gl_present_callback(present_info); } // |GPUSurfaceGLDelegate| @@ -59,6 +64,16 @@ bool EmbedderSurfaceGL::GLContextFBOResetAfterPresent() const { return fbo_reset_after_present_; } +// |GPUSurfaceGLDelegate| +void EmbedderSurfaceGL::GLContextSetDamageRegion( + const std::optional& region) { + // TODO(btrevisan): add checks. + FML_DCHECK(IsValid()); + + // The region given here is the buffer damage. + // onscreen_surface_->SetDamageRegion(region); +} + // |GPUSurfaceGLDelegate| SkMatrix EmbedderSurfaceGL::GLContextSurfaceTransformation() const { auto callback = gl_dispatch_table_.gl_surface_transformation_callback; diff --git a/shell/platform/embedder/embedder_surface_gl.h b/shell/platform/embedder/embedder_surface_gl.h index c0a2b6a55d98f..6c7d19eba7767 100644 --- a/shell/platform/embedder/embedder_surface_gl.h +++ b/shell/platform/embedder/embedder_surface_gl.h @@ -18,7 +18,7 @@ class EmbedderSurfaceGL final : public EmbedderSurface, struct GLDispatchTable { std::function gl_make_current_callback; // required std::function gl_clear_current_callback; // required - std::function gl_present_callback; // required + std::function gl_present_callback; // required std::function gl_fbo_callback; // required std::function gl_make_resource_current_callback; // optional std::function @@ -37,6 +37,7 @@ class EmbedderSurfaceGL final : public EmbedderSurface, bool valid_ = false; GLDispatchTable gl_dispatch_table_; bool fbo_reset_after_present_; + // auto set_damage_region_ = nullptr; std::shared_ptr external_view_embedder_; @@ -64,6 +65,9 @@ class EmbedderSurfaceGL final : public EmbedderSurface, // |GPUSurfaceGLDelegate| bool GLContextFBOResetAfterPresent() const override; + // |GPUSurfaceGLDelegate| + void GLContextSetDamageRegion(const std::optional& region) override; + // |GPUSurfaceGLDelegate| SkMatrix GLContextSurfaceTransformation() const override;