BufferItem.cpp revision eea6d682b8b0f7081f0fe8fab8feadb16e22b30b
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    mTransform(0),
28    mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
29    mTimestamp(0),
30    mIsAutoTimestamp(false),
31    mDataSpace(HAL_DATASPACE_UNKNOWN),
32    mFrameNumber(0),
33    mSlot(INVALID_BUFFER_SLOT),
34    mIsDroppable(false),
35    mAcquireCalled(false),
36    mTransformToDisplayInverse(false) {
37    mCrop.makeInvalid();
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    // Must align<8> before writing these fields for this to be correct
50    size_t size = 0;
51    addAligned(size, mCrop);
52    addAligned(size, mTransform);
53    addAligned(size, mScalingMode);
54    addAligned(size, mTimestamp);
55    addAligned(size, mIsAutoTimestamp);
56    addAligned(size, mDataSpace);
57    addAligned(size, mFrameNumber);
58    addAligned(size, mSlot);
59    addAligned(size, mIsDroppable);
60    addAligned(size, mAcquireCalled);
61    addAligned(size, mTransformToDisplayInverse);
62    return size;
63}
64
65size_t BufferItem::getFlattenedSize() const {
66    size_t size = sizeof(uint32_t); // Flags
67    if (mGraphicBuffer != 0) {
68        size += mGraphicBuffer->getFlattenedSize();
69        FlattenableUtils::align<4>(size);
70    }
71    if (mFence != 0) {
72        size += mFence->getFlattenedSize();
73        FlattenableUtils::align<4>(size);
74    }
75    size += mSurfaceDamage.getFlattenedSize();
76    size = FlattenableUtils::align<8>(size);
77    return size + getPodSize();
78}
79
80size_t BufferItem::getFdCount() const {
81    size_t count = 0;
82    if (mGraphicBuffer != 0) {
83        count += mGraphicBuffer->getFdCount();
84    }
85    if (mFence != 0) {
86        count += mFence->getFdCount();
87    }
88    return count;
89}
90
91template <typename T>
92static void writeAligned(void*& buffer, size_t& size, T value) {
93    size -= FlattenableUtils::align<alignof(T)>(buffer);
94    FlattenableUtils::write(buffer, size, value);
95}
96
97status_t BufferItem::flatten(
98        void*& buffer, size_t& size, int*& fds, size_t& count) const {
99
100    // make sure we have enough space
101    if (size < BufferItem::getFlattenedSize()) {
102        return NO_MEMORY;
103    }
104
105    // content flags are stored first
106    uint32_t& flags = *static_cast<uint32_t*>(buffer);
107
108    // advance the pointer
109    FlattenableUtils::advance(buffer, size, sizeof(uint32_t));
110
111    flags = 0;
112    if (mGraphicBuffer != 0) {
113        status_t err = mGraphicBuffer->flatten(buffer, size, fds, count);
114        if (err) return err;
115        size -= FlattenableUtils::align<4>(buffer);
116        flags |= 1;
117    }
118    if (mFence != 0) {
119        status_t err = mFence->flatten(buffer, size, fds, count);
120        if (err) return err;
121        size -= FlattenableUtils::align<4>(buffer);
122        flags |= 2;
123    }
124
125    status_t err = mSurfaceDamage.flatten(buffer, size);
126    if (err) return err;
127    FlattenableUtils::advance(buffer, size, mSurfaceDamage.getFlattenedSize());
128
129    // Must align<8> so that getPodSize returns the correct value
130    size -= FlattenableUtils::align<8>(buffer);
131
132    // Check we still have enough space
133    if (size < getPodSize()) {
134        return NO_MEMORY;
135    }
136
137    writeAligned(buffer, size, mCrop);
138    writeAligned(buffer, size, mTransform);
139    writeAligned(buffer, size, mScalingMode);
140    writeAligned(buffer, size, mTimestamp);
141    writeAligned(buffer, size, mIsAutoTimestamp);
142    writeAligned(buffer, size, mDataSpace);
143    writeAligned(buffer, size, mFrameNumber);
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    // Must align<8> so that getPodSize returns the correct value
187    size -= FlattenableUtils::align<8>(buffer);
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, mTimestamp);
198    readAligned(buffer, size, mIsAutoTimestamp);
199    readAligned(buffer, size, mDataSpace);
200    readAligned(buffer, size, mFrameNumber);
201    readAligned(buffer, size, mSlot);
202    readAligned(buffer, size, mIsDroppable);
203    readAligned(buffer, size, mAcquireCalled);
204    readAligned(buffer, size, mTransformToDisplayInverse);
205
206    return NO_ERROR;
207}
208
209const char* BufferItem::scalingModeName(uint32_t scalingMode) {
210    switch (scalingMode) {
211        case NATIVE_WINDOW_SCALING_MODE_FREEZE: return "FREEZE";
212        case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: return "SCALE_TO_WINDOW";
213        case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: return "SCALE_CROP";
214        default: return "Unknown";
215    }
216}
217
218} // namespace android
219