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