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