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