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