hwc2: Add support for multiple displays
- Add support for an additional display which can be either a builtin
display or pluggable display.
- Restructure HWCDisplayPrimary as HWCBuiltIn and HWCDisplayExternal
as HWCDisplayPluggable.
- Refactor hotplug handling. Iterate through all pluggable displays,
and check present connection status. Connect/disconnect a given
display if connection status has changed.
CRs-Fixed: 2200594
Change-Id: Ibd2f93ddfbe72af58220691ad481469c8fdcbf86
diff --git a/sdm/libs/hwc2/Android.mk b/sdm/libs/hwc2/Android.mk
index d9ffa0b..a8f259b 100644
--- a/sdm/libs/hwc2/Android.mk
+++ b/sdm/libs/hwc2/Android.mk
@@ -30,12 +30,16 @@
ifeq ($(display_config_version), DISPLAY_CONFIG_1_1)
LOCAL_SHARED_LIBRARIES += vendor.display.config@1.1
endif
+ifeq ($(display_config_version), DISPLAY_CONFIG_1_2)
+LOCAL_SHARED_LIBRARIES += vendor.display.config@1.2 vendor.display.config@1.1
+endif
LOCAL_SRC_FILES := hwc_session.cpp \
hwc_session_services.cpp \
hwc_display.cpp \
- hwc_display_primary.cpp \
- hwc_display_external.cpp \
+ hwc_display_builtin.cpp \
+ hwc_display_pluggable.cpp \
+ hwc_display_pluggable_test.cpp \
hwc_display_virtual.cpp \
hwc_debugger.cpp \
hwc_buffer_sync_handler.cpp \
@@ -46,8 +50,7 @@
hwc_tonemapper.cpp \
display_null.cpp \
hwc_socket_handler.cpp \
- hwc_buffer_allocator.cpp \
- hwc_display_external_test.cpp
+ hwc_buffer_allocator.cpp
include $(BUILD_SHARED_LIBRARY)
endif
diff --git a/sdm/libs/hwc2/hwc_color_manager.cpp b/sdm/libs/hwc2/hwc_color_manager.cpp
index 1b4e15a..31c876f 100644
--- a/sdm/libs/hwc2/hwc_color_manager.cpp
+++ b/sdm/libs/hwc2/hwc_color_manager.cpp
@@ -199,14 +199,14 @@
FLOAT(solid_fill_params_.rect.y) + FLOAT(solid_fill_params_.rect.height),
};
- hwc_display->Perform(HWCDisplayPrimary::SET_QDCM_SOLID_FILL_INFO, &solid_fill_color);
- hwc_display->Perform(HWCDisplayPrimary::SET_QDCM_SOLID_FILL_RECT, &solid_fill_rect);
+ hwc_display->Perform(HWCDisplayBuiltIn::SET_QDCM_SOLID_FILL_INFO, &solid_fill_color);
+ hwc_display->Perform(HWCDisplayBuiltIn::SET_QDCM_SOLID_FILL_RECT, &solid_fill_rect);
} else {
solid_fill_color.red = 0;
solid_fill_color.blue = 0;
solid_fill_color.green = 0;
solid_fill_color.alpha = 0;
- hwc_display->Perform(HWCDisplayPrimary::UNSET_QDCM_SOLID_FILL_INFO, &solid_fill_color);
+ hwc_display->Perform(HWCDisplayBuiltIn::UNSET_QDCM_SOLID_FILL_INFO, &solid_fill_color);
}
return 0;
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index ef65057..002d7f9 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -315,15 +315,16 @@
*os << std::endl;
}
-HWCDisplay::HWCDisplay(CoreInterface *core_intf, HWCCallbacks *callbacks,
- HWCDisplayEventHandler* event_handler, DisplayType type, hwc2_display_t id,
- bool needs_blit, qService::QService *qservice, DisplayClass display_class,
- BufferAllocator *buffer_allocator)
+HWCDisplay::HWCDisplay(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
+ HWCCallbacks *callbacks, HWCDisplayEventHandler* event_handler,
+ qService::QService *qservice, DisplayType type, hwc2_display_t id,
+ int32_t sdm_id, bool needs_blit, DisplayClass display_class)
: core_intf_(core_intf),
callbacks_(callbacks),
event_handler_(event_handler),
type_(type),
id_(id),
+ sdm_id_(sdm_id),
needs_blit_(needs_blit),
qservice_(qservice),
display_class_(display_class) {
@@ -342,10 +343,10 @@
display_intf_ = disp_null;
DLOGI("Enabling null display mode for display type %d", type_);
} else {
- error = core_intf_->CreateDisplay(type_, this, &display_intf_);
+ error = core_intf_->CreateDisplay(sdm_id_, 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_);
+ DLOGE("Display create failed. Error = %d display_id = %d event_handler = %p disp_intf = %p",
+ error, sdm_id_, this, &display_intf_);
return -EINVAL;
}
}
@@ -855,14 +856,14 @@
}
std::string name;
- switch (id_) {
- case HWC_DISPLAY_PRIMARY:
- name = "Primary Display";
+ switch (type_) {
+ case kBuiltIn:
+ name = "Built-in Display";
break;
- case HWC_DISPLAY_EXTERNAL:
- name = "External Display";
+ case kPluggable:
+ name = "Pluggable Display";
break;
- case HWC_DISPLAY_VIRTUAL:
+ case kVirtual:
name = "Virtual Display";
break;
default:
@@ -886,16 +887,13 @@
}
HWC2::Error HWCDisplay::GetDisplayType(int32_t *out_type) {
- if (out_type != nullptr) {
- if (id_ == HWC_DISPLAY_VIRTUAL) {
- *out_type = HWC2_DISPLAY_TYPE_VIRTUAL;
- } else {
- *out_type = HWC2_DISPLAY_TYPE_PHYSICAL;
- }
- return HWC2::Error::None;
- } else {
+ if (out_type == nullptr) {
return HWC2::Error::BadParameter;
}
+
+ *out_type = HWC2_DISPLAY_TYPE_PHYSICAL;
+
+ return HWC2::Error::None;
}
HWC2::Error HWCDisplay::GetPerFrameMetadataKeys(uint32_t *out_num_keys,
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index b4bb554..9c09ab0 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -53,8 +53,8 @@
// Subclasses set this to their type. This has to be different from DisplayType.
// This is to avoid RTTI and dynamic_cast
enum DisplayClass {
- DISPLAY_CLASS_PRIMARY,
- DISPLAY_CLASS_EXTERNAL,
+ DISPLAY_CLASS_BUILTIN,
+ DISPLAY_CLASS_PLUGGABLE,
DISPLAY_CLASS_VIRTUAL,
DISPLAY_CLASS_NULL
};
@@ -272,10 +272,9 @@
// Maximum number of layers supported by display manager.
static const uint32_t kMaxLayerCount = 32;
- HWCDisplay(CoreInterface *core_intf, HWCCallbacks *callbacks,
- HWCDisplayEventHandler *event_handler, DisplayType type, hwc2_display_t id,
- bool needs_blit, qService::QService *qservice, DisplayClass display_class,
- BufferAllocator *buffer_allocator);
+ HWCDisplay(CoreInterface *core_intf, BufferAllocator *buffer_allocator, HWCCallbacks *callbacks,
+ HWCDisplayEventHandler *event_handler, qService::QService *qservice, DisplayType type,
+ hwc2_display_t id, int32_t sdm_id, bool needs_blit, DisplayClass display_class);
// DisplayEventHandler methods
virtual DisplayError VSync(const DisplayEventVSync &vsync);
@@ -307,11 +306,12 @@
bool validated_ = false;
bool layer_stack_invalid_ = true;
CoreInterface *core_intf_ = nullptr;
+ HWCBufferAllocator *buffer_allocator_ = NULL;
HWCCallbacks *callbacks_ = nullptr;
HWCDisplayEventHandler *event_handler_ = nullptr;
- HWCBufferAllocator *buffer_allocator_ = NULL;
- DisplayType type_;
- hwc2_display_t id_;
+ DisplayType type_ = kDisplayTypeMax;
+ hwc2_display_t id_ = UINT64_MAX;
+ int32_t sdm_id_ = -1;
bool needs_blit_ = false;
DisplayInterface *display_intf_ = NULL;
LayerStack layer_stack_;
diff --git a/sdm/libs/hwc2/hwc_display_primary.cpp b/sdm/libs/hwc2/hwc_display_builtin.cpp
similarity index 84%
rename from sdm/libs/hwc2/hwc_display_primary.cpp
rename to sdm/libs/hwc2/hwc_display_builtin.cpp
index e285c04..f841dbc 100644
--- a/sdm/libs/hwc2/hwc_display_primary.cpp
+++ b/sdm/libs/hwc2/hwc_display_builtin.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014 - 2018, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014-2018, 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
@@ -39,62 +39,66 @@
#include <string>
#include <vector>
-#include "hwc_display_primary.h"
+#include "hwc_display_builtin.h"
#include "hwc_debugger.h"
-#define __CLASS__ "HWCDisplayPrimary"
+#define __CLASS__ "HWCDisplayBuiltIn"
namespace sdm {
-int HWCDisplayPrimary::Create(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
+int HWCDisplayBuiltIn::Create(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
- qService::QService *qservice, HWCDisplay **hwc_display) {
+ qService::QService *qservice, hwc2_display_t id, int32_t sdm_id,
+ HWCDisplay **hwc_display) {
int status = 0;
- uint32_t primary_width = 0;
- uint32_t primary_height = 0;
+ uint32_t builtin_width = 0;
+ uint32_t builtin_height = 0;
- HWCDisplay *hwc_display_primary =
- new HWCDisplayPrimary(core_intf, buffer_allocator, callbacks, event_handler, qservice);
- status = hwc_display_primary->Init();
+ HWCDisplay *hwc_display_builtin =
+ new HWCDisplayBuiltIn(core_intf, buffer_allocator, callbacks, event_handler, qservice, id,
+ sdm_id);
+ status = hwc_display_builtin->Init();
if (status) {
- delete hwc_display_primary;
+ delete hwc_display_builtin;
return status;
}
- hwc_display_primary->GetMixerResolution(&primary_width, &primary_height);
+ hwc_display_builtin->GetMixerResolution(&builtin_width, &builtin_height);
int width = 0, height = 0;
HWCDebugHandler::Get()->GetProperty(FB_WIDTH_PROP, &width);
HWCDebugHandler::Get()->GetProperty(FB_HEIGHT_PROP, &height);
if (width > 0 && height > 0) {
- primary_width = UINT32(width);
- primary_height = UINT32(height);
+ builtin_width = UINT32(width);
+ builtin_height = UINT32(height);
}
- status = hwc_display_primary->SetFrameBufferResolution(primary_width, primary_height);
+ status = hwc_display_builtin->SetFrameBufferResolution(builtin_width, builtin_height);
if (status) {
- Destroy(hwc_display_primary);
+ Destroy(hwc_display_builtin);
return status;
}
- *hwc_display = hwc_display_primary;
+ *hwc_display = hwc_display_builtin;
return status;
}
-void HWCDisplayPrimary::Destroy(HWCDisplay *hwc_display) {
+void HWCDisplayBuiltIn::Destroy(HWCDisplay *hwc_display) {
hwc_display->Deinit();
delete hwc_display;
}
-HWCDisplayPrimary::HWCDisplayPrimary(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
+HWCDisplayBuiltIn::HWCDisplayBuiltIn(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
- qService::QService *qservice)
- : HWCDisplay(core_intf, callbacks, event_handler, kPrimary, HWC_DISPLAY_PRIMARY, true,
- qservice, DISPLAY_CLASS_PRIMARY, buffer_allocator),
- buffer_allocator_(buffer_allocator), cpu_hint_(NULL) {
+ qService::QService *qservice, hwc2_display_t id,
+ int32_t sdm_id)
+ : HWCDisplay(core_intf, buffer_allocator, callbacks, event_handler, qservice, kBuiltIn, id,
+ sdm_id, true, DISPLAY_CLASS_BUILTIN),
+ buffer_allocator_(buffer_allocator),
+ cpu_hint_(NULL) {
}
-int HWCDisplayPrimary::Init() {
+int HWCDisplayBuiltIn::Init() {
cpu_hint_ = new CPUHint();
if (cpu_hint_->Init(static_cast<HWCDebugHandler *>(HWCDebugHandler::Get())) != kErrorNone) {
delete cpu_hint_;
@@ -120,7 +124,7 @@
return status;
}
-void HWCDisplayPrimary::ProcessBootAnimCompleted() {
+void HWCDisplayBuiltIn::ProcessBootAnimCompleted() {
uint32_t numBootUpLayers = 0;
// TODO(user): Remove this hack
@@ -161,7 +165,7 @@
}
}
-HWC2::Error HWCDisplayPrimary::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
+HWC2::Error HWCDisplayBuiltIn::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
auto status = HWC2::Error::None;
DisplayError error = kErrorNone;
@@ -229,7 +233,7 @@
return status;
}
-HWC2::Error HWCDisplayPrimary::Present(int32_t *out_retire_fence) {
+HWC2::Error HWCDisplayBuiltIn::Present(int32_t *out_retire_fence) {
auto status = HWC2::Error::None;
if (display_paused_) {
DisplayError error = display_intf_->Flush();
@@ -250,7 +254,7 @@
return status;
}
-HWC2::Error HWCDisplayPrimary::GetColorModes(uint32_t *out_num_modes, ColorMode *out_modes) {
+HWC2::Error HWCDisplayBuiltIn::GetColorModes(uint32_t *out_num_modes, ColorMode *out_modes) {
if (out_modes == nullptr) {
*out_num_modes = color_mode_->GetColorModeCount();
} else {
@@ -260,7 +264,7 @@
return HWC2::Error::None;
}
-HWC2::Error HWCDisplayPrimary::GetRenderIntents(ColorMode mode, uint32_t *out_num_intents,
+HWC2::Error HWCDisplayBuiltIn::GetRenderIntents(ColorMode mode, uint32_t *out_num_intents,
RenderIntent *out_intents) {
if (out_intents == nullptr) {
*out_num_intents = color_mode_->GetRenderIntentCount(mode);
@@ -270,11 +274,11 @@
return HWC2::Error::None;
}
-HWC2::Error HWCDisplayPrimary::SetColorMode(ColorMode mode) {
+HWC2::Error HWCDisplayBuiltIn::SetColorMode(ColorMode mode) {
return SetColorModeWithRenderIntent(mode, RenderIntent::COLORIMETRIC);
}
-HWC2::Error HWCDisplayPrimary::SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent) {
+HWC2::Error HWCDisplayBuiltIn::SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent) {
auto status = color_mode_->SetColorModeWithRenderIntent(mode, intent);
if (status != HWC2::Error::None) {
DLOGE("failed for mode = %d intent = %d", mode, intent);
@@ -285,7 +289,7 @@
return status;
}
-HWC2::Error HWCDisplayPrimary::SetColorModeById(int32_t color_mode_id) {
+HWC2::Error HWCDisplayBuiltIn::SetColorModeById(int32_t color_mode_id) {
auto status = color_mode_->SetColorModeById(color_mode_id);
if (status != HWC2::Error::None) {
DLOGE("failed for mode = %d", color_mode_id);
@@ -298,7 +302,7 @@
return status;
}
-HWC2::Error HWCDisplayPrimary::RestoreColorTransform() {
+HWC2::Error HWCDisplayBuiltIn::RestoreColorTransform() {
auto status = color_mode_->RestoreColorTransform();
if (status != HWC2::Error::None) {
DLOGE("failed to RestoreColorTransform");
@@ -310,7 +314,7 @@
return status;
}
-HWC2::Error HWCDisplayPrimary::SetColorTransform(const float *matrix,
+HWC2::Error HWCDisplayBuiltIn::SetColorTransform(const float *matrix,
android_color_transform_t hint) {
if (!matrix) {
return HWC2::Error::BadParameter;
@@ -330,7 +334,7 @@
return status;
}
-HWC2::Error HWCDisplayPrimary::SetReadbackBuffer(const native_handle_t *buffer,
+HWC2::Error HWCDisplayBuiltIn::SetReadbackBuffer(const native_handle_t *buffer,
int32_t acquire_fence,
bool post_processed_output) {
const private_handle_t *handle = reinterpret_cast<const private_handle_t *>(buffer);
@@ -358,7 +362,7 @@
return HWC2::Error::None;
}
-HWC2::Error HWCDisplayPrimary::GetReadbackBufferFence(int32_t *release_fence) {
+HWC2::Error HWCDisplayBuiltIn::GetReadbackBufferFence(int32_t *release_fence) {
auto status = HWC2::Error::None;
if (readback_configured_ && (output_buffer_.release_fence_fd >= 0)) {
@@ -376,7 +380,7 @@
return status;
}
-int HWCDisplayPrimary::Perform(uint32_t operation, ...) {
+int HWCDisplayBuiltIn::Perform(uint32_t operation, ...) {
va_list args;
va_start(args, operation);
int val = 0;
@@ -419,7 +423,7 @@
return 0;
}
-DisplayError HWCDisplayPrimary::SetDisplayMode(uint32_t mode) {
+DisplayError HWCDisplayBuiltIn::SetDisplayMode(uint32_t mode) {
DisplayError error = kErrorNone;
if (display_intf_) {
@@ -429,7 +433,7 @@
return error;
}
-void HWCDisplayPrimary::SetMetaDataRefreshRateFlag(bool enable) {
+void HWCDisplayBuiltIn::SetMetaDataRefreshRateFlag(bool enable) {
int disable_metadata_dynfps = 0;
HWCDebugHandler::Get()->GetProperty(DISABLE_METADATA_DYNAMIC_FPS_PROP, &disable_metadata_dynfps);
@@ -439,12 +443,12 @@
use_metadata_refresh_rate_ = enable;
}
-void HWCDisplayPrimary::SetQDCMSolidFillInfo(bool enable, const LayerSolidFill &color) {
+void HWCDisplayBuiltIn::SetQDCMSolidFillInfo(bool enable, const LayerSolidFill &color) {
solid_fill_enable_ = enable;
solid_fill_color_ = color;
}
-void HWCDisplayPrimary::ToggleCPUHint(bool set) {
+void HWCDisplayBuiltIn::ToggleCPUHint(bool set) {
if (!cpu_hint_) {
return;
}
@@ -456,7 +460,7 @@
}
}
-int HWCDisplayPrimary::HandleSecureSession(const std::bitset<kSecureMax> &secure_sessions,
+int HWCDisplayBuiltIn::HandleSecureSession(const std::bitset<kSecureMax> &secure_sessions,
bool *power_on_pending) {
if (!power_on_pending) {
return -EINVAL;
@@ -480,7 +484,7 @@
return 0;
}
-void HWCDisplayPrimary::ForceRefreshRate(uint32_t refresh_rate) {
+void HWCDisplayBuiltIn::ForceRefreshRate(uint32_t refresh_rate) {
if ((refresh_rate && (refresh_rate < min_refresh_rate_ || refresh_rate > max_refresh_rate_)) ||
force_refresh_rate_ == refresh_rate) {
// Cannot honor force refresh rate, as its beyond the range or new request is same
@@ -494,7 +498,7 @@
return;
}
-uint32_t HWCDisplayPrimary::GetOptimalRefreshRate(bool one_updating_layer) {
+uint32_t HWCDisplayBuiltIn::GetOptimalRefreshRate(bool one_updating_layer) {
if (force_refresh_rate_) {
return force_refresh_rate_;
} else if (use_metadata_refresh_rate_ && one_updating_layer && metadata_refresh_rate_) {
@@ -504,7 +508,7 @@
return max_refresh_rate_;
}
-DisplayError HWCDisplayPrimary::Refresh() {
+DisplayError HWCDisplayBuiltIn::Refresh() {
DisplayError error = kErrorNone;
callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
@@ -512,12 +516,12 @@
return error;
}
-void HWCDisplayPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
+void HWCDisplayBuiltIn::SetIdleTimeoutMs(uint32_t timeout_ms) {
display_intf_->SetIdleTimeoutMs(timeout_ms);
validated_ = false;
}
-void HWCDisplayPrimary::HandleFrameOutput() {
+void HWCDisplayBuiltIn::HandleFrameOutput() {
if (readback_buffer_queued_) {
validated_ = false;
}
@@ -527,7 +531,7 @@
}
}
-void HWCDisplayPrimary::HandleFrameDump() {
+void HWCDisplayBuiltIn::HandleFrameDump() {
if (!readback_configured_) {
dump_frame_count_ = 0;
}
@@ -565,7 +569,7 @@
}
}
-HWC2::Error HWCDisplayPrimary::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
+HWC2::Error HWCDisplayBuiltIn::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
HWCDisplay::SetFrameDumpConfig(count, bit_mask_layer_type);
dump_output_to_file_ = bit_mask_layer_type & (1 << OUTPUT_LAYER_DUMP);
DLOGI("output_layer_dump_enable %d", dump_output_to_file_);
@@ -604,7 +608,7 @@
return HWC2::Error::None;
}
-int HWCDisplayPrimary::FrameCaptureAsync(const BufferInfo &output_buffer_info,
+int HWCDisplayBuiltIn::FrameCaptureAsync(const BufferInfo &output_buffer_info,
bool post_processed_output) {
// Note: This function is called in context of a binder thread and a lock is already held
if (output_buffer_info.alloc_buffer_info.fd < 0) {
@@ -636,11 +640,11 @@
return 0;
}
-bool HWCDisplayPrimary::GetFrameCaptureFence(int32_t *release_fence) {
+bool HWCDisplayBuiltIn::GetFrameCaptureFence(int32_t *release_fence) {
return (GetReadbackBufferFence(release_fence) == HWC2::Error::None);
}
-DisplayError HWCDisplayPrimary::SetDetailEnhancerConfig
+DisplayError HWCDisplayBuiltIn::SetDetailEnhancerConfig
(const DisplayDetailEnhancerData &de_data) {
DisplayError error = kErrorNotSupported;
@@ -651,7 +655,7 @@
return error;
}
-DisplayError HWCDisplayPrimary::ControlPartialUpdate(bool enable, uint32_t *pending) {
+DisplayError HWCDisplayBuiltIn::ControlPartialUpdate(bool enable, uint32_t *pending) {
DisplayError error = kErrorNone;
if (display_intf_) {
@@ -662,7 +666,7 @@
return error;
}
-DisplayError HWCDisplayPrimary::DisablePartialUpdateOneFrame() {
+DisplayError HWCDisplayBuiltIn::DisablePartialUpdateOneFrame() {
DisplayError error = kErrorNone;
if (display_intf_) {
@@ -674,17 +678,17 @@
}
-DisplayError HWCDisplayPrimary::SetMixerResolution(uint32_t width, uint32_t height) {
+DisplayError HWCDisplayBuiltIn::SetMixerResolution(uint32_t width, uint32_t height) {
DisplayError error = display_intf_->SetMixerResolution(width, height);
validated_ = false;
return error;
}
-DisplayError HWCDisplayPrimary::GetMixerResolution(uint32_t *width, uint32_t *height) {
+DisplayError HWCDisplayBuiltIn::GetMixerResolution(uint32_t *width, uint32_t *height) {
return display_intf_->GetMixerResolution(width, height);
}
-HWC2::Error HWCDisplayPrimary::SetQSyncMode(QSyncMode qsync_mode) {
+HWC2::Error HWCDisplayBuiltIn::SetQSyncMode(QSyncMode qsync_mode) {
auto err = display_intf_->SetQSyncMode(qsync_mode);
if (err != kErrorNone) {
return HWC2::Error::Unsupported;
diff --git a/sdm/libs/hwc2/hwc_display_primary.h b/sdm/libs/hwc2/hwc_display_builtin.h
similarity index 89%
rename from sdm/libs/hwc2/hwc_display_primary.h
rename to sdm/libs/hwc2/hwc_display_builtin.h
index 8957855..7cda451 100644
--- a/sdm/libs/hwc2/hwc_display_primary.h
+++ b/sdm/libs/hwc2/hwc_display_builtin.h
@@ -27,8 +27,8 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __HWC_DISPLAY_PRIMARY_H__
-#define __HWC_DISPLAY_PRIMARY_H__
+#ifndef __HWC_DISPLAY_BUILTIN_H__
+#define __HWC_DISPLAY_BUILTIN_H__
#include <string>
@@ -37,7 +37,7 @@
namespace sdm {
-class HWCDisplayPrimary : public HWCDisplay {
+class HWCDisplayBuiltIn : public HWCDisplay {
public:
enum {
SET_METADATA_DYN_REFRESH_RATE,
@@ -49,8 +49,9 @@
};
static int Create(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
- HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
- qService::QService *qservice, HWCDisplay **hwc_display);
+ HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
+ qService::QService *qservice, hwc2_display_t id, int32_t sdm_id,
+ HWCDisplay **hwc_display);
static void Destroy(HWCDisplay *hwc_display);
virtual int Init();
virtual HWC2::Error Validate(uint32_t *out_num_types, uint32_t *out_num_requests);
@@ -79,9 +80,9 @@
virtual HWC2::Error SetQSyncMode(QSyncMode qsync_mode);
private:
- HWCDisplayPrimary(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
+ HWCDisplayBuiltIn(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
- qService::QService *qservice);
+ qService::QService *qservice, hwc2_display_t id, int32_t sdm_id);
void SetMetaDataRefreshRateFlag(bool enable);
virtual DisplayError SetDisplayMode(uint32_t mode);
virtual DisplayError DisablePartialUpdateOneFrame();
@@ -98,7 +99,7 @@
BufferAllocator *buffer_allocator_ = nullptr;
CPUHint *cpu_hint_ = nullptr;
- // Primary readback buffer configuration
+ // Builtin readback buffer configuration
LayerBuffer output_buffer_ = {};
bool post_processed_output_ = false;
bool readback_buffer_queued_ = false;
@@ -113,4 +114,4 @@
} // namespace sdm
-#endif // __HWC_DISPLAY_PRIMARY_H__
+#endif // __HWC_DISPLAY_BUILTIN_H__
diff --git a/sdm/libs/hwc2/hwc_display_external.cpp b/sdm/libs/hwc2/hwc_display_pluggable.cpp
similarity index 74%
rename from sdm/libs/hwc2/hwc_display_external.cpp
rename to sdm/libs/hwc2/hwc_display_pluggable.cpp
index ad18868..7d22642 100644
--- a/sdm/libs/hwc2/hwc_display_external.cpp
+++ b/sdm/libs/hwc2/hwc_display_pluggable.cpp
@@ -32,70 +32,63 @@
#include <utils/debug.h>
#include <algorithm>
-#include "hwc_display_external.h"
+#include "hwc_display_pluggable.h"
#include "hwc_debugger.h"
-#define __CLASS__ "HWCDisplayExternal"
+#define __CLASS__ "HWCDisplayPluggable"
namespace sdm {
-int HWCDisplayExternal::Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+int HWCDisplayPluggable::Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
- qService::QService *qservice, HWCDisplay **hwc_display) {
- return Create(core_intf, buffer_allocator, callbacks, event_handler, 0, 0, qservice, false,
- hwc_display);
-}
-
-int HWCDisplayExternal::Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
- HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
+ qService::QService *qservice, hwc2_display_t id, int32_t sdm_id,
uint32_t primary_width, uint32_t primary_height,
- qService::QService *qservice, bool use_primary_res,
- HWCDisplay **hwc_display) {
- uint32_t external_width = 0;
- uint32_t external_height = 0;
+ bool use_primary_res, HWCDisplay **hwc_display) {
+ uint32_t pluggable_width = 0;
+ uint32_t pluggable_height = 0;
DisplayError error = kErrorNone;
- HWCDisplay *hwc_display_external = new HWCDisplayExternal(core_intf, buffer_allocator, callbacks,
- event_handler, qservice);
- int status = hwc_display_external->Init();
+ HWCDisplay *hwc_display_pluggable = new HWCDisplayPluggable(core_intf, buffer_allocator,
+ callbacks, event_handler, qservice, id, sdm_id);
+ int status = hwc_display_pluggable->Init();
if (status) {
- delete hwc_display_external;
+ delete hwc_display_pluggable;
return status;
}
- error = hwc_display_external->GetMixerResolution(&external_width, &external_height);
+ error = hwc_display_pluggable->GetMixerResolution(&pluggable_width, &pluggable_height);
if (error != kErrorNone) {
- Destroy(hwc_display_external);
+ Destroy(hwc_display_pluggable);
return -EINVAL;
}
if (primary_width && primary_height) {
- // use_primary_res means HWCDisplayExternal should directly set framebuffer resolution to the
+ // use_primary_res means HWCDisplayPluggable should directly set framebuffer resolution to the
// provided primary_width and primary_height
if (use_primary_res) {
- external_width = primary_width;
- external_height = primary_height;
+ pluggable_width = primary_width;
+ pluggable_height = primary_height;
} else {
int downscale_enabled = 0;
HWCDebugHandler::Get()->GetProperty(ENABLE_EXTERNAL_DOWNSCALE_PROP, &downscale_enabled);
if (downscale_enabled) {
- GetDownscaleResolution(primary_width, primary_height, &external_width, &external_height);
+ GetDownscaleResolution(primary_width, primary_height, &pluggable_width, &pluggable_height);
}
}
}
- status = hwc_display_external->SetFrameBufferResolution(external_width, external_height);
+ status = hwc_display_pluggable->SetFrameBufferResolution(pluggable_width, pluggable_height);
if (status) {
- Destroy(hwc_display_external);
+ Destroy(hwc_display_pluggable);
return status;
}
- *hwc_display = hwc_display_external;
+ *hwc_display = hwc_display_pluggable;
return status;
}
-int HWCDisplayExternal::Init() {
+int HWCDisplayPluggable::Init() {
int status = HWCDisplay::Init();
if (status) {
return status;
@@ -106,21 +99,25 @@
return status;
}
-void HWCDisplayExternal::Destroy(HWCDisplay *hwc_display) {
+void HWCDisplayPluggable::Destroy(HWCDisplay *hwc_display) {
+ // Flush the display to have outstanding fences signaled.
+ hwc_display->Flush();
hwc_display->Deinit();
delete hwc_display;
}
-HWCDisplayExternal::HWCDisplayExternal(CoreInterface *core_intf,
- HWCBufferAllocator *buffer_allocator,
- HWCCallbacks *callbacks,
- HWCDisplayEventHandler *event_handler,
- qService::QService *qservice)
- : HWCDisplay(core_intf, callbacks, event_handler, kHDMI, HWC_DISPLAY_EXTERNAL, false,
- qservice, DISPLAY_CLASS_EXTERNAL, buffer_allocator) {
+HWCDisplayPluggable::HWCDisplayPluggable(CoreInterface *core_intf,
+ HWCBufferAllocator *buffer_allocator,
+ HWCCallbacks *callbacks,
+ HWCDisplayEventHandler *event_handler,
+ qService::QService *qservice,
+ hwc2_display_t id,
+ int32_t sdm_id)
+ : HWCDisplay(core_intf, buffer_allocator, callbacks, event_handler, qservice, kPluggable, id,
+ sdm_id, false, DISPLAY_CLASS_PLUGGABLE) {
}
-HWC2::Error HWCDisplayExternal::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
+HWC2::Error HWCDisplayPluggable::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
auto status = HWC2::Error::None;
if (active_secure_sessions_[kSecureDisplay]) {
@@ -149,7 +146,7 @@
return status;
}
-HWC2::Error HWCDisplayExternal::Present(int32_t *out_retire_fence) {
+HWC2::Error HWCDisplayPluggable::Present(int32_t *out_retire_fence) {
auto status = HWC2::Error::None;
if (!active_secure_sessions_[kSecureDisplay]) {
@@ -161,7 +158,7 @@
return status;
}
-void HWCDisplayExternal::ApplyScanAdjustment(hwc_rect_t *display_frame) {
+void HWCDisplayPluggable::ApplyScanAdjustment(hwc_rect_t *display_frame) {
if ((underscan_width_ <= 0) || (underscan_height_ <= 0)) {
return;
}
@@ -200,7 +197,7 @@
*src_width = dst_width;
}
-void HWCDisplayExternal::GetDownscaleResolution(uint32_t primary_width, uint32_t primary_height,
+void HWCDisplayPluggable::GetDownscaleResolution(uint32_t primary_width, uint32_t primary_height,
uint32_t *non_primary_width,
uint32_t *non_primary_height) {
uint32_t primary_area = primary_width * primary_height;
@@ -214,7 +211,7 @@
}
}
-int HWCDisplayExternal::SetState(bool connected) {
+int HWCDisplayPluggable::SetState(bool connected) {
DisplayError error = kErrorNone;
DisplayState state = kStateOff;
DisplayConfigVariableInfo fb_config = {};
@@ -283,7 +280,7 @@
return 0;
}
-void HWCDisplayExternal::GetUnderScanConfig() {
+void HWCDisplayPluggable::GetUnderScanConfig() {
if (!display_intf_->IsUnderscanSupported()) {
// Read user defined underscan width and height
HWCDebugHandler::Get()->GetProperty(EXTERNAL_ACTION_SAFE_WIDTH_PROP, &underscan_width_);
@@ -291,11 +288,11 @@
}
}
-DisplayError HWCDisplayExternal::Flush() {
+DisplayError HWCDisplayPluggable::Flush() {
return display_intf_->Flush();
}
-HWC2::Error HWCDisplayExternal::GetColorModes(uint32_t *out_num_modes, ColorMode *out_modes) {
+HWC2::Error HWCDisplayPluggable::GetColorModes(uint32_t *out_num_modes, ColorMode *out_modes) {
if (out_modes == nullptr) {
*out_num_modes = color_mode_->GetColorModeCount();
} else {
@@ -304,7 +301,7 @@
return HWC2::Error::None;
}
-HWC2::Error HWCDisplayExternal::GetRenderIntents(ColorMode mode, uint32_t *out_num_intents,
+HWC2::Error HWCDisplayPluggable::GetRenderIntents(ColorMode mode, uint32_t *out_num_intents,
RenderIntent *out_intents) {
if (out_intents == nullptr) {
*out_num_intents = color_mode_->GetRenderIntentCount(mode);
@@ -314,11 +311,11 @@
return HWC2::Error::None;
}
-HWC2::Error HWCDisplayExternal::SetColorMode(ColorMode mode) {
+HWC2::Error HWCDisplayPluggable::SetColorMode(ColorMode mode) {
return SetColorModeWithRenderIntent(mode, RenderIntent::COLORIMETRIC);
}
-HWC2::Error HWCDisplayExternal::SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent) {
+HWC2::Error HWCDisplayPluggable::SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent) {
auto status = color_mode_->SetColorModeWithRenderIntent(mode, intent);
if (status != HWC2::Error::None) {
DLOGE("failed for mode = %d intent = %d", mode, intent);
diff --git a/sdm/libs/hwc2/hwc_display_external.h b/sdm/libs/hwc2/hwc_display_pluggable.h
similarity index 80%
rename from sdm/libs/hwc2/hwc_display_external.h
rename to sdm/libs/hwc2/hwc_display_pluggable.h
index 89ac87e..1b35b98 100644
--- a/sdm/libs/hwc2/hwc_display_external.h
+++ b/sdm/libs/hwc2/hwc_display_pluggable.h
@@ -27,8 +27,8 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __HWC_DISPLAY_EXTERNAL_H__
-#define __HWC_DISPLAY_EXTERNAL_H__
+#ifndef __HWC_DISPLAY_PLUGGABLE_H__
+#define __HWC_DISPLAY_PLUGGABLE_H__
#include "hwc_display.h"
#include "display_null.h"
@@ -36,15 +36,13 @@
namespace sdm {
-class HWCDisplayExternal : public HWCDisplay {
+class HWCDisplayPluggable : public HWCDisplay {
public:
static int Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
- uint32_t primary_width, uint32_t primary_height, qService::QService *qservice,
+ qService::QService *qservice, hwc2_display_t id,
+ int32_t sdm_id, uint32_t primary_width, uint32_t primary_height,
bool use_primary_res, HWCDisplay **hwc_display);
- static int Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
- HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
- qService::QService *qservice, HWCDisplay **hwc_display);
static void Destroy(HWCDisplay *hwc_display);
virtual int Init();
virtual HWC2::Error Validate(uint32_t *out_num_types, uint32_t *out_num_requests);
@@ -58,9 +56,9 @@
virtual HWC2::Error SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent);
private:
- HWCDisplayExternal(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
- HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
- qService::QService *qservice);
+ HWCDisplayPluggable(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+ HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
+ qService::QService *qservice, hwc2_display_t id, int32_t sdm_id);
void ApplyScanAdjustment(hwc_rect_t *display_frame);
void GetUnderScanConfig();
static void GetDownscaleResolution(uint32_t primary_width, uint32_t primary_height,
@@ -73,4 +71,4 @@
} // namespace sdm
-#endif // __HWC_DISPLAY_EXTERNAL_H__
+#endif // __HWC_DISPLAY_PLUGGABLE_H__
diff --git a/sdm/libs/hwc2/hwc_display_external_test.cpp b/sdm/libs/hwc2/hwc_display_pluggable_test.cpp
similarity index 85%
rename from sdm/libs/hwc2/hwc_display_external_test.cpp
rename to sdm/libs/hwc2/hwc_display_pluggable_test.cpp
index aaeb891..4aa7f9d 100644
--- a/sdm/libs/hwc2/hwc_display_external_test.cpp
+++ b/sdm/libs/hwc2/hwc_display_pluggable_test.cpp
@@ -40,61 +40,64 @@
#include <string>
#include <fstream>
-#include "hwc_display_external_test.h"
+#include "hwc_display_pluggable_test.h"
#include "hwc_debugger.h"
-#define __CLASS__ "HWCDisplayExternalTest"
+#define __CLASS__ "HWCDisplayPluggableTest"
namespace sdm {
using std::array;
-int HWCDisplayExternalTest::Create(CoreInterface *core_intf,
- HWCBufferAllocator *buffer_allocator,
- HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
- qService::QService *qservice, uint32_t panel_bpp,
- uint32_t pattern_type, HWCDisplay **hwc_display) {
- HWCDisplay *hwc_external_test = new HWCDisplayExternalTest(core_intf, buffer_allocator,
- callbacks, event_handler, qservice,
- panel_bpp, pattern_type);
+int HWCDisplayPluggableTest::Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+ HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
+ qService::QService *qservice, hwc2_display_t id,
+ int32_t sdm_id, uint32_t panel_bpp, uint32_t pattern_type,
+ HWCDisplay **hwc_display) {
+ HWCDisplay *hwc_pluggable_test = new HWCDisplayPluggableTest(core_intf, buffer_allocator,
+ callbacks, event_handler, qservice,
+ id, sdm_id, panel_bpp, pattern_type);
- int status = static_cast<HWCDisplayExternalTest *>(hwc_external_test)->Init();
+ int status = hwc_pluggable_test->Init();
if (status) {
- delete hwc_external_test;
+ delete hwc_pluggable_test;
return status;
}
- *hwc_display = hwc_external_test;
+ *hwc_display = hwc_pluggable_test;
- DLOGE("EXTERNAL panel_bpp %d, pattern_type %d", panel_bpp, pattern_type);
+ DLOGD("Pluggable panel_bpp %d, pattern_type %d", panel_bpp, pattern_type);
return status;
}
-void HWCDisplayExternalTest::Destroy(HWCDisplay *hwc_display) {
- static_cast<HWCDisplayExternalTest *>(hwc_display)->Deinit();
+void HWCDisplayPluggableTest::Destroy(HWCDisplay *hwc_display) {
+ // Flush the display to have outstanding fences signaled.
+ hwc_display->Flush();
+ hwc_display->Deinit();
delete hwc_display;
}
-HWCDisplayExternalTest::HWCDisplayExternalTest(CoreInterface *core_intf,
- HWCBufferAllocator *buffer_allocator,
- HWCCallbacks *callbacks,
- HWCDisplayEventHandler *event_handler,
- qService::QService *qservice, uint32_t panel_bpp,
- uint32_t pattern_type)
- : HWCDisplay(core_intf, callbacks, event_handler, kHDMI, HWC_DISPLAY_EXTERNAL, false,
- qservice, DISPLAY_CLASS_EXTERNAL, buffer_allocator), panel_bpp_(panel_bpp),
- pattern_type_(pattern_type) {
+HWCDisplayPluggableTest::HWCDisplayPluggableTest(CoreInterface *core_intf,
+ HWCBufferAllocator *buffer_allocator,
+ HWCCallbacks *callbacks,
+ HWCDisplayEventHandler *event_handler,
+ qService::QService *qservice, hwc2_display_t id,
+ int32_t sdm_id, uint32_t panel_bpp,
+ uint32_t pattern_type)
+ : HWCDisplay(core_intf, buffer_allocator, callbacks, event_handler, qservice, kPluggable, id,
+ sdm_id, false, DISPLAY_CLASS_PLUGGABLE),
+ panel_bpp_(panel_bpp), pattern_type_(pattern_type) {
}
-int HWCDisplayExternalTest::Init() {
- uint32_t external_width = 0;
- uint32_t external_height = 0;
+int HWCDisplayPluggableTest::Init() {
+ uint32_t pluggable_width = 0;
+ uint32_t pluggable_height = 0;
int status = HWCDisplay::Init();
if (status) {
- DLOGE("HWCDisplayExternalTest::Init status = %d ", status);
+ DLOGE("HWCDisplayPluggableTest::Init status = %d ", status);
return status;
}
@@ -104,29 +107,29 @@
return status;
}
- DisplayError error = HWCDisplay::GetMixerResolution(&external_width, &external_height);
+ DisplayError error = HWCDisplay::GetMixerResolution(&pluggable_width, &pluggable_height);
if (error != kErrorNone) {
Deinit();
return -EINVAL;
}
- status = HWCDisplay::SetFrameBufferResolution(external_width, external_height);
+ status = HWCDisplay::SetFrameBufferResolution(pluggable_width, pluggable_height);
if (status) {
Deinit();
- DLOGE("HWCDisplayExternalTest:: set fb resolution status = %d ", status);
+ DLOGE("HWCDisplayPluggableTest:: set fb resolution status = %d ", status);
return status;
}
return status;
}
-int HWCDisplayExternalTest::Deinit() {
+int HWCDisplayPluggableTest::Deinit() {
DestroyLayerStack();
return HWCDisplay::Deinit();
}
-HWC2::Error HWCDisplayExternalTest::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
+HWC2::Error HWCDisplayPluggableTest::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
auto status = HWC2::Error::None;
if (active_secure_sessions_[kSecureDisplay] || display_paused_) {
MarkLayersForGPUBypass();
@@ -158,7 +161,7 @@
return status;
}
-HWC2::Error HWCDisplayExternalTest::Present(int32_t *out_retire_fence) {
+HWC2::Error HWCDisplayPluggableTest::Present(int32_t *out_retire_fence) {
auto status = HWC2::Error::None;
if (active_secure_sessions_[kSecureDisplay]) {
@@ -201,11 +204,11 @@
return status;
}
-int HWCDisplayExternalTest::Perform(uint32_t operation, ...) {
+int HWCDisplayPluggableTest::Perform(uint32_t operation, ...) {
return 0;
}
-void HWCDisplayExternalTest::DumpInputBuffer() {
+void HWCDisplayPluggableTest::DumpInputBuffer() {
if (!dump_frame_count_ || flush_ || !dump_input_layers_) {
return;
}
@@ -263,7 +266,7 @@
}
}
-void HWCDisplayExternalTest::CalcCRC(uint32_t color_val, std::bitset<16> *crc_data) {
+void HWCDisplayPluggableTest::CalcCRC(uint32_t color_val, std::bitset<16> *crc_data) {
std::bitset<16> color = {};
std::bitset<16> temp_crc = {};
@@ -319,7 +322,7 @@
(*crc_data) = temp_crc;
}
-int HWCDisplayExternalTest::FillBuffer() {
+int HWCDisplayPluggableTest::FillBuffer() {
uint8_t *buffer = reinterpret_cast<uint8_t *>(mmap(NULL, buffer_info_.alloc_buffer_info.size,
PROT_READ|PROT_WRITE, MAP_SHARED,
buffer_info_.alloc_buffer_info.fd, 0));
@@ -351,7 +354,7 @@
return 0;
}
-int HWCDisplayExternalTest::GetStride(LayerBufferFormat format, uint32_t width, uint32_t *stride) {
+int HWCDisplayPluggableTest::GetStride(LayerBufferFormat format, uint32_t width, uint32_t *stride) {
switch (format) {
case kFormatRGBA8888:
case kFormatRGBA1010102:
@@ -368,7 +371,7 @@
return 0;
}
-void HWCDisplayExternalTest::PixelCopy(uint32_t red, uint32_t green, uint32_t blue, uint32_t alpha,
+void HWCDisplayPluggableTest::PixelCopy(uint32_t red, uint32_t green, uint32_t blue, uint32_t alpha,
uint8_t **buffer) {
LayerBufferFormat format = buffer_info_.buffer_config.format;
@@ -403,7 +406,7 @@
}
}
-void HWCDisplayExternalTest::GenerateColorRamp(uint8_t *buffer) {
+void HWCDisplayPluggableTest::GenerateColorRamp(uint8_t *buffer) {
uint32_t width = buffer_info_.buffer_config.width;
uint32_t height = buffer_info_.buffer_config.height;
LayerBufferFormat format = buffer_info_.buffer_config.format;
@@ -497,7 +500,7 @@
DLOGI("CRC blue %x", crc_blue.to_ulong());
}
-void HWCDisplayExternalTest::GenerateBWVertical(uint8_t *buffer) {
+void HWCDisplayPluggableTest::GenerateBWVertical(uint8_t *buffer) {
uint32_t width = buffer_info_.buffer_config.width;
uint32_t height = buffer_info_.buffer_config.height;
LayerBufferFormat format = buffer_info_.buffer_config.format;
@@ -543,7 +546,7 @@
DLOGI("CRC blue %x", crc_blue.to_ulong());
}
-void HWCDisplayExternalTest::GenerateColorSquare(uint8_t *buffer) {
+void HWCDisplayPluggableTest::GenerateColorSquare(uint8_t *buffer) {
uint32_t width = buffer_info_.buffer_config.width;
uint32_t height = buffer_info_.buffer_config.height;
LayerBufferFormat format = buffer_info_.buffer_config.format;
@@ -611,7 +614,7 @@
DLOGI("CRC blue %x", crc_blue.to_ulong());
}
-int HWCDisplayExternalTest::InitLayer(Layer *layer) {
+int HWCDisplayPluggableTest::InitLayer(Layer *layer) {
uint32_t active_config = 0;
DisplayConfigVariableInfo var_info = {};
@@ -674,7 +677,7 @@
return 0;
}
-int HWCDisplayExternalTest::DeinitLayer(Layer *layer) {
+int HWCDisplayPluggableTest::DeinitLayer(Layer *layer) {
if (layer->composition != kCompositionGPUTarget) {
int ret = buffer_allocator_->FreeBuffer(&buffer_info_);
if (ret != 0) {
@@ -686,14 +689,14 @@
return 0;
}
-int HWCDisplayExternalTest::CreateLayerStack() {
+int HWCDisplayPluggableTest::CreateLayerStack() {
for (uint32_t i = 0; i < (kTestLayerCnt + 1 /* one dummy gpu_target layer */); i++) {
Layer *layer = new Layer();
if (i == kTestLayerCnt) {
layer->composition = kCompositionGPUTarget;
}
- DLOGE("External :: CreateLayerStack %d", i);
+ DLOGD("External :: CreateLayerStack %d", i);
int ret = InitLayer(layer);
if (ret != 0) {
delete layer;
@@ -705,7 +708,7 @@
return 0;
}
-int HWCDisplayExternalTest::DestroyLayerStack() {
+int HWCDisplayPluggableTest::DestroyLayerStack() {
for (uint32_t i = 0; i < UINT32(layer_stack_.layers.size()); i++) {
Layer *layer = layer_stack_.layers.at(i);
int ret = DeinitLayer(layer);
@@ -719,7 +722,7 @@
return 0;
}
-HWC2::Error HWCDisplayExternalTest::PostCommit(int32_t *out_retire_fence) {
+HWC2::Error HWCDisplayPluggableTest::PostCommit(int32_t *out_retire_fence) {
auto status = HWC2::Error::None;
// Do no call flush on errors, if a successful buffer is never submitted.
if (flush_ && flush_on_error_) {
diff --git a/sdm/libs/hwc2/hwc_display_external_test.h b/sdm/libs/hwc2/hwc_display_pluggable_test.h
similarity index 82%
rename from sdm/libs/hwc2/hwc_display_external_test.h
rename to sdm/libs/hwc2/hwc_display_pluggable_test.h
index 2526e5c..920003e 100644
--- a/sdm/libs/hwc2/hwc_display_external_test.h
+++ b/sdm/libs/hwc2/hwc_display_pluggable_test.h
@@ -27,8 +27,8 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __HWC_DISPLAY_EXTERNAL_TEST_H__
-#define __HWC_DISPLAY_EXTERNAL_TEST_H__
+#ifndef __HWC_DISPLAY_PLUGGABLE_TEST_H__
+#define __HWC_DISPLAY_PLUGGABLE_TEST_H__
#include <bitset>
@@ -37,12 +37,12 @@
namespace sdm {
-class HWCDisplayExternalTest : public HWCDisplay {
+class HWCDisplayPluggableTest : public HWCDisplay {
public:
static int Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
- qService::QService *qservice, uint32_t panel_bpp, uint32_t pattern_type,
- HWCDisplay **hwc_display);
+ qService::QService *qservice, hwc2_display_t id, int32_t sdm_id,
+ uint32_t panel_bpp, uint32_t pattern_type, HWCDisplay **hwc_display);
static void Destroy(HWCDisplay *hwc_display);
virtual HWC2::Error Validate(uint32_t *out_num_types, uint32_t *out_num_requests);
virtual HWC2::Error Present(int32_t *out_retire_fence);
@@ -79,9 +79,10 @@
};
private:
- HWCDisplayExternalTest(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
- HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
- qService::QService *qservice, uint32_t panel_bpp, uint32_t pattern_type);
+ HWCDisplayPluggableTest(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+ HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
+ qService::QService *qservice, hwc2_display_t id,
+ int32_t sdm_id, uint32_t panel_bpp, uint32_t pattern_type);
int Init();
int Deinit();
void DumpInputBuffer();
@@ -103,5 +104,5 @@
} // namespace sdm
-#endif // __HWC_DISPLAY_EXTERNAL_TEST_H__
+#endif // __HWC_DISPLAY_PLUGGABLE_TEST_H__
diff --git a/sdm/libs/hwc2/hwc_display_virtual.cpp b/sdm/libs/hwc2/hwc_display_virtual.cpp
index f98e433..97d74ef 100644
--- a/sdm/libs/hwc2/hwc_display_virtual.cpp
+++ b/sdm/libs/hwc2/hwc_display_virtual.cpp
@@ -40,11 +40,12 @@
namespace sdm {
int HWCDisplayVirtual::Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
- HWCCallbacks *callbacks, uint32_t width, uint32_t height,
- int32_t *format, HWCDisplay **hwc_display) {
+ HWCCallbacks *callbacks, hwc2_display_t id, int32_t sdm_id,
+ uint32_t width, uint32_t height, int32_t *format,
+ HWCDisplay **hwc_display) {
int status = 0;
HWCDisplayVirtual *hwc_display_virtual = new HWCDisplayVirtual(core_intf, buffer_allocator,
- callbacks);
+ callbacks, id, sdm_id);
// TODO(user): Populate format correctly
DLOGI("Creating virtual display: w: %d h:%d format:0x%x", width, height, *format);
@@ -89,9 +90,9 @@
}
HWCDisplayVirtual::HWCDisplayVirtual(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
- HWCCallbacks *callbacks) :
- HWCDisplay(core_intf, callbacks, nullptr, kVirtual, HWC_DISPLAY_VIRTUAL, false, nullptr,
- DISPLAY_CLASS_VIRTUAL, buffer_allocator) {
+ HWCCallbacks *callbacks, hwc2_display_t id, int32_t sdm_id) :
+ HWCDisplay(core_intf, buffer_allocator, callbacks, nullptr, nullptr, kVirtual, id, sdm_id,
+ false, DISPLAY_CLASS_VIRTUAL) {
}
int HWCDisplayVirtual::Init() {
@@ -293,4 +294,14 @@
return HWC2::Error::None;
}
+HWC2::Error HWCDisplayVirtual::GetDisplayType(int32_t *out_type) {
+ if (out_type == nullptr) {
+ return HWC2::Error::BadParameter;
+ }
+
+ *out_type = HWC2_DISPLAY_TYPE_VIRTUAL;
+
+ return HWC2::Error::None;
+}
+
} // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_display_virtual.h b/sdm/libs/hwc2/hwc_display_virtual.h
index ba7dd04..509e398 100644
--- a/sdm/libs/hwc2/hwc_display_virtual.h
+++ b/sdm/libs/hwc2/hwc_display_virtual.h
@@ -40,19 +40,20 @@
class HWCDisplayVirtual : public HWCDisplay {
public:
static int Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
- HWCCallbacks *callbacks, uint32_t width, uint32_t height, int32_t *format,
- HWCDisplay **hwc_display);
+ HWCCallbacks *callbacks, hwc2_display_t id, int32_t sdm_id, uint32_t width,
+ uint32_t height, int32_t *format, HWCDisplay **hwc_display);
static void Destroy(HWCDisplay *hwc_display);
virtual int Init();
virtual int Deinit();
virtual HWC2::Error Validate(uint32_t *out_num_types, uint32_t *out_num_requests);
virtual HWC2::Error Present(int32_t *out_retire_fence);
virtual HWC2::Error SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
+ virtual HWC2::Error GetDisplayType(int32_t *out_type);
HWC2::Error SetOutputBuffer(buffer_handle_t buf, int32_t release_fence);
private:
HWCDisplayVirtual(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
- HWCCallbacks *callbacks);
+ HWCCallbacks *callbacks, hwc2_display_t id, int32_t sdm_id);
int SetConfig(uint32_t width, uint32_t height);
bool dump_output_layer_ = false;
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 10482ae..d0a8ff5 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -31,6 +31,7 @@
#include <utils/String16.h>
#include <utils/constants.h>
#include <utils/debug.h>
+#include <QService.h>
#include <utils/utils.h>
#include <algorithm>
#include <bitset>
@@ -43,9 +44,6 @@
#include "hwc_buffer_sync_handler.h"
#include "hwc_session.h"
#include "hwc_debugger.h"
-#include "hwc_display_primary.h"
-#include "hwc_display_virtual.h"
-#include "hwc_display_external_test.h"
#define __CLASS__ "HWCSession"
@@ -72,7 +70,7 @@
namespace sdm {
static HWCUEvent g_hwc_uevent_;
-Locker HWCSession::locker_[HWC_NUM_DISPLAY_TYPES];
+Locker HWCSession::locker_[kNumDisplays];
static const int kSolidFillDelay = 100 * 1000;
void HWCUEvent::UEventThread(HWCUEvent *hwc_uevent) {
@@ -99,7 +97,7 @@
while (1) {
char uevent_data[PAGE_SIZE] = {};
- // keep last 2 zeroes to ensure double 0 termination
+ // keep last 2 zeros to ensure double 0 termination
int length = uevent_next_event(uevent_data, INT32(sizeof(uevent_data)) - 2);
// scope of lock to this block only, so that caller is free to set event handler to nullptr;
@@ -147,6 +145,8 @@
return status;
}
+ InitDisplaySlots();
+
// Start QService and connect to it.
qService::QService::init();
android::sp<qService::IQService> iqservice = android::interface_cast<qService::IQService>(
@@ -171,7 +171,6 @@
hw_disp_info.is_connected = true;
} else {
g_hwc_uevent_.Register(this);
-
error = CoreInterface::CreateCore(&buffer_allocator_, &buffer_sync_handler_, &socket_handler_,
&core_intf_);
@@ -185,58 +184,34 @@
}
}
- // If HDMI display is primary display, defer display creation until hotplug event is received.
- 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 = CreateExternalDisplay(HWC_DISPLAY_PRIMARY, 0, 0, false);
- }
- } else {
- // Create and power on primary display
- status = HWCDisplayPrimary::Create(core_intf_, &buffer_allocator_, &callbacks_, this, qservice_,
- &hwc_display_[HWC_DISPLAY_PRIMARY]);
- color_mgr_ = HWCColorManager::CreateColorManager(&buffer_allocator_);
- if (!color_mgr_) {
- DLOGW("Failed to load HWCColorManager.");
- }
- }
-
+ // Create primary display here. Remaining builtin displays will be created after client has set
+ // display indexes which may happen sometime before callback is registered.
+ status = CreatePrimaryDisplay();
if (status) {
- g_hwc_uevent_.Register(nullptr);
- CoreInterface::DestroyCore();
+ Deinit();
return status;
}
is_composer_up_ = true;
- struct rlimit fd_limit = {};
- getrlimit(RLIMIT_NOFILE, &fd_limit);
- fd_limit.rlim_cur = fd_limit.rlim_cur * 2;
- if (fd_limit.rlim_cur < fd_limit.rlim_max) {
- auto err = setrlimit(RLIMIT_NOFILE, &fd_limit);
- if (err) {
- DLOGW("Unable to increase fd limit - err:%d, %s", errno, strerror(errno));
- }
- }
return 0;
}
int HWCSession::Deinit() {
- Locker::SequenceCancelScopeLock lock_v(locker_[HWC_DISPLAY_VIRTUAL]);
- Locker::SequenceCancelScopeLock lock_e(locker_[HWC_DISPLAY_EXTERNAL]);
- Locker::SequenceCancelScopeLock lock_p(locker_[HWC_DISPLAY_PRIMARY]);
+ // Destroy all connected displays
+ DestroyDisplay(&map_info_primary_);
- HWCDisplay *primary_display = hwc_display_[HWC_DISPLAY_PRIMARY];
- if (primary_display) {
- if (hdmi_is_primary_) {
- HWCDisplayExternal::Destroy(primary_display);
- } else {
- HWCDisplayPrimary::Destroy(primary_display);
- }
+ for (auto &map_info : map_info_builtin_) {
+ DestroyDisplay(&map_info);
}
- hwc_display_[HWC_DISPLAY_PRIMARY] = nullptr;
+
+ for (auto &map_info : map_info_pluggable_) {
+ DestroyDisplay(&map_info);
+ }
+
+ for (auto &map_info : map_info_virtual_) {
+ DestroyDisplay(&map_info);
+ }
if (color_mgr_) {
color_mgr_->DestroyColorManager();
@@ -254,6 +229,57 @@
return 0;
}
+void HWCSession::InitDisplaySlots() {
+ // Default slots:
+ // Primary = 0, External = 1, Virtual = 2 (legacy IDs)
+ // Additional builtin displays 3, 4 ... x
+ // Additional external displays x+1, x+2 ... y
+ // Additional virtual displays y+1, y+2 ... z
+ // If client does not support additional displays, hotplug for such displays
+ // will be disregarded by the client.
+ // If client supports different range of ids for additional displays, those
+ // will be set and overridden by an explicit call to set display indexes.
+ hwc2_display_t additional_base_id = qdutils::DISPLAY_VIRTUAL + 1;
+
+ map_info_primary_.client_id = qdutils::DISPLAY_PRIMARY;
+
+ map_info_builtin_.resize(kNumBuiltIn);
+ for (size_t i = 0; i < kNumBuiltIn; i++) {
+ map_info_builtin_[i].client_id = additional_base_id++;
+ }
+
+ map_info_pluggable_.resize(kNumPluggable);
+ for (size_t i = 0; i < kNumPluggable; i++) {
+ map_info_pluggable_[i].client_id = i ? additional_base_id++ : qdutils::DISPLAY_EXTERNAL;
+ }
+
+ map_info_virtual_.resize(kNumVirtual);
+ for (size_t i = 0; i < kNumVirtual; i++) {
+ map_info_virtual_[i].client_id = i ? additional_base_id++ : qdutils::DISPLAY_VIRTUAL;
+ }
+}
+
+int HWCSession::GetDisplayIndex(int dpy) {
+ DisplayMapInfo *map_info = nullptr;
+ switch (dpy) {
+ case qdutils::DISPLAY_PRIMARY:
+ map_info = &map_info_primary_;
+ break;
+ case qdutils::DISPLAY_EXTERNAL:
+ map_info = map_info_pluggable_.size() ? &map_info_pluggable_[0] : nullptr;
+ break;
+ case qdutils::DISPLAY_VIRTUAL:
+ map_info = map_info_virtual_.size() ? &map_info_virtual_[0] : nullptr;
+ break;
+ }
+
+ if (!map_info) {
+ return -1;
+ }
+
+ return INT(map_info->client_id);
+}
+
int HWCSession::Open(const hw_module_t *module, const char *name, hw_device_t **device) {
if (!module || !name || !device) {
DLOGE("Invalid parameters.");
@@ -349,12 +375,9 @@
}
HWCSession *hwc_session = static_cast<HWCSession *>(device);
- auto status = hwc_session->CreateVirtualDisplayObject(width, height, format);
-
+ auto status = hwc_session->CreateVirtualDisplayObj(width, height, format, out_display_id);
if (status == HWC2::Error::None) {
- *out_display_id = HWC_DISPLAY_VIRTUAL;
- DLOGI("Created virtual display id:% " PRIu64 " with res: %dx%d",
- *out_display_id, width, height);
+ DLOGI("Created virtual display id:% " PRIu64 ", res: %dx%d", *out_display_id, width, height);
} else {
DLOGE("Failed to create virtual display: %s", to_string(status).c_str());
}
@@ -367,7 +390,7 @@
}
int32_t HWCSession::DestroyVirtualDisplay(hwc2_device_t *device, hwc2_display_t display) {
- if (!device || display != HWC_DISPLAY_VIRTUAL) {
+ if (!device || display >= kNumDisplays) {
return HWC2_ERROR_BAD_DISPLAY;
}
@@ -386,13 +409,15 @@
}
}
- if (hwc_session->hwc_display_[display]) {
- HWCDisplayVirtual::Destroy(hwc_session->hwc_display_[display]);
- hwc_session->hwc_display_[display] = nullptr;
- return HWC2_ERROR_NONE;
- } else {
- return HWC2_ERROR_BAD_DISPLAY;
+ for (auto &map_info : hwc_session->map_info_virtual_) {
+ if (map_info.client_id == display) {
+ DLOGI("Destroying virtual display id:%" PRIu64, display);
+ hwc_session->DestroyDisplay(&map_info);
+ break;
+ }
}
+
+ return HWC2_ERROR_NONE;
}
void HWCSession::Dump(hwc2_device_t *device, uint32_t *out_size, char *out_buffer) {
@@ -407,7 +432,7 @@
*out_size = max_dump_size;
} else {
std::string s {};
- for (int id = HWC_DISPLAY_PRIMARY; id <= HWC_DISPLAY_VIRTUAL; id++) {
+ for (int id = 0; id < kNumDisplays; id++) {
SCOPE_LOCK(locker_[id]);
if (hwc_session->hwc_display_[id]) {
s += hwc_session->hwc_display_[id]->Dump();
@@ -565,7 +590,7 @@
return HWC2_ERROR_BAD_PARAMETER;
}
- if (display >= HWC_NUM_DISPLAY_TYPES) {
+ if (display >= HWCSession::kNumDisplays) {
return HWC2_ERROR_BAD_DISPLAY;
}
@@ -608,7 +633,7 @@
auto status = HWC2::Error::BadDisplay;
DTRACE_SCOPED();
- if (display >= HWC_NUM_DISPLAY_TYPES) {
+ if (display >= kNumDisplays) {
return HWC2_ERROR_BAD_DISPLAY;
}
@@ -636,6 +661,13 @@
hwc_session->HandlePowerOnPending(display, *out_retire_fence);
hwc_session->HandleHotplugPending(display, *out_retire_fence);
+ // Handle pending builtin/pluggable display connections
+ if (!hwc_session->primary_ready_ && (display == HWC_DISPLAY_PRIMARY)) {
+ hwc_session->CreateBuiltInDisplays();
+ hwc_session->CreatePluggableDisplays(false);
+ hwc_session->primary_ready_ = true;
+ }
+
return INT32(status);
}
@@ -649,15 +681,21 @@
SCOPE_LOCK(hwc_session->callbacks_lock_);
auto desc = static_cast<HWC2::Callback>(descriptor);
auto error = hwc_session->callbacks_.Register(desc, callback_data, pointer);
+ if (error != HWC2::Error::None) {
+ return INT32(error);
+ }
+
DLOGD("%s callback: %s", pointer ? "Registering" : "Deregistering", to_string(desc).c_str());
if (descriptor == HWC2_CALLBACK_HOTPLUG) {
if (hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY]) {
hwc_session->callbacks_.Hotplug(HWC_DISPLAY_PRIMARY, HWC2::Connection::Connected);
}
+ hwc_session->client_connected_ = true;
}
hwc_session->need_invalidate_ = false;
hwc_session->callbacks_lock_.Broadcast();
- return INT32(error);
+
+ return 0;
}
static int32_t SetActiveConfig(hwc2_device_t *device, hwc2_display_t display,
@@ -797,12 +835,12 @@
return HWC2_ERROR_BAD_PARAMETER;
}
- if (display != HWC_DISPLAY_VIRTUAL) {
+ auto *hwc_session = static_cast<HWCSession *>(device);
+ if (INT32(display) != hwc_session->GetDisplayIndex(qdutils::DISPLAY_VIRTUAL)) {
return HWC2_ERROR_UNSUPPORTED;
}
SCOPE_LOCK(locker_[display]);
- auto *hwc_session = static_cast<HWCSession *>(device);
if (hwc_session->hwc_display_[display]) {
auto vds = reinterpret_cast<HWCDisplayVirtual *>(hwc_session->hwc_display_[display]);
auto status = vds->SetOutputBuffer(buffer, releaseFence);
@@ -813,7 +851,7 @@
}
int32_t HWCSession::SetPowerMode(hwc2_device_t *device, hwc2_display_t display, int32_t int_mode) {
- if (display >= HWC_NUM_DISPLAY_TYPES) {
+ if (display >= kNumDisplays) {
return HWC2_ERROR_BAD_DISPLAY;
}
@@ -857,14 +895,13 @@
return HWC2_ERROR_BAD_PARAMETER;
}
- if (display >= HWC_NUM_DISPLAY_TYPES) {
+ if (display >= kNumDisplays) {
return HWC2_ERROR_BAD_DISPLAY;
}
DTRACE_SCOPED();
HWCSession *hwc_session = static_cast<HWCSession *>(device);
// TODO(user): Handle secure session, handle QDCM solid fill
- // Handle external_pending_connect_ in CreateVirtualDisplay
auto status = HWC2::Error::BadDisplay;
hwc_session->HandleSecureSession(display);
{
@@ -998,8 +1035,8 @@
return nullptr;
}
-HWC2::Error HWCSession::CreateVirtualDisplayObject(uint32_t width, uint32_t height,
- int32_t *format) {
+HWC2::Error HWCSession::CreateVirtualDisplayObj(uint32_t width, uint32_t height, int32_t *format,
+ hwc2_display_t *out_display_id) {
if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
std :: bitset < kSecureMax > secure_sessions = 0;
@@ -1010,18 +1047,58 @@
}
}
+ if (!client_connected_) {
+ DLOGE("Client is not ready yet.");
+ return HWC2::Error::BadDisplay;
+ }
+
+ // Use first virtual display only for now.
+ if (!map_info_virtual_.size()) {
+ DLOGE("Virtual display is not supported");
+ return HWC2::Error::NoResources;
+ }
+
+ HWDisplaysInfo hw_displays_info = {};
+ DisplayError error = core_intf_->GetDisplaysStatus(&hw_displays_info);
+ if (error != kErrorNone) {
+ DLOGE("Failed to get connected display list. Error = %d", error);
+ return HWC2::Error::BadDisplay;
+ }
+
+ auto &map_info = map_info_virtual_[0];
+ hwc2_display_t client_id = map_info.client_id;
+
+ // Lock confined to this scope
+ int status = -EINVAL;
{
- SCOPE_LOCK(locker_[HWC_DISPLAY_VIRTUAL]);
- if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
+ SCOPE_LOCK(locker_[client_id]);
+ auto &hwc_display = hwc_display_[client_id];
+ if (hwc_display) {
+ DLOGE("Virtual display is already created.");
return HWC2::Error::NoResources;
}
- auto status = HWCDisplayVirtual::Create(core_intf_, &buffer_allocator_, &callbacks_,
- width, height, format,
- &hwc_display_[HWC_DISPLAY_VIRTUAL]);
- // TODO(user): validate width and height support
+ for (auto &iter : hw_displays_info) {
+ auto &info = iter.second;
+ if (info.display_type != kVirtual) {
+ continue;
+ }
+
+ status = HWCDisplayVirtual::Create(core_intf_, &buffer_allocator_, &callbacks_, client_id,
+ info.display_id, width, height, format, &hwc_display);
+ // TODO(user): validate width and height support
+ if (!status) {
+ DLOGI("Created virtual display id:% " PRIu64 " with res: %dx%d", client_id, width, height);
+
+ *out_display_id = client_id;
+ map_info.disp_type = info.display_type;
+ map_info.sdm_id = info.display_id;
+ }
+ break;
+ }
+
if (status) {
- return HWC2::Error::Unsupported;
+ return HWC2::Error::BadDisplay;
}
}
@@ -1031,46 +1108,6 @@
return HWC2::Error::None;
}
-int32_t HWCSession::ConnectDisplay(int disp) {
- DLOGI("Display = %d", disp);
-
- int status = 0;
- uint32_t primary_width = 0;
- uint32_t primary_height = 0;
-
- hwc_display_[HWC_DISPLAY_PRIMARY]->GetFrameBufferResolution(&primary_width, &primary_height);
-
- if (disp == HWC_DISPLAY_EXTERNAL) {
- status = CreateExternalDisplay(disp, primary_width, primary_height, false);
- } else {
- DLOGE("Invalid display type");
- return -1;
- }
-
- return status;
-}
-
-int HWCSession::DisconnectDisplay(int disp) {
- DLOGI("Display = %d", disp);
-
- if (disp == HWC_DISPLAY_EXTERNAL) {
- DisplayError error = hwc_display_[disp]->Flush();
- if (error != kErrorNone) {
- DLOGW("Flush failed. Error = %d", error);
- }
- HWCDisplayExternal::Destroy(hwc_display_[disp]);
- } else if (disp == HWC_DISPLAY_VIRTUAL) {
- HWCDisplayVirtual::Destroy(hwc_display_[disp]);
- } else {
- DLOGE("Invalid display type");
- return -1;
- }
-
- hwc_display_[disp] = NULL;
-
- return 0;
-}
-
// Qclient methods
android::status_t HWCSession::notifyCallback(uint32_t command, const android::Parcel *input_parcel,
android::Parcel *output_parcel) {
@@ -1230,7 +1267,7 @@
DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
break;
}
- status = HandleGetDisplayAttributesForConfig(input_parcel, output_parcel);
+ status = GetDisplayAttributesForConfig(input_parcel, output_parcel);
break;
case qService::IQService::GET_PANEL_BRIGHTNESS: {
@@ -1345,21 +1382,22 @@
return is_composer_up_;
}
-android::status_t HWCSession::HandleGetDisplayAttributesForConfig(const android::Parcel
- *input_parcel,
- android::Parcel *output_parcel) {
+android::status_t HWCSession::GetDisplayAttributesForConfig(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel) {
int config = input_parcel->readInt32();
int dpy = input_parcel->readInt32();
int error = android::BAD_VALUE;
DisplayConfigVariableInfo display_attributes;
- if (dpy < HWC_DISPLAY_PRIMARY || dpy >= HWC_NUM_DISPLAY_TYPES || config < 0) {
+ int disp_idx = GetDisplayIndex(dpy);
+ if (disp_idx == -1 || config < 0) {
+ DLOGE("Invalid display = %d, or config = %d", dpy, config);
return android::BAD_VALUE;
}
- SEQUENCE_WAIT_SCOPE_LOCK(locker_[dpy]);
- if (hwc_display_[dpy]) {
- error = hwc_display_[dpy]->GetDisplayAttributesForConfig(config, &display_attributes);
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
+ if (hwc_display_[disp_idx]) {
+ error = hwc_display_[disp_idx]->GetDisplayAttributesForConfig(config, &display_attributes);
if (error == 0) {
output_parcel->writeInt32(INT(display_attributes.vsync_period_ns));
output_parcel->writeInt32(INT(display_attributes.x_pixels));
@@ -1386,14 +1424,14 @@
switch (operation) {
case qdutils::DISABLE_METADATA_DYN_REFRESH_RATE:
- return hwc_display->Perform(HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, false);
+ return hwc_display->Perform(HWCDisplayBuiltIn::SET_METADATA_DYN_REFRESH_RATE, false);
case qdutils::ENABLE_METADATA_DYN_REFRESH_RATE:
- return hwc_display->Perform(HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, true);
+ return hwc_display->Perform(HWCDisplayBuiltIn::SET_METADATA_DYN_REFRESH_RATE, true);
case qdutils::SET_BINDER_DYN_REFRESH_RATE: {
uint32_t refresh_rate = UINT32(input_parcel->readInt32());
- return hwc_display->Perform(HWCDisplayPrimary::SET_BINDER_DYN_REFRESH_RATE, refresh_rate);
+ return hwc_display->Perform(HWCDisplayBuiltIn::SET_BINDER_DYN_REFRESH_RATE, refresh_rate);
}
default:
@@ -1413,7 +1451,7 @@
}
uint32_t mode = UINT32(input_parcel->readInt32());
- return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(HWCDisplayPrimary::SET_DISPLAY_MODE, mode);
+ return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(HWCDisplayBuiltIn::SET_DISPLAY_MODE, mode);
}
android::status_t HWCSession::SetMaxMixerStages(const android::Parcel *input_parcel) {
@@ -1422,20 +1460,22 @@
uint32_t max_mixer_stages = UINT32(input_parcel->readInt32());
android::status_t status = 0;
- for (uint32_t disp_id = HWC_DISPLAY_PRIMARY; disp_id < HWC_NUM_DISPLAY_TYPES; disp_id++) {
- if (bit_mask_display_type[disp_id]) {
- SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
- if (hwc_display_[disp_id]) {
- error = hwc_display_[disp_id]->SetMaxMixerStages(max_mixer_stages);
- if (error != kErrorNone) {
- status = -EINVAL;
- continue;
- }
- } else {
- DLOGW("Display = %d is not connected.", disp_id);
- status = (status)? status : -ENODEV; // Return higher priority error.
- continue;
- }
+ for (uint32_t i = 0; i < 32 && bit_mask_display_type[i]; i++) {
+ int disp_idx = GetDisplayIndex(INT(i));
+ if (disp_idx == -1) {
+ continue;
+ }
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
+ auto &hwc_display = hwc_display_[disp_idx];
+ if (!hwc_display) {
+ DLOGW("Display = %d is not connected.", disp_idx);
+ status = (status)? status : -ENODEV; // Return higher priority error.
+ continue;
+ }
+
+ error = hwc_display->SetMaxMixerStages(max_mixer_stages);
+ if (error != kErrorNone) {
+ status = -EINVAL;
}
}
@@ -1448,24 +1488,22 @@
uint32_t bit_mask_layer_type = UINT32(input_parcel->readInt32());
android::status_t status = 0;
- for (uint32_t disp_id = HWC_DISPLAY_PRIMARY; disp_id < HWC_NUM_DISPLAY_TYPES; disp_id++) {
- if (bit_mask_display_type[disp_id]) {
- SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
- if (hwc_display_[disp_id]) {
- HWC2::Error error;
- error = hwc_display_[disp_id]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
- if (HWC2::Error::None != error) {
- if (HWC2::Error::NoResources == error)
- status = -ENOMEM;
- else
- status = -EINVAL;
- continue;
- }
- } else {
- DLOGW("Display = %d is not connected.", disp_id);
- status = (status)? status : -ENODEV; // Return higher priority error.
- continue;
- }
+ for (uint32_t i = 0; i < 32 && bit_mask_display_type[i]; i++) {
+ int disp_idx = GetDisplayIndex(INT(i));
+ if (disp_idx == -1) {
+ continue;
+ }
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
+ auto &hwc_display = hwc_display_[disp_idx];
+ if (!hwc_display) {
+ DLOGW("Display = %d is not connected.", disp_idx);
+ status = (status)? status : -ENODEV; // Return higher priority error.
+ continue;
+ }
+
+ HWC2::Error error = hwc_display->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
+ if (error != HWC2::Error::None) {
+ status = (HWC2::Error::NoResources == error) ? -ENOMEM : -EINVAL;
}
}
@@ -1499,11 +1537,18 @@
}
android::status_t HWCSession::SetColorModeOverride(const android::Parcel *input_parcel) {
- auto display = static_cast<hwc2_display_t >(input_parcel->readInt32());
+ int display = static_cast<int>(input_parcel->readInt32());
auto mode = static_cast<ColorMode>(input_parcel->readInt32());
auto device = static_cast<hwc2_device_t *>(this);
- auto err = CallDisplayFunction(device, display, &HWCDisplay::SetColorMode, mode);
+ int disp_idx = GetDisplayIndex(display);
+ if (disp_idx == -1) {
+ DLOGE("Invalid display = %d", display);
+ return -EINVAL;
+ }
+
+ auto err = CallDisplayFunction(device, static_cast<hwc2_display_t>(disp_idx),
+ &HWCDisplay::SetColorMode, mode);
if (err != HWC2_ERROR_NONE)
return -EINVAL;
@@ -1525,11 +1570,18 @@
return 0;
}
android::status_t HWCSession::SetColorModeById(const android::Parcel *input_parcel) {
- auto display = static_cast<hwc2_display_t >(input_parcel->readInt32());
+ int display = static_cast<int >(input_parcel->readInt32());
auto mode = input_parcel->readInt32();
auto device = static_cast<hwc2_device_t *>(this);
- auto err = CallDisplayFunction(device, display, &HWCDisplay::SetColorModeById, mode);
+ int disp_idx = GetDisplayIndex(display);
+ if (disp_idx == -1) {
+ DLOGE("Invalid display = %d", display);
+ return -EINVAL;
+ }
+
+ auto err = CallDisplayFunction(device, static_cast<hwc2_display_t>(disp_idx),
+ &HWCDisplay::SetColorModeById, mode);
if (err != HWC2_ERROR_NONE)
return -EINVAL;
@@ -1606,7 +1658,7 @@
// Read display_id, payload_size and payload from in_parcel.
ret = HWCColorManager::CreatePayloadFromParcel(*input_parcel, &display_id, &req_payload);
if (!ret) {
- if ((display_id >= HWC_NUM_DISPLAY_TYPES) || !hwc_display_[display_id]) {
+ if (display_id >= kNumDisplays || !hwc_display_[display_id]) {
DLOGW("Invalid display id or display = %d is not connected.", display_id);
ret = -ENODEV;
}
@@ -1722,26 +1774,17 @@
return ret;
}
-void HWCSession::UEventHandler(const char *uevent_data, int length) {
- if (strcasestr(uevent_data, HWC_UEVENT_SWITCH_HDMI)) {
- DLOGI("Uevent HDMI = %s", uevent_data);
- int connected = GetEventValue(uevent_data, length, "SWITCH_STATE=");
- if (connected >= 0) {
- DLOGI("HDMI = %s", connected ? "connected" : "disconnected");
- if (HotPlugHandler(connected) == -1) {
- DLOGE("Failed handling Hotplug = %s", connected ? "connected" : "disconnected");
- }
+int GetEventValue(const char *uevent_data, int length, const char *event_info) {
+ const char *iterator_str = uevent_data;
+ while (((iterator_str - uevent_data) <= length) && (*iterator_str)) {
+ const char *pstr = strstr(iterator_str, event_info);
+ if (pstr != NULL) {
+ return (atoi(iterator_str + strlen(event_info)));
}
- } else if (strcasestr(uevent_data, HWC_UEVENT_GRAPHICS_FB0)) {
- DLOGI("Uevent FB0 = %s", uevent_data);
- int panel_reset = GetEventValue(uevent_data, length, "PANEL_ALIVE=");
- if (panel_reset == 0) {
- Refresh(0);
- reset_panel_ = true;
- }
- } else if (strcasestr(uevent_data, HWC_UEVENT_DRM_EXT_HOTPLUG)) {
- HandleExtHPD(uevent_data, length);
+ iterator_str += strlen(iterator_str) + 1;
}
+
+ return -1;
}
const char *GetTokenValue(const char *uevent_data, int length, const char *token) {
@@ -1761,46 +1804,41 @@
return pstr;
}
-void HWCSession::HandleExtHPD(const char *uevent_data, int length) {
- const char *pstr = GetTokenValue(uevent_data, length, "name=");
- if (!pstr || (strncmp(pstr, "DP-1", strlen("DP-1")) != 0)) {
+void HWCSession::UEventHandler(const char *uevent_data, int length) {
+ if (strcasestr(uevent_data, HWC_UEVENT_GRAPHICS_FB0)) {
+ DLOGI("Uevent FB0 = %s", uevent_data);
+ int panel_reset = GetEventValue(uevent_data, length, "PANEL_ALIVE=");
+ if (panel_reset == 0) {
+ Refresh(0);
+ reset_panel_ = true;
+ }
return;
}
- pstr = GetTokenValue(uevent_data, length, "status=");
- if (pstr) {
- bool connected = false;
- hpd_bpp_ = 0;
- hpd_pattern_ = 0;
- if (strncmp(pstr, "connected", strlen("connected")) == 0) {
- connected = true;
- }
- int bpp = GetEventValue(uevent_data, length, "bpp=");
- int pattern = GetEventValue(uevent_data, length, "pattern=");
- if (bpp >=0 && pattern >= 0) {
- hpd_bpp_ = bpp;
- hpd_pattern_ = pattern;
+ if (strcasestr(uevent_data, HWC_UEVENT_DRM_EXT_HOTPLUG)) {
+ // MST hotplug will not carry connection status/test pattern etc.
+ // Pluggable display handler will check all connection status' and take action accordingly.
+ const char *str_status = GetTokenValue(uevent_data, length, "status=");
+ const char *str_mst = GetTokenValue(uevent_data, length, "MST_HOTPLUG=");
+ if (!str_status && !str_mst) {
+ return;
}
- DLOGI("Recived Ext HPD, connected:%d status=%s bpp = %d pattern =%d ",
- connected, pstr, hpd_bpp_, hpd_pattern_);
- HotPlugHandler(connected);
+ hpd_bpp_ = GetEventValue(uevent_data, length, "bpp=");
+ hpd_pattern_ = GetEventValue(uevent_data, length, "pattern=");
+ DLOGI("Uevent = %s, bpp = %d, pattern = %d", uevent_data, hpd_bpp_, hpd_pattern_);
+ if (CreatePluggableDisplays(true)) {
+ DLOGE("Could not handle hotplug. Event dropped.");
+ }
+
+ if (str_status) {
+ bool connected = (strncmp(str_status, "connected", strlen("connected")) == 0);
+ DLOGI("Connected = %d", connected);
+ qservice_->onHdmiHotplug(INT(connected));
+ }
}
}
-int HWCSession::GetEventValue(const char *uevent_data, int length, const char *event_info) {
- const char *iterator_str = uevent_data;
- while (((iterator_str - uevent_data) <= length) && (*iterator_str)) {
- const char *pstr = strstr(iterator_str, event_info);
- if (pstr != NULL) {
- return (atoi(iterator_str + strlen(event_info)));
- }
- iterator_str += strlen(iterator_str) + 1;
- }
-
- return -1;
-}
-
void HWCSession::ResetPanel() {
HWC2::Error status = HWC2::Error::None;
@@ -1825,116 +1863,6 @@
reset_panel_ = false;
}
-int HWCSession::HotPlugHandler(bool connected) {
- int status = 0;
- bool notify_hotplug = false;
- std :: bitset < kSecureMax > secure_sessions = 0;
-
- // 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 {
- // 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_) {
- SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
- if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
- status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetState(connected);
- } else {
- status = CreateExternalDisplay(HWC_DISPLAY_PRIMARY, 0, 0, false);
- notify_hotplug = true;
- }
- break;
- }
-
- {
- SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
- // Primary display must be connected for HDMI as secondary cases.
- if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
- DLOGE("Primary display is not connected.");
- return -1;
- }
- hwc_display_[HWC_DISPLAY_PRIMARY]->ResetValidation();
- hwc_display_[HWC_DISPLAY_PRIMARY]->GetActiveSecureSession(&secure_sessions);
- hotplug_pending_event_ = kHotPlugNone;
- if (secure_sessions[kSecureDisplay]) {
- hotplug_pending_event_ = connected ? kHotPlugConnect : kHotPlugDisconnect;
- notify_hotplug = connected ? false : true;
- break;
- }
- }
-
- if (connected) {
- SCOPE_LOCK(locker_[HWC_DISPLAY_EXTERNAL]);
- Locker::ScopeLock lock_v(locker_[HWC_DISPLAY_VIRTUAL]);
- // 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.
- if (!hwc_display_[HWC_DISPLAY_VIRTUAL]) {
- status = ConnectDisplay(HWC_DISPLAY_EXTERNAL);
- if (status) {
- return status;
- }
- notify_hotplug = true;
- } else {
- DLOGI("Virtual display is connected, pending connection");
- hotplug_pending_event_ = kHotPlugConnect;
- }
- } else {
- SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_EXTERNAL]);
- if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
- notify_hotplug = true;
- }
- }
- } while (0);
-
- if (connected) {
- // In connect case, we send hotplug after we create display
- Refresh(0);
-
- 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);
- }
- if (notify_hotplug) {
- HotPlug(hdmi_is_primary_ ? HWC_DISPLAY_PRIMARY : HWC_DISPLAY_EXTERNAL,
- HWC2::Connection::Connected);
- }
- } else {
- // In disconnect case, we notify hotplug first to let the listener state update happen first
- // Then we can destroy the underlying display object
- if (notify_hotplug) {
- HotPlug(hdmi_is_primary_ ? HWC_DISPLAY_PRIMARY : HWC_DISPLAY_EXTERNAL,
- HWC2::Connection::Disconnected);
- }
- Refresh(0);
- if (!hdmi_is_primary_) {
- uint32_t vsync_period = UINT32(GetVsyncPeriod(HWC_DISPLAY_PRIMARY));
- usleep(vsync_period * 2 / 1000);
- }
- // Now disconnect the display
- {
- SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_EXTERNAL]);
- // 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 secure display session is in progress, defer disconnection of external display
- if (hwc_display_[HWC_DISPLAY_EXTERNAL] && !secure_sessions[kSecureDisplay]) {
- status = DisconnectDisplay(HWC_DISPLAY_EXTERNAL);
- }
- }
- }
-
- // notify client
-
- qservice_->onHdmiHotplug(INT(connected));
-
- return 0;
-}
-
int HWCSession::GetVsyncPeriod(int disp) {
SCOPE_LOCK(locker_[disp]);
// default value
@@ -1950,18 +1878,19 @@
android::status_t HWCSession::GetVisibleDisplayRect(const android::Parcel *input_parcel,
android::Parcel *output_parcel) {
- int dpy = input_parcel->readInt32();
- if (dpy < HWC_DISPLAY_PRIMARY || dpy >= HWC_NUM_DISPLAY_TYPES) {
+ int disp_idx = GetDisplayIndex(input_parcel->readInt32());
+ if (disp_idx == -1) {
+ DLOGE("Invalid display = %d", disp_idx);
return android::BAD_VALUE;
}
- SEQUENCE_WAIT_SCOPE_LOCK(locker_[dpy]);
- if (!hwc_display_[dpy]) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
+ if (!hwc_display_[disp_idx]) {
return android::NO_INIT;
}
hwc_rect_t visible_rect = {0, 0, 0, 0};
- int error = hwc_display_[dpy]->GetVisibleDisplayRect(&visible_rect);
+ int error = hwc_display_[disp_idx]->GetVisibleDisplayRect(&visible_rect);
if (error < 0) {
return error;
}
@@ -1992,36 +1921,295 @@
}
}
-int HWCSession::CreateExternalDisplay(int disp_id, uint32_t primary_width,
- uint32_t primary_height, bool use_primary_res) {
- uint32_t panel_bpp = 0;
- uint32_t pattern_type = 0;
+int HWCSession::CreatePrimaryDisplay() {
+ int status = -EINVAL;
+ HWDisplaysInfo hw_displays_info = {};
- if (GetDriverType() == DriverType::FB) {
- qdutils::getDPTestConfig(&panel_bpp, &pattern_type);
- } else {
- panel_bpp = static_cast<uint32_t>(hpd_bpp_);
- pattern_type = static_cast<uint32_t>(hpd_pattern_);
+ DisplayError error = core_intf_->GetDisplaysStatus(&hw_displays_info);
+ if (error != kErrorNone) {
+ DLOGE("Failed to get connected display list. Error = %d", error);
+ return status;
}
- if (panel_bpp && pattern_type) {
- return HWCDisplayExternalTest::Create(core_intf_, &buffer_allocator_, &callbacks_, this,
- qservice_, panel_bpp, pattern_type,
- &hwc_display_[disp_id]);
+ for (auto &iter : hw_displays_info) {
+ auto &info = iter.second;
+ if (!info.is_primary) {
+ continue;
+ }
+
+ // todo (user): If primary display is not connected (e.g. hdmi as primary), a NULL display
+ // need to be created. SF expects primary display hotplug during callback registration unlike
+ // previous implementation where first hotplug could be notified anytime.
+ if (!info.is_connected) {
+ DLOGE("Primary display is not connected. Not supported at present.");
+ break;
+ }
+
+ auto hwc_display = &hwc_display_[HWC_DISPLAY_PRIMARY];
+ hwc2_display_t client_id = map_info_primary_.client_id;
+
+ DLOGI("Create primary display type = %d, sdm id = %d, client id = %d", info.display_type,
+ info.display_id, client_id);
+ if (info.display_type == kBuiltIn) {
+ status = HWCDisplayBuiltIn::Create(core_intf_, &buffer_allocator_, &callbacks_, this,
+ qservice_, client_id, info.display_id, hwc_display);
+ } else if (info.display_type == kPluggable) {
+ status = HWCDisplayPluggable::Create(core_intf_, &buffer_allocator_, &callbacks_, this,
+ qservice_, client_id, info.display_id, 0, 0, false,
+ hwc_display);
+ } else {
+ DLOGE("Spurious primary display type = %d", info.display_type);
+ break;
+ }
+
+ if (!status) {
+ DLOGI("Primary display created.");
+ map_info_primary_.disp_type = info.display_type;
+ map_info_primary_.sdm_id = info.display_id;
+
+ color_mgr_ = HWCColorManager::CreateColorManager(&buffer_allocator_);
+ if (!color_mgr_) {
+ DLOGW("Failed to load HWCColorManager.");
+ }
+ } else {
+ DLOGE("Primary display creation failed.");
+ }
+
+ // Primary display is found, no need to parse more.
+ break;
}
- return HWCDisplayExternal::Create(core_intf_, &buffer_allocator_, &callbacks_, this,
- primary_width, primary_height, qservice_, use_primary_res,
- &hwc_display_[disp_id]);
+ return status;
}
-#ifdef DISPLAY_CONFIG_1_1
-// Methods from ::vendor::hardware::display::config::V1_1::IDisplayConfig follow.
-Return<int32_t> HWCSession::setDisplayAnimating(uint64_t display_id, bool animating ) {
- return CallDisplayFunction(static_cast<hwc2_device_t *>(this), display_id,
- &HWCDisplay::SetDisplayAnimating, animating);
+int HWCSession::CreateBuiltInDisplays() {
+ HWDisplaysInfo hw_displays_info = {};
+
+ DisplayError error = core_intf_->GetDisplaysStatus(&hw_displays_info);
+ if (error != kErrorNone) {
+ DLOGE("Failed to get connected display list. Error = %d", error);
+ return -EINVAL;
+ }
+
+ int status = 0;
+ size_t next_builtin_index = 0;
+ for (auto &iter : hw_displays_info) {
+ auto &info = iter.second;
+
+ // Do not recreate primary display.
+ if (info.is_primary || info.display_type != kBuiltIn) {
+ continue;
+ }
+
+ if (next_builtin_index >= map_info_builtin_.size()) {
+ DLOGW("Insufficient builtin display slots. All displays could not be created.");
+ return 0;
+ }
+
+ DisplayMapInfo &map_info = map_info_builtin_[next_builtin_index];
+ hwc2_display_t client_id = map_info.client_id;
+
+ // Lock confined to this scope
+ {
+ SCOPE_LOCK(locker_[client_id]);
+
+ DLOGI("Create builtin display, sdm id = %d, client id = %d", info.display_id, client_id);
+ status = HWCDisplayBuiltIn::Create(core_intf_, &buffer_allocator_, &callbacks_, this,
+ qservice_, client_id, info.display_id,
+ &hwc_display_[client_id]);
+ if (!status) {
+ DLOGI("Builtin display created.");
+ map_info.disp_type = info.display_type;
+ map_info.sdm_id = info.display_id;
+ } else {
+ DLOGE("Builtin display creation failed.");
+ break;
+ }
+ }
+
+ callbacks_.Hotplug(client_id, HWC2::Connection::Connected);
+ }
+
+ return status;
}
-#endif
+
+int HWCSession::CreatePluggableDisplays(bool delay_hotplug) {
+ if (!primary_ready_) {
+ DLOGI("Primary display is not ready. Connect displays later if any.");
+ return 0;
+ }
+
+ HWDisplaysInfo hw_displays_info = {};
+
+ DisplayError error = core_intf_->GetDisplaysStatus(&hw_displays_info);
+ if (error != kErrorNone) {
+ DLOGE("Failed to get connected display list. Error = %d", error);
+ return -EINVAL;
+ }
+
+ int status = HandleDisconnectedDisplays(&hw_displays_info);
+ if (status) {
+ DLOGE("All displays could not be disconnected.");
+ return status;
+ }
+
+ status = HandleConnectedDisplays(&hw_displays_info, delay_hotplug);
+ if (status) {
+ DLOGE("All displays could not be connected.");
+ return status;
+ }
+
+ return 0;
+}
+
+int HWCSession::HandleConnectedDisplays(HWDisplaysInfo *hw_displays_info, bool delay_hotplug) {
+ int status = 0;
+ std::vector<hwc2_display_t> pending_hotplugs = {};
+
+ for (auto &iter : *hw_displays_info) {
+ auto &info = iter.second;
+
+ // Do not recreate primary display or if display is not connected.
+ if (info.is_primary || info.display_type != kPluggable || !info.is_connected) {
+ continue;
+ }
+
+ // find an empty slot to create display.
+ for (auto &map_info : map_info_pluggable_) {
+ hwc2_display_t client_id = map_info.client_id;
+
+ // Lock confined to this scope
+ {
+ SCOPE_LOCK(locker_[client_id]);
+ auto &hwc_display = hwc_display_[client_id];
+ if (hwc_display) {
+ // Display is already connected.
+ continue;
+ }
+
+ DLOGI("Create pluggable display, sdm id = %d, client id = %d", info.display_id, client_id);
+
+ // Test pattern generation ?
+ map_info.test_pattern = (hpd_bpp_ > 0) && (hpd_pattern_ > 0);
+ if (!map_info.test_pattern) {
+ status = HWCDisplayPluggable::Create(core_intf_, &buffer_allocator_, &callbacks_, this,
+ qservice_, client_id, info.display_id, 0, 0, false,
+ &hwc_display);
+ } else {
+ status = HWCDisplayPluggableTest::Create(core_intf_, &buffer_allocator_, &callbacks_,
+ this, qservice_, client_id, info.display_id,
+ UINT32(hpd_bpp_), UINT32(hpd_pattern_),
+ &hwc_display);
+ }
+
+ if (status) {
+ DLOGE("Pluggable display creation failed.");
+ return status;
+ }
+
+ DLOGI("Created pluggable display successfully.");
+ }
+
+ map_info.disp_type = info.display_type;
+ map_info.sdm_id = info.display_id;
+
+ pending_hotplugs.push_back((hwc2_display_t)client_id);
+
+ // Display is created for this sdm id, move to next connected display.
+ break;
+ }
+ }
+
+ // No display was created.
+ if (!pending_hotplugs.size()) {
+ return 0;
+ }
+
+ // Primary display needs revalidation
+ {
+ SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+ hwc_display_[HWC_DISPLAY_PRIMARY]->ResetValidation();
+ }
+
+ Refresh(0);
+
+ // Do not sleep if this method is called from client thread.
+ if (delay_hotplug) {
+ // wait sufficient time to ensure resources are available for new display connection.
+ usleep(UINT32(GetVsyncPeriod(HWC_DISPLAY_PRIMARY)) * 2 / 1000);
+ }
+
+ for (auto client_id : pending_hotplugs) {
+ DLOGI("Notify hotplug connected: client id = %d", client_id);
+ callbacks_.Hotplug(client_id, HWC2::Connection::Connected);
+ }
+
+ return 0;
+}
+
+int HWCSession::HandleDisconnectedDisplays(HWDisplaysInfo *hw_displays_info) {
+ // Destroy pluggable displays which were connected earlier but got disconnected now.
+ for (auto &map_info : map_info_pluggable_) {
+ bool disconnect = true; // disconnect in case display id is not found in list.
+
+ for (auto &iter : *hw_displays_info) {
+ auto &info = iter.second;
+ if (info.display_id != map_info.sdm_id) {
+ continue;
+ }
+ if (info.is_connected) {
+ disconnect = false;
+ }
+ }
+
+ if (disconnect) {
+ DestroyDisplay(&map_info);
+ }
+ }
+
+ return 0;
+}
+
+void HWCSession::DestroyDisplay(DisplayMapInfo *map_info) {
+ hwc2_display_t client_id = map_info->client_id;
+ int notify_hotplug = false;
+
+ // Lock confined to this scope. Do not notify hotplug while holding a lock.
+ {
+ SCOPE_LOCK(locker_[client_id]);
+
+ auto &hwc_display = hwc_display_[client_id];
+ if (!hwc_display) {
+ return;
+ }
+
+ DLOGI("Destroy display type = %d, client id = %d", map_info->disp_type, client_id);
+ switch (map_info->disp_type) {
+ case kBuiltIn:
+ HWCDisplayBuiltIn::Destroy(hwc_display);
+ break;
+
+ case kPluggable:
+ if (!map_info->test_pattern) {
+ HWCDisplayPluggable::Destroy(hwc_display);
+ } else {
+ HWCDisplayPluggableTest::Destroy(hwc_display);
+ }
+ notify_hotplug = true;
+ break;
+
+ default:
+ HWCDisplayVirtual::Destroy(hwc_display);
+ break;
+ }
+ hwc_display = nullptr;
+ map_info->Reset();
+ }
+
+ if (notify_hotplug) {
+ callbacks_.Hotplug(client_id, HWC2::Connection::Disconnected);
+ }
+}
HWC2::Error HWCSession::ValidateDisplayInternal(hwc2_display_t display, uint32_t *out_num_types,
uint32_t *out_num_requests) {
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index 119c931..7bcfe00 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -20,7 +20,9 @@
#ifndef __HWC_SESSION_H__
#define __HWC_SESSION_H__
-#ifdef DISPLAY_CONFIG_1_1
+#ifdef DISPLAY_CONFIG_1_2
+#include <vendor/display/config/1.2/IDisplayConfig.h>
+#elif DISPLAY_CONFIG_1_1
#include <vendor/display/config/1.1/IDisplayConfig.h>
#else
#include <vendor/display/config/1.0/IDisplayConfig.h>
@@ -28,20 +30,26 @@
#include <core/core_interface.h>
#include <utils/locker.h>
+#include <qd_utils.h>
+#include <display_config.h>
+#include <vector>
#include "hwc_callbacks.h"
#include "hwc_layers.h"
#include "hwc_display.h"
-#include "hwc_display_primary.h"
-#include "hwc_display_external.h"
+#include "hwc_display_builtin.h"
+#include "hwc_display_pluggable.h"
#include "hwc_display_virtual.h"
+#include "hwc_display_pluggable_test.h"
#include "hwc_color_manager.h"
#include "hwc_socket_handler.h"
#include "hwc_display_event_handler.h"
namespace sdm {
-#ifdef DISPLAY_CONFIG_1_1
+#ifdef DISPLAY_CONFIG_1_2
+using vendor::display::config::V1_2::IDisplayConfig;
+#elif DISPLAY_CONFIG_1_1
using vendor::display::config::V1_1::IDisplayConfig;
#else
using ::vendor::display::config::V1_0::IDisplayConfig;
@@ -80,6 +88,12 @@
class HWCSession : hwc2_device_t, HWCUEventListener, IDisplayConfig, public qClient::BnQClient,
public HWCDisplayEventHandler {
public:
+ static const int kNumBuiltIn = 4;
+ static const int kNumPluggable = 4;
+ static const int kNumVirtual = 4;
+ // Add 1 primary display which can be either a builtin or pluggable.
+ static const int kNumDisplays = 1 + kNumBuiltIn + kNumPluggable + kNumVirtual;
+
struct HWCModuleMethods : public hw_module_methods_t {
HWCModuleMethods() { hw_module_methods_t::open = HWCSession::Open; }
};
@@ -93,7 +107,8 @@
explicit HWCSession(const hw_module_t *module);
int Init();
int Deinit();
- HWC2::Error CreateVirtualDisplayObject(uint32_t width, uint32_t height, int32_t *format);
+ HWC2::Error CreateVirtualDisplayObj(uint32_t width, uint32_t height, int32_t *format,
+ hwc2_display_t *out_display_id);
template <typename... Args>
static int32_t CallDisplayFunction(hwc2_device_t *device, hwc2_display_t display,
@@ -102,7 +117,7 @@
return HWC2_ERROR_BAD_PARAMETER;
}
- if (display >= HWC_NUM_DISPLAY_TYPES) {
+ if (display >= kNumDisplays) {
return HWC2_ERROR_BAD_DISPLAY;
}
@@ -124,7 +139,7 @@
return HWC2_ERROR_BAD_PARAMETER;
}
- if (display >= HWC_NUM_DISPLAY_TYPES) {
+ if (display >= kNumDisplays) {
return HWC2_ERROR_BAD_DISPLAY;
}
@@ -181,9 +196,22 @@
// HWCDisplayEventHandler
virtual void DisplayPowerReset();
- static Locker locker_[HWC_NUM_DISPLAY_TYPES];
+ static Locker locker_[kNumDisplays];
private:
+ struct DisplayMapInfo {
+ hwc2_display_t client_id = kNumDisplays; // mapped sf id for this display
+ int32_t sdm_id = -1; // sdm id for this display
+ sdm:: DisplayType disp_type = kDisplayTypeMax; // sdm display type
+ bool test_pattern = false; // display will show test pattern
+ void Reset() {
+ // Do not clear client id
+ sdm_id = -1;
+ disp_type = kDisplayTypeMax;
+ test_pattern = false;
+ }
+ };
+
static const int kExternalConnectionTimeoutMs = 500;
static const int kPartialUpdateControlTimeoutMs = 100;
@@ -196,12 +224,15 @@
// Uevent handler
virtual void UEventHandler(const char *uevent_data, int length);
- int GetEventValue(const char *uevent_data, int length, const char *event_info);
- void HandleExtHPD(const char *uevent_data, int length);
- int HotPlugHandler(bool connected);
void ResetPanel();
- int32_t ConnectDisplay(int disp);
- int DisconnectDisplay(int disp);
+ void InitDisplaySlots();
+ int GetDisplayIndex(int dpy);
+ int CreatePrimaryDisplay();
+ int CreateBuiltInDisplays();
+ int CreatePluggableDisplays(bool delay_hotplug);
+ int HandleConnectedDisplays(HWDisplaysInfo *hw_displays_info, bool delay_hotplug);
+ int HandleDisconnectedDisplays(HWDisplaysInfo *hw_displays_info);
+ void DestroyDisplay(DisplayMapInfo *map_info);
int GetVsyncPeriod(int disp);
int32_t GetConfigCount(int disp_id, uint32_t *count);
int32_t GetActiveConfigIndex(int disp_id, uint32_t *config);
@@ -211,8 +242,6 @@
int32_t SetSecondaryDisplayStatus(int disp_id, HWCDisplay::DisplayStatus status);
int32_t GetPanelBrightness(int *level);
int32_t MinHdcpEncryptionLevelChanged(int disp_id, uint32_t min_enc_level);
- int32_t CreateExternalDisplay(int disp_id, uint32_t primary_width, uint32_t primary_height,
- bool use_primary_res);
// service methods
void StartServices();
@@ -248,6 +277,11 @@
#ifdef DISPLAY_CONFIG_1_1
Return<int32_t> setDisplayAnimating(uint64_t display_id, bool animating) override;
#endif
+ // Methods from ::android::hardware::display::config::V1_2::IDisplayConfig follow.
+#ifdef DISPLAY_CONFIG_1_2
+ Return<int32_t> setDisplayIndex(IDisplayConfig::DisplayTypeExt disp_type,
+ uint32_t base, uint32_t count) override;
+#endif
// QClient methods
virtual android::status_t notifyCallback(uint32_t command, const android::Parcel *input_parcel,
@@ -259,8 +293,8 @@
android::status_t ConfigureRefreshRate(const android::Parcel *input_parcel);
android::status_t QdcmCMDHandler(const android::Parcel *input_parcel,
android::Parcel *output_parcel);
- android::status_t HandleGetDisplayAttributesForConfig(const android::Parcel *input_parcel,
- android::Parcel *output_parcel);
+ android::status_t GetDisplayAttributesForConfig(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel);
android::status_t GetVisibleDisplayRect(const android::Parcel *input_parcel,
android::Parcel *output_parcel);
android::status_t SetMixerResolution(const android::Parcel *input_parcel);
@@ -281,12 +315,18 @@
void HandleHotplugPending(hwc2_display_t disp_id, int retire_fence);
CoreInterface *core_intf_ = nullptr;
- HWCDisplay *hwc_display_[HWC_NUM_DISPLAY_TYPES] = {nullptr};
+ HWCDisplay *hwc_display_[kNumDisplays] = {nullptr};
HWCCallbacks callbacks_;
HWCBufferAllocator buffer_allocator_;
HWCBufferSyncHandler buffer_sync_handler_;
HWCColorManager *color_mgr_ = nullptr;
+ DisplayMapInfo map_info_primary_; // Primary display (either builtin or pluggable)
+ std::vector<DisplayMapInfo> map_info_builtin_; // Builtin displays excluding primary
+ std::vector<DisplayMapInfo> map_info_pluggable_; // Pluggable displays excluding primary
+ std::vector<DisplayMapInfo> map_info_virtual_; // Virtual displays
bool reset_panel_ = false;
+ bool primary_ready_ = false;
+ bool client_connected_ = false;
bool new_bw_mode_ = false;
bool need_invalidate_ = false;
int bw_mode_release_fd_ = -1;
diff --git a/sdm/libs/hwc2/hwc_session_services.cpp b/sdm/libs/hwc2/hwc_session_services.cpp
index 5a595e3..d1fb02a 100644
--- a/sdm/libs/hwc2/hwc_session_services.cpp
+++ b/sdm/libs/hwc2/hwc_session_services.cpp
@@ -30,6 +30,7 @@
#include <core/buffer_allocator.h>
#include <utils/debug.h>
#include <sync/sync.h>
+#include <vector>
#include "hwc_buffer_sync_handler.h"
#include "hwc_session.h"
@@ -52,13 +53,13 @@
int MapDisplayType(IDisplayConfig::DisplayType dpy) {
switch (dpy) {
case IDisplayConfig::DisplayType::DISPLAY_PRIMARY:
- return HWC_DISPLAY_PRIMARY;
+ return qdutils::DISPLAY_PRIMARY;
case IDisplayConfig::DisplayType::DISPLAY_EXTERNAL:
- return HWC_DISPLAY_EXTERNAL;
+ return qdutils::DISPLAY_EXTERNAL;
case IDisplayConfig::DisplayType::DISPLAY_VIRTUAL:
- return HWC_DISPLAY_VIRTUAL;
+ return qdutils::DISPLAY_VIRTUAL;
default:
break;
@@ -94,36 +95,36 @@
int32_t error = -EINVAL;
bool connected = false;
int disp_id = MapDisplayType(dpy);
+ int disp_idx = GetDisplayIndex(disp_id);
- if (disp_id < HWC_DISPLAY_PRIMARY || disp_id >= HWC_NUM_DISPLAY_TYPES) {
- _hidl_cb(error, connected);
- return Void();
+ if (disp_idx == -1) {
+ DLOGE("Invalid display = %d", disp_id);
+ } else {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
+ connected = hwc_display_[disp_idx];
+ error = 0;
}
-
- SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
-
- connected = hwc_display_[disp_id];
- error = 0;
-
_hidl_cb(error, connected);
+
return Void();
}
int32_t HWCSession::SetSecondaryDisplayStatus(int disp_id, HWCDisplay::DisplayStatus status) {
- if (disp_id < HWC_DISPLAY_PRIMARY || disp_id >= HWC_NUM_DISPLAY_TYPES) {
+ int disp_idx = GetDisplayIndex(disp_id);
+ if (disp_idx == -1) {
DLOGE("Invalid display = %d", disp_id);
return -EINVAL;
}
- SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
- DLOGI("Display = %d, Status = %d", disp_id, status);
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
+ DLOGI("Display = %d, Status = %d", disp_idx, status);
- if (disp_id == HWC_DISPLAY_PRIMARY) {
+ if (disp_idx == qdutils::DISPLAY_PRIMARY) {
DLOGE("Not supported for this display");
- } else if (!hwc_display_[disp_id]) {
+ } else if (!hwc_display_[disp_idx]) {
DLOGW("Display is not connected");
} else {
- return hwc_display_[disp_id]->SetDisplayStatus(status);
+ return hwc_display_[disp_idx]->SetDisplayStatus(status);
}
return -EINVAL;
@@ -146,13 +147,13 @@
switch (op) {
case IDisplayConfig::DisplayDynRefreshRateOp::DISABLE_METADATA_DYN_REFRESH_RATE:
- return hwc_display->Perform(HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, false);
+ return hwc_display->Perform(HWCDisplayBuiltIn::SET_METADATA_DYN_REFRESH_RATE, false);
case IDisplayConfig::DisplayDynRefreshRateOp::ENABLE_METADATA_DYN_REFRESH_RATE:
- return hwc_display->Perform(HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, true);
+ return hwc_display->Perform(HWCDisplayBuiltIn::SET_METADATA_DYN_REFRESH_RATE, true);
case IDisplayConfig::DisplayDynRefreshRateOp::SET_BINDER_DYN_REFRESH_RATE:
- return hwc_display->Perform(HWCDisplayPrimary::SET_BINDER_DYN_REFRESH_RATE, refreshRate);
+ return hwc_display->Perform(HWCDisplayBuiltIn::SET_BINDER_DYN_REFRESH_RATE, refreshRate);
default:
DLOGW("Invalid operation %d", op);
@@ -163,14 +164,16 @@
}
int32_t HWCSession::GetConfigCount(int disp_id, uint32_t *count) {
- if (disp_id < 0) {
+ int disp_idx = GetDisplayIndex(disp_id);
+ if (disp_idx == -1) {
+ DLOGE("Invalid display = %d", disp_id);
return -EINVAL;
}
- SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
- if (hwc_display_[disp_id]) {
- return hwc_display_[disp_id]->GetDisplayConfigCount(count);
+ if (hwc_display_[disp_idx]) {
+ return hwc_display_[disp_idx]->GetDisplayConfigCount(count);
}
return -EINVAL;
@@ -187,14 +190,16 @@
}
int32_t HWCSession::GetActiveConfigIndex(int disp_id, uint32_t *config) {
- if (disp_id < 0) {
+ int disp_idx = GetDisplayIndex(disp_id);
+ if (disp_idx == -1) {
+ DLOGE("Invalid display = %d", disp_id);
return -EINVAL;
}
- SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
- if (hwc_display_[disp_id]) {
- return hwc_display_[disp_id]->GetActiveDisplayConfig(config);
+ if (hwc_display_[disp_idx]) {
+ return hwc_display_[disp_idx]->GetActiveDisplayConfig(config);
}
return -EINVAL;
@@ -211,14 +216,16 @@
}
int32_t HWCSession::SetActiveConfigIndex(int disp_id, uint32_t config) {
- if (disp_id < 0) {
+ int disp_idx = GetDisplayIndex(disp_id);
+ if (disp_idx == -1) {
+ DLOGE("Invalid display = %d", disp_id);
return -EINVAL;
}
- SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
int32_t error = -EINVAL;
- if (hwc_display_[disp_id]) {
- error = hwc_display_[disp_id]->SetActiveDisplayConfig(config);
+ if (hwc_display_[disp_idx]) {
+ error = hwc_display_[disp_idx]->SetActiveDisplayConfig(config);
if (!error) {
Refresh(0);
}
@@ -237,21 +244,23 @@
int32_t error = -EINVAL;
IDisplayConfig::DisplayAttributes display_attributes = {};
int disp_id = MapDisplayType(dpy);
+ int disp_idx = GetDisplayIndex(disp_id);
- if (disp_id >= HWC_DISPLAY_PRIMARY && disp_id < HWC_NUM_DISPLAY_TYPES) {
- SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
- if (hwc_display_[disp_id]) {
- DisplayConfigVariableInfo hwc_display_attributes;
- error = hwc_display_[disp_id]->GetDisplayAttributesForConfig(static_cast<int>(configIndex),
- &hwc_display_attributes);
+ if (disp_idx == -1) {
+ DLOGE("Invalid display = %d", disp_id);
+ } else {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
+ if (hwc_display_[disp_idx]) {
+ DisplayConfigVariableInfo var_info;
+ error = hwc_display_[disp_idx]->GetDisplayAttributesForConfig(INT(configIndex), &var_info);
if (!error) {
- display_attributes.vsyncPeriod = hwc_display_attributes.vsync_period_ns;
- display_attributes.xRes = hwc_display_attributes.x_pixels;
- display_attributes.yRes = hwc_display_attributes.y_pixels;
- display_attributes.xDpi = hwc_display_attributes.x_dpi;
- display_attributes.yDpi = hwc_display_attributes.y_dpi;
+ display_attributes.vsyncPeriod = var_info.vsync_period_ns;
+ display_attributes.xRes = var_info.x_pixels;
+ display_attributes.yRes = var_info.y_pixels;
+ display_attributes.xDpi = var_info.x_dpi;
+ display_attributes.yDpi = var_info.y_dpi;
display_attributes.panelType = IDisplayConfig::DisplayPortType::DISPLAY_PORT_DEFAULT;
- display_attributes.isYuv = hwc_display_attributes.is_yuv;
+ display_attributes.isYuv = var_info.is_yuv;
}
}
}
@@ -265,7 +274,7 @@
int32_t error = -EINVAL;
if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
- error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(static_cast<int>(level));
+ error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(INT(level));
if (error) {
DLOGE("Failed to set the panel brightness = %d. Error = %d", level, error);
}
@@ -402,22 +411,23 @@
int32_t error = -EINVAL;
IDisplayConfig::DisplayHDRCapabilities hdr_caps = {};
- if (!_hidl_cb) {
- DLOGE("_hidl_cb callback not provided.");
- return Void();
- }
-
do {
- int disp_id = MapDisplayType(dpy);
- if ((disp_id < 0) || (disp_id >= HWC_NUM_DISPLAY_TYPES)) {
- DLOGE("Invalid display id = %d", disp_id);
+ if (!_hidl_cb) {
+ DLOGE("_hidl_cb callback not provided.");
break;
}
- SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
- HWCDisplay *hwc_display = hwc_display_[disp_id];
+ int disp_id = MapDisplayType(dpy);
+ int disp_idx = GetDisplayIndex(disp_id);
+ if (disp_idx == -1) {
+ DLOGE("Invalid display = %d", disp_id);
+ break;
+ }
+
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
+ HWCDisplay *hwc_display = hwc_display_[disp_idx];
if (!hwc_display) {
- DLOGW("Display = %d is not connected.", disp_id);
+ DLOGW("Display = %d is not connected.", disp_idx);
error = -ENODEV;
break;
}
@@ -442,8 +452,7 @@
float out_min_luminance = 0.0f;
if (hwc_display->GetHdrCapabilities(&out_num_types, hdr_caps.supportedHdrTypes.data(),
&out_max_luminance, &out_max_average_luminance,
- &out_min_luminance)
- == HWC2::Error::None) {
+ &out_min_luminance) == HWC2::Error::None) {
error = 0;
}
} while (false);
@@ -517,4 +526,71 @@
return Void();
}
+#ifdef DISPLAY_CONFIG_1_1
+Return<int32_t> HWCSession::setDisplayAnimating(uint64_t display_id, bool animating ) {
+ return CallDisplayFunction(static_cast<hwc2_device_t *>(this), display_id,
+ &HWCDisplay::SetDisplayAnimating, animating);
+}
+#endif
+
+#ifdef DISPLAY_CONFIG_1_2
+static const char * GetDisplayTypeName(IDisplayConfig::DisplayTypeExt disp_type) {
+ switch (disp_type) {
+ case IDisplayConfig::DisplayTypeExt::DISPLAY_BUILTIN: return "Built-in";
+ case IDisplayConfig::DisplayTypeExt::DISPLAY_PLUGGABLE: return "Pluggable";
+ case IDisplayConfig::DisplayTypeExt::DISPLAY_VIRTUAL: return "Virtual";
+ case IDisplayConfig::DisplayTypeExt::DISPLAY_PRIMARY: return "Primary";
+ default: return "Unknown";
+ }
+}
+
+Return<int32_t> HWCSession::setDisplayIndex(IDisplayConfig::DisplayTypeExt disp_type,
+ uint32_t base, uint32_t count) {
+ if (client_connected_) {
+ DLOGW("Not supported after client connection is completed.");
+ return -1;
+ }
+
+ DLOGI("%s display: base = %d, count = %d", GetDisplayTypeName(disp_type), base, count);
+
+ // Is display slots capacity smaller than what client can support?
+ if ((base + count) > kNumDisplays) {
+ DLOGE("Exceeds max supported display slots = %d", kNumDisplays);
+ return -1;
+ }
+
+ std::vector<DisplayMapInfo> *map_info_v = nullptr;
+ switch (disp_type) {
+ case IDisplayConfig::DisplayTypeExt::DISPLAY_BUILTIN:
+ map_info_v = &map_info_builtin_;
+ break;
+ case IDisplayConfig::DisplayTypeExt::DISPLAY_PLUGGABLE:
+ map_info_v = &map_info_pluggable_;
+ break;
+ case IDisplayConfig::DisplayTypeExt::DISPLAY_VIRTUAL:
+ map_info_v = &map_info_virtual_;
+ break;
+ case IDisplayConfig::DisplayTypeExt::DISPLAY_PRIMARY:
+ // nothing to do
+ return 0;
+ default:
+ return -1;
+ }
+
+ // Reset default client id for each display with a new client id in given range.
+ // Remove remaining elements as client as client can not handle these displays.
+ DLOGI("Change %s display capacity to %d", GetDisplayTypeName(disp_type), count);
+ map_info_v->resize(count);
+
+ uint32_t idx = 0;
+ for (auto &map_info : *map_info_v) {
+ map_info.client_id = base++;
+ DLOGI("Override: %s display: Index = %d, Client ID = %d",
+ GetDisplayTypeName(disp_type), idx++, map_info.client_id);
+ }
+
+ return 0;
+}
+#endif
+
} // namespace sdm