Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
a69e0f3
Create GLFBOInfo.
betrevisan Jul 30, 2022
a28f3a9
Update FlutterPresentInfo with frame and buffer damage
betrevisan Jul 30, 2022
030e54e
Update GLContextFBO prototype to return a GLFBOInfo.
betrevisan Jul 30, 2022
dde31a1
Update affected functions by updates to GLPresentInfo
betrevisan Jul 30, 2022
b035be5
Update the behavior of GL Skia to account for dirty region management.
betrevisan Jul 30, 2022
7f4bd47
Updated affected functions by the changes to the return value of GLCo…
betrevisan Jul 30, 2022
89b112c
Create FlutterDamage.
betrevisan Jul 30, 2022
10df5e3
Update FlutterPresentInfo fields.
betrevisan Jul 30, 2022
ab17275
Add new callback fbo_with_damage_callback.
betrevisan Jul 30, 2022
a30e016
Update dispatch table.
betrevisan Jul 30, 2022
e532950
Add check to make sure gl_fbo_with_damage_callback was passed.
betrevisan Jul 30, 2022
2b23637
Update GLContextPresent and GLContextFBO.
betrevisan Jul 30, 2022
de95990
Update open gl default renderer config for tests.
betrevisan Jul 30, 2022
98d2d6a
Add GetRendererConfig function.
betrevisan Jul 30, 2022
c6b8668
Update GLPresent used in tests.
betrevisan Jul 30, 2022
b50677d
Add fbo_with_damage_callback to tests.
betrevisan Jul 30, 2022
a865ab3
Add unittests to check valid fbo_with_damage callback.
betrevisan Jul 30, 2022
8f95371
Add unittests for partial repaint.
betrevisan Jul 30, 2022
8fd3a9d
Add unittest to make sure fbo with damage receives the correct inform…
betrevisan Jul 30, 2022
ae1481f
Add log message if the user did not define an fbo_with_damage callback.
betrevisan Jul 30, 2022
e6e1154
Add auxiliar functions.
betrevisan Jul 30, 2022
f4d5043
Update behavior of present callback within the embedder.
betrevisan Jul 30, 2022
c2ce2af
Update behavior of fbo with damage callback within the embedder.
betrevisan Jul 30, 2022
ef0cc25
Formatting.
betrevisan Jul 30, 2022
6a64daa
Update the fbo_with_damage_callback.
betrevisan Aug 1, 2022
931e53e
Documenting.
betrevisan Aug 1, 2022
3f97449
Update auxiliary functions as static functions.
betrevisan Aug 1, 2022
1092807
Force full repaint when the user tries to do partial repaint with mul…
betrevisan Aug 1, 2022
ecec224
Update construction of information passed to the present callback.
betrevisan Aug 1, 2022
c1be604
Fix static function warning.
betrevisan Aug 1, 2022
bde9b09
Fix static function error.
betrevisan Aug 1, 2022
104b7ca
Rename fbo_with_damage_callback to populate_existing_damage_callback.
betrevisan Aug 1, 2022
73434c3
Force full repaint when no existing damage rectangle was given
betrevisan Aug 4, 2022
0136a18
Update the callback name.
betrevisan Aug 12, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions shell/common/shell_test_platform_view_gl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,10 @@ bool ShellTestPlatformViewGL::GLContextPresent(
}

