GraphicBuffer.cpp revision cb8405e7e74398aeafc9ef6ddb59af2d7cc6d2a6
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 <ui/GraphicBuffer.h> 20 21#include <cutils/atomic.h> 22 23#include <grallocusage/GrallocUsageConversion.h> 24 25#include <ui/Gralloc2.h> 26#include <ui/GraphicBufferAllocator.h> 27#include <ui/GraphicBufferMapper.h> 28 29namespace android { 30 31// =========================================================================== 32// Buffer and implementation of ANativeWindowBuffer 33// =========================================================================== 34 35static uint64_t getUniqueId() { 36 static volatile int32_t nextId = 0; 37 uint64_t id = static_cast<uint64_t>(getpid()) << 32; 38 id |= static_cast<uint32_t>(android_atomic_inc(&nextId)); 39 return id; 40} 41 42sp<GraphicBuffer> GraphicBuffer::from(ANativeWindowBuffer* anwb) { 43 return static_cast<GraphicBuffer *>(anwb); 44} 45 46GraphicBuffer::GraphicBuffer() 47 : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()), 48 mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0) 49{ 50 width = 51 height = 52 stride = 53 format = 54 usage = 0; 55 layerCount = 0; 56 handle = NULL; 57} 58 59// deprecated 60GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight, 61 PixelFormat inFormat, uint32_t inUsage, std::string requestorName) 62 : GraphicBuffer(inWidth, inHeight, inFormat, 1, inUsage, inUsage, 63 requestorName) 64{ 65} 66 67GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight, 68 PixelFormat inFormat, uint32_t inLayerCount, uint64_t producerUsage, 69 uint64_t consumerUsage, std::string requestorName) 70 : GraphicBuffer() 71{ 72 mInitCheck = initWithSize(inWidth, inHeight, inFormat, inLayerCount, 73 producerUsage, consumerUsage, std::move(requestorName)); 74} 75 76// deprecated 77GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight, 78 PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage, 79 uint32_t inStride, native_handle_t* inHandle, bool keepOwnership) 80 : GraphicBuffer(inHandle, keepOwnership ? TAKE_HANDLE : WRAP_HANDLE, 81 inWidth, inHeight, inFormat, inLayerCount, inUsage, inUsage, 82 inStride) 83{ 84} 85 86GraphicBuffer::GraphicBuffer(const native_handle_t* handle, 87 HandleWrapMethod method, uint32_t width, uint32_t height, 88 PixelFormat format, uint32_t layerCount, 89 uint64_t producerUsage, uint64_t consumerUsage, 90 uint32_t stride) 91 : GraphicBuffer() 92{ 93 mInitCheck = initWithHandle(handle, method, width, height, format, 94 layerCount, producerUsage, consumerUsage, stride); 95} 96 97GraphicBuffer::~GraphicBuffer() 98{ 99 if (handle) { 100 free_handle(); 101 } 102} 103 104void GraphicBuffer::free_handle() 105{ 106 if (mOwner == ownHandle) { 107 mBufferMapper.freeBuffer(handle); 108 } else if (mOwner == ownData) { 109 GraphicBufferAllocator& allocator(GraphicBufferAllocator::get()); 110 allocator.free(handle); 111 } 112 handle = NULL; 113} 114 115status_t GraphicBuffer::initCheck() const { 116 return static_cast<status_t>(mInitCheck); 117} 118 119void GraphicBuffer::dumpAllocationsToSystemLog() 120{ 121 GraphicBufferAllocator::dumpToSystemLog(); 122} 123 124ANativeWindowBuffer* GraphicBuffer::getNativeBuffer() const 125{ 126 LOG_ALWAYS_FATAL_IF(this == NULL, "getNativeBuffer() called on NULL GraphicBuffer"); 127 return static_cast<ANativeWindowBuffer*>( 128 const_cast<GraphicBuffer*>(this)); 129} 130 131status_t GraphicBuffer::reallocate(uint32_t inWidth, uint32_t inHeight, 132 PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage) 133{ 134 if (mOwner != ownData) 135 return INVALID_OPERATION; 136 137 if (handle && 138 static_cast<int>(inWidth) == width && 139 static_cast<int>(inHeight) == height && 140 inFormat == format && 141 inLayerCount == layerCount && 142 static_cast<int>(inUsage) == usage) 143 return NO_ERROR; 144 145 if (handle) { 146 GraphicBufferAllocator& allocator(GraphicBufferAllocator::get()); 147 allocator.free(handle); 148 handle = 0; 149 } 150 return initWithSize(inWidth, inHeight, inFormat, inLayerCount, 151 inUsage, inUsage, "[Reallocation]"); 152} 153 154bool GraphicBuffer::needsReallocation(uint32_t inWidth, uint32_t inHeight, 155 PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage) 156{ 157 if (static_cast<int>(inWidth) != width) return true; 158 if (static_cast<int>(inHeight) != height) return true; 159 if (inFormat != format) return true; 160 if (inLayerCount != layerCount) return true; 161 if ((static_cast<uint32_t>(usage) & inUsage) != inUsage) return true; 162 return false; 163} 164 165status_t GraphicBuffer::initWithSize(uint32_t inWidth, uint32_t inHeight, 166 PixelFormat inFormat, uint32_t inLayerCount, uint64_t inProducerUsage, 167 uint64_t inConsumerUsage, std::string requestorName) 168{ 169 GraphicBufferAllocator& allocator = GraphicBufferAllocator::get(); 170 uint32_t outStride = 0; 171 status_t err = allocator.allocate(inWidth, inHeight, inFormat, inLayerCount, 172 inProducerUsage, inConsumerUsage, &handle, &outStride, mId, 173 std::move(requestorName)); 174 if (err == NO_ERROR) { 175 width = static_cast<int>(inWidth); 176 height = static_cast<int>(inHeight); 177 format = inFormat; 178 layerCount = inLayerCount; 179 usage = android_convertGralloc1To0Usage(inProducerUsage, inConsumerUsage); 180 stride = static_cast<int>(outStride); 181 } 182 return err; 183} 184 185status_t GraphicBuffer::initWithHandle(const native_handle_t* handle, 186 HandleWrapMethod method, uint32_t width, uint32_t height, 187 PixelFormat format, uint32_t layerCount, 188 uint64_t producerUsage, uint64_t consumerUsage, 189 uint32_t stride) 190{ 191 ANativeWindowBuffer::width = static_cast<int>(width); 192 ANativeWindowBuffer::height = static_cast<int>(height); 193 ANativeWindowBuffer::stride = static_cast<int>(stride); 194 ANativeWindowBuffer::format = format; 195 ANativeWindowBuffer::usage = 196 android_convertGralloc1To0Usage(producerUsage, consumerUsage); 197 198 ANativeWindowBuffer::layerCount = layerCount; 199 200 mOwner = (method == WRAP_HANDLE) ? ownNone : ownHandle; 201 202 if (method == TAKE_UNREGISTERED_HANDLE || method == CLONE_HANDLE) { 203 buffer_handle_t importedHandle; 204 status_t err = mBufferMapper.importBuffer(handle, &importedHandle); 205 if (err != NO_ERROR) { 206 initWithHandle(nullptr, WRAP_HANDLE, 0, 0, 0, 0, 0, 0, 0); 207 208 return err; 209 } 210 211 if (method == TAKE_UNREGISTERED_HANDLE) { 212 native_handle_close(handle); 213 native_handle_delete(const_cast<native_handle_t*>(handle)); 214 } 215 216 handle = importedHandle; 217 } 218 219 ANativeWindowBuffer::handle = handle; 220 221 return NO_ERROR; 222} 223 224status_t GraphicBuffer::lock(uint32_t inUsage, void** vaddr) 225{ 226 const Rect lockBounds(width, height); 227 status_t res = lock(inUsage, lockBounds, vaddr); 228 return res; 229} 230 231status_t GraphicBuffer::lock(uint32_t inUsage, const Rect& rect, void** vaddr) 232{ 233 if (rect.left < 0 || rect.right > width || 234 rect.top < 0 || rect.bottom > height) { 235 ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)", 236 rect.left, rect.top, rect.right, rect.bottom, 237 width, height); 238 return BAD_VALUE; 239 } 240 status_t res = getBufferMapper().lock(handle, inUsage, rect, vaddr); 241 return res; 242} 243 244status_t GraphicBuffer::lockYCbCr(uint32_t inUsage, android_ycbcr* ycbcr) 245{ 246 const Rect lockBounds(width, height); 247 status_t res = lockYCbCr(inUsage, lockBounds, ycbcr); 248 return res; 249} 250 251status_t GraphicBuffer::lockYCbCr(uint32_t inUsage, const Rect& rect, 252 android_ycbcr* ycbcr) 253{ 254 if (rect.left < 0 || rect.right > width || 255 rect.top < 0 || rect.bottom > height) { 256 ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)", 257 rect.left, rect.top, rect.right, rect.bottom, 258 width, height); 259 return BAD_VALUE; 260 } 261 status_t res = getBufferMapper().lockYCbCr(handle, inUsage, rect, ycbcr); 262 return res; 263} 264 265status_t GraphicBuffer::unlock() 266{ 267 status_t res = getBufferMapper().unlock(handle); 268 return res; 269} 270 271status_t GraphicBuffer::lockAsync(uint32_t inUsage, void** vaddr, int fenceFd) 272{ 273 const Rect lockBounds(width, height); 274 status_t res = lockAsync(inUsage, lockBounds, vaddr, fenceFd); 275 return res; 276} 277 278status_t GraphicBuffer::lockAsync(uint32_t inUsage, const Rect& rect, 279 void** vaddr, int fenceFd) 280{ 281 return lockAsync(inUsage, inUsage, rect, vaddr, fenceFd); 282} 283 284status_t GraphicBuffer::lockAsync(uint64_t inProducerUsage, 285 uint64_t inConsumerUsage, const Rect& rect, void** vaddr, int fenceFd) 286{ 287 if (rect.left < 0 || rect.right > width || 288 rect.top < 0 || rect.bottom > height) { 289 ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)", 290 rect.left, rect.top, rect.right, rect.bottom, 291 width, height); 292 return BAD_VALUE; 293 } 294 status_t res = getBufferMapper().lockAsync(handle, inProducerUsage, 295 inConsumerUsage, rect, vaddr, fenceFd); 296 return res; 297} 298 299status_t GraphicBuffer::lockAsyncYCbCr(uint32_t inUsage, android_ycbcr* ycbcr, 300 int fenceFd) 301{ 302 const Rect lockBounds(width, height); 303 status_t res = lockAsyncYCbCr(inUsage, lockBounds, ycbcr, fenceFd); 304 return res; 305} 306 307status_t GraphicBuffer::lockAsyncYCbCr(uint32_t inUsage, const Rect& rect, 308 android_ycbcr* ycbcr, int fenceFd) 309{ 310 if (rect.left < 0 || rect.right > width || 311 rect.top < 0 || rect.bottom > height) { 312 ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)", 313 rect.left, rect.top, rect.right, rect.bottom, 314 width, height); 315 return BAD_VALUE; 316 } 317 status_t res = getBufferMapper().lockAsyncYCbCr(handle, inUsage, rect, 318 ycbcr, fenceFd); 319 return res; 320} 321 322status_t GraphicBuffer::unlockAsync(int *fenceFd) 323{ 324 status_t res = getBufferMapper().unlockAsync(handle, fenceFd); 325 return res; 326} 327 328size_t GraphicBuffer::getFlattenedSize() const { 329 return static_cast<size_t>(12 + (handle ? handle->numInts : 0)) * sizeof(int); 330} 331 332size_t GraphicBuffer::getFdCount() const { 333 return static_cast<size_t>(handle ? handle->numFds : 0); 334} 335 336status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const { 337 size_t sizeNeeded = GraphicBuffer::getFlattenedSize(); 338 if (size < sizeNeeded) return NO_MEMORY; 339 340 size_t fdCountNeeded = GraphicBuffer::getFdCount(); 341 if (count < fdCountNeeded) return NO_MEMORY; 342 343 int32_t* buf = static_cast<int32_t*>(buffer); 344 buf[0] = 'GBFR'; 345 buf[1] = width; 346 buf[2] = height; 347 buf[3] = stride; 348 buf[4] = format; 349 buf[5] = static_cast<int32_t>(layerCount); 350 buf[6] = usage; 351 buf[7] = static_cast<int32_t>(mId >> 32); 352 buf[8] = static_cast<int32_t>(mId & 0xFFFFFFFFull); 353 buf[9] = static_cast<int32_t>(mGenerationNumber); 354 buf[10] = 0; 355 buf[11] = 0; 356 357 if (handle) { 358 buf[10] = handle->numFds; 359 buf[11] = handle->numInts; 360 memcpy(fds, handle->data, 361 static_cast<size_t>(handle->numFds) * sizeof(int)); 362 memcpy(&buf[12], handle->data + handle->numFds, 363 static_cast<size_t>(handle->numInts) * sizeof(int)); 364 } 365 366 buffer = static_cast<void*>(static_cast<uint8_t*>(buffer) + sizeNeeded); 367 size -= sizeNeeded; 368 if (handle) { 369 fds += handle->numFds; 370 count -= static_cast<size_t>(handle->numFds); 371 } 372 373 return NO_ERROR; 374} 375 376status_t GraphicBuffer::unflatten( 377 void const*& buffer, size_t& size, int const*& fds, size_t& count) { 378 if (size < 12 * sizeof(int)) return NO_MEMORY; 379 380 int const* buf = static_cast<int const*>(buffer); 381 if (buf[0] != 'GBFR') return BAD_TYPE; 382 383 const size_t numFds = static_cast<size_t>(buf[10]); 384 const size_t numInts = static_cast<size_t>(buf[11]); 385 386 // Limit the maxNumber to be relatively small. The number of fds or ints 387 // should not come close to this number, and the number itself was simply 388 // chosen to be high enough to not cause issues and low enough to prevent 389 // overflow problems. 390 const size_t maxNumber = 4096; 391 if (numFds >= maxNumber || numInts >= (maxNumber - 12)) { 392 width = height = stride = format = layerCount = usage = 0; 393 handle = NULL; 394 ALOGE("unflatten: numFds or numInts is too large: %zd, %zd", 395 numFds, numInts); 396 return BAD_VALUE; 397 } 398 399 const size_t sizeNeeded = (12 + numInts) * sizeof(int); 400 if (size < sizeNeeded) return NO_MEMORY; 401 402 size_t fdCountNeeded = numFds; 403 if (count < fdCountNeeded) return NO_MEMORY; 404 405 if (handle) { 406 // free previous handle if any 407 free_handle(); 408 } 409 410 if (numFds || numInts) { 411 width = buf[1]; 412 height = buf[2]; 413 stride = buf[3]; 414 format = buf[4]; 415 layerCount = static_cast<uintptr_t>(buf[5]); 416 usage = buf[6]; 417 native_handle* h = native_handle_create( 418 static_cast<int>(numFds), static_cast<int>(numInts)); 419 if (!h) { 420 width = height = stride = format = layerCount = usage = 0; 421 handle = NULL; 422 ALOGE("unflatten: native_handle_create failed"); 423 return NO_MEMORY; 424 } 425 memcpy(h->data, fds, numFds * sizeof(int)); 426 memcpy(h->data + numFds, &buf[12], numInts * sizeof(int)); 427 handle = h; 428 } else { 429 width = height = stride = format = layerCount = usage = 0; 430 handle = NULL; 431 } 432 433 mId = static_cast<uint64_t>(buf[7]) << 32; 434 mId |= static_cast<uint32_t>(buf[8]); 435 436 mGenerationNumber = static_cast<uint32_t>(buf[9]); 437 438 mOwner = ownHandle; 439 440 if (handle != 0) { 441 buffer_handle_t importedHandle; 442 status_t err = mBufferMapper.importBuffer(handle, &importedHandle); 443 if (err != NO_ERROR) { 444 width = height = stride = format = layerCount = usage = 0; 445 handle = NULL; 446 ALOGE("unflatten: registerBuffer failed: %s (%d)", 447 strerror(-err), err); 448 return err; 449 } 450 451 native_handle_close(handle); 452 native_handle_delete(const_cast<native_handle_t*>(handle)); 453 handle = importedHandle; 454 } 455 456 buffer = static_cast<void const*>(static_cast<uint8_t const*>(buffer) + sizeNeeded); 457 size -= sizeNeeded; 458 fds += numFds; 459 count -= numFds; 460 461 return NO_ERROR; 462} 463 464// --------------------------------------------------------------------------- 465 466}; // namespace android 467