blob: 3fb3f3c6ff1102918c6a5a9a3ce78a9feaed7e7c [file] [log] [blame]
#include <private/dvr/ion_buffer.h>
#include <ui/GraphicBufferMapper.h>
#include <log/log.h>
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#include <utils/Trace.h>
#include <mutex>
namespace android {
namespace dvr {
IonBuffer::IonBuffer() : IonBuffer(nullptr, 0, 0, 0, 0, 0, 0, 0) {}
IonBuffer::IonBuffer(int width, int height, int format, int usage)
: IonBuffer() {
Alloc(width, height, format, usage);
}
IonBuffer::IonBuffer(buffer_handle_t handle, int width, int height, int stride,
int format, int usage)
: IonBuffer(handle, width, height, 1, stride, 0, format, usage) {}
IonBuffer::IonBuffer(buffer_handle_t handle, int width, int height,
int layer_count, int stride, int layer_stride, int format,
int usage)
: buffer_(nullptr) {
ALOGD_IF(TRACE,
"IonBuffer::IonBuffer: handle=%p width=%d height=%d layer_count=%d "
"stride=%d layer stride=%d format=%d usage=%d",
handle, width, height, layer_count, stride, layer_stride,
format, usage);
if (handle != 0) {
Import(handle, width, height, stride, format, usage);
}
}
IonBuffer::~IonBuffer() {
ALOGD_IF(TRACE,
"IonBuffer::~IonBuffer: handle=%p width=%d height=%d stride=%d "
"format=%d usage=%d",
handle() , width(), height(), stride(), format(), usage());
FreeHandle();
}
IonBuffer::IonBuffer(IonBuffer&& other) : IonBuffer() {
*this = std::move(other);
}
IonBuffer& IonBuffer::operator=(IonBuffer&& other) {
ALOGD_IF(TRACE, "IonBuffer::operator=: handle_=%p other.handle_=%p", handle(),
other.handle());
if (this != &other) {
buffer_ = other.buffer_;
other.FreeHandle();
}
return *this;
}
void IonBuffer::FreeHandle() {
if (buffer_.get()) {
// GraphicBuffer unregisters and cleans up the handle if needed
buffer_ = nullptr;
}
}
int IonBuffer::Alloc(int width, int height, int format, int usage) {
ALOGD_IF(TRACE, "IonBuffer::Alloc: width=%d height=%d format=%d usage=%d",
width, height, format, usage);
GraphicBufferMapper& mapper = GraphicBufferMapper::get();
buffer_ = new GraphicBuffer(width, height, format, usage);
if (mapper.registerBuffer(buffer_.get()) != OK) {
ALOGE("IonBuffer::Aloc: Failed to register buffer");
}
return 0;
}
void IonBuffer::Reset(buffer_handle_t handle, int width, int height, int stride,
int format, int usage) {
ALOGD_IF(TRACE,
"IonBuffer::Reset: handle=%p width=%d height=%d stride=%d format=%d "
"usage=%d",
handle, width, height, stride, format, usage);
Import(handle, width, height, stride, format, usage);
}
int IonBuffer::Import(buffer_handle_t handle, int width, int height, int stride,
int format, int usage) {
ATRACE_NAME("IonBuffer::Import1");
ALOGD_IF(
TRACE,
"IonBuffer::Import: handle=%p width=%d height=%d stride=%d format=%d "
"usage=%d",
handle, width, height, stride, format, usage);
FreeHandle();
GraphicBufferMapper& mapper = GraphicBufferMapper::get();
buffer_ = new GraphicBuffer(width, height, format, 1, usage,
stride, (native_handle_t*)handle, true);
if (mapper.registerBuffer(buffer_.get()) != OK) {
ALOGE("IonBuffer::Import: Failed to register cloned buffer");
return -EINVAL;
}
return 0;
}
int IonBuffer::Import(const int* fd_array, int fd_count, const int* int_array,
int int_count, int width, int height, int stride,
int format, int usage) {
ATRACE_NAME("IonBuffer::Import2");
ALOGD_IF(TRACE,
"IonBuffer::Import: fd_count=%d int_count=%d width=%d height=%d "
"stride=%d format=%d usage=%d",
fd_count, int_count, width, height, stride, format, usage);
if (fd_count < 0 || int_count < 0) {
ALOGE("IonBuffer::Import: invalid arguments.");
return -EINVAL;
}
native_handle_t* handle = native_handle_create(fd_count, int_count);
if (!handle) {
ALOGE("IonBuffer::Import: failed to create new native handle.");
return -ENOMEM;
}
// Copy fd_array into the first part of handle->data and int_array right
// after it.
memcpy(handle->data, fd_array, sizeof(int) * fd_count);
memcpy(handle->data + fd_count, int_array, sizeof(int) * int_count);
int ret = Import(handle, width, height, stride, format, usage);
if (ret < 0) {
ALOGE("IonBuffer::Import: failed to import raw native handle: %s",
strerror(-ret));
native_handle_close(handle);
native_handle_delete(handle);
}
return ret;
}
int IonBuffer::Duplicate(const IonBuffer* other) {
if (!other->handle())
return -EINVAL;
const int fd_count = other->handle()->numFds;
const int int_count = other->handle()->numInts;
if (fd_count < 0 || int_count < 0)
return -EINVAL;
native_handle_t* handle = native_handle_create(fd_count, int_count);
if (!handle) {
ALOGE("IonBuffer::Duplicate: Failed to create new native handle.");
return -ENOMEM;
}
// Duplicate the file descriptors from the other native handle.
for (int i = 0; i < fd_count; i++)
handle->data[i] = dup(other->handle()->data[i]);
// Copy the ints after the file descriptors.
memcpy(handle->data + fd_count, other->handle()->data + fd_count,
sizeof(int) * int_count);
const int ret = Import(handle, other->width(), other->height(),
other->stride(), other->format(), other->usage());
if (ret < 0) {
ALOGE("IonBuffer::Duplicate: Failed to import duplicate native handle: %s",
strerror(-ret));
native_handle_close(handle);
native_handle_delete(handle);
}
return ret;
}
int IonBuffer::Lock(int usage, int x, int y, int width, int height,
void** address) {
ATRACE_NAME("IonBuffer::Lock");
ALOGD_IF(TRACE,
"IonBuffer::Lock: handle=%p usage=%d x=%d y=%d width=%d height=%d "
"address=%p",
handle(), usage, x, y, width, height, address);
status_t err = buffer_->lock(usage, Rect(x, y, x + width, y + height),
address);
if (err != NO_ERROR)
return -EINVAL;
else
return 0;
}
int IonBuffer::LockYUV(int usage, int x, int y, int width, int height,
struct android_ycbcr* yuv) {
ATRACE_NAME("IonBuffer::LockYUV");
ALOGD_IF(TRACE,
"IonBuffer::Lock: handle=%p usage=%d x=%d y=%d width=%d height=%d",
handle(), usage, x, y, width, height);
status_t err = buffer_->lockYCbCr(usage, Rect(x, y, x + width, y + height),
yuv);
if (err != NO_ERROR)
return -EINVAL;
else
return 0;
}
int IonBuffer::Unlock() {
ATRACE_NAME("IonBuffer::Unlock");
ALOGD_IF(TRACE, "IonBuffer::Unlock: handle=%p", handle());
status_t err = buffer_->unlock();
if (err != NO_ERROR)
return -EINVAL;
else
return 0;
}
} // namespace dvr
} // namespace android