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