| 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()), | 
| Pablo Ceballos | 53390e1 | 2015-08-04 11:25:59 -0700 | [diff] [blame] | 46 |       mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0) | 
| Dan Stoza | b1363d3 | 2014-03-28 15:10:52 -0700 | [diff] [blame] | 47 | { | 
| Dan Stoza | 01049c8 | 2014-11-11 10:32:31 -0800 | [diff] [blame] | 48 |     width  = | 
 | 49 |     height = | 
 | 50 |     stride = | 
 | 51 |     format = | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 52 |     usage  = 0; | 
 | 53 |     handle = NULL; | 
 | 54 | } | 
 | 55 |  | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 56 | GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight, | 
| Dan Stoza | d4079af | 2016-08-22 17:26:41 -0700 | [diff] [blame] | 57 |         PixelFormat inFormat, uint32_t inUsage, std::string requestorName) | 
| Mathias Agopian | 54ba51d | 2009-10-26 20:12:37 -0700 | [diff] [blame] | 58 |     : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()), | 
| Pablo Ceballos | 53390e1 | 2015-08-04 11:25:59 -0700 | [diff] [blame] | 59 |       mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0) | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 60 | { | 
| Dan Stoza | 01049c8 | 2014-11-11 10:32:31 -0800 | [diff] [blame] | 61 |     width  = | 
 | 62 |     height = | 
 | 63 |     stride = | 
 | 64 |     format = | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 65 |     usage  = 0; | 
 | 66 |     handle = NULL; | 
| Dan Stoza | d4079af | 2016-08-22 17:26:41 -0700 | [diff] [blame] | 67 |     mInitCheck = initSize(inWidth, inHeight, inFormat, inUsage, | 
 | 68 |             std::move(requestorName)); | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 69 | } | 
 | 70 |  | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 71 | GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight, | 
 | 72 |         PixelFormat inFormat, uint32_t inUsage, uint32_t inStride, | 
 | 73 |         native_handle_t* inHandle, bool keepOwnership) | 
| Mathias Agopian | 54ba51d | 2009-10-26 20:12:37 -0700 | [diff] [blame] | 74 |     : BASE(), mOwner(keepOwnership ? ownHandle : ownNone), | 
 | 75 |       mBufferMapper(GraphicBufferMapper::get()), | 
| Pablo Ceballos | 53390e1 | 2015-08-04 11:25:59 -0700 | [diff] [blame] | 76 |       mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0) | 
| Mathias Agopian | 54ba51d | 2009-10-26 20:12:37 -0700 | [diff] [blame] | 77 | { | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 78 |     width  = static_cast<int>(inWidth); | 
 | 79 |     height = static_cast<int>(inHeight); | 
 | 80 |     stride = static_cast<int>(inStride); | 
| Mathias Agopian | 54ba51d | 2009-10-26 20:12:37 -0700 | [diff] [blame] | 81 |     format = inFormat; | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 82 |     usage  = static_cast<int>(inUsage); | 
| Mathias Agopian | 54ba51d | 2009-10-26 20:12:37 -0700 | [diff] [blame] | 83 |     handle = inHandle; | 
 | 84 | } | 
 | 85 |  | 
| Iliyan Malchev | 697526b | 2011-05-01 11:33:26 -0700 | [diff] [blame] | 86 | GraphicBuffer::GraphicBuffer(ANativeWindowBuffer* buffer, bool keepOwnership) | 
| Jamie Gennis | 309d3bb | 2010-10-07 13:46:55 -0700 | [diff] [blame] | 87 |     : BASE(), mOwner(keepOwnership ? ownHandle : ownNone), | 
 | 88 |       mBufferMapper(GraphicBufferMapper::get()), | 
| Pablo Ceballos | 53390e1 | 2015-08-04 11:25:59 -0700 | [diff] [blame] | 89 |       mInitCheck(NO_ERROR), mWrappedBuffer(buffer), mId(getUniqueId()), | 
 | 90 |       mGenerationNumber(0) | 
