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