2020-07-02 16:43:19 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
#ifndef MOZILLA_LAYERS_ANDROID_HARDWARE_BUFFER
|
|
|
|
#define MOZILLA_LAYERS_ANDROID_HARDWARE_BUFFER
|
|
|
|
|
|
|
|
#include <android/hardware_buffer.h>
|
2020-08-24 12:34:51 +03:00
|
|
|
#include <atomic>
|
|
|
|
#include <unordered_map>
|
2020-07-02 16:43:19 +03:00
|
|
|
|
|
|
|
#include "mozilla/layers/TextureClient.h"
|
|
|
|
#include "mozilla/gfx/Types.h"
|
|
|
|
#include "mozilla/gfx/2D.h"
|
2020-08-24 12:34:51 +03:00
|
|
|
#include "mozilla/Monitor.h"
|
2020-07-02 16:43:19 +03:00
|
|
|
#include "mozilla/RefPtr.h"
|
|
|
|
#include "mozilla/StaticPtr.h"
|
2020-08-24 12:34:51 +03:00
|
|
|
#include "mozilla/ThreadSafeWeakPtr.h"
|
2020-07-02 16:43:19 +03:00
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
namespace layers {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* AndroidHardwareBufferApi provides apis for managing AHardwareBuffer.
|
|
|
|
* The apis are supported since Android O(APIVersion 26).
|
|
|
|
*/
|
|
|
|
class AndroidHardwareBufferApi final {
|
|
|
|
public:
|
|
|
|
static void Init();
|
|
|
|
static void Shutdown();
|
|
|
|
|
|
|
|
static AndroidHardwareBufferApi* Get() { return sInstance; }
|
|
|
|
|
|
|
|
void Allocate(const AHardwareBuffer_Desc* aDesc,
|
|
|
|
AHardwareBuffer** aOutBuffer);
|
|
|
|
void Acquire(AHardwareBuffer* aBuffer);
|
|
|
|
void Release(AHardwareBuffer* aBuffer);
|
|
|
|
void Describe(const AHardwareBuffer* aBuffer, AHardwareBuffer_Desc* aOutDesc);
|
|
|
|
int Lock(AHardwareBuffer* aBuffer, uint64_t aUsage, int32_t aFence,
|
|
|
|
const ARect* aRect, void** aOutVirtualAddress);
|
|
|
|
int Unlock(AHardwareBuffer* aBuffer, int32_t* aFence);
|
|
|
|
int SendHandleToUnixSocket(const AHardwareBuffer* aBuffer, int aSocketFd);
|
|
|
|
int RecvHandleFromUnixSocket(int aSocketFd, AHardwareBuffer** aOutBuffer);
|
|
|
|
|
|
|
|
private:
|
|
|
|
AndroidHardwareBufferApi();
|
|
|
|
bool Load();
|
|
|
|
|
|
|
|
using _AHardwareBuffer_allocate = int (*)(const AHardwareBuffer_Desc* desc,
|
|
|
|
AHardwareBuffer** outBuffer);
|
|
|
|
using _AHardwareBuffer_acquire = void (*)(AHardwareBuffer* buffer);
|
|
|
|
using _AHardwareBuffer_release = void (*)(AHardwareBuffer* buffer);
|
|
|
|
using _AHardwareBuffer_describe = void (*)(const AHardwareBuffer* buffer,
|
|
|
|
AHardwareBuffer_Desc* outDesc);
|
|
|
|
using _AHardwareBuffer_lock = int (*)(AHardwareBuffer* buffer, uint64_t usage,
|
|
|
|
int32_t fence, const ARect* rect,
|
|
|
|
void** outVirtualAddress);
|
|
|
|
using _AHardwareBuffer_unlock = int (*)(AHardwareBuffer* buffer,
|
|
|
|
int32_t* fence);
|
|
|
|
using _AHardwareBuffer_sendHandleToUnixSocket =
|
|
|
|
int (*)(const AHardwareBuffer* buffer, int socketFd);
|
|
|
|
using _AHardwareBuffer_recvHandleFromUnixSocket =
|
|
|
|
int (*)(int socketFd, AHardwareBuffer** outBuffer);
|
|
|
|
|
|
|
|
_AHardwareBuffer_allocate mAHardwareBuffer_allocate = nullptr;
|
|
|
|
_AHardwareBuffer_acquire mAHardwareBuffer_acquire = nullptr;
|
|
|
|
_AHardwareBuffer_release mAHardwareBuffer_release = nullptr;
|
|
|
|
_AHardwareBuffer_describe mAHardwareBuffer_describe = nullptr;
|
|
|
|
_AHardwareBuffer_lock mAHardwareBuffer_lock = nullptr;
|
|
|
|
_AHardwareBuffer_unlock mAHardwareBuffer_unlock = nullptr;
|
|
|
|
_AHardwareBuffer_sendHandleToUnixSocket
|
|
|
|
mAHardwareBuffer_sendHandleToUnixSocket = nullptr;
|
|
|
|
_AHardwareBuffer_recvHandleFromUnixSocket
|
|
|
|
mAHardwareBuffer_recvHandleFromUnixSocket = nullptr;
|
|
|
|
|
|
|
|
static StaticAutoPtr<AndroidHardwareBufferApi> sInstance;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* AndroidHardwareBuffer is a wrapper of AHardwareBuffer. AHardwareBuffer wraps
|
|
|
|
* android GraphicBuffer. It is supported since Android O(APIVersion 26).
|
2020-08-24 12:34:51 +03:00
|
|
|
* The manager is mainly used for release fences delivery from
|
|
|
|
* host side to client side.
|
2020-07-02 16:43:19 +03:00
|
|
|
*/
|
2020-08-24 12:34:51 +03:00
|
|
|
class AndroidHardwareBuffer
|
|
|
|
: public SupportsThreadSafeWeakPtr<AndroidHardwareBuffer> {
|
2020-07-02 16:43:19 +03:00
|
|
|
public:
|
2020-08-24 12:34:51 +03:00
|
|
|
MOZ_DECLARE_REFCOUNTED_TYPENAME(AndroidHardwareBuffer)
|
2020-07-02 16:43:19 +03:00
|
|
|
|
|
|
|
static already_AddRefed<AndroidHardwareBuffer> Create(
|
|
|
|
gfx::IntSize aSize, gfx::SurfaceFormat aFormat);
|
|
|
|
|
2020-08-24 12:34:51 +03:00
|
|
|
// This function creates AndroidHardwareBuffer from FileDescriptor.
|
|
|
|
// The fuction is expected to be called on host side. Client side creates
|
|
|
|
// the FileDescriptor and it is delivered to host side via ipc.
|
2020-07-02 16:43:19 +03:00
|
|
|
static already_AddRefed<AndroidHardwareBuffer> FromFileDescriptor(
|
2020-08-24 12:34:51 +03:00
|
|
|
ipc::FileDescriptor& aFileDescriptor, uint64_t aBufferId,
|
|
|
|
gfx::IntSize aSize, gfx::SurfaceFormat aFormat);
|
|
|
|
|
|
|
|
virtual ~AndroidHardwareBuffer();
|
2020-07-02 16:43:19 +03:00
|
|
|
|
2020-08-24 12:34:51 +03:00
|
|
|
int Lock(uint64_t aUsage, const ARect* aRect, void** aOutVirtualAddress);
|
2020-10-13 03:31:30 +03:00
|
|
|
int Unlock();
|
2020-07-02 16:43:19 +03:00
|
|
|
|
|
|
|
int SendHandleToUnixSocket(int aSocketFd);
|
|
|
|
|
|
|
|
AHardwareBuffer* GetNativeBuffer() const { return mNativeBuffer; }
|
|
|
|
|
2020-08-24 12:34:51 +03:00
|
|
|
// Waits until the buffer is no longer used by host side.
|
|
|
|
// Returns false when wait is aborted by timeout.
|
|
|
|
bool WaitForBufferOwnership();
|
|
|
|
|
|
|
|
// Returns true when the buffer is still in use by host side.
|
|
|
|
bool IsWaitingForBufferOwnership();
|
|
|
|
|
|
|
|
void SetAcquireFence(ipc::FileDescriptor&& aFenceFd);
|
|
|
|
|
|
|
|
void SetReleaseFence(ipc::FileDescriptor&& aFenceFd);
|
|
|
|
|
|
|
|
ipc::FileDescriptor GetAndResetReleaseFence();
|
|
|
|
|
|
|
|
ipc::FileDescriptor GetAndResetAcquireFence();
|
|
|
|
|
|
|
|
ipc::FileDescriptor GetAcquireFence();
|
|
|
|
|
2020-09-28 23:29:50 +03:00
|
|
|
RefPtr<TextureClient> GetTextureClientOfSharedSurfaceTextureData(
|
|
|
|
const layers::SurfaceDescriptor& aDesc, const gfx::SurfaceFormat aFormat,
|
|
|
|
const gfx::IntSize& aSize, const TextureFlags aFlags,
|
|
|
|
LayersIPCChannel* aAllocator);
|
|
|
|
|
2020-07-02 16:43:19 +03:00
|
|
|
const gfx::IntSize mSize;
|
|
|
|
const uint32_t mStride;
|
|
|
|
const gfx::SurfaceFormat mFormat;
|
2020-08-24 12:34:51 +03:00
|
|
|
const uint64_t mId;
|
2020-07-02 16:43:19 +03:00
|
|
|
|
|
|
|
protected:
|
|
|
|
AndroidHardwareBuffer(AHardwareBuffer* aNativeBuffer, gfx::IntSize aSize,
|
2020-08-24 12:34:51 +03:00
|
|
|
uint32_t aStride, gfx::SurfaceFormat aFormat,
|
|
|
|
uint64_t aId);
|
|
|
|
|
|
|
|
void SetLastFwdTransactionId(uint64_t aFwdTransactionId,
|
|
|
|
bool aUsesImageBridge,
|
|
|
|
const MonitorAutoLock& aAutoLock);
|
|
|
|
|
|
|
|
uint64_t GetLastFwdTransactionId(const MonitorAutoLock& aAutoLock);
|
|
|
|
|
|
|
|
void SetReleaseFence(ipc::FileDescriptor&& aFenceFd,
|
|
|
|
const MonitorAutoLock& aAutoLock);
|
|
|
|
|
|
|
|
struct FwdTransactionId {
|
|
|
|
FwdTransactionId(uint64_t aFwdTransactionId, bool aUsesImageBridge)
|
|
|
|
: mId(aFwdTransactionId), mUsesImageBridge(aUsesImageBridge) {}
|
|
|
|
uint64_t mId;
|
|
|
|
bool mUsesImageBridge;
|
|
|
|
};
|
2020-07-02 16:43:19 +03:00
|
|
|
|
|
|
|
AHardwareBuffer* mNativeBuffer;
|
2020-08-24 12:34:51 +03:00
|
|
|
|
|
|
|
// When true, AndroidHardwareBuffer is registered to
|
|
|
|
// AndroidHardwareBufferManager.
|
|
|
|
bool mIsRegistered;
|
|
|
|
|
|
|
|
// protected by AndroidHardwareBufferManager::mMonitor
|
|
|
|
|
|
|
|
Maybe<FwdTransactionId> mTransactionId;
|
|
|
|
|
|
|
|
// FileDescriptor of release fence.
|
|
|
|
// Release fence is a fence that is used for waiting until usage/composite of
|
|
|
|
// AHardwareBuffer is ended. The fence is delivered via ImageBridge.
|
|
|
|
ipc::FileDescriptor mReleaseFenceFd;
|
|
|
|
|
|
|
|
// FileDescriptor of acquire fence.
|
|
|
|
// Acquire fence is a fence that is used for waiting until rendering to
|
|
|
|
// its AHardwareBuffer is completed.
|
|
|
|
ipc::FileDescriptor mAcquireFenceFd;
|
|
|
|
|
2020-09-28 23:29:50 +03:00
|
|
|
// Only TextureClient of SharedSurfaceTextureData could be here.
|
|
|
|
// SharedSurfaceTextureData does not own AndroidHardwareBuffer,
|
|
|
|
// then it does not affect to a lifetime of AndroidHardwareBuffer.
|
|
|
|
// It is used for reducing SharedSurfaceTextureData re-creation to
|
|
|
|
// avoid re-allocating file descriptor by
|
|
|
|
// SharedSurfaceTextureData::Serialize().
|
|
|
|
RefPtr<TextureClient> mTextureClientOfSharedSurfaceTextureData;
|
|
|
|
|
2020-08-24 12:34:51 +03:00
|
|
|
static uint64_t GetNextId();
|
|
|
|
|
|
|
|
friend class AndroidHardwareBufferManager;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* AndroidHardwareBufferManager manages AndroidHardwareBuffers that is
|
|
|
|
* allocated by client side.
|
|
|
|
* Host side only uses mMonitor for thread safety of AndroidHardwareBuffer.
|
|
|
|
*/
|
|
|
|
class AndroidHardwareBufferManager {
|
|
|
|
public:
|
|
|
|
static void Init();
|
|
|
|
static void Shutdown();
|
|
|
|
|
|
|
|
AndroidHardwareBufferManager();
|
|
|
|
|
|
|
|
static AndroidHardwareBufferManager* Get() { return sInstance; }
|
|
|
|
|
|
|
|
void Register(RefPtr<AndroidHardwareBuffer> aBuffer);
|
|
|
|
|
|
|
|
void Unregister(AndroidHardwareBuffer* aBuffer);
|
|
|
|
|
|
|
|
already_AddRefed<AndroidHardwareBuffer> GetBuffer(uint64_t aBufferId);
|
|
|
|
|
|
|
|
bool WaitForBufferOwnership(AndroidHardwareBuffer* aBuffer);
|
|
|
|
|
|
|
|
bool IsWaitingForBufferOwnership(AndroidHardwareBuffer* aBuffer);
|
|
|
|
|
|
|
|
void HoldUntilNotifyNotUsed(uint64_t aBufferId, uint64_t aFwdTransactionId,
|
|
|
|
bool aUsesImageBridge);
|
|
|
|
|
|
|
|
void NotifyNotUsed(ipc::FileDescriptor&& aFenceFd, uint64_t aBufferId,
|
|
|
|
uint64_t aTransactionId, bool aUsesImageBridge);
|
|
|
|
|
|
|
|
Monitor& GetMonitor() { return mMonitor; }
|
|
|
|
|
|
|
|
private:
|
2022-03-16 21:47:08 +03:00
|
|
|
Monitor mMonitor MOZ_UNANNOTATED;
|
2020-08-24 12:34:51 +03:00
|
|
|
std::unordered_map<uint64_t, ThreadSafeWeakPtr<AndroidHardwareBuffer>>
|
|
|
|
mBuffers;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Hold AndroidHardwareBuffers that are used by host side via
|
|
|
|
* CompositorBridgeChild and ImageBridgeChild until end of their usages
|
|
|
|
* on host side.
|
|
|
|
*/
|
|
|
|
std::unordered_map<uint64_t, RefPtr<AndroidHardwareBuffer>>
|
|
|
|
mWaitingNotifyNotUsed;
|
|
|
|
|
|
|
|
static StaticAutoPtr<AndroidHardwareBufferManager> sInstance;
|
2020-07-02 16:43:19 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace layers
|
|
|
|
} // namespace mozilla
|
|
|
|
|
|
|
|
#endif
|