blob: 1141d5fb190afd7abf54c79f2489da03ddada4a8 [file] [log] [blame]
// Copyright 2017 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/gl/gl_fence_android_native_fence_sync.h"
#include <sync/sync.h>
#include "base/files/scoped_file.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/time/time.h"
#include "ui/gfx/gpu_fence_handle.h"
#include "ui/gl/gl_surface_egl.h"
#if defined(OS_POSIX) || defined(OS_FUCHSIA)
#include <unistd.h>
#include "base/posix/eintr_wrapper.h"
#endif
namespace gl {
GLFenceAndroidNativeFenceSync::GLFenceAndroidNativeFenceSync() {}
GLFenceAndroidNativeFenceSync::~GLFenceAndroidNativeFenceSync() {}
// static
std::unique_ptr<GLFenceAndroidNativeFenceSync>
GLFenceAndroidNativeFenceSync::CreateInternal(EGLenum type, EGLint* attribs) {
DCHECK(GLSurfaceEGL::IsAndroidNativeFenceSyncSupported());
// Can't use MakeUnique, the no-args constructor is private.
auto fence = base::WrapUnique(new GLFenceAndroidNativeFenceSync());
if (!fence->InitializeInternal(type, attribs))
return nullptr;
return fence;
}
// static
std::unique_ptr<GLFenceAndroidNativeFenceSync>
GLFenceAndroidNativeFenceSync::CreateForGpuFence() {
return CreateInternal(EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
}
// static
std::unique_ptr<GLFenceAndroidNativeFenceSync>
GLFenceAndroidNativeFenceSync::CreateFromGpuFence(
const gfx::GpuFence& gpu_fence) {
gfx::GpuFenceHandle handle =
gfx::CloneHandleForIPC(gpu_fence.GetGpuFenceHandle());
DCHECK_GE(handle.native_fd.fd, 0);
EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, handle.native_fd.fd,
EGL_NONE};
return CreateInternal(EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
}
std::unique_ptr<gfx::GpuFence> GLFenceAndroidNativeFenceSync::GetGpuFence() {
DCHECK(GLSurfaceEGL::IsAndroidNativeFenceSyncSupported());
EGLint sync_fd = eglDupNativeFenceFDANDROID(display_, sync_);
if (sync_fd < 0)
return nullptr;
gfx::GpuFenceHandle handle;
handle.type = gfx::GpuFenceHandleType::kAndroidNativeFenceSync;
handle.native_fd = base::FileDescriptor(sync_fd, /*auto_close=*/true);
return std::make_unique<gfx::GpuFence>(handle);
}
base::TimeTicks GLFenceAndroidNativeFenceSync::GetStatusChangeTime() {
EGLint sync_fd = eglDupNativeFenceFDANDROID(display_, sync_);
if (sync_fd < 0)
return base::TimeTicks();
base::ScopedFD scoped_fd(sync_fd);
struct sync_fence_info_data* info;
info = sync_fence_info(scoped_fd.get());
if (!info)
return base::TimeTicks();
struct sync_pt_info* pt_info = nullptr;
pt_info = sync_pt_info(info, pt_info);
if (!pt_info)
return base::TimeTicks();
base::TimeTicks t = base::TimeTicks() +
base::TimeDelta::FromNanoseconds(pt_info->timestamp_ns);
if (sync_pt_info(info, pt_info)) {
// It is possible that multiple sync_pt_info could be extracted from
// sync_fence_info_data. We currently only handle one.
DLOG(WARNING) << "Ambiguous status change time. More than one result "
"could be extracted";
return base::TimeTicks();
}
sync_fence_info_free(info);
return t;
}
} // namespace gl