1 /*
2 * Copyright 2021 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 <compositionengine/impl/planner/LayerState.h>
18
19 namespace {
__asan_default_options()20 extern "C" const char* __attribute__((unused)) __asan_default_options() {
21 return "detect_container_overflow=0";
22 }
23 } // namespace
24
25 namespace android::compositionengine::impl::planner {
26
LayerState(compositionengine::OutputLayer * layer)27 LayerState::LayerState(compositionengine::OutputLayer* layer)
28 : mOutputLayer(layer),
29 mColorTransform({[](auto layer) {
30 const auto state = layer->getLayerFE().getCompositionState();
31 return state->colorTransformIsIdentity ? mat4{}
32 : state->colorTransform;
33 },
34 [](const mat4& mat) {
35 using namespace std::string_literals;
36 std::vector<std::string> split =
37 base::Split(std::string(mat.asString().string()), "\n"s);
38 split.pop_back(); // Strip the last (empty) line
39 return split;
40 }}) {
41 update(layer);
42 }
43
update(compositionengine::OutputLayer * layer)44 ftl::Flags<LayerStateField> LayerState::update(compositionengine::OutputLayer* layer) {
45 ALOGE_IF(mOutputLayer != layer && layer->getLayerFE().getSequence() != mId.get(),
46 "[%s] Expected mOutputLayer ID to never change: %d, %d", __func__,
47 layer->getLayerFE().getSequence(), mId.get());
48
49 // It's possible for the OutputLayer pointer to change even when the layer is logically the
50 // same, i.e., the LayerFE is the same. An example use-case is screen rotation.
51 mOutputLayer = layer;
52
53 ftl::Flags<LayerStateField> differences;
54
55 // Update the unique fields as well, since we have to set them at least
56 // once from the OutputLayer
57 differences |= mId.update(layer);
58 differences |= mName.update(layer);
59
60 for (StateInterface* field : getNonUniqueFields()) {
61 differences |= field->update(layer);
62 }
63
64 return differences;
65 }
66
getHash() const67 size_t LayerState::getHash() const {
68 size_t hash = 0;
69 for (const StateInterface* field : getNonUniqueFields()) {
70 if (field->getField() == LayerStateField::Buffer) {
71 continue;
72 }
73 android::hashCombineSingleHashed(hash, field->getHash());
74 }
75
76 return hash;
77 }
78
getDifferingFields(const LayerState & other) const79 ftl::Flags<LayerStateField> LayerState::getDifferingFields(const LayerState& other) const {
80 ftl::Flags<LayerStateField> differences;
81 auto myFields = getNonUniqueFields();
82 auto otherFields = other.getNonUniqueFields();
83 for (size_t i = 0; i < myFields.size(); ++i) {
84 if (myFields[i]->getField() == LayerStateField::Buffer) {
85 continue;
86 }
87
88 differences |= myFields[i]->getFieldIfDifferent(otherFields[i]);
89 }
90
91 return differences;
92 }
93
dump(std::string & result) const94 void LayerState::dump(std::string& result) const {
95 for (const StateInterface* field : getNonUniqueFields()) {
96 base::StringAppendF(&result, " %16s: ", ftl::flag_string(field->getField()).c_str());
97
98 bool first = true;
99 for (const std::string& line : field->toStrings()) {
100 base::StringAppendF(&result, "%s%s\n", first ? "" : " ",
101 line.c_str());
102 first = false;
103 }
104 }
105 result.append("\n");
106 }
107
compare(const LayerState & other) const108 std::optional<std::string> LayerState::compare(const LayerState& other) const {
109 std::string result;
110
111 const auto& thisFields = getNonUniqueFields();
112 const auto& otherFields = other.getNonUniqueFields();
113 for (size_t f = 0; f < thisFields.size(); ++f) {
114 const auto& thisField = thisFields[f];
115 const auto& otherField = otherFields[f];
116 // Skip comparing buffers
117 if (thisField->getField() == LayerStateField::Buffer) {
118 continue;
119 }
120
121 if (thisField->equals(otherField)) {
122 continue;
123 }
124
125 base::StringAppendF(&result, " %16s: ", ftl::flag_string(thisField->getField()).c_str());
126
127 const auto& thisStrings = thisField->toStrings();
128 const auto& otherStrings = otherField->toStrings();
129 bool first = true;
130 for (size_t line = 0; line < std::max(thisStrings.size(), otherStrings.size()); ++line) {
131 if (!first) {
132 result.append(" ");
133 }
134 first = false;
135
136 if (line < thisStrings.size()) {
137 base::StringAppendF(&result, "%-48.48s", thisStrings[line].c_str());
138 } else {
139 result.append(" ");
140 }
141
142 if (line < otherStrings.size()) {
143 base::StringAppendF(&result, "%-48.48s", otherStrings[line].c_str());
144 } else {
145 result.append(" ");
146 }
147 result.append("\n");
148 }
149 }
150
151 return result.empty() ? std::nullopt : std::make_optional(result);
152 }
153
operator ==(const LayerState & lhs,const LayerState & rhs)154 bool operator==(const LayerState& lhs, const LayerState& rhs) {
155 return lhs.mId == rhs.mId && lhs.mName == rhs.mName && lhs.mDisplayFrame == rhs.mDisplayFrame &&
156 lhs.mSourceCrop == rhs.mSourceCrop && lhs.mBufferTransform == rhs.mBufferTransform &&
157 lhs.mBlendMode == rhs.mBlendMode && lhs.mAlpha == rhs.mAlpha &&
158 lhs.mLayerMetadata == rhs.mLayerMetadata && lhs.mVisibleRegion == rhs.mVisibleRegion &&
159 lhs.mOutputDataspace == rhs.mOutputDataspace && lhs.mPixelFormat == rhs.mPixelFormat &&
160 lhs.mColorTransform == rhs.mColorTransform &&
161 lhs.mCompositionType == rhs.mCompositionType &&
162 lhs.mSidebandStream == rhs.mSidebandStream && lhs.mBuffer == rhs.mBuffer &&
163 (lhs.mCompositionType.get() !=
164 aidl::android::hardware::graphics::composer3::Composition::SOLID_COLOR ||
165 lhs.mSolidColor == rhs.mSolidColor);
166 }
167
getNonBufferHash(const std::vector<const LayerState * > & layers)168 NonBufferHash getNonBufferHash(const std::vector<const LayerState*>& layers) {
169 size_t hash = 0;
170 for (const auto layer : layers) {
171 android::hashCombineSingleHashed(hash, layer->getHash());
172 }
173
174 return hash;
175 }
176
177 } // namespace android::compositionengine::impl::planner
178