aboutsummaryrefslogtreecommitdiff
path: root/hwc2_device
diff options
context:
space:
mode:
Diffstat (limited to 'hwc2_device')
-rw-r--r--hwc2_device/DrmHwcTwo.cpp220
-rw-r--r--hwc2_device/DrmHwcTwo.h49
-rw-r--r--hwc2_device/HwcDisplay.cpp361
-rw-r--r--hwc2_device/HwcDisplay.h95
-rw-r--r--hwc2_device/HwcDisplayConfigs.cpp38
-rw-r--r--hwc2_device/HwcDisplayConfigs.h14
-rw-r--r--hwc2_device/hwc2_device.cpp14
7 files changed, 448 insertions, 343 deletions
diff --git a/hwc2_device/DrmHwcTwo.cpp b/hwc2_device/DrmHwcTwo.cpp
index a2a093f..e689419 100644
--- a/hwc2_device/DrmHwcTwo.cpp
+++ b/hwc2_device/DrmHwcTwo.cpp
@@ -18,61 +18,117 @@
#include "DrmHwcTwo.h"
+#include <cinttypes>
+
#include "backend/Backend.h"
#include "utils/log.h"
namespace android {
-DrmHwcTwo::DrmHwcTwo() = default;
+DrmHwcTwo::DrmHwcTwo() : resource_manager_(this){};
-HWC2::Error DrmHwcTwo::CreateDisplay(hwc2_display_t displ,
- HWC2::DisplayType type) {
- DrmDevice *drm = resource_manager_.GetDrmDevice(static_cast<int>(displ));
- if (!drm) {
- ALOGE("Failed to get a valid drmresource");
- return HWC2::Error::NoResources;
+/* Must be called after every display attach/detach cycle */
+void DrmHwcTwo::FinalizeDisplayBinding() {
+ if (displays_.count(kPrimaryDisplay) == 0) {
+ /* Primary display MUST always exist */
+ ALOGI("No pipelines available. Creating null-display for headless mode");
+ displays_[kPrimaryDisplay] = std::make_unique<
+ HwcDisplay>(kPrimaryDisplay, HWC2::DisplayType::Physical, this);
+ /* Initializes null-display */
+ displays_[kPrimaryDisplay]->SetPipeline(nullptr);
}
- displays_.emplace(std::piecewise_construct, std::forward_as_tuple(displ),
- std::forward_as_tuple(&resource_manager_, drm, displ, type,
- this));
- DrmCrtc *crtc = drm->GetCrtcForDisplay(static_cast<int>(displ));
- if (!crtc) {
- ALOGE("Failed to get crtc for display %d", static_cast<int>(displ));
- return HWC2::Error::BadDisplay;
+ if (displays_[kPrimaryDisplay]->IsInHeadlessMode() &&
+ !display_handles_.empty()) {
+ /* Reattach first secondary display to take place of the primary */
+ auto *pipe = display_handles_.begin()->first;
+ ALOGI("Primary display was disconnected, reattaching '%s' as new primary",
+ pipe->connector->Get()->GetName().c_str());
+ UnbindDisplay(pipe);
+ BindDisplay(pipe);
}
- auto display_planes = std::vector<DrmPlane *>();
- for (const auto &plane : drm->planes()) {
- if (plane->GetCrtcSupported(*crtc))
- display_planes.push_back(plane.get());
+
+ // Finally, send hotplug events to the client
+ for (auto &dhe : deferred_hotplug_events_) {
+ SendHotplugEventToClient(dhe.first, dhe.second);
}
- displays_.at(displ).Init(&display_planes);
- return HWC2::Error::None;
+ deferred_hotplug_events_.clear();
+
+ /* Wait 0.2s before removing the displays to flush pending HWC2 transactions
+ */
+ auto &mutex = GetResMan().GetMainLock();
+ mutex.unlock();
+ const int kTimeForSFToDisposeDisplayUs = 200000;
+ usleep(kTimeForSFToDisposeDisplayUs);
+ mutex.lock();
+ std::vector<std::unique_ptr<HwcDisplay>> for_disposal;
+ for (auto handle : displays_for_removal_list_) {
+ for_disposal.emplace_back(
+ std::unique_ptr<HwcDisplay>(displays_[handle].release()));
+ displays_.erase(handle);
+ }
+ /* Destroy HwcDisplays while unlocked to avoid vsyncworker deadlocks */
+ mutex.unlock();
+ for_disposal.clear();
+ mutex.lock();
}
-HWC2::Error DrmHwcTwo::Init() {
- int rv = resource_manager_.Init();
- if (rv) {
- ALOGE("Can't initialize the resource manager %d", rv);
- return HWC2::Error::NoResources;
+bool DrmHwcTwo::BindDisplay(DrmDisplayPipeline *pipeline) {
+ if (display_handles_.count(pipeline) != 0) {
+ ALOGE("%s, pipeline is already used by another display, FIXME!!!: %p",
+ __func__, pipeline);
+ return false;
}
- HWC2::Error ret = HWC2::Error::None;
- for (int i = 0; i < resource_manager_.GetDisplayCount(); i++) {
- ret = CreateDisplay(i, HWC2::DisplayType::Physical);
- if (ret != HWC2::Error::None) {
- ALOGE("Failed to create display %d with error %d", i, ret);
- return ret;
- }
+ uint32_t disp_handle = kPrimaryDisplay;
+
+ if (displays_.count(kPrimaryDisplay) != 0 &&
+ !displays_[kPrimaryDisplay]->IsInHeadlessMode()) {
+ disp_handle = ++last_display_handle_;
}
- resource_manager_.GetUEventListener()->RegisterHotplugHandler([this] {
- const std::lock_guard<std::mutex> lock(GetResMan().GetMainLock());
+ if (displays_.count(disp_handle) == 0) {
+ auto disp = std::make_unique<HwcDisplay>(disp_handle,
+ HWC2::DisplayType::Physical, this);
+ displays_[disp_handle] = std::move(disp);
+ }
+
+ ALOGI("Attaching pipeline '%s' to the display #%d%s",
+ pipeline->connector->Get()->GetName().c_str(), (int)disp_handle,
+ disp_handle == kPrimaryDisplay ? " (Primary)" : "");
- HandleHotplugUEvent();
- });
+ displays_[disp_handle]->SetPipeline(pipeline);
+ display_handles_[pipeline] = disp_handle;
- return ret;
+ return true;
+}
+
+bool DrmHwcTwo::UnbindDisplay(DrmDisplayPipeline *pipeline) {
+ if (display_handles_.count(pipeline) == 0) {
+ ALOGE("%s, can't find the display, pipeline: %p", __func__, pipeline);
+ return false;
+ }
+ auto handle = display_handles_[pipeline];
+ display_handles_.erase(pipeline);
+
+ ALOGI("Detaching the pipeline '%s' from the display #%i%s",
+ pipeline->connector->Get()->GetName().c_str(), (int)handle,
+ handle == kPrimaryDisplay ? " (Primary)" : "");
+
+ if (displays_.count(handle) == 0) {
+ ALOGE("%s, can't find the display, handle: %" PRIu64, __func__, handle);
+ return false;
+ }
+ displays_[handle]->SetPipeline(nullptr);
+
+ /* We must defer display disposal and removal, since it may still have pending
+ * HWC_API calls scheduled and waiting until ueventlistener thread releases
+ * main lock, otherwise transaction may fail and SF may crash
+ */
+ if (handle != kPrimaryDisplay) {
+ displays_for_removal_list_.emplace_back(handle);
+ }
+ return true;
}
HWC2::Error DrmHwcTwo::CreateVirtualDisplay(uint32_t /*width*/,
@@ -99,8 +155,8 @@ void DrmHwcTwo::Dump(uint32_t *outSize, char *outBuffer) {
output << "-- drm_hwcomposer --\n\n";
- for (std::pair<const hwc2_display_t, HwcDisplay> &dp : displays_)
- output << dp.second.Dump();
+ for (auto &disp : displays_)
+ output << disp.second->Dump();
mDumpString = output.str();
*outSize = static_cast<uint32_t>(mDumpString.size());
@@ -117,9 +173,13 @@ HWC2::Error DrmHwcTwo::RegisterCallback(int32_t descriptor,
switch (static_cast<HWC2::Callback>(descriptor)) {
case HWC2::Callback::Hotplug: {
hotplug_callback_ = std::make_pair(HWC2_PFN_HOTPLUG(function), data);
- const auto &drm_devices = resource_manager_.GetDrmDevices();
- for (const auto &device : drm_devices)
- HandleInitialHotplugState(device.get());
+ if (function != nullptr) {
+ resource_manager_.Init();
+ } else {
+ resource_manager_.DeInit();
+ /* Headless display may still be here, remove it */
+ displays_.erase(kPrimaryDisplay);
+ }
break;
}
case HWC2::Callback::Refresh: {
@@ -135,6 +195,11 @@ HWC2::Error DrmHwcTwo::RegisterCallback(int32_t descriptor,
vsync_2_4_callback_ = std::make_pair(HWC2_PFN_VSYNC_2_4(function), data);
break;
}
+ case HWC2::Callback::VsyncPeriodTimingChanged: {
+ period_timing_changed_callback_ = std::
+ make_pair(HWC2_PFN_VSYNC_PERIOD_TIMING_CHANGED(function), data);
+ break;
+ }
#endif
default:
break;
@@ -142,7 +207,8 @@ HWC2::Error DrmHwcTwo::RegisterCallback(int32_t descriptor,
return HWC2::Error::None;
}
-void DrmHwcTwo::HandleDisplayHotplug(hwc2_display_t displayid, int state) {
+void DrmHwcTwo::SendHotplugEventToClient(hwc2_display_t displayid,
+ bool connected) {
auto &mutex = GetResMan().GetMainLock();
if (mutex.try_lock()) {
ALOGE("FIXME!!!: Main mutex must be locked in %s", __func__);
@@ -157,52 +223,44 @@ void DrmHwcTwo::HandleDisplayHotplug(hwc2_display_t displayid, int state) {
*/
mutex.unlock();
hc.first(hc.second, displayid,
- state == DRM_MODE_CONNECTED ? HWC2_CONNECTION_CONNECTED
- : HWC2_CONNECTION_DISCONNECTED);
+ connected == DRM_MODE_CONNECTED ? HWC2_CONNECTION_CONNECTED
+ : HWC2_CONNECTION_DISCONNECTED);
mutex.lock();
}
}
-void DrmHwcTwo::HandleInitialHotplugState(DrmDevice *drmDevice) {
- for (const auto &conn : drmDevice->connectors()) {
- int display_id = conn->display();
- auto &display = displays_.at(display_id);
-
- if (conn->state() != DRM_MODE_CONNECTED && !display.IsInHeadlessMode())
- continue;
- HandleDisplayHotplug(conn->display(), display.IsInHeadlessMode()
- ? DRM_MODE_CONNECTED
- : conn->state());
+void DrmHwcTwo::SendVsyncEventToClient(
+ hwc2_display_t displayid, int64_t timestamp,
+ [[maybe_unused]] uint32_t vsync_period) const {
+ /* vsync callback */
+#if PLATFORM_SDK_VERSION > 29
+ if (vsync_2_4_callback_.first != nullptr &&
+ vsync_2_4_callback_.second != nullptr) {
+ vsync_2_4_callback_.first(vsync_2_4_callback_.second, displayid, timestamp,
+ vsync_period);
+ } else
+#endif
+ if (vsync_callback_.first != nullptr &&
+ vsync_callback_.second != nullptr) {
+ vsync_callback_.first(vsync_callback_.second, displayid, timestamp);
}
}
-void DrmHwcTwo::HandleHotplugUEvent() {
- for (const auto &drm : resource_manager_.GetDrmDevices()) {
- for (const auto &conn : drm->connectors()) {
- drmModeConnection old_state = conn->state();
- drmModeConnection cur_state = conn->UpdateModes()
- ? DRM_MODE_UNKNOWNCONNECTION
- : conn->state();
-
- if (cur_state == old_state)
- continue;
-
- ALOGI("%s event for connector %u on display %d",
- cur_state == DRM_MODE_CONNECTED ? "Plug" : "Unplug", conn->id(),
- conn->display());
-
- int display_id = conn->display();
- auto &display = displays_.at(display_id);
- display.ChosePreferredConfig();
- if (cur_state != DRM_MODE_CONNECTED) {
- display.ClearDisplay();
- }
-
- HandleDisplayHotplug(display_id, display.IsInHeadlessMode()
- ? DRM_MODE_CONNECTED
- : cur_state);
- }
+void DrmHwcTwo::SendVsyncPeriodTimingChangedEventToClient(
+ [[maybe_unused]] hwc2_display_t displayid,
+ [[maybe_unused]] int64_t timestamp) const {
+#if PLATFORM_SDK_VERSION > 29
+ hwc_vsync_period_change_timeline_t timeline = {
+ .newVsyncAppliedTimeNanos = timestamp,
+ .refreshRequired = false,
+ .refreshTimeNanos = 0,
+ };
+ if (period_timing_changed_callback_.first != nullptr &&
+ period_timing_changed_callback_.second != nullptr) {
+ period_timing_changed_callback_
+ .first(period_timing_changed_callback_.second, displayid, &timeline);
}
+#endif
}
} // namespace android
diff --git a/hwc2_device/DrmHwcTwo.h b/hwc2_device/DrmHwcTwo.h
index f38ba05..2b8a74f 100644
--- a/hwc2_device/DrmHwcTwo.h
+++ b/hwc2_device/DrmHwcTwo.h
@@ -24,27 +24,20 @@
namespace android {
-class DrmHwcTwo {
+class DrmHwcTwo : public PipelineToFrontendBindingInterface {
public:
DrmHwcTwo();
-
- HWC2::Error Init();
+ ~DrmHwcTwo() override = default;
std::pair<HWC2_PFN_HOTPLUG, hwc2_callback_data_t> hotplug_callback_{};
std::pair<HWC2_PFN_VSYNC, hwc2_callback_data_t> vsync_callback_{};
#if PLATFORM_SDK_VERSION > 29
std::pair<HWC2_PFN_VSYNC_2_4, hwc2_callback_data_t> vsync_2_4_callback_{};
+ std::pair<HWC2_PFN_VSYNC_PERIOD_TIMING_CHANGED, hwc2_callback_data_t>
+ period_timing_changed_callback_{};
#endif
std::pair<HWC2_PFN_REFRESH, hwc2_callback_data_t> refresh_callback_{};
- static HwcDisplay *GetDisplay(DrmHwcTwo *hwc, hwc2_display_t display_handle) {
- auto it = hwc->displays_.find(display_handle);
- if (it == hwc->displays_.end())
- return nullptr;
-
- return &it->second;
- }
-
// Device functions
HWC2::Error CreateVirtualDisplay(uint32_t width, uint32_t height,
int32_t *format, hwc2_display_t *display);
@@ -53,22 +46,44 @@ class DrmHwcTwo {
uint32_t GetMaxVirtualDisplayCount();
HWC2::Error RegisterCallback(int32_t descriptor, hwc2_callback_data_t data,
hwc2_function_pointer_t function);
- HWC2::Error CreateDisplay(hwc2_display_t displ, HWC2::DisplayType type);
+
+ auto GetDisplay(hwc2_display_t display_handle) {
+ return displays_.count(display_handle) != 0
+ ? displays_[display_handle].get()
+ : nullptr;
+ }
auto &GetResMan() {
return resource_manager_;
}
- private:
- void HandleDisplayHotplug(hwc2_display_t displayid, int state);
- void HandleInitialHotplugState(DrmDevice *drmDevice);
+ void ScheduleHotplugEvent(hwc2_display_t displayid, bool connected) {
+ deferred_hotplug_events_[displayid] = connected;
+ }
+
+ // PipelineToFrontendBindingInterface
+ bool BindDisplay(DrmDisplayPipeline *pipeline) override;
+ bool UnbindDisplay(DrmDisplayPipeline *pipeline) override;
+ void FinalizeDisplayBinding() override;
+
+ void SendVsyncEventToClient(hwc2_display_t displayid, int64_t timestamp,
+ uint32_t vsync_period) const;
+ void SendVsyncPeriodTimingChangedEventToClient(hwc2_display_t displayid,
+ int64_t timestamp) const;
- void HandleHotplugUEvent();
+ private:
+ void SendHotplugEventToClient(hwc2_display_t displayid, bool connected);
ResourceManager resource_manager_;
- std::map<hwc2_display_t, HwcDisplay> displays_;
+ std::map<hwc2_display_t, std::unique_ptr<HwcDisplay>> displays_;
+ std::map<DrmDisplayPipeline *, hwc2_display_t> display_handles_;
std::string mDumpString;
+
+ std::map<hwc2_display_t, bool> deferred_hotplug_events_;
+ std::vector<hwc2_display_t> displays_for_removal_list_;
+
+ uint32_t last_display_handle_ = kPrimaryDisplay;
};
} // namespace android
diff --git a/hwc2_device/HwcDisplay.cpp b/hwc2_device/HwcDisplay.cpp
index 8936136..cedac19 100644
--- a/hwc2_device/HwcDisplay.cpp
+++ b/hwc2_device/HwcDisplay.cpp
@@ -20,6 +20,7 @@
#include "HwcDisplay.h"
#include "DrmHwcTwo.h"
+#include "backend/Backend.h"
#include "backend/BackendManager.h"
#include "bufferinfo/BufferInfoGetter.h"
#include "utils/log.h"
@@ -68,8 +69,12 @@ std::string HwcDisplay::Dump() {
" VSync remains";
}
+ std::string connector_name = IsInHeadlessMode()
+ ? "NULL-DISPLAY"
+ : GetPipe().connector->Get()->GetName();
+
std::stringstream ss;
- ss << "- Display on: " << connector_->name() << "\n"
+ ss << "- Display on: " << connector_name << "\n"
<< " Flattening state: " << flattening_state_str << "\n"
<< "Statistics since system boot:\n"
<< DumpDelta(total_stats_) << "\n\n"
@@ -80,12 +85,9 @@ std::string HwcDisplay::Dump() {
return ss.str();
}
-HwcDisplay::HwcDisplay(ResourceManager *resource_manager, DrmDevice *drm,
- hwc2_display_t handle, HWC2::DisplayType type,
+HwcDisplay::HwcDisplay(hwc2_display_t handle, HWC2::DisplayType type,
DrmHwcTwo *hwc2)
: hwc2_(hwc2),
- resource_manager_(resource_manager),
- drm_(drm),
handle_(handle),
type_(type),
color_transform_hint_(HAL_COLOR_TRANSFORM_IDENTITY) {
@@ -97,108 +99,72 @@ HwcDisplay::HwcDisplay(ResourceManager *resource_manager, DrmDevice *drm,
// clang-format on
}
-void HwcDisplay::ClearDisplay() {
- if (IsInHeadlessMode()) {
- ALOGE("%s: Headless mode, should never reach here: ", __func__);
- return;
- }
+HwcDisplay::~HwcDisplay() = default;
- AtomicCommitArgs a_args = {.clear_active_composition = true};
- compositor_.ExecuteAtomicCommit(a_args);
-}
+void HwcDisplay::SetPipeline(DrmDisplayPipeline *pipeline) {
+ pipeline_ = pipeline;
-HWC2::Error HwcDisplay::Init(std::vector<DrmPlane *> *planes) {
- int display = static_cast<int>(handle_);
- int ret = compositor_.Init(resource_manager_, display);
- if (ret) {
- ALOGE("Failed display compositor init for display %d (%d)", display, ret);
- return HWC2::Error::NoResources;
- }
-
- // Split up the given display planes into primary and overlay to properly
- // interface with the composition
- char use_overlay_planes_prop[PROPERTY_VALUE_MAX];
- property_get("vendor.hwc.drm.use_overlay_planes", use_overlay_planes_prop,
- "1");
- bool use_overlay_planes = strtol(use_overlay_planes_prop, nullptr, 10);
- for (auto &plane : *planes) {
- if (plane->GetType() == DRM_PLANE_TYPE_PRIMARY)
- primary_planes_.push_back(plane);
- else if (use_overlay_planes && (plane)->GetType() == DRM_PLANE_TYPE_OVERLAY)
- overlay_planes_.push_back(plane);
- }
-
- crtc_ = drm_->GetCrtcForDisplay(display);
- if (!crtc_) {
- ALOGE("Failed to get crtc for display %d", display);
- return HWC2::Error::BadDisplay;
- }
+ if (pipeline != nullptr) {
+ ChosePreferredConfig();
+ Init();
- connector_ = drm_->GetConnectorForDisplay(display);
- if (!connector_) {
- ALOGE("Failed to get connector for display %d", display);
- return HWC2::Error::BadDisplay;
+ hwc2_->ScheduleHotplugEvent(handle_, /*connected = */ true);
+ } else {
+ backend_.reset();
+ vsync_worker_.Init(nullptr, [](int64_t) {});
+ SetClientTarget(nullptr, -1, 0, {});
+ if (handle_ != kPrimaryDisplay) {
+ hwc2_->ScheduleHotplugEvent(handle_, /*connected = */ false);
+ }
}
+}
- ret = vsync_worker_.Init(drm_, display, [this](int64_t timestamp) {
+HWC2::Error HwcDisplay::Init() {
+ int ret = vsync_worker_.Init(pipeline_, [this](int64_t timestamp) {
const std::lock_guard<std::mutex> lock(hwc2_->GetResMan().GetMainLock());
- /* vsync callback */
-#if PLATFORM_SDK_VERSION > 29
- if (hwc2_->vsync_2_4_callback_.first != nullptr &&
- hwc2_->vsync_2_4_callback_.second != nullptr) {
- hwc2_vsync_period_t period_ns{};
+ if (vsync_event_en_) {
+ uint32_t period_ns{};
GetDisplayVsyncPeriod(&period_ns);
- hwc2_->vsync_2_4_callback_.first(hwc2_->vsync_2_4_callback_.second,
- handle_, timestamp, period_ns);
- } else
-#endif
- if (hwc2_->vsync_callback_.first != nullptr &&
- hwc2_->vsync_callback_.second != nullptr) {
- hwc2_->vsync_callback_.first(hwc2_->vsync_callback_.second, handle_,
- timestamp);
+ 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) {
- ALOGE("Failed to create event worker for d=%d %d\n", display, ret);
+ if (ret && ret != -EALREADY) {
+ ALOGE("Failed to create event worker for d=%d %d\n", int(handle_), ret);
return HWC2::Error::BadDisplay;
}
- ret = flattening_vsync_worker_
- .Init(drm_, display, [this](int64_t /*timestamp*/) {
- const std::lock_guard<std::mutex> lock(
- hwc2_->GetResMan().GetMainLock());
- /* Frontend flattening */
- 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_);
- flattening_vsync_worker_.VSyncControl(false);
- }
- });
- if (ret) {
- ALOGE("Failed to create event worker for d=%d %d\n", display, ret);
- return HWC2::Error::BadDisplay;
- }
-
- ret = BackendManager::GetInstance().SetBackendForDisplay(this);
- if (ret) {
- ALOGE("Failed to set backend for d=%d %d\n", display, ret);
- return HWC2::Error::BadDisplay;
+ if (!IsInHeadlessMode()) {
+ ret = BackendManager::GetInstance().SetBackendForDisplay(this);
+ if (ret) {
+ ALOGE("Failed to set backend for d=%d %d\n", int(handle_), ret);
+ return HWC2::Error::BadDisplay;
+ }
}
client_layer_.SetLayerBlendMode(HWC2_BLEND_MODE_PREMULTIPLIED);
- return ChosePreferredConfig();
+ return HWC2::Error::None;
}
HWC2::Error HwcDisplay::ChosePreferredConfig() {
- HWC2::Error err = configs_.Update(*connector_);
- if (!IsInHeadlessMode() && err != HWC2::Error::None)
+ HWC2::Error err{};
+ if (!IsInHeadlessMode()) {
+ err = configs_.Update(*pipeline_->connector->Get());
+ } else {
+ configs_.FillHeadless();
+ }
+ if (!IsInHeadlessMode() && err != HWC2::Error::None) {
return HWC2::Error::BadDisplay;
+ }
return SetActiveConfig(configs_.preferred_config_id);
}
@@ -217,18 +183,19 @@ HWC2::Error HwcDisplay::CreateLayer(hwc2_layer_t *layer) {
}
HWC2::Error HwcDisplay::DestroyLayer(hwc2_layer_t layer) {
- if (!get_layer(layer))
+ if (!get_layer(layer)) {
return HWC2::Error::BadLayer;
+ }
layers_.erase(layer);
return HWC2::Error::None;
}
HWC2::Error HwcDisplay::GetActiveConfig(hwc2_config_t *config) const {
- if (configs_.hwc_configs.count(configs_.active_config_id) == 0)
+ if (configs_.hwc_configs.count(staged_mode_config_id_) == 0)
return HWC2::Error::BadConfig;
- *config = configs_.active_config_id;
+ *config = staged_mode_config_id_;
return HWC2::Error::None;
}
@@ -258,12 +225,13 @@ HWC2::Error HwcDisplay::GetChangedCompositionTypes(uint32_t *num_elements,
HWC2::Error HwcDisplay::GetClientTargetSupport(uint32_t width, uint32_t height,
int32_t /*format*/,
int32_t dataspace) {
- std::pair<uint32_t, uint32_t> min = drm_->min_resolution();
- std::pair<uint32_t, uint32_t> max = drm_->max_resolution();
if (IsInHeadlessMode()) {
return HWC2::Error::None;
}
+ std::pair<uint32_t, uint32_t> min = pipeline_->device->GetMinResolution();
+ std::pair<uint32_t, uint32_t> max = pipeline_->device->GetMaxResolution();
+
if (width < min.first || height < min.second)
return HWC2::Error::Unsupported;
@@ -293,7 +261,7 @@ HWC2::Error HwcDisplay::GetDisplayAttribute(hwc2_config_t config,
int conf = static_cast<int>(config);
if (configs_.hwc_configs.count(conf) == 0) {
- ALOGE("Could not find active mode for %d", conf);
+ ALOGE("Could not find mode #%d", conf);
return HWC2::Error::BadConfig;
}
@@ -330,7 +298,7 @@ HWC2::Error HwcDisplay::GetDisplayAttribute(hwc2_config_t config,
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 */
- *value = hwc_config.group_id;
+ *value = int(hwc_config.group_id);
break;
#endif
default:
@@ -363,7 +331,11 @@ HWC2::Error HwcDisplay::GetDisplayConfigs(uint32_t *num_configs,
HWC2::Error HwcDisplay::GetDisplayName(uint32_t *size, char *name) {
std::ostringstream stream;
- stream << "display-" << connector_->id();
+ if (IsInHeadlessMode()) {
+ stream << "null-display";
+ } else {
+ stream << "display-" << GetPipe().connector->Get()->GetId();
+ }
std::string string = stream.str();
size_t length = string.length();
if (!name) {
@@ -441,6 +413,26 @@ HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) {
return HWC2::Error::None;
}
+ int PrevModeVsyncPeriodNs = static_cast<int>(
+ 1E9 / GetPipe().connector->Get()->GetActiveMode().v_refresh());
+
+ auto mode_update_commited_ = false;
+ if (staged_mode_ &&
+ staged_mode_change_time_ <= ResourceManager::GetTimeMonotonicNs()) {
+ 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())});
+
+ configs_.active_config_id = staged_mode_config_id_;
+
+ a_args.display_mode = *staged_mode_;
+ if (!a_args.test_only) {
+ mode_update_commited_ = true;
+ }
+ }
+
// order the layers by z-order
bool use_client_layer = false;
uint32_t client_z_order = UINT32_MAX;
@@ -471,7 +463,7 @@ HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) {
for (std::pair<const uint32_t, HwcLayer *> &l : z_map) {
DrmHwcLayer layer;
l.second->PopulateDrmLayer(&layer);
- int ret = layer.ImportBuffer(drm_);
+ int ret = layer.ImportBuffer(GetPipe().device);
if (ret) {
ALOGE("Failed to import layer, ret=%d", ret);
return HWC2::Error::NoResources;
@@ -479,29 +471,21 @@ HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) {
composition_layers.emplace_back(std::move(layer));
}
- auto composition = std::make_shared<DrmDisplayComposition>(crtc_);
-
- // TODO(nobody): Don't always assume geometry changed
- int ret = composition->SetLayers(composition_layers.data(),
- composition_layers.size());
- if (ret) {
- ALOGE("Failed to set layers in the composition ret=%d", ret);
- return HWC2::Error::BadLayer;
- }
-
- std::vector<DrmPlane *> primary_planes(primary_planes_);
- std::vector<DrmPlane *> overlay_planes(overlay_planes_);
- ret = composition->Plan(&primary_planes, &overlay_planes);
- if (ret) {
- ALOGV("Failed to plan the composition ret=%d", ret);
+ /* Store plan to ensure shared planes won't be stolen by other display
+ * in between of ValidateDisplay() and PresentDisplay() calls
+ */
+ current_plan_ = DrmKmsPlan::CreateDrmKmsPlan(GetPipe(),
+ std::move(composition_layers));
+ if (!current_plan_) {
+ if (!a_args.test_only) {
+ ALOGE("Failed to create DrmKmsPlan");
+ }
return HWC2::Error::BadConfig;
}
- a_args.composition = composition;
- if (staged_mode) {
- a_args.display_mode = *staged_mode;
- }
- ret = compositor_.ExecuteAtomicCommit(a_args);
+ a_args.composition = current_plan_;
+
+ int ret = GetPipe().atomic_state_manager->ExecuteAtomicCommit(a_args);
if (ret) {
if (!a_args.test_only)
@@ -509,8 +493,13 @@ HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) {
return HWC2::Error::BadParameter;
}
- if (!a_args.test_only) {
- staged_mode.reset();
+ if (mode_update_commited_) {
+ staged_mode_.reset();
+ vsync_tracking_en_ = false;
+ if (last_vsync_ts_ != 0) {
+ hwc2_->SendVsyncPeriodTimingChangedEventToClient(
+ handle_, last_vsync_ts_ + PrevModeVsyncPeriodNs);
+ }
}
return HWC2::Error::None;
@@ -548,30 +537,24 @@ HWC2::Error HwcDisplay::PresentDisplay(int32_t *present_fence) {
return HWC2::Error::None;
}
-HWC2::Error HwcDisplay::SetActiveConfig(hwc2_config_t config) {
- int conf = static_cast<int>(config);
-
- if (configs_.hwc_configs.count(conf) == 0) {
- ALOGE("Could not find active mode for %d", conf);
+HWC2::Error HwcDisplay::SetActiveConfigInternal(uint32_t config,
+ int64_t change_time) {
+ if (configs_.hwc_configs.count(config) == 0) {
+ ALOGE("Could not find active mode for %u", config);
return HWC2::Error::BadConfig;
}
- auto &mode = configs_.hwc_configs[conf].mode;
-
- staged_mode = mode;
-
- configs_.active_config_id = conf;
-
- // Setup the client layer's dimensions
- hwc_rect_t display_frame = {.left = 0,
- .top = 0,
- .right = static_cast<int>(mode.h_display()),
- .bottom = static_cast<int>(mode.v_display())};
- client_layer_.SetLayerDisplayFrame(display_frame);
+ staged_mode_ = configs_.hwc_configs[config].mode;
+ staged_mode_change_time_ = change_time;
+ staged_mode_config_id_ = config;
return HWC2::Error::None;
}
+HWC2::Error HwcDisplay::SetActiveConfig(hwc2_config_t config) {
+ return SetActiveConfigInternal(config, ResourceManager::GetTimeMonotonicNs());
+}
+
/* Find API details at:
* https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:hardware/libhardware/include/hardware/hwcomposer2.h;l=1861
*/
@@ -656,7 +639,7 @@ HWC2::Error HwcDisplay::SetPowerMode(int32_t mode_in) {
* true, as the next composition frame will implicitly activate
* the display
*/
- return compositor_.ActivateDisplayUsingDPMS() == 0
+ return GetPipe().atomic_state_manager->ActivateDisplayUsingDPMS() == 0
? HWC2::Error::None
: HWC2::Error::BadParameter;
break;
@@ -668,7 +651,7 @@ HWC2::Error HwcDisplay::SetPowerMode(int32_t mode_in) {
return HWC2::Error::BadParameter;
};
- int err = compositor_.ExecuteAtomicCommit(a_args);
+ int err = GetPipe().atomic_state_manager->ExecuteAtomicCommit(a_args);
if (err) {
ALOGE("Failed to apply the dpms composition err=%d", err);
return HWC2::Error::BadParameter;
@@ -677,7 +660,10 @@ HWC2::Error HwcDisplay::SetPowerMode(int32_t mode_in) {
}
HWC2::Error HwcDisplay::SetVsyncEnabled(int32_t enabled) {
- vsync_worker_.VSyncControl(HWC2_VSYNC_ENABLE == enabled);
+ vsync_event_en_ = HWC2_VSYNC_ENABLE == enabled;
+ if (vsync_event_en_) {
+ vsync_worker_.VSyncControl(true);
+ }
return HWC2::Error::None;
}
@@ -706,11 +692,25 @@ std::vector<HwcLayer *> HwcDisplay::GetOrderLayersByZPos() {
return ordered_layers;
}
+HWC2::Error HwcDisplay::GetDisplayVsyncPeriod(
+ uint32_t *outVsyncPeriod /* ns */) {
+ return GetDisplayAttribute(configs_.active_config_id,
+ HWC2_ATTRIBUTE_VSYNC_PERIOD,
+ (int32_t *)(outVsyncPeriod));
+}
+
#if PLATFORM_SDK_VERSION > 29
HWC2::Error HwcDisplay::GetDisplayConnectionType(uint32_t *outType) {
- if (connector_->internal())
+ if (IsInHeadlessMode()) {
*outType = static_cast<uint32_t>(HWC2::DisplayConnectionType::Internal);
- else if (connector_->external())
+ return HWC2::Error::None;
+ }
+ /* Primary display should be always internal,
+ * otherwise SF will be unhappy and will crash
+ */
+ if (GetPipe().connector->Get()->IsInternal() || handle_ == kPrimaryDisplay)
+ *outType = static_cast<uint32_t>(HWC2::DisplayConnectionType::Internal);
+ else if (GetPipe().connector->Get()->IsExternal())
*outType = static_cast<uint32_t>(HWC2::DisplayConnectionType::External);
else
return HWC2::Error::BadConfig;
@@ -718,22 +718,38 @@ HWC2::Error HwcDisplay::GetDisplayConnectionType(uint32_t *outType) {
return HWC2::Error::None;
}
-HWC2::Error HwcDisplay::GetDisplayVsyncPeriod(
- hwc2_vsync_period_t *outVsyncPeriod /* ns */) {
- return GetDisplayAttribute(configs_.active_config_id,
- HWC2_ATTRIBUTE_VSYNC_PERIOD,
- (int32_t *)(outVsyncPeriod));
-}
-
HWC2::Error HwcDisplay::SetActiveConfigWithConstraints(
- hwc2_config_t /*config*/,
+ hwc2_config_t config,
hwc_vsync_period_change_constraints_t *vsyncPeriodChangeConstraints,
hwc_vsync_period_change_timeline_t *outTimeline) {
if (vsyncPeriodChangeConstraints == nullptr || outTimeline == nullptr) {
return HWC2::Error::BadParameter;
}
- return HWC2::Error::BadConfig;
+ uint32_t current_vsync_period{};
+ GetDisplayVsyncPeriod(&current_vsync_period);
+
+ if (vsyncPeriodChangeConstraints->seamlessRequired) {
+ return HWC2::Error::SeamlessNotAllowed;
+ }
+
+ outTimeline->refreshTimeNanos = vsyncPeriodChangeConstraints
+ ->desiredTimeNanos -
+ current_vsync_period;
+ auto ret = SetActiveConfigInternal(config, outTimeline->refreshTimeNanos);
+ if (ret != HWC2::Error::None) {
+ return ret;
+ }
+
+ outTimeline->refreshRequired = true;
+ outTimeline->newVsyncAppliedTimeNanos = vsyncPeriodChangeConstraints
+ ->desiredTimeNanos;
+
+ last_vsync_ts_ = 0;
+ vsync_tracking_en_ = true;
+ vsync_worker_.VSyncControl(true);
+
+ return HWC2::Error::None;
}
HWC2::Error HwcDisplay::SetAutoLowLatencyMode(bool /*on*/) {
@@ -765,11 +781,18 @@ HWC2::Error HwcDisplay::SetContentType(int32_t contentType) {
HWC2::Error HwcDisplay::GetDisplayIdentificationData(uint8_t *outPort,
uint32_t *outDataSize,
uint8_t *outData) {
- auto blob = connector_->GetEdidBlob();
+ if (IsInHeadlessMode()) {
+ return HWC2::Error::None;
+ }
+ auto blob = GetPipe().connector->Get()->GetEdidBlob();
+
+ *outPort = handle_ - 1;
if (!blob) {
- ALOGE("Failed to get edid property value.");
- return HWC2::Error::Unsupported;
+ if (outData == nullptr) {
+ *outDataSize = 0;
+ }
+ return HWC2::Error::None;
}
if (outData) {
@@ -778,7 +801,6 @@ HWC2::Error HwcDisplay::GetDisplayIdentificationData(uint8_t *outPort,
} else {
*outDataSize = blob->length;
}
- *outPort = connector_->id();
return HWC2::Error::None;
}
@@ -851,4 +873,37 @@ 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
diff --git a/hwc2_device/HwcDisplay.h b/hwc2_device/HwcDisplay.h
index c3e0f6e..98d8e9b 100644
--- a/hwc2_device/HwcDisplay.h
+++ b/hwc2_device/HwcDisplay.h
@@ -22,7 +22,7 @@
#include <optional>
#include "HwcDisplayConfigs.h"
-#include "compositor/DrmDisplayCompositor.h"
+#include "drm/DrmAtomicStateManager.h"
#include "drm/ResourceManager.h"
#include "drm/VSyncWorker.h"
#include "drmhwcomposer.h"
@@ -33,12 +33,16 @@ namespace android {
class Backend;
class DrmHwcTwo;
+inline constexpr uint32_t kPrimaryDisplay = 0;
+
class HwcDisplay {
public:
- HwcDisplay(ResourceManager *resource_manager, DrmDevice *drm,
- hwc2_display_t handle, HWC2::DisplayType type, DrmHwcTwo *hwc2);
+ HwcDisplay(hwc2_display_t handle, HWC2::DisplayType type, DrmHwcTwo *hwc2);
HwcDisplay(const HwcDisplay &) = delete;
- HWC2::Error Init(std::vector<DrmPlane *> *planes);
+ ~HwcDisplay();
+
+ /* SetPipeline should be carefully used only by DrmHwcTwo hotplug handlers */
+ void SetPipeline(DrmDisplayPipeline *pipeline);
HWC2::Error CreateComposition(AtomicCommitArgs &a_args);
std::vector<HwcLayer *> GetOrderLayersByZPos();
@@ -81,7 +85,6 @@ class HwcDisplay {
#endif
#if PLATFORM_SDK_VERSION > 29
HWC2::Error GetDisplayConnectionType(uint32_t *outType);
- HWC2::Error GetDisplayVsyncPeriod(hwc2_vsync_period_t *outVsyncPeriod);
HWC2::Error SetActiveConfigWithConstraints(
hwc2_config_t config,
@@ -94,6 +97,7 @@ class HwcDisplay {
HWC2::Error SetContentType(int32_t contentType);
#endif
+ HWC2::Error GetDisplayVsyncPeriod(uint32_t *outVsyncPeriod);
HWC2::Error GetDozeSupport(int32_t *support);
HWC2::Error GetHdrCapabilities(uint32_t *num_types, int32_t *types,
@@ -142,32 +146,16 @@ class HwcDisplay {
const Backend *backend() const;
void set_backend(std::unique_ptr<Backend> backend);
- const std::vector<DrmPlane *> &primary_planes() const {
- return primary_planes_;
- }
-
- const std::vector<DrmPlane *> &overlay_planes() const {
- return overlay_planes_;
+ auto GetHwc2() {
+ return hwc2_;
}
std::map<hwc2_layer_t, HwcLayer> &layers() {
return layers_;
}
- const DrmDisplayCompositor &compositor() const {
- return compositor_;
- }
-
- const DrmDevice *drm() const {
- return drm_;
- }
-
- const DrmConnector *connector() const {
- return connector_;
- }
-
- ResourceManager *resource_manager() const {
- return resource_manager_;
+ auto &GetPipe() {
+ return *pipeline_;
}
android_color_transform_t &color_transform_hint() {
@@ -179,26 +167,8 @@ class HwcDisplay {
}
/* returns true if composition should be sent to client */
- bool 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;
- }
-
- flattening_vsync_worker_.VSyncControl(true);
- flattenning_state_ = ClientFlattenningState::VsyncCountdownMax;
- return false;
- }
+ bool ProcessClientFlatteningState(bool skip);
+ void ProcessFlatenningVsyncInternal();
/* Headless mode required to keep SurfaceFlinger alive when all display are
* disconnected, Without headless mode Android will continuously crash.
@@ -207,7 +177,7 @@ class HwcDisplay {
* https://source.android.com/devices/graphics/hotplug#handling-common-scenarios
*/
bool IsInHeadlessMode() {
- return handle_ == 0 && connector_->state() != DRM_MODE_CONNECTED;
+ return !pipeline_;
}
private:
@@ -220,41 +190,48 @@ class HwcDisplay {
};
std::atomic_int flattenning_state_{ClientFlattenningState::NotRequired};
- VSyncWorker flattening_vsync_worker_;
constexpr static size_t MATRIX_SIZE = 16;
HwcDisplayConfigs configs_;
- DrmHwcTwo *hwc2_;
-
- std::optional<DrmMode> staged_mode;
+ DrmHwcTwo *const hwc2_;
- ResourceManager *resource_manager_;
- DrmDevice *drm_;
- DrmDisplayCompositor compositor_;
+ std::optional<DrmMode> staged_mode_;
+ int64_t staged_mode_change_time_{};
+ uint32_t staged_mode_config_id_{};
- std::vector<DrmPlane *> primary_planes_;
- std::vector<DrmPlane *> overlay_planes_;
+ DrmDisplayPipeline *pipeline_{};
std::unique_ptr<Backend> backend_;
VSyncWorker vsync_worker_;
- DrmConnector *connector_ = nullptr;
- DrmCrtc *crtc_ = nullptr;
- hwc2_display_t handle_;
+ bool vsync_event_en_{};
+ bool vsync_flattening_en_{};
+ bool vsync_tracking_en_{};
+ int64_t last_vsync_ts_{};
+
+ const hwc2_display_t handle_;
HWC2::DisplayType type_;
- uint32_t layer_idx_ = 0;
+
+ uint32_t layer_idx_{};
+
std::map<hwc2_layer_t, HwcLayer> layers_;
HwcLayer client_layer_;
int32_t color_mode_{};
std::array<float, MATRIX_SIZE> color_transform_matrix_{};
android_color_transform_t color_transform_hint_;
+ std::shared_ptr<DrmKmsPlan> current_plan_;
+
uint32_t frame_no_ = 0;
Stats total_stats_;
Stats prev_stats_;
std::string DumpDelta(HwcDisplay::Stats delta);
+
+ HWC2::Error Init();
+
+ HWC2::Error SetActiveConfigInternal(uint32_t config, int64_t change_time);
};
} // namespace android
diff --git a/hwc2_device/HwcDisplayConfigs.cpp b/hwc2_device/HwcDisplayConfigs.cpp
index 16f1ed0..6a3ed5a 100644
--- a/hwc2_device/HwcDisplayConfigs.cpp
+++ b/hwc2_device/HwcDisplayConfigs.cpp
@@ -31,10 +31,10 @@ constexpr uint32_t kHeadlessModeDisplayVRefresh = 60;
namespace android {
-// NOLINTNEXTLINE (readability-function-cognitive-complexity): Fixme
-HWC2::Error HwcDisplayConfigs::Update(DrmConnector &connector) {
- /* In case UpdateModes will fail we will still have one mode for headless
- * mode*/
+// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
+uint32_t HwcDisplayConfigs::last_config_id = 1;
+
+void HwcDisplayConfigs::FillHeadless() {
hwc_configs.clear();
last_config_id++;
@@ -53,7 +53,13 @@ HWC2::Error HwcDisplayConfigs::Update(DrmConnector &connector) {
mm_width = kHeadlessModeDisplayWidthMm;
mm_height = kHeadlessModeDisplayHeightMm;
+}
+// NOLINTNEXTLINE (readability-function-cognitive-complexity): Fixme
+HWC2::Error HwcDisplayConfigs::Update(DrmConnector &connector) {
+ /* In case UpdateModes will fail we will still have one mode for headless
+ * mode*/
+ FillHeadless();
/* Read real configs */
int ret = connector.UpdateModes();
if (ret != 0) {
@@ -61,25 +67,25 @@ HWC2::Error HwcDisplayConfigs::Update(DrmConnector &connector) {
return HWC2::Error::BadDisplay;
}
- if (connector.modes().empty()) {
+ if (connector.GetModes().empty()) {
ALOGE("No modes reported by KMS");
return HWC2::Error::BadDisplay;
}
hwc_configs.clear();
- mm_width = connector.mm_width();
- mm_height = connector.mm_height();
+ mm_width = connector.GetMmWidth();
+ mm_height = connector.GetMmHeight();
preferred_config_id = 0;
- int preferred_config_group_id = 0;
+ uint32_t preferred_config_group_id = 0;
- int first_config_id = last_config_id;
- int last_group_id = 1;
+ uint32_t first_config_id = last_config_id;
+ uint32_t last_group_id = 1;
/* Group modes */
- for (const auto &mode : connector.modes()) {
+ for (const auto &mode : connector.GetModes()) {
/* Find group for the new mode or create new group */
- int group_found = 0;
+ uint32_t group_found = 0;
for (auto &hwc_config : hwc_configs) {
if (mode.h_display() == hwc_config.second.mode.h_display() &&
mode.v_display() == hwc_config.second.mode.v_display()) {
@@ -122,7 +128,7 @@ HWC2::Error HwcDisplayConfigs::Update(DrmConnector &connector) {
preferred_config_group_id = 1;
}
- for (int group = 1; group < last_group_id; group++) {
+ for (uint32_t group = 1; group < last_group_id; group++) {
bool has_interlaced = false;
bool has_progressive = false;
for (auto &hwc_config : hwc_configs) {
@@ -173,8 +179,8 @@ HWC2::Error HwcDisplayConfigs::Update(DrmConnector &connector) {
* otherwise android.graphics.cts.SetFrameRateTest CTS will fail
*/
constexpr float kMinFpsDelta = 1.0; // FPS
- for (int m1 = first_config_id; m1 < last_config_id; m1++) {
- for (int m2 = first_config_id; m2 < last_config_id; m2++) {
+ for (uint32_t m1 = first_config_id; m1 < last_config_id; m1++) {
+ for (uint32_t m2 = first_config_id; m2 < last_config_id; m2++) {
if (m1 != m2 && hwc_configs[m1].group_id == hwc_configs[m2].group_id &&
!hwc_configs[m1].disabled && !hwc_configs[m2].disabled &&
fabsf(hwc_configs[m1].mode.v_refresh() -
@@ -190,8 +196,6 @@ HWC2::Error HwcDisplayConfigs::Update(DrmConnector &connector) {
}
}
- /* Set active mode to be valid mode */
- active_config_id = preferred_config_id;
return HWC2::Error::None;
}
diff --git a/hwc2_device/HwcDisplayConfigs.h b/hwc2_device/HwcDisplayConfigs.h
index 5bcf696..7c173d6 100644
--- a/hwc2_device/HwcDisplayConfigs.h
+++ b/hwc2_device/HwcDisplayConfigs.h
@@ -28,8 +28,8 @@ namespace android {
class DrmConnector;
struct HwcDisplayConfig {
- int id{};
- int group_id{};
+ uint32_t id{};
+ uint32_t group_id{};
DrmMode mode;
bool disabled{};
@@ -40,13 +40,15 @@ struct HwcDisplayConfig {
struct HwcDisplayConfigs {
HWC2::Error Update(DrmConnector &conn);
+ void FillHeadless();
- std::map<int /*config_id*/, struct HwcDisplayConfig> hwc_configs;
+ std::map<uint32_t /*config_id*/, struct HwcDisplayConfig> hwc_configs;
- int active_config_id = 0;
- int preferred_config_id = 0;
+ uint32_t active_config_id = 0;
+ uint32_t preferred_config_id = 0;
- int last_config_id = 1;
+ // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
+ static uint32_t last_config_id;
uint32_t mm_width = 0;
uint32_t mm_height = 0;
diff --git a/hwc2_device/hwc2_device.cpp b/hwc2_device/hwc2_device.cpp
index 6d258e8..a6dedb4 100644
--- a/hwc2_device/hwc2_device.cpp
+++ b/hwc2_device/hwc2_device.cpp
@@ -74,8 +74,8 @@ static int32_t DisplayHook(hwc2_device_t *dev, hwc2_display_t display_handle,
GetFuncName(__PRETTY_FUNCTION__).c_str());
DrmHwcTwo *hwc = ToDrmHwcTwo(dev);
const std::lock_guard<std::mutex> lock(hwc->GetResMan().GetMainLock());
- HwcDisplay *display = DrmHwcTwo::GetDisplay(hwc, display_handle);
- if (!display)
+ auto *display = hwc->GetDisplay(display_handle);
+ if (display == nullptr)
return static_cast<int32_t>(HWC2::Error::BadDisplay);
return static_cast<int32_t>((display->*func)(std::forward<Args>(args)...));
@@ -88,8 +88,8 @@ static int32_t LayerHook(hwc2_device_t *dev, hwc2_display_t display_handle,
layer_handle, GetFuncName(__PRETTY_FUNCTION__).c_str());
DrmHwcTwo *hwc = ToDrmHwcTwo(dev);
const std::lock_guard<std::mutex> lock(hwc->GetResMan().GetMainLock());
- HwcDisplay *display = DrmHwcTwo::GetDisplay(hwc, display_handle);
- if (!display)
+ auto *display = hwc->GetDisplay(display_handle);
+ if (display == nullptr)
return static_cast<int32_t>(HWC2::Error::BadDisplay);
HwcLayer *layer = display->get_layer(layer_handle);
@@ -390,12 +390,6 @@ static int HookDevOpen(const struct hw_module_t *module, const char *name,
ctx->getCapabilities = HookDevGetCapabilities;
ctx->getFunction = HookDevGetFunction;
- HWC2::Error err = ctx->drmhwctwo.Init();
- if (err != HWC2::Error::None) {
- ALOGE("Failed to initialize DrmHwcTwo err=%d\n", err);
- return -EINVAL;
- }
-
*dev = &ctx.release()->common;
return 0;