Klaus Weidner | e66cc7d | 2017-12-09 17:26:30 | [diff] [blame] | 1 | // Copyright 2014 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 | |
| 5 | #include "ui/gfx/gpu_fence.h" |
| 6 | |
| 7 | #include "base/logging.h" |
Hans Wennborg | 3930cf3 | 2020-06-17 16:29:52 | [diff] [blame] | 8 | #include "base/notreached.h" |
Daniele Castagna | 3bbaa0e6 | 2020-06-25 14:54:27 | [diff] [blame] | 9 | #include "base/time/time.h" |
Xiaohan Wang | d1b0e6b | 2022-01-20 21:40:20 | [diff] [blame] | 10 | #include "build/build_config.h" |
Klaus Weidner | e66cc7d | 2017-12-09 17:26:30 | [diff] [blame] | 11 | |
Xiaohan Wang | d1b0e6b | 2022-01-20 21:40:20 | [diff] [blame] | 12 | #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) |
Alexandros Frantzis | 922160ed | 2018-05-16 21:19:10 | [diff] [blame] | 13 | #include <sync/sync.h> |
| 14 | #endif |
| 15 | |
Klaus Weidner | e66cc7d | 2017-12-09 17:26:30 | [diff] [blame] | 16 | namespace gfx { |
| 17 | |
Rafael Cintron | aac6e73 | 2020-09-17 20:11:50 | [diff] [blame] | 18 | GpuFence::GpuFence(GpuFenceHandle fence_handle) |
| 19 | : fence_handle_(std::move(fence_handle)) {} |
Klaus Weidner | e66cc7d | 2017-12-09 17:26:30 | [diff] [blame] | 20 | |
| 21 | GpuFence::~GpuFence() = default; |
| 22 | |
Emircan Uysaler | 04a56b0 | 2020-10-30 18:43:29 | [diff] [blame] | 23 | GpuFence::GpuFence(GpuFence&& other) = default; |
| 24 | |
| 25 | GpuFence& GpuFence::operator=(GpuFence&& other) = default; |
| 26 | |
Rafael Cintron | aac6e73 | 2020-09-17 20:11:50 | [diff] [blame] | 27 | const GpuFenceHandle& GpuFence::GetGpuFenceHandle() const { |
| 28 | return fence_handle_; |
Klaus Weidner | e66cc7d | 2017-12-09 17:26:30 | [diff] [blame] | 29 | } |
| 30 | |
| 31 | ClientGpuFence GpuFence::AsClientGpuFence() { |
| 32 | return reinterpret_cast<ClientGpuFence>(this); |
| 33 | } |
| 34 | |
| 35 | // static |
| 36 | GpuFence* GpuFence::FromClientGpuFence(ClientGpuFence gpu_fence) { |
| 37 | return reinterpret_cast<GpuFence*>(gpu_fence); |
| 38 | } |
| 39 | |
Alexandros Frantzis | 922160ed | 2018-05-16 21:19:10 | [diff] [blame] | 40 | void GpuFence::Wait() { |
Rafael Cintron | 16519e5 | 2020-09-24 01:06:28 | [diff] [blame] | 41 | if (fence_handle_.is_null()) { |
| 42 | return; |
Alexandros Frantzis | 922160ed | 2018-05-16 21:19:10 | [diff] [blame] | 43 | } |
Rafael Cintron | 16519e5 | 2020-09-24 01:06:28 | [diff] [blame] | 44 | |
Xiaohan Wang | d1b0e6b | 2022-01-20 21:40:20 | [diff] [blame] | 45 | #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) |
Rafael Cintron | 16519e5 | 2020-09-24 01:06:28 | [diff] [blame] | 46 | static const int kInfiniteSyncWaitTimeout = -1; |
| 47 | DCHECK_GE(fence_handle_.owned_fd.get(), 0); |
| 48 | if (sync_wait(fence_handle_.owned_fd.get(), kInfiniteSyncWaitTimeout) < 0) { |
| 49 | LOG(FATAL) << "Failed while waiting for gpu fence fd"; |
| 50 | } |
| 51 | #else |
| 52 | NOTREACHED(); |
| 53 | #endif |
Alexandros Frantzis | 922160ed | 2018-05-16 21:19:10 | [diff] [blame] | 54 | } |
| 55 | |
Daniele Castagna | 3bbaa0e6 | 2020-06-25 14:54:27 | [diff] [blame] | 56 | // static |
| 57 | GpuFence::FenceStatus GpuFence::GetStatusChangeTime(int fd, |
| 58 | base::TimeTicks* time) { |
| 59 | DCHECK_NE(fd, -1); |
Xiaohan Wang | d1b0e6b | 2022-01-20 21:40:20 | [diff] [blame] | 60 | #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) |
Daniele Castagna | 3bbaa0e6 | 2020-06-25 14:54:27 | [diff] [blame] | 61 | auto info = |
| 62 | std::unique_ptr<sync_fence_info_data, void (*)(sync_fence_info_data*)>{ |
| 63 | sync_fence_info(fd), sync_fence_info_free}; |
| 64 | if (!info) { |
| 65 | LOG(ERROR) << "sync_fence_info returned null for fd : " << fd; |
| 66 | return FenceStatus::kInvalid; |
| 67 | } |
| 68 | |
| 69 | // Not signalled yet. |
| 70 | if (info->status != 1) { |
| 71 | return FenceStatus::kNotSignaled; |
| 72 | } |
| 73 | |
| 74 | uint64_t timestamp_ns = 0u; |
| 75 | struct sync_pt_info* pt_info = nullptr; |
| 76 | while ((pt_info = sync_pt_info(info.get(), pt_info))) |
| 77 | timestamp_ns = std::max(timestamp_ns, pt_info->timestamp_ns); |
| 78 | |
| 79 | if (timestamp_ns == 0u) { |
| 80 | LOG(ERROR) << "No timestamp provided from sync_pt_info for fd : " << fd; |
| 81 | return FenceStatus::kInvalid; |
| 82 | } |
Peter Kasting | e5a38ed | 2021-10-02 03:06:35 | [diff] [blame] | 83 | *time = base::TimeTicks() + base::Nanoseconds(timestamp_ns); |
Daniele Castagna | 3bbaa0e6 | 2020-06-25 14:54:27 | [diff] [blame] | 84 | return FenceStatus::kSignaled; |
| 85 | #endif |
| 86 | NOTREACHED(); |
| 87 | return FenceStatus::kInvalid; |
| 88 | } |
| 89 | |
| 90 | base::TimeTicks GpuFence::GetMaxTimestamp() const { |
| 91 | base::TimeTicks timestamp; |
Xiaohan Wang | d1b0e6b | 2022-01-20 21:40:20 | [diff] [blame] | 92 | #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) |
Rafael Cintron | aac6e73 | 2020-09-17 20:11:50 | [diff] [blame] | 93 | FenceStatus status = |
| 94 | GetStatusChangeTime(fence_handle_.owned_fd.get(), ×tamp); |
Daniele Castagna | 3bbaa0e6 | 2020-06-25 14:54:27 | [diff] [blame] | 95 | DCHECK_EQ(status, FenceStatus::kSignaled); |
| 96 | return timestamp; |
| 97 | #endif |
| 98 | NOTREACHED(); |
| 99 | return timestamp; |
| 100 | } |
| 101 | |
Klaus Weidner | e66cc7d | 2017-12-09 17:26:30 | [diff] [blame] | 102 | } // namespace gfx |