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