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