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