| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 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 |  | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 17 | #define LOG_TAG "GraphicBuffer" | 
 | 18 |  | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 19 | #include <stdlib.h> | 
 | 20 | #include <stdint.h> | 
 | 21 | #include <sys/types.h> | 
 | 22 |  | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 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 |  | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 31 | namespace android { | 
 | 32 |  | 
 | 33 | // =========================================================================== | 
| Iliyan Malchev | 697526b | 2011-05-01 11:33:26 -0700 | [diff] [blame] | 34 | // Buffer and implementation of ANativeWindowBuffer | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 35 | // =========================================================================== | 
 | 36 |  | 
| Dan Stoza | b1363d3 | 2014-03-28 15:10:52 -0700 | [diff] [blame] | 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 |  | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 44 | GraphicBuffer::GraphicBuffer() | 
| Mathias Agopian | 54ba51d | 2009-10-26 20:12:37 -0700 | [diff] [blame] | 45 |     : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()), | 
| Dan Stoza | b1363d3 | 2014-03-28 15:10:52 -0700 | [diff] [blame] | 46 |       mInitCheck(NO_ERROR), mId(getUniqueId()) | 
 | 47 | { | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 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) | 
| Mathias Agopian | 54ba51d | 2009-10-26 20:12:37 -0700 | [diff] [blame] | 58 |     : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()), | 
| Dan Stoza | b1363d3 | 2014-03-28 15:10:52 -0700 | [diff] [blame] | 59 |       mInitCheck(NO_ERROR), mId(getUniqueId()) | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 60 | { | 
 | 61 |     width  =  | 
 | 62 |     height =  | 
 | 63 |     stride =  | 
 | 64 |     format =  | 
 | 65 |     usage  = 0; | 
 | 66 |     handle = NULL; | 
 | 67 |     mInitCheck = initSize(w, h, reqFormat, reqUsage); | 
 | 68 | } | 
 | 69 |  | 
| Mathias Agopian | 54ba51d | 2009-10-26 20:12:37 -0700 | [diff] [blame] | 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()), | 
| Dan Stoza | b1363d3 | 2014-03-28 15:10:52 -0700 | [diff] [blame] | 75 |       mInitCheck(NO_ERROR), mId(getUniqueId()) | 
| Mathias Agopian | 54ba51d | 2009-10-26 20:12:37 -0700 | [diff] [blame] | 76 | { | 
 | 77 |     width  = w; | 
 | 78 |     height = h; | 
 | 79 |     stride = inStride; | 
 | 80 |     format = inFormat; | 
 | 81 |     usage  = inUsage; | 
 | 82 |     handle = inHandle; | 
 | 83 | } | 
 | 84 |  | 
| Iliyan Malchev | 697526b | 2011-05-01 11:33:26 -0700 | [diff] [blame] | 85 | GraphicBuffer::GraphicBuffer(ANativeWindowBuffer* buffer, bool keepOwnership) | 
| Jamie Gennis | 309d3bb | 2010-10-07 13:46:55 -0700 | [diff] [blame] | 86 |     : BASE(), mOwner(keepOwnership ? ownHandle : ownNone), | 
 | 87 |       mBufferMapper(GraphicBufferMapper::get()), | 
| Dan Stoza | b1363d3 | 2014-03-28 15:10:52 -0700 | [diff] [blame] | 88 |       mInitCheck(NO_ERROR), mWrappedBuffer(buffer), mId(getUniqueId()) | 
| Jamie Gennis | 309d3bb | 2010-10-07 13:46:55 -0700 | [diff] [blame] | 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 |  | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 98 | GraphicBuffer::~GraphicBuffer() | 
 | 99 | { | 
 | 100 |     if (handle) { | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 101 |         free_handle(); | 
 | 102 |     } | 
 | 103 | } | 
 | 104 |  | 
 | 105 | void GraphicBuffer::free_handle() | 
 | 106 | { | 
 | 107 |     if (mOwner == ownHandle) { | 
| Jamie Gennis | 309d3bb | 2010-10-07 13:46:55 -0700 | [diff] [blame] | 108 |         mBufferMapper.unregisterBuffer(handle); | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 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); | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 114 |     } | 
| Jamie Gennis | 309d3bb | 2010-10-07 13:46:55 -0700 | [diff] [blame] | 115 |     mWrappedBuffer = 0; | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 116 | } | 
 | 117 |  | 
 | 118 | status_t GraphicBuffer::initCheck() const { | 
 | 119 |     return mInitCheck; | 
 | 120 | } | 
 | 121 |  | 
