1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "GraphicBuffer" 18 19 #include <stdlib.h> 20 #include <stdint.h> 21 #include <sys/types.h> 22 23 #include <utils/Errors.h> 24 #include <utils/Log.h> 25 26 #include <ui/GraphicBuffer.h> 27 #include <ui/GraphicBufferAllocator.h> 28 #include <ui/GraphicBufferMapper.h> 29 #include <ui/PixelFormat.h> 30 31 namespace android { 32 33 // =========================================================================== 34 // Buffer and implementation of ANativeWindowBuffer 35 // =========================================================================== 36 37 static uint64_t getUniqueId() { 38 static volatile int32_t nextId = 0; 39 uint64_t id = static_cast<uint64_t>(getpid()) << 32; 40 id |= static_cast<uint32_t>(android_atomic_inc(&nextId)); 41 return id; 42 } 43 44 GraphicBuffer::GraphicBuffer() 45 : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()), 46 mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0) 47 { 48 width = 49 height = 50 stride = 51 format = 52 usage = 0; 53 handle = NULL; 54 } 55 56 GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight, 57 PixelFormat inFormat, uint32_t inUsage, std::string requestorName) 58 : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()), 59 mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0) 60 { 61 width = 62 height = 63 stride = 64 format = 65 usage = 0; 66 handle = NULL; 67 mInitCheck = initSize(inWidth, inHeight, inFormat, inUsage, 68 std::move(requestorName)); 69 } 70 71 GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight, 72 PixelFormat inFormat, uint32_t inUsage, uint32_t inStride, 73 native_handle_t* inHandle, bool keepOwnership) 74 : BASE(), mOwner(keepOwnership ? ownHandle : ownNone), 75 mBufferMapper(GraphicBufferMapper::get()), 76 mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0) 77 { 78 width = static_cast<int>(inWidth); 79 height = static_cast<int>(inHeight); 80 stride = static_cast<int>(inStride); 81 format = inFormat; 82 usage = static_cast<int>(inUsage); 83 handle = inHandle; 84 } 85 86 GraphicBuffer::GraphicBuffer(ANativeWindowBuffer* buffer, bool keepOwnership) 87 : BASE(), mOwner(keepOwnership ? ownHandle : ownNone), 88 mBufferMapper(GraphicBufferMapper::get()), 89 mInitCheck(NO_ERROR), mWrappedBuffer(buffer), mId(getUniqueId()), 90 mGenerationNumber(0) 91 { 92 width = buffer->width; 93 height = buffer->height; 94 stride = buffer->stride; 95 format = buffer->format; 96 usage = buffer->usage; 97 handle = buffer->handle; 98 } 99 100 GraphicBuffer::~GraphicBuffer() 101 { 102 if (handle) { 103 free_handle(); 104 } 105 } 106 107 void GraphicBuffer::free_handle() 108 { 109 if (mOwner == ownHandle) { 110 mBufferMapper.unregisterBuffer(handle); 111 native_handle_close(handle); 112 native_handle_delete(const_cast<native_handle*>(handle)); 113 } else if (mOwner == ownData) { 114 GraphicBufferAllocator& allocator(GraphicBufferAllocator::get()); 115 allocator.free(handle); 116 } 117 handle = NULL; 118 mWrappedBuffer = 0; 119 } 120 121 status_t GraphicBuffer::initCheck() const { 122 return static_cast<status_t>(mInitCheck); 123 } 124 125 void GraphicBuffer::dumpAllocationsToSystemLog() 126 { 127 GraphicBufferAllocator::dumpToSystemLog(); 128 } 129 130 ANativeWindowBuffer* GraphicBuffer::getNativeBuffer() const 131 { 132 LOG_ALWAYS_FATAL_IF(this == NULL, "getNativeBuffer() called on NULL GraphicBuffer"); 133 return static_cast<ANativeWindowBuffer*>( 134 const_cast<GraphicBuffer*>(this)); 135 } 136 137 status_t GraphicBuffer::reallocate(uint32_t inWidth, uint32_t inHeight, 138 PixelFormat inFormat, uint32_t inUsage) 139 { 140 if (mOwner != ownData) 141 return INVALID_OPERATION; 142 143 if (handle && 144 static_cast<int>(inWidth) == width && 145 static_cast<int>(inHeight) == height && 146 inFormat == format && 147 static_cast<int>(inUsage) == usage) 148 return NO_ERROR; 149 150 if (handle) { 151 GraphicBufferAllocator& allocator(GraphicBufferAllocator::get()); 152 allocator.free(handle); 153 handle = 0; 154 } 155 return initSize(inWidth, inHeight, inFormat, inUsage, "[Reallocation]"); 156 } 157 158 bool GraphicBuffer::needsReallocation(uint32_t inWidth, uint32_t inHeight, 159 PixelFormat inFormat, uint32_t inUsage) 160 { 161 if (static_cast<int>(inWidth) != width) return true; 162 if (static_cast<int>(inHeight) != height) return true; 163 if (inFormat != format) return true; 164 if ((static_cast<uint32_t>(usage) & inUsage) != inUsage) return true; 165 return false; 166 } 167 168 status_t GraphicBuffer::initSize(uint32_t inWidth, uint32_t inHeight, 169 PixelFormat inFormat, uint32_t inUsage, std::string requestorName) 170 { 171 GraphicBufferAllocator& allocator = GraphicBufferAllocator::get(); 172 uint32_t outStride = 0; 173 status_t err = allocator.allocate(inWidth, inHeight, inFormat, inUsage, 174 &handle, &outStride, mId, std::move(requestorName)); 175 if (err == NO_ERROR) { 176 width = static_cast<int>(inWidth); 177 height = static_cast<int>(inHeight); 178 format = inFormat; 179 usage = static_cast<int>(inUsage); 180 stride = static_cast<int>(outStride); 181 } 182 return err; 183 } 184 185 status_t GraphicBuffer::lock(uint32_t inUsage, void** vaddr) 186 { 187 const Rect lockBounds(width, height); 188 status_t res = lock(inUsage, lockBounds, vaddr); 189 return res; 190 } 191 192 status_t GraphicBuffer::lock(uint32_t inUsage, const Rect& rect, void** vaddr) 193 { 194 if (rect.left < 0 || rect.right > width || 195 rect.top < 0 || rect.bottom > height) { 196 ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)", 197 rect.left, rect.top, rect.right, rect.bottom, 198 width, height); 199 return BAD_VALUE; 200 } 201 status_t res = getBufferMapper().lock(handle, inUsage, rect, vaddr); 202 return res; 203 } 204 205 status_t GraphicBuffer::lockYCbCr(uint32_t inUsage, android_ycbcr* ycbcr) 206 { 207 const Rect lockBounds(width, height); 208 status_t res = lockYCbCr(inUsage, lockBounds, ycbcr); 209 return res; 210 } 211 212 status_t GraphicBuffer::lockYCbCr(uint32_t inUsage, const Rect& rect, 213 android_ycbcr* ycbcr) 214 { 215 if (rect.left < 0 || rect.right > width || 216 rect.top < 0 || rect.bottom > height) { 217 ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)", 218 rect.left, rect.top, rect.right, rect.bottom, 219 width, height); 220 return BAD_VALUE; 221 } 222 status_t res = getBufferMapper().lockYCbCr(handle, inUsage, rect, ycbcr); 223 return res; 224 } 225 226 status_t GraphicBuffer::unlock() 227 { 228 status_t res = getBufferMapper().unlock(handle); 229 return res; 230 } 231 232 status_t GraphicBuffer::lockAsync(uint32_t inUsage, void** vaddr, int fenceFd) 233 { 234 const Rect lockBounds(width, height); 235 status_t res = lockAsync(inUsage, lockBounds, vaddr, fenceFd); 236 return res; 237 } 238 239 status_t GraphicBuffer::lockAsync(uint32_t inUsage, const Rect& rect, 240 void** vaddr, int fenceFd) 241 { 242 if (rect.left < 0 || rect.right > width || 243 rect.top < 0 || rect.bottom > height) { 244 ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)", 245 rect.left, rect.top, rect.right, rect.bottom, 246 width, height); 247 return BAD_VALUE; 248 } 249 status_t res = getBufferMapper().lockAsync(handle, inUsage, rect, vaddr, 250 fenceFd); 251 return res; 252 } 253 254 status_t GraphicBuffer::lockAsyncYCbCr(uint32_t inUsage, android_ycbcr* ycbcr, 255 int fenceFd) 256 { 257 const Rect lockBounds(width, height); 258 status_t res = lockAsyncYCbCr(inUsage, lockBounds, ycbcr, fenceFd); 259 return res; 260 } 261 262 status_t GraphicBuffer::lockAsyncYCbCr(uint32_t inUsage, const Rect& rect, 263 android_ycbcr* ycbcr, int fenceFd) 264 { 265 if (rect.left < 0 || rect.right > width || 266 rect.top < 0 || rect.bottom > height) { 267 ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)", 268 rect.left, rect.top, rect.right, rect.bottom, 269 width, height); 270 return BAD_VALUE; 271 } 272 status_t res = getBufferMapper().lockAsyncYCbCr(handle, inUsage, rect, 273 ycbcr, fenceFd); 274 return res; 275 } 276 277 status_t GraphicBuffer::unlockAsync(int *fenceFd) 278 { 279 status_t res = getBufferMapper().unlockAsync(handle, fenceFd); 280 return res; 281 } 282 283 size_t GraphicBuffer::getFlattenedSize() const { 284 return static_cast<size_t>(11 + (handle ? handle->numInts : 0)) * sizeof(int); 285 } 286 287 size_t GraphicBuffer::getFdCount() const { 288 return static_cast<size_t>(handle ? handle->numFds : 0); 289 } 290 291 status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const { 292 size_t sizeNeeded = GraphicBuffer::getFlattenedSize(); 293 if (size < sizeNeeded) return NO_MEMORY; 294 295 size_t fdCountNeeded = GraphicBuffer::getFdCount(); 296 if (count < fdCountNeeded) return NO_MEMORY; 297 298 int32_t* buf = static_cast<int32_t*>(buffer); 299 buf[0] = 'GBFR'; 300 buf[1] = width; 301 buf[2] = height; 302 buf[3] = stride; 303 buf[4] = format; 304 buf[5] = usage; 305 buf[6] = static_cast<int32_t>(mId >> 32); 306 buf[7] = static_cast<int32_t>(mId & 0xFFFFFFFFull); 307 buf[8] = static_cast<int32_t>(mGenerationNumber); 308 buf[9] = 0; 309 buf[10] = 0; 310 311 if (handle) { 312 buf[9] = handle->numFds; 313 buf[10] = handle->numInts; 314 memcpy(fds, handle->data, 315 static_cast<size_t>(handle->numFds) * sizeof(int)); 316 memcpy(&buf[11], handle->data + handle->numFds, 317 static_cast<size_t>(handle->numInts) * sizeof(int)); 318 } 319 320 buffer = static_cast<void*>(static_cast<uint8_t*>(buffer) + sizeNeeded); 321 size -= sizeNeeded; 322 if (handle) { 323 fds += handle->numFds; 324 count -= static_cast<size_t>(handle->numFds); 325 } 326 327 return NO_ERROR; 328 } 329 330 status_t GraphicBuffer::unflatten( 331 void const*& buffer, size_t& size, int const*& fds, size_t& count) { 332 if (size < 11 * sizeof(int)) return NO_MEMORY; 333 334 int const* buf = static_cast<int const*>(buffer); 335 if (buf[0] != 'GBFR') return BAD_TYPE; 336 337 const size_t numFds = static_cast<size_t>(buf[9]); 338 const size_t numInts = static_cast<size_t>(buf[10]); 339 340 // Limit the maxNumber to be relatively small. The number of fds or ints 341 // should not come close to this number, and the number itself was simply 342 // chosen to be high enough to not cause issues and low enough to prevent 343 // overflow problems. 344 const size_t maxNumber = 4096; 345 if (numFds >= maxNumber || numInts >= (maxNumber - 11)) { 346 width = height = stride = format = usage = 0; 347 handle = NULL; 348 ALOGE("unflatten: numFds or numInts is too large: %zd, %zd", 349 numFds, numInts); 350 return BAD_VALUE; 351 } 352 353 const size_t sizeNeeded = (11 + numInts) * sizeof(int); 354 if (size < sizeNeeded) return NO_MEMORY; 355 356 size_t fdCountNeeded = numFds; 357 if (count < fdCountNeeded) return NO_MEMORY; 358 359 if (handle) { 360 // free previous handle if any 361 free_handle(); 362 } 363 364 if (numFds || numInts) { 365 width = buf[1]; 366 height = buf[2]; 367 stride = buf[3]; 368 format = buf[4]; 369 usage = buf[5]; 370 native_handle* h = native_handle_create( 371 static_cast<int>(numFds), static_cast<int>(numInts)); 372 if (!h) { 373 width = height = stride = format = usage = 0; 374 handle = NULL; 375 ALOGE("unflatten: native_handle_create failed"); 376 return NO_MEMORY; 377 } 378 memcpy(h->data, fds, numFds * sizeof(int)); 379 memcpy(h->data + numFds, &buf[11], numInts * sizeof(int)); 380 handle = h; 381 } else { 382 width = height = stride = format = usage = 0; 383 handle = NULL; 384 } 385 386 mId = static_cast<uint64_t>(buf[6]) << 32; 387 mId |= static_cast<uint32_t>(buf[7]); 388 389 mGenerationNumber = static_cast<uint32_t>(buf[8]); 390 391 mOwner = ownHandle; 392 393 if (handle != 0) { 394 status_t err = mBufferMapper.registerBuffer(this); 395 if (err != NO_ERROR) { 396 width = height = stride = format = usage = 0; 397 handle = NULL; 398 ALOGE("unflatten: registerBuffer failed: %s (%d)", 399 strerror(-err), err); 400 return err; 401 } 402 } 403 404 buffer = static_cast<void const*>(static_cast<uint8_t const*>(buffer) + sizeNeeded); 405 size -= sizeNeeded; 406 fds += numFds; 407 count -= numFds; 408 409 return NO_ERROR; 410 } 411 412 // --------------------------------------------------------------------------- 413 414 }; // namespace android 415