GraphicBuffer.cpp revision 2f3dca149a2bcae96f18e38f7ba99a95c3e1b08c
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 return static_cast<ANativeWindowBuffer*>( 130 const_cast<GraphicBuffer*>(this)); 131} 132 133status_t GraphicBuffer::reallocate(uint32_t w, uint32_t h, PixelFormat f, 134 uint32_t reqUsage) 135{ 136 if (mOwner != ownData) 137 return INVALID_OPERATION; 138 139 if (handle && w==width && h==height && f==format && reqUsage==usage) 140 return NO_ERROR; 141 142 if (handle) { 143 GraphicBufferAllocator& allocator(GraphicBufferAllocator::get()); 144 allocator.free(handle); 145 handle = 0; 146 } 147 return initSize(w, h, f, reqUsage); 148} 149 150status_t GraphicBuffer::initSize(uint32_t w, uint32_t h, PixelFormat format, 151 uint32_t reqUsage) 152{ 153 GraphicBufferAllocator& allocator = GraphicBufferAllocator::get(); 154 status_t err = allocator.alloc(w, h, format, reqUsage, &handle, &stride); 155 if (err == NO_ERROR) { 156 this->width = w; 157 this->height = h; 158 this->format = format; 159 this->usage = reqUsage; 160 } 161 return err; 162} 163 164status_t GraphicBuffer::lock(uint32_t usage, void** vaddr) 165{ 166 const Rect lockBounds(width, height); 167 status_t res = lock(usage, lockBounds, vaddr); 168 return res; 169} 170 171status_t GraphicBuffer::lock(uint32_t usage, const Rect& rect, void** vaddr) 172{ 173 if (rect.left < 0 || rect.right > this->width || 174 rect.top < 0 || rect.bottom > this->height) { 175 ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)", 176 rect.left, rect.top, rect.right, rect.bottom, 177 this->width, this->height); 178 return BAD_VALUE; 179 } 180 status_t res = getBufferMapper().lock(handle, usage, rect, vaddr); 181 return res; 182} 183 184status_t GraphicBuffer::lockYCbCr(uint32_t usage, android_ycbcr *ycbcr) 185{ 186 const Rect lockBounds(width, height); 187 status_t res = lockYCbCr(usage, lockBounds, ycbcr); 188 return res; 189} 190 191status_t GraphicBuffer::lockYCbCr(uint32_t usage, const Rect& rect, 192 android_ycbcr *ycbcr) 193{ 194 if (rect.left < 0 || rect.right > this->width || 195 rect.top < 0 || rect.bottom > this->height) { 196 ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)", 197 rect.left, rect.top, rect.right, rect.bottom, 198 this->width, this->height); 199 return BAD_VALUE; 200 } 201 status_t res = getBufferMapper().lockYCbCr(handle, usage, rect, ycbcr); 202 return res; 203} 204 205status_t GraphicBuffer::unlock() 206{ 207 status_t res = getBufferMapper().unlock(handle); 208 return res; 209} 210 211size_t GraphicBuffer::getFlattenedSize() const { 212 return (10 + (handle ? handle->numInts : 0))*sizeof(int); 213} 214 215size_t GraphicBuffer::getFdCount() const { 216 return handle ? handle->numFds : 0; 217} 218 219status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const { 220 size_t sizeNeeded = GraphicBuffer::getFlattenedSize(); 221 if (size < sizeNeeded) return NO_MEMORY; 222 223 size_t fdCountNeeded = GraphicBuffer::getFdCount(); 224 if (count < fdCountNeeded) return NO_MEMORY; 225 226 int32_t* buf = static_cast<int32_t*>(buffer); 227 buf[0] = 'GBFR'; 228 buf[1] = width; 229 buf[2] = height; 230 buf[3] = stride; 231 buf[4] = format; 232 buf[5] = usage; 233 buf[6] = static_cast<int32_t>(mId >> 32); 234 buf[7] = static_cast<int32_t>(mId & 0xFFFFFFFFull); 235 buf[8] = 0; 236 buf[9] = 0; 237 238 if (handle) { 239 buf[8] = handle->numFds; 240 buf[9] = handle->numInts; 241 native_handle_t const* const h = handle; 242 memcpy(fds, h->data, h->numFds*sizeof(int)); 243 memcpy(&buf[10], h->data + h->numFds, h->numInts*sizeof(int)); 244 } 245 246 buffer = reinterpret_cast<void*>(static_cast<int*>(buffer) + sizeNeeded); 247 size -= sizeNeeded; 248 if (handle) { 249 fds += handle->numFds; 250 count -= handle->numFds; 251 } 252 253 return NO_ERROR; 254} 255 256status_t GraphicBuffer::unflatten( 257 void const*& buffer, size_t& size, int const*& fds, size_t& count) { 258 if (size < 8*sizeof(int)) return NO_MEMORY; 259 260 int const* buf = static_cast<int const*>(buffer); 261 if (buf[0] != 'GBFR') return BAD_TYPE; 262 263 const size_t numFds = buf[8]; 264 const size_t numInts = buf[9]; 265 266 const size_t sizeNeeded = (10 + numInts) * sizeof(int); 267 if (size < sizeNeeded) return NO_MEMORY; 268 269 size_t fdCountNeeded = 0; 270 if (count < fdCountNeeded) return NO_MEMORY; 271 272 if (handle) { 273 // free previous handle if any 274 free_handle(); 275 } 276 277 if (numFds || numInts) { 278 width = buf[1]; 279 height = buf[2]; 280 stride = buf[3]; 281 format = buf[4]; 282 usage = buf[5]; 283 native_handle* h = native_handle_create(numFds, numInts); 284 memcpy(h->data, fds, numFds*sizeof(int)); 285 memcpy(h->data + numFds, &buf[10], numInts*sizeof(int)); 286 handle = h; 287 } else { 288 width = height = stride = format = usage = 0; 289 handle = NULL; 290 } 291 292 mId = static_cast<uint64_t>(buf[6]) << 32; 293 mId |= static_cast<uint32_t>(buf[7]); 294 295 mOwner = ownHandle; 296 297 if (handle != 0) { 298 status_t err = mBufferMapper.registerBuffer(handle); 299 if (err != NO_ERROR) { 300 width = height = stride = format = usage = 0; 301 handle = NULL; 302 ALOGE("unflatten: registerBuffer failed: %s (%d)", 303 strerror(-err), err); 304 return err; 305 } 306 } 307 308 buffer = reinterpret_cast<void const*>(static_cast<int const*>(buffer) + sizeNeeded); 309 size -= sizeNeeded; 310 fds += numFds; 311 count -= numFds; 312 313 return NO_ERROR; 314} 315 316// --------------------------------------------------------------------------- 317 318}; // namespace android 319