GraphicBuffer.cpp revision 38803268570f90e97452cd9a30ac831661829091
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 w, uint32_t h, 57 PixelFormat reqFormat, uint32_t reqUsage) 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(w, h, reqFormat, reqUsage); 68} 69 70GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h, 71 PixelFormat inFormat, uint32_t inUsage, 72 uint32_t inStride, 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 = w; 78 height = h; 79 stride = inStride; 80 format = inFormat; 81 usage = 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 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 w, uint32_t h, PixelFormat f, 135 uint32_t reqUsage) 136{ 137 if (mOwner != ownData) 138 return INVALID_OPERATION; 139 140 if (handle && w==width && h==height && f==format && reqUsage==usage) 141 return NO_ERROR; 142 143 if (handle) { 144 GraphicBufferAllocator& allocator(GraphicBufferAllocator::get()); 145 allocator.free(handle); 146 handle = 0; 147 } 148 return initSize(w, h, f, reqUsage); 149} 150 151status_t GraphicBuffer::initSize(uint32_t w, uint32_t h, PixelFormat format, 152 uint32_t reqUsage) 153{ 154 GraphicBufferAllocator& allocator = GraphicBufferAllocator::get(); 155 status_t err = allocator.alloc(w, h, format, reqUsage, &handle, &stride); 156 if (err == NO_ERROR) { 157 this->width = w; 158 this->height = h; 159 this->format = format; 160 this->usage = reqUsage; 161 } 162 return err; 163} 164 165status_t GraphicBuffer::lock(uint32_t usage, void** vaddr) 166{ 167 const Rect lockBounds(width, height); 168 status_t res = lock(usage, lockBounds, vaddr); 169 return res; 170} 171 172status_t GraphicBuffer::lock(uint32_t usage, const Rect& rect, void** vaddr) 173{ 174 if (rect.left < 0 || rect.right > this->width || 175 rect.top < 0 || rect.bottom > this->height) { 176 ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)", 177 rect.left, rect.top, rect.right, rect.bottom, 178 this->width, this->height); 179 return BAD_VALUE; 180 } 181 status_t res = getBufferMapper().lock(handle, usage, rect, vaddr); 182 return res; 183} 184 185status_t GraphicBuffer::lockYCbCr(uint32_t usage, android_ycbcr *ycbcr) 186{ 187 const Rect lockBounds(width, height); 188 status_t res = lockYCbCr(usage, lockBounds, ycbcr); 189 return res; 190} 191 192status_t GraphicBuffer::lockYCbCr(uint32_t usage, const Rect& rect, 193 android_ycbcr *ycbcr) 194{ 195 if (rect.left < 0 || rect.right > this->width || 196 rect.top < 0 || rect.bottom > this->height) { 197 ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)", 198 rect.left, rect.top, rect.right, rect.bottom, 199 this->width, this->height); 200 return BAD_VALUE; 201 } 202 status_t res = getBufferMapper().lockYCbCr(handle, usage, rect, ycbcr); 203 return res; 204} 205 206status_t GraphicBuffer::unlock() 207{ 208 status_t res = getBufferMapper().unlock(handle); 209 return res; 210} 211 212status_t GraphicBuffer::lockAsync(uint32_t usage, void** vaddr, int fenceFd) 213{ 214 const Rect lockBounds(width, height); 215 status_t res = lockAsync(usage, lockBounds, vaddr, fenceFd); 216 return res; 217} 218 219status_t GraphicBuffer::lockAsync(uint32_t usage, const Rect& rect, void** vaddr, int fenceFd) 220{ 221 if (rect.left < 0 || rect.right > this->width || 222 rect.top < 0 || rect.bottom > this->height) { 223 ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)", 224 rect.left, rect.top, rect.right, rect.bottom, 225 this->width, this->height); 226 return BAD_VALUE; 227 } 228 status_t res = getBufferMapper().lockAsync(handle, usage, rect, vaddr, fenceFd); 229 return res; 230} 231 232status_t GraphicBuffer::lockAsyncYCbCr(uint32_t usage, android_ycbcr *ycbcr, int fenceFd) 233{ 234 const Rect lockBounds(width, height); 235 status_t res = lockAsyncYCbCr(usage, lockBounds, ycbcr, fenceFd); 236 return res; 237} 238 239status_t GraphicBuffer::lockAsyncYCbCr(uint32_t usage, const Rect& rect, android_ycbcr *ycbcr, int fenceFd) 240{ 241 if (rect.left < 0 || rect.right > this->width || 242 rect.top < 0 || rect.bottom > this->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 this->width, this->height); 246 return BAD_VALUE; 247 } 248 status_t res = getBufferMapper().lockAsyncYCbCr(handle, usage, rect, ycbcr, fenceFd); 249 return res; 250} 251 252status_t GraphicBuffer::unlockAsync(int *fenceFd) 253{ 254 status_t res = getBufferMapper().unlockAsync(handle, fenceFd); 255 return res; 256} 257 258size_t GraphicBuffer::getFlattenedSize() const { 259 return (10 + (handle ? handle->numInts : 0))*sizeof(int); 260} 261 262size_t GraphicBuffer::getFdCount() const { 263 return handle ? handle->numFds : 0; 264} 265 266status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const { 267 size_t sizeNeeded = GraphicBuffer::getFlattenedSize(); 268 if (size < sizeNeeded) return NO_MEMORY; 269 270 size_t fdCountNeeded = GraphicBuffer::getFdCount(); 271 if (count < fdCountNeeded) return NO_MEMORY; 272 273 int32_t* buf = static_cast<int32_t*>(buffer); 274 buf[0] = 'GBFR'; 275 buf[1] = width; 276 buf[2] = height; 277 buf[3] = stride; 278 buf[4] = format; 279 buf[5] = usage; 280 buf[6] = static_cast<int32_t>(mId >> 32); 281 buf[7] = static_cast<int32_t>(mId & 0xFFFFFFFFull); 282 buf[8] = 0; 283 buf[9] = 0; 284 285 if (handle) { 286 buf[8] = handle->numFds; 287 buf[9] = handle->numInts; 288 native_handle_t const* const h = handle; 289 memcpy(fds, h->data, h->numFds*sizeof(int)); 290 memcpy(&buf[10], h->data + h->numFds, h->numInts*sizeof(int)); 291 } 292 293 buffer = reinterpret_cast<void*>(static_cast<int*>(buffer) + sizeNeeded); 294 size -= sizeNeeded; 295 if (handle) { 296 fds += handle->numFds; 297 count -= handle->numFds; 298 } 299 300 return NO_ERROR; 301} 302 303status_t GraphicBuffer::unflatten( 304 void const*& buffer, size_t& size, int const*& fds, size_t& count) { 305 if (size < 8*sizeof(int)) return NO_MEMORY; 306 307 int const* buf = static_cast<int const*>(buffer); 308 if (buf[0] != 'GBFR') return BAD_TYPE; 309 310 const size_t numFds = buf[8]; 311 const size_t numInts = buf[9]; 312 313 const size_t maxNumber = UINT_MAX / sizeof(int); 314 if (numFds >= maxNumber || numInts >= (maxNumber - 10)) { 315 width = height = stride = format = usage = 0; 316 handle = NULL; 317 ALOGE("unflatten: numFds or numInts is too large: %d, %d", 318 numFds, numInts); 319 return BAD_VALUE; 320 } 321 322 const size_t sizeNeeded = (10 + numInts) * sizeof(int); 323 if (size < sizeNeeded) return NO_MEMORY; 324 325 size_t fdCountNeeded = numFds; 326 if (count < fdCountNeeded) return NO_MEMORY; 327 328 if (handle) { 329 // free previous handle if any 330 free_handle(); 331 } 332 333 if (numFds || numInts) { 334 width = buf[1]; 335 height = buf[2]; 336 stride = buf[3]; 337 format = buf[4]; 338 usage = buf[5]; 339 native_handle* h = native_handle_create(numFds, numInts); 340 if (!h) { 341 width = height = stride = format = usage = 0; 342 handle = NULL; 343 ALOGE("unflatten: native_handle_create failed"); 344 return NO_MEMORY; 345 } 346 memcpy(h->data, fds, numFds*sizeof(int)); 347 memcpy(h->data + numFds, &buf[10], numInts*sizeof(int)); 348 handle = h; 349 } else { 350 width = height = stride = format = usage = 0; 351 handle = NULL; 352 } 353 354 mId = static_cast<uint64_t>(buf[6]) << 32; 355 mId |= static_cast<uint32_t>(buf[7]); 356 357 mOwner = ownHandle; 358 359 if (handle != 0) { 360 status_t err = mBufferMapper.registerBuffer(handle); 361 if (err != NO_ERROR) { 362 width = height = stride = format = usage = 0; 363 handle = NULL; 364 ALOGE("unflatten: registerBuffer failed: %s (%d)", 365 strerror(-err), err); 366 return err; 367 } 368 } 369 370 buffer = reinterpret_cast<void const*>(static_cast<int const*>(buffer) + sizeNeeded); 371 size -= sizeNeeded; 372 fds += numFds; 373 count -= numFds; 374 375 return NO_ERROR; 376} 377 378// --------------------------------------------------------------------------- 379 380}; // namespace android 381