• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 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     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 Flags<LayerStateField> LayerState::getDifferingFields(const LayerState& other) const {
80     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         if (auto viewOpt = flag_name(field->getField()); viewOpt) {
97             base::StringAppendF(&result, "  %16s: ", std::string(*viewOpt).c_str());
98         } else {
99             result.append("<UNKNOWN FIELD>:\n");
100         }
101 
102         bool first = true;
103         for (const std::string& line : field->toStrings()) {
104             base::StringAppendF(&result, "%s%s\n", first ? "" : "                    ",
105                                 line.c_str());
106             first = false;
107         }
108     }
109     result.append("\n");
110 }
111 
compare(const LayerState & other) const112 std::optional<std::string> LayerState::compare(const LayerState& other) const {
113     std::string result;
114 
115     const auto& thisFields = getNonUniqueFields();
116     const auto& otherFields = other.getNonUniqueFields();
117     for (size_t f = 0; f < thisFields.size(); ++f) {
118         const auto& thisField = thisFields[f];
119         const auto& otherField = otherFields[f];
120         // Skip comparing buffers
121         if (thisField->getField() == LayerStateField::Buffer) {
122             continue;
123         }
124 
125         if (thisField->equals(otherField)) {
126             continue;
127         }
128 
129         if (auto viewOpt = flag_name(thisField->getField()); viewOpt) {
130             base::StringAppendF(&result, "  %16s: ", std::string(*viewOpt).c_str());
131         } else {
132             result.append("<UNKNOWN FIELD>:\n");
133         }
134 
135         const auto& thisStrings = thisField->toStrings();
136         const auto& otherStrings = otherField->toStrings();
137         bool first = true;
138         for (size_t line = 0; line < std::max(thisStrings.size(), otherStrings.size()); ++line) {
139             if (!first) {
140                 result.append("                    ");
141             }
142             first = false;
143 
144             if (line < thisStrings.size()) {
145                 base::StringAppendF(&result, "%-48.48s", thisStrings[line].c_str());
146             } else {
147                 result.append("                                                ");
148             }
149 
150             if (line < otherStrings.size()) {
151                 base::StringAppendF(&result, "%-48.48s", otherStrings[line].c_str());
152             } else {
153                 result.append("                                                ");
154             }
155             result.append("\n");
156         }
157     }
158 
159     return result.empty() ? std::nullopt : std::make_optional(result);
160 }
161 
operator ==(const LayerState & lhs,const LayerState & rhs)162 bool operator==(const LayerState& lhs, const LayerState& rhs) {
163     return lhs.mId == rhs.mId && lhs.mName == rhs.mName && lhs.mDisplayFrame == rhs.mDisplayFrame &&
164             lhs.mSourceCrop == rhs.mSourceCrop && lhs.mBufferTransform == rhs.mBufferTransform &&
165             lhs.mBlendMode == rhs.mBlendMode && lhs.mAlpha == rhs.mAlpha &&
166             lhs.mLayerMetadata == rhs.mLayerMetadata && lhs.mVisibleRegion == rhs.mVisibleRegion &&
167             lhs.mOutputDataspace == rhs.mOutputDataspace && lhs.mPixelFormat == rhs.mPixelFormat &&
168             lhs.mColorTransform == rhs.mColorTransform &&
169             lhs.mCompositionType == rhs.mCompositionType &&
170             lhs.mSidebandStream == rhs.mSidebandStream && lhs.mBuffer == rhs.mBuffer &&
171             (lhs.mCompositionType.get() != hal::Composition::SOLID_COLOR ||
172              lhs.mSolidColor == rhs.mSolidColor);
173 }
174 
getNonBufferHash(const std::vector<const LayerState * > & layers)175 NonBufferHash getNonBufferHash(const std::vector<const LayerState*>& layers) {
176     size_t hash = 0;
177     for (const auto layer : layers) {
178         android::hashCombineSingleHashed(hash, layer->getHash());
179     }
180 
181     return hash;
182 }
183 
184 } // namespace android::compositionengine::impl::planner
185