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
BufferItem()26 BufferItem::BufferItem() :
27 mTransform(0),
28 mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
29 mTimestamp(0),
30 mIsAutoTimestamp(false),
31 mDataSpace(HAL_DATASPACE_UNKNOWN),
32 mFrameNumber(0),
33 mSlot(INVALID_BUFFER_SLOT),
34 mIsDroppable(false),
35 mAcquireCalled(false),
36 mTransformToDisplayInverse(false) {
37 mCrop.makeInvalid();
38 }
39
~BufferItem()40 BufferItem::~BufferItem() {}
41
42 template <typename T>
addAligned(size_t & size,T)43 static void addAligned(size_t& size, T /* value */) {
44 size = FlattenableUtils::align<sizeof(T)>(size);
45 size += sizeof(T);
46 }
47
getPodSize() const48 size_t BufferItem::getPodSize() const {
49 size_t size = 0;
50 addAligned(size, mCrop);
51 addAligned(size, mTransform);
52 addAligned(size, mScalingMode);
53 addAligned(size, mTimestampLo);
54 addAligned(size, mTimestampHi);
55 addAligned(size, mIsAutoTimestamp);
56 addAligned(size, mDataSpace);
57 addAligned(size, mFrameNumberLo);
58 addAligned(size, mFrameNumberHi);
59 addAligned(size, mSlot);
60 addAligned(size, mIsDroppable);
61 addAligned(size, mAcquireCalled);
62 addAligned(size, mTransformToDisplayInverse);
63 return size;
64 }
65
getFlattenedSize() const66 size_t BufferItem::getFlattenedSize() const {
67 size_t size = sizeof(uint32_t); // Flags
68 if (mGraphicBuffer != 0) {
69 size += mGraphicBuffer->getFlattenedSize();
70 FlattenableUtils::align<4>(size);
71 }
72 if (mFence != 0) {
73 size += mFence->getFlattenedSize();
74 FlattenableUtils::align<4>(size);
75 }
76 size += mSurfaceDamage.getFlattenedSize();
77 size = FlattenableUtils::align<8>(size);
78 return size + getPodSize();
79 }
80
getFdCount() const81 size_t BufferItem::getFdCount() const {
82 size_t count = 0;
83 if (mGraphicBuffer != 0) {
84 count += mGraphicBuffer->getFdCount();
85 }
86 if (mFence != 0) {
87 count += mFence->getFdCount();
88 }
89 return count;
90 }
91
92 template <typename T>
writeAligned(void * & buffer,size_t & size,T value)93 static void writeAligned(void*& buffer, size_t& size, T value) {
94 size -= FlattenableUtils::align<alignof(T)>(buffer);
95 FlattenableUtils::write(buffer, size, value);
96 }
97
flatten(void * & buffer,size_t & size,int * & fds,size_t & count) const98 status_t BufferItem::flatten(
99 void*& buffer, size_t& size, int*& fds, size_t& count) const {
100
101 // make sure we have enough space
102 if (size < BufferItem::getFlattenedSize()) {
103 return NO_MEMORY;
104 }
105
106 // content flags are stored first
107 uint32_t& flags = *static_cast<uint32_t*>(buffer);
108
109 // advance the pointer
110 FlattenableUtils::advance(buffer, size, sizeof(uint32_t));
111
112 flags = 0;
113 if (mGraphicBuffer != 0) {
114 status_t err = mGraphicBuffer->flatten(buffer, size, fds, count);
115 if (err) return err;
116 size -= FlattenableUtils::align<4>(buffer);
117 flags |= 1;
118 }
119 if (mFence != 0) {
120 status_t err = mFence->flatten(buffer, size, fds, count);
121 if (err) return err;
122 size -= FlattenableUtils::align<4>(buffer);
123 flags |= 2;
124 }
125
126 status_t err = mSurfaceDamage.flatten(buffer, size);
127 if (err) return err;
128 FlattenableUtils::advance(buffer, size, mSurfaceDamage.getFlattenedSize());
129
130 // Check we still have enough space
131 if (size < getPodSize()) {
132 return NO_MEMORY;
133 }
134
135 writeAligned(buffer, size, mCrop);
136 writeAligned(buffer, size, mTransform);
137 writeAligned(buffer, size, mScalingMode);
138 writeAligned(buffer, size, mTimestampLo);
139 writeAligned(buffer, size, mTimestampHi);
140 writeAligned(buffer, size, mIsAutoTimestamp);
141 writeAligned(buffer, size, mDataSpace);
142 writeAligned(buffer, size, mFrameNumberLo);
143 writeAligned(buffer, size, mFrameNumberHi);
144 writeAligned(buffer, size, mSlot);
145 writeAligned(buffer, size, mIsDroppable);
146 writeAligned(buffer, size, mAcquireCalled);
147 writeAligned(buffer, size, mTransformToDisplayInverse);
148
149 return NO_ERROR;
150 }
151
152 template <typename T>
readAligned(const void * & buffer,size_t & size,T & value)153 static void readAligned(const void*& buffer, size_t& size, T& value) {
154 size -= FlattenableUtils::align<alignof(T)>(buffer);
155 FlattenableUtils::read(buffer, size, value);
156 }
157
unflatten(void const * & buffer,size_t & size,int const * & fds,size_t & count)158 status_t BufferItem::unflatten(
159 void const*& buffer, size_t& size, int const*& fds, size_t& count) {
160
161 if (size < sizeof(uint32_t)) {
162 return NO_MEMORY;
163 }
164
165 uint32_t flags = 0;
166 FlattenableUtils::read(buffer, size, flags);
167
168 if (flags & 1) {
169 mGraphicBuffer = new GraphicBuffer();
170 status_t err = mGraphicBuffer->unflatten(buffer, size, fds, count);
171 if (err) return err;
172 size -= FlattenableUtils::align<4>(buffer);
173 }
174
175 if (flags & 2) {
176 mFence = new Fence();
177 status_t err = mFence->unflatten(buffer, size, fds, count);
178 if (err) return err;
179 size -= FlattenableUtils::align<4>(buffer);
180 }
181
182 status_t err = mSurfaceDamage.unflatten(buffer, size);
183 if (err) return err;
184 FlattenableUtils::advance(buffer, size, mSurfaceDamage.getFlattenedSize());
185
186 // Check we still have enough space
187 if (size < getPodSize()) {
188 return NO_MEMORY;
189 }
190
191 readAligned(buffer, size, mCrop);
192 readAligned(buffer, size, mTransform);
193 readAligned(buffer, size, mScalingMode);
194 readAligned(buffer, size, mTimestampLo);
195 readAligned(buffer, size, mTimestampHi);
196 readAligned(buffer, size, mIsAutoTimestamp);
197 readAligned(buffer, size, mDataSpace);
198 readAligned(buffer, size, mFrameNumberLo);
199 readAligned(buffer, size, mFrameNumberHi);
200 readAligned(buffer, size, mSlot);
201 readAligned(buffer, size, mIsDroppable);
202 readAligned(buffer, size, mAcquireCalled);
203 readAligned(buffer, size, mTransformToDisplayInverse);
204
205 return NO_ERROR;
206 }
207
scalingModeName(uint32_t scalingMode)208 const char* BufferItem::scalingModeName(uint32_t scalingMode) {
209 switch (scalingMode) {
210 case NATIVE_WINDOW_SCALING_MODE_FREEZE: return "FREEZE";
211 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: return "SCALE_TO_WINDOW";
212 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: return "SCALE_CROP";
213 default: return "Unknown";
214 }
215 }
216
217 } // namespace android
218