drm_hwcomposer: Remove HWC2 usage for Validate Add HwcDisplay::ValidateStagedComposition to be called after HwcDisplay::SetDisplayProperties to check whether any layer composition types need to be updated. Change-Id: I3a46e97b1c1721ac62de98fb89c73a1ffb0141fe Signed-off-by: Drew Davenport <ddavenport@google.com>
diff --git a/hwc2_device/HwcDisplay.cpp b/hwc2_device/HwcDisplay.cpp index 4068e71..9fbd6b9 100644 --- a/hwc2_device/HwcDisplay.cpp +++ b/hwc2_device/HwcDisplay.cpp
@@ -368,6 +368,39 @@ return ConfigError::kNone; } +auto HwcDisplay::ValidateStagedComposition() -> std::vector<ChangedLayer> { + if (IsInHeadlessMode()) { + return {}; + } + + /* In current drm_hwc design in case previous frame layer was not validated as + * a CLIENT, it is used by display controller (Front buffer). We have to store + * this state to provide the CLIENT with the release fences for such buffers. + */ + for (auto &l : layers_) { + l.second.SetPriorBufferScanOutFlag(l.second.GetValidatedType() != + HWC2::Composition::Client); + } + + // ValidateDisplay returns the number of layers that may be changed. + uint32_t num_types = 0; + uint32_t num_requests = 0; + backend_->ValidateDisplay(this, &num_types, &num_requests); + + if (num_types == 0) { + return {}; + } + + // Iterate through the layers to find which layers actually changed. + std::vector<ChangedLayer> changed_layers; + for (auto &l : layers_) { + if (l.second.IsTypeChanged()) { + changed_layers.emplace_back(l.first, l.second.GetValidatedType()); + } + } + return changed_layers; +} + void HwcDisplay::SetPipeline(std::shared_ptr<DrmDisplayPipeline> pipeline) { Deinit();
diff --git a/hwc2_device/HwcDisplay.h b/hwc2_device/HwcDisplay.h index 19b4caa..9c113fd 100644 --- a/hwc2_device/HwcDisplay.h +++ b/hwc2_device/HwcDisplay.h
@@ -89,6 +89,12 @@ // Get the HwcDisplayConfig, or nullptor if none. auto GetConfig(hwc2_config_t config_id) const -> const HwcDisplayConfig *; + // To be called after SetDisplayProperties. Returns an empty vector if the + // requested layers have been validated, otherwise the vector describes + // the requested composition type changes. + using ChangedLayer = std::pair<hwc2_layer_t, HWC2::Composition>; + auto ValidateStagedComposition() -> std::vector<ChangedLayer>; + // HWC2 Hooks - these should not be used outside of the hwc2 device. HWC2::Error AcceptDisplayChanges(); HWC2::Error CreateLayer(hwc2_layer_t *layer);
diff --git a/hwc3/ComposerClient.cpp b/hwc3/ComposerClient.cpp index 0b73e36..d084ef0 100644 --- a/hwc3/ComposerClient.cpp +++ b/hwc3/ComposerClient.cpp
@@ -456,68 +456,6 @@ return ToBinderStatus(err); } -hwc3::Error ComposerClient::ValidateDisplayInternal( - HwcDisplay& display, std::vector<int64_t>* out_changed_layers, - std::vector<Composition>* out_composition_types, - int32_t* out_display_request_mask, - std::vector<int64_t>* out_requested_layers, - std::vector<int32_t>* out_request_masks, - ClientTargetProperty* /*out_client_target_property*/, - DimmingStage* /*out_dimming_stage*/) { - DEBUG_FUNC(); - - uint32_t num_types = 0; - uint32_t num_requests = 0; - const HWC2::Error hwc2_error = display.ValidateDisplay(&num_types, - &num_requests); - - /* Check if display has pending changes and no errors */ - if (hwc2_error != HWC2::Error::None && - hwc2_error != HWC2::Error::HasChanges) { - return Hwc2toHwc3Error(hwc2_error); - } - - hwc3::Error error = Hwc2toHwc3Error( - display.GetChangedCompositionTypes(&num_types, nullptr, nullptr)); - if (error != hwc3::Error::kNone) { - return error; - } - - std::vector<hwc2_layer_t> hwc_changed_layers(num_types); - std::vector<int32_t> hwc_composition_types(num_types); - error = Hwc2toHwc3Error( - display.GetChangedCompositionTypes(&num_types, hwc_changed_layers.data(), - hwc_composition_types.data())); - if (error != hwc3::Error::kNone) { - return error; - } - - int32_t display_reqs = 0; - out_request_masks->resize(num_requests); - std::vector<hwc2_layer_t> hwc_requested_layers(num_requests); - error = Hwc2toHwc3Error( - display.GetDisplayRequests(&display_reqs, &num_requests, - hwc_requested_layers.data(), - out_request_masks->data())); - if (error != hwc3::Error::kNone) { - return error; - } - - for (const auto& layer : hwc_changed_layers) { - out_changed_layers->emplace_back(Hwc2LayerToHwc3(layer)); - } - for (const auto& type : hwc_composition_types) { - out_composition_types->emplace_back(Hwc2CompositionTypeToHwc3(type)); - } - for (const auto& layer : hwc_requested_layers) { - out_requested_layers->emplace_back(Hwc2LayerToHwc3(layer)); - } - *out_display_request_mask = display_reqs; - - /* Client target property/dimming stage unsupported */ - return hwc3::Error::kNone; -} - hwc3::Error ComposerClient::PresentDisplayInternal( uint64_t display_id, ::android::base::unique_fd& out_display_fence, std::unordered_map<int64_t, ::android::base::unique_fd>& @@ -661,6 +599,10 @@ DispatchLayerCommand(command.display, layer_cmd); } + if (cmd_result_writer_->HasError()) { + return; + } + if (command.clientTarget) { ExecuteSetDisplayClientTarget(command.display, *command.clientTarget); } @@ -675,19 +617,36 @@ display->SetColorTransformMatrix(ctm.value()); } - if (command.validateDisplay) { - ExecuteValidateDisplay(command.display, command.expectedPresentTime); + if (command.validateDisplay || command.presentOrValidateDisplay) { + std::vector<HwcDisplay::ChangedLayer> + changed_layers = display->ValidateStagedComposition(); + DisplayChanges changes{}; + for (auto [layer_id, composition_type] : changed_layers) { + changes.AddLayerCompositionChange(command.display, + Hwc2LayerToHwc3(layer_id), + static_cast<Composition>( + composition_type)); + } + cmd_result_writer_->AddChanges(changes); + composer_resources_->SetDisplayMustValidateState(display_id, false); + + // TODO: DisplayRequests are not implemented. + + /* TODO: Add check if it's possible to skip display validation for + * presentOrValidateDisplay */ + if (command.presentOrValidateDisplay) { + cmd_result_writer_ + ->AddPresentOrValidateResult(display_id, + PresentOrValidate::Result::Validated); + } } + if (command.acceptDisplayChanges) { ExecuteAcceptDisplayChanges(command.display); } if (command.presentDisplay) { ExecutePresentDisplay(command.display); } - if (command.presentOrValidateDisplay) { - ExecutePresentOrValidateDisplay(command.display, - command.expectedPresentTime); - } } ndk::ScopedAStatus ComposerClient::executeCommands( @@ -1442,68 +1401,6 @@ return; } } -void ComposerClient::ExecuteValidateDisplay( - int64_t display_id, - std::optional<ClockMonotonicTimestamp> /*expected_present_time*/ -) { - auto* display = GetDisplay(display_id); - if (display == nullptr) { - cmd_result_writer_->AddError(hwc3::Error::kBadDisplay); - return; - } - - /* TODO: Handle expectedPresentTime */ - /* This can be implemented in multiple ways. For example, the expected present - * time property can be implemented by the DRM driver directly as a CRTC - * property. See: - * https://cs.android.com/android/platform/superproject/main/+/b8b3b1646e64d0235f77b9e717a3e4082e26f2a8:hardware/google/graphics/common/libhwc2.1/libdrmresource/drm/drmcrtc.cpp;drc=468f6172546ab98983de18210222f231f16b21e1;l=88 - * Unfortunately there doesn't seem to be a standardised way of delaying - * presentation with a timestamp in the DRM API. What we can do alternatively - * is to spawn a separate presentation thread that could handle the VBlank - * events by using DRM_MODE_PAGE_FLIP_EVENT and schedule them appropriately. - */ - - std::vector<int64_t> changed_layers; - std::vector<Composition> composition_types; - int32_t display_request_mask = 0; - std::vector<int64_t> requested_layers; - std::vector<int32_t> request_masks; - - const hwc3::Error error = ValidateDisplayInternal(*display, &changed_layers, - &composition_types, - &display_request_mask, - &requested_layers, - &request_masks, nullptr, - nullptr); - - if (error != hwc3::Error::kNone) { - cmd_result_writer_->AddError(error); - } - - // If a CommandError has been been set for the current DisplayCommand, then - // no other results should be returned besides the error. - if (cmd_result_writer_->HasError()) { - return; - } - - DisplayChanges changes{}; - for (size_t i = 0; i < composition_types.size(); i++) { - changes.AddLayerCompositionChange(display_id, changed_layers[i], - composition_types[i]); - } - - std::vector<DisplayRequest::LayerRequest> layer_requests; - for (size_t i = 0; i < requested_layers.size(); i++) { - layer_requests.push_back({requested_layers[i], request_masks[i]}); - } - - const DisplayRequest request_changes{display_id, display_request_mask, - layer_requests}; - changes.display_request_changes = request_changes; - - cmd_result_writer_->AddChanges(changes); - composer_resources_->SetDisplayMustValidateState(display_id, false); -} void ComposerClient::ExecuteAcceptDisplayChanges(int64_t display_id) { auto* display = GetDisplay(display_id); @@ -1541,31 +1438,4 @@ cmd_result_writer_->AddReleaseFence(display_id, release_fences); } -void ComposerClient::ExecutePresentOrValidateDisplay( - int64_t display_id, - std::optional<ClockMonotonicTimestamp> expected_present_time) { - auto* display = GetDisplay(display_id); - if (display == nullptr) { - cmd_result_writer_->AddError(hwc3::Error::kBadDisplay); - return; - } - - /* TODO: Handle expectedPresentTime */ - /* This can be implemented in multiple ways. For example, the expected present - * time property can be implemented by the DRM driver directly as a CRTC - * property. See: - * https://cs.android.com/android/platform/superproject/main/+/b8b3b1646e64d0235f77b9e717a3e4082e26f2a8:hardware/google/graphics/common/libhwc2.1/libdrmresource/drm/drmcrtc.cpp;drc=468f6172546ab98983de18210222f231f16b21e1;l=88 - * Unfortunately there doesn't seem to be a standardised way of delaying - * presentation with a timestamp in the DRM API. What we can do alternatively - * is to spawn a separate presentation thread that could handle the VBlank - * events by using DRM_MODE_PAGE_FLIP_EVENT and schedule them appropriately. - */ - - /* TODO: Add check if it's possible to skip display validation */ - ExecuteValidateDisplay(display_id, expected_present_time); - cmd_result_writer_ - ->AddPresentOrValidateResult(display_id, - PresentOrValidate::Result::Validated); -} - } // namespace aidl::android::hardware::graphics::composer3::impl
diff --git a/hwc3/ComposerClient.h b/hwc3/ComposerClient.h index 3fe8250..9b891e7 100644 --- a/hwc3/ComposerClient.h +++ b/hwc3/ComposerClient.h
@@ -171,23 +171,8 @@ void ExecuteSetDisplayClientTarget(uint64_t display_id, const ClientTarget& command); void ExecuteSetDisplayOutputBuffer(uint64_t display_id, const Buffer& buffer); - void ExecuteValidateDisplay( - int64_t display_id, - std::optional<ClockMonotonicTimestamp> expected_present_time); void ExecuteAcceptDisplayChanges(int64_t display_id); void ExecutePresentDisplay(int64_t display_id); - void ExecutePresentOrValidateDisplay( - int64_t display_id, - std::optional<ClockMonotonicTimestamp> expected_present_time); - - static hwc3::Error ValidateDisplayInternal( - ::android::HwcDisplay& display, std::vector<int64_t>* out_changed_layers, - std::vector<Composition>* out_composition_types, - int32_t* out_display_request_mask, - std::vector<int64_t>* out_requested_layers, - std::vector<int32_t>* out_request_masks, - ClientTargetProperty* out_client_target_property, - DimmingStage* out_dimming_stage); hwc3::Error PresentDisplayInternal( uint64_t display_id, ::android::base::unique_fd& out_display_fence,