diff options
-rw-r--r-- | sdm/libs/hwc2/Android.mk | 3 | ||||
-rw-r--r-- | sdm/libs/hwc2/display_null.cpp | 68 | ||||
-rw-r--r-- | sdm/libs/hwc2/display_null.h | 107 | ||||
-rw-r--r-- | sdm/libs/hwc2/hwc_display.cpp | 1 | ||||
-rw-r--r-- | sdm/libs/hwc2/hwc_display.h | 3 | ||||
-rw-r--r-- | sdm/libs/hwc2/hwc_display_external.cpp | 64 | ||||
-rw-r--r-- | sdm/libs/hwc2/hwc_display_external.h | 6 | ||||
-rw-r--r-- | sdm/libs/hwc2/hwc_session.cpp | 164 | ||||
-rw-r--r-- | sdm/libs/hwc2/hwc_session.h | 14 |
9 files changed, 338 insertions, 92 deletions
diff --git a/sdm/libs/hwc2/Android.mk b/sdm/libs/hwc2/Android.mk index 592dc027..9f1f3c77 100644 --- a/sdm/libs/hwc2/Android.mk +++ b/sdm/libs/hwc2/Android.mk @@ -39,7 +39,8 @@ LOCAL_SRC_FILES := hwc_session.cpp \ hwc_callbacks.cpp \ ../hwc/cpuhint.cpp \ ../hwc/hwc_socket_handler.cpp \ - hwc_tonemapper.cpp + hwc_tonemapper.cpp \ + display_null.cpp ifneq ($(TARGET_USES_GRALLOC1), true) LOCAL_SRC_FILES += ../hwc/hwc_buffer_allocator.cpp diff --git a/sdm/libs/hwc2/display_null.cpp b/sdm/libs/hwc2/display_null.cpp new file mode 100644 index 00000000..16f4da66 --- /dev/null +++ b/sdm/libs/hwc2/display_null.cpp @@ -0,0 +1,68 @@ +/* +* Copyright (c) 2017, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "display_null.h" + +#define __CLASS__ "DisplayNull" + +namespace sdm { + +DisplayError DisplayNull::Commit(LayerStack *layer_stack) { + for (Layer *layer : layer_stack->layers) { + if (layer->composition != kCompositionGPUTarget) { + layer->composition = kCompositionSDE; + layer->input_buffer.release_fence_fd = -1; + } + } + layer_stack->retire_fence_fd = -1; + + return kErrorNone; +} + +DisplayError DisplayNull::GetDisplayState(DisplayState *state) { + *state = state_; + return kErrorNone; +} + +DisplayError DisplayNull::SetDisplayState(DisplayState state) { + state_ = state; + return kErrorNone; +} + +DisplayError DisplayNull::SetFrameBufferConfig(const DisplayConfigVariableInfo &variable_info) { + fb_config_ = variable_info; + return kErrorNone; +} + +DisplayError DisplayNull::GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info) { + *variable_info = fb_config_; + return kErrorNone; +} + +} // namespace sdm diff --git a/sdm/libs/hwc2/display_null.h b/sdm/libs/hwc2/display_null.h new file mode 100644 index 00000000..fa88c281 --- /dev/null +++ b/sdm/libs/hwc2/display_null.h @@ -0,0 +1,107 @@ +/* +* Copyright (c) 2017, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef __DISPLAY_NULL_H__ +#define __DISPLAY_NULL_H__ + +#include <core/display_interface.h> +#include <string> +#include <vector> + +namespace sdm { + +#define MAKE_NO_OP(virtual_method_name) \ + virtual DisplayError virtual_method_name { return kErrorNone; } + +class DisplayNull : public DisplayInterface { + public: + virtual ~DisplayNull() { } + virtual DisplayError Commit(LayerStack *layer_stack); + virtual DisplayError GetDisplayState(DisplayState *state); + virtual DisplayError SetDisplayState(DisplayState state); + virtual DisplayError SetFrameBufferConfig(const DisplayConfigVariableInfo &variable_info); + virtual DisplayError GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info); + virtual bool IsUnderscanSupported() { return true; } + virtual void SetIdleTimeoutMs(uint32_t active_ms) { } + virtual bool IsPrimaryDisplay() { return true; } + + void SetActive(bool active) { + active_ = active; + } + + bool IsActive() { + return active_; + } + + MAKE_NO_OP(Prepare(LayerStack *)) + MAKE_NO_OP(Flush()) + MAKE_NO_OP(GetNumVariableInfoConfigs(uint32_t *)) + MAKE_NO_OP(GetConfig(uint32_t, DisplayConfigVariableInfo *)) + MAKE_NO_OP(GetConfig(DisplayConfigFixedInfo *)) + MAKE_NO_OP(GetActiveConfig(uint32_t *)) + MAKE_NO_OP(GetVSyncState(bool *)) + MAKE_NO_OP(SetActiveConfig(uint32_t)) + MAKE_NO_OP(SetActiveConfig(DisplayConfigVariableInfo *)) + MAKE_NO_OP(SetMaxMixerStages(uint32_t)) + MAKE_NO_OP(ControlPartialUpdate(bool, uint32_t *)) + MAKE_NO_OP(DisablePartialUpdateOneFrame()) + MAKE_NO_OP(SetDisplayMode(uint32_t)) + MAKE_NO_OP(SetPanelBrightness(int)) + MAKE_NO_OP(CachePanelBrightness(int)) + MAKE_NO_OP(OnMinHdcpEncryptionLevelChange(uint32_t)) + MAKE_NO_OP(ColorSVCRequestRoute(const PPDisplayAPIPayload &, PPDisplayAPIPayload *, + PPPendingParams *)) + MAKE_NO_OP(GetColorModeCount(uint32_t *)) + MAKE_NO_OP(GetColorModes(uint32_t *, std::vector<std::string> *)) + MAKE_NO_OP(GetColorModeAttr(const std::string &, AttrVal *)) + MAKE_NO_OP(SetColorMode(const std::string &)) + MAKE_NO_OP(SetColorModeById(int32_t)) + MAKE_NO_OP(SetColorTransform(const uint32_t, const double *)) + MAKE_NO_OP(GetDefaultColorMode(std::string *)) + MAKE_NO_OP(ApplyDefaultDisplayMode()) + MAKE_NO_OP(SetCursorPosition(int, int)) + MAKE_NO_OP(GetRefreshRateRange(uint32_t *, uint32_t *)) + MAKE_NO_OP(SetRefreshRate(uint32_t, bool)) + MAKE_NO_OP(GetPanelBrightness(int *)) + MAKE_NO_OP(SetVSyncState(bool)) + MAKE_NO_OP(SetMixerResolution(uint32_t, uint32_t)) + MAKE_NO_OP(GetMixerResolution(uint32_t *, uint32_t *)) + MAKE_NO_OP(SetDetailEnhancerData(const DisplayDetailEnhancerData &)) + MAKE_NO_OP(GetDisplayPort(DisplayPort *)) + MAKE_NO_OP(SetCompositionState(LayerComposition, bool)) + + private: + bool active_ = false; + DisplayState state_ = kStateOff; + DisplayConfigVariableInfo fb_config_ = {}; +}; + +} // namespace sdm + +#endif // __DISPLAY_NULL_H__ diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp index 69b0acd8..f3c81f24 100644 --- a/sdm/libs/hwc2/hwc_display.cpp +++ b/sdm/libs/hwc2/hwc_display.cpp @@ -1598,6 +1598,7 @@ void HWCDisplay::MarkLayersForGPUBypass() { auto layer = hwc_layer->GetSDMLayer(); layer->composition = kCompositionSDE; } + validated_ = true; } void HWCDisplay::MarkLayersForClientComposition() { diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h index 9ee78112..b70f1608 100644 --- a/sdm/libs/hwc2/hwc_display.h +++ b/sdm/libs/hwc2/hwc_display.h @@ -159,6 +159,9 @@ class HWCDisplay : public DisplayEventHandler { return INT32(status); } + virtual int SetState(bool connected) { + return kErrorNotSupported; + } int SetPanelBrightness(int level); int GetPanelBrightness(int *level); int ToggleScreenUpdates(bool enable); diff --git a/sdm/libs/hwc2/hwc_display_external.cpp b/sdm/libs/hwc2/hwc_display_external.cpp index a8f8480f..e89451d5 100644 --- a/sdm/libs/hwc2/hwc_display_external.cpp +++ b/sdm/libs/hwc2/hwc_display_external.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved. +* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -64,6 +64,7 @@ int HWCDisplayExternal::Create(CoreInterface *core_intf, HWCBufferAllocator *buf error = hwc_display_external->GetMixerResolution(&external_width, &external_height); if (error != kErrorNone) { + Destroy(hwc_display_external); return -EINVAL; } @@ -215,4 +216,65 @@ void HWCDisplayExternal::GetDownscaleResolution(uint32_t primary_width, uint32_t } } +int HWCDisplayExternal::SetState(bool connected) { + DisplayError error = kErrorNone; + DisplayState state = kStateOff; + DisplayConfigVariableInfo fb_config = {}; + + if (connected) { + if (display_null_.IsActive()) { + error = core_intf_->CreateDisplay(type_, this, &display_intf_); + if (error != kErrorNone) { + DLOGE("Display create failed. Error = %d display_type %d event_handler %p disp_intf %p", + error, type_, this, &display_intf_); + return -EINVAL; + } + + // Restore HDMI attributes when display is reconnected. + // This is to ensure that surfaceflinger & sdm are in sync. + display_null_.GetFrameBufferConfig(&fb_config); + int status = SetFrameBufferResolution(fb_config.x_pixels, fb_config.y_pixels); + if (status) { + DLOGW("Set frame buffer config failed. Error = %d", error); + return -1; + } + + display_null_.GetDisplayState(&state); + display_intf_->SetDisplayState(state); + + SetVsyncEnabled(HWC2::Vsync::Enable); + + display_null_.SetActive(false); + DLOGI("Display is connected successfully."); + } else { + DLOGI("Display is already connected."); + } + } else { + if (!display_null_.IsActive()) { + // Preserve required attributes of HDMI display that surfaceflinger sees. + // Restore HDMI attributes when display is reconnected. + display_intf_->GetDisplayState(&state); + display_null_.SetDisplayState(state); + + error = display_intf_->GetFrameBufferConfig(&fb_config); + if (error != kErrorNone) { + DLOGW("Get frame buffer config failed. Error = %d", error); + return -1; + } + display_null_.SetFrameBufferConfig(fb_config); + + SetVsyncEnabled(HWC2::Vsync::Disable); + core_intf_->DestroyDisplay(display_intf_); + display_intf_ = &display_null_; + + display_null_.SetActive(true); + DLOGI("Display is disconnected successfully."); + } else { + DLOGI("Display is already disconnected."); + } + } + + return 0; +} + } // namespace sdm diff --git a/sdm/libs/hwc2/hwc_display_external.h b/sdm/libs/hwc2/hwc_display_external.h index 802a77c8..7aa84b2c 100644 --- a/sdm/libs/hwc2/hwc_display_external.h +++ b/sdm/libs/hwc2/hwc_display_external.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -31,6 +31,7 @@ #define __HWC_DISPLAY_EXTERNAL_H__ #include "hwc_display.h" +#include "display_null.h" namespace sdm { @@ -47,6 +48,7 @@ class HWCDisplayExternal : public HWCDisplay { virtual HWC2::Error Validate(uint32_t *out_num_types, uint32_t *out_num_requests); virtual HWC2::Error Present(int32_t *out_retire_fence); virtual void SetSecureDisplay(bool secure_display_active); + virtual int SetState(bool connected); private: HWCDisplayExternal(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator, @@ -54,6 +56,8 @@ class HWCDisplayExternal : public HWCDisplay { void ApplyScanAdjustment(hwc_rect_t *display_frame); static void GetDownscaleResolution(uint32_t primary_width, uint32_t primary_height, uint32_t *virtual_width, uint32_t *virtual_height); + + DisplayNull display_null_; }; } // namespace sdm diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp index a6739b2a..b305a9ad 100644 --- a/sdm/libs/hwc2/hwc_session.cpp +++ b/sdm/libs/hwc2/hwc_session.cpp @@ -96,9 +96,7 @@ int HWCSession::Init() { StartServices(); - buffer_allocator_ = new HWCBufferAllocator(); - - DisplayError error = CoreInterface::CreateCore(HWCDebugHandler::Get(), buffer_allocator_, + DisplayError error = CoreInterface::CreateCore(HWCDebugHandler::Get(), &buffer_allocator_, &buffer_sync_handler_, &socket_handler_, &core_intf_); if (error != kErrorNone) { @@ -106,20 +104,31 @@ int HWCSession::Init() { return -EINVAL; } - // Read which display is first, and create it and store it in primary slot - // TODO(user): This will need to be redone for HWC2 - right now we validate only - // the primary physical path - HWDisplayInterfaceInfo hw_disp_info; + // If HDMI display is primary display, defer display creation until hotplug event is received. + HWDisplayInterfaceInfo hw_disp_info = {}; error = core_intf_->GetFirstDisplayInterfaceType(&hw_disp_info); - if (error == kErrorNone && hw_disp_info.type == kHDMI && hw_disp_info.is_connected) { - // HDMI is primary display. If already connected, then create it and store in - // primary display slot. If not connected, create a NULL display for now. - status = HWCDisplayExternal::Create(core_intf_, buffer_allocator_, &callbacks_, qservice_, - &hwc_display_[HWC_DISPLAY_PRIMARY]); + if (error != kErrorNone) { + CoreInterface::DestroyCore(); + DLOGE("Primary display type not recognized. Error = %d", error); + return -EINVAL; + } + + if (hw_disp_info.type == kHDMI) { + status = 0; + hdmi_is_primary_ = true; + // Create display if it is connected, else wait for hotplug connect event. + if (hw_disp_info.is_connected) { + status = HWCDisplayExternal::Create(core_intf_, &buffer_allocator_, &callbacks_, qservice_, + &hwc_display_[HWC_DISPLAY_PRIMARY]); + } } else { // Create and power on primary display - status = HWCDisplayPrimary::Create(core_intf_, buffer_allocator_, &callbacks_, qservice_, + status = HWCDisplayPrimary::Create(core_intf_, &buffer_allocator_, &callbacks_, qservice_, &hwc_display_[HWC_DISPLAY_PRIMARY]); + color_mgr_ = HWCColorManager::CreateColorManager(&buffer_allocator_); + if (!color_mgr_) { + DLOGW("Failed to load HWCColorManager."); + } } if (status) { @@ -127,19 +136,6 @@ int HWCSession::Init() { return status; } - color_mgr_ = HWCColorManager::CreateColorManager(buffer_allocator_); - if (!color_mgr_) { - DLOGW("Failed to load HWCColorManager."); - } - - if (pthread_create(&uevent_thread_, NULL, &HWCUeventThread, this) < 0) { - DLOGE("Failed to start = %s, error = %s", uevent_thread_name_, strerror(errno)); - HWCDisplayPrimary::Destroy(hwc_display_[HWC_DISPLAY_PRIMARY]); - hwc_display_[HWC_DISPLAY_PRIMARY] = 0; - CoreInterface::DestroyCore(); - return -errno; - } - struct rlimit fd_limit = {}; getrlimit(RLIMIT_NOFILE, &fd_limit); fd_limit.rlim_cur = fd_limit.rlim_cur * 2; @@ -149,31 +145,38 @@ int HWCSession::Init() { DLOGW("Unable to increase fd limit - err:%d, %s", errno, strerror(errno)); } } + + std::thread uevent_thread(HWCUeventThread, this); + uevent_thread_.swap(uevent_thread); + return 0; } int HWCSession::Deinit() { - HWCDisplayPrimary::Destroy(hwc_display_[HWC_DISPLAY_PRIMARY]); - hwc_display_[HWC_DISPLAY_PRIMARY] = 0; + HWCDisplay *primary_display = hwc_display_[HWC_DISPLAY_PRIMARY]; + if (primary_display) { + if (hdmi_is_primary_) { + HWCDisplayExternal::Destroy(primary_display); + } else { + HWCDisplayPrimary::Destroy(primary_display); + } + } + hwc_display_[HWC_DISPLAY_PRIMARY] = nullptr; + if (color_mgr_) { color_mgr_->DestroyColorManager(); } - uevent_thread_exit_ = true; + DLOGD("Terminating uevent thread"); - // TODO(user): on restarting HWC in the same process, the uevent thread does not restart - // cleanly. - Sys::pthread_cancel_(uevent_thread_); + uevent_thread_exit_ = true; + // todo(user): add a local event to interrupt thread execution and join. + uevent_thread_.detach(); DisplayError error = CoreInterface::DestroyCore(); if (error != kErrorNone) { DLOGE("Display core de-initialization failed. Error = %d", error); } - if (buffer_allocator_ != nullptr) { - delete buffer_allocator_; - } - buffer_allocator_ = nullptr; - return 0; } @@ -436,8 +439,13 @@ int32_t HWCSession::RegisterCallback(hwc2_device_t *device, int32_t descriptor, auto desc = static_cast<HWC2::Callback>(descriptor); auto error = hwc_session->callbacks_.Register(desc, callback_data, pointer); DLOGD("Registering callback: %s", to_string(desc).c_str()); - if (descriptor == HWC2_CALLBACK_HOTPLUG) - hwc_session->callbacks_.Hotplug(HWC_DISPLAY_PRIMARY, HWC2::Connection::Connected); + if (descriptor == HWC2_CALLBACK_HOTPLUG) { + // If primary display (HDMI) is not created yet, wait for it to be hotplugged. + if (hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY]) { + hwc_session->callbacks_.Hotplug(HWC_DISPLAY_PRIMARY, HWC2::Connection::Connected); + } + } + return INT32(error); } @@ -719,7 +727,7 @@ HWC2::Error HWCSession::CreateVirtualDisplayObject(uint32_t width, uint32_t heig if (hwc_display_[HWC_DISPLAY_VIRTUAL]) { return HWC2::Error::NoResources; } - auto status = HWCDisplayVirtual::Create(core_intf_, buffer_allocator_, &callbacks_, width, + auto status = HWCDisplayVirtual::Create(core_intf_, &buffer_allocator_, &callbacks_, width, height, format, &hwc_display_[HWC_DISPLAY_VIRTUAL]); // TODO(user): validate width and height support if (status) @@ -738,7 +746,7 @@ int32_t HWCSession::ConnectDisplay(int disp) { hwc_display_[HWC_DISPLAY_PRIMARY]->GetFrameBufferResolution(&primary_width, &primary_height); if (disp == HWC_DISPLAY_EXTERNAL) { - status = HWCDisplayExternal::Create(core_intf_, buffer_allocator_, &callbacks_, primary_width, + status = HWCDisplayExternal::Create(core_intf_, &buffer_allocator_, &callbacks_, primary_width, primary_height, qservice_, false, &hwc_display_[disp]); } else { DLOGE("Invalid display type"); @@ -1341,34 +1349,35 @@ void HWCSession::ResetPanel() { int HWCSession::HotPlugHandler(bool connected) { int status = 0; bool notify_hotplug = false; - bool hdmi_primary = false; // To prevent sending events to client while a lock is held, acquire scope locks only within // below scope so that those get automatically unlocked after the scope ends. - { + do { SEQUENCE_WAIT_SCOPE_LOCK(locker_); + // If HDMI is primary but not created yet (first time), create it and notify surfaceflinger. + // if it is already created, but got disconnected/connected again, + // just toggle display status and do not notify surfaceflinger. + // If HDMI is not primary, create/destroy external display normally. + if (hdmi_is_primary_) { + if (hwc_display_[HWC_DISPLAY_PRIMARY]) { + status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetState(connected); + } else { + status = HWCDisplayExternal::Create(core_intf_, &buffer_allocator_, &callbacks_, + qservice_, &hwc_display_[HWC_DISPLAY_PRIMARY]); + notify_hotplug = true; + } + + break; + } + + // Primary display must be connected for HDMI as secondary cases. if (!hwc_display_[HWC_DISPLAY_PRIMARY]) { DLOGE("Primary display is not connected."); return -1; } - HWCDisplay *primary_display = hwc_display_[HWC_DISPLAY_PRIMARY]; - HWCDisplay *external_display = NULL; - - if (primary_display->GetDisplayClass() == DISPLAY_CLASS_EXTERNAL) { - external_display = static_cast<HWCDisplayExternal *>(hwc_display_[HWC_DISPLAY_PRIMARY]); - hdmi_primary = true; - } - - // If primary display connected is a NULL display, then replace it with the external display if (connected) { - // If we are in HDMI as primary and the primary display just got plugged in - if (hwc_display_[HWC_DISPLAY_EXTERNAL]) { - DLOGE("HDMI is already connected"); - return -1; - } - // Connect external display if virtual display is not connected. // Else, defer external display connection and process it when virtual display // tears down; Do not notify SurfaceFlinger since connection is deferred now. @@ -1386,39 +1395,28 @@ int HWCSession::HotPlugHandler(bool connected) { // Do not return error if external display is not in connected status. // Due to virtual display concurrency, external display connection might be still pending // but hdmi got disconnected before pending connection could be processed. - - if (hdmi_primary) { - assert(external_display != NULL); - uint32_t x_res, y_res; - external_display->GetFrameBufferResolution(&x_res, &y_res); - // Need to manually disable VSYNC as SF is not aware of connect/disconnect cases - // for HDMI as primary - external_display->SetVsyncEnabled(HWC2::Vsync::Disable); - HWCDisplayExternal::Destroy(external_display); - - // In HWC2, primary displays can be hotplugged out + if (hwc_display_[HWC_DISPLAY_EXTERNAL]) { + status = DisconnectDisplay(HWC_DISPLAY_EXTERNAL); notify_hotplug = true; - } else { - if (hwc_display_[HWC_DISPLAY_EXTERNAL]) { - status = DisconnectDisplay(HWC_DISPLAY_EXTERNAL); - notify_hotplug = true; - } - external_pending_connect_ = false; } + external_pending_connect_ = false; } - } + } while (0); - if (connected && notify_hotplug) { - // trigger screen refresh to ensure sufficient resources are available to process new - // new display connection. + if (connected) { callbacks_.Refresh(0); - uint32_t vsync_period = UINT32(GetVsyncPeriod(HWC_DISPLAY_PRIMARY)); - usleep(vsync_period * 2 / 1000); + + if (!hdmi_is_primary_) { + // wait for sufficient time to ensure sufficient resources are available to process new + // new display connection. + uint32_t vsync_period = UINT32(GetVsyncPeriod(HWC_DISPLAY_PRIMARY)); + usleep(vsync_period * 2 / 1000); + } } + // notify client - // Handle HDMI as primary here if (notify_hotplug) { - callbacks_.Hotplug(HWC_DISPLAY_EXTERNAL, + callbacks_.Hotplug(hdmi_is_primary_ ? HWC_DISPLAY_PRIMARY : HWC_DISPLAY_EXTERNAL, connected ? HWC2::Connection::Connected : HWC2::Connection::Disconnected); } diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h index be4494ee..cd9831d9 100644 --- a/sdm/libs/hwc2/hwc_session.h +++ b/sdm/libs/hwc2/hwc_session.h @@ -23,6 +23,7 @@ #include <vendor/display/config/1.0/IDisplayConfig.h> #include <core/core_interface.h> #include <utils/locker.h> +#include <thread> #include "hwc_callbacks.h" #include "hwc_layers.h" @@ -188,23 +189,24 @@ class HWCSession : hwc2_device_t, public IDisplayConfig, public qClient::BnQClie android::status_t SetColorModeById(const android::Parcel *input_parcel); static Locker locker_; - CoreInterface *core_intf_ = NULL; - HWCDisplay *hwc_display_[HWC_NUM_DISPLAY_TYPES] = {NULL}; + CoreInterface *core_intf_ = nullptr; + HWCDisplay *hwc_display_[HWC_NUM_DISPLAY_TYPES] = {nullptr}; HWCCallbacks callbacks_; - pthread_t uevent_thread_; + std::thread uevent_thread_; bool uevent_thread_exit_ = false; const char *uevent_thread_name_ = "HWC_UeventThread"; - HWCBufferAllocator *buffer_allocator_; + HWCBufferAllocator buffer_allocator_; HWCBufferSyncHandler buffer_sync_handler_; - HWCColorManager *color_mgr_ = NULL; + HWCColorManager *color_mgr_ = nullptr; bool reset_panel_ = false; bool secure_display_active_ = false; bool external_pending_connect_ = false; bool new_bw_mode_ = false; bool need_invalidate_ = false; int bw_mode_release_fd_ = -1; - qService::QService *qservice_ = NULL; + qService::QService *qservice_ = nullptr; HWCSocketHandler socket_handler_; + bool hdmi_is_primary_ = false; }; } // namespace sdm |