• 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 #pragma once
18 
19 #include <string>
20 
21 #include <aidl/android/hardware/graphics/common/BufferUsage.h>
22 #include <aidl/android/hardware/graphics/composer3/Composition.h>
23 #include <android-base/strings.h>
24 #include <ftl/flags.h>
25 #include <math/HashCombine.h>
26 
27 #include <compositionengine/LayerFE.h>
28 #include <compositionengine/LayerFECompositionState.h>
29 #include <compositionengine/OutputLayer.h>
30 #include <compositionengine/impl/OutputLayerCompositionState.h>
31 
32 #include "DisplayHardware/Hal.h"
33 
34 namespace std {
35 template <typename T>
36 struct hash<android::sp<T>> {
37     size_t operator()(const android::sp<T>& p) { return std::hash<void*>()(p.get()); }
38 };
39 
40 template <typename T>
41 struct hash<android::wp<T>> {
42     size_t operator()(const android::wp<T>& p) {
43         android::sp<T> promoted = p.promote();
44         return std::hash<void*>()(promoted ? promoted.get() : nullptr);
45     }
46 };
47 } // namespace std
48 
49 namespace android::compositionengine::impl::planner {
50 
51 using LayerId = int32_t;
52 
53 // clang-format off
54 enum class LayerStateField : uint32_t {
55     None                  = 0u,
56     Id                    = 1u << 0,
57     Name                  = 1u << 1,
58     DisplayFrame          = 1u << 2,
59     SourceCrop            = 1u << 3,
60     BufferTransform       = 1u << 4,
61     BlendMode             = 1u << 5,
62     Alpha                 = 1u << 6,
63     LayerMetadata         = 1u << 7,
64     VisibleRegion         = 1u << 8,
65     Dataspace             = 1u << 9,
66     PixelFormat           = 1u << 10,
67     ColorTransform        = 1u << 11,
68     SurfaceDamage         = 1u << 12,
69     CompositionType       = 1u << 13,
70     SidebandStream        = 1u << 14,
71     Buffer                = 1u << 15,
72     SolidColor            = 1u << 16,
73     BackgroundBlurRadius  = 1u << 17,
74     BlurRegions           = 1u << 18,
75     HasProtectedContent   = 1u << 19,
76     CachingHint           = 1u << 20,
77     DimmingEnabled        = 1u << 21,
78 };
79 // clang-format on
80 
81 std::string to_string(LayerStateField field);
82 
83 // An abstract interface allows us to iterate over all of the OutputLayerState fields
84 // without having to worry about their templated types.
85 // See `LayerState::getNonUniqueFields` below.
86 class StateInterface {
87 public:
88     virtual ~StateInterface() = default;
89 
90     virtual ftl::Flags<LayerStateField> update(const compositionengine::OutputLayer* layer) = 0;
91 
92     virtual size_t getHash() const = 0;
93 
94     virtual LayerStateField getField() const = 0;
95 
96     virtual ftl::Flags<LayerStateField> getFieldIfDifferent(const StateInterface* other) const = 0;
97 
98     virtual bool equals(const StateInterface* other) const = 0;
99 
100     virtual std::vector<std::string> toStrings() const = 0;
101 };
102 
103 template <typename T, LayerStateField FIELD>
104 class OutputLayerState : public StateInterface {
105 public:
106     using ReadFromLayerState = std::function<T(const compositionengine::OutputLayer* layer)>;
107     using ToStrings = std::function<std::vector<std::string>(const T&)>;
108     using Equals = std::function<bool(const T&, const T&)>;
109     using Hashes = std::function<size_t(const T&)>;
110 
111     static ToStrings getDefaultToStrings() {
112         return [](const T& value) {
113             using std::to_string;
114             return std::vector<std::string>{to_string(value)};
115         };
116     }
117 
118     static ToStrings getHalToStrings() {
119         return [](const T& value) { return std::vector<std::string>{toString(value)}; };
120     }
121 
122     static ToStrings getRegionToStrings() {
123         return [](const Region& region) {
124             using namespace std::string_literals;
125             std::string dump;
126             region.dump(dump, "");
127             std::vector<std::string> split = base::Split(dump, "\n"s);
128             split.erase(split.begin()); // Strip the header
129             split.pop_back();           // Strip the last (empty) line
130             for (std::string& line : split) {
131                 line.erase(0, 4); // Strip leading padding before each rect
132             }
133             return split;
134         };
135     }
136 
137     static Equals getDefaultEquals() {
138         return [](const T& lhs, const T& rhs) { return lhs == rhs; };
139     }
140 
141     static Equals getRegionEquals() {
142         return [](const Region& lhs, const Region& rhs) { return lhs.hasSameRects(rhs); };
143     }
144 
145     static Hashes getDefaultHashes() {
146         return [](const T& value) { return std::hash<T>{}(value); };
147     }
148 
149     OutputLayerState(ReadFromLayerState reader,
150                      ToStrings toStrings = OutputLayerState::getDefaultToStrings(),
151                      Equals equals = OutputLayerState::getDefaultEquals(),
152                      Hashes hashes = OutputLayerState::getDefaultHashes())
153           : mReader(reader), mToStrings(toStrings), mEquals(equals), mHashes(hashes) {}
154 
155     ~OutputLayerState() override = default;
156 
157     // Returns this member's field flag if it was changed
158     ftl::Flags<LayerStateField> update(const compositionengine::OutputLayer* layer) override {
159         T newValue = mReader(layer);
160         return update(newValue);
161     }
162 
163     ftl::Flags<LayerStateField> update(const T& newValue) {
164         if (!mEquals(mValue, newValue)) {
165             mValue = newValue;
166             mHash = {};
167             return FIELD;
168         }
169         return {};
170     }
171 
172     LayerStateField getField() const override { return FIELD; }
173     const T& get() const { return mValue; }
174 
175     size_t getHash() const override {
176         if (!mHash) {
177             mHash = mHashes(mValue);
178         }
179         return *mHash;
180     }
181 
182     ftl::Flags<LayerStateField> getFieldIfDifferent(const StateInterface* other) const override {
183         if (other->getField() != FIELD) {
184             return {};
185         }
186 
187         // The early return ensures that this downcast is sound
188         const OutputLayerState* otherState = static_cast<const OutputLayerState*>(other);
189         return *this != *otherState ? FIELD : ftl::Flags<LayerStateField>{};
190     }
191 
192     bool equals(const StateInterface* other) const override {
193         if (other->getField() != FIELD) {
194             return false;
195         }
196 
197         // The early return ensures that this downcast is sound
198         const OutputLayerState* otherState = static_cast<const OutputLayerState*>(other);
199         return *this == *otherState;
200     }
201 
202     std::vector<std::string> toStrings() const override { return mToStrings(mValue); }
203 
204     bool operator==(const OutputLayerState& other) const { return mEquals(mValue, other.mValue); }
205     bool operator!=(const OutputLayerState& other) const { return !(*this == other); }
206 
207 private:
208     const ReadFromLayerState mReader;
209     const ToStrings mToStrings;
210     const Equals mEquals;
211     const Hashes mHashes;
212     T mValue = {};
213     mutable std::optional<size_t> mHash = {};
214 };
215 
216 class LayerState {
217 public:
218     LayerState(compositionengine::OutputLayer* layer);
219 
220     // Returns which fields were updated
221     ftl::Flags<LayerStateField> update(compositionengine::OutputLayer*);
222 
223     // Computes a hash for this LayerState.
224     // The hash is only computed from NonUniqueFields, and excludes GraphicBuffers since they are
225     // not guaranteed to live longer than the LayerState object.
226     size_t getHash() const;
227 
228     // Returns the bit-set of differing fields between this LayerState and another LayerState.
229     // This bit-set is based on NonUniqueFields only, and excludes GraphicBuffers.
230     ftl::Flags<LayerStateField> getDifferingFields(const LayerState& other) const;
231     bool isSourceCropSizeEqual(const LayerState& other) const;
232 
233     compositionengine::OutputLayer* getOutputLayer() const { return mOutputLayer; }
234     int32_t getId() const { return mId.get(); }
235     const std::string& getName() const { return mName.get(); }
236     Rect getDisplayFrame() const { return mDisplayFrame.get(); }
237     const Region& getVisibleRegion() const { return mVisibleRegion.get(); }
238     bool hasBlurBehind() const {
239         return mBackgroundBlurRadius.get() > 0 || !mBlurRegions.get().empty();
240     }
241     int32_t getBackgroundBlurRadius() const { return mBackgroundBlurRadius.get(); }
242     aidl::android::hardware::graphics::composer3::Composition getCompositionType() const {
243         return mCompositionType.get();
244     }
245 
246     void incrementFramesSinceBufferUpdate() { ++mFramesSinceBufferUpdate; }
247     void resetFramesSinceBufferUpdate() { mFramesSinceBufferUpdate = 0; }
248     int64_t getFramesSinceBufferUpdate() const { return mFramesSinceBufferUpdate; }
249 
250     ui::Dataspace getDataspace() const { return mOutputDataspace.get(); }
251 
252     hardware::graphics::composer::hal::PixelFormat getPixelFormat() const {
253         return mPixelFormat.get();
254     }
255 
256     float getHdrSdrRatio() const {
257         return getOutputLayer()->getLayerFE().getCompositionState()->currentHdrSdrRatio;
258     };
259 
260     wp<GraphicBuffer> getBuffer() const { return mBuffer.get(); }
261 
262     bool isProtected() const { return mIsProtected.get(); }
263 
264     gui::CachingHint getCachingHint() const { return mCachingHint.get(); }
265 
266     bool isDimmingEnabled() const { return mIsDimmingEnabled.get(); }
267 
268     float getFps() const { return getOutputLayer()->getLayerFE().getCompositionState()->fps; }
269 
270     void dump(std::string& result) const;
271     std::optional<std::string> compare(const LayerState& other) const;
272 
273     // This makes LayerState's private members accessible to the operator
274     friend bool operator==(const LayerState& lhs, const LayerState& rhs);
275     friend bool operator!=(const LayerState& lhs, const LayerState& rhs) { return !(lhs == rhs); }
276 
277 private:
278     compositionengine::OutputLayer* mOutputLayer = nullptr;
279 
280     OutputLayerState<LayerId, LayerStateField::Id> mId{
281             [](const compositionengine::OutputLayer* layer) {
282                 return layer->getLayerFE().getSequence();
283             }};
284 
285     OutputLayerState<std::string, LayerStateField::Name>
286             mName{[](auto layer) { return layer->getLayerFE().getDebugName(); },
287                   [](const std::string& name) { return std::vector<std::string>{name}; }};
288 
289     // Output-dependent geometry state
290 
291     OutputLayerState<Rect, LayerStateField::DisplayFrame>
292             mDisplayFrame{[](auto layer) { return layer->getState().displayFrame; },
293                           [](const Rect& rect) {
294                               return std::vector<std::string>{
295                                       base::StringPrintf("[%d, %d, %d, %d]", rect.left, rect.top,
296                                                          rect.right, rect.bottom)};
297                           }};
298 
299     OutputLayerState<FloatRect, LayerStateField::SourceCrop>
300             mSourceCrop{[](auto layer) { return layer->getState().sourceCrop; },
301                         [](const FloatRect& rect) {
302                             return std::vector<std::string>{
303                                     base::StringPrintf("[%.2f, %.2f, %.2f, %.2f]", rect.left,
304                                                        rect.top, rect.right, rect.bottom)};
305                         }};
306 
307     using BufferTransformState = OutputLayerState<hardware::graphics::composer::hal::Transform,
308                                                   LayerStateField::BufferTransform>;
309     BufferTransformState mBufferTransform{[](auto layer) {
310                                               return layer->getState().bufferTransform;
311                                           },
312                                           BufferTransformState::getHalToStrings()};
313 
314     // Output-independent geometry state
315 
316     using BlendModeState = OutputLayerState<hardware::graphics::composer::hal::BlendMode,
317                                             LayerStateField::BlendMode>;
318     BlendModeState mBlendMode{[](auto layer) {
319                                   return layer->getLayerFE().getCompositionState()->blendMode;
320                               },
321                               BlendModeState::getHalToStrings()};
322 
323     OutputLayerState<float, LayerStateField::Alpha> mAlpha{
324             [](auto layer) { return layer->getLayerFE().getCompositionState()->alpha; }};
325 
326     using LayerMetadataState =
327             OutputLayerState<GenericLayerMetadataMap, LayerStateField::LayerMetadata>;
328     LayerMetadataState
329             mLayerMetadata{[](auto layer) {
330                                return layer->getLayerFE().getCompositionState()->metadata;
331                            },
332                            [](const GenericLayerMetadataMap& metadata) {
333                                std::vector<std::string> result;
334                                if (metadata.empty()) {
335                                    result.push_back("{}");
336                                    return result;
337                                }
338                                result.push_back("{");
339                                for (const auto& [key, value] : metadata) {
340                                    std::string keyValueDump;
341                                    keyValueDump.append("           ");
342                                    keyValueDump.append(key);
343                                    keyValueDump.append("=");
344                                    keyValueDump.append(value.dumpAsString());
345                                    result.push_back(keyValueDump);
346                                }
347                                result.push_back("}");
348                                return result;
349                            },
350                            LayerMetadataState::getDefaultEquals(),
351                            [](const GenericLayerMetadataMap& metadata) {
352                                size_t hash = 0;
353                                for (const auto& [key, value] : metadata) {
354                                    size_t entryHash = 0;
355                                    hashCombineSingleHashed(entryHash,
356                                                            std::hash<std::string>{}(key));
357                                    hashCombineSingleHashed(entryHash,
358                                                            GenericLayerMetadataEntry::Hasher{}(
359                                                                    value));
360                                    hash ^= entryHash;
361                                }
362                                return hash;
363                            }};
364 
365     // Output-dependent per-frame state
366 
367     using VisibleRegionState = OutputLayerState<Region, LayerStateField::VisibleRegion>;
368     VisibleRegionState mVisibleRegion{[](auto layer) { return layer->getState().visibleRegion; },
369                                       VisibleRegionState::getRegionToStrings(),
370                                       VisibleRegionState::getRegionEquals()};
371 
372     using DataspaceState = OutputLayerState<ui::Dataspace, LayerStateField::Dataspace>;
373     DataspaceState mOutputDataspace{[](auto layer) { return layer->getState().dataspace; },
374                                     DataspaceState::getHalToStrings()};
375 
376     // Output-independent per-frame state
377 
378     using PixelFormatState = OutputLayerState<hardware::graphics::composer::hal::PixelFormat,
379                                               LayerStateField::PixelFormat>;
380     PixelFormatState
381             mPixelFormat{[](auto layer) {
382                              return layer->getLayerFE().getCompositionState()->buffer
383                                      ? static_cast<hardware::graphics::composer::hal::PixelFormat>(
384                                                layer->getLayerFE()
385                                                        .getCompositionState()
386                                                        ->buffer->getPixelFormat())
387                                      : hardware::graphics::composer::hal::PixelFormat::RGBA_8888;
388                          },
389                          PixelFormatState::getHalToStrings()};
390 
391     OutputLayerState<mat4, LayerStateField::ColorTransform> mColorTransform;
392 
393     using CompositionTypeState =
394             OutputLayerState<aidl::android::hardware::graphics::composer3::Composition,
395                              LayerStateField::CompositionType>;
396     CompositionTypeState mCompositionType{[](auto layer) {
397                                               return layer->getState().forceClientComposition
398                                                       ? aidl::android::hardware::graphics::
399                                                                 composer3::Composition::CLIENT
400                                                       : layer->getLayerFE()
401                                                                 .getCompositionState()
402                                                                 ->compositionType;
403                                           },
404                                           CompositionTypeState::getHalToStrings()};
405 
406     OutputLayerState<void*, LayerStateField::SidebandStream>
407             mSidebandStream{[](auto layer) {
408                                 return layer->getLayerFE()
409                                         .getCompositionState()
410                                         ->sidebandStream.get();
411                             },
412                             [](void* p) {
413                                 return std::vector<std::string>{base::StringPrintf("%p", p)};
414                             }};
415 
416     static auto constexpr BufferEquals = [](const wp<GraphicBuffer>& lhs,
417                                             const wp<GraphicBuffer>& rhs) -> bool {
418         // Avoid a promotion if the wp<>'s aren't equal
419         if (lhs != rhs) return false;
420 
421         // Even if the buffer didn't change, check to see if we need to act as if the buffer changed
422         // anyway. Specifically, look to see if the buffer is FRONT_BUFFER & if so act as if it's
423         // always different
424         using ::aidl::android::hardware::graphics::common::BufferUsage;
425         sp<GraphicBuffer> promotedBuffer = lhs.promote();
426         return !(promotedBuffer &&
427                  ((promotedBuffer->getUsage() & static_cast<int64_t>(BufferUsage::FRONT_BUFFER)) !=
428                   0));
429     };
430 
431     OutputLayerState<wp<GraphicBuffer>, LayerStateField::Buffer>
432             mBuffer{[](auto layer) { return layer->getLayerFE().getCompositionState()->buffer; },
433                     [](const wp<GraphicBuffer>& buffer) {
434                         sp<GraphicBuffer> promotedBuffer = buffer.promote();
435                         return std::vector<std::string>{
436                                 base::StringPrintf("%p",
437                                                    promotedBuffer ? promotedBuffer.get()
438                                                                   : nullptr)};
439                     },
440                     BufferEquals};
441 
442     // Even if the same buffer is passed to BLAST's setBuffer(), we still increment the frame
443     // number and need to treat it as if the buffer changed. Otherwise we break existing
444     // front-buffer rendering paths (such as egl's EGL_SINGLE_BUFFER).
445     OutputLayerState<uint64_t, LayerStateField::Buffer> mFrameNumber{
446             [](auto layer) { return layer->getLayerFE().getCompositionState()->frameNumber; }};
447 
448     int64_t mFramesSinceBufferUpdate = 0;
449 
450     OutputLayerState<half4, LayerStateField::SolidColor>
451             mSolidColor{[](auto layer) { return layer->getLayerFE().getCompositionState()->color; },
452                         [](const half4& vec) {
453                             std::stringstream stream;
454                             stream << vec;
455                             return std::vector<std::string>{stream.str()};
456                         }};
457 
458     OutputLayerState<int32_t, LayerStateField::BackgroundBlurRadius> mBackgroundBlurRadius{
459             [](auto layer) {
460                 return layer->getLayerFE().getCompositionState()->backgroundBlurRadius;
461             }};
462 
463     using BlurRegionsState =
464             OutputLayerState<std::vector<BlurRegion>, LayerStateField::BlurRegions>;
465     BlurRegionsState mBlurRegions{[](auto layer) {
466                                       return layer->getLayerFE().getCompositionState()->blurRegions;
467                                   },
468                                   [](const std::vector<BlurRegion>& regions) {
469                                       std::vector<std::string> result;
470                                       for (const auto region : regions) {
471                                           std::string str;
472                                           base::StringAppendF(&str,
473                                                               "{radius=%du, cornerRadii=[%f, %f, "
474                                                               "%f, %f], alpha=%f, rect=[%d, "
475                                                               "%d, %d, %d]",
476                                                               region.blurRadius,
477                                                               region.cornerRadiusTL,
478                                                               region.cornerRadiusTR,
479                                                               region.cornerRadiusBL,
480                                                               region.cornerRadiusBR, region.alpha,
481                                                               region.left, region.top, region.right,
482                                                               region.bottom);
483                                           result.push_back(str);
484                                       }
485                                       return result;
486                                   },
487                                   BlurRegionsState::getDefaultEquals(),
488                                   [](const std::vector<BlurRegion>& regions) {
489                                       size_t hash = 0;
490                                       for (const auto& region : regions) {
491                                           android::hashCombineSingle(hash, region);
492                                       }
493                                       return hash;
494                                   }};
495 
496     OutputLayerState<bool, LayerStateField::HasProtectedContent> mIsProtected{[](auto layer) {
497         return layer->getLayerFE().getCompositionState()->hasProtectedContent;
498     }};
499 
500     OutputLayerState<gui::CachingHint, LayerStateField::CachingHint>
501             mCachingHint{[](auto layer) {
502                              return layer->getLayerFE().getCompositionState()->cachingHint;
503                          },
504                          [](const gui::CachingHint& cachingHint) {
505                              return std::vector<std::string>{toString(cachingHint)};
506                          }};
507 
508     OutputLayerState<bool, LayerStateField::DimmingEnabled> mIsDimmingEnabled{
509             [](auto layer) { return layer->getLayerFE().getCompositionState()->dimmingEnabled; }};
510 
511     static const constexpr size_t kNumNonUniqueFields = 20;
512 
513     std::array<StateInterface*, kNumNonUniqueFields> getNonUniqueFields() {
514         std::array<const StateInterface*, kNumNonUniqueFields> constFields =
515                 const_cast<const LayerState*>(this)->getNonUniqueFields();
516         std::array<StateInterface*, kNumNonUniqueFields> fields;
517         std::transform(constFields.cbegin(), constFields.cend(), fields.begin(),
518                        [](const StateInterface* constField) {
519                            return const_cast<StateInterface*>(constField);
520                        });
521         return fields;
522     }
523 
524     std::array<const StateInterface*, kNumNonUniqueFields> getNonUniqueFields() const {
525         return {&mDisplayFrame, &mSourceCrop,     &mBufferTransform,      &mBlendMode,
526                 &mAlpha,        &mLayerMetadata,  &mVisibleRegion,        &mOutputDataspace,
527                 &mPixelFormat,  &mColorTransform, &mCompositionType,      &mSidebandStream,
528                 &mBuffer,       &mSolidColor,     &mBackgroundBlurRadius, &mBlurRegions,
529                 &mFrameNumber,  &mIsProtected,    &mCachingHint,          &mIsDimmingEnabled};
530     }
531 };
532 
533 using NonBufferHash = size_t;
534 NonBufferHash getNonBufferHash(const std::vector<const LayerState*>&);
535 
536 } // namespace android::compositionengine::impl::planner
537