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