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