| Jamie Gennis | 309d3bb | 2010-10-07 13:46:55 -0700 | [diff] [blame] | 91 | { | 
 | 92 |     width  = buffer->width; | 
 | 93 |     height = buffer->height; | 
 | 94 |     stride = buffer->stride; | 
 | 95 |     format = buffer->format; | 
 | 96 |     usage  = buffer->usage; | 
 | 97 |     handle = buffer->handle; | 
 | 98 | } | 
 | 99 |  | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 100 | GraphicBuffer::~GraphicBuffer() | 
 | 101 | { | 
 | 102 |     if (handle) { | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 103 |         free_handle(); | 
 | 104 |     } | 
 | 105 | } | 
 | 106 |  | 
 | 107 | void GraphicBuffer::free_handle() | 
 | 108 | { | 
 | 109 |     if (mOwner == ownHandle) { | 
| Jamie Gennis | 309d3bb | 2010-10-07 13:46:55 -0700 | [diff] [blame] | 110 |         mBufferMapper.unregisterBuffer(handle); | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 111 |         native_handle_close(handle); | 
 | 112 |         native_handle_delete(const_cast<native_handle*>(handle)); | 
 | 113 |     } else if (mOwner == ownData) { | 
 | 114 |         GraphicBufferAllocator& allocator(GraphicBufferAllocator::get()); | 
 | 115 |         allocator.free(handle); | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 116 |     } | 
| Praveen Chavan | 22e4cc3 | 2015-09-16 11:20:00 -0700 | [diff] [blame] | 117 |     handle = NULL; | 
| Jamie Gennis | 309d3bb | 2010-10-07 13:46:55 -0700 | [diff] [blame] | 118 |     mWrappedBuffer = 0; | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 119 | } | 
 | 120 |  | 
 | 121 | status_t GraphicBuffer::initCheck() const { | 
| Dan Stoza | 133caac | 2014-12-01 15:15:31 -0800 | [diff] [blame] | 122 |     return static_cast<status_t>(mInitCheck); | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 123 | } | 
 | 124 |  | 
| Mathias Agopian | 678bdd6 | 2010-12-03 17:33:09 -0800 | [diff] [blame] | 125 | void GraphicBuffer::dumpAllocationsToSystemLog() | 
 | 126 | { | 
 | 127 |     GraphicBufferAllocator::dumpToSystemLog(); | 
 | 128 | } | 
 | 129 |  | 
| Iliyan Malchev | 697526b | 2011-05-01 11:33:26 -0700 | [diff] [blame] | 130 | ANativeWindowBuffer* GraphicBuffer::getNativeBuffer() const | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 131 | { | 
| Colin Cross | 18fae75 | 2014-07-22 15:55:08 -0700 | [diff] [blame] | 132 |     LOG_ALWAYS_FATAL_IF(this == NULL, "getNativeBuffer() called on NULL GraphicBuffer"); | 
| Iliyan Malchev | 697526b | 2011-05-01 11:33:26 -0700 | [diff] [blame] | 133 |     return static_cast<ANativeWindowBuffer*>( | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 134 |             const_cast<GraphicBuffer*>(this)); | 
 | 135 | } | 
 | 136 |  | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 137 | status_t GraphicBuffer::reallocate(uint32_t inWidth, uint32_t inHeight, | 
 | 138 |         PixelFormat inFormat, uint32_t inUsage) | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 139 | { | 
| Mathias Agopian | 54ba51d | 2009-10-26 20:12:37 -0700 | [diff] [blame] | 140 |     if (mOwner != ownData) | 
 | 141 |         return INVALID_OPERATION; | 
 | 142 |  | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 143 |     if (handle && | 
 | 144 |             static_cast<int>(inWidth) == width && | 
 | 145 |             static_cast<int>(inHeight) == height && | 
 | 146 |             inFormat == format && | 
 | 147 |             static_cast<int>(inUsage) == usage) | 
| Mathias Agopian | 579b3f8 | 2010-06-08 19:54:15 -0700 | [diff] [blame] | 148 |         return NO_ERROR; | 
 | 149 |  | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 150 |     if (handle) { | 
 | 151 |         GraphicBufferAllocator& allocator(GraphicBufferAllocator::get()); | 
 | 152 |         allocator.free(handle); | 
 | 153 |         handle = 0; | 
 | 154 |     } | 
| Dan Stoza | d4079af | 2016-08-22 17:26:41 -0700 | [diff] [blame] | 155 |     return initSize(inWidth, inHeight, inFormat, inUsage, "[Reallocation]"); | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 156 | } | 
 | 157 |  | 
