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