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>
low32(const T n)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>
high32(const T n)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>
to64(const uint32_t lo,const uint32_t hi)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
BufferItem()41 BufferItem::BufferItem()
42 : mGraphicBuffer(nullptr),
43 mFence(nullptr),
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
~BufferItem()61 BufferItem::~BufferItem() {}
62
63 template <typename T>
addAligned(size_t & size,T)64 static void addAligned(size_t& size, T /* value */) {
65 size = FlattenableUtils::align<sizeof(T)>(size);
66 size += sizeof(T);
67 }
68
getPodSize() const69 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 #if COM_ANDROID_GRAPHICS_LIBUI_FLAGS_APPLY_PICTURE_PROFILES
79 addAligned(size, mPictureProfileHandle.has_value());
80 addAligned(size, low32(PictureProfileHandle::NONE.getId()));
81 addAligned(size, high32(PictureProfileHandle::NONE.getId()));
82 #endif // COM_ANDROID_GRAPHICS_LIBUI_FLAGS_APPLY_PICTURE_PROFILES
83 addAligned(size, low32(mFrameNumber));
84 addAligned(size, high32(mFrameNumber));
85 addAligned(size, mSlot);
86 addAligned(size, mIsDroppable);
87 addAligned(size, mAcquireCalled);
88 addAligned(size, mTransformToDisplayInverse);
89 addAligned(size, mAutoRefresh);
90 addAligned(size, mQueuedBuffer);
91 addAligned(size, mIsStale);
92 addAligned(size, mApi);
93 return size;
94 }
95
getFlattenedSize() const96 size_t BufferItem::getFlattenedSize() const {
97 size_t size = sizeof(uint32_t); // Flags
98 if (mGraphicBuffer != nullptr) {
99 size += mGraphicBuffer->getFlattenedSize();
100 size = FlattenableUtils::align<4>(size);
101 }
102 if (mFence != nullptr) {
103 size += mFence->getFlattenedSize();
104 size = FlattenableUtils::align<4>(size);
105 }
106 size += mSurfaceDamage.getFlattenedSize();
107 size += mHdrMetadata.getFlattenedSize();
108 size = FlattenableUtils::align<8>(size);
109 return size + getPodSize();
110 }
111
getFdCount() const112 size_t BufferItem::getFdCount() const {
113 size_t count = 0;
114 if (mGraphicBuffer != nullptr) {
115 count += mGraphicBuffer->getFdCount();
116 }
117 if (mFence != nullptr) {
118 count += mFence->getFdCount();
119 }
120 return count;
121 }
122
123 template <typename T>
writeAligned(void * & buffer,size_t & size,T value)124 static void writeAligned(void*& buffer, size_t& size, T value) {
125 size -= FlattenableUtils::align<alignof(T)>(buffer);
126 FlattenableUtils::write(buffer, size, value);
127 }
128
flatten(void * & buffer,size_t & size,int * & fds,size_t & count) const129 status_t BufferItem::flatten(
130 void*& buffer, size_t& size, int*& fds, size_t& count) const {
131
132 // make sure we have enough space
133 if (size < BufferItem::getFlattenedSize()) {
134 return NO_MEMORY;
135 }
136
137 // content flags are stored first
138 uint32_t& flags = *static_cast<uint32_t*>(buffer);
139
140 // advance the pointer
141 FlattenableUtils::advance(buffer, size, sizeof(uint32_t));
142
143 flags = 0;
144 if (mGraphicBuffer != nullptr) {
145 status_t err = mGraphicBuffer->flatten(buffer, size, fds, count);
146 if (err) return err;
147 size -= FlattenableUtils::align<4>(buffer);
148 flags |= 1;
149 }
150 if (mFence != nullptr) {
151 status_t err = mFence->flatten(buffer, size, fds, count);
152 if (err) return err;
153 size -= FlattenableUtils::align<4>(buffer);
154 flags |= 2;
155 }
156
157 status_t err = mSurfaceDamage.flatten(buffer, size);
158 if (err) return err;
159 FlattenableUtils::advance(buffer, size, mSurfaceDamage.getFlattenedSize());
160
161 err = mHdrMetadata.flatten(buffer, size);
162 if (err) return err;
163 FlattenableUtils::advance(buffer, size, mHdrMetadata.getFlattenedSize());
164
165 // Check we still have enough space
166 if (size < getPodSize()) {
167 return NO_MEMORY;
168 }
169
170 writeAligned(buffer, size, mCrop);
171 writeAligned(buffer, size, mTransform);
172 writeAligned(buffer, size, mScalingMode);
173 writeAligned(buffer, size, low32(mTimestamp));
174 writeAligned(buffer, size, high32(mTimestamp));
175 writeAligned(buffer, size, mIsAutoTimestamp);
176 writeAligned(buffer, size, mDataSpace);
177 #if COM_ANDROID_GRAPHICS_LIBUI_FLAGS_APPLY_PICTURE_PROFILES
178 writeAligned(buffer, size, mPictureProfileHandle.has_value());
179 if (mPictureProfileHandle.has_value()) {
180 writeAligned(buffer, size, low32(mPictureProfileHandle->getId()));
181 writeAligned(buffer, size, high32(mPictureProfileHandle->getId()));
182 } else {
183 writeAligned(buffer, size, low32(PictureProfileHandle::NONE.getId()));
184 writeAligned(buffer, size, high32(PictureProfileHandle::NONE.getId()));
185 }
186 #endif // COM_ANDROID_GRAPHICS_LIBUI_FLAGS_APPLY_PICTURE_PROFILES
187 writeAligned(buffer, size, low32(mFrameNumber));
188 writeAligned(buffer, size, high32(mFrameNumber));
189 writeAligned(buffer, size, mSlot);
190 writeAligned(buffer, size, mIsDroppable);
191 writeAligned(buffer, size, mAcquireCalled);
192 writeAligned(buffer, size, mTransformToDisplayInverse);
193 writeAligned(buffer, size, mAutoRefresh);
194 writeAligned(buffer, size, mQueuedBuffer);
195 writeAligned(buffer, size, mIsStale);
196 writeAligned(buffer, size, mApi);
197
198 return NO_ERROR;
199 }
200
201 template <typename T>
readAligned(const void * & buffer,size_t & size,T & value)202 static void readAligned(const void*& buffer, size_t& size, T& value) {
203 size -= FlattenableUtils::align<alignof(T)>(buffer);
204 FlattenableUtils::read(buffer, size, value);
205 }
206
unflatten(void const * & buffer,size_t & size,int const * & fds,size_t & count)207 status_t BufferItem::unflatten(
208 void const*& buffer, size_t& size, int const*& fds, size_t& count) {
209
210 if (size < sizeof(uint32_t)) {
211 return NO_MEMORY;
212 }
213
214 uint32_t flags = 0;
215 FlattenableUtils::read(buffer, size, flags);
216
217 if (flags & 1) {
218 mGraphicBuffer = new GraphicBuffer();
219 status_t err = mGraphicBuffer->unflatten(buffer, size, fds, count);
220 if (err) return err;
221 size -= FlattenableUtils::align<4>(buffer);
222 }
223
224 if (flags & 2) {
225 mFence = new Fence();
226 status_t err = mFence->unflatten(buffer, size, fds, count);
227 if (err) return err;
228 size -= FlattenableUtils::align<4>(buffer);
229
230 mFenceTime = std::make_shared<FenceTime>(mFence);
231 }
232
233 status_t err = mSurfaceDamage.unflatten(buffer, size);
234 if (err) return err;
235 FlattenableUtils::advance(buffer, size, mSurfaceDamage.getFlattenedSize());
236
237 err = mHdrMetadata.unflatten(buffer, size);
238 if (err) return err;
239 FlattenableUtils::advance(buffer, size, mHdrMetadata.getFlattenedSize());
240
241 // Check we still have enough space
242 if (size < getPodSize()) {
243 return NO_MEMORY;
244 }
245
246 uint32_t timestampLo = 0, timestampHi = 0;
247 uint32_t frameNumberLo = 0, frameNumberHi = 0;
248 int32_t pictureProfileIdLo = 0, pictureProfileIdHi = 0;
249
250 readAligned(buffer, size, mCrop);
251 readAligned(buffer, size, mTransform);
252 readAligned(buffer, size, mScalingMode);
253 readAligned(buffer, size, timestampLo);
254 readAligned(buffer, size, timestampHi);
255 mTimestamp = to64<int64_t>(timestampLo, timestampHi);
256 readAligned(buffer, size, mIsAutoTimestamp);
257 readAligned(buffer, size, mDataSpace);
258 #if COM_ANDROID_GRAPHICS_LIBUI_FLAGS_APPLY_PICTURE_PROFILES
259 bool hasPictureProfileHandle;
260 readAligned(buffer, size, hasPictureProfileHandle);
261 readAligned(buffer, size, pictureProfileIdLo);
262 readAligned(buffer, size, pictureProfileIdHi);
263 mPictureProfileHandle = hasPictureProfileHandle
264 ? std::optional(PictureProfileHandle(
265 to64<PictureProfileId>(pictureProfileIdLo, pictureProfileIdHi)))
266 : std::nullopt;
267 #endif // COM_ANDROID_GRAPHICS_LIBUI_FLAGS_APPLY_PICTURE_PROFILES
268 readAligned(buffer, size, frameNumberLo);
269 readAligned(buffer, size, frameNumberHi);
270 mFrameNumber = to64<uint64_t>(frameNumberLo, frameNumberHi);
271 readAligned(buffer, size, mSlot);
272 readAligned(buffer, size, mIsDroppable);
273 readAligned(buffer, size, mAcquireCalled);
274 readAligned(buffer, size, mTransformToDisplayInverse);
275 readAligned(buffer, size, mAutoRefresh);
276 readAligned(buffer, size, mQueuedBuffer);
277 readAligned(buffer, size, mIsStale);
278 readAligned(buffer, size, mApi);
279
280 return NO_ERROR;
281 }
282
scalingModeName(uint32_t scalingMode)283 const char* BufferItem::scalingModeName(uint32_t scalingMode) {
284 switch (scalingMode) {
285 case NATIVE_WINDOW_SCALING_MODE_FREEZE: return "FREEZE";
286 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: return "SCALE_TO_WINDOW";
287 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: return "SCALE_CROP";
288 default: return "Unknown";
289 }
290 }
291
292 } // namespace android
293