| Dan Stoza | 9de7293 | 2015-04-16 17:28:43 -0700 | [diff] [blame] | 158 | bool GraphicBuffer::needsReallocation(uint32_t inWidth, uint32_t inHeight, | 
 | 159 |         PixelFormat inFormat, uint32_t inUsage) | 
 | 160 | { | 
 | 161 |     if (static_cast<int>(inWidth) != width) return true; | 
 | 162 |     if (static_cast<int>(inHeight) != height) return true; | 
 | 163 |     if (inFormat != format) return true; | 
 | 164 |     if ((static_cast<uint32_t>(usage) & inUsage) != inUsage) return true; | 
 | 165 |     return false; | 
 | 166 | } | 
 | 167 |  | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 168 | status_t GraphicBuffer::initSize(uint32_t inWidth, uint32_t inHeight, | 
| Dan Stoza | d4079af | 2016-08-22 17:26:41 -0700 | [diff] [blame] | 169 |         PixelFormat inFormat, uint32_t inUsage, std::string requestorName) | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 170 | { | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 171 |     GraphicBufferAllocator& allocator = GraphicBufferAllocator::get(); | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 172 |     uint32_t outStride = 0; | 
| Dan Stoza | 8deb4da | 2016-06-01 18:21:44 -0700 | [diff] [blame] | 173 |     status_t err = allocator.allocate(inWidth, inHeight, inFormat, inUsage, | 
| Dan Stoza | d4079af | 2016-08-22 17:26:41 -0700 | [diff] [blame] | 174 |             &handle, &outStride, mId, std::move(requestorName)); | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 175 |     if (err == NO_ERROR) { | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 176 |         width = static_cast<int>(inWidth); | 
 | 177 |         height = static_cast<int>(inHeight); | 
 | 178 |         format = inFormat; | 
 | 179 |         usage = static_cast<int>(inUsage); | 
 | 180 |         stride = static_cast<int>(outStride); | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 181 |     } | 
 | 182 |     return err; | 
 | 183 | } | 
 | 184 |  | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 185 | status_t GraphicBuffer::lock(uint32_t inUsage, void** vaddr) | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 186 | { | 
 | 187 |     const Rect lockBounds(width, height); | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 188 |     status_t res = lock(inUsage, lockBounds, vaddr); | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 189 |     return res; | 
 | 190 | } | 
 | 191 |  | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 192 | status_t GraphicBuffer::lock(uint32_t inUsage, const Rect& rect, void** vaddr) | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 193 | { | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 194 |     if (rect.left < 0 || rect.right  > width || | 
 | 195 |         rect.top  < 0 || rect.bottom > height) { | 
| Steve Block | e6f43dd | 2012-01-06 19:20:56 +0000 | [diff] [blame] | 196 |         ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)", | 
| Dan Stoza | 01049c8 | 2014-11-11 10:32:31 -0800 | [diff] [blame] | 197 |                 rect.left, rect.top, rect.right, rect.bottom, | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 198 |                 width, height); | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 199 |         return BAD_VALUE; | 
 | 200 |     } | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 201 |     status_t res = getBufferMapper().lock(handle, inUsage, rect, vaddr); | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 202 |     return res; | 
 | 203 | } | 
 | 204 |  | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 205 | status_t GraphicBuffer::lockYCbCr(uint32_t inUsage, android_ycbcr* ycbcr) | 
| Eino-Ville Talvala | c43946b | 2013-05-04 18:07:43 -0700 | [diff] [blame] | 206 | { | 
 | 207 |     const Rect lockBounds(width, height); | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 208 |     status_t res = lockYCbCr(inUsage, lockBounds, ycbcr); | 
| Eino-Ville Talvala | c43946b | 2013-05-04 18:07:43 -0700 | [diff] [blame] | 209 |     return res; | 
 | 210 | } | 
 | 211 |  | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 212 | status_t GraphicBuffer::lockYCbCr(uint32_t inUsage, const Rect& rect, | 
 | 213 |         android_ycbcr* ycbcr) | 
