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, static_cast<uint64_t>(inUsage), 63 requestorName) 64{ 65} 66 67GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight, 68 PixelFormat inFormat, uint32_t inLayerCount, uint64_t usage, 69 std::string requestorName) 70 : GraphicBuffer() 71{ 72 mInitCheck = initWithSize(inWidth, inHeight, inFormat, inLayerCount, 73 usage, 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, static_cast<uint64_t>(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 usage, 90 uint32_t stride) 91 : GraphicBuffer() 92{ 93 mInitCheck = initWithHandle(handle, method, width, height, format, 94 layerCount, usage, 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, uint64_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, "[Reallocation]"); 152} 153 154bool GraphicBuffer::needsReallocation(uint32_t inWidth, uint32_t inHeight, 155 PixelFormat inFormat, uint32_t inLayerCount, uint64_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 inUsage, 167 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 inUsage, &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 = static_cast<int>(inUsage); 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, uint64_t usage, 188 uint32_t stride) 189{ 190 ANativeWindowBuffer::width = static_cast<int>(width); 191 ANativeWindowBuffer::height = static_cast<int>(height); 192 ANativeWindowBuffer::stride = static_cast<int>(stride); 193 ANativeWindowBuffer::format = format; 194 ANativeWindowBuffer::usage = static_cast<int>(usage); 195 196 ANativeWindowBuffer::layerCount = layerCount; 197 198 mOwner = (method == WRAP_HANDLE) ? ownNone : ownHandle; 199 200 if (method == TAKE_UNREGISTERED_HANDLE || method == CLONE_HANDLE) { 201 buffer_handle_t importedHandle; 202 status_t err = mBufferMapper.importBuffer(handle, &importedHandle); 203 if (err != NO_ERROR) { 204 initWithHandle(nullptr, WRAP_HANDLE, 0, 0, 0, 0, 0, 0); 205 206 return err; 207 } 208 209 if (method == TAKE_UNREGISTERED_HANDLE) { 210 native_handle_close(handle); 211 native_handle_delete(const_cast<native_handle_t*>(handle)); 212 } 213 214 handle = importedHandle; 215 } 216 217 ANativeWindowBuffer::handle = handle; 218 219 return NO_ERROR; 220} 221 222status_t GraphicBuffer::lock(uint32_t inUsage, void** vaddr) 223{ 224 const Rect lockBounds(width, height); 225 status_t res = lock(inUsage, lockBounds, vaddr); 226 return res; 227} 228 229status_t GraphicBuffer::lock(uint32_t inUsage, const Rect& rect, void** vaddr) 230{ 231 if (rect.left < 0 || rect.right > width || 232 rect.top < 0 || rect.bottom > height) { 233 ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)", 234 rect.left, rect.top, rect.right, rect.bottom, 235 width, height); 236 return BAD_VALUE; 237 } 238 status_t res = getBufferMapper().lock(handle, inUsage, rect, vaddr); 239 return res; 240} 241 242status_t GraphicBuffer::lockYCbCr(uint32_t inUsage, android_ycbcr* ycbcr) 243{ 244 const Rect lockBounds(width, height); 245 status_t res = lockYCbCr(inUsage, lockBounds, ycbcr); 246 return res; 247} 248 249status_t GraphicBuffer::lockYCbCr(uint32_t inUsage, const Rect& rect, 250 android_ycbcr* ycbcr) 251{ 252 if (rect.left < 0 || rect.right > width || 253 rect.top < 0 || rect.bottom > height) { 254 ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)", 255 rect.left, rect.top, rect.right, rect.bottom, 256 width, height); 257 return BAD_VALUE; 258 } 259 status_t res = getBufferMapper().lockYCbCr(handle, inUsage, rect, ycbcr); 260 return res; 261} 262 263status_t GraphicBuffer::unlock() 264{ 265 status_t res = getBufferMapper().unlock(handle); 266 return res; 267} 268 269status_t GraphicBuffer::lockAsync(uint32_t inUsage, void** vaddr, int fenceFd) 270{ 271 const Rect lockBounds(width, height); 272 status_t res = lockAsync(inUsage, lockBounds, vaddr, fenceFd); 273 return res; 274} 275 276status_t GraphicBuffer::lockAsync(uint32_t inUsage, const Rect& rect, 277 void** vaddr, int fenceFd) 278{ 279 return lockAsync(inUsage, inUsage, rect, vaddr, fenceFd); 280} 281 282status_t GraphicBuffer::lockAsync(uint64_t inProducerUsage, 283 uint64_t inConsumerUsage, const Rect& rect, void** vaddr, int fenceFd) 284{ 285 if (rect.left < 0 || rect.right > width || 286 rect.top < 0 || rect.bottom > height) { 287 ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)", 288 rect.left, rect.top, rect.right, rect.bottom, 289 width, height); 290 return BAD_VALUE; 291 } 292 status_t res = getBufferMapper().lockAsync(handle, inProducerUsage, 293 inConsumerUsage, rect, vaddr, fenceFd); 294 return res; 295} 296 297status_t GraphicBuffer::lockAsyncYCbCr(uint32_t inUsage, android_ycbcr* ycbcr, 298 int fenceFd) 299{ 300 const Rect lockBounds(width, height); 301 status_t res = lockAsyncYCbCr(inUsage, lockBounds, ycbcr, fenceFd); 302 return res; 303} 304 305status_t GraphicBuffer::lockAsyncYCbCr(uint32_t inUsage, const Rect& rect, 306 android_ycbcr* ycbcr, int fenceFd) 307{ 308 if (rect.left < 0 || rect.right > width || 309 rect.top < 0 || rect.bottom > height) { 310 ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)", 311 rect.left, rect.top, rect.right, rect.bottom, 312 width, height); 313 return BAD_VALUE; 314 } 315 status_t res = getBufferMapper().lockAsyncYCbCr(handle, inUsage, rect, 316 ycbcr, fenceFd); 317 return res; 318} 319 320status_t GraphicBuffer::unlockAsync(int *fenceFd) 321{ 322 status_t res = getBufferMapper().unlockAsync(handle, fenceFd); 323 return res; 324} 325 326size_t GraphicBuffer::getFlattenedSize() const { 327 return static_cast<size_t>(12 + (handle ? handle->numInts : 0)) * sizeof(int); 328} 329 330size_t GraphicBuffer::getFdCount() const { 331 return static_cast<size_t>(handle ? handle->numFds : 0); 332} 333 334status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const { 335 size_t sizeNeeded = GraphicBuffer::getFlattenedSize(); 336 if (size < sizeNeeded) return NO_MEMORY; 337 338 size_t fdCountNeeded = GraphicBuffer::getFdCount(); 339 if (count < fdCountNeeded) return NO_MEMORY; 340 341 int32_t* buf = static_cast<int32_t*>(buffer); 342 buf[0] = 'GBFR'; 343 buf[1] = width; 344 buf[2] = height; 345 buf[3] = stride; 346 buf[4] = format; 347 buf[5] = static_cast<int32_t>(layerCount); 348 buf[6] = usage; 349 buf[7] = static_cast<int32_t>(mId >> 32); 350 buf[8] = static_cast<int32_t>(mId & 0xFFFFFFFFull); 351 buf[9] = static_cast<int32_t>(mGenerationNumber); 352 buf[10] = 0; 353 buf[11] = 0; 354 355 if (handle) { 356 buf[10] = handle->numFds; 357 buf[11] = handle->numInts; 358 memcpy(fds, handle->data, 359 static_cast<size_t>(handle->numFds) * sizeof(int)); 360 memcpy(&buf[12], handle->data + handle->numFds, 361 static_cast<size_t>(handle->numInts) * sizeof(int)); 362 } 363 364 buffer = static_cast<void*>(static_cast<uint8_t*>(buffer) + sizeNeeded); 365 size -= sizeNeeded; 366 if (handle) { 367 fds += handle->numFds; 368 count -= static_cast<size_t>(handle->numFds); 369 } 370 371 return NO_ERROR; 372} 373 374status_t GraphicBuffer::unflatten( 375 void const*& buffer, size_t& size, int const*& fds, size_t& count) { 376 if (size < 12 * sizeof(int)) return NO_MEMORY; 377 378 int const* buf = static_cast<int const*>(buffer); 379 if (buf[0] != 'GBFR') return BAD_TYPE; 380 381 const size_t numFds = static_cast<size_t>(buf[10]); 382 const size_t numInts = static_cast<size_t>(buf[11]); 383 384 // Limit the maxNumber to be relatively small. The number of fds or ints 385 // should not come close to this number, and the number itself was simply 386 // chosen to be high enough to not cause issues and low enough to prevent 387 // overflow problems. 388 const size_t maxNumber = 4096; 389 if (numFds >= maxNumber || numInts >= (maxNumber - 12)) { 390 width = height = stride = format = layerCount = usage = 0; 391 handle = NULL; 392 ALOGE("unflatten: numFds or numInts is too large: %zd, %zd", 393 numFds, numInts); 394 return BAD_VALUE; 395 } 396 397 const size_t sizeNeeded = (12 + numInts) * sizeof(int); 398 if (size < sizeNeeded) return NO_MEMORY; 399 400 size_t fdCountNeeded = numFds; 401 if (count < fdCountNeeded) return NO_MEMORY; 402 403 if (handle) { 404 // free previous handle if any 405 free_handle(); 406 } 407 408 if (numFds || numInts) { 409 width = buf[1]; 410 height = buf[2]; 411 stride = buf[3]; 412 format = buf[4]; 413 layerCount = static_cast<uintptr_t>(buf[5]); 414 usage = buf[6]; 415 native_handle* h = native_handle_create( 416 static_cast<int>(numFds), static_cast<int>(numInts)); 417 if (!h) { 418 width = height = stride = format = layerCount = usage = 0; 419 handle = NULL; 420 ALOGE("unflatten: native_handle_create failed"); 421 return NO_MEMORY; 422 } 423 memcpy(h->data, fds, numFds * sizeof(int)); 424 memcpy(h->data + numFds, &buf[12], numInts * sizeof(int)); 425 handle = h; 426 } else { 427 width = height = stride = format = layerCount = usage = 0; 428 handle = NULL; 429 } 430 431 mId = static_cast<uint64_t>(buf[7]) << 32; 432 mId |= static_cast<uint32_t>(buf[8]); 433 434 mGenerationNumber = static_cast<uint32_t>(buf[9]); 435 436 mOwner = ownHandle; 437 438 if (handle != 0) { 439 buffer_handle_t importedHandle; 440 status_t err = mBufferMapper.importBuffer(handle, &importedHandle); 441 if (err != NO_ERROR) { 442 width = height = stride = format = layerCount = usage = 0; 443 handle = NULL; 444 ALOGE("unflatten: registerBuffer failed: %s (%d)", 445 strerror(-err), err); 446 return err; 447 } 448 449 native_handle_close(handle); 450 native_handle_delete(const_cast<native_handle_t*>(handle)); 451 handle = importedHandle; 452 } 453 454 buffer = static_cast<void const*>(static_cast<uint8_t const*>(buffer) + sizeNeeded); 455 size -= sizeNeeded; 456 fds += numFds; 457 count -= numFds; 458 459 return NO_ERROR; 460} 461 462// --------------------------------------------------------------------------- 463 464}; // namespace android 465