diff options
Diffstat (limited to 'hwc2_device/HwcDisplay.cpp')
-rw-r--r-- | hwc2_device/HwcDisplay.cpp | 313 |
1 files changed, 177 insertions, 136 deletions
diff --git a/hwc2_device/HwcDisplay.cpp b/hwc2_device/HwcDisplay.cpp index d968ab3..efd8c14 100644 --- a/hwc2_device/HwcDisplay.cpp +++ b/hwc2_device/HwcDisplay.cpp @@ -31,7 +31,7 @@ namespace android { std::string HwcDisplay::DumpDelta(HwcDisplay::Stats delta) { if (delta.total_pixops_ == 0) return "No stats yet"; - double ratio = 1.0 - double(delta.gpu_pixops_) / double(delta.total_pixops_); + auto ratio = 1.0 - double(delta.gpu_pixops_) / double(delta.total_pixops_); std::stringstream ss; ss << " Total frames count: " << delta.total_frames_ << "\n" @@ -50,32 +50,12 @@ std::string HwcDisplay::DumpDelta(HwcDisplay::Stats delta) { } std::string HwcDisplay::Dump() { - std::string flattening_state_str; - switch (flattenning_state_) { - case ClientFlattenningState::Disabled: - flattening_state_str = "Disabled"; - break; - case ClientFlattenningState::NotRequired: - flattening_state_str = "Not needed"; - break; - case ClientFlattenningState::Flattened: - flattening_state_str = "Active"; - break; - case ClientFlattenningState::ClientRefreshRequested: - flattening_state_str = "Refresh requested"; - break; - default: - flattening_state_str = std::to_string(flattenning_state_) + - " VSync remains"; - } - - std::string connector_name = IsInHeadlessMode() - ? "NULL-DISPLAY" - : GetPipe().connector->Get()->GetName(); + auto connector_name = IsInHeadlessMode() + ? std::string("NULL-DISPLAY") + : GetPipe().connector->Get()->GetName(); std::stringstream ss; ss << "- Display on: " << connector_name << "\n" - << " Flattening state: " << flattening_state_str << "\n" << "Statistics since system boot:\n" << DumpDelta(total_stats_) << "\n\n" << "Statistics since last dumpsys request:\n" @@ -87,17 +67,18 @@ std::string HwcDisplay::Dump() { HwcDisplay::HwcDisplay(hwc2_display_t handle, HWC2::DisplayType type, DrmHwcTwo *hwc2) - : hwc2_(hwc2), - handle_(handle), - type_(type), - client_layer_(this), - color_transform_hint_(HAL_COLOR_TRANSFORM_IDENTITY) { - // clang-format off - color_transform_matrix_ = {1.0, 0.0, 0.0, 0.0, - 0.0, 1.0, 0.0, 0.0, - 0.0, 0.0, 1.0, 0.0, - 0.0, 0.0, 0.0, 1.0}; - // clang-format on + : hwc2_(hwc2), handle_(handle), type_(type), client_layer_(this){}; + +void HwcDisplay::SetColorMarixToIdentity() { + color_matrix_ = std::make_shared<drm_color_ctm>(); + for (int i = 0; i < kCtmCols; i++) { + for (int j = 0; j < kCtmRows; j++) { + constexpr uint64_t kOne = (1ULL << 32); /* 1.0 in s31.32 format */ + color_matrix_->matrix[i * kCtmRows + j] = (i == j) ? kOne : 0; + } + } + + color_transform_hint_ = HAL_COLOR_TRANSFORM_IDENTITY; } HwcDisplay::~HwcDisplay() = default; @@ -137,9 +118,17 @@ void HwcDisplay::Deinit() { GetPipe().atomic_state_manager->ExecuteAtomicCommit(a_args); #endif - vsync_worker_.Init(nullptr, [](int64_t) {}); current_plan_.reset(); backend_.reset(); + if (flatcon_) { + flatcon_->StopThread(); + flatcon_.reset(); + } + } + + if (vsync_worker_) { + vsync_worker_->StopThread(); + vsync_worker_ = {}; } SetClientTarget(nullptr, -1, 0, {}); @@ -148,38 +137,54 @@ void HwcDisplay::Deinit() { HWC2::Error HwcDisplay::Init() { ChosePreferredConfig(); - int ret = vsync_worker_.Init(pipeline_, [this](int64_t timestamp) { - const std::lock_guard<std::mutex> lock(hwc2_->GetResMan().GetMainLock()); - if (vsync_event_en_) { - uint32_t period_ns{}; - GetDisplayVsyncPeriod(&period_ns); - hwc2_->SendVsyncEventToClient(handle_, timestamp, period_ns); - } - if (vsync_flattening_en_) { - ProcessFlatenningVsyncInternal(); - } - if (vsync_tracking_en_) { - last_vsync_ts_ = timestamp; - } - if (!vsync_event_en_ && !vsync_flattening_en_ && !vsync_tracking_en_) { - vsync_worker_.VSyncControl(false); - } - }); - if (ret && ret != -EALREADY) { - ALOGE("Failed to create event worker for d=%d %d\n", int(handle_), ret); + auto vsw_callbacks = (VSyncWorkerCallbacks){ + .out_event = + [this](int64_t timestamp) { + const std::unique_lock lock(hwc2_->GetResMan().GetMainLock()); + if (vsync_event_en_) { + uint32_t period_ns{}; + GetDisplayVsyncPeriod(&period_ns); + hwc2_->SendVsyncEventToClient(handle_, timestamp, period_ns); + } + if (vsync_tracking_en_) { + last_vsync_ts_ = timestamp; + } + if (!vsync_event_en_ && !vsync_tracking_en_) { + vsync_worker_->VSyncControl(false); + } + }, + .get_vperiod_ns = [this]() -> uint32_t { + uint32_t outVsyncPeriod = 0; + GetDisplayVsyncPeriod(&outVsyncPeriod); + return outVsyncPeriod; + }, + }; + + vsync_worker_ = VSyncWorker::CreateInstance(pipeline_, vsw_callbacks); + if (!vsync_worker_) { + ALOGE("Failed to create event worker for d=%d\n", int(handle_)); return HWC2::Error::BadDisplay; } if (!IsInHeadlessMode()) { - ret = BackendManager::GetInstance().SetBackendForDisplay(this); + auto ret = BackendManager::GetInstance().SetBackendForDisplay(this); if (ret) { ALOGE("Failed to set backend for d=%d %d\n", int(handle_), ret); return HWC2::Error::BadDisplay; } + auto flatcbk = (struct FlatConCallbacks){.trigger = [this]() { + if (hwc2_->refresh_callback_.first != nullptr && + hwc2_->refresh_callback_.second != nullptr) + hwc2_->refresh_callback_.first(hwc2_->refresh_callback_.second, + handle_); + }}; + flatcon_ = FlatteningController::CreateInstance(flatcbk); } client_layer_.SetLayerBlendMode(HWC2_BLEND_MODE_PREMULTIPLIED); + SetColorMarixToIdentity(); + return HWC2::Error::None; } @@ -236,7 +241,7 @@ HWC2::Error HwcDisplay::GetChangedCompositionTypes(uint32_t *num_elements, } uint32_t num_changes = 0; - for (std::pair<const hwc2_layer_t, HwcLayer> &l : layers_) { + for (auto &l : layers_) { if (l.second.IsTypeChanged()) { if (layers && num_changes < *num_elements) layers[num_changes] = l.first; @@ -257,8 +262,8 @@ HWC2::Error HwcDisplay::GetClientTargetSupport(uint32_t width, uint32_t height, return HWC2::Error::None; } - std::pair<uint32_t, uint32_t> min = pipeline_->device->GetMinResolution(); - std::pair<uint32_t, uint32_t> max = pipeline_->device->GetMaxResolution(); + auto min = pipeline_->device->GetMinResolution(); + auto max = pipeline_->device->GetMaxResolution(); if (width < min.first || height < min.second) return HWC2::Error::Unsupported; @@ -296,33 +301,33 @@ HWC2::Error HwcDisplay::GetDisplayAttribute(hwc2_config_t config, auto &hwc_config = configs_.hwc_configs[conf]; static const int32_t kUmPerInch = 25400; - uint32_t mm_width = configs_.mm_width; - uint32_t mm_height = configs_.mm_height; + auto mm_width = configs_.mm_width; + auto mm_height = configs_.mm_height; auto attribute = static_cast<HWC2::Attribute>(attribute_in); switch (attribute) { case HWC2::Attribute::Width: - *value = static_cast<int>(hwc_config.mode.h_display()); + *value = static_cast<int>(hwc_config.mode.GetRawMode().hdisplay); break; case HWC2::Attribute::Height: - *value = static_cast<int>(hwc_config.mode.v_display()); + *value = static_cast<int>(hwc_config.mode.GetRawMode().vdisplay); break; case HWC2::Attribute::VsyncPeriod: // in nanoseconds - *value = static_cast<int>(1E9 / hwc_config.mode.v_refresh()); + *value = static_cast<int>(1E9 / hwc_config.mode.GetVRefresh()); break; case HWC2::Attribute::DpiX: // Dots per 1000 inches - *value = mm_width ? static_cast<int>(hwc_config.mode.h_display() * - kUmPerInch / mm_width) + *value = mm_width ? int(hwc_config.mode.GetRawMode().hdisplay * + kUmPerInch / mm_width) : -1; break; case HWC2::Attribute::DpiY: // Dots per 1000 inches - *value = mm_height ? static_cast<int>(hwc_config.mode.v_display() * - kUmPerInch / mm_height) + *value = mm_height ? int(hwc_config.mode.GetRawMode().vdisplay * + kUmPerInch / mm_height) : -1; break; -#if PLATFORM_SDK_VERSION > 29 +#if __ANDROID_API__ > 29 case HWC2::Attribute::ConfigGroup: /* Dispite ConfigGroup is a part of HWC2.4 API, framework * able to request it even if service @2.1 is used */ @@ -364,8 +369,8 @@ HWC2::Error HwcDisplay::GetDisplayName(uint32_t *size, char *name) { } else { stream << "display-" << GetPipe().connector->Get()->GetId(); } - std::string string = stream.str(); - size_t length = string.length(); + auto string = stream.str(); + auto length = string.length(); if (!name) { *size = length; return HWC2::Error::None; @@ -437,7 +442,7 @@ HWC2::Error HwcDisplay::GetReleaseFences(uint32_t *num_elements, } layers[num_layers - 1] = l.first; - fences[num_layers - 1] = UniqueFd::Dup(present_fence_.Get()).Release(); + fences[num_layers - 1] = DupFd(present_fence_); } *num_elements = num_layers; @@ -450,8 +455,10 @@ HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) { return HWC2::Error::None; } - int PrevModeVsyncPeriodNs = static_cast<int>( - 1E9 / GetPipe().connector->Get()->GetActiveMode().v_refresh()); + a_args.color_matrix = color_matrix_; + + uint32_t prev_vperiod_ns = 0; + GetDisplayVsyncPeriod(&prev_vperiod_ns); auto mode_update_commited_ = false; if (staged_mode_ && @@ -459,8 +466,8 @@ HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) { client_layer_.SetLayerDisplayFrame( (hwc_rect_t){.left = 0, .top = 0, - .right = static_cast<int>(staged_mode_->h_display()), - .bottom = static_cast<int>(staged_mode_->v_display())}); + .right = int(staged_mode_->GetRawMode().hdisplay), + .bottom = int(staged_mode_->GetRawMode().vdisplay)}); configs_.active_config_id = staged_mode_config_id_; @@ -477,7 +484,7 @@ HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) { for (std::pair<const hwc2_layer_t, HwcLayer> &l : layers_) { switch (l.second.GetValidatedType()) { case HWC2::Composition::Device: - z_map.emplace(std::make_pair(l.second.GetZOrder(), &l.second)); + z_map.emplace(l.second.GetZOrder(), &l.second); break; case HWC2::Composition::Client: // Place it at the z_order of the lowest client layer @@ -489,7 +496,7 @@ HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) { } } if (use_client_layer) - z_map.emplace(std::make_pair(client_z_order, &client_layer_)); + z_map.emplace(client_z_order, &client_layer_); if (z_map.empty()) return HWC2::Error::BadLayer; @@ -498,7 +505,7 @@ HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) { /* Import & populate */ for (std::pair<const uint32_t, HwcLayer *> &l : z_map) { - l.second->PopulateLayerData(a_args.test_only); + l.second->PopulateLayerData(); } // now that they're ordered by z, add them to the composition @@ -513,7 +520,7 @@ HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) { */ return HWC2::Error::BadLayer; } - composition_layers.emplace_back(l.second->GetLayerData().Clone()); + composition_layers.emplace_back(l.second->GetLayerData()); } /* Store plan to ensure shared planes won't be stolen by other display @@ -530,7 +537,7 @@ HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) { a_args.composition = current_plan_; - int ret = GetPipe().atomic_state_manager->ExecuteAtomicCommit(a_args); + auto ret = GetPipe().atomic_state_manager->ExecuteAtomicCommit(a_args); if (ret) { if (!a_args.test_only) @@ -542,8 +549,9 @@ HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) { staged_mode_.reset(); vsync_tracking_en_ = false; if (last_vsync_ts_ != 0) { - hwc2_->SendVsyncPeriodTimingChangedEventToClient( - handle_, last_vsync_ts_ + PrevModeVsyncPeriodNs); + hwc2_->SendVsyncPeriodTimingChangedEventToClient(handle_, + last_vsync_ts_ + + prev_vperiod_ns); } } @@ -576,8 +584,11 @@ HWC2::Error HwcDisplay::PresentDisplay(int32_t *out_present_fence) { if (ret != HWC2::Error::None) return ret; - this->present_fence_ = UniqueFd::Dup(a_args.out_fence.Get()); - *out_present_fence = a_args.out_fence.Release(); + this->present_fence_ = a_args.out_fence; + *out_present_fence = DupFd(a_args.out_fence); + + // Reset the color matrix so we don't apply it over and over again. + color_matrix_ = {}; ++frame_no_; return HWC2::Error::None; @@ -625,17 +636,22 @@ HWC2::Error HwcDisplay::SetClientTarget(buffer_handle_t target, return HWC2::Error::None; } - client_layer_.PopulateLayerData(/*test = */ true); + client_layer_.PopulateLayerData(); if (!client_layer_.IsLayerUsableAsDevice()) { ALOGE("Client layer must be always usable by DRM/KMS"); return HWC2::Error::BadLayer; } auto &bi = client_layer_.GetLayerData().bi; - hwc_frect_t source_crop = {.left = 0.0F, - .top = 0.0F, - .right = static_cast<float>(bi->width), - .bottom = static_cast<float>(bi->height)}; + if (!bi) { + ALOGE("%s: Invalid state", __func__); + return HWC2::Error::BadLayer; + } + + auto source_crop = (hwc_frect_t){.left = 0.0F, + .top = 0.0F, + .right = static_cast<float>(bi->width), + .bottom = static_cast<float>(bi->height)}; client_layer_.SetLayerSourceCrop(source_crop); return HWC2::Error::None; @@ -652,6 +668,8 @@ HWC2::Error HwcDisplay::SetColorMode(int32_t mode) { return HWC2::Error::None; } +#include <xf86drmMode.h> + HWC2::Error HwcDisplay::SetColorTransform(const float *matrix, int32_t hint) { if (hint < HAL_COLOR_TRANSFORM_IDENTITY || hint > HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA) @@ -661,12 +679,49 @@ HWC2::Error HwcDisplay::SetColorTransform(const float *matrix, int32_t hint) { return HWC2::Error::BadParameter; color_transform_hint_ = static_cast<android_color_transform_t>(hint); - if (color_transform_hint_ == HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX) - std::copy(matrix, matrix + MATRIX_SIZE, color_transform_matrix_.begin()); + + if (IsInHeadlessMode()) + return HWC2::Error::None; + + if (!GetPipe().crtc->Get()->GetCtmProperty()) + return HWC2::Error::None; + + switch (color_transform_hint_) { + case HAL_COLOR_TRANSFORM_IDENTITY: + SetColorMarixToIdentity(); + break; + case HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX: + color_matrix_ = std::make_shared<drm_color_ctm>(); + /* DRM expects a 3x3 matrix, but the HAL provides a 4x4 matrix. */ + for (int i = 0; i < kCtmCols; i++) { + for (int j = 0; j < kCtmRows; j++) { + constexpr int kInCtmRows = 4; + /* HAL matrix type is float, but DRM expects a s31.32 fix point */ + auto value = uint64_t(matrix[i * kInCtmRows + j] * float(1ULL << 32)); + color_matrix_->matrix[i * kCtmRows + j] = value; + } + } + break; + default: + return HWC2::Error::Unsupported; + } return HWC2::Error::None; } +bool HwcDisplay::CtmByGpu() { + if (color_transform_hint_ == HAL_COLOR_TRANSFORM_IDENTITY) + return false; + + if (GetPipe().crtc->Get()->GetCtmProperty()) + return false; + + if (GetHwc2()->GetResMan().GetCtmHandling() == CtmHandling::kDrmOrIgnore) + return false; + + return true; +} + HWC2::Error HwcDisplay::SetOutputBuffer(buffer_handle_t /*buffer*/, int32_t /*release_fence*/) { // TODO(nobody): Need virtual display support @@ -697,7 +752,7 @@ HWC2::Error HwcDisplay::SetPowerMode(int32_t mode_in) { return HWC2::Error::None; } - if (a_args.active) { + if (a_args.active && *a_args.active) { /* * Setting the display to active before we have a composition * can break some drivers, so skip setting a_args.active to @@ -709,7 +764,7 @@ HWC2::Error HwcDisplay::SetPowerMode(int32_t mode_in) { : HWC2::Error::BadParameter; }; - int err = GetPipe().atomic_state_manager->ExecuteAtomicCommit(a_args); + auto err = GetPipe().atomic_state_manager->ExecuteAtomicCommit(a_args); if (err) { ALOGE("Failed to apply the dpms composition err=%d", err); return HWC2::Error::BadParameter; @@ -720,7 +775,7 @@ HWC2::Error HwcDisplay::SetPowerMode(int32_t mode_in) { HWC2::Error HwcDisplay::SetVsyncEnabled(int32_t enabled) { vsync_event_en_ = HWC2_VSYNC_ENABLE == enabled; if (vsync_event_en_) { - vsync_worker_.VSyncControl(true); + vsync_worker_->VSyncControl(true); } return HWC2::Error::None; } @@ -767,7 +822,7 @@ HWC2::Error HwcDisplay::GetDisplayVsyncPeriod( (int32_t *)(outVsyncPeriod)); } -#if PLATFORM_SDK_VERSION > 29 +#if __ANDROID_API__ > 29 HWC2::Error HwcDisplay::GetDisplayConnectionType(uint32_t *outType) { if (IsInHeadlessMode()) { *outType = static_cast<uint32_t>(HWC2::DisplayConnectionType::Internal); @@ -815,7 +870,7 @@ HWC2::Error HwcDisplay::SetActiveConfigWithConstraints( last_vsync_ts_ = 0; vsync_tracking_en_ = true; - vsync_worker_.VSyncControl(true); + vsync_worker_->VSyncControl(true); return HWC2::Error::None; } @@ -845,7 +900,7 @@ HWC2::Error HwcDisplay::SetContentType(int32_t contentType) { } #endif -#if PLATFORM_SDK_VERSION > 28 +#if __ANDROID_API__ > 28 HWC2::Error HwcDisplay::GetDisplayIdentificationData(uint8_t *outPort, uint32_t *outDataSize, uint8_t *outData) { @@ -871,12 +926,31 @@ HWC2::Error HwcDisplay::GetDisplayIdentificationData(uint8_t *outPort, } HWC2::Error HwcDisplay::GetDisplayCapabilities(uint32_t *outNumCapabilities, - uint32_t * /*outCapabilities*/) { + uint32_t *outCapabilities) { if (outNumCapabilities == nullptr) { return HWC2::Error::BadParameter; } - *outNumCapabilities = 0; + bool skip_ctm = false; + + // Skip client CTM if user requested DRM_OR_IGNORE + if (GetHwc2()->GetResMan().GetCtmHandling() == CtmHandling::kDrmOrIgnore) + skip_ctm = true; + + // Skip client CTM if DRM can handle it + if (!skip_ctm && !IsInHeadlessMode() && + GetPipe().crtc->Get()->GetCtmProperty()) + skip_ctm = true; + + if (!skip_ctm) { + *outNumCapabilities = 0; + return HWC2::Error::None; + } + + *outNumCapabilities = 1; + if (outCapabilities) { + outCapabilities[0] = HWC2_DISPLAY_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM; + } return HWC2::Error::None; } @@ -890,9 +964,9 @@ HWC2::Error HwcDisplay::SetDisplayBrightness(float /* brightness */) { return HWC2::Error::Unsupported; } -#endif /* PLATFORM_SDK_VERSION > 28 */ +#endif /* __ANDROID_API__ > 28 */ -#if PLATFORM_SDK_VERSION > 27 +#if __ANDROID_API__ > 27 HWC2::Error HwcDisplay::GetRenderIntents( int32_t mode, uint32_t *outNumIntents, @@ -928,7 +1002,7 @@ HWC2::Error HwcDisplay::SetColorModeWithIntent(int32_t mode, int32_t intent) { return HWC2::Error::None; } -#endif /* PLATFORM_SDK_VERSION > 27 */ +#endif /* __ANDROID_API__ > 27 */ const Backend *HwcDisplay::backend() const { return backend_.get(); @@ -938,37 +1012,4 @@ void HwcDisplay::set_backend(std::unique_ptr<Backend> backend) { backend_ = std::move(backend); } -/* returns true if composition should be sent to client */ -bool HwcDisplay::ProcessClientFlatteningState(bool skip) { - int flattenning_state = flattenning_state_; - if (flattenning_state == ClientFlattenningState::Disabled) { - return false; - } - - if (skip) { - flattenning_state_ = ClientFlattenningState::NotRequired; - return false; - } - - if (flattenning_state == ClientFlattenningState::ClientRefreshRequested) { - flattenning_state_ = ClientFlattenningState::Flattened; - return true; - } - - vsync_flattening_en_ = true; - vsync_worker_.VSyncControl(true); - flattenning_state_ = ClientFlattenningState::VsyncCountdownMax; - return false; -} - -void HwcDisplay::ProcessFlatenningVsyncInternal() { - if (flattenning_state_ > ClientFlattenningState::ClientRefreshRequested && - --flattenning_state_ == ClientFlattenningState::ClientRefreshRequested && - hwc2_->refresh_callback_.first != nullptr && - hwc2_->refresh_callback_.second != nullptr) { - hwc2_->refresh_callback_.first(hwc2_->refresh_callback_.second, handle_); - vsync_flattening_en_ = false; - } -} - } // namespace android |