Home | History | Annotate | Download | only in libbufferhub
      1 #include <private/dvr/ion_buffer.h>
      2 
      3 #include <log/log.h>
      4 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
      5 #include <utils/Trace.h>
      6 
      7 #include <mutex>
      8 
      9 namespace {
     10 
     11 constexpr uint32_t kDefaultGraphicBufferLayerCount = 1;
     12 
     13 }  // anonymous namespace
     14 
     15 namespace android {
     16 namespace dvr {
     17 
     18 IonBuffer::IonBuffer() : IonBuffer(nullptr, 0, 0, 0, 0, 0, 0) {}
     19 
     20 IonBuffer::IonBuffer(uint32_t width, uint32_t height, uint32_t format,
     21                      uint64_t usage)
     22     : IonBuffer() {
     23   Alloc(width, height, kDefaultGraphicBufferLayerCount, format, usage);
     24 }
     25 
     26 IonBuffer::IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
     27                      uint32_t stride, uint32_t format, uint64_t usage)
     28     : IonBuffer(handle, width, height, kDefaultGraphicBufferLayerCount, stride,
     29                 format, usage) {}
     30 
     31 IonBuffer::IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
     32                      uint32_t layer_count, uint32_t stride, uint32_t format,
     33                      uint64_t usage)
     34     : buffer_(nullptr) {
     35   ALOGD_IF(TRACE,
     36            "IonBuffer::IonBuffer: handle=%p width=%u height=%u layer_count=%u "
     37            "stride=%u format=%u usage=%" PRIx64,
     38            handle, width, height, layer_count, stride, format, usage);
     39   if (handle != 0) {
     40     Import(handle, width, height, layer_count, stride, format, usage);
     41   }
     42 }
     43 
     44 IonBuffer::~IonBuffer() {
     45   ALOGD_IF(TRACE,
     46            "IonBuffer::~IonBuffer: handle=%p width=%u height=%u stride=%u "
     47            "format=%u usage=%" PRIx64,
     48            handle(), width(), height(), stride(), format(), usage());
     49   FreeHandle();
     50 }
     51 
     52 IonBuffer::IonBuffer(IonBuffer&& other) : IonBuffer() {
     53   *this = std::move(other);
     54 }
     55 
     56 IonBuffer& IonBuffer::operator=(IonBuffer&& other) {
     57   ALOGD_IF(TRACE, "IonBuffer::operator=: handle_=%p other.handle_=%p", handle(),
     58            other.handle());
     59 
     60   if (this != &other) {
     61     buffer_ = other.buffer_;
     62     other.FreeHandle();
     63   }
     64   return *this;
     65 }
     66 
     67 void IonBuffer::FreeHandle() {
     68   if (buffer_.get()) {
     69     // GraphicBuffer unregisters and cleans up the handle if needed
     70     buffer_ = nullptr;
     71   }
     72 }
     73 
     74 int IonBuffer::Alloc(uint32_t width, uint32_t height, uint32_t layer_count,
     75                      uint32_t format, uint64_t usage) {
     76   ALOGD_IF(TRACE,
     77            "IonBuffer::Alloc: width=%u height=%u layer_count=%u format=%u "
     78            "usage=%" PRIx64, width, height, layer_count, format, usage);
     79 
     80   sp<GraphicBuffer> buffer =
     81       new GraphicBuffer(width, height, format, layer_count, usage);
     82   if (buffer->initCheck() != OK) {
     83     ALOGE("IonBuffer::Aloc: Failed to allocate buffer");
     84     return -EINVAL;
     85   } else {
     86     buffer_ = buffer;
     87     return 0;
     88   }
     89 }
     90 
     91 void IonBuffer::Reset(buffer_handle_t handle, uint32_t width, uint32_t height,
     92                       uint32_t layer_count, uint32_t stride, uint32_t format,
     93                       uint64_t usage) {
     94   ALOGD_IF(TRACE,
     95            "IonBuffer::Reset: handle=%p width=%u height=%u layer_count=%u "
     96            "stride=%u format=%u usage=%" PRIx64,
     97            handle, width, height, layer_count, stride, format, usage);
     98   Import(handle, width, height, layer_count, stride, format, usage);
     99 }
    100 
    101 int IonBuffer::Import(buffer_handle_t handle, uint32_t width, uint32_t height,
    102                       uint32_t layer_count, uint32_t stride, uint32_t format,
    103                       uint64_t usage) {
    104   ATRACE_NAME("IonBuffer::Import1");
    105   ALOGD_IF(TRACE,
    106            "IonBuffer::Import: handle=%p width=%u height=%u layer_count=%u "
    107            "stride=%u format=%u usage=%" PRIx64,
    108            handle, width, height, layer_count, stride, format, usage);
    109   FreeHandle();
    110   sp<GraphicBuffer> buffer =
    111       new GraphicBuffer(handle, GraphicBuffer::TAKE_UNREGISTERED_HANDLE, width,
    112                         height, format, layer_count, usage, stride);
    113   if (buffer->initCheck() != OK) {
    114     ALOGE("IonBuffer::Import: Failed to import buffer");
    115     return -EINVAL;
    116   } else {
    117     buffer_ = buffer;
    118     return 0;
    119   }
    120 }
    121 
    122 int IonBuffer::Import(const int* fd_array, int fd_count, const int* int_array,
    123                       int int_count, uint32_t width, uint32_t height,
    124                       uint32_t layer_count, uint32_t stride, uint32_t format,
    125                       uint64_t usage) {
    126   ATRACE_NAME("IonBuffer::Import2");
    127   ALOGD_IF(TRACE,
    128            "IonBuffer::Import: fd_count=%d int_count=%d width=%u height=%u "
    129            "layer_count=%u stride=%u format=%u usage=%" PRIx64,
    130            fd_count, int_count, width, height, layer_count, stride, format,
    131            usage);
    132 
    133   if (fd_count < 0 || int_count < 0) {
    134     ALOGE("IonBuffer::Import: invalid arguments.");
    135     return -EINVAL;
    136   }
    137 
    138   native_handle_t* handle = native_handle_create(fd_count, int_count);
    139   if (!handle) {
    140     ALOGE("IonBuffer::Import: failed to create new native handle.");
    141     return -ENOMEM;
    142   }
    143 
    144   // Copy fd_array into the first part of handle->data and int_array right
    145   // after it.
    146   memcpy(handle->data, fd_array, sizeof(int) * fd_count);
    147   memcpy(handle->data + fd_count, int_array, sizeof(int) * int_count);
    148 
    149   const int ret =
    150       Import(handle, width, height, layer_count, stride, format, usage);
    151   if (ret < 0) {
    152     ALOGE("IonBuffer::Import: failed to import raw native handle: %s",
    153           strerror(-ret));
    154     native_handle_close(handle);
    155     native_handle_delete(handle);
    156   }
    157 
    158   return ret;
    159 }
    160 
    161 int IonBuffer::Duplicate(const IonBuffer* other) {
    162   if (!other->handle())
    163     return -EINVAL;
    164 
    165   const int fd_count = other->handle()->numFds;
    166   const int int_count = other->handle()->numInts;
    167 
    168   if (fd_count < 0 || int_count < 0)
    169     return -EINVAL;
    170 
    171   native_handle_t* handle = native_handle_create(fd_count, int_count);
    172   if (!handle) {
    173     ALOGE("IonBuffer::Duplicate: Failed to create new native handle.");
    174     return -ENOMEM;
    175   }
    176 
    177   // Duplicate the file descriptors from the other native handle.
    178   for (int i = 0; i < fd_count; i++)
    179     handle->data[i] = dup(other->handle()->data[i]);
    180 
    181   // Copy the ints after the file descriptors.
    182   memcpy(handle->data + fd_count, other->handle()->data + fd_count,
    183          sizeof(int) * int_count);
    184 
    185   const int ret =
    186       Import(handle, other->width(), other->height(), other->layer_count(),
    187              other->stride(), other->format(), other->usage());
    188   if (ret < 0) {
    189     ALOGE("IonBuffer::Duplicate: Failed to import duplicate native handle: %s",
    190           strerror(-ret));
    191     native_handle_close(handle);
    192     native_handle_delete(handle);
    193   }
    194 
    195   return ret;
    196 }
    197 
    198 int IonBuffer::Lock(uint32_t usage, int x, int y, int width, int height,
    199                     void** address) {
    200   ATRACE_NAME("IonBuffer::Lock");
    201   ALOGD_IF(TRACE,
    202            "IonBuffer::Lock: handle=%p usage=%d x=%d y=%d width=%d height=%d "
    203            "address=%p",
    204            handle(), usage, x, y, width, height, address);
    205 
    206   status_t err =
    207       buffer_->lock(usage, Rect(x, y, x + width, y + height), address);
    208   if (err != NO_ERROR)
    209     return -EINVAL;
    210   else
    211     return 0;
    212 }
    213 
    214 int IonBuffer::LockYUV(uint32_t usage, int x, int y, int width, int height,
    215                        struct android_ycbcr* yuv) {
    216   ATRACE_NAME("IonBuffer::LockYUV");
    217   ALOGD_IF(TRACE,
    218            "IonBuffer::Lock: handle=%p usage=%d x=%d y=%d width=%d height=%d",
    219            handle(), usage, x, y, width, height);
    220 
    221   status_t err =
    222       buffer_->lockYCbCr(usage, Rect(x, y, x + width, y + height), yuv);
    223   if (err != NO_ERROR)
    224     return -EINVAL;
    225   else
    226     return 0;
    227 }
    228 
    229 int IonBuffer::Unlock() {
    230   ATRACE_NAME("IonBuffer::Unlock");
    231   ALOGD_IF(TRACE, "IonBuffer::Unlock: handle=%p", handle());
    232 
    233   status_t err = buffer_->unlock();
    234   if (err != NO_ERROR)
    235     return -EINVAL;
    236   else
    237     return 0;
    238 }
    239 }  // namespace dvr
    240 }  // namespace android
    241