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