1 /* 2 * Copyright (C) 2010 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 // #define LOG_NDEBUG 0 18 19 #undef LOG_TAG 20 #define LOG_TAG "HWComposer" 21 #define ATRACE_TAG ATRACE_TAG_GRAPHICS 22 23 #include <compositionengine/Output.h> 24 #include <compositionengine/OutputLayer.h> 25 #include <compositionengine/impl/OutputLayerCompositionState.h> 26 #include <log/log.h> 27 #include <ui/DebugUtils.h> 28 #include <ui/GraphicBuffer.h> 29 #include <utils/Errors.h> 30 #include <utils/Trace.h> 31 32 #include "HWComposer.h" 33 #include "HWC2.h" 34 #include "ComposerHal.h" 35 36 #include "../Layer.h" // needed only for debugging 37 #include "../SurfaceFlinger.h" 38 39 #define LOG_HWC_DISPLAY_ERROR(hwcDisplayId, msg) \ 40 ALOGE("%s failed for HWC display %" PRIu64 ": %s", __FUNCTION__, hwcDisplayId, msg) 41 42 #define LOG_DISPLAY_ERROR(displayId, msg) \ 43 ALOGE("%s failed for display %s: %s", __FUNCTION__, to_string(displayId).c_str(), msg) 44 45 #define LOG_HWC_ERROR(what, error, displayId) \ 46 ALOGE("%s: %s failed for display %s: %s (%d)", __FUNCTION__, what, \ 47 to_string(displayId).c_str(), to_string(error).c_str(), static_cast<int32_t>(error)) 48 49 #define RETURN_IF_INVALID_DISPLAY(displayId, ...) \ 50 do { \ 51 if (mDisplayData.count(displayId) == 0) { \ 52 LOG_DISPLAY_ERROR(displayId, "Invalid display"); \ 53 return __VA_ARGS__; \ 54 } \ 55 } while (false) 56 57 #define RETURN_IF_HWC_ERROR_FOR(what, error, displayId, ...) \ 58 do { \ 59 if (error != HWC2::Error::None) { \ 60 LOG_HWC_ERROR(what, error, displayId); \ 61 return __VA_ARGS__; \ 62 } \ 63 } while (false) 64 65 #define RETURN_IF_HWC_ERROR(error, displayId, ...) \ 66 RETURN_IF_HWC_ERROR_FOR(__FUNCTION__, error, displayId, __VA_ARGS__) 67 68 namespace android { 69 70 HWComposer::~HWComposer() = default; 71 72 namespace impl { 73 74 HWComposer::HWComposer(std::unique_ptr<Hwc2::Composer> composer) 75 : mHwcDevice(std::make_unique<HWC2::Device>(std::move(composer))) {} 76 77 HWComposer::~HWComposer() { 78 mDisplayData.clear(); 79 } 80 81 void HWComposer::registerCallback(HWC2::ComposerCallback* callback, 82 int32_t sequenceId) { 83 mHwcDevice->registerCallback(callback, sequenceId); 84 } 85 86 bool HWComposer::getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8_t* outPort, 87 DisplayIdentificationData* outData) const { 88 const auto error = mHwcDevice->getDisplayIdentificationData(hwcDisplayId, outPort, outData); 89 if (error != HWC2::Error::None) { 90 if (error != HWC2::Error::Unsupported) { 91 LOG_HWC_DISPLAY_ERROR(hwcDisplayId, to_string(error).c_str()); 92 } 93 return false; 94 } 95 return true; 96 } 97 98 bool HWComposer::hasCapability(HWC2::Capability capability) const 99 { 100 return mHwcDevice->getCapabilities().count(capability) > 0; 101 } 102 103 bool HWComposer::hasDisplayCapability(const std::optional<DisplayId>& displayId, 104 HWC2::DisplayCapability capability) const { 105 if (!displayId) { 106 // Checkout global capabilities for displays without a corresponding HWC display. 107 if (capability == HWC2::DisplayCapability::SkipClientColorTransform) { 108 return hasCapability(HWC2::Capability::SkipClientColorTransform); 109 } 110 return false; 111 } 112 RETURN_IF_INVALID_DISPLAY(*displayId, false); 113 return mDisplayData.at(*displayId).hwcDisplay->getCapabilities().count(capability) > 0; 114 } 115 116 void HWComposer::validateChange(HWC2::Composition from, HWC2::Composition to) { 117 bool valid = true; 118 switch (from) { 119 case HWC2::Composition::Client: 120 valid = false; 121 break; 122 case HWC2::Composition::Device: 123 case HWC2::Composition::SolidColor: 124 valid = (to == HWC2::Composition::Client); 125 break; 126 case HWC2::Composition::Cursor: 127 case HWC2::Composition::Sideband: 128 valid = (to == HWC2::Composition::Client || 129 to == HWC2::Composition::Device); 130 break; 131 default: 132 break; 133 } 134 135 if (!valid) { 136 ALOGE("Invalid layer type change: %s --> %s", to_string(from).c_str(), 137 to_string(to).c_str()); 138 } 139 } 140 141 std::optional<DisplayIdentificationInfo> HWComposer::onHotplug(hwc2_display_t hwcDisplayId, 142 HWC2::Connection connection) { 143 std::optional<DisplayIdentificationInfo> info; 144 145 if (const auto displayId = toPhysicalDisplayId(hwcDisplayId)) { 146 info = DisplayIdentificationInfo{*displayId, std::string()}; 147 } else { 148 if (connection == HWC2::Connection::Disconnected) { 149 ALOGE("Ignoring disconnection of invalid HWC display %" PRIu64, hwcDisplayId); 150 return {}; 151 } 152 153 info = onHotplugConnect(hwcDisplayId); 154 if (!info) return {}; 155 } 156 157 ALOGV("%s: %s %s display %s with HWC ID %" PRIu64, __FUNCTION__, to_string(connection).c_str(), 158 hwcDisplayId == mInternalHwcDisplayId ? "internal" : "external", 159 to_string(info->id).c_str(), hwcDisplayId); 160 161 mHwcDevice->onHotplug(hwcDisplayId, connection); 162 163 // Disconnect is handled through HWComposer::disconnectDisplay via 164 // SurfaceFlinger's onHotplugReceived callback handling 165 if (connection == HWC2::Connection::Connected) { 166 mDisplayData[info->id].hwcDisplay = mHwcDevice->getDisplayById(hwcDisplayId); 167 mPhysicalDisplayIdMap[hwcDisplayId] = info->id; 168 } 169 170 return info; 171 } 172 173 bool HWComposer::onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp) { 174 const auto displayId = toPhysicalDisplayId(hwcDisplayId); 175 if (!displayId) { 176 LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid HWC display"); 177 return false; 178 } 179 180 RETURN_IF_INVALID_DISPLAY(*displayId, false); 181 182 auto& displayData = mDisplayData[*displayId]; 183 if (displayData.isVirtual) { 184 LOG_DISPLAY_ERROR(*displayId, "Invalid operation on virtual display"); 185 return false; 186 } 187 188 { 189 std::lock_guard lock(displayData.lastHwVsyncLock); 190 191 // There have been reports of HWCs that signal several vsync events 192 // with the same timestamp when turning the display off and on. This 193 // is a bug in the HWC implementation, but filter the extra events 194 // out here so they don't cause havoc downstream. 195 if (timestamp == displayData.lastHwVsync) { 196 ALOGW("Ignoring duplicate VSYNC event from HWC for display %s (t=%" PRId64 ")", 197 to_string(*displayId).c_str(), timestamp); 198 return false; 199 } 200 201 displayData.lastHwVsync = timestamp; 202 } 203 204 const auto tag = "HW_VSYNC_" + to_string(*displayId); 205 ATRACE_INT(tag.c_str(), displayData.vsyncTraceToggle); 206 displayData.vsyncTraceToggle = !displayData.vsyncTraceToggle; 207 208 return true; 209 } 210 211 std::optional<DisplayId> HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height, 212 ui::PixelFormat* format) { 213 if (mRemainingHwcVirtualDisplays == 0) { 214 ALOGE("%s: No remaining virtual displays", __FUNCTION__); 215 return {}; 216 } 217 218 if (SurfaceFlinger::maxVirtualDisplaySize != 0 && 219 (width > SurfaceFlinger::maxVirtualDisplaySize || 220 height > SurfaceFlinger::maxVirtualDisplaySize)) { 221 ALOGE("%s: Display size %ux%u exceeds maximum dimension of %" PRIu64, __FUNCTION__, width, 222 height, SurfaceFlinger::maxVirtualDisplaySize); 223 return {}; 224 } 225 HWC2::Display* display; 226 auto error = mHwcDevice->createVirtualDisplay(width, height, format, 227 &display); 228 if (error != HWC2::Error::None) { 229 ALOGE("%s: Failed to create HWC virtual display", __FUNCTION__); 230 return {}; 231 } 232 233 DisplayId displayId; 234 if (mFreeVirtualDisplayIds.empty()) { 235 displayId = getVirtualDisplayId(mNextVirtualDisplayId++); 236 } else { 237 displayId = *mFreeVirtualDisplayIds.begin(); 238 mFreeVirtualDisplayIds.erase(displayId); 239 } 240 241 auto& displayData = mDisplayData[displayId]; 242 displayData.hwcDisplay = display; 243 displayData.isVirtual = true; 244 245 --mRemainingHwcVirtualDisplays; 246 return displayId; 247 } 248 249 HWC2::Layer* HWComposer::createLayer(DisplayId displayId) { 250 RETURN_IF_INVALID_DISPLAY(displayId, nullptr); 251 252 auto display = mDisplayData[displayId].hwcDisplay; 253 HWC2::Layer* layer; 254 auto error = display->createLayer(&layer); 255 RETURN_IF_HWC_ERROR(error, displayId, nullptr); 256 return layer; 257 } 258 259 void HWComposer::destroyLayer(DisplayId displayId, HWC2::Layer* layer) { 260 RETURN_IF_INVALID_DISPLAY(displayId); 261 262 auto display = mDisplayData[displayId].hwcDisplay; 263 auto error = display->destroyLayer(layer); 264 RETURN_IF_HWC_ERROR(error, displayId); 265 } 266 267 nsecs_t HWComposer::getRefreshTimestamp(DisplayId displayId) const { 268 RETURN_IF_INVALID_DISPLAY(displayId, 0); 269 const auto& displayData = mDisplayData.at(displayId); 270 // this returns the last refresh timestamp. 271 // if the last one is not available, we estimate it based on 272 // the refresh period and whatever closest timestamp we have. 273 std::lock_guard lock(displayData.lastHwVsyncLock); 274 nsecs_t now = systemTime(CLOCK_MONOTONIC); 275 auto vsyncPeriod = getActiveConfig(displayId)->getVsyncPeriod(); 276 return now - ((now - displayData.lastHwVsync) % vsyncPeriod); 277 } 278 279 bool HWComposer::isConnected(DisplayId displayId) const { 280 RETURN_IF_INVALID_DISPLAY(displayId, false); 281 return mDisplayData.at(displayId).hwcDisplay->isConnected(); 282 } 283 284 std::vector<std::shared_ptr<const HWC2::Display::Config>> HWComposer::getConfigs( 285 DisplayId displayId) const { 286 RETURN_IF_INVALID_DISPLAY(displayId, {}); 287 288 const auto& displayData = mDisplayData.at(displayId); 289 auto configs = displayData.hwcDisplay->getConfigs(); 290 if (displayData.configMap.empty()) { 291 for (size_t i = 0; i < configs.size(); ++i) { 292 displayData.configMap[i] = configs[i]; 293 } 294 } 295 return configs; 296 } 297 298 std::shared_ptr<const HWC2::Display::Config> HWComposer::getActiveConfig( 299 DisplayId displayId) const { 300 RETURN_IF_INVALID_DISPLAY(displayId, nullptr); 301 302 std::shared_ptr<const HWC2::Display::Config> config; 303 auto error = mDisplayData.at(displayId).hwcDisplay->getActiveConfig(&config); 304 if (error == HWC2::Error::BadConfig) { 305 LOG_DISPLAY_ERROR(displayId, "No active config"); 306 return nullptr; 307 } 308 309 RETURN_IF_HWC_ERROR(error, displayId, nullptr); 310 311 if (!config) { 312 LOG_DISPLAY_ERROR(displayId, "Unknown config"); 313 return nullptr; 314 } 315 316 return config; 317 } 318 319 int HWComposer::getActiveConfigIndex(DisplayId displayId) const { 320 RETURN_IF_INVALID_DISPLAY(displayId, -1); 321 322 int index; 323 auto error = mDisplayData.at(displayId).hwcDisplay->getActiveConfigIndex(&index); 324 if (error == HWC2::Error::BadConfig) { 325 LOG_DISPLAY_ERROR(displayId, "No active config"); 326 return -1; 327 } 328 329 RETURN_IF_HWC_ERROR(error, displayId, -1); 330 331 if (index < 0) { 332 LOG_DISPLAY_ERROR(displayId, "Unknown config"); 333 return -1; 334 } 335 336 return index; 337 } 338 339 std::vector<ui::ColorMode> HWComposer::getColorModes(DisplayId displayId) const { 340 RETURN_IF_INVALID_DISPLAY(displayId, {}); 341 342 std::vector<ui::ColorMode> modes; 343 auto error = mDisplayData.at(displayId).hwcDisplay->getColorModes(&modes); 344 RETURN_IF_HWC_ERROR(error, displayId, {}); 345 return modes; 346 } 347 348 status_t HWComposer::setActiveColorMode(DisplayId displayId, ui::ColorMode mode, 349 ui::RenderIntent renderIntent) { 350 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); 351 352 auto& displayData = mDisplayData[displayId]; 353 auto error = displayData.hwcDisplay->setColorMode(mode, renderIntent); 354 RETURN_IF_HWC_ERROR_FOR(("setColorMode(" + decodeColorMode(mode) + ", " + 355 decodeRenderIntent(renderIntent) + ")") 356 .c_str(), 357 error, displayId, UNKNOWN_ERROR); 358 359 return NO_ERROR; 360 } 361 362 void HWComposer::setVsyncEnabled(DisplayId displayId, HWC2::Vsync enabled) { 363 RETURN_IF_INVALID_DISPLAY(displayId); 364 auto& displayData = mDisplayData[displayId]; 365 366 if (displayData.isVirtual) { 367 LOG_DISPLAY_ERROR(displayId, "Invalid operation on virtual display"); 368 return; 369 } 370 371 // NOTE: we use our own internal lock here because we have to call 372 // into the HWC with the lock held, and we want to make sure 373 // that even if HWC blocks (which it shouldn't), it won't 374 // affect other threads. 375 std::lock_guard lock(displayData.vsyncEnabledLock); 376 if (enabled == displayData.vsyncEnabled) { 377 return; 378 } 379 380 ATRACE_CALL(); 381 auto error = displayData.hwcDisplay->setVsyncEnabled(enabled); 382 RETURN_IF_HWC_ERROR(error, displayId); 383 384 displayData.vsyncEnabled = enabled; 385 386 const auto tag = "HW_VSYNC_ON_" + to_string(displayId); 387 ATRACE_INT(tag.c_str(), enabled == HWC2::Vsync::Enable ? 1 : 0); 388 } 389 390 status_t HWComposer::setClientTarget(DisplayId displayId, uint32_t slot, 391 const sp<Fence>& acquireFence, const sp<GraphicBuffer>& target, 392 ui::Dataspace dataspace) { 393 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); 394 395 ALOGV("%s for display %s", __FUNCTION__, to_string(displayId).c_str()); 396 auto& hwcDisplay = mDisplayData[displayId].hwcDisplay; 397 auto error = hwcDisplay->setClientTarget(slot, target, acquireFence, dataspace); 398 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE); 399 return NO_ERROR; 400 } 401 402 status_t HWComposer::prepare(DisplayId displayId, const compositionengine::Output& output) { 403 ATRACE_CALL(); 404 405 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); 406 407 auto& displayData = mDisplayData[displayId]; 408 auto& hwcDisplay = displayData.hwcDisplay; 409 if (!hwcDisplay->isConnected()) { 410 return NO_ERROR; 411 } 412 413 uint32_t numTypes = 0; 414 uint32_t numRequests = 0; 415 416 HWC2::Error error = HWC2::Error::None; 417 418 // First try to skip validate altogether when there is no client 419 // composition. When there is client composition, since we haven't 420 // rendered to the client target yet, we should not attempt to skip 421 // validate. 422 // 423 // displayData.hasClientComposition hasn't been updated for this frame. 424 // The check below is incorrect. We actually rely on HWC here to fall 425 // back to validate when there is any client layer. 426 displayData.validateWasSkipped = false; 427 if (!displayData.hasClientComposition) { 428 sp<Fence> outPresentFence; 429 uint32_t state = UINT32_MAX; 430 error = hwcDisplay->presentOrValidate(&numTypes, &numRequests, &outPresentFence , &state); 431 if (error != HWC2::Error::HasChanges) { 432 RETURN_IF_HWC_ERROR_FOR("presentOrValidate", error, displayId, UNKNOWN_ERROR); 433 } 434 if (state == 1) { //Present Succeeded. 435 std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences; 436 error = hwcDisplay->getReleaseFences(&releaseFences); 437 displayData.releaseFences = std::move(releaseFences); 438 displayData.lastPresentFence = outPresentFence; 439 displayData.validateWasSkipped = true; 440 displayData.presentError = error; 441 return NO_ERROR; 442 } 443 // Present failed but Validate ran. 444 } else { 445 error = hwcDisplay->validate(&numTypes, &numRequests); 446 } 447 ALOGV("SkipValidate failed, Falling back to SLOW validate/present"); 448 if (error != HWC2::Error::HasChanges) { 449 RETURN_IF_HWC_ERROR_FOR("validate", error, displayId, BAD_INDEX); 450 } 451 452 std::unordered_map<HWC2::Layer*, HWC2::Composition> changedTypes; 453 changedTypes.reserve(numTypes); 454 error = hwcDisplay->getChangedCompositionTypes(&changedTypes); 455 RETURN_IF_HWC_ERROR_FOR("getChangedCompositionTypes", error, displayId, BAD_INDEX); 456 457 displayData.displayRequests = static_cast<HWC2::DisplayRequest>(0); 458 std::unordered_map<HWC2::Layer*, HWC2::LayerRequest> layerRequests; 459 layerRequests.reserve(numRequests); 460 error = hwcDisplay->getRequests(&displayData.displayRequests, 461 &layerRequests); 462 RETURN_IF_HWC_ERROR_FOR("getRequests", error, displayId, BAD_INDEX); 463 464 displayData.hasClientComposition = false; 465 displayData.hasDeviceComposition = false; 466 for (auto& outputLayer : output.getOutputLayersOrderedByZ()) { 467 auto& state = outputLayer->editState(); 468 LOG_FATAL_IF(!state.hwc.); 469 auto hwcLayer = (*state.hwc).hwcLayer; 470 471 if (auto it = changedTypes.find(hwcLayer.get()); it != changedTypes.end()) { 472 auto newCompositionType = it->second; 473 validateChange(static_cast<HWC2::Composition>((*state.hwc).hwcCompositionType), 474 newCompositionType); 475 (*state.hwc).hwcCompositionType = 476 static_cast<Hwc2::IComposerClient::Composition>(newCompositionType); 477 } 478 479 switch ((*state.hwc).hwcCompositionType) { 480 case Hwc2::IComposerClient::Composition::CLIENT: 481 displayData.hasClientComposition = true; 482 break; 483 case Hwc2::IComposerClient::Composition::DEVICE: 484 case Hwc2::IComposerClient::Composition::SOLID_COLOR: 485 case Hwc2::IComposerClient::Composition::CURSOR: 486 case Hwc2::IComposerClient::Composition::SIDEBAND: 487 displayData.hasDeviceComposition = true; 488 break; 489 default: 490 break; 491 } 492 493 state.clearClientTarget = false; 494 if (auto it = layerRequests.find(hwcLayer.get()); it != layerRequests.end()) { 495 auto request = it->second; 496 if (request == HWC2::LayerRequest::ClearClientTarget) { 497 state.clearClientTarget = true; 498 } else { 499 LOG_DISPLAY_ERROR(displayId, 500 ("Unknown layer request " + to_string(request)).c_str()); 501 } 502 } 503 } 504 505 error = hwcDisplay->acceptChanges(); 506 RETURN_IF_HWC_ERROR_FOR("acceptChanges", error, displayId, BAD_INDEX); 507 508 return NO_ERROR; 509 } 510 511 bool HWComposer::hasDeviceComposition(const std::optional<DisplayId>& displayId) const { 512 if (!displayId) { 513 // Displays without a corresponding HWC display are never composed by 514 // the device 515 return false; 516 } 517 518 RETURN_IF_INVALID_DISPLAY(*displayId, false); 519 return mDisplayData.at(*displayId).hasDeviceComposition; 520 } 521 522 bool HWComposer::hasFlipClientTargetRequest(const std::optional<DisplayId>& displayId) const { 523 if (!displayId) { 524 // Displays without a corresponding HWC display are never composed by 525 // the device 526 return false; 527 } 528 529 RETURN_IF_INVALID_DISPLAY(*displayId, false); 530 return ((static_cast<uint32_t>(mDisplayData.at(*displayId).displayRequests) & 531 static_cast<uint32_t>(HWC2::DisplayRequest::FlipClientTarget)) != 0); 532 } 533 534 bool HWComposer::hasClientComposition(const std::optional<DisplayId>& displayId) const { 535 if (!displayId) { 536 // Displays without a corresponding HWC display are always composed by 537 // the client 538 return true; 539 } 540 541 RETURN_IF_INVALID_DISPLAY(*displayId, true); 542 return mDisplayData.at(*displayId).hasClientComposition; 543 } 544 545 sp<Fence> HWComposer::getPresentFence(DisplayId displayId) const { 546 RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE); 547 return mDisplayData.at(displayId).lastPresentFence; 548 } 549 550 sp<Fence> HWComposer::getLayerReleaseFence(DisplayId displayId, HWC2::Layer* layer) const { 551 RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE); 552 auto displayFences = mDisplayData.at(displayId).releaseFences; 553 if (displayFences.count(layer) == 0) { 554 ALOGV("getLayerReleaseFence: Release fence not found"); 555 return Fence::NO_FENCE; 556 } 557 return displayFences[layer]; 558 } 559 560 status_t HWComposer::presentAndGetReleaseFences(DisplayId displayId) { 561 ATRACE_CALL(); 562 563 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); 564 565 auto& displayData = mDisplayData[displayId]; 566 auto& hwcDisplay = displayData.hwcDisplay; 567 568 if (displayData.validateWasSkipped) { 569 // explicitly flush all pending commands 570 auto error = mHwcDevice->flushCommands(); 571 RETURN_IF_HWC_ERROR_FOR("flushCommands", error, displayId, UNKNOWN_ERROR); 572 RETURN_IF_HWC_ERROR_FOR("present", displayData.presentError, displayId, UNKNOWN_ERROR); 573 return NO_ERROR; 574 } 575 576 auto error = hwcDisplay->present(&displayData.lastPresentFence); 577 RETURN_IF_HWC_ERROR_FOR("present", error, displayId, UNKNOWN_ERROR); 578 579 std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences; 580 error = hwcDisplay->getReleaseFences(&releaseFences); 581 RETURN_IF_HWC_ERROR_FOR("getReleaseFences", error, displayId, UNKNOWN_ERROR); 582 583 displayData.releaseFences = std::move(releaseFences); 584 585 return NO_ERROR; 586 } 587 588 status_t HWComposer::setPowerMode(DisplayId displayId, int32_t intMode) { 589 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); 590 591 const auto& displayData = mDisplayData[displayId]; 592 if (displayData.isVirtual) { 593 LOG_DISPLAY_ERROR(displayId, "Invalid operation on virtual display"); 594 return INVALID_OPERATION; 595 } 596 597 auto mode = static_cast<HWC2::PowerMode>(intMode); 598 if (mode == HWC2::PowerMode::Off) { 599 setVsyncEnabled(displayId, HWC2::Vsync::Disable); 600 } 601 602 auto& hwcDisplay = displayData.hwcDisplay; 603 switch (mode) { 604 case HWC2::PowerMode::Off: 605 case HWC2::PowerMode::On: 606 ALOGV("setPowerMode: Calling HWC %s", to_string(mode).c_str()); 607 { 608 auto error = hwcDisplay->setPowerMode(mode); 609 if (error != HWC2::Error::None) { 610 LOG_HWC_ERROR(("setPowerMode(" + to_string(mode) + ")").c_str(), 611 error, displayId); 612 } 613 } 614 break; 615 case HWC2::PowerMode::Doze: 616 case HWC2::PowerMode::DozeSuspend: 617 ALOGV("setPowerMode: Calling HWC %s", to_string(mode).c_str()); 618 { 619 bool supportsDoze = false; 620 auto error = hwcDisplay->supportsDoze(&supportsDoze); 621 if (error != HWC2::Error::None) { 622 LOG_HWC_ERROR("supportsDoze", error, displayId); 623 } 624 625 if (!supportsDoze) { 626 mode = HWC2::PowerMode::On; 627 } 628 629 error = hwcDisplay->setPowerMode(mode); 630 if (error != HWC2::Error::None) { 631 LOG_HWC_ERROR(("setPowerMode(" + to_string(mode) + ")").c_str(), 632 error, displayId); 633 } 634 } 635 break; 636 default: 637 ALOGV("setPowerMode: Not calling HWC"); 638 break; 639 } 640 641 return NO_ERROR; 642 } 643 644 status_t HWComposer::setActiveConfig(DisplayId displayId, size_t configId) { 645 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); 646 647 auto& displayData = mDisplayData[displayId]; 648 if (displayData.configMap.count(configId) == 0) { 649 LOG_DISPLAY_ERROR(displayId, ("Invalid config " + std::to_string(configId)).c_str()); 650 return BAD_INDEX; 651 } 652 653 auto error = displayData.hwcDisplay->setActiveConfig(displayData.configMap[configId]); 654 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR); 655 return NO_ERROR; 656 } 657 658 status_t HWComposer::setColorTransform(DisplayId displayId, const mat4& transform) { 659 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); 660 661 auto& displayData = mDisplayData[displayId]; 662 bool isIdentity = transform == mat4(); 663 auto error = displayData.hwcDisplay->setColorTransform(transform, 664 isIdentity ? HAL_COLOR_TRANSFORM_IDENTITY : 665 HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX); 666 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR); 667 return NO_ERROR; 668 } 669 670 void HWComposer::disconnectDisplay(DisplayId displayId) { 671 RETURN_IF_INVALID_DISPLAY(displayId); 672 auto& displayData = mDisplayData[displayId]; 673 674 // If this was a virtual display, add its slot back for reuse by future 675 // virtual displays 676 if (displayData.isVirtual) { 677 mFreeVirtualDisplayIds.insert(displayId); 678 ++mRemainingHwcVirtualDisplays; 679 } 680 681 const auto hwcDisplayId = displayData.hwcDisplay->getId(); 682 mPhysicalDisplayIdMap.erase(hwcDisplayId); 683 mDisplayData.erase(displayId); 684 685 // TODO(b/74619554): Select internal/external display from remaining displays. 686 if (hwcDisplayId == mInternalHwcDisplayId) { 687 mInternalHwcDisplayId.reset(); 688 } else if (hwcDisplayId == mExternalHwcDisplayId) { 689 mExternalHwcDisplayId.reset(); 690 } 691 692 mHwcDevice->destroyDisplay(hwcDisplayId); 693 } 694 695 status_t HWComposer::setOutputBuffer(DisplayId displayId, const sp<Fence>& acquireFence, 696 const sp<GraphicBuffer>& buffer) { 697 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); 698 const auto& displayData = mDisplayData[displayId]; 699 700 if (!displayData.isVirtual) { 701 LOG_DISPLAY_ERROR(displayId, "Invalid operation on physical display"); 702 return INVALID_OPERATION; 703 } 704 705 auto error = displayData.hwcDisplay->setOutputBuffer(buffer, acquireFence); 706 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR); 707 return NO_ERROR; 708 } 709 710 void HWComposer::clearReleaseFences(DisplayId displayId) { 711 RETURN_IF_INVALID_DISPLAY(displayId); 712 mDisplayData[displayId].releaseFences.clear(); 713 } 714 715 status_t HWComposer::getHdrCapabilities(DisplayId displayId, HdrCapabilities* outCapabilities) { 716 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); 717 718 auto& hwcDisplay = mDisplayData[displayId].hwcDisplay; 719 auto error = hwcDisplay->getHdrCapabilities(outCapabilities); 720 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR); 721 return NO_ERROR; 722 } 723 724 int32_t HWComposer::getSupportedPerFrameMetadata(DisplayId displayId) const { 725 RETURN_IF_INVALID_DISPLAY(displayId, 0); 726 return mDisplayData.at(displayId).hwcDisplay->getSupportedPerFrameMetadata(); 727 } 728 729 std::vector<ui::RenderIntent> HWComposer::getRenderIntents(DisplayId displayId, 730 ui::ColorMode colorMode) const { 731 RETURN_IF_INVALID_DISPLAY(displayId, {}); 732 733 std::vector<ui::RenderIntent> renderIntents; 734 auto error = mDisplayData.at(displayId).hwcDisplay->getRenderIntents(colorMode, &renderIntents); 735 RETURN_IF_HWC_ERROR(error, displayId, {}); 736 return renderIntents; 737 } 738 739 mat4 HWComposer::getDataspaceSaturationMatrix(DisplayId displayId, ui::Dataspace dataspace) { 740 RETURN_IF_INVALID_DISPLAY(displayId, {}); 741 742 mat4 matrix; 743 auto error = mDisplayData[displayId].hwcDisplay->getDataspaceSaturationMatrix(dataspace, 744 &matrix); 745 RETURN_IF_HWC_ERROR(error, displayId, {}); 746 return matrix; 747 } 748 749 status_t HWComposer::getDisplayedContentSamplingAttributes(DisplayId displayId, 750 ui::PixelFormat* outFormat, 751 ui::Dataspace* outDataspace, 752 uint8_t* outComponentMask) { 753 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); 754 const auto error = 755 mDisplayData[displayId] 756 .hwcDisplay->getDisplayedContentSamplingAttributes(outFormat, outDataspace, 757 outComponentMask); 758 if (error == HWC2::Error::Unsupported) RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION); 759 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR); 760 return NO_ERROR; 761 } 762 763 status_t HWComposer::setDisplayContentSamplingEnabled(DisplayId displayId, bool enabled, 764 uint8_t componentMask, uint64_t maxFrames) { 765 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); 766 const auto error = 767 mDisplayData[displayId].hwcDisplay->setDisplayContentSamplingEnabled(enabled, 768 componentMask, 769 maxFrames); 770 771 if (error == HWC2::Error::Unsupported) RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION); 772 if (error == HWC2::Error::BadParameter) RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE); 773 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR); 774 return NO_ERROR; 775 } 776 777 status_t HWComposer::getDisplayedContentSample(DisplayId displayId, uint64_t maxFrames, 778 uint64_t timestamp, DisplayedFrameStats* outStats) { 779 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); 780 const auto error = 781 mDisplayData[displayId].hwcDisplay->getDisplayedContentSample(maxFrames, timestamp, 782 outStats); 783 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR); 784 return NO_ERROR; 785 } 786 787 status_t HWComposer::setDisplayBrightness(DisplayId displayId, float brightness) { 788 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); 789 const auto error = mDisplayData[displayId].hwcDisplay->setDisplayBrightness(brightness); 790 if (error == HWC2::Error::Unsupported) { 791 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION); 792 } 793 if (error == HWC2::Error::BadParameter) { 794 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE); 795 } 796 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR); 797 return NO_ERROR; 798 } 799 800 bool HWComposer::isUsingVrComposer() const { 801 return getComposer()->isUsingVrComposer(); 802 } 803 804 void HWComposer::dump(std::string& result) const { 805 // TODO: In order to provide a dump equivalent to HWC1, we need to shadow 806 // all the state going into the layers. This is probably better done in 807 // Layer itself, but it's going to take a bit of work to get there. 808 result.append(mHwcDevice->dump()); 809 } 810 811 std::optional<DisplayId> HWComposer::toPhysicalDisplayId(hwc2_display_t hwcDisplayId) const { 812 if (const auto it = mPhysicalDisplayIdMap.find(hwcDisplayId); 813 it != mPhysicalDisplayIdMap.end()) { 814 return it->second; 815 } 816 return {}; 817 } 818 819 std::optional<hwc2_display_t> HWComposer::fromPhysicalDisplayId(DisplayId displayId) const { 820 if (const auto it = mDisplayData.find(displayId); 821 it != mDisplayData.end() && !it->second.isVirtual) { 822 return it->second.hwcDisplay->getId(); 823 } 824 return {}; 825 } 826 827 std::optional<DisplayIdentificationInfo> HWComposer::onHotplugConnect(hwc2_display_t hwcDisplayId) { 828 if (isUsingVrComposer() && mInternalHwcDisplayId) { 829 ALOGE("Ignoring connection of external display %" PRIu64 " in VR mode", hwcDisplayId); 830 return {}; 831 } 832 833 uint8_t port; 834 DisplayIdentificationData data; 835 const bool hasMultiDisplaySupport = getDisplayIdentificationData(hwcDisplayId, &port, &data); 836 837 if (mPhysicalDisplayIdMap.empty()) { 838 mHasMultiDisplaySupport = hasMultiDisplaySupport; 839 ALOGI("Switching to %s multi-display mode", 840 hasMultiDisplaySupport ? "generalized" : "legacy"); 841 } else if (mHasMultiDisplaySupport && !hasMultiDisplaySupport) { 842 ALOGE("Ignoring connection of display %" PRIu64 " without identification data", 843 hwcDisplayId); 844 return {}; 845 } 846 847 std::optional<DisplayIdentificationInfo> info; 848 849 if (mHasMultiDisplaySupport) { 850 info = parseDisplayIdentificationData(port, data); 851 ALOGE_IF(!info, "Failed to parse identification data for display %" PRIu64, hwcDisplayId); 852 } else if (mInternalHwcDisplayId && mExternalHwcDisplayId) { 853 ALOGE("Ignoring connection of tertiary display %" PRIu64, hwcDisplayId); 854 return {}; 855 } else { 856 ALOGW_IF(hasMultiDisplaySupport, "Ignoring identification data for display %" PRIu64, 857 hwcDisplayId); 858 port = mInternalHwcDisplayId ? HWC_DISPLAY_EXTERNAL : HWC_DISPLAY_PRIMARY; 859 } 860 861 if (!mInternalHwcDisplayId) { 862 mInternalHwcDisplayId = hwcDisplayId; 863 } else if (!mExternalHwcDisplayId) { 864 mExternalHwcDisplayId = hwcDisplayId; 865 } 866 867 if (info) return info; 868 869 return DisplayIdentificationInfo{getFallbackDisplayId(port), 870 hwcDisplayId == mInternalHwcDisplayId ? "Internal display" 871 : "External display"}; 872 } 873 874 } // namespace impl 875 } // namespace android 876