xref: /aosp_15_r20/frameworks/native/libs/gui/BufferItem.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
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