1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
|
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_ANDROID_DELEGATED_FRAME_HOST_ANDROID_H_
#define UI_ANDROID_DELEGATED_FRAME_HOST_ANDROID_H_
#include <vector>
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/numerics/safe_conversions.h"
#include "base/time/time.h"
#include "cc/layers/deadline_policy.h"
#include "components/viz/client/frame_evictor.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "components/viz/common/frame_timing_details_map.h"
#include "components/viz/common/resources/returned_resource.h"
#include "components/viz/common/surfaces/surface_id.h"
#include "components/viz/common/surfaces/surface_info.h"
#include "components/viz/host/host_frame_sink_client.h"
#include "third_party/blink/public/common/page/content_to_visible_time_reporter.h"
#include "third_party/blink/public/mojom/widget/record_content_to_visible_time_request.mojom.h"
#include "ui/android/browser_controls_offset_tag_definitions.h"
#include "ui/android/ui_android_export.h"
#include "ui/android/window_android_compositor.h"
namespace cc::slim {
class SurfaceLayer;
}
namespace viz {
class HostFrameSinkManager;
} // namespace viz
namespace ui {
class ViewAndroid;
class WindowAndroidCompositor;
class UI_ANDROID_EXPORT DelegatedFrameHostAndroid
: public viz::HostFrameSinkClient,
public viz::FrameEvictorClient {
public:
class Client : public WindowAndroidCompositor::FrameSubmissionObserver {
public:
~Client() override {}
virtual void OnFrameTokenChanged(uint32_t frame_token,
base::TimeTicks activation_time) = 0;
virtual void WasEvicted() = 0;
virtual void OnSurfaceIdChanged() = 0;
virtual std::vector<viz::SurfaceId> CollectSurfaceIdsForEviction()
const = 0;
};
DelegatedFrameHostAndroid(ViewAndroid* view,
viz::HostFrameSinkManager* host_frame_sink_manager,
Client* client,
const viz::FrameSinkId& frame_sink_id);
DelegatedFrameHostAndroid(const DelegatedFrameHostAndroid&) = delete;
DelegatedFrameHostAndroid& operator=(const DelegatedFrameHostAndroid&) =
delete;
~DelegatedFrameHostAndroid() override;
static int64_t TimeDeltaToFrames(base::TimeDelta delta) {
return base::ClampRound<int64_t>(delta /
viz::BeginFrameArgs::DefaultInterval());
}
// Wait up to 5 seconds for the first frame to be produced. Having Android
// display a placeholder for a longer period of time is preferable to drawing
// nothing, and the first frame can take a while on low-end systems.
static constexpr base::TimeDelta FirstFrameTimeout() {
return base::Seconds(5);
}
static int64_t FirstFrameTimeoutFrames() {
return TimeDeltaToFrames(FirstFrameTimeout());
}
// Wait up to 175 milliseconds for a frame of the correct size to be produced.
// Android OS will only wait 200 milliseconds, so we limit this to make sure
// that Viz is able to produce the latest frame from the Browser before the OS
// stops waiting. Otherwise a rotated version of the previous frame will be
// displayed with a large black region where there is no content yet.
static constexpr base::TimeDelta ResizeTimeout() {
return base::Milliseconds(175);
}
static int64_t ResizeTimeoutFrames() {
return TimeDeltaToFrames(ResizeTimeout());
}
void ClearFallbackSurfaceForCommitPending();
// Advances the fallback surface to the first surface after navigation. This
// ensures that stale surfaces are not presented to the user for an indefinite
// period of time.
void ResetFallbackToFirstNavigationSurface();
bool HasDelegatedContent() const;
const cc::slim::SurfaceLayer* content_layer() const {
return content_layer_.get();
}
const viz::FrameSinkId& GetFrameSinkId() const;
// Should only be called when the host has a content layer. Use this for one-
// off screen capture, not for video. Always provides ResultFormat::RGBA,
// ResultDestination::kSystemMemory CopyOutputResults.
// `capture_exact_surface_id` indicates if the `CopyOutputRequest` will be
// issued against a specific surface or not.
void CopyFromCompositingSurface(
const gfx::Rect& src_subrect,
const gfx::Size& output_size,
base::OnceCallback<void(const SkBitmap&)> callback,
bool capture_exact_surface_id,
base::TimeDelta ipc_delay);
bool CanCopyFromCompositingSurface() const;
void CompositorFrameSinkChanged();
// Called when this DFH is attached/detached from a parent browser compositor
// and needs to be attached to the surface hierarchy.
void AttachToCompositor(WindowAndroidCompositor* compositor);
void DetachFromCompositor();
bool IsPrimarySurfaceEvicted() const;
bool HasSavedFrame() const;
void WasHidden();
void WasShown(const viz::LocalSurfaceId& local_surface_id,
const gfx::Size& size_in_pixels,
bool is_fullscreen,
blink::mojom::RecordContentToVisibleTimeRequestPtr
content_to_visible_time_request);
void EmbedSurface(const viz::LocalSurfaceId& new_local_surface_id,
const gfx::Size& new_size_in_pixels,
cc::DeadlinePolicy deadline_policy,
bool is_fullscreen);
// Called to request the presentation time for the next frame or cancel any
// requests when the RenderWidget's visibility state is not changing. If the
// visibility state is changing call WasHidden or WasShown instead.
void RequestSuccessfulPresentationTimeForNextFrame(
blink::mojom::RecordContentToVisibleTimeRequestPtr
content_to_visible_time_request);
void CancelSuccessfulPresentationTimeRequest();
// Returns the ID for the current Surface. Returns an invalid ID if no
// surface exists (!HasDelegatedContent()).
viz::SurfaceId SurfaceId() const;
bool HasPrimarySurface() const;
bool HasFallbackSurface() const;
void TakeFallbackContentFrom(DelegatedFrameHostAndroid* other);
// Called when navigation has completed, and this DelegatedFrameHost is
// visible. A new Surface will have been embedded at this point. If navigation
// is done while hidden, this will be called upon becoming visible.
void DidNavigate();
// Navigation to a different page than the current one has begun. This is
// called regardless of the visibility of the page. Caches the current
// LocalSurfaceId information so that old content can be evicted if
// navigation fails to complete.
void DidNavigateMainFramePreCommit();
// Called when the page has just entered BFCache.
void DidEnterBackForwardCache();
// Called when the page was activated from BFCache.
void ActivatedOrEvictedFromBackForwardCache();
viz::SurfaceId GetFallbackSurfaceIdForTesting() const;
viz::SurfaceId GetCurrentSurfaceIdForTesting() const;
viz::SurfaceId GetPreNavigationSurfaceIdForTesting() const {
return GetPreNavigationSurfaceId();
}
viz::SurfaceId GetFirstSurfaceIdAfterNavigationForTesting() const;
viz::SurfaceId GetBFCacheFallbackSurfaceIdForTesting() const;
void SetIsFrameSinkIdOwner(bool is_owner);
void RegisterOffsetTags(
const BrowserControlsOffsetTagDefinitions& tag_definitions);
void UnregisterOffsetTags(const cc::BrowserControlsOffsetTags& tags);
private:
// FrameEvictorClient implementation.
void EvictDelegatedFrame(
const std::vector<viz::SurfaceId>& surface_ids) override;
viz::FrameEvictorClient::EvictIds CollectSurfaceIdsForEviction()
const override;
viz::SurfaceId GetCurrentSurfaceId() const override;
viz::SurfaceId GetPreNavigationSurfaceId() const override;
// viz::HostFrameSinkClient implementation.
void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override;
void OnFrameTokenChanged(uint32_t frame_token,
base::TimeTicks activation_time) override;
void ProcessCopyOutputRequest(
std::unique_ptr<viz::CopyOutputRequest> request);
void SetLocalSurfaceId(const viz::LocalSurfaceId& local_surface_id);
// We cannot guarantee to be attached to `registered_parent_compositor_` when
// either WasShown or RequestSuccessfulPresentationTimeForNextFrame is called.
// In such cases we enqueue the request and attempt again to send it once the
// compositor has been attached.
void PostRequestSuccessfulPresentationTimeForNextFrame(
blink::mojom::RecordContentToVisibleTimeRequestPtr
content_to_visible_time_request);
void UpdateCaptureKeepAlive();
void ReleaseCaptureKeepAlive();
const viz::FrameSinkId frame_sink_id_;
raw_ptr<ViewAndroid> view_;
const raw_ptr<viz::HostFrameSinkManager> host_frame_sink_manager_;
raw_ptr<WindowAndroidCompositor> registered_parent_compositor_ = nullptr;
raw_ptr<Client> client_;
scoped_refptr<cc::slim::SurfaceLayer> content_layer_;
// Whether we've received a frame from the renderer since navigating.
// Only used when surface synchronization is on.
viz::LocalSurfaceId first_local_surface_id_after_navigation_;
// While navigating we have no active |local_surface_id_|. Track the one from
// before a navigation, because if the navigation fails to complete, we will
// need to evict its surface. If the old page enters BFCache, this id is used
// to restore `local_surface_id_`.
viz::LocalSurfaceId pre_navigation_local_surface_id_;
// The fallback ID for BFCache restore. It is set when `this` enters the
// BFCache and is cleared when resize-while-hidden (which supplies with a
// latest fallback ID) or after it is used in `EmbedSurface`.
viz::LocalSurfaceId bfcache_fallback_;
// The LocalSurfaceId of the currently embedded surface. If surface sync is
// on, this surface is not necessarily active.
//
// TODO(crbug.com/40274223): this value is a copy of what the browser
// wants to embed. The source of truth is stored else where. We should
// consider de-dup this ID.
viz::LocalSurfaceId local_surface_id_;
// The size of the above surface (updated at the same time).
gfx::Size surface_size_in_pixels_;
// If `registered_parent_compositor_` is not attached when we receive a
// request, we save it and attempt again to send it once the compositor has
// been attached.
blink::mojom::RecordContentToVisibleTimeRequestPtr
content_to_visible_time_request_;
blink::ContentToVisibleTimeReporter content_to_visible_time_recorder_;
std::unique_ptr<viz::FrameEvictor> frame_evictor_;
// If the tab is backgrounded (not visible in the UI), then make sure that the
// surface is kept alive. This is required for e.g. capture of surfaces during
// tab sharing to work. We do this for tabs visible in the UI as well, which
// is redundant, but shouldn't hurt anything.
ui::WindowAndroidCompositor::ScopedKeepSurfaceAliveCallback
capture_keep_alive_callback_;
// Speculative RenderWidgetHostViews can start with a FrameSinkId owned by the
// currently committed RenderWidgetHostView. Ownership is transferred when the
// navigation is committed. This bit tracks whether this
// DelegatedFrameHostAndroid owns its FrameSinkId.
bool owns_frame_sink_id_ = false;
};
} // namespace ui
#endif // UI_ANDROID_DELEGATED_FRAME_HOST_ANDROID_H_
|