Skip to content

Commit

Permalink
WebView setFrameContentVelocity integration
Browse files Browse the repository at this point in the history
To be conservative, compute the change in scroll offset before and after
a begin frame, which can be done on the UI thread since begin frame is
synchronous. This covers touch scroll, fling, and and any css scroll
animations.

Limitations is this only covers root scroll, and does not cover things
like js scroll or java scroll. These cases it's not possible to
distinguish between scroll vs a jump.

Use delta between frame time since it's the only reliable source of
current frame rate and is the time stamp used for animations.

Bug: 346732738
Change-Id: I60c30b77235802a7b194b6edbaa9d3f509e8086a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5741874
Commit-Queue: Bo Liu <boliu@chromium.org>
Reviewed-by: Vasiliy Telezhnikov <vasilyt@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1333006}
  • Loading branch information
Bo Liu authored and pull[bot] committed Jul 26, 2024
1 parent c008050 commit 1270133
Show file tree
Hide file tree
Showing 15 changed files with 83 additions and 2 deletions.
4 changes: 4 additions & 0 deletions android_webview/browser/aw_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1098,6 +1098,10 @@ bool AwContents::OnDraw(JNIEnv* env,
return browser_view_renderer_.OnDrawSoftware(canvas_holder->GetCanvas());
}

jfloat AwContents::GetVelocityInPixelsPerSecond(JNIEnv* env) {
return browser_view_renderer_.GetVelocityInPixelsPerSecond();
}

bool AwContents::NeedToDrawBackgroundColor(JNIEnv* env) {
return browser_view_renderer_.NeedToDrawBackgroundColor();
}
Expand Down
1 change: 1 addition & 0 deletions android_webview/browser/aw_contents.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ class AwContents : public FindHelper::Listener,
jint visible_right,
jint visible_bottom,
jboolean force_auxiliary_bitmap_rendering);
jfloat GetVelocityInPixelsPerSecond(JNIEnv* env);
bool NeedToDrawBackgroundColor(JNIEnv* env);
jlong CapturePicture(JNIEnv* env, int width, int height);
void EnableOnNewPicture(JNIEnv* env, jboolean enabled);
Expand Down
1 change: 1 addition & 0 deletions android_webview/browser/aw_feature_map.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const base::Feature* const kFeaturesExposedToJava[] = {
&features::kWebViewDisplayCutout,
&features::kWebViewDragDropFiles,
&features::kWebViewExitReasonMetric,
&features::kWebViewFrameRateHints,
&features::kWebViewInvokeZoomPickerOnGSU,
&features::kWebViewMixedContentAutoupgrades,
&features::kWebViewTestFeature,
Expand Down
7 changes: 7 additions & 0 deletions android_webview/browser/gfx/browser_view_renderer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,13 @@ bool BrowserViewRenderer::OnDrawSoftware(SkCanvas* canvas) {
return CanOnDraw() && CompositeSW(canvas, /*software_canvas=*/true);
}

float BrowserViewRenderer::GetVelocityInPixelsPerSecond() {
if (!compositor_) {
return 0.f;
}
return compositor_->GetVelocityInPixelsPerSecond();
}

bool BrowserViewRenderer::NeedToDrawBackgroundColor() {
return !has_rendered_frame_;
}
Expand Down
2 changes: 2 additions & 0 deletions android_webview/browser/gfx/browser_view_renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ class BrowserViewRenderer : public content::SynchronousCompositorClient,
bool OnDrawHardware();
bool OnDrawSoftware(SkCanvas* canvas);

float GetVelocityInPixelsPerSecond();

bool NeedToDrawBackgroundColor();

// CapturePicture API methods.
Expand Down
5 changes: 5 additions & 0 deletions android_webview/common/aw_features.cc
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ BASE_FEATURE(kWebViewForceDarkModeMatchTheme,
"WebViewForceDarkModeMatchTheme",
base::FEATURE_DISABLED_BY_DEFAULT);

// Enable WebView providing frame rate hints to View system.
BASE_FEATURE(kWebViewFrameRateHints,
"WebViewFrameRateHints",
base::FEATURE_DISABLED_BY_DEFAULT);

BASE_FEATURE(kWebViewHitTestInBlinkOnTouchStart,
"WebViewHitTestInBlinkOnTouchStart",
base::FEATURE_ENABLED_BY_DEFAULT);
Expand Down
1 change: 1 addition & 0 deletions android_webview/common/aw_features.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ BASE_DECLARE_FEATURE(kWebViewEnumerateDevicesCache);
BASE_DECLARE_FEATURE(kWebViewExitReasonMetric);
BASE_DECLARE_FEATURE(kWebViewExtraHeadersSameOriginOnly);
BASE_DECLARE_FEATURE(kWebViewForceDarkModeMatchTheme);
BASE_DECLARE_FEATURE(kWebViewFrameRateHints);
BASE_DECLARE_FEATURE(kWebViewHitTestInBlinkOnTouchStart);
BASE_DECLARE_FEATURE(kWebViewImageDrag);
BASE_DECLARE_FEATURE(kWebViewInvokeZoomPickerOnGSU);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4575,6 +4575,13 @@ public void onDraw(Canvas canvas) {
setFunctor(newFunctor);
}

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM
&& AwFeatureMap.isEnabled(AwFeatures.WEBVIEW_FRAME_RATE_HINTS)) {
float velocity =
AwContentsJni.get().getVelocityInPixelsPerSecond(mNativeAwContents);
mContainerView.setFrameContentVelocity(velocity);
}

