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