// |GPUSurfaceGLDelegate|
intptr_t ShellTestPlatformViewGL::GLContextFBO(GLFrameInfo frame_info) const {
return gl_surface_.GetFramebuffer(frame_info.width, frame_info.height);
GLFBOInfo ShellTestPlatformViewGL::GLContextFBO(GLFrameInfo frame_info) const {
return GLFBOInfo{
.fbo_id = gl_surface_.GetFramebuffer(frame_info.width, frame_info.height),
};
}

// |GPUSurfaceGLDelegate|
Expand Down
2 changes: 1 addition & 1 deletion shell/common/shell_test_platform_view_gl.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class ShellTestPlatformViewGL : public ShellTestPlatformView,
bool GLContextPresent(const GLPresentInfo& present_info) override;

// |GPUSurfaceGLDelegate|
intptr_t GLContextFBO(GLFrameInfo frame_info) const override;
GLFBOInfo GLContextFBO(GLFrameInfo frame_info) const override;

// |GPUSurfaceGLDelegate|
GLProcResolver GetGLProcResolver() const override;
Expand Down
26 changes: 21 additions & 5 deletions shell/gpu/gpu_surface_gl_delegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,32 @@ struct GLFrameInfo {
uint32_t height;
};

// A structure to represent the frame buffer information which is returned to
// the rendering backend after requesting a frame buffer object.
struct GLFBOInfo {
// The frame buffer's ID.
uint32_t fbo_id;
// This boolean flags whether the returned FBO supports partial repaint.
const bool partial_repaint_enabled;
// The frame buffer's existing damage (i.e. damage since it was last used).
const SkIRect existing_damage;
};

// Information passed during presentation of a frame.
struct GLPresentInfo {
uint32_t fbo_id;

// Damage is a hint to compositor telling it which parts of front buffer
// need to be updated
const std::optional<SkIRect>& damage;
// The frame damage is a hint to compositor telling it which parts of front
// buffer need to be updated.
const std::optional<SkIRect>& frame_damage;

// Time at which this frame is scheduled to be presented. This is a hint
// that can be passed to the platform to drop queued frames.
std::optional<fml::TimePoint> presentation_time = std::nullopt;

// The buffer damage refers to the region that needs to be set as damaged
// within the frame buffer.
const std::optional<SkIRect>& buffer_damage;
};

class GPUSurfaceGLDelegate {
Expand All @@ -54,8 +69,9 @@ class GPUSurfaceGLDelegate {
// context and not any of the contexts dedicated for IO.
virtual bool GLContextPresent(const GLPresentInfo& present_info) = 0;

// The ID of the main window bound framebuffer. Typically FBO0.
virtual intptr_t GLContextFBO(GLFrameInfo frame_info) const = 0;
// The information about the main window bound framebuffer. ID is Typically
// FBO0.
virtual GLFBOInfo GLContextFBO(GLFrameInfo frame_info) const = 0;

// The rendering subsystem assumes that the ID of the main window bound
// framebuffer remains constant throughout. If this assumption in incorrect,
Expand Down
3 changes: 2 additions & 1 deletion shell/gpu/gpu_surface_gl_impeller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,11 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceGLImpeller::AcquireFrame(
if (weak) {
GLPresentInfo present_info = {
.fbo_id = 0,
.damage = std::nullopt,
.frame_damage = std::nullopt,
// TODO (https://github.com/flutter/flutter/issues/105597): wire-up
// presentation time to impeller backend.
.presentation_time = std::nullopt,
.buffer_damage = std::nullopt,
};
delegate->GLContextPresent(present_info);
}
Expand Down
22 changes: 15 additions & 7 deletions shell/gpu/gpu_surface_gl_skia.cc
Original file line number Diff line number Diff line change
Expand Up @@ -181,10 +181,10 @@ bool GPUSurfaceGLSkia::CreateOrUpdateSurfaces(const SkISize& size) {

GLFrameInfo frame_info = {static_cast<uint32_t>(size.width()),
static_cast<uint32_t>(size.height())};
const uint32_t fbo_id = delegate_->GLContextFBO(frame_info);
const GLFBOInfo fbo_info = delegate_->GLContextFBO(frame_info);
onscreen_surface = WrapOnscreenSurface(context_.get(), // GL context
size, // root surface size
fbo_id // window FBO ID
fbo_info.fbo_id // window FBO ID
);

if (onscreen_surface == nullptr) {
Expand All @@ -195,7 +195,9 @@ bool GPUSurfaceGLSkia::CreateOrUpdateSurfaces(const SkISize& size) {
}

onscreen_surface_ = std::move(onscreen_surface);
fbo_id_ = fbo_id;
fbo_id_ = fbo_info.fbo_id;
supports_partial_repaint_ = fbo_info.partial_repaint_enabled;
existing_damage_ = fbo_info.existing_damage;

return true;
}
Expand Down Expand Up @@ -248,6 +250,9 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceGLSkia::AcquireFrame(
};

framebuffer_info = delegate_->GLContextFramebufferInfo();
// Partial repaint is enabled by default
framebuffer_info.supports_partial_repaint = supports_partial_repaint_;
framebuffer_info.existing_damage = existing_damage_;
return std::make_unique<SurfaceFrame>(surface, std::move(framebuffer_info),
submit_callback,
std::move(context_switch));
Expand All @@ -268,8 +273,9 @@ bool GPUSurfaceGLSkia::PresentSurface(const SurfaceFrame& frame,

GLPresentInfo present_info = {
.fbo_id = fbo_id_,
.damage = frame.submit_info().frame_damage,
.frame_damage = frame.submit_info().frame_damage,
.presentation_time = frame.submit_info().presentation_time,
.buffer_damage = frame.submit_info().buffer_damage,
};
if (!delegate_->GLContextPresent(present_info)) {
return false;
Expand All @@ -284,19 +290,21 @@ bool GPUSurfaceGLSkia::PresentSurface(const SurfaceFrame& frame,

// The FBO has changed, ask the delegate for the new FBO and do a surface
// re-wrap.
const uint32_t fbo_id = delegate_->GLContextFBO(frame_info);
const GLFBOInfo fbo_info = delegate_->GLContextFBO(frame_info);
auto new_onscreen_surface =
WrapOnscreenSurface(context_.get(), // GL context
current_size, // root surface size
fbo_id // window FBO ID
fbo_info.fbo_id // window FBO ID
);

if (!new_onscreen_surface) {
return false;
}

onscreen_surface_ = std::move(new_onscreen_surface);
fbo_id_ = fbo_id;
fbo_id_ = fbo_info.fbo_id;
supports_partial_repaint_ = fbo_info.partial_repaint_enabled;
existing_damage_ = fbo_info.existing_damage;
}

return true;
Expand Down
4 changes: 4 additions & 0 deletions shell/gpu/gpu_surface_gl_skia.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,17 @@ class GPUSurfaceGLSkia : public Surface {
sk_sp<SkSurface> onscreen_surface_;
/// FBO backing the current `onscreen_surface_`.
uint32_t fbo_id_ = 0;
// Private variable used to keep track of the current FBO's existing damage.
SkIRect existing_damage_ = SkIRect::MakeEmpty();
bool context_owner_ = false;
// TODO(38466): Refactor GPU surface APIs take into account the fact that an
// external view embedder may want to render to the root surface. This is a
// hack to make avoid allocating resources for the root surface when an
// external view embedder is present.
const bool render_to_surface_ = true;
bool valid_ = false;
// Partial repaint is on by default.
bool supports_partial_repaint_ = true;

// WeakPtrFactory must be the last member.
fml::TaskRunnerAffineWeakPtrFactory<GPUSurfaceGLSkia> weak_factory_;
Expand Down
6 changes: 4 additions & 2 deletions shell/platform/android/android_surface_gl_impeller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -295,9 +295,11 @@ bool AndroidSurfaceGLImpeller::GLContextPresent(
}

// |GPUSurfaceGLDelegate|
intptr_t AndroidSurfaceGLImpeller::GLContextFBO(GLFrameInfo frame_info) const {
GLFBOInfo AndroidSurfaceGLImpeller::GLContextFBO(GLFrameInfo frame_info) const {
// FBO0 is the default window bound framebuffer in EGL environments.
return 0;
return GLFBOInfo{
.fbo_id = 0,
};
}

// |GPUSurfaceGLDelegate|
Expand Down
2 changes: 1 addition & 1 deletion shell/platform/android/android_surface_gl_impeller.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class AndroidSurfaceGLImpeller final : public GPUSurfaceGLDelegate,
bool GLContextPresent(const GLPresentInfo& present_info) override;

// |GPUSurfaceGLDelegate|
intptr_t GLContextFBO(GLFrameInfo frame_info) const override;
GLFBOInfo GLContextFBO(GLFrameInfo frame_info) const override;

// |GPUSurfaceGLDelegate|
sk_sp<const GrGLInterface> GetGLInterface() const override;
Expand Down
8 changes: 5 additions & 3 deletions shell/platform/android/android_surface_gl_skia.cc
Original file line number Diff line number Diff line change
Expand Up @@ -159,13 +159,15 @@ bool AndroidSurfaceGLSkia::GLContextPresent(const GLPresentInfo& present_info) {
if (present_info.presentation_time) {
onscreen_surface_->SetPresentationTime(*present_info.presentation_time);
}
return onscreen_surface_->SwapBuffers(present_info.damage);
return onscreen_surface_->SwapBuffers(present_info.frame_damage);
}

intptr_t AndroidSurfaceGLSkia::GLContextFBO(GLFrameInfo frame_info) const {
GLFBOInfo AndroidSurfaceGLSkia::GLContextFBO(GLFrameInfo frame_info) const {
FML_DCHECK(IsValid());
// The default window bound framebuffer on Android.
return 0;
return GLFBOInfo{
.fbo_id = 0,
};
}

// |GPUSurfaceGLDelegate|
Expand Down
2 changes: 1 addition & 1 deletion shell/platform/android/android_surface_gl_skia.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class AndroidSurfaceGLSkia final : public GPUSurfaceGLDelegate,
bool GLContextPresent(const GLPresentInfo& present_info) override;

// |GPUSurfaceGLDelegate|
intptr_t GLContextFBO(GLFrameInfo frame_info) const override;
GLFBOInfo GLContextFBO(GLFrameInfo frame_info) const override;

// |GPUSurfaceGLDelegate|
sk_sp<const GrGLInterface> GetGLInterface() const override;
Expand Down
6 changes: 4 additions & 2 deletions shell/platform/android/surface/android_surface_mock.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ bool AndroidSurfaceMock::GLContextPresent(const GLPresentInfo& present_info) {
return true;
}

intptr_t AndroidSurfaceMock::GLContextFBO(GLFrameInfo frame_info) const {
return 0;
GLFBOInfo AndroidSurfaceMock::GLContextFBO(GLFrameInfo frame_info) const {
return GLFBOInfo{
.fbo_id = 0,
};
}

} // namespace flutter
2 changes: 1 addition & 1 deletion shell/platform/android/surface/android_surface_mock.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class AndroidSurfaceMock final : public GPUSurfaceGLDelegate,
bool GLContextPresent(const GLPresentInfo& present_info) override;

// |GPUSurfaceGLDelegate|
intptr_t GLContextFBO(GLFrameInfo frame_info) const override;
GLFBOInfo GLContextFBO(GLFrameInfo frame_info) const override;
};

} // namespace flutter
Expand Down
117 changes: 110 additions & 7 deletions shell/platform/embedder/embedder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,12 @@ static bool IsOpenGLRendererConfigValid(const FlutterRendererConfig* config) {
return false;
}

if (!SAFE_EXISTS(open_gl_config, populate_existing_damage)) {
FML_LOG(INFO) << "populate_existing_damage was not defined, disabling "
"partial repaint. If you wish to enable partial repaint, "
"please define this callback.";
}

return true;
}

Expand Down Expand Up @@ -222,7 +228,29 @@ static void* DefaultGLProcResolver(const char* name) {
}
#endif // FML_OS_LINUX || FML_OS_WIN

static flutter::Shell::CreateCallback<flutter::PlatformView>
#ifdef SHELL_ENABLE_GL
// Auxiliary function used to translate rectangles of type SkIRect to
// FlutterRect.
static FlutterRect SkIRectToFlutterRect(const SkIRect sk_rect) {
FlutterRect flutter_rect = {static_cast<double>(sk_rect.fLeft),
static_cast<double>(sk_rect.fTop),
static_cast<double>(sk_rect.fRight),
static_cast<double>(sk_rect.fBottom)};
return flutter_rect;
}

// Auxiliary function used to translate rectangles of type FlutterRect to
// SkIRect.
static const SkIRect FlutterRectToSkIRect(FlutterRect flutter_rect) {
SkIRect rect = {static_cast<int32_t>(flutter_rect.left),
static_cast<int32_t>(flutter_rect.top),
static_cast<int32_t>(flutter_rect.right),
static_cast<int32_t>(flutter_rect.bottom)};
return rect;
}
#endif

static inline flutter::Shell::CreateCallback<flutter::PlatformView>
InferOpenGLPlatformViewCreationCallback(
const FlutterRendererConfig* config,
void* user_data,
Expand All @@ -241,15 +269,45 @@ 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;
// Format the frame and buffer damages accordingly. Note that, since the
// current compute damage algorithm only returns one rectangle for damage
// we are assuming the number of rectangles provided in frame and buffer
// damage are always 1. Once the function that computes damage implements
// support for multiple damage rectangles, GLPresentInfo should also
// contain the number of damage rectangles.
const size_t num_rects = 1;

std::array<FlutterRect, num_rects> frame_damage_rect = {
SkIRectToFlutterRect(*(gl_present_info.frame_damage))};
std::array<FlutterRect, num_rects> buffer_damage_rect = {
SkIRectToFlutterRect(*(gl_present_info.buffer_damage))};

FlutterDamage frame_damage{
.struct_size = sizeof(FlutterDamage),
.num_rects = frame_damage_rect.size(),
.damage = frame_damage_rect.data(),
};
FlutterDamage buffer_damage{
.struct_size = sizeof(FlutterDamage),
.num_rects = buffer_damage_rect.size(),
.damage = buffer_damage_rect.data(),
};

// Construct the present information concerning the frame being rendered.
FlutterPresentInfo present_info = {
.struct_size = sizeof(FlutterPresentInfo),
.fbo_id = gl_present_info.fbo_id,
.frame_damage = frame_damage,
.buffer_damage = buffer_damage,
};

return present_with_info(user_data, &present_info);
}
};
Expand All @@ -269,6 +327,50 @@ InferOpenGLPlatformViewCreationCallback(
}
};

auto gl_populate_existing_damage =
[populate_existing_damage = config->open_gl.populate_existing_damage,
user_data](intptr_t id) -> flutter::GLFBOInfo {
// If no populate_existing_damage was provided, disable partial
// repaint.
if (!populate_existing_damage) {
return flutter::GLFBOInfo{
.fbo_id = static_cast<uint32_t>(id),
.partial_repaint_enabled = false,
.existing_damage = SkIRect::MakeEmpty(),
};
}

// Given the FBO's ID, get its existing damage.
FlutterDamage existing_damage;
populate_existing_damage(user_data, id, &existing_damage);

bool partial_repaint_enabled = true;
SkIRect existing_damage_rect;

// Verify that at least one damage rectangle was provided.
if (existing_damage.num_rects <= 0 || existing_damage.damage == nullptr) {
FML_LOG(INFO) << "No damage was provided. Forcing full repaint.";
existing_damage_rect = SkIRect::MakeEmpty();
partial_repaint_enabled = false;
} else if (existing_damage.num_rects > 1) {
// Log message notifying users that multi-damage is not yet available in
// case they try to make use of it.
FML_LOG(INFO) << "Damage with multiple rectangles not yet supported. "
"Repainting the whole frame.";
existing_damage_rect = SkIRect::MakeEmpty();
partial_repaint_enabled = false;
} else {
existing_damage_rect = FlutterRectToSkIRect(*(existing_damage.damage));
}

// Pass the information about this FBO to the rendering backend.
return flutter::GLFBOInfo{
.fbo_id = static_cast<uint32_t>(id),
.partial_repaint_enabled = partial_repaint_enabled,
.existing_damage = existing_damage_rect,
};
};

const FlutterOpenGLRendererConfig* open_gl_config = &config->open_gl;
std::function<bool()> gl_make_resource_current_callback = nullptr;
if (SAFE_ACCESS(open_gl_config, make_resource_current, nullptr) != nullptr) {
Expand Down Expand Up @@ -326,6 +428,7 @@ InferOpenGLPlatformViewCreationCallback(
gl_make_resource_current_callback, // gl_make_resource_current_callback
gl_surface_transformation_callback, // gl_surface_transformation_callback
gl_proc_resolver, // gl_proc_resolver
gl_populate_existing_damage, // gl_populate_existing_damage
};

return fml::MakeCopyable(
Expand Down
Loading