mScrollOffsetManager.syncScrollOffsetFromOnDraw();
int scrollX = mContainerView.getScrollX();
int scrollY = mContainerView.getScrollY();
Expand Down Expand Up @@ -5035,6 +5042,8 @@ boolean onDraw(
int visibleBottom,
boolean forceAuxiliaryBitmapRendering);

float getVelocityInPixelsPerSecond(long nativeAwContents);

boolean needToDrawBackgroundColor(long nativeAwContents);

void findAllAsync(long nativeAwContents, String searchString);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,9 @@ private ProductionSupportedFlagList() {}
AwFeatures.WEBVIEW_FORCE_DARK_MODE_MATCH_THEME,
"Automatically darken page if"
+ " WebView is set to FORCE_DARK_AUTO and the app has dark theme"),
Flag.baseFeature(
AwFeatures.WEBVIEW_FRAME_RATE_HINTS,
"Provide frame rate hints to View system if supported by OS"),
Flag.baseFeature(
ContentFeatures.VERIFY_DID_COMMIT_PARAMS,
"Enables reporting of browser and renderer navigation inconsistencies on"
Expand Down
32 changes: 32 additions & 0 deletions content/browser/android/synchronous_compositor_host.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <algorithm>
#include <atomic>
#include <cmath>
#include <memory>
#include <utility>

Expand Down Expand Up @@ -216,6 +217,7 @@ SynchronousCompositorHost::DemandDrawHwAsync(
const gfx::Size& viewport_size,
const gfx::Rect& viewport_rect_for_tile_priority,
const gfx::Transform& transform_for_tile_priority) {
velocity_in_pixels_per_second_ = 0.f;
draw_hw_called_ = true;
invalidate_needs_draw_ = false;
num_invalidates_since_last_draw_ = 0u;
Expand Down Expand Up @@ -386,6 +388,7 @@ struct SynchronousCompositorHost::SharedMemoryWithSize {

bool SynchronousCompositorHost::DemandDrawSw(SkCanvas* canvas,
bool software_canvas) {
velocity_in_pixels_per_second_ = 0.f;
num_invalidates_since_last_draw_ = 0u;
if (use_in_process_zero_copy_software_draw_)
return DemandDrawSwInProc(canvas);
Expand Down Expand Up @@ -546,6 +549,10 @@ void SynchronousCompositorHost::SetMemoryPolicy(size_t bytes_limit) {
compositor->SetMemoryPolicy(bytes_limit_);
}

float SynchronousCompositorHost::GetVelocityInPixelsPerSecond() {
return velocity_in_pixels_per_second_;
}

void SynchronousCompositorHost::DidChangeRootLayerScrollOffset(
const gfx::PointF& root_offset) {
if (root_scroll_offset_ == root_offset)
Expand Down Expand Up @@ -694,6 +701,9 @@ void SynchronousCompositorHost::OnBeginFrame(const viz::BeginFrameArgs& args) {
(outstanding_begin_frame_requests_ & BEGIN_FRAME) ||
(outstanding_begin_frame_requests_ & PERSISTENT_BEGIN_FRAME);

last_begin_frame_time_delta_ =
args.frame_time - last_begin_frame_args_.frame_time;

// Update |last_begin_frame_args_| before handling
// |outstanding_begin_frame_requests_| to prevent the BeginFrameSource from
// sending the same MISSED args in infinite recursion.
Expand Down Expand Up @@ -780,6 +790,28 @@ void SynchronousCompositorHost::SendBeginFrame(viz::BeginFrameArgs args) {
timing_details_.clear();
}

void SynchronousCompositorHost::BeginFrameComplete(
blink::mojom::SyncCompositorCommonRendererParamsPtr params) {
velocity_in_pixels_per_second_ = 0.f;
gfx::PointF offset = root_scroll_offset_;
if (params) {
UpdateState(std::move(params));
}
// Sanity check frame time delta.
if (last_begin_frame_time_delta_.InMicroseconds() < 100 ||
last_begin_frame_time_delta_.InMicroseconds() > 1000000) {
return;
}
gfx::Vector2dF scroll = root_scroll_offset_ - offset;
float major_scroll_in_last_begin_frame =
std::abs(scroll.x()) > std::abs(scroll.y()) ? scroll.x() : scroll.y();
velocity_in_pixels_per_second_ = major_scroll_in_last_begin_frame /
last_begin_frame_time_delta_.InSecondsF();
TRACE_EVENT_INSTANT("cc", "SynchronousCompositorHost::BeginFrameComplete",
"scroll", major_scroll_in_last_begin_frame, "delta",
last_begin_frame_time_delta_.InMicroseconds());
}

void SynchronousCompositorHost::SetBeginFrameSource(
viz::BeginFrameSource* begin_frame_source) {
DCHECK(!begin_frame_source_);
Expand Down
6 changes: 6 additions & 0 deletions content/browser/android/synchronous_compositor_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class CONTENT_EXPORT SynchronousCompositorHost
void DidPresentCompositorFrames(viz::FrameTimingDetailsMap timing_details,
uint32_t frame_token) override;
void SetMemoryPolicy(size_t bytes_limit) override;
float GetVelocityInPixelsPerSecond() override;
void DidBecomeActive() override;
void DidChangeRootLayerScrollOffset(const gfx::PointF& root_offset) override;
void SynchronouslyZoomBy(float zoom_delta, const gfx::Point& anchor) override;
Expand All @@ -90,6 +91,8 @@ class CONTENT_EXPORT SynchronousCompositorHost
uint32_t version,
viz::CompositorFrameMetadata frame_metadata,
std::optional<viz::LocalSurfaceId> new_local_surface_id);
void BeginFrameComplete(
blink::mojom::SyncCompositorCommonRendererParamsPtr params);

// Called when the mojo channel should be created.
void InitMojo();
Expand Down Expand Up @@ -182,6 +185,9 @@ class CONTENT_EXPORT SynchronousCompositorHost
// Updated by both renderer and browser. This is in physical pixels.
gfx::PointF root_scroll_offset_;

float velocity_in_pixels_per_second_ = 0.f;
base::TimeDelta last_begin_frame_time_delta_;

// Indicates that whether OnComputeScroll is called or overridden. The
// fling_controller should advance the fling only when OnComputeScroll is not
// overridden.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,9 @@ void SynchronousCompositorSyncCallBridge::BeginFrameCompleteOnUIThread() {
render_params = last_render_params_.Clone();
}
}
if (render_params)
host_->UpdateState(std::move(render_params));
if (render_params) {
host_->BeginFrameComplete(std::move(render_params));
}
}

void SynchronousCompositorSyncCallBridge::ProcessFrameMetadataOnUIThread(
Expand Down
4 changes: 4 additions & 0 deletions content/public/browser/android/synchronous_compositor.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ class CONTENT_EXPORT SynchronousCompositor {
// Set the memory limit policy of this compositor.
virtual void SetMemoryPolicy(size_t bytes_limit) = 0;

// Returns the higher of x or y scroll velocity. Only returns valid value
// after begin frame and before DemandDraw of a frame.
virtual float GetVelocityInPixelsPerSecond() = 0;

// Called during renderer swap. Should push any relevant up to
// SynchronousCompositorClient.
virtual void DidBecomeActive() = 0;
Expand Down
4 changes: 4 additions & 0 deletions content/public/test/test_synchronous_compositor_android.cc
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ bool TestSynchronousCompositor::DemandDrawSw(SkCanvas* canvas,
return true;
}

float TestSynchronousCompositor::GetVelocityInPixelsPerSecond() {
return 0.f;
}

void TestSynchronousCompositor::SetHardwareFrame(
uint32_t layer_tree_frame_sink_id,
std::unique_ptr<viz::CompositorFrame> frame) {
Expand Down
1 change: 1 addition & 0 deletions content/public/test/test_synchronous_compositor_android.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class CONTENT_EXPORT TestSynchronousCompositor : public SynchronousCompositor {
uint32_t frame_token) override {}
bool DemandDrawSw(SkCanvas* canvas, bool software_canvas) override;
void SetMemoryPolicy(size_t bytes_limit) override {}
float GetVelocityInPixelsPerSecond() override;
void DidBecomeActive() override {}
void DidChangeRootLayerScrollOffset(const gfx::PointF& root_offset) override {
}
Expand Down

0 comments on commit 1270133

Please sign in to comment.