GraphicBuffer.cpp revision e2d1157381b863a94ccb36a1c6d70cad47e79c1a
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 203size_t GraphicBuffer::getFlattenedSize() const { 204 return (8 + (handle ? handle->numInts : 0))*sizeof(int); 205} 206 207size_t GraphicBuffer::getFdCount() const { 208 return handle ? handle->numFds : 0; 209} 210 211status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const { 212 size_t sizeNeeded = GraphicBuffer::getFlattenedSize(); 213 if (size < sizeNeeded) return NO_MEMORY; 214 215 size_t fdCountNeeded = GraphicBuffer::getFdCount(); 216 if (count < fdCountNeeded) return NO_MEMORY; 217 218 int* buf = static_cast<int*>(buffer); 219 buf[0] = 'GBFR'; 220 buf[1] = width; 221 buf[2] = height; 222 buf[3] = stride; 223 buf[4] = format; 224 buf[5] = usage; 225 buf[6] = 0; 226 buf[7] = 0; 227 228 if (handle) { 229 buf[6] = handle->numFds; 230 buf[7] = handle->numInts; 231 native_handle_t const* const h = handle; 232 memcpy(fds, h->data, h->numFds*sizeof(int)); 233 memcpy(&buf[8], h->data + h->numFds, h->numInts*sizeof(int)); 234 } 235 236 buffer = reinterpret_cast<void*>(static_cast<int*>(buffer) + sizeNeeded); 237 size -= sizeNeeded; 238 if (handle) { 239 fds += handle->numFds; 240 count -= handle->numFds; 241 } 242 243 return NO_ERROR; 244} 245 246status_t GraphicBuffer::unflatten( 247 void const*& buffer, size_t& size, int const*& fds, size_t& count) { 248 if (size < 8*sizeof(int)) return NO_MEMORY; 249 250 int const* buf = static_cast<int const*>(buffer); 251 if (buf[0] != 'GBFR') return BAD_TYPE; 252 253 const size_t numFds = buf[6]; 254 const size_t numInts = buf[7]; 255 256 const size_t sizeNeeded = (8 + numInts) * sizeof(int); 257 if (size < sizeNeeded) return NO_MEMORY; 258 259 size_t fdCountNeeded = 0; 260 if (count < fdCountNeeded) return NO_MEMORY; 261 262 if (handle) { 263 // free previous handle if any 264 free_handle(); 265 } 266 267 if (numFds || numInts) { 268 width = buf[1]; 269 height = buf[2]; 270 stride = buf[3]; 271 format = buf[4]; 272 usage = buf[5]; 273 native_handle* h = native_handle_create(numFds, numInts); 274 memcpy(h->data, fds, numFds*sizeof(int)); 275 memcpy(h->data + numFds, &buf[8], numInts*sizeof(int)); 276 handle = h; 277 } else { 278 width = height = stride = format = usage = 0; 279 handle = NULL; 280 } 281 282 mOwner = ownHandle; 283 284 if (handle != 0) { 285 status_t err = mBufferMapper.registerBuffer(handle); 286 if (err != NO_ERROR) { 287 width = height = stride = format = usage = 0; 288 handle = NULL; 289 ALOGE("unflatten: registerBuffer failed: %s (%d)", 290 strerror(-err), err); 291 return err; 292 } 293 } 294 295 buffer = reinterpret_cast<void const*>(static_cast<int const*>(buffer) + sizeNeeded); 296 size -= sizeNeeded; 297 fds += numFds; 298 count -= numFds; 299 300 return NO_ERROR; 301} 302 303// --------------------------------------------------------------------------- 304 305}; // namespace android 306