| Mathias Agopian | 678bdd6 | 2010-12-03 17:33:09 -0800 | [diff] [blame] | 122 | void GraphicBuffer::dumpAllocationsToSystemLog() | 
 | 123 | { | 
 | 124 |     GraphicBufferAllocator::dumpToSystemLog(); | 
 | 125 | } | 
 | 126 |  | 
| Iliyan Malchev | 697526b | 2011-05-01 11:33:26 -0700 | [diff] [blame] | 127 | ANativeWindowBuffer* GraphicBuffer::getNativeBuffer() const | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 128 | { | 
| Iliyan Malchev | 697526b | 2011-05-01 11:33:26 -0700 | [diff] [blame] | 129 |     return static_cast<ANativeWindowBuffer*>( | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 130 |             const_cast<GraphicBuffer*>(this)); | 
 | 131 | } | 
 | 132 |  | 
 | 133 | status_t GraphicBuffer::reallocate(uint32_t w, uint32_t h, PixelFormat f, | 
 | 134 |         uint32_t reqUsage) | 
 | 135 | { | 
| Mathias Agopian | 54ba51d | 2009-10-26 20:12:37 -0700 | [diff] [blame] | 136 |     if (mOwner != ownData) | 
 | 137 |         return INVALID_OPERATION; | 
 | 138 |  | 
| Mathias Agopian | 579b3f8 | 2010-06-08 19:54:15 -0700 | [diff] [blame] | 139 |     if (handle && w==width && h==height && f==format && reqUsage==usage) | 
 | 140 |         return NO_ERROR; | 
 | 141 |  | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 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 |  | 
 | 150 | status_t GraphicBuffer::initSize(uint32_t w, uint32_t h, PixelFormat format, | 
 | 151 |         uint32_t reqUsage) | 
 | 152 | { | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 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; | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 160 |     } | 
 | 161 |     return err; | 
 | 162 | } | 
 | 163 |  | 
 | 164 | status_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 |  | 
 | 171 | status_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) { | 
| Steve Block | e6f43dd | 2012-01-06 19:20:56 +0000 | [diff] [blame] | 175 |         ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)", | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 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 |  | 
| Eino-Ville Talvala | c43946b | 2013-05-04 18:07:43 -0700 | [diff] [blame] | 184 | status_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 |  | 
 | 191 | status_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 |  | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 205 | status_t GraphicBuffer::unlock() | 
 | 206 | { | 
 | 207 |     status_t res = getBufferMapper().unlock(handle); | 
 | 208 |     return res; | 
 | 209 | } | 
 | 210 |  | 
| Francis Hart | 8f39601 | 2014-04-01 15:30:53 +0300 | [diff] [blame] | 211 | status_t GraphicBuffer::lockAsync(uint32_t usage, void** vaddr, int fenceFd) | 
 | 212 | { | 
 | 213 |     const Rect lockBounds(width, height); | 
 | 214 |     status_t res = lockAsync(usage, lockBounds, vaddr, fenceFd); | 
 | 215 |     return res; | 
 | 216 | } | 
 | 217 |  | 
 | 218 | status_t GraphicBuffer::lockAsync(uint32_t usage, const Rect& rect, void** vaddr, int fenceFd) | 
 | 219 | { | 
 | 220 |     if (rect.left < 0 || rect.right  > this->width || | 
 | 221 |         rect.top  < 0 || rect.bottom > this->height) { | 
 | 222 |         ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)", | 
 | 223 |                 rect.left, rect.top, rect.right, rect.bottom, | 
 | 224 |                 this->width, this->height); | 
 | 225 |         return BAD_VALUE; | 
 | 226 |     } | 
 | 227 |     status_t res = getBufferMapper().lockAsync(handle, usage, rect, vaddr, fenceFd); | 
 | 228 |     return res; | 
 | 229 | } | 
 | 230 |  | 
 | 231 | status_t GraphicBuffer::lockAsyncYCbCr(uint32_t usage, android_ycbcr *ycbcr, int fenceFd) | 
 | 232 | { | 
 | 233 |     const Rect lockBounds(width, height); | 
 | 234 |     status_t res = lockAsyncYCbCr(usage, lockBounds, ycbcr, fenceFd); | 
 | 235 |     return res; | 
 | 236 | } | 
 | 237 |  | 
 | 238 | status_t GraphicBuffer::lockAsyncYCbCr(uint32_t usage, const Rect& rect, android_ycbcr *ycbcr, int fenceFd) | 
 | 239 | { | 
 | 240 |     if (rect.left < 0 || rect.right  > this->width || | 
 | 241 |         rect.top  < 0 || rect.bottom > this->height) { | 
 | 242 |         ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)", | 
 | 243 |                 rect.left, rect.top, rect.right, rect.bottom, | 
 | 244 |                 this->width, this->height); | 
 | 245 |         return BAD_VALUE; | 
 | 246 |     } | 
 | 247 |     status_t res = getBufferMapper().lockAsyncYCbCr(handle, usage, rect, ycbcr, fenceFd); | 
 | 248 |     return res; | 
 | 249 | } | 
 | 250 |  | 
 | 251 | status_t GraphicBuffer::unlockAsync(int *fenceFd) | 
 | 252 | { | 
 | 253 |     status_t res = getBufferMapper().unlockAsync(handle, fenceFd); | 
 | 254 |     return res; | 
 | 255 | } | 
 | 256 |  | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 257 | size_t GraphicBuffer::getFlattenedSize() const { | 
| Dan Stoza | b1363d3 | 2014-03-28 15:10:52 -0700 | [diff] [blame] | 258 |     return (10 + (handle ? handle->numInts : 0))*sizeof(int); | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 259 | } | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 260 |  | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 261 | size_t GraphicBuffer::getFdCount() const { | 
 | 262 |     return handle ? handle->numFds : 0; | 
 | 263 | } | 
 | 264 |  | 
