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