BufferItem.cpp revision 60d6922a011fe18c111b8d30fb6ef1f655b6b15e
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    mCrop(Rect::INVALID_RECT),
28    mTransform(0),
29    mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
30    mTimestamp(0),
31    mIsAutoTimestamp(false),
32    mDataSpace(HAL_DATASPACE_UNKNOWN),
33    mFrameNumber(0),
34    mSlot(INVALID_BUFFER_SLOT),
35    mIsDroppable(false),
36    mAcquireCalled(false),
37    mTransformToDisplayInverse(false) {
38}
39
40BufferItem::~BufferItem() {}
41
42template <typename T>
43static void addAligned(size_t& size, T /* value */) {
44    size = FlattenableUtils::align<sizeof(T)>(size);
45    size += sizeof(T);
46}
47
48size_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
66size_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
81size_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
92template <typename T>
93static void writeAligned(void*& buffer, size_t& size, T value) {
94    size -= FlattenableUtils::align<alignof(T)>(buffer);
95    FlattenableUtils::write(buffer, size, value);
96}
97
98status_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
152template <typename T>
153static 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
158status_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
208const 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