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 31 namespace android { 32 33 // =========================================================================== 34 // Buffer and implementation of ANativeWindowBuffer 35 // =========================================================================== 36 37 GraphicBuffer::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 48 GraphicBuffer::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 62 GraphicBuffer::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 77 GraphicBuffer::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 90 GraphicBuffer::~GraphicBuffer() 91 { 92 if (handle) { 93 free_handle(); 94 } 95 } 96 97 void 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 110 status_t GraphicBuffer::initCheck() const { 111 return mInitCheck; 112 } 113 114 void GraphicBuffer::dumpAllocationsToSystemLog() 115 { 116 GraphicBufferAllocator::dumpToSystemLog(); 117 } 118 119 ANativeWindowBuffer* GraphicBuffer::getNativeBuffer() const 120 { 121 return static_cast<ANativeWindowBuffer*>( 122 const_cast<GraphicBuffer*>(this)); 123 } 124 125 status_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 142 status_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 156 status_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 163 status_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 176 status_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 183 status_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 197 status_t GraphicBuffer::unlock() 198 { 199 status_t res = getBufferMapper().unlock(handle); 200 return res; 201 } 202 203 size_t GraphicBuffer::getFlattenedSize() const { 204 return (8 + (handle ? handle->numInts : 0))*sizeof(int); 205 } 206 207 size_t GraphicBuffer::getFdCount() const { 208 return handle ? handle->numFds : 0; 209 } 210 211 status_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 fds += handle->numFds; 239 count -= handle->numFds; 240 241 return NO_ERROR; 242 } 243 244 status_t GraphicBuffer::unflatten( 245 void const*& buffer, size_t& size, int const*& fds, size_t& count) { 246 if (size < 8*sizeof(int)) return NO_MEMORY; 247 248 int const* buf = static_cast<int const*>(buffer); 249 if (buf[0] != 'GBFR') return BAD_TYPE; 250 251 const size_t numFds = buf[6]; 252 const size_t numInts = buf[7]; 253 254 const size_t sizeNeeded = (8 + numInts) * sizeof(int); 255 if (size < sizeNeeded) return NO_MEMORY; 256 257 size_t fdCountNeeded = 0; 258 if (count < fdCountNeeded) return NO_MEMORY; 259 260 if (handle) { 261 // free previous handle if any 262 free_handle(); 263 } 264 265 if (numFds || numInts) { 266 width = buf[1]; 267 height = buf[2]; 268 stride = buf[3]; 269 format = buf[4]; 270 usage = buf[5]; 271 native_handle* h = native_handle_create(numFds, numInts); 272 memcpy(h->data, fds, numFds*sizeof(int)); 273 memcpy(h->data + numFds, &buf[8], numInts*sizeof(int)); 274 handle = h; 275 } else { 276 width = height = stride = format = usage = 0; 277 handle = NULL; 278 } 279 280 mOwner = ownHandle; 281 282 if (handle != 0) { 283 status_t err = mBufferMapper.registerBuffer(handle); 284 if (err != NO_ERROR) { 285 ALOGE("unflatten: registerBuffer failed: %s (%d)", 286 strerror(-err), err); 287 return err; 288 } 289 } 290 291 buffer = reinterpret_cast<void const*>(static_cast<int const*>(buffer) + sizeNeeded); 292 size -= sizeNeeded; 293 fds += numFds; 294 count -= numFds; 295 296 return NO_ERROR; 297 } 298 299 // --------------------------------------------------------------------------- 300 301 }; // namespace android 302