| Mathias Agopian | e142428 | 2013-07-29 21:24:40 -0700 | [diff] [blame] | 265 | status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const { | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 266 |     size_t sizeNeeded = GraphicBuffer::getFlattenedSize(); | 
 | 267 |     if (size < sizeNeeded) return NO_MEMORY; | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 268 |  | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 269 |     size_t fdCountNeeded = GraphicBuffer::getFdCount(); | 
 | 270 |     if (count < fdCountNeeded) return NO_MEMORY; | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 271 |  | 
| Dan Stoza | b1363d3 | 2014-03-28 15:10:52 -0700 | [diff] [blame] | 272 |     int32_t* buf = static_cast<int32_t*>(buffer); | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 273 |     buf[0] = 'GBFR'; | 
 | 274 |     buf[1] = width; | 
 | 275 |     buf[2] = height; | 
 | 276 |     buf[3] = stride; | 
 | 277 |     buf[4] = format; | 
 | 278 |     buf[5] = usage; | 
| Dan Stoza | b1363d3 | 2014-03-28 15:10:52 -0700 | [diff] [blame] | 279 |     buf[6] = static_cast<int32_t>(mId >> 32); | 
 | 280 |     buf[7] = static_cast<int32_t>(mId & 0xFFFFFFFFull); | 
 | 281 |     buf[8] = 0; | 
 | 282 |     buf[9] = 0; | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 283 |  | 
 | 284 |     if (handle) { | 
| Dan Stoza | b1363d3 | 2014-03-28 15:10:52 -0700 | [diff] [blame] | 285 |         buf[8] = handle->numFds; | 
 | 286 |         buf[9] = handle->numInts; | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 287 |         native_handle_t const* const h = handle; | 
 | 288 |         memcpy(fds,     h->data,             h->numFds*sizeof(int)); | 
| Dan Stoza | b1363d3 | 2014-03-28 15:10:52 -0700 | [diff] [blame] | 289 |         memcpy(&buf[10], h->data + h->numFds, h->numInts*sizeof(int)); | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 290 |     } | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 291 |  | 
| Mathias Agopian | e142428 | 2013-07-29 21:24:40 -0700 | [diff] [blame] | 292 |     buffer = reinterpret_cast<void*>(static_cast<int*>(buffer) + sizeNeeded); | 
 | 293 |     size -= sizeNeeded; | 
| Andy McFadden | bc96e47 | 2014-03-17 16:48:23 -0700 | [diff] [blame] | 294 |     if (handle) { | 
 | 295 |         fds += handle->numFds; | 
 | 296 |         count -= handle->numFds; | 
 | 297 |     } | 
| Mathias Agopian | e142428 | 2013-07-29 21:24:40 -0700 | [diff] [blame] | 298 |  | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 299 |     return NO_ERROR; | 
 | 300 | } | 
 | 301 |  | 
