// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "ui/gfx/gpu_fence.h" #include "base/logging.h" #include "base/notreached.h" #include "base/time/time.h" #if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) #include #endif namespace gfx { GpuFence::GpuFence(GpuFenceHandle fence_handle) : fence_handle_(std::move(fence_handle)) {} GpuFence::~GpuFence() = default; GpuFence::GpuFence(GpuFence&& other) = default; GpuFence& GpuFence::operator=(GpuFence&& other) = default; const GpuFenceHandle& GpuFence::GetGpuFenceHandle() const { return fence_handle_; } ClientGpuFence GpuFence::AsClientGpuFence() { return reinterpret_cast(this); } // static GpuFence* GpuFence::FromClientGpuFence(ClientGpuFence gpu_fence) { return reinterpret_cast(gpu_fence); } void GpuFence::Wait() { if (fence_handle_.is_null()) { return; } #if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) static const int kInfiniteSyncWaitTimeout = -1; DCHECK_GE(fence_handle_.owned_fd.get(), 0); if (sync_wait(fence_handle_.owned_fd.get(), kInfiniteSyncWaitTimeout) < 0) { LOG(FATAL) << "Failed while waiting for gpu fence fd"; } #else NOTREACHED(); #endif } // static GpuFence::FenceStatus GpuFence::GetStatusChangeTime(int fd, base::TimeTicks* time) { DCHECK_NE(fd, -1); #if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) auto info = std::unique_ptr{ sync_fence_info(fd), sync_fence_info_free}; if (!info) { LOG(ERROR) << "sync_fence_info returned null for fd : " << fd; return FenceStatus::kInvalid; } // Not signalled yet. if (info->status != 1) { return FenceStatus::kNotSignaled; } uint64_t timestamp_ns = 0u; struct sync_pt_info* pt_info = nullptr; while ((pt_info = sync_pt_info(info.get(), pt_info))) timestamp_ns = std::max(timestamp_ns, pt_info->timestamp_ns); if (timestamp_ns == 0u) { LOG(ERROR) << "No timestamp provided from sync_pt_info for fd : " << fd; return FenceStatus::kInvalid; } *time = base::TimeTicks() + base::TimeDelta::FromNanoseconds(timestamp_ns); return FenceStatus::kSignaled; #endif NOTREACHED(); return FenceStatus::kInvalid; } base::TimeTicks GpuFence::GetMaxTimestamp() const { base::TimeTicks timestamp; #if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) FenceStatus status = GetStatusChangeTime(fence_handle_.owned_fd.get(), ×tamp); DCHECK_EQ(status, FenceStatus::kSignaled); return timestamp; #endif NOTREACHED(); return timestamp; } } // namespace gfx