gl_surface_egl_surface_control.cc 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784
  1. // Copyright 2018 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 "ui/gl/gl_surface_egl_surface_control.h"
  5. #include <utility>
  6. #include "base/android/android_hardware_buffer_compat.h"
  7. #include "base/android/build_info.h"
  8. #include "base/android/scoped_hardware_buffer_fence_sync.h"
  9. #include "base/bind.h"
  10. #include "base/posix/eintr_wrapper.h"
  11. #include "base/strings/strcat.h"
  12. #include "base/threading/thread_task_runner_handle.h"
  13. #include "base/trace_event/trace_event.h"
  14. #include "cc/base/math_util.h"
  15. #include "ui/gfx/geometry/rect_conversions.h"
  16. #include "ui/gfx/overlay_transform_utils.h"
  17. #include "ui/gl/egl_util.h"
  18. #include "ui/gl/gl_context.h"
  19. #include "ui/gl/gl_features.h"
  20. #include "ui/gl/gl_fence_android_native_fence_sync.h"
  21. #include "ui/gl/gl_image_ahardwarebuffer.h"
  22. #include "ui/gl/gl_utils.h"
  23. namespace gl {
  24. namespace {
  25. constexpr char kRootSurfaceName[] = "ChromeNativeWindowSurface";
  26. constexpr char kChildSurfaceName[] = "ChromeChildSurface";
  27. gfx::Size GetBufferSize(const AHardwareBuffer* buffer) {
  28. AHardwareBuffer_Desc desc;
  29. base::AndroidHardwareBufferCompat::GetInstance().Describe(buffer, &desc);
  30. return gfx::Size(desc.width, desc.height);
  31. }
  32. std::string BuildSurfaceName(const char* suffix) {
  33. return base::StrCat(
  34. {base::android::BuildInfo::GetInstance()->package_name(), "/", suffix});
  35. }
  36. base::TimeTicks GetSignalTime(const base::ScopedFD& fence) {
  37. if (!fence.is_valid())
  38. return base::TimeTicks();
  39. base::TimeTicks signal_time;
  40. auto status = gfx::GpuFence::GetStatusChangeTime(fence.get(), &signal_time);
  41. if (status != gfx::GpuFence::kSignaled)
  42. return base::TimeTicks();
  43. return signal_time;
  44. }
  45. } // namespace
  46. GLSurfaceEGLSurfaceControl::GLSurfaceEGLSurfaceControl(
  47. GLDisplayEGL* display,
  48. ANativeWindow* window,
  49. scoped_refptr<base::SingleThreadTaskRunner> task_runner)
  50. : GLSurfaceEGL(display),
  51. root_surface_name_(BuildSurfaceName(kRootSurfaceName)),
  52. child_surface_name_(BuildSurfaceName(kChildSurfaceName)),
  53. window_rect_(0,
  54. 0,
  55. ANativeWindow_getWidth(window),
  56. ANativeWindow_getHeight(window)),
  57. root_surface_(
  58. new gfx::SurfaceControl::Surface(window, root_surface_name_.c_str())),
  59. transaction_ack_timeout_manager_(task_runner),
  60. gpu_task_runner_(std::move(task_runner)),
  61. use_target_deadline_(features::IsAndroidFrameDeadlineEnabled()),
  62. using_on_commit_callback_(!use_target_deadline_ &&
  63. gfx::SurfaceControl::SupportsOnCommit()) {}
  64. GLSurfaceEGLSurfaceControl::~GLSurfaceEGLSurfaceControl() {
  65. Destroy();
  66. }
  67. int GLSurfaceEGLSurfaceControl::GetBufferCount() const {
  68. // Triple buffering to match framework's BufferQueue.
  69. return 3;
  70. }
  71. bool GLSurfaceEGLSurfaceControl::Initialize(GLSurfaceFormat format) {
  72. if (!root_surface_->surface())
  73. return false;
  74. format_ = format;
  75. // Surfaceless is always disabled on Android so we create a 1x1 pbuffer
  76. // surface.
  77. if (!offscreen_surface_) {
  78. if (!display_->GetDisplay()) {
  79. LOG(ERROR) << "Trying to create surface with invalid display.";
  80. return false;
  81. }
  82. EGLint pbuffer_attribs[] = {
  83. EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE,
  84. };
  85. offscreen_surface_ = eglCreatePbufferSurface(display_->GetDisplay(),
  86. GetConfig(), pbuffer_attribs);
  87. if (!offscreen_surface_) {
  88. LOG(ERROR) << "eglCreatePbufferSurface failed with error "
  89. << ui::GetLastEGLErrorString();
  90. return false;
  91. }
  92. }
  93. return true;
  94. }
  95. void GLSurfaceEGLSurfaceControl::PrepareToDestroy(bool have_context) {
  96. // Drop all transaction callbacks since its not possible to make the context
  97. // current after this point.
  98. weak_factory_.InvalidateWeakPtrs();
  99. }
  100. void GLSurfaceEGLSurfaceControl::PreserveChildSurfaceControls() {
  101. TRACE_EVENT_INSTANT0(
  102. "gpu", "GLSurfaceEGLSurfaceControl::PreserveChildSurfaceControls",
  103. TRACE_EVENT_SCOPE_THREAD);
  104. preserve_children_ = true;
  105. }
  106. void GLSurfaceEGLSurfaceControl::Destroy() {
  107. TRACE_EVENT0("gpu", "GLSurfaceEGLSurfaceControl::Destroy");
  108. // Detach all child layers to prevent leaking unless browser asked us not too.
  109. if (!preserve_children_) {
  110. gfx::SurfaceControl::Transaction transaction;
  111. for (auto& surface : surface_list_) {
  112. transaction.SetParent(*surface.surface, nullptr);
  113. }
  114. transaction.Apply();
  115. }
  116. pending_transaction_.reset();
  117. surface_list_.clear();
  118. root_surface_.reset();
  119. if (offscreen_surface_) {
  120. if (!eglDestroySurface(display_->GetDisplay(), offscreen_surface_)) {
  121. LOG(ERROR) << "eglDestroySurface failed with error "
  122. << ui::GetLastEGLErrorString();
  123. }
  124. offscreen_surface_ = nullptr;
  125. }
  126. }
  127. bool GLSurfaceEGLSurfaceControl::Resize(const gfx::Size& size,
  128. float scale_factor,
  129. const gfx::ColorSpace& color_space,
  130. bool has_alpha) {
  131. // TODO(khushalsagar): Update GLSurfaceFormat using the |color_space| above?
  132. // We don't do this for the NativeViewGLSurfaceEGL as well yet.
  133. window_rect_ = gfx::Rect(size);
  134. return true;
  135. }
  136. bool GLSurfaceEGLSurfaceControl::IsOffscreen() {
  137. return false;
  138. }
  139. gfx::SwapResult GLSurfaceEGLSurfaceControl::SwapBuffers(
  140. PresentationCallback callback) {
  141. NOTREACHED();
  142. return gfx::SwapResult::SWAP_FAILED;
  143. }
  144. gfx::SwapResult GLSurfaceEGLSurfaceControl::CommitOverlayPlanes(
  145. PresentationCallback callback) {
  146. NOTREACHED();
  147. return gfx::SwapResult::SWAP_FAILED;
  148. }
  149. gfx::SwapResult GLSurfaceEGLSurfaceControl::PostSubBuffer(
  150. int x,
  151. int y,
  152. int width,
  153. int height,
  154. PresentationCallback callback) {
  155. NOTREACHED();
  156. return gfx::SwapResult::SWAP_FAILED;
  157. }
  158. void GLSurfaceEGLSurfaceControl::SwapBuffersAsync(
  159. SwapCompletionCallback completion_callback,
  160. PresentationCallback presentation_callback) {
  161. CommitPendingTransaction(window_rect_, std::move(completion_callback),
  162. std::move(presentation_callback));
  163. }
  164. void GLSurfaceEGLSurfaceControl::CommitOverlayPlanesAsync(
  165. SwapCompletionCallback completion_callback,
  166. PresentationCallback presentation_callback) {
  167. CommitPendingTransaction(window_rect_, std::move(completion_callback),
  168. std::move(presentation_callback));
  169. }
  170. void GLSurfaceEGLSurfaceControl::PostSubBufferAsync(
  171. int x,
  172. int y,
  173. int width,
  174. int height,
  175. SwapCompletionCallback completion_callback,
  176. PresentationCallback presentation_callback) {
  177. CommitPendingTransaction(gfx::Rect(x, y, width, height),
  178. std::move(completion_callback),
  179. std::move(presentation_callback));
  180. }
  181. void GLSurfaceEGLSurfaceControl::CommitPendingTransaction(
  182. const gfx::Rect& damage_rect,
  183. SwapCompletionCallback completion_callback,
  184. PresentationCallback present_callback) {
  185. // The transaction is initialized on the first ScheduleOverlayPlane call. If
  186. // we don't have a transaction at this point, it means the scheduling the
  187. // overlay plane failed. Simply report a swap failure to lose the context and
  188. // recreate the surface.
  189. if (!pending_transaction_ || surface_lost_) {
  190. LOG(ERROR) << "CommitPendingTransaction failed because surface is lost";
  191. surface_lost_ = true;
  192. std::move(completion_callback)
  193. .Run(gfx::SwapCompletionResult(gfx::SwapResult::SWAP_FAILED));
  194. std::move(present_callback).Run(gfx::PresentationFeedback::Failure());
  195. return;
  196. }
  197. // This is to workaround an Android bug where not specifying a damage region
  198. // is assumed to mean nothing is damaged. See crbug.com/993977.
  199. for (size_t i = 0; i < pending_surfaces_count_; ++i) {
  200. const auto& surface_state = surface_list_[i];
  201. if (!surface_state.hardware_buffer)
  202. continue;
  203. pending_transaction_->SetDamageRect(
  204. *surface_state.surface,
  205. gfx::Rect(GetBufferSize(surface_state.hardware_buffer)));
  206. }
  207. // Surfaces which are present in the current frame but not in the next frame
  208. // need to be explicitly updated in order to get a release fence for them in
  209. // the next transaction.
  210. DCHECK_LE(pending_surfaces_count_, surface_list_.size());
  211. for (size_t i = pending_surfaces_count_; i < surface_list_.size(); ++i) {
  212. auto& surface_state = surface_list_[i];
  213. if (surface_state.hardware_buffer) {
  214. pending_transaction_->SetBuffer(*surface_state.surface, nullptr,
  215. base::ScopedFD());
  216. surface_state.hardware_buffer = nullptr;
  217. }
  218. if (surface_state.visibility) {
  219. pending_transaction_->SetVisibility(*surface_state.surface, false);
  220. surface_state.visibility = false;
  221. }
  222. }
  223. // TODO(khushalsagar): Consider using the SetDamageRect API for partial
  224. // invalidations. Note that the damage rect set should be in the space in
  225. // which the content is rendered (including the pre-transform). See
  226. // crbug.com/988857 for details.
  227. // Release resources for the current frame once the next frame is acked.
  228. ResourceRefs resources_to_release;
  229. resources_to_release.swap(current_frame_resources_);
  230. current_frame_resources_.clear();
  231. // Track resources to be owned by the framework after this transaction.
  232. current_frame_resources_.swap(pending_frame_resources_);
  233. pending_frame_resources_.clear();
  234. gfx::SurfaceControl::Transaction::OnCompleteCb complete_cb = base::BindOnce(
  235. &GLSurfaceEGLSurfaceControl::OnTransactionAckOnGpuThread,
  236. weak_factory_.GetWeakPtr(), std::move(completion_callback),
  237. std::move(present_callback), std::move(resources_to_release),
  238. std::move(primary_plane_fences_));
  239. primary_plane_fences_.reset();
  240. pending_transaction_->SetOnCompleteCb(std::move(complete_cb),
  241. gpu_task_runner_);
  242. if (use_target_deadline_) {
  243. DCHECK(!!choreographer_vsync_id_for_next_frame_);
  244. DCHECK(gfx::SurfaceControl::SupportsSetFrameTimeline());
  245. pending_transaction_->SetFrameTimelineId(
  246. choreographer_vsync_id_for_next_frame_.value());
  247. choreographer_vsync_id_for_next_frame_.reset();
  248. }
  249. if (using_on_commit_callback_) {
  250. gfx::SurfaceControl::Transaction::OnCommitCb commit_cb = base::BindOnce(
  251. &GLSurfaceEGLSurfaceControl::OnTransactionCommittedOnGpuThread,
  252. weak_factory_.GetWeakPtr());
  253. pending_transaction_->SetOnCommitCb(std::move(commit_cb), gpu_task_runner_);
  254. }
  255. pending_surfaces_count_ = 0u;
  256. frame_rate_update_pending_ = false;
  257. if (transaction_ack_pending_ && !use_target_deadline_) {
  258. pending_transaction_queue_.push(std::move(pending_transaction_).value());
  259. } else {
  260. transaction_ack_pending_ = true;
  261. pending_transaction_->Apply();
  262. transaction_ack_timeout_manager_.ScheduleHangDetection();
  263. }
  264. pending_transaction_.reset();
  265. }
  266. gfx::Size GLSurfaceEGLSurfaceControl::GetSize() {
  267. return gfx::Size(0, 0);
  268. }
  269. bool GLSurfaceEGLSurfaceControl::OnMakeCurrent(GLContext* context) {
  270. context_ = context;
  271. return true;
  272. }
  273. bool GLSurfaceEGLSurfaceControl::ScheduleOverlayPlane(
  274. GLImage* image,
  275. std::unique_ptr<gfx::GpuFence> gpu_fence,
  276. const gfx::OverlayPlaneData& overlay_plane_data) {
  277. if (surface_lost_) {
  278. LOG(ERROR) << "ScheduleOverlayPlane failed because surface is lost";
  279. return false;
  280. }
  281. if (!pending_transaction_)
  282. pending_transaction_.emplace();
  283. bool uninitialized = false;
  284. if (pending_surfaces_count_ == surface_list_.size()) {
  285. uninitialized = true;
  286. surface_list_.emplace_back(*root_surface_, child_surface_name_);
  287. }
  288. pending_surfaces_count_++;
  289. auto& surface_state = surface_list_.at(pending_surfaces_count_ - 1);
  290. // Make the surface visible if its hidden or uninitialized..
  291. if (uninitialized || !surface_state.visibility) {
  292. pending_transaction_->SetVisibility(*surface_state.surface, true);
  293. surface_state.visibility = true;
  294. }
  295. if (uninitialized || surface_state.z_order != overlay_plane_data.z_order) {
  296. surface_state.z_order = overlay_plane_data.z_order;
  297. pending_transaction_->SetZOrder(*surface_state.surface,
  298. overlay_plane_data.z_order);
  299. }
  300. AHardwareBuffer* hardware_buffer = nullptr;
  301. base::ScopedFD fence_fd;
  302. auto scoped_hardware_buffer = image->GetAHardwareBuffer();
  303. bool is_primary_plane = false;
  304. if (scoped_hardware_buffer) {
  305. hardware_buffer = scoped_hardware_buffer->buffer();
  306. // We currently only promote the display compositor's buffer or a video
  307. // buffer to an overlay. So if this buffer is not for video then it implies
  308. // its the primary plane.
  309. is_primary_plane = !scoped_hardware_buffer->is_video();
  310. DCHECK(!is_primary_plane || !primary_plane_fences_);
  311. if (is_primary_plane) {
  312. primary_plane_fences_.emplace();
  313. primary_plane_fences_->available_fence =
  314. scoped_hardware_buffer->TakeAvailableFence();
  315. }
  316. auto* a_surface = surface_state.surface->surface();
  317. DCHECK_EQ(pending_frame_resources_.count(a_surface), 0u);
  318. auto& resource_ref = pending_frame_resources_[a_surface];
  319. resource_ref.surface = surface_state.surface;
  320. resource_ref.scoped_buffer = std::move(scoped_hardware_buffer);
  321. }
  322. surface_state.buffer_updated_in_pending_transaction =
  323. uninitialized || surface_state.hardware_buffer != hardware_buffer;
  324. if (surface_state.buffer_updated_in_pending_transaction) {
  325. surface_state.hardware_buffer = hardware_buffer;
  326. if (gpu_fence && surface_state.hardware_buffer) {
  327. auto fence_handle = gpu_fence->GetGpuFenceHandle().Clone();
  328. DCHECK(!fence_handle.is_null());
  329. fence_fd = std::move(fence_handle.owned_fd);
  330. }
  331. if (is_primary_plane) {
  332. primary_plane_fences_->ready_fence =
  333. base::ScopedFD(HANDLE_EINTR(dup(fence_fd.get())));
  334. }
  335. pending_transaction_->SetBuffer(*surface_state.surface,
  336. surface_state.hardware_buffer,
  337. std::move(fence_fd));
  338. }
  339. if (hardware_buffer) {
  340. gfx::Size buffer_size = GetBufferSize(hardware_buffer);
  341. gfx::RectF scaled_rect =
  342. gfx::ScaleRect(overlay_plane_data.crop_rect, buffer_size.width(),
  343. buffer_size.height());
  344. gfx::Rect dst = gfx::ToNearestRect(overlay_plane_data.display_bounds);
  345. gfx::Rect src = gfx::ToEnclosedRect(scaled_rect);
  346. // When the video is being scrolled offscreen DisplayCompositor will crop it
  347. // to only visible portion and adjust crop_rect accordingly. When the video
  348. // is smaller than the surface is can lead to the crop rect being less than
  349. // a pixel in size. This adjusts the crop rect size to at least 1 pixel as
  350. // we want to stretch last visible pixel line/column in this case.
  351. // Note: We will do it even if crop_rect width/height is exact 0.0f. In
  352. // reality this should never happen and there is no way to display video
  353. // with empty crop rect, so display compositor should not request this.
  354. if (src.width() == 0) {
  355. src.set_width(1);
  356. if (src.right() > buffer_size.width())
  357. src.set_x(buffer_size.width() - 1);
  358. }
  359. if (src.height() == 0) {
  360. src.set_height(1);
  361. if (src.bottom() > buffer_size.height())
  362. src.set_y(buffer_size.height() - 1);
  363. }
  364. // When display compositor rounds up destination rect to integer coordinates
  365. // it becomes slightly bigger. After we adjust source rect accordingly, it
  366. // can become larger then a buffer so we clip it here. See crbug.com/1083412
  367. src.Intersect(gfx::Rect(buffer_size));
  368. if (uninitialized || surface_state.src != src || surface_state.dst != dst ||
  369. surface_state.transform != overlay_plane_data.plane_transform) {
  370. surface_state.src = src;
  371. surface_state.dst = dst;
  372. surface_state.transform = overlay_plane_data.plane_transform;
  373. pending_transaction_->SetGeometry(*surface_state.surface, src, dst,
  374. overlay_plane_data.plane_transform);
  375. }
  376. }
  377. bool opaque = !overlay_plane_data.enable_blend;
  378. if (uninitialized || surface_state.opaque != opaque) {
  379. surface_state.opaque = opaque;
  380. pending_transaction_->SetOpaque(*surface_state.surface, opaque);
  381. }
  382. const auto& image_color_space = overlay_plane_data.color_space;
  383. if (!gfx::SurfaceControl::SupportsColorSpace(image_color_space)) {
  384. LOG(DFATAL) << "Not supported color space used with overlay : "
  385. << image_color_space.ToString();
  386. }
  387. if (uninitialized || surface_state.color_space != image_color_space) {
  388. surface_state.color_space = image_color_space;
  389. pending_transaction_->SetColorSpace(*surface_state.surface,
  390. image_color_space);
  391. }
  392. if (uninitialized ||
  393. surface_state.hdr_metadata != overlay_plane_data.hdr_metadata) {
  394. DCHECK(!overlay_plane_data.hdr_metadata ||
  395. surface_state.color_space.IsHDR());
  396. surface_state.hdr_metadata = overlay_plane_data.hdr_metadata;
  397. pending_transaction_->SetHDRMetadata(*surface_state.surface,
  398. surface_state.hdr_metadata);
  399. }
  400. if (frame_rate_update_pending_)
  401. pending_transaction_->SetFrameRate(*surface_state.surface, frame_rate_);
  402. return true;
  403. }
  404. bool GLSurfaceEGLSurfaceControl::IsSurfaceless() const {
  405. return true;
  406. }
  407. void* GLSurfaceEGLSurfaceControl::GetHandle() {
  408. return offscreen_surface_;
  409. }
  410. bool GLSurfaceEGLSurfaceControl::SupportsPostSubBuffer() {
  411. return true;
  412. }
  413. bool GLSurfaceEGLSurfaceControl::SupportsAsyncSwap() {
  414. return true;
  415. }
  416. bool GLSurfaceEGLSurfaceControl::SupportsPlaneGpuFences() const {
  417. return true;
  418. }
  419. bool GLSurfaceEGLSurfaceControl::SupportsCommitOverlayPlanes() {
  420. return true;
  421. }
  422. void GLSurfaceEGLSurfaceControl::OnTransactionAckOnGpuThread(
  423. SwapCompletionCallback completion_callback,
  424. PresentationCallback presentation_callback,
  425. ResourceRefs released_resources,
  426. absl::optional<PrimaryPlaneFences> primary_plane_fences,
  427. gfx::SurfaceControl::TransactionStats transaction_stats) {
  428. TRACE_EVENT0("gpu",
  429. "GLSurfaceEGLSurfaceControl::OnTransactionAckOnGpuThread");
  430. DCHECK(gpu_task_runner_->BelongsToCurrentThread());
  431. transaction_ack_timeout_manager_.OnTransactionAck();
  432. const bool has_context = context_->MakeCurrent(this);
  433. for (auto& surface_stat : transaction_stats.surface_stats) {
  434. auto it = released_resources.find(surface_stat.surface);
  435. // The transaction ack includes data for all surfaces updated in this
  436. // transaction. So the following condition can occur if a new surface was
  437. // added in this transaction with a buffer. It'll be included in the ack
  438. // with no fence, since its not being released and so shouldn't be in
  439. // |released_resources| either.
  440. if (it == released_resources.end()) {
  441. // TODO(vasilyt): We used to DCHECK(!surface_stat.fence.is_valid()) here,
  442. // but due to flinger behavior it doesn't hold. This seems to be a
  443. // potential fligner bug. DCHECK is useful for catching resource
  444. // life-time issues, so we should consider bringing it back when Android
  445. // side will be fixed.
  446. continue;
  447. }
  448. if (surface_stat.fence.is_valid()) {
  449. it->second.scoped_buffer->SetReadFence(std::move(surface_stat.fence),
  450. has_context);
  451. }
  452. }
  453. // Note that we may not see |surface_stats| for every resource above. This is
  454. // because we take a ref on every buffer used in a frame, even if it is not
  455. // updated in that frame. Since the transaction ack only includes surfaces
  456. // which were updated in that transaction, the surfaces with no buffer updates
  457. // won't be present in the ack.
  458. released_resources.clear();
  459. // The presentation feedback callback must run after swap completion.
  460. std::move(completion_callback)
  461. .Run(gfx::SwapCompletionResult(gfx::SwapResult::SWAP_ACK));
  462. PendingPresentationCallback pending_cb;
  463. if (primary_plane_fences) {
  464. pending_cb.available_time =
  465. GetSignalTime(primary_plane_fences->available_fence);
  466. pending_cb.ready_time = GetSignalTime(primary_plane_fences->ready_fence);
  467. }
  468. pending_cb.latch_time = transaction_stats.latch_time;
  469. pending_cb.present_fence = std::move(transaction_stats.present_fence);
  470. pending_cb.callback = std::move(presentation_callback);
  471. pending_presentation_callback_queue_.push(std::move(pending_cb));
  472. CheckPendingPresentationCallbacks();
  473. // If we don't use OnCommit, we advance transaction queue after we received
  474. // OnComplete.
  475. if (!using_on_commit_callback_)
  476. AdvanceTransactionQueue();
  477. }
  478. void GLSurfaceEGLSurfaceControl::OnTransactionCommittedOnGpuThread() {
  479. TRACE_EVENT0("gpu",
  480. "GLSurfaceEGLSurfaceControl::OnTransactionCommittedOnGpuThread");
  481. DCHECK(using_on_commit_callback_);
  482. AdvanceTransactionQueue();
  483. }
  484. void GLSurfaceEGLSurfaceControl::AdvanceTransactionQueue() {
  485. DCHECK(transaction_ack_pending_);
  486. transaction_ack_pending_ = false;
  487. if (!pending_transaction_queue_.empty()) {
  488. transaction_ack_pending_ = true;
  489. pending_transaction_queue_.front().Apply();
  490. pending_transaction_queue_.pop();
  491. transaction_ack_timeout_manager_.ScheduleHangDetection();
  492. }
  493. }
  494. void GLSurfaceEGLSurfaceControl::CheckPendingPresentationCallbacks() {
  495. TRACE_EVENT0("gpu",
  496. "GLSurfaceEGLSurfaceControl::CheckPendingPresentationCallbacks");
  497. check_pending_presentation_callback_queue_task_.Cancel();
  498. while (!pending_presentation_callback_queue_.empty()) {
  499. auto& pending_cb = pending_presentation_callback_queue_.front();
  500. base::TimeTicks signal_time;
  501. auto status = pending_cb.present_fence.is_valid()
  502. ? gfx::GpuFence::GetStatusChangeTime(
  503. pending_cb.present_fence.get(), &signal_time)
  504. : gfx::GpuFence::kInvalid;
  505. if (status == gfx::GpuFence::kNotSignaled)
  506. break;
  507. auto flags = gfx::PresentationFeedback::kHWCompletion |
  508. gfx::PresentationFeedback::kVSync;
  509. if (status == gfx::GpuFence::kInvalid) {
  510. signal_time = pending_cb.latch_time;
  511. flags = 0u;
  512. }
  513. TRACE_EVENT_INSTANT0(
  514. "gpu",
  515. "GLSurfaceEGLSurfaceControl::CheckPendingPresentationCallbacks - "
  516. "presentation_feedback",
  517. TRACE_EVENT_SCOPE_THREAD);
  518. gfx::PresentationFeedback feedback(signal_time, base::TimeDelta(), flags);
  519. feedback.available_timestamp = pending_cb.available_time;
  520. feedback.ready_timestamp = pending_cb.ready_time;
  521. feedback.latch_timestamp = pending_cb.latch_time;
  522. std::move(pending_cb.callback).Run(feedback);
  523. pending_presentation_callback_queue_.pop();
  524. }
  525. // If there are unsignaled fences and we don't have any pending transactions,
  526. // schedule a task to poll the fences again. If there is a pending transaction
  527. // already, then we'll poll when that transaction is acked.
  528. if (!pending_presentation_callback_queue_.empty() &&
  529. pending_transaction_queue_.empty()) {
  530. check_pending_presentation_callback_queue_task_.Reset(base::BindOnce(
  531. &GLSurfaceEGLSurfaceControl::CheckPendingPresentationCallbacks,
  532. weak_factory_.GetWeakPtr()));
  533. gpu_task_runner_->PostDelayedTask(
  534. FROM_HERE, check_pending_presentation_callback_queue_task_.callback(),
  535. base::Seconds(1) / 60);
  536. }
  537. }
  538. void GLSurfaceEGLSurfaceControl::SetDisplayTransform(
  539. gfx::OverlayTransform transform) {
  540. display_transform_ = transform;
  541. }
  542. gfx::SurfaceOrigin GLSurfaceEGLSurfaceControl::GetOrigin() const {
  543. // GLSurfaceEGLSurfaceControl's y-axis is flipped compare to GL - (0,0) is at
  544. // top left corner.
  545. return gfx::SurfaceOrigin::kTopLeft;
  546. }
  547. void GLSurfaceEGLSurfaceControl::SetFrameRate(float frame_rate) {
  548. if (frame_rate_ == frame_rate)
  549. return;
  550. frame_rate_ = frame_rate;
  551. frame_rate_update_pending_ = true;
  552. }
  553. void GLSurfaceEGLSurfaceControl::SetChoreographerVsyncIdForNextFrame(
  554. absl::optional<int64_t> choreographer_vsync_id) {
  555. choreographer_vsync_id_for_next_frame_ = choreographer_vsync_id;
  556. }
  557. gfx::Rect GLSurfaceEGLSurfaceControl::ApplyDisplayInverse(
  558. const gfx::Rect& input) const {
  559. gfx::Transform display_inverse = gfx::OverlayTransformToTransform(
  560. gfx::InvertOverlayTransform(display_transform_),
  561. gfx::SizeF(window_rect_.size()));
  562. return cc::MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(
  563. display_inverse, input);
  564. }
  565. const gfx::ColorSpace&
  566. GLSurfaceEGLSurfaceControl::GetNearestSupportedColorSpace(
  567. const gfx::ColorSpace& buffer_color_space) const {
  568. static constexpr gfx::ColorSpace kSRGB = gfx::ColorSpace::CreateSRGB();
  569. static constexpr gfx::ColorSpace kP3 = gfx::ColorSpace::CreateDisplayP3D65();
  570. switch (format_.GetColorSpace()) {
  571. case GLSurfaceFormat::COLOR_SPACE_UNSPECIFIED:
  572. case GLSurfaceFormat::COLOR_SPACE_SRGB:
  573. return kSRGB;
  574. case GLSurfaceFormat::COLOR_SPACE_DISPLAY_P3:
  575. return buffer_color_space == kP3 ? kP3 : kSRGB;
  576. }
  577. NOTREACHED();
  578. return kSRGB;
  579. }
  580. GLSurfaceEGLSurfaceControl::SurfaceState::SurfaceState(
  581. const gfx::SurfaceControl::Surface& parent,
  582. const std::string& name)
  583. : surface(new gfx::SurfaceControl::Surface(parent, name.c_str())) {}
  584. GLSurfaceEGLSurfaceControl::SurfaceState::SurfaceState() = default;
  585. GLSurfaceEGLSurfaceControl::SurfaceState::SurfaceState(SurfaceState&& other) =
  586. default;
  587. GLSurfaceEGLSurfaceControl::SurfaceState&
  588. GLSurfaceEGLSurfaceControl::SurfaceState::operator=(SurfaceState&& other) =
  589. default;
  590. GLSurfaceEGLSurfaceControl::SurfaceState::~SurfaceState() = default;
  591. GLSurfaceEGLSurfaceControl::ResourceRef::ResourceRef() = default;
  592. GLSurfaceEGLSurfaceControl::ResourceRef::~ResourceRef() = default;
  593. GLSurfaceEGLSurfaceControl::ResourceRef::ResourceRef(ResourceRef&& other) =
  594. default;
  595. GLSurfaceEGLSurfaceControl::ResourceRef&
  596. GLSurfaceEGLSurfaceControl::ResourceRef::operator=(ResourceRef&& other) =
  597. default;
  598. GLSurfaceEGLSurfaceControl::PendingPresentationCallback::
  599. PendingPresentationCallback() = default;
  600. GLSurfaceEGLSurfaceControl::PendingPresentationCallback::
  601. ~PendingPresentationCallback() = default;
  602. GLSurfaceEGLSurfaceControl::PendingPresentationCallback::
  603. PendingPresentationCallback(PendingPresentationCallback&& other) = default;
  604. GLSurfaceEGLSurfaceControl::PendingPresentationCallback&
  605. GLSurfaceEGLSurfaceControl::PendingPresentationCallback::operator=(
  606. PendingPresentationCallback&& other) = default;
  607. GLSurfaceEGLSurfaceControl::PrimaryPlaneFences::PrimaryPlaneFences() = default;
  608. GLSurfaceEGLSurfaceControl::PrimaryPlaneFences::~PrimaryPlaneFences() = default;
  609. GLSurfaceEGLSurfaceControl::PrimaryPlaneFences::PrimaryPlaneFences(
  610. PrimaryPlaneFences&& other) = default;
  611. GLSurfaceEGLSurfaceControl::PrimaryPlaneFences&
  612. GLSurfaceEGLSurfaceControl::PrimaryPlaneFences::operator=(
  613. PrimaryPlaneFences&& other) = default;
  614. GLSurfaceEGLSurfaceControl::TransactionAckTimeoutManager::
  615. TransactionAckTimeoutManager(
  616. scoped_refptr<base::SingleThreadTaskRunner> task_runner)
  617. : gpu_task_runner_(std::move(task_runner)) {}
  618. GLSurfaceEGLSurfaceControl::TransactionAckTimeoutManager::
  619. ~TransactionAckTimeoutManager() = default;
  620. void GLSurfaceEGLSurfaceControl::TransactionAckTimeoutManager::
  621. ScheduleHangDetection() {
  622. DCHECK(gpu_task_runner_->BelongsToCurrentThread());
  623. ++current_transaction_id_;
  624. if (!hang_detection_cb_.IsCancelled())
  625. return;
  626. constexpr int kIdleDelaySeconds = 5;
  627. hang_detection_cb_.Reset(
  628. base::BindOnce(&GLSurfaceEGLSurfaceControl::TransactionAckTimeoutManager::
  629. OnTransactionTimeout,
  630. base::Unretained(this), current_transaction_id_));
  631. gpu_task_runner_->PostDelayedTask(FROM_HERE, hang_detection_cb_.callback(),
  632. base::Seconds(kIdleDelaySeconds));
  633. }
  634. void GLSurfaceEGLSurfaceControl::TransactionAckTimeoutManager::
  635. OnTransactionAck() {
  636. // Since only one transaction is in flight at a time, an ack is for the latest
  637. // transaction.
  638. last_acked_transaction_id_ = current_transaction_id_;
  639. }
  640. void GLSurfaceEGLSurfaceControl::TransactionAckTimeoutManager::
  641. OnTransactionTimeout(TransactionId transaction_id) {
  642. hang_detection_cb_.Cancel();
  643. // If the last transaction was already acked, we do not need to schedule
  644. // any checks until a new transaction comes.
  645. if (current_transaction_id_ == last_acked_transaction_id_)
  646. return;
  647. // If more transactions have happened since the last task, schedule another
  648. // hang detection check.
  649. if (transaction_id < current_transaction_id_) {
  650. // Decrement the |current_transaction_id_| since ScheduleHangDetection()
  651. // will increment it again.
  652. --current_transaction_id_;
  653. ScheduleHangDetection();
  654. return;
  655. }
  656. LOG(ERROR) << "Transaction id " << transaction_id
  657. << " haven't received any ack from past 5 second which indicates "
  658. "it hanged";
  659. }
  660. } // namespace gl