1 /* 2 * Copyright 2014 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 #include <gui/BufferItem.h> 18 19 #include <ui/Fence.h> 20 #include <ui/GraphicBuffer.h> 21 22 #include <system/window.h> 23 24 namespace android { 25 26 template<typename T> 27 static inline constexpr uint32_t low32(const T n) { 28 return static_cast<uint32_t>(static_cast<uint64_t>(n)); 29 } 30 31 template<typename T> 32 static inline constexpr uint32_t high32(const T n) { 33 return static_cast<uint32_t>(static_cast<uint64_t>(n)>>32); 34 } 35 36 template<typename T> 37 static inline constexpr T to64(const uint32_t lo, const uint32_t hi) { 38 return static_cast<T>(static_cast<uint64_t>(hi)<<32 | lo); 39 } 40 41 BufferItem::BufferItem() : 42 mGraphicBuffer(NULL), 43 mFence(NULL), 44 mCrop(Rect::INVALID_RECT), 45 mTransform(0), 46 mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), 47 mTimestamp(0), 48 mIsAutoTimestamp(false), 49 mDataSpace(HAL_DATASPACE_UNKNOWN), 50 mFrameNumber(0), 51 mSlot(INVALID_BUFFER_SLOT), 52 mIsDroppable(false), 53 mAcquireCalled(false), 54 mTransformToDisplayInverse(false), 55 mSurfaceDamage(), 56 mAutoRefresh(false), 57 mQueuedBuffer(true), 58 mIsStale(false), 59 mApi(0) { 60 } 61 62 BufferItem::~BufferItem() {} 63 64 template <typename T> 65 static void addAligned(size_t& size, T /* value */) { 66 size = FlattenableUtils::align<sizeof(T)>(size); 67 size += sizeof(T); 68 } 69 70 size_t BufferItem::getPodSize() const { 71 size_t size = 0; 72 addAligned(size, mCrop); 73 addAligned(size, mTransform); 74 addAligned(size, mScalingMode); 75 addAligned(size, low32(mTimestamp)); 76 addAligned(size, high32(mTimestamp)); 77 addAligned(size, mIsAutoTimestamp); 78 addAligned(size, mDataSpace); 79 addAligned(size, low32(mFrameNumber)); 80 addAligned(size, high32(mFrameNumber)); 81 addAligned(size, mSlot); 82 addAligned(size, mIsDroppable); 83 addAligned(size, mAcquireCalled); 84 addAligned(size, mTransformToDisplayInverse); 85 addAligned(size, mAutoRefresh); 86 addAligned(size, mQueuedBuffer); 87 addAligned(size, mIsStale); 88 addAligned(size, mApi); 89 return size; 90 } 91 92 size_t BufferItem::getFlattenedSize() const { 93 size_t size = sizeof(uint32_t); // Flags 94 if (mGraphicBuffer != 0) { 95 size += mGraphicBuffer->getFlattenedSize(); 96 size = FlattenableUtils::align<4>(size); 97 } 98 if (mFence != 0) { 99 size += mFence->getFlattenedSize(); 100 size = FlattenableUtils::align<4>(size); 101 } 102 size += mSurfaceDamage.getFlattenedSize(); 103 size += mHdrMetadata.getFlattenedSize(); 104 size = FlattenableUtils::align<8>(size); 105 return size + getPodSize(); 106 } 107 108 size_t BufferItem::getFdCount() const { 109 size_t count = 0; 110 if (mGraphicBuffer != 0) { 111 count += mGraphicBuffer->getFdCount(); 112 } 113 if (mFence != 0) { 114 count += mFence->getFdCount(); 115 } 116 return count; 117 } 118 119 template <typename T> 120 static void writeAligned(void*& buffer, size_t& size, T value) { 121 size -= FlattenableUtils::align<alignof(T)>(buffer); 122 FlattenableUtils::write(buffer, size, value); 123 } 124 125 status_t BufferItem::flatten( 126 void*& buffer, size_t& size, int*& fds, size_t& count) const { 127 128 // make sure we have enough space 129 if (size < BufferItem::getFlattenedSize()) { 130 return NO_MEMORY; 131 } 132 133 // content flags are stored first 134 uint32_t& flags = *static_cast<uint32_t*>(buffer); 135 136 // advance the pointer 137 FlattenableUtils::advance(buffer, size, sizeof(uint32_t)); 138 139 flags = 0; 140 if (mGraphicBuffer != 0) { 141 status_t err = mGraphicBuffer->flatten(buffer, size, fds, count); 142 if (err) return err; 143 size -= FlattenableUtils::align<4>(buffer); 144 flags |= 1; 145 } 146 if (mFence != 0) { 147 status_t err = mFence->flatten(buffer, size, fds, count); 148 if (err) return err; 149 size -= FlattenableUtils::align<4>(buffer); 150 flags |= 2; 151 } 152 153 status_t err = mSurfaceDamage.flatten(buffer, size); 154 if (err) return err; 155 FlattenableUtils::advance(buffer, size, mSurfaceDamage.getFlattenedSize()); 156 157 err = mHdrMetadata.flatten(buffer, size); 158 if (err) return err; 159 FlattenableUtils::advance(buffer, size, mHdrMetadata.getFlattenedSize()); 160 161 // Check we still have enough space 162 if (size < getPodSize()) { 163 return NO_MEMORY; 164 } 165 166 writeAligned(buffer, size, mCrop); 167 writeAligned(buffer, size, mTransform); 168 writeAligned(buffer, size, mScalingMode); 169 writeAligned(buffer, size, low32(mTimestamp)); 170 writeAligned(buffer, size, high32(mTimestamp)); 171 writeAligned(buffer, size, mIsAutoTimestamp); 172 writeAligned(buffer, size, mDataSpace); 173 writeAligned(buffer, size, low32(mFrameNumber)); 174 writeAligned(buffer, size, high32(mFrameNumber)); 175 writeAligned(buffer, size, mSlot); 176 writeAligned(buffer, size, mIsDroppable); 177 writeAligned(buffer, size, mAcquireCalled); 178 writeAligned(buffer, size, mTransformToDisplayInverse); 179 writeAligned(buffer, size, mAutoRefresh); 180 writeAligned(buffer, size, mQueuedBuffer); 181 writeAligned(buffer, size, mIsStale); 182 writeAligned(buffer, size, mApi); 183 184 return NO_ERROR; 185 } 186 187 template <typename T> 188 static void readAligned(const void*& buffer, size_t& size, T& value) { 189 size -= FlattenableUtils::align<alignof(T)>(buffer); 190 FlattenableUtils::read(buffer, size, value); 191 } 192 193 status_t BufferItem::unflatten( 194 void const*& buffer, size_t& size, int const*& fds, size_t& count) { 195 196 if (size < sizeof(uint32_t)) { 197 return NO_MEMORY; 198 } 199 200 uint32_t flags = 0; 201 FlattenableUtils::read(buffer, size, flags); 202 203 if (flags & 1) { 204 mGraphicBuffer = new GraphicBuffer(); 205 status_t err = mGraphicBuffer->unflatten(buffer, size, fds, count); 206 if (err) return err; 207 size -= FlattenableUtils::align<4>(buffer); 208 } 209 210 if (flags & 2) { 211 mFence = new Fence(); 212 status_t err = mFence->unflatten(buffer, size, fds, count); 213 if (err) return err; 214 size -= FlattenableUtils::align<4>(buffer); 215 216 mFenceTime = std::make_shared<FenceTime>(mFence); 217 } 218 219 status_t err = mSurfaceDamage.unflatten(buffer, size); 220 if (err) return err; 221 FlattenableUtils::advance(buffer, size, mSurfaceDamage.getFlattenedSize()); 222 223 err = mHdrMetadata.unflatten(buffer, size); 224 if (err) return err; 225 FlattenableUtils::advance(buffer, size, mHdrMetadata.getFlattenedSize()); 226 227 // Check we still have enough space 228 if (size < getPodSize()) { 229 return NO_MEMORY; 230 } 231 232 uint32_t timestampLo = 0, timestampHi = 0; 233 uint32_t frameNumberLo = 0, frameNumberHi = 0; 234 235 readAligned(buffer, size, mCrop); 236 readAligned(buffer, size, mTransform); 237 readAligned(buffer, size, mScalingMode); 238 readAligned(buffer, size, timestampLo); 239 readAligned(buffer, size, timestampHi); 240 mTimestamp = to64<int64_t>(timestampLo, timestampHi); 241 readAligned(buffer, size, mIsAutoTimestamp); 242 readAligned(buffer, size, mDataSpace); 243 readAligned(buffer, size, frameNumberLo); 244 readAligned(buffer, size, frameNumberHi); 245 mFrameNumber = to64<uint64_t>(frameNumberLo, frameNumberHi); 246 readAligned(buffer, size, mSlot); 247 readAligned(buffer, size, mIsDroppable); 248 readAligned(buffer, size, mAcquireCalled); 249 readAligned(buffer, size, mTransformToDisplayInverse); 250 readAligned(buffer, size, mAutoRefresh); 251 readAligned(buffer, size, mQueuedBuffer); 252 readAligned(buffer, size, mIsStale); 253 readAligned(buffer, size, mApi); 254 255 return NO_ERROR; 256 } 257 258 const char* BufferItem::scalingModeName(uint32_t scalingMode) { 259 switch (scalingMode) { 260 case NATIVE_WINDOW_SCALING_MODE_FREEZE: return "FREEZE"; 261 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: return "SCALE_TO_WINDOW"; 262 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: return "SCALE_CROP"; 263 default: return "Unknown"; 264 } 265 } 266 267 } // namespace android 268