| Eino-Ville Talvala | c43946b | 2013-05-04 18:07:43 -0700 | [diff] [blame] | 214 | { | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 215 |     if (rect.left < 0 || rect.right  > width || | 
 | 216 |         rect.top  < 0 || rect.bottom > height) { | 
| Eino-Ville Talvala | c43946b | 2013-05-04 18:07:43 -0700 | [diff] [blame] | 217 |         ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)", | 
 | 218 |                 rect.left, rect.top, rect.right, rect.bottom, | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 219 |                 width, height); | 
| Eino-Ville Talvala | c43946b | 2013-05-04 18:07:43 -0700 | [diff] [blame] | 220 |         return BAD_VALUE; | 
 | 221 |     } | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 222 |     status_t res = getBufferMapper().lockYCbCr(handle, inUsage, rect, ycbcr); | 
| Eino-Ville Talvala | c43946b | 2013-05-04 18:07:43 -0700 | [diff] [blame] | 223 |     return res; | 
 | 224 | } | 
 | 225 |  | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 226 | status_t GraphicBuffer::unlock() | 
 | 227 | { | 
 | 228 |     status_t res = getBufferMapper().unlock(handle); | 
 | 229 |     return res; | 
 | 230 | } | 
 | 231 |  | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 232 | status_t GraphicBuffer::lockAsync(uint32_t inUsage, void** vaddr, int fenceFd) | 
| Francis Hart | 8f39601 | 2014-04-01 15:30:53 +0300 | [diff] [blame] | 233 | { | 
 | 234 |     const Rect lockBounds(width, height); | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 235 |     status_t res = lockAsync(inUsage, lockBounds, vaddr, fenceFd); | 
| Francis Hart | 8f39601 | 2014-04-01 15:30:53 +0300 | [diff] [blame] | 236 |     return res; | 
 | 237 | } | 
 | 238 |  | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 239 | status_t GraphicBuffer::lockAsync(uint32_t inUsage, const Rect& rect, | 
 | 240 |         void** vaddr, int fenceFd) | 
| Francis Hart | 8f39601 | 2014-04-01 15:30:53 +0300 | [diff] [blame] | 241 | { | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 242 |     if (rect.left < 0 || rect.right  > width || | 
 | 243 |         rect.top  < 0 || rect.bottom > height) { | 
| Francis Hart | 8f39601 | 2014-04-01 15:30:53 +0300 | [diff] [blame] | 244 |         ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)", | 
 | 245 |                 rect.left, rect.top, rect.right, rect.bottom, | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 246 |                 width, height); | 
| Francis Hart | 8f39601 | 2014-04-01 15:30:53 +0300 | [diff] [blame] | 247 |         return BAD_VALUE; | 
 | 248 |     } | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 249 |     status_t res = getBufferMapper().lockAsync(handle, inUsage, rect, vaddr, | 
 | 250 |             fenceFd); | 
| Francis Hart | 8f39601 | 2014-04-01 15:30:53 +0300 | [diff] [blame] | 251 |     return res; | 
 | 252 | } | 
 | 253 |  | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 254 | status_t GraphicBuffer::lockAsyncYCbCr(uint32_t inUsage, android_ycbcr* ycbcr, | 
 | 255 |         int fenceFd) | 
| Francis Hart | 8f39601 | 2014-04-01 15:30:53 +0300 | [diff] [blame] | 256 | { | 
 | 257 |     const Rect lockBounds(width, height); | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 258 |     status_t res = lockAsyncYCbCr(inUsage, lockBounds, ycbcr, fenceFd); | 
| Francis Hart | 8f39601 | 2014-04-01 15:30:53 +0300 | [diff] [blame] | 259 |     return res; | 
 | 260 | } | 
 | 261 |  | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 262 | status_t GraphicBuffer::lockAsyncYCbCr(uint32_t inUsage, const Rect& rect, | 
 | 263 |         android_ycbcr* ycbcr, int fenceFd) | 