| Mathias Agopian | e142428 | 2013-07-29 21:24:40 -0700 | [diff] [blame] | 302 | status_t GraphicBuffer::unflatten( | 
 | 303 |         void const*& buffer, size_t& size, int const*& fds, size_t& count) { | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 304 |     if (size < 8*sizeof(int)) return NO_MEMORY; | 
 | 305 |  | 
 | 306 |     int const* buf = static_cast<int const*>(buffer); | 
 | 307 |     if (buf[0] != 'GBFR') return BAD_TYPE; | 
 | 308 |  | 
| Dan Stoza | b1363d3 | 2014-03-28 15:10:52 -0700 | [diff] [blame] | 309 |     const size_t numFds  = buf[8]; | 
 | 310 |     const size_t numInts = buf[9]; | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 311 |  | 
| Dan Stoza | b1363d3 | 2014-03-28 15:10:52 -0700 | [diff] [blame] | 312 |     const size_t sizeNeeded = (10 + numInts) * sizeof(int); | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 313 |     if (size < sizeNeeded) return NO_MEMORY; | 
 | 314 |  | 
 | 315 |     size_t fdCountNeeded = 0; | 
 | 316 |     if (count < fdCountNeeded) return NO_MEMORY; | 
 | 317 |  | 
 | 318 |     if (handle) { | 
 | 319 |         // free previous handle if any | 
 | 320 |         free_handle(); | 
 | 321 |     } | 
 | 322 |  | 
 | 323 |     if (numFds || numInts) { | 
 | 324 |         width  = buf[1]; | 
 | 325 |         height = buf[2]; | 
 | 326 |         stride = buf[3]; | 
 | 327 |         format = buf[4]; | 
 | 328 |         usage  = buf[5]; | 
 | 329 |         native_handle* h = native_handle_create(numFds, numInts); | 
 | 330 |         memcpy(h->data,          fds,     numFds*sizeof(int)); | 
| Dan Stoza | b1363d3 | 2014-03-28 15:10:52 -0700 | [diff] [blame] | 331 |         memcpy(h->data + numFds, &buf[10], numInts*sizeof(int)); | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 332 |         handle = h; | 
 | 333 |     } else { | 
 | 334 |         width = height = stride = format = usage = 0; | 
 | 335 |         handle = NULL; | 
 | 336 |     } | 
 | 337 |  | 
| Dan Stoza | b1363d3 | 2014-03-28 15:10:52 -0700 | [diff] [blame] | 338 |     mId = static_cast<uint64_t>(buf[6]) << 32; | 
 | 339 |     mId |= static_cast<uint32_t>(buf[7]); | 
 | 340 |  | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 341 |     mOwner = ownHandle; | 
| Jamie Gennis | 309d3bb | 2010-10-07 13:46:55 -0700 | [diff] [blame] | 342 |  | 
 | 343 |     if (handle != 0) { | 
| Jamie Gennis | d69097f | 2012-08-30 13:28:23 -0700 | [diff] [blame] | 344 |         status_t err = mBufferMapper.registerBuffer(handle); | 
 | 345 |         if (err != NO_ERROR) { | 
| Lingyun Zhu | 2aff702 | 2012-11-20 19:24:35 +0800 | [diff] [blame] | 346 |             width = height = stride = format = usage = 0; | 
 | 347 |             handle = NULL; | 
| Jamie Gennis | d69097f | 2012-08-30 13:28:23 -0700 | [diff] [blame] | 348 |             ALOGE("unflatten: registerBuffer failed: %s (%d)", | 
 | 349 |                     strerror(-err), err); | 
 | 350 |             return err; | 
 | 351 |         } | 
| Jamie Gennis | 309d3bb | 2010-10-07 13:46:55 -0700 | [diff] [blame] | 352 |     } | 
 | 353 |  | 
| Mathias Agopian | e142428 | 2013-07-29 21:24:40 -0700 | [diff] [blame] | 354 |     buffer = reinterpret_cast<void const*>(static_cast<int const*>(buffer) + sizeNeeded); | 
 | 355 |     size -= sizeNeeded; | 
 | 356 |     fds += numFds; | 
 | 357 |     count -= numFds; | 
 | 358 |  | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 359 |     return NO_ERROR; | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 360 | } | 
 | 361 |  | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 362 | // --------------------------------------------------------------------------- | 
 | 363 |  | 
 | 364 | }; // namespace android |