Commit 6d052ffd authored by Dave Tapuska's avatar Dave Tapuska Committed by Commit Bot

Move queueing swap promise into WidgetBase.

Move the queueing of the swap promise from RenderWidget into
WidgetBase. This requires expose a callback AddPresentationCallback
which will be eventually be removed when LayerTreeView moves into blink.

Change-Id: I765d787bc6f1fd2246e142bc4c5a1ecc91ec79dc
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2090461
Commit-Queue: Dave Tapuska <dtapuska@chromium.org>
Reviewed-by: default avatardanakj <danakj@chromium.org>
Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
Reviewed-by: default avatarJeremy Roman <jbroman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#750304}
parent 058af229
......@@ -1199,8 +1199,10 @@ bool GpuBenchmarking::AddSwapCompletionEventListener(gin::Arguments* args) {
auto callback_and_context = base::MakeRefCounted<CallbackAndContext>(
args->isolate(), callback, context.web_frame()->MainWorldScriptContext());
context.render_widget()->NotifySwapTime(base::BindOnce(
&OnSwapCompletedHelper, base::RetainedRef(callback_and_context)));
context.web_frame()->FrameWidget()->NotifySwapAndPresentationTime(
base::NullCallback(),
base::BindOnce(&OnSwapCompletedHelper,
base::RetainedRef(callback_and_context)));
return true;
}
......
......@@ -3252,155 +3252,14 @@ void RenderWidget::RequestDecode(const cc::PaintImage& image,
layer_tree_host_->QueueImageDecode(image, std::move(callback));
}
// Enables measuring and reporting both presentation times and swap times in
// swap promises.
class ReportTimeSwapPromise : public cc::SwapPromise {
using ReportTimeCallback = blink::WebReportTimeCallback;
public:
ReportTimeSwapPromise(ReportTimeCallback swap_time_callback,
ReportTimeCallback presentation_time_callback,
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
LayerTreeView* layer_tree_view,
base::WeakPtr<RenderWidget> render_widget)
: swap_time_callback_(std::move(swap_time_callback)),
presentation_time_callback_(std::move(presentation_time_callback)),
task_runner_(std::move(task_runner)),
layer_tree_view_(layer_tree_view),
render_widget_(std::move(render_widget)) {}
~ReportTimeSwapPromise() override = default;
void DidActivate() override {}
void WillSwap(viz::CompositorFrameMetadata* metadata) override {
DCHECK_GT(metadata->frame_token, 0u);
// The interval between the current swap and its presentation time is
// reported in UMA (see corresponding code in DidSwap() below).
frame_token_ = metadata->frame_token;
}
void DidSwap() override {
DCHECK_GT(frame_token_, 0u);
task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&RunCallbackAfterSwap, base::TimeTicks::Now(),
std::move(swap_time_callback_),
std::move(presentation_time_callback_), layer_tree_view_,
std::move(render_widget_), frame_token_));
}
cc::SwapPromise::DidNotSwapAction DidNotSwap(
DidNotSwapReason reason) override {
blink::WebSwapResult result;
switch (reason) {
case cc::SwapPromise::DidNotSwapReason::SWAP_FAILS:
result = blink::WebSwapResult::kDidNotSwapSwapFails;
break;
case cc::SwapPromise::DidNotSwapReason::COMMIT_FAILS:
result = blink::WebSwapResult::kDidNotSwapCommitFails;
break;
case cc::SwapPromise::DidNotSwapReason::COMMIT_NO_UPDATE:
result = blink::WebSwapResult::kDidNotSwapCommitNoUpdate;
break;
case cc::SwapPromise::DidNotSwapReason::ACTIVATION_FAILS:
result = blink::WebSwapResult::kDidNotSwapActivationFails;
break;
}
// During a failed swap, return the current time regardless of whether we're
// using presentation or swap timestamps.
task_runner_->PostTask(
FROM_HERE,
base::BindOnce(
[](blink::WebSwapResult result, base::TimeTicks swap_time,
ReportTimeCallback swap_time_callback,
ReportTimeCallback presentation_time_callback) {
ReportTime(std::move(swap_time_callback), result, swap_time);
ReportTime(std::move(presentation_time_callback), result,
swap_time);
},
result, base::TimeTicks::Now(), std::move(swap_time_callback_),
std::move(presentation_time_callback_)));
return DidNotSwapAction::BREAK_PROMISE;
}
int64_t TraceId() const override { return 0; }
private:
// LayerTreeView is valid while RenderWidget is valid.
static void RunCallbackAfterSwap(
base::TimeTicks swap_time,
ReportTimeCallback swap_time_callback,
ReportTimeCallback presentation_time_callback,
LayerTreeView* layer_tree_view,
base::WeakPtr<RenderWidget> render_widget,
int frame_token) {
if (render_widget) {
layer_tree_view->AddPresentationCallback(
frame_token,
base::BindOnce(&RunCallbackAfterPresentation,
std::move(presentation_time_callback), swap_time));
ReportTime(std::move(swap_time_callback), blink::WebSwapResult::kDidSwap,
swap_time);
} else {
ReportTime(std::move(swap_time_callback), blink::WebSwapResult::kDidSwap,
swap_time);
ReportTime(std::move(presentation_time_callback),
blink::WebSwapResult::kDidSwap, swap_time);
}
}
static void RunCallbackAfterPresentation(
ReportTimeCallback presentation_time_callback,
base::TimeTicks swap_time,
base::TimeTicks presentation_time) {
DCHECK(!swap_time.is_null());
bool presentation_time_is_valid =
!presentation_time.is_null() && (presentation_time > swap_time);
UMA_HISTOGRAM_BOOLEAN("PageLoad.Internal.Renderer.PresentationTime.Valid",
presentation_time_is_valid);
if (presentation_time_is_valid) {
// This measures from 1ms to 10seconds.
UMA_HISTOGRAM_TIMES(
"PageLoad.Internal.Renderer.PresentationTime.DeltaFromSwapTime",
presentation_time - swap_time);
}
ReportTime(std::move(presentation_time_callback),
blink::WebSwapResult::kDidSwap,
presentation_time_is_valid ? presentation_time : swap_time);
}
static void ReportTime(ReportTimeCallback callback,
blink::WebSwapResult result,
base::TimeTicks time) {
if (callback)
std::move(callback).Run(result, time);
}
ReportTimeCallback swap_time_callback_;
ReportTimeCallback presentation_time_callback_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
// This pointer is valid while |render_widget_| is valid.
LayerTreeView* const layer_tree_view_;
base::WeakPtr<RenderWidget> render_widget_;
uint32_t frame_token_ = 0;
DISALLOW_COPY_AND_ASSIGN(ReportTimeSwapPromise);
};
void RenderWidget::NotifySwapTime(blink::WebReportTimeCallback callback) {
NotifySwapAndPresentationTime(base::NullCallback(), std::move(callback));
}
viz::FrameSinkId RenderWidget::GetFrameSinkId() {
return viz::FrameSinkId(RenderThread::Get()->GetClientId(), routing_id());
}
void RenderWidget::NotifySwapAndPresentationTime(
blink::WebReportTimeCallback swap_time_callback,
blink::WebReportTimeCallback presentation_time_callback) {
layer_tree_host_->QueueSwapPromise(std::make_unique<ReportTimeSwapPromise>(
std::move(swap_time_callback), std::move(presentation_time_callback),
layer_tree_host_->GetTaskRunnerProvider()->MainThreadTaskRunner(),
layer_tree_view_.get(), weak_ptr_factory_.GetWeakPtr()));
void RenderWidget::AddPresentationCallback(
uint32_t frame_token,
base::OnceCallback<void(base::TimeTicks)> callback) {
layer_tree_view_->AddPresentationCallback(frame_token, std::move(callback));
}
void RenderWidget::RequestUnbufferedInputEvents() {
......
......@@ -432,8 +432,10 @@ class CONTENT_EXPORT RenderWidget
void DispatchRafAlignedInput(base::TimeTicks frame_time) override;
void RequestDecode(const cc::PaintImage& image,
base::OnceCallback<void(bool)> callback) override;
void NotifySwapTime(blink::WebReportTimeCallback callback) override;
viz::FrameSinkId GetFrameSinkId() override;
void AddPresentationCallback(
uint32_t frame_token,
base::OnceCallback<void(base::TimeTicks)> callback) override;
// Returns the scale being applied to the document in blink by the device
// emulator. Returns 1 if there is no emulation active. Use this to position
......@@ -441,16 +443,6 @@ class CONTENT_EXPORT RenderWidget
// position.
float GetEmulatorScale() const;
// Registers a SwapPromise to report presentation time and possibly swap time.
// If |swap_time_callback| is not a null callback, it would be called once
// swap happens. |presentation_time_callback| will be called some time after
// pixels are presented on screen. Swap time is needed only in tests and
// production code uses |NotifySwapTime()| above which calls this one passing
// a null callback as |swap_time_callback|.
void NotifySwapAndPresentationTime(
blink::WebReportTimeCallback swap_time_callback,
blink::WebReportTimeCallback presentation_time_callback);
// Override point to obtain that the current input method state and caret
// position.
ui::TextInputType GetTextInputType();
......
This diff is collapsed.
......@@ -35,6 +35,7 @@
#include "third_party/blink/public/platform/web_common.h"
#include "third_party/blink/public/platform/web_drag_operation.h"
#include "third_party/blink/public/platform/web_touch_action.h"
#include "third_party/blink/public/web/web_swap_result.h"
#include "third_party/blink/public/web/web_widget.h"
namespace blink {
......@@ -141,6 +142,13 @@ class WebFrameWidget : public WebWidget {
virtual void ApplyViewportChangesForTesting(
const cc::ApplyViewportChangesArgs& args) = 0;
// The |callback| will be fired when the corresponding renderer frame is
// submitted (still called "swapped") to the display compositor (either with
// DidSwap or DidNotSwap).
virtual void NotifySwapAndPresentationTime(
WebReportTimeCallback swap_callback,
WebReportTimeCallback presentation_callback) = 0;
private:
// This private constructor and the class/friend declaration ensures that
// WebFrameWidgetBase is the only concrete subclass that implements
......
......@@ -33,7 +33,9 @@
#include <memory>
#include "base/callback.h"
#include "base/i18n/rtl.h"
#include "base/time/time.h"
#include "cc/trees/layer_tree_host.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
#include "services/network/public/mojom/referrer_policy.mojom-shared.h"
......@@ -47,7 +49,6 @@
#include "third_party/blink/public/platform/web_touch_action.h"
#include "third_party/blink/public/web/web_meaningful_layout.h"
#include "third_party/blink/public/web/web_navigation_policy.h"
#include "third_party/blink/public/web/web_swap_result.h"
class SkBitmap;
......@@ -81,6 +82,7 @@ class WebWidgetClient {
// single thread and no scheduler, the impl should schedule a task to run
// a synchronous composite.
virtual void ScheduleAnimation() {}
// A notification callback for when the intrinsic sizing of the
// widget changed. This is only called for SVG within a remote frame.
virtual void IntrinsicSizingInfoChanged(const WebIntrinsicSizingInfo&) {}
......@@ -253,15 +255,18 @@ class WebWidgetClient {
virtual void RequestDecode(const cc::PaintImage& image,
base::OnceCallback<void(bool)> callback) {}
// The |callback| will be fired when the corresponding renderer frame is
// submitted (still called "swapped") to the display compositor (either with
// DidSwap or DidNotSwap).
virtual void NotifySwapTime(WebReportTimeCallback callback) {}
virtual viz::FrameSinkId GetFrameSinkId() {
NOTREACHED();
return viz::FrameSinkId();
}
// Add a presentation callback. |callback| should be called when
// |frame_token| has been completely displayed by the compositor.
// |callback| should be run on the main thread.
virtual void AddPresentationCallback(
uint32_t frame_token,
base::OnceCallback<void(base::TimeTicks)> callback) {}
};
} // namespace blink
......
......@@ -11,4 +11,7 @@ specific_include_rules = {
"remote_frame_view.cc": [
"+components/paint_preview/common/paint_preview_tracker.h",
],
"web_frame_widget_base.cc": [
"+cc/trees/swap_promise.h",
],
}
......@@ -7,7 +7,11 @@
#include <memory>
#include <utility>
#include "base/metrics/histogram_macros.h"
#include "base/single_thread_task_runner.h"
#include "base/time/time.h"
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/swap_promise.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_widget_client.h"
......@@ -35,7 +39,18 @@
#include "third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.h"
#include "third_party/blink/renderer/platform/graphics/compositor_mutator_client.h"
#include "third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
namespace WTF {
template <>
struct CrossThreadCopier<blink::WebReportTimeCallback>
: public CrossThreadCopierByValuePassThrough<blink::WebReportTimeCallback> {
STATIC_ONLY(CrossThreadCopier);
};
} // namespace WTF
namespace blink {
......@@ -608,4 +623,144 @@ WebFrameWidgetBase::EnsureCompositorPaintDispatcher(
return paint_dispatcher_;
}
// Enables measuring and reporting both presentation times and swap times in
// swap promises.
class ReportTimeSwapPromise : public cc::SwapPromise {
public:
ReportTimeSwapPromise(WebReportTimeCallback swap_time_callback,
WebReportTimeCallback presentation_time_callback,
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
WebFrameWidgetBase* widget)
: swap_time_callback_(std::move(swap_time_callback)),
presentation_time_callback_(std::move(presentation_time_callback)),
task_runner_(std::move(task_runner)),
widget_(widget) {}
~ReportTimeSwapPromise() override = default;
void DidActivate() override {}
void WillSwap(viz::CompositorFrameMetadata* metadata) override {
DCHECK_GT(metadata->frame_token, 0u);
// The interval between the current swap and its presentation time is
// reported in UMA (see corresponding code in DidSwap() below).
frame_token_ = metadata->frame_token;
}
void DidSwap() override {
DCHECK_GT(frame_token_, 0u);
PostCrossThreadTask(
*task_runner_, FROM_HERE,
CrossThreadBindOnce(
&RunCallbackAfterSwap, widget_, base::TimeTicks::Now(),
std::move(swap_time_callback_),
std::move(presentation_time_callback_), frame_token_));
}
cc::SwapPromise::DidNotSwapAction DidNotSwap(
DidNotSwapReason reason) override {
WebSwapResult result;
switch (reason) {
case cc::SwapPromise::DidNotSwapReason::SWAP_FAILS:
result = WebSwapResult::kDidNotSwapSwapFails;
break;
case cc::SwapPromise::DidNotSwapReason::COMMIT_FAILS:
result = WebSwapResult::kDidNotSwapCommitFails;
break;
case cc::SwapPromise::DidNotSwapReason::COMMIT_NO_UPDATE:
result = WebSwapResult::kDidNotSwapCommitNoUpdate;
break;
case cc::SwapPromise::DidNotSwapReason::ACTIVATION_FAILS:
result = WebSwapResult::kDidNotSwapActivationFails;
break;
}
// During a failed swap, return the current time regardless of whether we're
// using presentation or swap timestamps.
PostCrossThreadTask(
*task_runner_, FROM_HERE,
CrossThreadBindOnce(
[](WebSwapResult result, base::TimeTicks swap_time,
WebReportTimeCallback swap_time_callback,
WebReportTimeCallback presentation_time_callback) {
ReportTime(std::move(swap_time_callback), result, swap_time);
ReportTime(std::move(presentation_time_callback), result,
swap_time);
},
result, base::TimeTicks::Now(), std::move(swap_time_callback_),
std::move(presentation_time_callback_)));
return DidNotSwapAction::BREAK_PROMISE;
}
int64_t TraceId() const override { return 0; }
private:
static void RunCallbackAfterSwap(
WebFrameWidgetBase* widget,
base::TimeTicks swap_time,
WebReportTimeCallback swap_time_callback,
WebReportTimeCallback presentation_time_callback,
int frame_token) {
// If the widget was collected or the widget wasn't collected yet, but
// it was closed don't schedule a presentation callback.
if (widget && widget->Client()) {
widget->Client()->AddPresentationCallback(
frame_token,
WTF::Bind(&RunCallbackAfterPresentation,
std::move(presentation_time_callback), swap_time));
ReportTime(std::move(swap_time_callback), WebSwapResult::kDidSwap,
swap_time);
} else {
ReportTime(std::move(swap_time_callback), WebSwapResult::kDidSwap,
swap_time);
ReportTime(std::move(presentation_time_callback), WebSwapResult::kDidSwap,
swap_time);
}
}
static void RunCallbackAfterPresentation(
WebReportTimeCallback presentation_time_callback,
base::TimeTicks swap_time,
base::TimeTicks presentation_time) {
DCHECK(!swap_time.is_null());
bool presentation_time_is_valid =
!presentation_time.is_null() && (presentation_time > swap_time);
UMA_HISTOGRAM_BOOLEAN("PageLoad.Internal.Renderer.PresentationTime.Valid",
presentation_time_is_valid);
if (presentation_time_is_valid) {
// This measures from 1ms to 10seconds.
UMA_HISTOGRAM_TIMES(
"PageLoad.Internal.Renderer.PresentationTime.DeltaFromSwapTime",
presentation_time - swap_time);
}
ReportTime(std::move(presentation_time_callback), WebSwapResult::kDidSwap,
presentation_time_is_valid ? presentation_time : swap_time);
}
static void ReportTime(WebReportTimeCallback callback,
WebSwapResult result,
base::TimeTicks time) {
if (callback)
std::move(callback).Run(result, time);
}
WebReportTimeCallback swap_time_callback_;
WebReportTimeCallback presentation_time_callback_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
CrossThreadWeakPersistent<WebFrameWidgetBase> widget_;
uint32_t frame_token_ = 0;
DISALLOW_COPY_AND_ASSIGN(ReportTimeSwapPromise);
};
void WebFrameWidgetBase::NotifySwapAndPresentationTime(
WebReportTimeCallback swap_time_callback,
WebReportTimeCallback presentation_time_callback) {
widget_base_.LayerTreeHost()->QueueSwapPromise(
std::make_unique<ReportTimeSwapPromise>(
std::move(swap_time_callback), std::move(presentation_time_callback),
widget_base_.LayerTreeHost()
->GetTaskRunnerProvider()
->MainThreadTaskRunner(),
this));
}
} // namespace blink
......@@ -118,6 +118,9 @@ class CORE_EXPORT WebFrameWidgetBase
void SetCompositorHosts(cc::LayerTreeHost*, cc::AnimationHost*) override;
void ApplyViewportChangesForTesting(
const ApplyViewportChangesArgs& args) override;
void NotifySwapAndPresentationTime(
WebReportTimeCallback swap_callback,
WebReportTimeCallback presentation_callback) override;
// Called when a drag-n-drop operation should begin.
void StartDragging(network::mojom::ReferrerPolicy,
......
......@@ -931,12 +931,14 @@ void ChromeClientImpl::RequestDecode(LocalFrame* frame,
void ChromeClientImpl::NotifySwapTime(LocalFrame& frame,
ReportTimeCallback callback) {
if (!web_view_->does_composite())
return;
WebLocalFrameImpl* web_frame = WebLocalFrameImpl::FromFrame(frame);
WebFrameWidgetBase* widget = web_frame->LocalRootFrameWidget();
if (!widget)
return;
WebWidgetClient* client = widget->Client();
client->NotifySwapTime(ConvertToBaseOnceCallback(std::move(callback)));
widget->NotifySwapAndPresentationTime(
base::NullCallback(), ConvertToBaseOnceCallback(std::move(callback)));
}
void ChromeClientImpl::FallbackCursorModeLockCursor(LocalFrame* frame,
......
......@@ -98,6 +98,7 @@ _CONFIG = [
# //base/callback.h is allowed, but you need to use WTF::Bind or
# WTF::BindRepeating to create callbacks in Blink.
'base::BarrierClosure',
'base::NullCallback',
'base::OnceCallback',
'base::OnceClosure',
'base::RepeatingCallback',
......@@ -536,6 +537,13 @@ _CONFIG = [
'gin::IsolateHolder',
],
},
{
'paths': ['third_party/blink/renderer/core/frame/web_frame_widget_base.cc'],
'allowed': [
'cc::SwapPromise',
'viz::CompositorFrameMetadata',
],
},
{
'paths': ['third_party/blink/renderer/core/fileapi/file_reader_loader.cc'],
'allowed': [
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment