overlay_processor_webview.cc 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "android_webview/browser/gfx/overlay_processor_webview.h"
  5. #include "android_webview/browser/gfx/gpu_service_webview.h"
  6. #include "android_webview/browser/gfx/viz_compositor_thread_runner_webview.h"
  7. #include "base/android/android_hardware_buffer_compat.h"
  8. #include "base/android/scoped_hardware_buffer_fence_sync.h"
  9. #include "base/callback_helpers.h"
  10. #include "base/memory/raw_ptr.h"
  11. #include "base/memory/ref_counted.h"
  12. #include "base/task/bind_post_task.h"
  13. #include "base/threading/thread_checker.h"
  14. #include "components/viz/common/quads/texture_draw_quad.h"
  15. #include "components/viz/service/display/display_compositor_memory_and_task_controller.h"
  16. #include "components/viz/service/display/resolved_frame_data.h"
  17. #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
  18. #include "components/viz/service/gl/gpu_service_impl.h"
  19. #include "components/viz/service/surfaces/surface.h"
  20. #include "gpu/command_buffer/service/display_compositor_memory_and_task_controller_on_gpu.h"
  21. #include "gpu/command_buffer/service/memory_tracking.h"
  22. #include "gpu/command_buffer/service/scheduler_sequence.h"
  23. #include "gpu/command_buffer/service/shared_image/shared_image_manager.h"
  24. #include "gpu/command_buffer/service/shared_image/shared_image_representation.h"
  25. #include "gpu/command_buffer/service/single_task_sequence.h"
  26. #include "ui/gfx/android/android_surface_control_compat.h"
  27. #include "ui/gfx/geometry/rect_conversions.h"
  28. namespace android_webview {
  29. namespace {
  30. constexpr gpu::CommandBufferNamespace kOverlayProcessorNamespace =
  31. gpu::CommandBufferNamespace::IN_PROCESS;
  32. constexpr int kMaxBuffersInFlight = 3;
  33. scoped_refptr<gpu::SyncPointClientState> CreateSyncPointClientState(
  34. gpu::CommandBufferId command_buffer_id,
  35. gpu::SequenceId sequence_id) {
  36. return GpuServiceWebView::GetInstance()
  37. ->sync_point_manager()
  38. ->CreateSyncPointClientState(kOverlayProcessorNamespace,
  39. command_buffer_id, sequence_id);
  40. }
  41. } // namespace
  42. // Manages ASurfaceControl life-cycle and handles ASurfaceTransactions. Created
  43. // on Android RenderThread, but both used on both Android RenderThread and GPU
  44. // Main thread, so can be destroyed on one of them.
  45. class OverlayProcessorWebView::Manager
  46. : public base::RefCountedThreadSafe<OverlayProcessorWebView::Manager> {
  47. private:
  48. class Resource {
  49. public:
  50. Resource(gpu::SharedImageManager* shared_image_manager,
  51. gpu::MemoryTypeTracker* memory_tracker,
  52. const gpu::Mailbox& mailbox,
  53. const gfx::RectF& uv_rect,
  54. base::ScopedClosureRunner return_resource)
  55. : return_resource(std::move(return_resource)) {
  56. representation_ =
  57. shared_image_manager->ProduceOverlay(mailbox, memory_tracker);
  58. if (!representation_) {
  59. return;
  60. }
  61. read_access_ = representation_->BeginScopedReadAccess(false);
  62. if (!read_access_) {
  63. LOG(ERROR) << "Couldn't access shared image for read.";
  64. return;
  65. }
  66. gfx::GpuFenceHandle acquire_fence = read_access_->TakeAcquireFence();
  67. if (!acquire_fence.is_null()) {
  68. begin_read_fence_ = std::move(acquire_fence.owned_fd);
  69. }
  70. AHardwareBuffer_Desc desc;
  71. base::AndroidHardwareBufferCompat::GetInstance().Describe(
  72. GetAHardwareBuffer(), &desc);
  73. gfx::RectF scaled_rect = gfx::ScaleRect(uv_rect, desc.width, desc.height);
  74. crop_rect_ = gfx::ToEnclosedRect(scaled_rect);
  75. }
  76. ~Resource() {
  77. DCHECK(!read_access_)
  78. << "Return() or ReturnUnused() must be called before dtor";
  79. DCHECK(!representation_);
  80. }
  81. Resource(Resource&&) = default;
  82. Resource& operator=(Resource&&) = default;
  83. Resource(const Resource&) = delete;
  84. Resource& operator=(const Resource&) = delete;
  85. void Return(base::ScopedFD end_read_fence) {
  86. // It's possible that we didn't have buffer for the first frame (see
  87. // `GetAHardwareBuffer()`) so there will be no read_access to set fence
  88. // to. On the other hand we shouldn't get a fence from flinger for this
  89. // surface in this case.
  90. if (read_access_) {
  91. gfx::GpuFenceHandle fence_handle;
  92. fence_handle.owned_fd = std::move(end_read_fence);
  93. read_access_->SetReleaseFence(std::move(fence_handle));
  94. read_access_.reset();
  95. } else {
  96. DCHECK(!end_read_fence.is_valid());
  97. }
  98. representation_.reset();
  99. }
  100. void ReturnUnused() {
  101. read_access_.reset();
  102. representation_.reset();
  103. begin_read_fence_.reset();
  104. }
  105. base::ScopedFD TakeBeginReadFence() { return std::move(begin_read_fence_); }
  106. AHardwareBuffer* GetAHardwareBuffer() {
  107. // Note, that it's possible that BeginScopedReadAccess() will fail if
  108. // media couldn't get us a frame. We don't fail creation of resource in
  109. // this case, because if affects Surface acks and we don't to change the
  110. // frame submission flow. Instead we just set empty buffer to the surface.
  111. // Note, that it should only happen for the first frame in very rare
  112. // cases.
  113. if (!read_access_)
  114. return nullptr;
  115. DCHECK(representation_);
  116. DCHECK(read_access_);
  117. return read_access_->GetAHardwareBuffer();
  118. }
  119. const gfx::Rect& crop_rect() { return crop_rect_; }
  120. private:
  121. gfx::Rect crop_rect_;
  122. base::ScopedClosureRunner return_resource;
  123. std::unique_ptr<gpu::OverlayImageRepresentation> representation_;
  124. std::unique_ptr<gpu::OverlayImageRepresentation::ScopedReadAccess>
  125. read_access_;
  126. base::ScopedFD begin_read_fence_;
  127. };
  128. public:
  129. Manager(gpu::CommandBufferId command_buffer_id, gpu::SequenceId sequence_id)
  130. : shared_image_manager_(
  131. GpuServiceWebView::GetInstance()->shared_image_manager()),
  132. memory_tracker_(std::make_unique<gpu::MemoryTypeTracker>(nullptr)),
  133. sync_point_client_state_(
  134. CreateSyncPointClientState(command_buffer_id, sequence_id)) {
  135. DETACH_FROM_THREAD(gpu_thread_checker_);
  136. }
  137. void SetGpuService(viz::GpuServiceImpl* gpu_service) {
  138. DCHECK_CALLED_ON_VALID_THREAD(render_thread_checker_);
  139. DCHECK_EQ(shared_image_manager_, gpu_service->shared_image_manager());
  140. gpu_task_runner_ = gpu_service->main_runner();
  141. }
  142. // Create SurfaceControl for |overlay_id| and set it up.
  143. void CreateOverlay(uint64_t overlay_id,
  144. const viz::OverlayCandidate& candidate,
  145. base::ScopedClosureRunner return_resource,
  146. uint64_t sync_fence_release) {
  147. DCHECK_CALLED_ON_VALID_THREAD(render_thread_checker_);
  148. TRACE_EVENT1("gpu,benchmark,android_webview",
  149. "OverlayProcessorWebview::Manager::CreateOverlay",
  150. "overlay_id", overlay_id);
  151. auto& transaction = GetHWUITransaction();
  152. std::unique_ptr<Resource> resource =
  153. CreateResource(candidate.mailbox, candidate.unclipped_uv_rect,
  154. std::move(return_resource));
  155. {
  156. base::AutoLock lock(lock_);
  157. bool inserted;
  158. base::flat_map<uint64_t, OverlaySurface>::iterator it;
  159. std::tie(it, inserted) =
  160. overlay_surfaces_.emplace(overlay_id, GetParentSurface());
  161. DCHECK(inserted);
  162. auto& overlay_surface = it->second;
  163. UpdateGeometryInTransaction(transaction, *overlay_surface.bounds_surface,
  164. candidate);
  165. UpdateBufferInTransaction(transaction, *overlay_surface.buffer_surface,
  166. resource.get());
  167. overlay_surface.buffer_update_pending = true;
  168. }
  169. DCHECK(!pending_resource_update_.contains(overlay_id));
  170. pending_resource_update_[overlay_id] = std::move(resource);
  171. sync_point_client_state_->ReleaseFenceSync(sync_fence_release);
  172. }
  173. // Update geometry of SurfaceControl for |overlay_id|.
  174. void UpdateOverlayGeometry(uint64_t overlay_id,
  175. const viz::OverlayCandidate& candidate) {
  176. DCHECK_CALLED_ON_VALID_THREAD(render_thread_checker_);
  177. TRACE_EVENT1("gpu,benchmark,android_webview",
  178. "OverlayProcessorWebview::Manager::UpdateOverlayGeometry",
  179. "overlay_id", overlay_id);
  180. auto& transaction = GetHWUITransaction();
  181. base::AutoLock lock(lock_);
  182. auto& overlay_surface = GetOverlaySurfaceLocked(overlay_id);
  183. UpdateGeometryInTransaction(transaction, *overlay_surface.bounds_surface,
  184. candidate);
  185. }
  186. // Update buffer in SurfaceControl for |overlay_id|. Called on GPU Main
  187. // Thread.
  188. void UpdateOverlayBuffer(uint64_t overlay_id,
  189. gpu::Mailbox mailbox,
  190. const gfx::RectF& uv_rect,
  191. base::ScopedClosureRunner return_resource) {
  192. DCHECK_CALLED_ON_VALID_THREAD(gpu_thread_checker_);
  193. TRACE_EVENT1("gpu,benchmark,android_webview",
  194. "OverlayProcessorWebview::Manager::UpdateOverlayBuffer",
  195. "overlay_id", overlay_id);
  196. base::AutoLock lock(lock_);
  197. auto& overlay_surface = GetOverlaySurfaceLocked(overlay_id);
  198. // If we're going to remove this overlay, there is no point in updating
  199. // buffer anymore. Resource will be unlocked by |return_resource| getting
  200. // out of scope.
  201. if (overlay_surface.pending_remove) {
  202. return;
  203. }
  204. std::unique_ptr<Resource> resource =
  205. CreateResource(mailbox, uv_rect, std::move(return_resource));
  206. // If there is already transaction with buffer update in-flight, store this
  207. // one. This will return any previous stored resource if any.
  208. if (overlay_surface.buffer_update_pending) {
  209. overlay_surface.SetPendingResource(std::move(resource));
  210. return;
  211. }
  212. SubmitTransactionWithBufferLocked(overlay_id, overlay_surface,
  213. std::move(resource));
  214. }
  215. // Initiate removal of SurfaceControl for |overlay_id|. Removal done in next
  216. // steps:
  217. // Unparent SurfaceControl, this happens synchronously with HWUI draw.
  218. // Set buffer to nullptr, to get current_buffer back with a fence.
  219. // Free SurfaceControl.
  220. void RemoveOverlay(uint64_t overlay_id) {
  221. DCHECK_CALLED_ON_VALID_THREAD(render_thread_checker_);
  222. TRACE_EVENT1("gpu,benchmark,android_webview",
  223. "OverlayProcessorWebview::Manager::RemoveOverlay",
  224. "overlay_id", overlay_id);
  225. auto& transaction = GetHWUITransaction();
  226. {
  227. base::AutoLock lock(lock_);
  228. auto& overlay_surface = GetOverlaySurfaceLocked(overlay_id);
  229. transaction.SetParent(*overlay_surface.bounds_surface, nullptr);
  230. }
  231. pending_removals_.insert(overlay_id);
  232. }
  233. // Initiate removal of all current surfaces and drop reference to
  234. // parent_surface. This can be called with empty array.
  235. void RemoveOverlays(std::vector<uint64_t> overlay_ids) {
  236. DCHECK_CALLED_ON_VALID_THREAD(render_thread_checker_);
  237. TRACE_EVENT0("gpu,benchmark,webview",
  238. "OverlayProcessorWebview::Manager::RemoveOverlays");
  239. parent_surface_.reset();
  240. if (overlay_ids.empty())
  241. return;
  242. auto& transaction = GetHWUITransaction();
  243. {
  244. base::AutoLock lock(lock_);
  245. for (auto overlay_id : overlay_ids) {
  246. auto& overlay = GetOverlaySurfaceLocked(overlay_id);
  247. transaction.SetParent(*overlay.bounds_surface, nullptr);
  248. }
  249. }
  250. pending_removals_.insert(overlay_ids.begin(), overlay_ids.end());
  251. }
  252. void OnUpdateBufferTransactionAck(
  253. uint64_t overlay_id,
  254. std::unique_ptr<Resource> resource,
  255. gfx::SurfaceControl::TransactionStats transaction_stats) {
  256. DCHECK_CALLED_ON_VALID_THREAD(gpu_thread_checker_);
  257. TRACE_EVENT2(
  258. "gpu,benchmark,android_webview",
  259. "OverlayProcessorWebview::Manager::OnUpdateBufferTransactionAck",
  260. "overlay_id", overlay_id, "has_resource", !!resource);
  261. base::AutoLock lock(lock_);
  262. auto& overlay_surface = GetOverlaySurfaceLocked(overlay_id);
  263. DCHECK_EQ(transaction_stats.surface_stats.size(), 1u);
  264. DCHECK_EQ(transaction_stats.surface_stats.front().surface,
  265. overlay_surface.buffer_surface->surface());
  266. bool empty_buffer = !resource;
  267. overlay_surface.SetResource(
  268. std::move(resource),
  269. std::move(transaction_stats.surface_stats.front().fence));
  270. if (overlay_surface.pending_resource) {
  271. DCHECK(!overlay_surface.pending_remove);
  272. SubmitTransactionWithBufferLocked(
  273. overlay_id, overlay_surface,
  274. std::move(overlay_surface.pending_resource));
  275. }
  276. if (overlay_surface.pending_remove) {
  277. // If there is no resource, we can free our surface.
  278. if (empty_buffer) {
  279. overlay_surface.Reset();
  280. overlay_surfaces_.erase(overlay_id);
  281. } else {
  282. // This means there was buffer transaction in flight when surface was
  283. // hidden, we need to set buffer to nullptr, to free current one before
  284. // we can free the surface.
  285. SubmitTransactionWithBufferLocked(overlay_id, overlay_surface, nullptr);
  286. }
  287. }
  288. }
  289. void OnHWUITransactionAck(
  290. base::flat_map<uint64_t, std::unique_ptr<Resource>> resource_updates,
  291. base::flat_set<uint64_t> removes,
  292. gfx::SurfaceControl::TransactionStats transaction_stats) {
  293. DCHECK_CALLED_ON_VALID_THREAD(gpu_thread_checker_);
  294. TRACE_EVENT0("gpu,benchmark,android_webview",
  295. "OverlayProcessorWebview::Manager::OnHWUITransactionAck");
  296. base::AutoLock lock(lock_);
  297. for (auto& update : resource_updates) {
  298. auto& overlay_surface = GetOverlaySurfaceLocked(update.first);
  299. base::ScopedFD fence;
  300. for (auto& stat : transaction_stats.surface_stats) {
  301. if (stat.surface == overlay_surface.buffer_surface->surface()) {
  302. DCHECK(!fence.is_valid());
  303. fence = std::move(stat.fence);
  304. }
  305. }
  306. overlay_surface.SetResource(std::move(update.second), std::move(fence));
  307. if (overlay_surface.pending_resource) {
  308. SubmitTransactionWithBufferLocked(
  309. update.first, overlay_surface,
  310. std::move(overlay_surface.pending_resource));
  311. }
  312. }
  313. for (auto& overlay_id : removes) {
  314. auto& overlay_surface = GetOverlaySurfaceLocked(overlay_id);
  315. overlay_surface.pending_remove = true;
  316. if (overlay_surface.pending_resource) {
  317. overlay_surface.pending_resource->ReturnUnused();
  318. overlay_surface.pending_resource.reset();
  319. }
  320. if (!overlay_surface.buffer_update_pending) {
  321. SubmitTransactionWithBufferLocked(overlay_id, overlay_surface, nullptr);
  322. }
  323. }
  324. }
  325. absl::optional<gfx::SurfaceControl::Transaction> TakeHWUITransaction() {
  326. DCHECK_CALLED_ON_VALID_THREAD(render_thread_checker_);
  327. absl::optional<gfx::SurfaceControl::Transaction> result;
  328. if (hwui_transaction_) {
  329. DCHECK(gpu_task_runner_);
  330. if (!pending_resource_update_.empty() || !pending_removals_.empty()) {
  331. auto cb = base::BindOnce(&Manager::OnHWUITransactionAck, this,
  332. std::move(pending_resource_update_),
  333. std::move(pending_removals_));
  334. hwui_transaction_->SetOnCompleteCb(std::move(cb), gpu_task_runner_);
  335. }
  336. result.swap(hwui_transaction_);
  337. }
  338. return result;
  339. }
  340. private:
  341. friend class OverlayProcessorWebView::ScopedSurfaceControlAvailable;
  342. friend class base::RefCountedThreadSafe<Manager>;
  343. // Class that holds SurfaceControl and associated resources.
  344. class OverlaySurface {
  345. public:
  346. OverlaySurface(const gfx::SurfaceControl::Surface& parent)
  347. : bounds_surface(base::MakeRefCounted<gfx::SurfaceControl::Surface>(
  348. parent,
  349. "webview_overlay_bounds")),
  350. buffer_surface(base::MakeRefCounted<gfx::SurfaceControl::Surface>(
  351. *bounds_surface,
  352. "webview_overlay_content")) {}
  353. OverlaySurface(OverlaySurface&& other) = default;
  354. OverlaySurface& operator=(OverlaySurface&& other) = default;
  355. ~OverlaySurface() {
  356. DCHECK(!bounds_surface);
  357. DCHECK(!buffer_surface);
  358. DCHECK(!current_resource);
  359. }
  360. void SetResource(std::unique_ptr<Resource> resource,
  361. base::ScopedFD end_read_fence) {
  362. if (current_resource) {
  363. current_resource->Return(std::move(end_read_fence));
  364. }
  365. current_resource = std::move(resource);
  366. DCHECK(buffer_update_pending);
  367. buffer_update_pending = false;
  368. }
  369. void SetPendingResource(std::unique_ptr<Resource> resource) {
  370. DCHECK(buffer_update_pending);
  371. if (pending_resource) {
  372. pending_resource->ReturnUnused();
  373. }
  374. pending_resource = std::move(resource);
  375. }
  376. void Reset() {
  377. DCHECK(!pending_resource);
  378. DCHECK(!current_resource);
  379. bounds_surface.reset();
  380. buffer_surface.reset();
  381. }
  382. // Set when we're in process of removing this overlay.
  383. bool pending_remove = false;
  384. // This is true when there is SurfaceControl transaction that affects buffer
  385. // of this overlay is in-flight.
  386. bool buffer_update_pending = false;
  387. // Resource that is currently latched by SurfaceControl
  388. std::unique_ptr<Resource> current_resource;
  389. // Resource that we want to send to SurfaceControl, but there was another
  390. // transaction with buffer update in-flight.
  391. std::unique_ptr<Resource> pending_resource;
  392. // SurfaceControl for this overlay.
  393. scoped_refptr<gfx::SurfaceControl::Surface> bounds_surface;
  394. scoped_refptr<gfx::SurfaceControl::Surface> buffer_surface;
  395. };
  396. ~Manager() {
  397. DCHECK(!hwui_transaction_);
  398. DCHECK(!parent_surface_);
  399. }
  400. gfx::SurfaceControl::Transaction& GetHWUITransaction() {
  401. DCHECK_CALLED_ON_VALID_THREAD(render_thread_checker_);
  402. if (!hwui_transaction_)
  403. hwui_transaction_.emplace();
  404. return hwui_transaction_.value();
  405. }
  406. const gfx::SurfaceControl::Surface& GetParentSurface() {
  407. DCHECK_CALLED_ON_VALID_THREAD(render_thread_checker_);
  408. if (!parent_surface_) {
  409. DCHECK(get_surface_control_);
  410. parent_surface_ =
  411. gfx::SurfaceControl::Surface::WrapUnowned(get_surface_control_());
  412. DCHECK(parent_surface_);
  413. }
  414. return *parent_surface_;
  415. }
  416. OverlaySurface& GetOverlaySurfaceLocked(uint64_t id) {
  417. lock_.AssertAcquired();
  418. auto surface = overlay_surfaces_.find(id);
  419. DCHECK(surface != overlay_surfaces_.end());
  420. return surface->second;
  421. }
  422. std::unique_ptr<Resource> CreateResource(
  423. const gpu::Mailbox& mailbox,
  424. const gfx::RectF uv_rect,
  425. base::ScopedClosureRunner return_resource) {
  426. if (mailbox.IsZero())
  427. return nullptr;
  428. return std::make_unique<Resource>(shared_image_manager_,
  429. memory_tracker_.get(), mailbox, uv_rect,
  430. std::move(return_resource));
  431. }
  432. // Because we update different parts of geometry on different threads we use
  433. // two surfaces to avoid races. The Bounds surface is setup the way it assumes
  434. // that its content size is kBoundsSurfaceContentSize. The Buffer surface is
  435. // setup to scale itself to kBoundsSurfaceContentSize. Note, that from scaling
  436. // perspective this number doesn't matter as scales of two surfaces will be
  437. // just multiplied inside SurfaceFlinger, but because positions and crop rects
  438. // are integers we need the content size to be large enough to avoid rounding
  439. // errors. To avoid floating point errors we also use power of two.
  440. static constexpr float kBoundsSurfaceContentSize = 8192.0f;
  441. static void UpdateGeometryInTransaction(
  442. gfx::SurfaceControl::Transaction& transaction,
  443. gfx::SurfaceControl::Surface& surface,
  444. const viz::OverlayCandidate& candidate) {
  445. DCHECK_EQ(candidate.transform, gfx::OVERLAY_TRANSFORM_NONE);
  446. gfx::Rect dst = gfx::ToEnclosingRect(candidate.unclipped_display_rect);
  447. transaction.SetPosition(surface, dst.origin());
  448. // Setup scale so the contents of size kBoundsSurfaceContentSize would fit
  449. // into display_rect. The buffer surface will make sure to scale its content
  450. // to kBoundsSurfaceContentSize.
  451. float scale_x = dst.width() / kBoundsSurfaceContentSize;
  452. float scale_y = dst.height() / kBoundsSurfaceContentSize;
  453. transaction.SetScale(surface, scale_x, scale_y);
  454. if (candidate.clip_rect) {
  455. // Make |crop_rect| relative to |display_rect|.
  456. auto crop_rect = dst;
  457. crop_rect.Intersect(*candidate.clip_rect);
  458. crop_rect.Offset(-dst.x(), -dst.y());
  459. // Crop rect is in content space, so we need to scale it.
  460. auto scaled_clip = gfx::ToEnclosingRect(gfx::ScaleRect(
  461. gfx::RectF(crop_rect), 1.0f / scale_x, 1.0f / scale_y));
  462. transaction.SetCrop(surface, scaled_clip);
  463. }
  464. }
  465. static void UpdateBufferInTransaction(
  466. gfx::SurfaceControl::Transaction& transaction,
  467. gfx::SurfaceControl::Surface& surface,
  468. Resource* resource) {
  469. TRACE_EVENT1("gpu,benchmark,android_webview",
  470. "OverlayProcessorWebview::Manager::UpdateBufferInTransaction",
  471. "has_resource", !!resource);
  472. auto* buffer = resource ? resource->GetAHardwareBuffer() : nullptr;
  473. if (buffer) {
  474. auto crop_rect = resource->crop_rect();
  475. // Crop rect defines the valid portion of the buffer, so we use its as a
  476. // surface size. This calculates scale from our size to bounds surface
  477. // content size, see comment at kBoundsSurfaceContentSize.
  478. float scale_x = kBoundsSurfaceContentSize / crop_rect.width();
  479. float scale_y = kBoundsSurfaceContentSize / crop_rect.height();
  480. // Crop rect is defined in buffer space, so we need to translate our
  481. // surface to make sure crop rect origin matches bounds surface (0, 0).
  482. // Position is defined in parent space, so we need to scale it.
  483. transaction.SetPosition(surface,
  484. gfx::Point(-ceil(crop_rect.x() * scale_x),
  485. -ceil(crop_rect.y() * scale_y)));
  486. transaction.SetScale(surface, scale_x, scale_y);
  487. transaction.SetCrop(surface, crop_rect);
  488. transaction.SetBuffer(surface, buffer, resource->TakeBeginReadFence());
  489. } else {
  490. transaction.SetBuffer(surface, nullptr, base::ScopedFD());
  491. }
  492. }
  493. void SubmitTransactionWithBufferLocked(uint64_t overlay_id,
  494. OverlaySurface& overlay_surface,
  495. std::unique_ptr<Resource> resource) {
  496. lock_.AssertAcquired();
  497. DCHECK(!overlay_surface.buffer_update_pending);
  498. DCHECK(gpu_task_runner_);
  499. overlay_surface.buffer_update_pending = true;
  500. gfx::SurfaceControl::Transaction transaction;
  501. UpdateBufferInTransaction(transaction, *overlay_surface.buffer_surface,
  502. resource.get());
  503. auto cb = base::BindOnce(&Manager::OnUpdateBufferTransactionAck, this,
  504. overlay_id, std::move(resource));
  505. transaction.SetOnCompleteCb(std::move(cb), gpu_task_runner_);
  506. transaction.Apply();
  507. }
  508. base::Lock lock_;
  509. // These can be accessed on any thread, but only initialized in ctor.
  510. const raw_ptr<gpu::SharedImageManager> shared_image_manager_;
  511. std::unique_ptr<gpu::MemoryTypeTracker> memory_tracker_;
  512. // GPU Main Thread task runner.
  513. scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner_;
  514. // SyncPointClientState for render thread sequence.
  515. scoped_refptr<gpu::SyncPointClientState> sync_point_client_state_;
  516. // Can be accessed on both threads.
  517. base::flat_map<uint64_t, OverlaySurface> overlay_surfaces_ GUARDED_BY(lock_);
  518. // Pending updates for the current hwui transaction.
  519. base::flat_map<uint64_t, std::unique_ptr<Resource>> pending_resource_update_;
  520. base::flat_set<uint64_t> pending_removals_;
  521. scoped_refptr<gfx::SurfaceControl::Surface> parent_surface_;
  522. absl::optional<gfx::SurfaceControl::Transaction> hwui_transaction_;
  523. GetSurfaceControlFn get_surface_control_ = nullptr;
  524. THREAD_CHECKER(render_thread_checker_);
  525. THREAD_CHECKER(gpu_thread_checker_);
  526. };
  527. OverlayProcessorWebView::OverlayProcessorWebView(
  528. viz::DisplayCompositorMemoryAndTaskController* display_controller,
  529. viz::FrameSinkManagerImpl* frame_sink_manager)
  530. : command_buffer_id_(gpu::DisplayCompositorMemoryAndTaskControllerOnGpu::
  531. NextCommandBufferId()),
  532. render_thread_sequence_(display_controller->gpu_task_scheduler()),
  533. frame_sink_manager_(frame_sink_manager) {
  534. base::WaitableEvent event;
  535. render_thread_sequence_->ScheduleGpuTask(
  536. base::BindOnce(&OverlayProcessorWebView::CreateManagerOnRT,
  537. base::Unretained(this), command_buffer_id_,
  538. render_thread_sequence_->GetSequenceId(), &event),
  539. std::vector<gpu::SyncToken>());
  540. event.Wait();
  541. }
  542. OverlayProcessorWebView::~OverlayProcessorWebView() {
  543. render_thread_sequence_->ScheduleGpuTask(
  544. base::BindOnce(
  545. [](scoped_refptr<Manager> manager) {
  546. // manager leaves scope.
  547. },
  548. std::move(manager_)),
  549. std::vector<gpu::SyncToken>());
  550. }
  551. void OverlayProcessorWebView::CreateManagerOnRT(
  552. gpu::CommandBufferId command_buffer_id,
  553. gpu::SequenceId sequence_id,
  554. base::WaitableEvent* event) {
  555. manager_ = base::MakeRefCounted<Manager>(command_buffer_id, sequence_id);
  556. event->Signal();
  557. }
  558. void OverlayProcessorWebView::SetOverlaysEnabledByHWUI(bool enabled) {
  559. overlays_enabled_by_hwui_ = enabled;
  560. }
  561. void OverlayProcessorWebView::RemoveOverlays() {
  562. overlays_enabled_by_hwui_ = false;
  563. std::vector<uint64_t> ids;
  564. ids.reserve(overlays_.size());
  565. for (auto overlay : overlays_)
  566. ids.push_back(overlay.second.id);
  567. // Note, that we send it even there are no overlays, to drop reference to the
  568. // parent surface.
  569. render_thread_sequence_->ScheduleGpuTask(
  570. base::BindOnce(&Manager::RemoveOverlays, base::Unretained(manager_.get()),
  571. std::move(ids)),
  572. std::vector<gpu::SyncToken>());
  573. overlays_.clear();
  574. }
  575. absl::optional<gfx::SurfaceControl::Transaction>
  576. OverlayProcessorWebView::TakeSurfaceTransactionOnRT() {
  577. DCHECK(manager_);
  578. return manager_->TakeHWUITransaction();
  579. }
  580. void OverlayProcessorWebView::CheckOverlaySupportImpl(
  581. const viz::OverlayProcessorInterface::OutputSurfaceOverlayPlane*
  582. primary_plane,
  583. viz::OverlayCandidateList* candidates) {
  584. // If HWUI doesn't want us to overlay, we shouldn't.
  585. if (!overlays_enabled_by_hwui_)
  586. return;
  587. // We need GpuServiceImpl (one for Gpu Main Thread, not GpuServiceWebView) to
  588. // use overlays. It takes time to initialize it, so we don't block
  589. // RenderThread for it. Instead we're just polling here if it's done.
  590. if (!gpu_thread_sequence_) {
  591. viz::GpuServiceImpl* gpu_service =
  592. VizCompositorThreadRunnerWebView::GetInstance()->GetGpuService();
  593. if (!gpu_service)
  594. return;
  595. gpu_thread_sequence_ = std::make_unique<gpu::SchedulerSequence>(
  596. gpu_service->GetGpuScheduler(), gpu_service->main_runner());
  597. render_thread_sequence_->ScheduleGpuTask(
  598. base::BindOnce(&OverlayProcessorWebView::Manager::SetGpuService,
  599. base::Unretained(manager_.get()), gpu_service),
  600. std::vector<gpu::SyncToken>());
  601. }
  602. // Check candidates if they can be used with surface control.
  603. OverlayProcessorSurfaceControl::CheckOverlaySupportImpl(primary_plane,
  604. candidates);
  605. }
  606. void OverlayProcessorWebView::TakeOverlayCandidates(
  607. viz::OverlayCandidateList* candidate_list) {
  608. overlay_candidates_.swap(*candidate_list);
  609. candidate_list->clear();
  610. }
  611. void OverlayProcessorWebView::ScheduleOverlays(
  612. viz::DisplayResourceProvider* resource_provider) {
  613. DCHECK(!resource_provider_ || resource_provider_ == resource_provider_);
  614. resource_provider_ = resource_provider;
  615. DCHECK(gpu_thread_sequence_ || overlay_candidates_.empty());
  616. base::flat_set<viz::FrameSinkId> seen;
  617. for (auto& candidate : overlay_candidates_) {
  618. viz::SurfaceId surface_id =
  619. resource_provider->GetSurfaceId(candidate.resource_id);
  620. viz::FrameSinkId sink_id = surface_id.frame_sink_id();
  621. seen.insert(sink_id);
  622. auto overlay = overlays_.find(sink_id);
  623. if (overlay != overlays_.end()) {
  624. // Need to update only geometry.
  625. render_thread_sequence_->ScheduleGpuTask(
  626. base::BindOnce(&Manager::UpdateOverlayGeometry,
  627. base::Unretained(manager_.get()), overlay->second.id,
  628. candidate),
  629. std::vector<gpu::SyncToken>());
  630. // If renderer embedded new surface (i.e video player size changed) we
  631. // need to update buffer here. For all other cases it's updated in
  632. // ProcessForFrameSinkId().
  633. if (overlay->second.surface_id != surface_id) {
  634. overlay->second.surface_id = surface_id;
  635. UpdateOverlayResource(sink_id, candidate.resource_id,
  636. candidate.unclipped_uv_rect);
  637. }
  638. } else {
  639. overlay =
  640. overlays_
  641. .insert(std::make_pair(
  642. sink_id, Overlay(next_overlay_id_++, candidate.resource_id,
  643. resource_provider_->GetChildId(
  644. candidate.resource_id))))
  645. .first;
  646. overlay->second.surface_id = surface_id;
  647. overlay->second.create_sync_token =
  648. gpu::SyncToken(kOverlayProcessorNamespace, command_buffer_id_,
  649. ++sync_fence_release_);
  650. auto result = LockResource(overlay->second);
  651. candidate.mailbox = result.mailbox;
  652. render_thread_sequence_->ScheduleGpuTask(
  653. base::BindOnce(&Manager::CreateOverlay,
  654. base::Unretained(manager_.get()), overlay->second.id,
  655. candidate, std::move(result.unlock_cb),
  656. overlay->second.create_sync_token.release_count()),
  657. {result.sync_token});
  658. }
  659. }
  660. for (auto it = overlays_.begin(); it != overlays_.end();) {
  661. if (!seen.contains(it->first)) {
  662. render_thread_sequence_->ScheduleGpuTask(
  663. base::BindOnce(&Manager::RemoveOverlay,
  664. base::Unretained(manager_.get()), it->second.id),
  665. std::vector<gpu::SyncToken>());
  666. it = overlays_.erase(it);
  667. } else {
  668. ++it;
  669. }
  670. }
  671. }
  672. OverlayProcessorWebView::LockResult OverlayProcessorWebView::LockResource(
  673. Overlay& overlay) {
  674. LockResult result{};
  675. auto resource_id = overlay.resource_id;
  676. resource_lock_count_[overlay.surface_id.frame_sink_id()]++;
  677. OverlayResourceLock lock = OverlayResourceLock(
  678. static_cast<viz::DisplayResourceProviderSkia*>(resource_provider_),
  679. resource_id);
  680. result.sync_token = lock.sync_token();
  681. result.mailbox = lock.mailbox();
  682. locked_resources_.insert(std::make_pair(resource_id, std::move(lock)));
  683. auto return_cb = base::BindOnce(&OverlayProcessorWebView::ReturnResource,
  684. weak_ptr_factory_.GetWeakPtr(), resource_id,
  685. overlay.surface_id);
  686. auto return_cb_on_thread = base::BindPostTask(
  687. base::ThreadTaskRunnerHandle::Get(), std::move(return_cb));
  688. result.unlock_cb = base::ScopedClosureRunner(std::move(return_cb_on_thread));
  689. return result;
  690. }
  691. void OverlayProcessorWebView::UpdateOverlayResource(
  692. viz::FrameSinkId frame_sink_id,
  693. viz::ResourceId new_resource_id,
  694. const gfx::RectF& uv_rect) {
  695. DCHECK(resource_provider_);
  696. auto overlay = overlays_.find(frame_sink_id);
  697. DCHECK(overlay != overlays_.end());
  698. DCHECK(resource_provider_->IsOverlayCandidate(new_resource_id));
  699. if (new_resource_id != overlay->second.resource_id) {
  700. overlay->second.resource_id = new_resource_id;
  701. auto result = LockResource(overlay->second);
  702. gpu_thread_sequence_->ScheduleTask(
  703. base::BindOnce(&Manager::UpdateOverlayBuffer,
  704. base::Unretained(manager_.get()), overlay->second.id,
  705. result.mailbox, uv_rect, std::move(result.unlock_cb)),
  706. {result.sync_token, overlay->second.create_sync_token});
  707. }
  708. }
  709. void OverlayProcessorWebView::ReturnResource(viz::ResourceId resource_id,
  710. viz::SurfaceId surface_id) {
  711. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  712. // |locked_resources_| is multimap and can contain multiple locks of the same
  713. // resource_id. There is no difference between locks at this point, they all
  714. // just keeping resource locked so it's safe to remove any of them when
  715. // OverlayManager return resources. When we delete last lock resource will be
  716. // return to the client.
  717. auto it = locked_resources_.find(resource_id);
  718. DCHECK(it != locked_resources_.end());
  719. locked_resources_.erase(it);
  720. DCHECK(resource_lock_count_.contains(surface_id.frame_sink_id()));
  721. auto& count = resource_lock_count_[surface_id.frame_sink_id()];
  722. DCHECK_GT(count, 0);
  723. // When the lock count reaches kMaxBuffersInFlight, we don't send acks to the
  724. // client in the ProcessForFrameSinkId. In this case we send ack here when the
  725. // lock count drops below the threshold. Note, that because we still lock
  726. // resource and schedule buffer update, the lock count can be larger than
  727. // kMaxBuffersInFlight in certain cases, like quick overlay demotion and
  728. // promotion again.
  729. if (count == kMaxBuffersInFlight) {
  730. auto* surface =
  731. frame_sink_manager_->surface_manager()->GetSurfaceForId(surface_id);
  732. if (surface) {
  733. surface->SendAckToClient();
  734. }
  735. }
  736. if (!--count)
  737. resource_lock_count_.erase(surface_id.frame_sink_id());
  738. }
  739. void OverlayProcessorWebView::ProcessForFrameSinkId(
  740. const viz::FrameSinkId& frame_sink_id,
  741. const viz::ResolvedFrameData* frame_data) {
  742. auto it = overlays_.find(frame_sink_id);
  743. DCHECK(it != overlays_.end());
  744. auto& overlay = it->second;
  745. auto& pass = frame_data->GetRootRenderPassData();
  746. if (!pass.draw_quads().empty()) {
  747. DCHECK_EQ(pass.draw_quads().size(), 1u);
  748. auto* surface = frame_sink_manager_->surface_manager()->GetSurfaceForId(
  749. overlay.surface_id);
  750. // TODO(vasilyt): We should get this from surface aggregator after
  751. // aggregator refactoring will be finished.
  752. const auto& frame = surface->GetActiveFrame();
  753. auto* quad = viz::TextureDrawQuad::MaterialCast(
  754. frame.render_pass_list.back()->quad_list.front());
  755. DCHECK(quad->is_stream_video);
  756. auto uv_rect = gfx::BoundingRect(quad->uv_top_left, quad->uv_bottom_right);
  757. UpdateOverlayResource(frame_sink_id,
  758. pass.draw_quads().front().remapped_resources.ids[0],
  759. uv_rect);
  760. // If resource lock count reached kMaxBuffersInFlight it means we can't
  761. // schedule any more frames right away, in this case we delay sending ack to
  762. // the client and will send it in ReturnResources after OverlayManager will
  763. // process previous update.
  764. if (resource_lock_count_[frame_sink_id] < kMaxBuffersInFlight) {
  765. surface->SendAckToClient();
  766. }
  767. }
  768. }
  769. viz::SurfaceId OverlayProcessorWebView::GetOverlaySurfaceId(
  770. const viz::FrameSinkId& frame_sink_id) {
  771. auto it = overlays_.find(frame_sink_id);
  772. if (it != overlays_.end()) {
  773. return it->second.surface_id;
  774. }
  775. return viz::SurfaceId();
  776. }
  777. bool OverlayProcessorWebView::IsFrameSinkOverlayed(
  778. viz::FrameSinkId frame_sink_id) {
  779. return overlays_.contains(frame_sink_id);
  780. }
  781. OverlayProcessorWebView::ScopedSurfaceControlAvailable::
  782. ScopedSurfaceControlAvailable(OverlayProcessorWebView* processor,
  783. GetSurfaceControlFn surface_getter)
  784. : processor_(processor) {
  785. DCHECK(processor_);
  786. DCHECK(processor_->manager_);
  787. processor_->manager_->get_surface_control_ = surface_getter;
  788. }
  789. OverlayProcessorWebView::ScopedSurfaceControlAvailable::
  790. ~ScopedSurfaceControlAvailable() {
  791. processor_->manager_->get_surface_control_ = nullptr;
  792. }
  793. OverlayProcessorWebView::Overlay::Overlay(uint64_t id,
  794. viz::ResourceId resource_id,
  795. int child_id)
  796. : id(id), resource_id(resource_id), child_id(child_id) {}
  797. OverlayProcessorWebView::Overlay::Overlay(const Overlay&) = default;
  798. OverlayProcessorWebView::Overlay::~Overlay() = default;
  799. } // namespace android_webview