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 31 namespace android { 32 33 // =========================================================================== 34 // Buffer and implementation of ANativeWindowBuffer 35 // =========================================================================== 36 getUniqueId()37 static 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 GraphicBuffer()44 GraphicBuffer::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 GraphicBuffer(uint32_t inWidth,uint32_t inHeight,PixelFormat inFormat,uint32_t inUsage)56 GraphicBuffer::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 GraphicBuffer(uint32_t inWidth,uint32_t inHeight,PixelFormat inFormat,uint32_t inUsage,uint32_t inStride,native_handle_t * inHandle,bool keepOwnership)70 GraphicBuffer::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 GraphicBuffer(ANativeWindowBuffer * buffer,bool keepOwnership)85 GraphicBuffer::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 ~GraphicBuffer()98 GraphicBuffer::~GraphicBuffer() 99 { 100 if (handle) { 101 free_handle(); 102 } 103 } 104 free_handle()105 void 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 initCheck() const118 status_t GraphicBuffer::initCheck() const { 119 return static_cast<status_t>(mInitCheck); 120 } 121 dumpAllocationsToSystemLog()122 void GraphicBuffer::dumpAllocationsToSystemLog() 123 { 124 GraphicBufferAllocator::dumpToSystemLog(); 125 } 126 getNativeBuffer() const127 ANativeWindowBuffer* 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 reallocate(uint32_t inWidth,uint32_t inHeight,PixelFormat inFormat,uint32_t inUsage)134 status_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 needsReallocation(uint32_t inWidth,uint32_t inHeight,PixelFormat inFormat,uint32_t inUsage)155 bool 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 initSize(uint32_t inWidth,uint32_t inHeight,PixelFormat inFormat,uint32_t inUsage)165 status_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 lock(uint32_t inUsage,void ** vaddr)182 status_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 lock(uint32_t inUsage,const Rect & rect,void ** vaddr)189 status_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 lockYCbCr(uint32_t inUsage,android_ycbcr * ycbcr)202 status_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 lockYCbCr(uint32_t inUsage,const Rect & rect,android_ycbcr * ycbcr)209 status_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 unlock()223 status_t GraphicBuffer::unlock() 224 { 225 status_t res = getBufferMapper().unlock(handle); 226 return res; 227 } 228 lockAsync(uint32_t inUsage,void ** vaddr,int fenceFd)229 status_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 lockAsync(uint32_t inUsage,const Rect & rect,void ** vaddr,int fenceFd)236 status_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 lockAsyncYCbCr(uint32_t inUsage,android_ycbcr * ycbcr,int fenceFd)251 status_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 lockAsyncYCbCr(uint32_t inUsage,const Rect & rect,android_ycbcr * ycbcr,int fenceFd)259 status_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 unlockAsync(int * fenceFd)274 status_t GraphicBuffer::unlockAsync(int *fenceFd) 275 { 276 status_t res = getBufferMapper().unlockAsync(handle, fenceFd); 277 return res; 278 } 279 getFlattenedSize() const280 size_t GraphicBuffer::getFlattenedSize() const { 281 return static_cast<size_t>(11 + (handle ? handle->numInts : 0)) * sizeof(int); 282 } 283 getFdCount() const284 size_t GraphicBuffer::getFdCount() const { 285 return static_cast<size_t>(handle ? handle->numFds : 0); 286 } 287 flatten(void * & buffer,size_t & size,int * & fds,size_t & count) const288 status_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] = static_cast<int32_t>(mGenerationNumber); 305 buf[9] = 0; 306 buf[10] = 0; 307 308 if (handle) { 309 buf[9] = handle->numFds; 310 buf[10] = handle->numInts; 311 memcpy(fds, handle->data, 312 static_cast<size_t>(handle->numFds) * sizeof(int)); 313 memcpy(&buf[11], handle->data + handle->numFds, 314 static_cast<size_t>(handle->numInts) * sizeof(int)); 315 } 316 317 buffer = static_cast<void*>(static_cast<uint8_t*>(buffer) + sizeNeeded); 318 size -= sizeNeeded; 319 if (handle) { 320 fds += handle->numFds; 321 count -= static_cast<size_t>(handle->numFds); 322 } 323 324 return NO_ERROR; 325 } 326 unflatten(void const * & buffer,size_t & size,int const * & fds,size_t & count)327 status_t GraphicBuffer::unflatten( 328 void const*& buffer, size_t& size, int const*& fds, size_t& count) { 329 if (size < 11 * sizeof(int)) return NO_MEMORY; 330 331 int const* buf = static_cast<int const*>(buffer); 332 if (buf[0] != 'GBFR') return BAD_TYPE; 333 334 const size_t numFds = static_cast<size_t>(buf[9]); 335 const size_t numInts = static_cast<size_t>(buf[10]); 336 337 // Limit the maxNumber to be relatively small. The number of fds or ints 338 // should not come close to this number, and the number itself was simply 339 // chosen to be high enough to not cause issues and low enough to prevent 340 // overflow problems. 341 const size_t maxNumber = 4096; 342 if (numFds >= maxNumber || numInts >= (maxNumber - 11)) { 343 width = height = stride = format = usage = 0; 344 handle = NULL; 345 ALOGE("unflatten: numFds or numInts is too large: %zd, %zd", 346 numFds, numInts); 347 return BAD_VALUE; 348 } 349 350 const size_t sizeNeeded = (11 + numInts) * sizeof(int); 351 if (size < sizeNeeded) return NO_MEMORY; 352 353 size_t fdCountNeeded = numFds; 354 if (count < fdCountNeeded) return NO_MEMORY; 355 356 if (handle) { 357 // free previous handle if any 358 free_handle(); 359 } 360 361 if (numFds || numInts) { 362 width = buf[1]; 363 height = buf[2]; 364 stride = buf[3]; 365 format = buf[4]; 366 usage = buf[5]; 367 native_handle* h = native_handle_create( 368 static_cast<int>(numFds), static_cast<int>(numInts)); 369 if (!h) { 370 width = height = stride = format = usage = 0; 371 handle = NULL; 372 ALOGE("unflatten: native_handle_create failed"); 373 return NO_MEMORY; 374 } 375 memcpy(h->data, fds, numFds * sizeof(int)); 376 memcpy(h->data + numFds, &buf[11], numInts * sizeof(int)); 377 handle = h; 378 } else { 379 width = height = stride = format = usage = 0; 380 handle = NULL; 381 } 382 383 mId = static_cast<uint64_t>(buf[6]) << 32; 384 mId |= static_cast<uint32_t>(buf[7]); 385 386 mGenerationNumber = static_cast<uint32_t>(buf[8]); 387 388 mOwner = ownHandle; 389 390 if (handle != 0) { 391 status_t err = mBufferMapper.registerBuffer(handle); 392 if (err != NO_ERROR) { 393 width = height = stride = format = usage = 0; 394 handle = NULL; 395 ALOGE("unflatten: registerBuffer failed: %s (%d)", 396 strerror(-err), err); 397 return err; 398 } 399 } 400 401 buffer = static_cast<void const*>(static_cast<uint8_t const*>(buffer) + sizeNeeded); 402 size -= sizeNeeded; 403 fds += numFds; 404 count -= numFds; 405 406 return NO_ERROR; 407 } 408 409 // --------------------------------------------------------------------------- 410 411 }; // namespace android 412