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