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 9namespace { 10 11constexpr uint32_t kDefaultGraphicBufferLayerCount = 1; 12 13} // anonymous namespace 14 15namespace android { 16namespace dvr { 17 18IonBuffer::IonBuffer() : IonBuffer(nullptr, 0, 0, 0, 0, 0, 0) {} 19 20IonBuffer::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 26IonBuffer::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 31IonBuffer::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 44IonBuffer::~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 52IonBuffer::IonBuffer(IonBuffer&& other) : IonBuffer() { 53 *this = std::move(other); 54} 55 56IonBuffer& 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 67void IonBuffer::FreeHandle() { 68 if (buffer_.get()) { 69 // GraphicBuffer unregisters and cleans up the handle if needed 70 buffer_ = nullptr; 71 } 72} 73 74int 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 91void 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 101int 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 122int 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 161int 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 198int 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 214int 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 229int 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