| Francis Hart | 8f39601 | 2014-04-01 15:30:53 +0300 | [diff] [blame] | 264 | { | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 265 |     if (rect.left < 0 || rect.right  > width || | 
 | 266 |         rect.top  < 0 || rect.bottom > height) { | 
| Francis Hart | 8f39601 | 2014-04-01 15:30:53 +0300 | [diff] [blame] | 267 |         ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)", | 
 | 268 |                 rect.left, rect.top, rect.right, rect.bottom, | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 269 |                 width, height); | 
| Francis Hart | 8f39601 | 2014-04-01 15:30:53 +0300 | [diff] [blame] | 270 |         return BAD_VALUE; | 
 | 271 |     } | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 272 |     status_t res = getBufferMapper().lockAsyncYCbCr(handle, inUsage, rect, | 
 | 273 |             ycbcr, fenceFd); | 
| Francis Hart | 8f39601 | 2014-04-01 15:30:53 +0300 | [diff] [blame] | 274 |     return res; | 
 | 275 | } | 
 | 276 |  | 
 | 277 | status_t GraphicBuffer::unlockAsync(int *fenceFd) | 
 | 278 | { | 
 | 279 |     status_t res = getBufferMapper().unlockAsync(handle, fenceFd); | 
 | 280 |     return res; | 
 | 281 | } | 
 | 282 |  | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 283 | size_t GraphicBuffer::getFlattenedSize() const { | 
| Dan Stoza | 812ed06 | 2015-06-02 15:45:22 -0700 | [diff] [blame] | 284 |     return static_cast<size_t>(11 + (handle ? handle->numInts : 0)) * sizeof(int); | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 285 | } | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 286 |  | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 287 | size_t GraphicBuffer::getFdCount() const { | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 288 |     return static_cast<size_t>(handle ? handle->numFds : 0); | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 289 | } | 
 | 290 |  | 
| Mathias Agopian | e142428 | 2013-07-29 21:24:40 -0700 | [diff] [blame] | 291 | 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] | 292 |     size_t sizeNeeded = GraphicBuffer::getFlattenedSize(); | 
 | 293 |     if (size < sizeNeeded) return NO_MEMORY; | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 294 |  | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 295 |     size_t fdCountNeeded = GraphicBuffer::getFdCount(); | 
 | 296 |     if (count < fdCountNeeded) return NO_MEMORY; | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 297 |  | 
| Dan Stoza | b1363d3 | 2014-03-28 15:10:52 -0700 | [diff] [blame] | 298 |     int32_t* buf = static_cast<int32_t*>(buffer); | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 299 |     buf[0] = 'GBFR'; | 
 | 300 |     buf[1] = width; | 
 | 301 |     buf[2] = height; | 
 | 302 |     buf[3] = stride; | 
 | 303 |     buf[4] = format; | 
 | 304 |     buf[5] = usage; | 
| Dan Stoza | b1363d3 | 2014-03-28 15:10:52 -0700 | [diff] [blame] | 305 |     buf[6] = static_cast<int32_t>(mId >> 32); | 
 | 306 |     buf[7] = static_cast<int32_t>(mId & 0xFFFFFFFFull); | 
