forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
AHardwareBuffer-based GpuMemoryBuffer implementation
AHardwareBuffer support is included on Android O and up. The NDK functions are included as of platform level 26, but Chromium currently doesn't use this as the target level, so we have to use dynamic loading to get the symbols at runtime. This is encapsulated in gfx::AndroidHardwareBufferCompat which makes it a bit easier to work with them across Android versions. The implementation adds a new ANDROID_HARDWARE_BUFFER subtype to the SharedMemoryHandle Android implementation in addition to the pre-existing ashmem support, including IPC transport via a SocketPair. It uses one end to write the native object using a NDK call, and the other end is a file descriptor sendable via usual IPC methods from which the receiver can fetch the object. BUG=761432 Cq-Include-Trybots: master.tryserver.chromium.android:android_optional_gpu_tests_rel;master.tryserver.chromium.linux:linux_optional_gpu_tests_rel;master.tryserver.chromium.mac:mac_optional_gpu_tests_rel;master.tryserver.chromium.win:win_optional_gpu_tests_rel Change-Id: I9edfa733ffccea21dd58a3940aa96cb6955c8f09 Reviewed-on: https://chromium-review.googlesource.com/680100 Commit-Queue: Klaus Weidner <klausw@chromium.org> Reviewed-by: Daniel Cheng <dcheng@chromium.org> Reviewed-by: Mark Mentovai <mark@chromium.org> Reviewed-by: Ken Rockot <rockot@chromium.org> Reviewed-by: Kenneth Russell <kbr@chromium.org> Reviewed-by: David Reveman <reveman@chromium.org> Cr-Commit-Position: refs/heads/master@{#513710}
- Loading branch information
Showing
31 changed files
with
1,272 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
// 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. | ||
|
||
#ifndef BASE_ANDROID_ANDROID_HARDWARE_BUFFER_ABI_H_ | ||
#define BASE_ANDROID_ANDROID_HARDWARE_BUFFER_ABI_H_ | ||
|
||
// Minimal binary interface definitions for AHardwareBuffer based on | ||
// include/android/hardware_buffer.h from the Android NDK for platform level | ||
// 26+. This is only intended for use from the AndroidHardwareBufferCompat | ||
// wrapper for building without NDK platform level support, it is not a | ||
// general-use header and is not complete. | ||
// | ||
// TODO(crbug.com/771171): Delete this file when third_party/android_tools/ndk/ | ||
// is updated to a version that contains the android/hardware_buffer.h file. | ||
// | ||
// Please refer to the API documentation for details: | ||
// https://developer.android.com/ndk/reference/hardware__buffer_8h.html | ||
|
||
#include <stdint.h> | ||
|
||
// Use "C" linkage to match the original header file. This isn't strictly | ||
// required since the file is not declaring global functions, but the types | ||
// should remain in the global namespace for compatibility, and it's a reminder | ||
// that forward declarations elsewhere should use "extern "C" to avoid | ||
// namespace issues. | ||
extern "C" { | ||
|
||
typedef struct AHardwareBuffer AHardwareBuffer; | ||
typedef struct ARect ARect; | ||
|
||
enum { | ||
AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM = 1, | ||
AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM = 2, | ||
AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM = 3, | ||
AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM = 4, | ||
AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT = 0x16, | ||
AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM = 0x2b, | ||
AHARDWAREBUFFER_FORMAT_BLOB = 0x21, | ||
}; | ||
|
||
enum { | ||
AHARDWAREBUFFER_USAGE_CPU_READ_NEVER = 0UL, | ||
AHARDWAREBUFFER_USAGE_CPU_READ_RARELY = 2UL, | ||
AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN = 3UL, | ||
AHARDWAREBUFFER_USAGE_CPU_READ_MASK = 0xFUL, | ||
AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER = 0UL << 4, | ||
AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY = 2UL << 4, | ||
AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN = 3UL << 4, | ||
AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK = 0xFUL << 4, | ||
AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE = 1UL << 8, | ||
AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT = 1UL << 9, | ||
AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT = 1UL << 14, | ||
AHARDWAREBUFFER_USAGE_VIDEO_ENCODE = 1UL << 16, | ||
AHARDWAREBUFFER_USAGE_SENSOR_DIRECT_DATA = 1UL << 23, | ||
AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER = 1UL << 24, | ||
}; | ||
|
||
typedef struct AHardwareBuffer_Desc { | ||
uint32_t width; | ||
uint32_t height; | ||
uint32_t layers; | ||
uint32_t format; | ||
uint64_t usage; | ||
uint32_t stride; | ||
uint32_t rfu0; | ||
uint64_t rfu1; | ||
} AHardwareBuffer_Desc; | ||
|
||
using PFAHardwareBuffer_allocate = void (*)(const AHardwareBuffer_Desc* desc, | ||
AHardwareBuffer** outBuffer); | ||
using PFAHardwareBuffer_acquire = void (*)(AHardwareBuffer* buffer); | ||
using PFAHardwareBuffer_describe = void (*)(const AHardwareBuffer* buffer, | ||
AHardwareBuffer_Desc* outDesc); | ||
using PFAHardwareBuffer_lock = int (*)(AHardwareBuffer* buffer, | ||
uint64_t usage, | ||
int32_t fence, | ||
const ARect* rect, | ||
void** outVirtualAddress); | ||
using PFAHardwareBuffer_recvHandleFromUnixSocket = | ||
int (*)(int socketFd, AHardwareBuffer** outBuffer); | ||
using PFAHardwareBuffer_release = void (*)(AHardwareBuffer* buffer); | ||
using PFAHardwareBuffer_sendHandleToUnixSocket = | ||
int (*)(const AHardwareBuffer* buffer, int socketFd); | ||
using PFAHardwareBuffer_unlock = int (*)(AHardwareBuffer* buffer, | ||
int32_t* fence); | ||
|
||
} // extern "C" | ||
|
||
#endif // BASE_ANDROID_ANDROID_HARDWARE_BUFFER_ABI_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
// 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 "base/android/android_hardware_buffer_compat.h" | ||
|
||
#include "base/android/build_info.h" | ||
#include "base/lazy_instance.h" | ||
#include "base/logging.h" | ||
|
||
#include <dlfcn.h> | ||
|
||
namespace base { | ||
|
||
namespace { | ||
|
||
static base::LazyInstance<AndroidHardwareBufferCompat>::Leaky g_compat = | ||
LAZY_INSTANCE_INITIALIZER; | ||
|
||
} // namespace | ||
|
||
AndroidHardwareBufferCompat::AndroidHardwareBufferCompat() { | ||
DCHECK(IsSupportAvailable()); | ||
|
||
// TODO(klausw): If the Chromium build requires __ANDROID_API__ >= 26 at some | ||
// point in the future, we could directly use the global functions instead of | ||
// dynamic loading. However, since this would be incompatible with pre-Oreo | ||
// devices, this is unlikely to happen in the foreseeable future, so just | ||
// unconditionally use dynamic loading. | ||
|
||
// cf. base/android/linker/modern_linker_jni.cc | ||
void* main_dl_handle = dlopen(nullptr, RTLD_NOW); | ||
|
||
*reinterpret_cast<void**>(&allocate_) = | ||
dlsym(main_dl_handle, "AHardwareBuffer_allocate"); | ||
DCHECK(allocate_); | ||
|
||
*reinterpret_cast<void**>(&acquire_) = | ||
dlsym(main_dl_handle, "AHardwareBuffer_acquire"); | ||
DCHECK(acquire_); | ||
|
||
*reinterpret_cast<void**>(&describe_) = | ||
dlsym(main_dl_handle, "AHardwareBuffer_describe"); | ||
DCHECK(describe_); | ||
|
||
*reinterpret_cast<void**>(&lock_) = | ||
dlsym(main_dl_handle, "AHardwareBuffer_lock"); | ||
DCHECK(lock_); | ||
|
||
*reinterpret_cast<void**>(&recv_handle_) = | ||
dlsym(main_dl_handle, "AHardwareBuffer_recvHandleFromUnixSocket"); | ||
DCHECK(recv_handle_); | ||
|
||
*reinterpret_cast<void**>(&release_) = | ||
dlsym(main_dl_handle, "AHardwareBuffer_release"); | ||
DCHECK(release_); | ||
|
||
*reinterpret_cast<void**>(&send_handle_) = | ||
dlsym(main_dl_handle, "AHardwareBuffer_sendHandleToUnixSocket"); | ||
DCHECK(send_handle_); | ||
|
||
*reinterpret_cast<void**>(&unlock_) = | ||
dlsym(main_dl_handle, "AHardwareBuffer_unlock"); | ||
DCHECK(unlock_); | ||
} | ||
|
||
// static | ||
bool AndroidHardwareBufferCompat::IsSupportAvailable() { | ||
return base::android::BuildInfo::GetInstance()->sdk_int() >= | ||
base::android::SDK_VERSION_OREO; | ||
} | ||
|
||
// static | ||
AndroidHardwareBufferCompat AndroidHardwareBufferCompat::GetInstance() { | ||
return g_compat.Get(); | ||
} | ||
|
||
void AndroidHardwareBufferCompat::Allocate(const AHardwareBuffer_Desc* desc, | ||
AHardwareBuffer** out_buffer) { | ||
DCHECK(IsSupportAvailable()); | ||
allocate_(desc, out_buffer); | ||
} | ||
|
||
void AndroidHardwareBufferCompat::Acquire(AHardwareBuffer* buffer) { | ||
DCHECK(IsSupportAvailable()); | ||
acquire_(buffer); | ||
} | ||
|
||
void AndroidHardwareBufferCompat::Describe(const AHardwareBuffer* buffer, | ||
AHardwareBuffer_Desc* out_desc) { | ||
DCHECK(IsSupportAvailable()); | ||
describe_(buffer, out_desc); | ||
} | ||
|
||
int AndroidHardwareBufferCompat::Lock(AHardwareBuffer* buffer, | ||
uint64_t usage, | ||
int32_t fence, | ||
const ARect* rect, | ||
void** out_virtual_address) { | ||
DCHECK(IsSupportAvailable()); | ||
return lock_(buffer, usage, fence, rect, out_virtual_address); | ||
} | ||
|
||
int AndroidHardwareBufferCompat::RecvHandleFromUnixSocket( | ||
int socket_fd, | ||
AHardwareBuffer** out_buffer) { | ||
DCHECK(IsSupportAvailable()); | ||
return recv_handle_(socket_fd, out_buffer); | ||
} | ||
|
||
void AndroidHardwareBufferCompat::Release(AHardwareBuffer* buffer) { | ||
DCHECK(IsSupportAvailable()); | ||
release_(buffer); | ||
} | ||
|
||
int AndroidHardwareBufferCompat::SendHandleToUnixSocket( | ||
const AHardwareBuffer* buffer, | ||
int socket_fd) { | ||
DCHECK(IsSupportAvailable()); | ||
return send_handle_(buffer, socket_fd); | ||
} | ||
|
||
int AndroidHardwareBufferCompat::Unlock(AHardwareBuffer* buffer, | ||
int32_t* fence) { | ||
DCHECK(IsSupportAvailable()); | ||
return unlock_(buffer, fence); | ||
} | ||
|
||
} // namespace base |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
// 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. | ||
|
||
#ifndef BASE_ANDROID_ANDROID_HARDWARE_BUFFER_COMPAT_H_ | ||
#define BASE_ANDROID_ANDROID_HARDWARE_BUFFER_COMPAT_H_ | ||
|
||
#include "base/android/android_hardware_buffer_abi.h" | ||
#include "base/base_export.h" | ||
#include "base/lazy_instance.h" | ||
|
||
namespace base { | ||
|
||
// This class provides runtime support for working with AHardwareBuffer objects | ||
// on Android O systems without requiring building for the Android O NDK level. | ||
// Don't call GetInstance() unless IsSupportAvailable() returns true. | ||
class BASE_EXPORT AndroidHardwareBufferCompat { | ||
public: | ||
static bool IsSupportAvailable(); | ||
static AndroidHardwareBufferCompat GetInstance(); | ||
|
||
void Allocate(const AHardwareBuffer_Desc* desc, AHardwareBuffer** outBuffer); | ||
void Acquire(AHardwareBuffer* buffer); | ||
void Describe(const AHardwareBuffer* buffer, AHardwareBuffer_Desc* outDesc); | ||
int Lock(AHardwareBuffer* buffer, | ||
uint64_t usage, | ||
int32_t fence, | ||
const ARect* rect, | ||
void** out_virtual_address); | ||
int RecvHandleFromUnixSocket(int socketFd, AHardwareBuffer** outBuffer); | ||
void Release(AHardwareBuffer* buffer); | ||
int SendHandleToUnixSocket(const AHardwareBuffer* buffer, int socketFd); | ||
int Unlock(AHardwareBuffer* buffer, int32_t* fence); | ||
|
||
private: | ||
friend struct base::LazyInstanceTraitsBase<AndroidHardwareBufferCompat>; | ||
AndroidHardwareBufferCompat(); | ||
|
||
PFAHardwareBuffer_allocate allocate_; | ||
PFAHardwareBuffer_acquire acquire_; | ||
PFAHardwareBuffer_describe describe_; | ||
PFAHardwareBuffer_lock lock_; | ||
PFAHardwareBuffer_recvHandleFromUnixSocket recv_handle_; | ||
PFAHardwareBuffer_release release_; | ||
PFAHardwareBuffer_sendHandleToUnixSocket send_handle_; | ||
PFAHardwareBuffer_unlock unlock_; | ||
}; | ||
|
||
} // namespace base | ||
|
||
#endif // BASE_ANDROID_ANDROID_HARDWARE_BUFFER_COMPAT_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.