hwc2: null display mode support
Adds null display support at HWC level. HWCDisplay will internally use
DisplayNull object as display_intf_ when in null display mode via sdm
debug property
Change-Id: I160caff9c354e23e6c5849b661dc3c3bf6c41d20
CRs-Fixed: 2186932
diff --git a/sdm/libs/hwc2/display_null.cpp b/sdm/libs/hwc2/display_null.cpp
index 16f4da6..9e3dc98 100644
--- a/sdm/libs/hwc2/display_null.cpp
+++ b/sdm/libs/hwc2/display_null.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-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
@@ -33,7 +33,100 @@
namespace sdm {
-DisplayError DisplayNull::Commit(LayerStack *layer_stack) {
+DisplayError DisplayNull::Init() {
+ default_variable_config_.vsync_period_ns = 16600000;
+ default_variable_config_.x_pixels = 1080;
+ default_variable_config_.y_pixels = 1920;
+ default_variable_config_.x_dpi = 300;
+ default_variable_config_.y_dpi = 300;
+ default_variable_config_.fps = 60;
+ default_variable_config_.is_yuv = false;
+
+ return kErrorNone;
+}
+
+DisplayError DisplayNull::GetMixerResolution(uint32_t *width, uint32_t *height) {
+ if (!width || !height) {
+ return kErrorParameters;
+ }
+
+ *width = default_variable_config_.x_pixels;
+ *height = default_variable_config_.y_pixels;
+ return kErrorNone;
+}
+
+DisplayError DisplayNull::GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info) {
+ if (!variable_info) {
+ return kErrorParameters;
+ }
+
+ *variable_info = default_variable_config_;
+ return kErrorNone;
+}
+
+DisplayError DisplayNull::GetConfig(uint32_t index, DisplayConfigVariableInfo *disp_attr) {
+ if (!disp_attr) {
+ return kErrorParameters;
+ }
+
+ *disp_attr = default_variable_config_;
+ return kErrorNone;
+}
+
+DisplayError DisplayNull::GetConfig(DisplayConfigFixedInfo *fixed_info) {
+ if (!fixed_info) {
+ return kErrorParameters;
+ }
+
+ *fixed_info = default_fixed_config_;
+ return kErrorNone;
+}
+
+DisplayError DisplayNull::GetRefreshRateRange(uint32_t *min_refresh_rate,
+ uint32_t *max_refresh_rate) {
+ if (!min_refresh_rate || !max_refresh_rate) {
+ return kErrorParameters;
+ }
+
+ *min_refresh_rate = 60;
+ *max_refresh_rate = 60;
+ return kErrorNone;
+}
+
+DisplayError DisplayNull::GetActiveConfig(uint32_t *config) {
+ if (!config) {
+ return kErrorParameters;
+ }
+
+ *config = 0;
+ return kErrorNone;
+}
+
+DisplayError DisplayNull::GetNumVariableInfoConfigs(uint32_t *count) {
+ if (!count) {
+ return kErrorParameters;
+ }
+
+ *count = 1;
+ return kErrorNone;
+}
+
+DisplayError DisplayNull::Prepare(LayerStack *layer_stack) {
+ if (!layer_stack) {
+ return kErrorParameters;
+ }
+
+ for (auto layer : layer_stack->layers) {
+ layer->composition = kCompositionGPU;
+ }
+ return kErrorNone;
+}
+
+DisplayError DisplayNullExternal::Commit(LayerStack *layer_stack) {
+ if (!layer_stack) {
+ return kErrorParameters;
+ }
+
for (Layer *layer : layer_stack->layers) {
if (layer->composition != kCompositionGPUTarget) {
layer->composition = kCompositionSDE;
@@ -41,26 +134,34 @@
}
}
layer_stack->retire_fence_fd = -1;
-
return kErrorNone;
}
-DisplayError DisplayNull::GetDisplayState(DisplayState *state) {
+DisplayError DisplayNullExternal::GetDisplayState(DisplayState *state) {
+ if (!state) {
+ return kErrorParameters;
+ }
+
*state = state_;
return kErrorNone;
}
-DisplayError DisplayNull::SetDisplayState(DisplayState state) {
+DisplayError DisplayNullExternal::SetDisplayState(DisplayState state) {
state_ = state;
return kErrorNone;
}
-DisplayError DisplayNull::SetFrameBufferConfig(const DisplayConfigVariableInfo &variable_info) {
+DisplayError DisplayNullExternal::SetFrameBufferConfig(const DisplayConfigVariableInfo
+ &variable_info) {
fb_config_ = variable_info;
return kErrorNone;
}
-DisplayError DisplayNull::GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info) {
+DisplayError DisplayNullExternal::GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info) {
+ if (!variable_info) {
+ return kErrorParameters;
+ }
+
*variable_info = fb_config_;
return kErrorNone;
}
diff --git a/sdm/libs/hwc2/display_null.h b/sdm/libs/hwc2/display_null.h
index f6c0dda..ea287d9 100644
--- a/sdm/libs/hwc2/display_null.h
+++ b/sdm/libs/hwc2/display_null.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-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
@@ -36,35 +36,31 @@
namespace sdm {
-#define MAKE_NO_OP(virtual_method_name) \
- virtual DisplayError virtual_method_name { return kErrorNone; }
+#define MAKE_NO_OP(virtual_method_signature) \
+ virtual DisplayError virtual_method_signature { return kErrorNone; }
class DisplayNull : public DisplayInterface {
public:
virtual ~DisplayNull() { }
- virtual DisplayError Commit(LayerStack *layer_stack);
- virtual DisplayError GetDisplayState(DisplayState *state);
- virtual DisplayError SetDisplayState(DisplayState state);
- virtual DisplayError SetFrameBufferConfig(const DisplayConfigVariableInfo &variable_info);
+ virtual DisplayError Init();
+ virtual DisplayError GetMixerResolution(uint32_t *width, uint32_t *height);
virtual DisplayError GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info);
+ virtual DisplayError GetConfig(uint32_t index, DisplayConfigVariableInfo *disp_attr);
+ virtual DisplayError GetConfig(DisplayConfigFixedInfo *fixed_info);
+ virtual DisplayError GetRefreshRateRange(uint32_t *min_refresh_rate, uint32_t *max_refresh_rate);
+ virtual DisplayError GetActiveConfig(uint32_t *config);
+ virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count);
+ virtual DisplayError Prepare(LayerStack *layer_stack);
+ virtual bool IsPrimaryDisplay() { return true; }
virtual bool IsUnderscanSupported() { return true; }
virtual void SetIdleTimeoutMs(uint32_t active_ms) { }
- virtual bool IsPrimaryDisplay() { return true; }
+ virtual std::string Dump() { return ""; }
- void SetActive(bool active) {
- active_ = active;
- }
-
- bool IsActive() {
- return active_;
- }
-
- MAKE_NO_OP(Prepare(LayerStack *))
+ MAKE_NO_OP(Commit(LayerStack *))
+ MAKE_NO_OP(GetDisplayState(DisplayState *))
+ MAKE_NO_OP(SetDisplayState(DisplayState))
+ MAKE_NO_OP(SetFrameBufferConfig(const DisplayConfigVariableInfo &))
MAKE_NO_OP(Flush())
- MAKE_NO_OP(GetNumVariableInfoConfigs(uint32_t *))
- MAKE_NO_OP(GetConfig(uint32_t, DisplayConfigVariableInfo *))
- MAKE_NO_OP(GetConfig(DisplayConfigFixedInfo *))
- MAKE_NO_OP(GetActiveConfig(uint32_t *))
MAKE_NO_OP(GetVSyncState(bool *))
MAKE_NO_OP(SetActiveConfig(uint32_t))
MAKE_NO_OP(SetActiveConfig(DisplayConfigVariableInfo *))
@@ -86,18 +82,29 @@
MAKE_NO_OP(GetDefaultColorMode(std::string *))
MAKE_NO_OP(ApplyDefaultDisplayMode())
MAKE_NO_OP(SetCursorPosition(int, int))
- MAKE_NO_OP(GetRefreshRateRange(uint32_t *, uint32_t *))
MAKE_NO_OP(SetRefreshRate(uint32_t, bool))
MAKE_NO_OP(GetPanelBrightness(int *))
MAKE_NO_OP(SetVSyncState(bool))
MAKE_NO_OP(SetMixerResolution(uint32_t, uint32_t))
- MAKE_NO_OP(GetMixerResolution(uint32_t *, uint32_t *))
MAKE_NO_OP(SetDetailEnhancerData(const DisplayDetailEnhancerData &))
MAKE_NO_OP(GetDisplayPort(DisplayPort *))
MAKE_NO_OP(SetCompositionState(LayerComposition, bool))
MAKE_NO_OP(GetClientTargetSupport(uint32_t, uint32_t, LayerBufferFormat,
const ColorMetaData &))
- std::string Dump() { return ""; }
+
+ DisplayConfigVariableInfo default_variable_config_ = {};
+ DisplayConfigFixedInfo default_fixed_config_ = {};
+};
+
+class DisplayNullExternal : public DisplayNull {
+ public:
+ virtual DisplayError Commit(LayerStack *layer_stack);
+ virtual DisplayError GetDisplayState(DisplayState *state);
+ virtual DisplayError SetDisplayState(DisplayState state);
+ virtual DisplayError SetFrameBufferConfig(const DisplayConfigVariableInfo &variable_info);
+ virtual DisplayError GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info);
+ void SetActive(bool active) { active_ = active; }
+ bool IsActive() { return active_; }
private:
bool active_ = false;
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index 870b8b6..3236c4a 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright 2015 The Android Open Source Project
@@ -360,11 +360,23 @@
}
int HWCDisplay::Init() {
- DisplayError error = core_intf_->CreateDisplay(type_, this, &display_intf_);
- if (error != kErrorNone) {
- DLOGE("Display create failed. Error = %d display_type %d event_handler %p disp_intf %p", error,
- type_, this, &display_intf_);
- return -EINVAL;
+ DisplayError error = kErrorNone;
+
+ HWCDebugHandler::Get()->GetProperty("sdm.debug.enable_null_display", &null_display_mode_);
+
+ if (null_display_mode_) {
+ DisplayNull *disp_null = new DisplayNull();
+ disp_null->Init();
+ use_metadata_refresh_rate_ = false;
+ display_intf_ = disp_null;
+ ALOGI("Enabling null display mode for display type %d", type_);
+ } else {
+ error = core_intf_->CreateDisplay(type_, this, &display_intf_);
+ if (error != kErrorNone) {
+ DLOGE("Display create failed. Error = %d display_type %d event_handler %p disp_intf %p",
+ error, type_, this, &display_intf_);
+ return -EINVAL;
+ }
}
validated_ = false;
@@ -405,10 +417,15 @@
}
int HWCDisplay::Deinit() {
- DisplayError error = core_intf_->DestroyDisplay(display_intf_);
- if (error != kErrorNone) {
- DLOGE("Display destroy failed. Error = %d", error);
- return -EINVAL;
+ if (null_display_mode_) {
+ delete static_cast<DisplayNull *>(display_intf_);
+ display_intf_ = nullptr;
+ } else {
+ DisplayError error = core_intf_->DestroyDisplay(display_intf_);
+ if (error != kErrorNone) {
+ DLOGE("Display destroy failed. Error = %d", error);
+ return -EINVAL;
+ }
}
delete client_target_;
@@ -421,8 +438,10 @@
delete color_mode_;
}
- delete tone_mapper_;
- tone_mapper_ = nullptr;
+ if (tone_mapper_) {
+ delete tone_mapper_;
+ tone_mapper_ = nullptr;
+ }
return 0;
}
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index a5e1457..1790257 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright 2015 The Android Open Source Project
@@ -36,6 +36,7 @@
#include "hwc_buffer_allocator.h"
#include "hwc_callbacks.h"
#include "hwc_layers.h"
+#include "display_null.h"
namespace sdm {
@@ -309,6 +310,7 @@
uint32_t geometry_changes_ = GeometryChanges::kNone;
bool skip_validate_ = false;
bool animating_ = false;
+ int null_display_mode_ = 0;
};
inline int HWCDisplay::Perform(uint32_t operation, ...) {
diff --git a/sdm/libs/hwc2/hwc_display_external.h b/sdm/libs/hwc2/hwc_display_external.h
index fbee6a3..75e9387 100644
--- a/sdm/libs/hwc2/hwc_display_external.h
+++ b/sdm/libs/hwc2/hwc_display_external.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2017, 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
@@ -58,7 +58,7 @@
static void GetDownscaleResolution(uint32_t primary_width, uint32_t primary_height,
uint32_t *virtual_width, uint32_t *virtual_height);
- DisplayNull display_null_;
+ DisplayNullExternal display_null_;
int underscan_width_ = 0;
int underscan_height_ = 0;
};
diff --git a/sdm/libs/hwc2/hwc_display_primary.cpp b/sdm/libs/hwc2/hwc_display_primary.cpp
index 1f2fdf6..21c958d 100644
--- a/sdm/libs/hwc2/hwc_display_primary.cpp
+++ b/sdm/libs/hwc2/hwc_display_primary.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014 - 2017, 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
@@ -475,13 +475,17 @@
}
void HWCDisplayPrimary::HandleFrameDump() {
- if (dump_frame_count_ && output_buffer_.release_fence_fd >= 0) {
- int ret = sync_wait(output_buffer_.release_fence_fd, 1000);
- ::close(output_buffer_.release_fence_fd);
- output_buffer_.release_fence_fd = -1;
- if (ret < 0) {
- DLOGE("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
- } else {
+ if (dump_frame_count_) {
+ int ret = 0;
+ if (output_buffer_.release_fence_fd >= 0) {
+ ret = sync_wait(output_buffer_.release_fence_fd, 1000);
+ ::close(output_buffer_.release_fence_fd);
+ output_buffer_.release_fence_fd = -1;
+ if (ret < 0) {
+ DLOGE("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
+ }
+ }
+ if (ret >= 0) {
DumpOutputBuffer(output_buffer_info_, output_buffer_base_, layer_stack_.retire_fence_fd);
}
}
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 36b55d0..693e7ca 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright 2015 The Android Open Source Project
@@ -160,35 +160,44 @@
StartServices();
+ HWCDebugHandler::Get()->GetProperty("sdm.debug.enable_null_display", &null_display_mode_);
+
DisplayError error = buffer_allocator_.Init();
if (error != kErrorNone) {
- ALOGE("%s::%s: Buffer allocaor initialization failed. Error = %d",
+ ALOGE("%s::%s: Buffer allocator initialization failed. Error = %d",
__CLASS__, __FUNCTION__, error);
return -EINVAL;
}
- g_hwc_uevent_.Register(this);
+ HWDisplayInterfaceInfo hw_disp_info = {};
+ if (null_display_mode_) {
+ hw_disp_info.type = kPrimary;
+ hw_disp_info.is_connected = true;
+ } else {
+ g_hwc_uevent_.Register(this);
- error = CoreInterface::CreateCore(HWCDebugHandler::Get(), &buffer_allocator_,
- &buffer_sync_handler_, &socket_handler_, &core_intf_);
- if (error != kErrorNone) {
- buffer_allocator_.Deinit();
- ALOGE("%s::%s: Display core initialization failed. Error = %d", __CLASS__, __FUNCTION__, error);
- return -EINVAL;
+ error = CoreInterface::CreateCore(HWCDebugHandler::Get(), &buffer_allocator_,
+ &buffer_sync_handler_, &socket_handler_, &core_intf_);
+
+ if (error != kErrorNone) {
+ buffer_allocator_.Deinit();
+ ALOGE("%s::%s: Display core initialization failed. Error = %d", __CLASS__, __FUNCTION__,
+ error);
+ return -EINVAL;
+ }
+
+ error = core_intf_->GetFirstDisplayInterfaceType(&hw_disp_info);
+
+ if (error != kErrorNone) {
+ g_hwc_uevent_.Register(nullptr);
+ CoreInterface::DestroyCore();
+ buffer_allocator_.Deinit();
+ DLOGE("Primary display type not recognized. Error = %d", error);
+ return -EINVAL;
+ }
}
-
// If HDMI display is primary display, defer display creation until hotplug event is received.
- HWDisplayInterfaceInfo hw_disp_info = {};
- error = core_intf_->GetFirstDisplayInterfaceType(&hw_disp_info);
- if (error != kErrorNone) {
- g_hwc_uevent_.Register(nullptr);
- CoreInterface::DestroyCore();
- buffer_allocator_.Deinit();
- DLOGE("Primary display type not recognized. Error = %d", error);
- return -EINVAL;
- }
-
if (hw_disp_info.type == kHDMI) {
status = 0;
hdmi_is_primary_ = true;
@@ -246,11 +255,13 @@
color_mgr_->DestroyColorManager();
}
- g_hwc_uevent_.Register(nullptr);
+ if (!null_display_mode_) {
+ g_hwc_uevent_.Register(nullptr);
- DisplayError error = CoreInterface::DestroyCore();
- if (error != kErrorNone) {
- ALOGE("Display core de-initialization failed. Error = %d", error);
+ DisplayError error = CoreInterface::DestroyCore();
+ if (error != kErrorNone) {
+ ALOGE("Display core de-initialization failed. Error = %d", error);
+ }
}
return 0;
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index 8d25989..c979a77 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright 2015 The Android Open Source Project
@@ -267,6 +267,7 @@
Locker callbacks_lock_;
int hpd_bpp_ = 0;
int hpd_pattern_ = 0;
+ int null_display_mode_ = 0;
};
} // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_session_services.cpp b/sdm/libs/hwc2/hwc_session_services.cpp
index 6984711..f91b8f1 100644
--- a/sdm/libs/hwc2/hwc_session_services.cpp
+++ b/sdm/libs/hwc2/hwc_session_services.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-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
@@ -452,6 +452,10 @@
Return<int32_t> HWCSession::setCameraLaunchStatus(uint32_t on) {
SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+ if (null_display_mode_) {
+ return 0;
+ }
+
if (!core_intf_) {
DLOGW("core_intf_ not initialized.");
return -ENOENT;