| Dan Stoza | 812ed06 | 2015-06-02 15:45:22 -0700 | [diff] [blame] | 307 |     buf[8] = static_cast<int32_t>(mGenerationNumber); | 
| Dan Stoza | b1363d3 | 2014-03-28 15:10:52 -0700 | [diff] [blame] | 308 |     buf[9] = 0; | 
| Dan Stoza | 812ed06 | 2015-06-02 15:45:22 -0700 | [diff] [blame] | 309 |     buf[10] = 0; | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 310 |  | 
 | 311 |     if (handle) { | 
| Dan Stoza | 812ed06 | 2015-06-02 15:45:22 -0700 | [diff] [blame] | 312 |         buf[9] = handle->numFds; | 
 | 313 |         buf[10] = handle->numInts; | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 314 |         memcpy(fds, handle->data, | 
 | 315 |                 static_cast<size_t>(handle->numFds) * sizeof(int)); | 
| Dan Stoza | 812ed06 | 2015-06-02 15:45:22 -0700 | [diff] [blame] | 316 |         memcpy(&buf[11], handle->data + handle->numFds, | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 317 |                 static_cast<size_t>(handle->numInts) * sizeof(int)); | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 318 |     } | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 319 |  | 
| Dan Stoza | eea6d68 | 2015-04-20 12:07:13 -0700 | [diff] [blame] | 320 |     buffer = static_cast<void*>(static_cast<uint8_t*>(buffer) + sizeNeeded); | 
| Mathias Agopian | e142428 | 2013-07-29 21:24:40 -0700 | [diff] [blame] | 321 |     size -= sizeNeeded; | 
| Andy McFadden | bc96e47 | 2014-03-17 16:48:23 -0700 | [diff] [blame] | 322 |     if (handle) { | 
 | 323 |         fds += handle->numFds; | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 324 |         count -= static_cast<size_t>(handle->numFds); | 
| Andy McFadden | bc96e47 | 2014-03-17 16:48:23 -0700 | [diff] [blame] | 325 |     } | 
| Mathias Agopian | e142428 | 2013-07-29 21:24:40 -0700 | [diff] [blame] | 326 |  | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 327 |     return NO_ERROR; | 
 | 328 | } | 
 | 329 |  | 
