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