| Mathias Agopian | e142428 | 2013-07-29 21:24:40 -0700 | [diff] [blame] | 330 | status_t GraphicBuffer::unflatten( | 
 | 331 |         void const*& buffer, size_t& size, int const*& fds, size_t& count) { | 
| Dan Stoza | 812ed06 | 2015-06-02 15:45:22 -0700 | [diff] [blame] | 332 |     if (size < 11 * sizeof(int)) return NO_MEMORY; | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 333 |  | 
 | 334 |     int const* buf = static_cast<int const*>(buffer); | 
 | 335 |     if (buf[0] != 'GBFR') return BAD_TYPE; | 
 | 336 |  | 
| Dan Stoza | 812ed06 | 2015-06-02 15:45:22 -0700 | [diff] [blame] | 337 |     const size_t numFds  = static_cast<size_t>(buf[9]); | 
 | 338 |     const size_t numInts = static_cast<size_t>(buf[10]); | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 339 |  | 
| Michael Lentine | c168b8a | 2015-02-18 10:14:18 -0800 | [diff] [blame] | 340 |     // Limit the maxNumber to be relatively small. The number of fds or ints | 
 | 341 |     // should not come close to this number, and the number itself was simply | 
 | 342 |     // chosen to be high enough to not cause issues and low enough to prevent | 
 | 343 |     // overflow problems. | 
 | 344 |     const size_t maxNumber = 4096; | 
| Dan Stoza | 812ed06 | 2015-06-02 15:45:22 -0700 | [diff] [blame] | 345 |     if (numFds >= maxNumber || numInts >= (maxNumber - 11)) { | 
| Michael Lentine | 3880326 | 2014-10-31 15:25:03 -0700 | [diff] [blame] | 346 |         width = height = stride = format = usage = 0; | 
 | 347 |         handle = NULL; | 
| Dan Stoza | 01049c8 | 2014-11-11 10:32:31 -0800 | [diff] [blame] | 348 |         ALOGE("unflatten: numFds or numInts is too large: %zd, %zd", | 
| Michael Lentine | 3880326 | 2014-10-31 15:25:03 -0700 | [diff] [blame] | 349 |                 numFds, numInts); | 
 | 350 |         return BAD_VALUE; | 
 | 351 |     } | 
 | 352 |  | 
| Dan Stoza | 812ed06 | 2015-06-02 15:45:22 -0700 | [diff] [blame] | 353 |     const size_t sizeNeeded = (11 + numInts) * sizeof(int); | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 354 |     if (size < sizeNeeded) return NO_MEMORY; | 
 | 355 |  | 
| Michael Lentine | 3880326 | 2014-10-31 15:25:03 -0700 | [diff] [blame] | 356 |     size_t fdCountNeeded = numFds; | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 357 |     if (count < fdCountNeeded) return NO_MEMORY; | 
 | 358 |  | 
 | 359 |     if (handle) { | 
 | 360 |         // free previous handle if any | 
 | 361 |         free_handle(); | 
 | 362 |     } | 
 | 363 |  | 
 | 364 |     if (numFds || numInts) { | 
 | 365 |         width  = buf[1]; | 
 | 366 |         height = buf[2]; | 
 | 367 |         stride = buf[3]; | 
 | 368 |         format = buf[4]; | 
 | 369 |         usage  = buf[5]; | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 370 |         native_handle* h = native_handle_create( | 
 | 371 |                 static_cast<int>(numFds), static_cast<int>(numInts)); | 
| Michael Lentine | 3880326 | 2014-10-31 15:25:03 -0700 | [diff] [blame] | 372 |         if (!h) { | 
 | 373 |             width = height = stride = format = usage = 0; | 
 | 374 |             handle = NULL; | 
 | 375 |             ALOGE("unflatten: native_handle_create failed"); | 
 | 376 |             return NO_MEMORY; | 
 | 377 |         } | 
| Dan Stoza | d318240 | 2014-11-17 12:03:59 -0800 | [diff] [blame] | 378 |         memcpy(h->data, fds, numFds * sizeof(int)); | 
| Dan Stoza | 812ed06 | 2015-06-02 15:45:22 -0700 | [diff] [blame] | 379 |         memcpy(h->data + numFds, &buf[11], numInts * sizeof(int)); | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 380 |         handle = h; | 
 | 381 |     } else { | 
 | 382 |         width = height = stride = format = usage = 0; | 
 | 383 |         handle = NULL; | 
 | 384 |     } | 
 | 385 |  | 
| Dan Stoza | b1363d3 | 2014-03-28 15:10:52 -0700 | [diff] [blame] | 386 |     mId = static_cast<uint64_t>(buf[6]) << 32; | 
 | 387 |     mId |= static_cast<uint32_t>(buf[7]); | 
 | 388 |  | 
| Dan Stoza | 812ed06 | 2015-06-02 15:45:22 -0700 | [diff] [blame] | 389 |     mGenerationNumber = static_cast<uint32_t>(buf[8]); | 
 | 390 |  | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 391 |     mOwner = ownHandle; | 
| Jamie Gennis | 309d3bb | 2010-10-07 13:46:55 -0700 | [diff] [blame] | 392 |  | 
 | 393 |     if (handle != 0) { | 
| Dan Stoza | 8deb4da | 2016-06-01 18:21:44 -0700 | [diff] [blame] | 394 |         status_t err = mBufferMapper.registerBuffer(this); | 
| Jamie Gennis | d69097f | 2012-08-30 13:28:23 -0700 | [diff] [blame] | 395 |         if (err != NO_ERROR) { | 
| Lingyun Zhu | 2aff702 | 2012-11-20 19:24:35 +0800 | [diff] [blame] | 396 |             width = height = stride = format = usage = 0; | 
 | 397 |             handle = NULL; | 
| Jamie Gennis | d69097f | 2012-08-30 13:28:23 -0700 | [diff] [blame] | 398 |             ALOGE("unflatten: registerBuffer failed: %s (%d)", | 
 | 399 |                     strerror(-err), err); | 
 | 400 |             return err; | 
 | 401 |         } | 
| Jamie Gennis | 309d3bb | 2010-10-07 13:46:55 -0700 | [diff] [blame] | 402 |     } | 
 | 403 |  | 
| Dan Stoza | eea6d68 | 2015-04-20 12:07:13 -0700 | [diff] [blame] | 404 |     buffer = static_cast<void const*>(static_cast<uint8_t const*>(buffer) + sizeNeeded); | 
| Mathias Agopian | e142428 | 2013-07-29 21:24:40 -0700 | [diff] [blame] | 405 |     size -= sizeNeeded; | 
 | 406 |     fds += numFds; | 
 | 407 |     count -= numFds; | 
 | 408 |  | 
| Mathias Agopian | 98e71dd | 2010-02-11 17:30:52 -0800 | [diff] [blame] | 409 |     return NO_ERROR; | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 410 | } | 
 | 411 |  | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 412 | // --------------------------------------------------------------------------- | 
 | 413 |  | 
 | 414 | }; // namespace android |