Merge "sdm: Set surfaceDamage numRects for solid-fill layer"
diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp
index 4b62c9c..8b512bf 100644
--- a/libgralloc/gpu.cpp
+++ b/libgralloc/gpu.cpp
@@ -290,11 +290,20 @@
grallocFormat = HAL_PIXEL_FORMAT_NV21_ZSL; //NV21 ZSL
else if(usage & GRALLOC_USAGE_HW_CAMERA_READ)
grallocFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP; //NV21
- else if(usage & GRALLOC_USAGE_HW_CAMERA_WRITE)
- grallocFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP; //NV21
- else if(usage & GRALLOC_USAGE_HW_COMPOSER)
+ else if(usage & GRALLOC_USAGE_HW_CAMERA_WRITE) {
+ if (format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+ grallocFormat = HAL_PIXEL_FORMAT_NV21_ZSL; //NV21
+ } else {
+ grallocFormat = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS; //NV12 preview
+ }
+ } else if(usage & GRALLOC_USAGE_HW_COMPOSER)
//XXX: If we still haven't set a format, default to RGBA8888
grallocFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+ else if(format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+ //If no other usage flags are detected, default the
+ //flexible YUV format to NV21_ZSL
+ grallocFormat = HAL_PIXEL_FORMAT_NV21_ZSL;
+ }
}
bool useFbMem = false;
diff --git a/libqdutils/display_config.h b/libqdutils/display_config.h
index 8e3fa78..101e230 100644
--- a/libqdutils/display_config.h
+++ b/libqdutils/display_config.h
@@ -49,6 +49,7 @@
enum {
DISPLAY_PRIMARY = 0,
DISPLAY_EXTERNAL,
+ DISPLAY_TERTIARY,
DISPLAY_VIRTUAL,
};
diff --git a/sdm/include/private/color_params.h b/sdm/include/private/color_params.h
index e36f8e5..a34d84c 100644
--- a/sdm/include/private/color_params.h
+++ b/sdm/include/private/color_params.h
@@ -387,36 +387,10 @@
// Once all features are consumed, destroy/release all TFeatureInfo<T> on the list,
// then clear dirty_ flag and return the lock to the TFeatureInfo<T> producer.
- inline void Reset() {
- for (int i = 0; i < kMaxNumPPFeatures; i++) {
- if (feature_[i]) {
- delete feature_[i];
- feature_[i] = NULL;
- }
- }
- dirty_ = false;
- next_idx_ = 0;
- }
+ void Reset();
// Consumer to call this to retrieve all the TFeatureInfo<T> on the list to be programmed.
- inline DisplayError RetrieveNextFeature(PPFeatureInfo **feature) {
- DisplayError ret = kErrorNone;
- int i(0);
-
- for (i = next_idx_; i < kMaxNumPPFeatures; i++) {
- if (feature_[i]) {
- *feature = feature_[i];
- next_idx_ = i + 1;
- break;
- }
- }
- if (i == kMaxNumPPFeatures) {
- ret = kErrorParameters;
- next_idx_ = 0;
- }
-
- return ret;
- }
+ DisplayError RetrieveNextFeature(PPFeatureInfo **feature);
inline bool IsDirty() { return dirty_; }
inline void MarkAsDirty() { dirty_ = true; }
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index 0c1b5f4..37d1f17 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -108,11 +108,9 @@
struct HWSplitInfo {
uint32_t left_split = 0;
uint32_t right_split = 0;
- bool always_src_split = false;
bool operator !=(const HWSplitInfo &split_info) {
- return ((left_split != split_info.left_split) || (right_split != split_info.right_split) ||
- (always_src_split != split_info.always_src_split));
+ return ((left_split != split_info.left_split) || (right_split != split_info.right_split));
}
bool operator ==(const HWSplitInfo &split_info) {
@@ -166,22 +164,6 @@
bool secure = false;
bool cache = false;
uint32_t frame_rate = 0;
-
- bool operator != (const HWSessionConfig &input_config) const {
- if ((src_width != input_config.src_width) || (src_height != input_config.src_height) ||
- (src_format != input_config.src_format) || (dst_width != input_config.dst_width) ||
- (dst_height != input_config.dst_height) || (dst_format != input_config.dst_format) ||
- (buffer_count != input_config.buffer_count) || (secure != input_config.secure) ||
- (cache != input_config.cache) || (frame_rate != input_config.frame_rate)) {
- return true;
- }
-
- return false;
- }
-
- bool operator == (const HWSessionConfig &input_config) const {
- return !(operator != (input_config));
- }
};
struct HWRotateInfo {
@@ -287,7 +269,6 @@
struct HWDisplayAttributes : DisplayConfigVariableInfo {
bool is_device_split = false;
uint32_t split_left = 0;
- bool always_src_split = false;
uint32_t v_front_porch = 0; //!< Vertical front porch of panel
uint32_t v_back_porch = 0; //!< Vertical back porch of panel
uint32_t v_pulse_width = 0; //!< Vertical pulse width of panel
@@ -298,7 +279,6 @@
bool operator !=(const HWDisplayAttributes &attributes) {
return ((is_device_split != attributes.is_device_split) ||
(split_left != attributes.split_left) ||
- (always_src_split != attributes.always_src_split) ||
(x_pixels != attributes.x_pixels) || (y_pixels != attributes.y_pixels) ||
(x_dpi != attributes.x_dpi) || (y_dpi != attributes.y_dpi) || (fps != attributes.fps) ||
(vsync_period_ns != attributes.vsync_period_ns) ||
diff --git a/sdm/include/utils/debug.h b/sdm/include/utils/debug.h
index 95efef6..c8a3a98 100644
--- a/sdm/include/utils/debug.h
+++ b/sdm/include/utils/debug.h
@@ -47,6 +47,7 @@
#define DLOGE(format, ...) DLOGE_IF(kTagNone, format, ##__VA_ARGS__)
#define DLOGW(format, ...) DLOGW_IF(kTagNone, format, ##__VA_ARGS__)
#define DLOGI(format, ...) DLOGI_IF(kTagNone, format, ##__VA_ARGS__)
+#define DLOGV(format, ...) DLOGV_IF(kTagNone, format, ##__VA_ARGS__)
#define DTRACE_BEGIN(custom_string) Debug::Get()->BeginTrace(__CLASS__, __FUNCTION__, custom_string)
#define DTRACE_END() Debug::Get()->EndTrace()
diff --git a/sdm/libs/core/color_manager.cpp b/sdm/libs/core/color_manager.cpp
index 0de2078..aea55b0 100644
--- a/sdm/libs/core/color_manager.cpp
+++ b/sdm/libs/core/color_manager.cpp
@@ -42,6 +42,39 @@
DestroyColorInterface ColorManagerProxy::destroy_intf_ = NULL;
HWResourceInfo ColorManagerProxy::hw_res_info_;
+// Below two functions are part of concrete implementation for SDM core private
+// color_params.h
+void PPFeaturesConfig::Reset() {
+ for (int i = 0; i < kMaxNumPPFeatures; i++) {
+ if (feature_[i]) {
+ delete feature_[i];
+ feature_[i] = NULL;
+ }
+ }
+ dirty_ = false;
+ next_idx_ = 0;
+}
+
+DisplayError PPFeaturesConfig::RetrieveNextFeature(PPFeatureInfo **feature) {
+ DisplayError ret = kErrorNone;
+ int i(0);
+
+ for (i = next_idx_; i < kMaxNumPPFeatures; i++) {
+ if (feature_[i]) {
+ *feature = feature_[i];
+ next_idx_ = i + 1;
+ break;
+ }
+ }
+
+ if (i == kMaxNumPPFeatures) {
+ ret = kErrorParameters;
+ next_idx_ = 0;
+ }
+
+ return ret;
+}
+
DisplayError ColorManagerProxy::Init(const HWResourceInfo &hw_res_info) {
DisplayError error = kErrorNone;
diff --git a/sdm/libs/core/display_primary.cpp b/sdm/libs/core/display_primary.cpp
old mode 100644
new mode 100755
index 1a00da4..06bbccb
--- a/sdm/libs/core/display_primary.cpp
+++ b/sdm/libs/core/display_primary.cpp
@@ -148,7 +148,18 @@
DisplayError DisplayPrimary::SetDisplayState(DisplayState state) {
SCOPE_LOCK(locker_);
- return DisplayBase::SetDisplayState(state);
+ DisplayError error = kErrorNone;
+ error = DisplayBase::SetDisplayState(state);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ // Set vsync enable state to false, as driver disables vsync during display power off.
+ if (state == kStateOff) {
+ vsync_enable_ = false;
+ }
+
+ return kErrorNone;
}
DisplayError DisplayPrimary::SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
diff --git a/sdm/libs/core/fb/hw_device.cpp b/sdm/libs/core/fb/hw_device.cpp
index 3ebd202..50e686a 100644
--- a/sdm/libs/core/fb/hw_device.cpp
+++ b/sdm/libs/core/fb/hw_device.cpp
@@ -595,6 +595,10 @@
if (layer.transform.flip_horizontal) {
*mdp_flags |= MDP_LAYER_FLIP_LR;
}
+
+ if (input_buffer->flags.interlace) {
+ *mdp_flags |= MDP_LAYER_DEINTERLACE;
+ }
}
if (input_buffer->flags.secure) {
@@ -669,7 +673,6 @@
DLOGI("FPS: min = %d, max =%d", hw_panel_info_.min_fps, hw_panel_info_.max_fps);
DLOGI("Left Split = %d, Right Split = %d", hw_panel_info_.split_info.left_split,
hw_panel_info_.split_info.right_split);
- DLOGI("Source Split Always = %d", hw_panel_info_.split_info.always_src_split);
}
void HWDevice::GetHWPanelInfoByNode(int device_node, HWPanelInfo *panel_info) {
@@ -820,7 +823,7 @@
// Format "left right" space as delimiter
read = Sys::getline_(&line, &len, fileptr);
- if (read != -1) {
+ if (read > 0) {
if (!ParseLine(line, tokens, max_count, &token_count)) {
panel_info->split_info.left_split = atoi(tokens[0]);
panel_info->split_info.right_split = atoi(tokens[1]);
@@ -828,24 +831,6 @@
}
Sys::fclose_(fileptr);
-
- // SourceSplit enabled - Get More information
- snprintf(stringbuffer , sizeof(stringbuffer), "%s%d/msm_fb_src_split_info", fb_path_,
- device_node);
- fileptr = Sys::fopen_(stringbuffer, "r");
- if (!fileptr) {
- DLOGW("File not found %s", stringbuffer);
- return;
- }
-
- read = Sys::getline_(&line, &len, fileptr);
- if (read != -1) {
- if (!strncmp(line, "src_split_always", strlen("src_split_always"))) {
- panel_info->split_info.always_src_split = true;
- }
- }
-
- Sys::fclose_(fileptr);
}
int HWDevice::ParseLine(char *input, char *tokens[], const uint32_t max_token, uint32_t *count) {
diff --git a/sdm/libs/core/fb/hw_hdmi.cpp b/sdm/libs/core/fb/hw_hdmi.cpp
index 61d3df8..c47a0bd 100644
--- a/sdm/libs/core/fb/hw_hdmi.cpp
+++ b/sdm/libs/core/fb/hw_hdmi.cpp
@@ -483,6 +483,7 @@
while (true) {
char config_buffer[kPageSize] = {0};
msm_hdmi_mode_timing_info *info = reinterpret_cast<msm_hdmi_mode_timing_info *>(config_buffer);
+ RequestNewPage(page_number);
if (!ReadResolutionFile(config_buffer)) {
break;
@@ -508,7 +509,6 @@
// Request HDMI driver to populate res_info with more
// timing information
page_number++;
- RequestNewPage(page_number);
}
if (page_number == MSM_HDMI_INIT_RES_PAGE || config_index == 0) {
diff --git a/sdm/libs/core/fb/hw_primary.cpp b/sdm/libs/core/fb/hw_primary.cpp
index 3c308d7..c548a26 100644
--- a/sdm/libs/core/fb/hw_primary.cpp
+++ b/sdm/libs/core/fb/hw_primary.cpp
@@ -325,7 +325,6 @@
(var_screeninfo.xres > hw_resource_.max_mixer_width)) ? true : false;
display_attributes_.split_left = hw_panel_info_.split_info.left_split ?
hw_panel_info_.split_info.left_split : display_attributes_.x_pixels / 2;
- display_attributes_.always_src_split = hw_panel_info_.split_info.always_src_split;
display_attributes_.h_total += display_attributes_.is_device_split ? h_blanking : 0;
return kErrorNone;
diff --git a/sdm/libs/core/resource_default.cpp b/sdm/libs/core/resource_default.cpp
index e421961..8c67b82 100644
--- a/sdm/libs/core/resource_default.cpp
+++ b/sdm/libs/core/resource_default.cpp
@@ -450,18 +450,13 @@
DisplayError ResourceDefault::SrcSplitConfig(DisplayResourceContext *display_resource_ctx,
const LayerRect &src_rect, const LayerRect &dst_rect,
HWLayerConfig *layer_config) {
- HWDisplayAttributes &display_attributes = display_resource_ctx->display_attributes;
HWPipeInfo *left_pipe = &layer_config->left_pipe;
HWPipeInfo *right_pipe = &layer_config->right_pipe;
float src_width = src_rect.right - src_rect.left;
float dst_width = dst_rect.right - dst_rect.left;
- float left_mixer_width = FLOAT(display_attributes.split_left);
// Layer cannot qualify for SrcSplit if source or destination width exceeds max pipe width.
- // For perf/power optimization, even if "always_src_split" is enabled, use 2 pipes only if:
- // Source width is greater than split_left (left_mixer_width)
- if ((src_width > hw_res_info_.max_pipe_width) || (dst_width > hw_res_info_.max_pipe_width) ||
- (display_resource_ctx->display_attributes.always_src_split && src_width > left_mixer_width)) {
+ if ((src_width > hw_res_info_.max_pipe_width) || (dst_width > hw_res_info_.max_pipe_width)) {
SplitRect(src_rect, dst_rect, &left_pipe->src_roi, &left_pipe->dst_roi, &right_pipe->src_roi,
&right_pipe->dst_roi);
left_pipe->valid = true;
diff --git a/sdm/libs/core/strategy.cpp b/sdm/libs/core/strategy.cpp
index 6bd9a9c..0b7bd3c 100644
--- a/sdm/libs/core/strategy.cpp
+++ b/sdm/libs/core/strategy.cpp
@@ -50,9 +50,6 @@
error = extension_intf_->CreatePartialUpdate(display_type_, hw_resource_info_,
hw_panel_info_, &partial_update_intf_);
- if (error != kErrorNone) {
- DLOGW("Partial Update creation failed, Continue without partial update.");
- }
}
return kErrorNone;
diff --git a/sdm/libs/hwc/cpuhint.cpp b/sdm/libs/hwc/cpuhint.cpp
index f328268..ccf55bf 100644
--- a/sdm/libs/hwc/cpuhint.cpp
+++ b/sdm/libs/hwc/cpuhint.cpp
@@ -29,6 +29,7 @@
#include <cutils/properties.h>
#include <dlfcn.h>
+#include <utils/debug.h>
#include "cpuhint.h"
#include "hwc_debugger.h"
diff --git a/sdm/libs/hwc/cpuhint.h b/sdm/libs/hwc/cpuhint.h
index 14ecd93..a4a7758 100644
--- a/sdm/libs/hwc/cpuhint.h
+++ b/sdm/libs/hwc/cpuhint.h
@@ -44,7 +44,7 @@
void Reset();
private:
- enum { HINT = 0x4701 /* 47-display layer hint, 01-Enable */ };
+ enum { HINT = 0x4501 /* 45-display layer hint, 01-Enable */ };
bool enabled_ = false;
// frames to wait before setting this hint
int pre_enable_window_ = 0;
diff --git a/sdm/libs/hwc/hwc_buffer_allocator.cpp b/sdm/libs/hwc/hwc_buffer_allocator.cpp
index 1ea2915..3149718 100644
--- a/sdm/libs/hwc/hwc_buffer_allocator.cpp
+++ b/sdm/libs/hwc/hwc_buffer_allocator.cpp
@@ -32,6 +32,7 @@
#include <gr.h>
#include <alloc_controller.h>
#include <utils/constants.h>
+#include <utils/debug.h>
#include <core/buffer_allocator.h>
#include "hwc_debugger.h"
diff --git a/sdm/libs/hwc/hwc_buffer_sync_handler.cpp b/sdm/libs/hwc/hwc_buffer_sync_handler.cpp
index 949745e..581bcd6 100644
--- a/sdm/libs/hwc/hwc_buffer_sync_handler.cpp
+++ b/sdm/libs/hwc/hwc_buffer_sync_handler.cpp
@@ -29,6 +29,7 @@
#include <sync/sync.h>
#include <utils/constants.h>
+#include <utils/debug.h>
#include "hwc_debugger.h"
#include "hwc_buffer_sync_handler.h"
diff --git a/sdm/libs/hwc/hwc_color_manager.cpp b/sdm/libs/hwc/hwc_color_manager.cpp
index 891d036..fcd2a55 100644
--- a/sdm/libs/hwc/hwc_color_manager.cpp
+++ b/sdm/libs/hwc/hwc_color_manager.cpp
@@ -40,6 +40,7 @@
#include <core/dump_interface.h>
#include <utils/constants.h>
+#include <utils/debug.h>
#include <core/buffer_allocator.h>
#include <private/color_params.h>
#include "hwc_buffer_allocator.h"
@@ -141,9 +142,16 @@
return color_mgr;
}
-HWCColorManager::~HWCColorManager() {}
+HWCColorManager::~HWCColorManager() {
+}
void HWCColorManager::DestroyColorManager() {
+ if (qdcm_mode_mgr_) {
+ delete qdcm_mode_mgr_;
+ }
+ if (qdcm_diag_deinit_) {
+ qdcm_diag_deinit_();
+ }
if (diag_client_lib_) {
::dlclose(diag_client_lib_);
}
@@ -156,24 +164,16 @@
int HWCColorManager::EnableQDCMMode(bool enable, HWCDisplay *hwc_display) {
int ret = 0;
- if (enable) { // entering QDCM mode, disable all active features and acquire Android wakelock
+ if (!qdcm_mode_mgr_) {
qdcm_mode_mgr_ = HWCQDCMModeManager::CreateQDCMModeMgr();
if (!qdcm_mode_mgr_) {
- DLOGE("failing to create QDCM operating mode manager.");
+ DLOGE("Unable to create QDCM operating mode manager.");
ret = -EFAULT;
- } else {
- ret = qdcm_mode_mgr_->EnableQDCMMode(enable, hwc_display);
}
- } else { // exiting QDCM mode, reverse the effect of entering.
- if (!qdcm_mode_mgr_) {
- DLOGE("failing to disable QDCM operating mode manager.");
- ret = -EFAULT;
- } else { // once exiting from QDCM operating mode, destroy QDCMModeMgr and release the
- // resources
- ret = qdcm_mode_mgr_->EnableQDCMMode(enable, hwc_display);
- delete qdcm_mode_mgr_;
- qdcm_mode_mgr_ = NULL;
- }
+ }
+
+ if (qdcm_mode_mgr_) {
+ ret = qdcm_mode_mgr_->EnableQDCMMode(enable, hwc_display);
}
return ret;
@@ -407,6 +407,7 @@
const HWCQDCMModeManager::ActiveFeatureCMD &cmds,
bool *was_running) {
int ret = 0;
+ ssize_t size = 0;
char response[kSocketCMDMaxLength] = {
0,
};
@@ -418,25 +419,31 @@
if (!enable) { // if client requesting to disable it.
// query CABL status, if off, no action. keep the status.
- if (::write(socket_fd_, cmds.cmd_query_status, strlen(cmds.cmd_query_status)) < 0) {
+ size = ::write(socket_fd_, cmds.cmd_query_status, strlen(cmds.cmd_query_status));
+ if (size < 0) {
DLOGW("Unable to send data over socket %s", ::strerror(errno));
ret = -EFAULT;
- } else if (::read(socket_fd_, response, kSocketCMDMaxLength) < 0) {
- DLOGW("Unable to read data over socket %s", ::strerror(errno));
- ret = -EFAULT;
- } else if (!strncmp(response, cmds.running, strlen(cmds.running))) {
- *was_running = true;
+ } else {
+ size = ::read(socket_fd_, response, kSocketCMDMaxLength);
+ if (size < 0) {
+ DLOGW("Unable to read data over socket %s", ::strerror(errno));
+ ret = -EFAULT;
+ } else if (!strncmp(response, cmds.running, strlen(cmds.running))) {
+ *was_running = true;
+ }
}
if (*was_running) { // if was running, it's requested to disable it.
- if (::write(socket_fd_, cmds.cmd_off, strlen(cmds.cmd_off)) < 0) {
+ size = ::write(socket_fd_, cmds.cmd_off, strlen(cmds.cmd_off));
+ if (size < 0) {
DLOGW("Unable to send data over socket %s", ::strerror(errno));
ret = -EFAULT;
}
}
} else { // if was running, need enable it back.
if (*was_running) {
- if (::write(socket_fd_, cmds.cmd_on, strlen(cmds.cmd_on)) < 0) {
+ size = ::write(socket_fd_, cmds.cmd_on, strlen(cmds.cmd_on));
+ if (size < 0) {
DLOGW("Unable to send data over socket %s", ::strerror(errno));
ret = -EFAULT;
}
diff --git a/sdm/libs/hwc/hwc_debugger.h b/sdm/libs/hwc/hwc_debugger.h
index 474e1c5..e4e1ea3 100644
--- a/sdm/libs/hwc/hwc_debugger.h
+++ b/sdm/libs/hwc/hwc_debugger.h
@@ -37,19 +37,6 @@
#include <cutils/log.h>
#include <utils/Trace.h>
-#define DLOG(Macro, format, ...) Macro(__CLASS__ "::%s: " format, __FUNCTION__, ##__VA_ARGS__)
-
-#define DLOGE(format, ...) DLOG(ALOGE, format, ##__VA_ARGS__)
-#define DLOGW(format, ...) DLOG(ALOGW, format, ##__VA_ARGS__)
-#define DLOGI(format, ...) DLOG(ALOGI, format, ##__VA_ARGS__)
-#define DLOGD(format, ...) DLOG(ALOGI, format, ##__VA_ARGS__)
-#define DLOGV(format, ...) DLOG(ALOGV, format, ##__VA_ARGS__)
-
-#define DTRACE_BEGIN(custom_string) HWCDebugHandler::Get()->BeginTrace(__CLASS__, __FUNCTION__, \
- custom_string)
-#define DTRACE_END() HWCDebugHandler::Get()->EndTrace()
-#define DTRACE_SCOPED() ScopeTracer<HWCDebugHandler> scope_tracer(__CLASS__, __FUNCTION__)
-
namespace sdm {
class HWCDebugHandler : public DebugHandler {
diff --git a/sdm/libs/hwc/hwc_display.cpp b/sdm/libs/hwc/hwc_display.cpp
index 30577a8..7fe8984 100644
--- a/sdm/libs/hwc/hwc_display.cpp
+++ b/sdm/libs/hwc/hwc_display.cpp
@@ -32,6 +32,8 @@
#include <gralloc_priv.h>
#include <gr.h>
#include <utils/constants.h>
+#include <utils/rect.h>
+#include <utils/debug.h>
#include <sync/sync.h>
#include <cutils/properties.h>
@@ -60,8 +62,6 @@
if (layer->input_buffer->flags.interlace) {
float height = (layer->src_rect.bottom - layer->src_rect.top) / 2.0f;
layer->src_rect.bottom = layer->src_rect.top + floorf(height);
- layer->input_buffer->height /= 2;
- layer->input_buffer->width *= 2;
}
}
@@ -477,6 +477,7 @@
use_blit_comp_ = false;
metadata_refresh_rate_ = 0;
+ display_rect_ = LayerRect();
// Configure each layer
for (size_t i = 0; i < num_hw_layers; i++) {
@@ -506,6 +507,11 @@
}
SetComposition(hwc_layer.compositionType, &layer.composition);
+ if (hwc_layer.compositionType != HWC_FRAMEBUFFER_TARGET) {
+ display_rect_ = Union(display_rect_, layer.dst_rect);
+ }
+
+
// For dim layers, SurfaceFlinger
// - converts planeAlpha to per pixel alpha,
// - sets RGB color to 000,
@@ -1308,6 +1314,21 @@
return ret;
}
+int HWCDisplay::GetVisibleDisplayRect(hwc_rect_t* visible_rect) {
+ if (!IsValid(display_rect_)) {
+ return -EINVAL;
+ }
+
+ visible_rect->left = INT(display_rect_.left);
+ visible_rect->top = INT(display_rect_.top);
+ visible_rect->right = INT(display_rect_.right);
+ visible_rect->bottom = INT(display_rect_.bottom);
+ DLOGI("Dpy = %d Visible Display Rect(%d %d %d %d)", visible_rect->left, visible_rect->top,
+ visible_rect->right, visible_rect->bottom);
+
+ return 0;
+}
+
void HWCDisplay::ResetLayerCacheStack() {
uint32_t layer_count = layer_stack_cache_.layer_count;
for (uint32_t i = 0; i < layer_count; i++) {
diff --git a/sdm/libs/hwc/hwc_display.h b/sdm/libs/hwc/hwc_display.h
index 3714a95..ce624a3 100644
--- a/sdm/libs/hwc/hwc_display.h
+++ b/sdm/libs/hwc/hwc_display.h
@@ -76,6 +76,7 @@
int ColorSVCRequestRoute(const PPDisplayAPIPayload &in_payload,
PPDisplayAPIPayload *out_payload,
PPPendingParams *pending_action);
+ int GetVisibleDisplayRect(hwc_rect_t* rect);
protected:
enum DisplayStatus {
@@ -186,7 +187,8 @@
bool skip_prepare_ = false;
bool solid_fill_enable_ = false;
- uint32_t solid_fill_color_ = 0;;
+ uint32_t solid_fill_color_ = 0;
+ LayerRect display_rect_;
private:
bool IsFrameBufferScaled();
diff --git a/sdm/libs/hwc/hwc_display_external.cpp b/sdm/libs/hwc/hwc_display_external.cpp
index 9053b42..a02be81 100644
--- a/sdm/libs/hwc/hwc_display_external.cpp
+++ b/sdm/libs/hwc/hwc_display_external.cpp
@@ -29,6 +29,7 @@
#include <cutils/properties.h>
#include <utils/constants.h>
+#include <utils/debug.h>
#include "hwc_display_external.h"
#include "hwc_debugger.h"
@@ -53,7 +54,7 @@
hwc_display_external->GetPanelResolution(&external_width, &external_height);
int downscale_enabled = 0;
- HWCDebugHandler::Get()->GetProperty("sdm.debug.sde_downscale_external", &downscale_enabled);
+ HWCDebugHandler::Get()->GetProperty("sdm.debug.downscale_external", &downscale_enabled);
if (downscale_enabled) {
GetDownscaleResolution(primary_width, primary_height, &external_width, &external_height);
}
diff --git a/sdm/libs/hwc/hwc_display_primary.cpp b/sdm/libs/hwc/hwc_display_primary.cpp
index d12bd1d..9842b61 100644
--- a/sdm/libs/hwc/hwc_display_primary.cpp
+++ b/sdm/libs/hwc/hwc_display_primary.cpp
@@ -29,6 +29,7 @@
#include <cutils/properties.h>
#include <utils/constants.h>
+#include <utils/debug.h>
#include <stdarg.h>
#include "hwc_display_primary.h"
#include "hwc_debugger.h"
diff --git a/sdm/libs/hwc/hwc_display_virtual.cpp b/sdm/libs/hwc/hwc_display_virtual.cpp
index 116c36d..219a81b 100644
--- a/sdm/libs/hwc/hwc_display_virtual.cpp
+++ b/sdm/libs/hwc/hwc_display_virtual.cpp
@@ -28,6 +28,7 @@
*/
#include <utils/constants.h>
+#include <utils/debug.h>
#include <sync/sync.h>
#include <stdarg.h>
#include <gr.h>
@@ -86,7 +87,7 @@
*hwc_display = static_cast<HWCDisplay *>(hwc_display_virtual);
- return status;
+ return 0;
}
void HWCDisplayVirtual::Destroy(HWCDisplay *hwc_display) {
diff --git a/sdm/libs/hwc/hwc_session.cpp b/sdm/libs/hwc/hwc_session.cpp
index 98444e1..f938f0d 100644
--- a/sdm/libs/hwc/hwc_session.cpp
+++ b/sdm/libs/hwc/hwc_session.cpp
@@ -41,6 +41,7 @@
#include <gr.h>
#include <gralloc_priv.h>
#include <display_config.h>
+#include <utils/debug.h>
#include "hwc_buffer_allocator.h"
#include "hwc_buffer_sync_handler.h"
@@ -73,6 +74,7 @@
namespace sdm {
Locker HWCSession::locker_;
+Locker HWCSession::concurrency_locker_;
bool HWCSession::reset_panel_ = false;
static void Invalidate(const struct hwc_procs *procs) {
@@ -292,22 +294,31 @@
for (size_t dpy = 0; dpy < num_displays; dpy++) {
hwc_display_contents_1_t *content_list = displays[dpy];
- if (dpy == HWC_DISPLAY_VIRTUAL) {
- if (hwc_session->hwc_display_[HWC_DISPLAY_EXTERNAL]) {
- if (content_list) {
- for (size_t i = 0; i < content_list->numHwLayers; i++) {
- if (content_list->hwLayers[i].acquireFenceFd >= 0) {
- close(content_list->hwLayers[i].acquireFenceFd);
- content_list->hwLayers[i].acquireFenceFd = -1;
- }
- }
- if (content_list->outbufAcquireFenceFd >= 0) {
- close(content_list->outbufAcquireFenceFd);
- content_list->outbufAcquireFenceFd = -1;
- }
- content_list->retireFenceFd = -1;
+
+ // Drop virtual display composition if virtual display object could not be created
+ // due to HDMI concurrency.
+ if (dpy == HWC_DISPLAY_VIRTUAL && !hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL]) {
+ if (!content_list) {
+ continue;
+ }
+
+ for (size_t i = 0; i < content_list->numHwLayers; i++) {
+ int &acquireFenceFd = content_list->hwLayers[i].acquireFenceFd;
+ if (acquireFenceFd >= 0) {
+ close(acquireFenceFd);
+ acquireFenceFd = -1;
}
}
+
+ int &outbufAcquireFenceFd = content_list->outbufAcquireFenceFd;
+ if (outbufAcquireFenceFd >= 0) {
+ close(outbufAcquireFenceFd);
+ outbufAcquireFenceFd = -1;
+ }
+
+ content_list->retireFenceFd = -1;
+
+ continue;
}
if (hwc_session->hwc_display_[dpy]) {
@@ -499,31 +510,35 @@
return status;
}
-int HWCSession::HandleVirtualDisplayLifeCycle(hwc_display_contents_1_t *content_list) {
- int status = 0;
+void HWCSession::HandleVirtualDisplayLifeCycle(hwc_display_contents_1_t *content_list) {
+ // Virtual display & HDMI concurrency is not supported.
+ // Acquire concurrency mutex before creating / destroying virtual display.
+ // Signal concurrency condition on virtual display destroy so that HDMI hotplug could
+ // proceed with connection.
+ SCOPE_LOCK(concurrency_locker_);
if (HWCDisplayVirtual::IsValidContentList(content_list)) {
if (!hwc_display_[HWC_DISPLAY_VIRTUAL]) {
+ DLOGI("Create Virtual Display");
uint32_t primary_width = 0;
uint32_t primary_height = 0;
hwc_display_[HWC_DISPLAY_PRIMARY]->GetFrameBufferResolution(&primary_width, &primary_height);
- // Create virtual display device
- status = HWCDisplayVirtual::Create(core_intf_, &hwc_procs_, primary_width, primary_height,
- content_list, &hwc_display_[HWC_DISPLAY_VIRTUAL]);
- if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
+
+ int status = HWCDisplayVirtual::Create(core_intf_, &hwc_procs_, primary_width,
+ primary_height, content_list,
+ &hwc_display_[HWC_DISPLAY_VIRTUAL]);
+ if (!status) {
hwc_display_[HWC_DISPLAY_VIRTUAL]->SetSecureDisplay(secure_display_active_);
}
}
} else {
if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
+ DLOGI("Destroy Virtual Display");
HWCDisplayVirtual::Destroy(hwc_display_[HWC_DISPLAY_VIRTUAL]);
- hwc_display_[HWC_DISPLAY_VIRTUAL] = 0;
- // Signal the HotPlug thread to continue with the external display connection
- locker_.Signal();
+ hwc_display_[HWC_DISPLAY_VIRTUAL] = NULL;
+ concurrency_locker_.Signal();
}
}
-
- return status;
}
android::status_t HWCSession::notifyCallback(uint32_t command, const android::Parcel *input_parcel,
@@ -559,8 +574,9 @@
case qService::IQService::SET_DISPLAY_MODE:
status = SetDisplayMode(input_parcel);
break;
+
case qService::IQService::SET_SECONDARY_DISPLAY_STATUS:
- status = SetSecondaryDisplayStatus(input_parcel);
+ status = SetSecondaryDisplayStatus(input_parcel, output_parcel);
break;
case qService::IQService::CONFIGURE_DYN_REFRESH_RATE:
@@ -610,6 +626,10 @@
status = SetPanelBrightness(input_parcel, output_parcel);
break;
+ case qService::IQService::GET_DISPLAY_VISIBLE_REGION:
+ status = GetVisibleDisplayRect(input_parcel, output_parcel);
+ break;
+
default:
DLOGW("QService command = %d is not supported", command);
return -EINVAL;
@@ -705,11 +725,11 @@
return ret;
}
+ // Todo(user): Unlock it before sending events to client. It may cause deadlocks in future.
hwc_procs_->invalidate(hwc_procs_);
// Wait until partial update control is complete
ret = locker_.WaitFinite(kPartialUpdateControlTimeoutMs);
- locker_.Unlock();
out->writeInt32(ret);
@@ -803,17 +823,28 @@
return error;
}
-android::status_t HWCSession::SetSecondaryDisplayStatus(const android::Parcel *input_parcel) {
+android::status_t HWCSession::SetSecondaryDisplayStatus(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel) {
+ int ret = -EINVAL;
+
uint32_t display_id = UINT32(input_parcel->readInt32());
uint32_t display_status = UINT32(input_parcel->readInt32());
- DLOGI("Display %d Status %d", display_id, display_status);
- if (display_id < HWC_DISPLAY_EXTERNAL || display_id > HWC_DISPLAY_VIRTUAL) {
- DLOGW("Not supported for display %d", display_id);
- return -EINVAL;
+ DLOGI("Display = %d, Status = %d", display_id, display_status);
+
+ if (display_id >= HWC_NUM_DISPLAY_TYPES) {
+ DLOGE("Invalid display_id");
+ } else if (display_id == HWC_DISPLAY_PRIMARY) {
+ DLOGE("Not supported for this display");
+ } else if (!hwc_display_[display_id]) {
+ DLOGW("Display is not connected");
+ } else {
+ ret = hwc_display_[display_id]->SetDisplayStatus(display_status);
}
- return hwc_display_[display_id]->SetDisplayStatus(display_status);
+ output_parcel->writeInt32(ret);
+
+ return ret;
}
android::status_t HWCSession::ConfigureRefreshRate(const android::Parcel *input_parcel) {
@@ -1025,10 +1056,13 @@
uint32_t display_id = UINT32(input_parcel->readInt32());
DLOGI("Display %d", display_id);
- if (display_id != HWC_DISPLAY_EXTERNAL) {
- DLOGW("Not supported for display %d", display_id);
+
+ if (display_id >= HWC_NUM_DISPLAY_TYPES) {
+ DLOGE("Invalid display_id");
+ } else if (display_id != HWC_DISPLAY_EXTERNAL) {
+ DLOGE("Not supported for display");
} else if (!hwc_display_[display_id]) {
- DLOGE("Display %d is not connected", display_id);
+ DLOGW("Display is not connected");
} else {
ret = hwc_display_[display_id]->OnMinHdcpEncryptionLevelChange();
}
@@ -1126,46 +1160,66 @@
}
int HWCSession::HotPlugHandler(bool connected) {
- if (!hwc_procs_) {
- DLOGW("Ignore hotplug - hwc_proc not registered");
- return -1;
- }
+ // 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.
+ {
+ // Virtual display & HDMI concurrency is not supported. Acquire concurrency lock
+ // and wait for virtual display to tear down if connected.
+ SCOPE_LOCK(concurrency_locker_);
- if (connected) {
- SEQUENCE_WAIT_SCOPE_LOCK(locker_);
- if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
- // Wait for the virtual display to tear down
- int status = locker_.WaitFinite(kExternalConnectionTimeoutMs);
- if (status != 0) {
- DLOGE("Timed out while waiting for virtual display to tear down.");
+ if (connected) {
+ // Acquire global lock and check if virtual display is connected.
+ // Release global lock before waiting for virtual display to disconnect and signal.
+ bool virtual_display_connected = false;
+ {
+ SCOPE_LOCK(locker_);
+ if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
+ DLOGE("Primay display is not connected");
+ return -1;
+ }
+
+ if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
+ DLOGE("HDMI is already connected");
+ return -1;
+ }
+
+ virtual_display_connected = (hwc_display_[HWC_DISPLAY_VIRTUAL] != NULL);
+ DLOGI("Virtual display connection status = %d", virtual_display_connected);
+ }
+
+ if (virtual_display_connected) {
+ DLOGI("Wait for virtual display to disconnect.");
+ concurrency_locker_.Wait();
+ DLOGI("virtual display is disconnected now.");
+ }
+
+ // Acquire global sequence lock now.
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+ uint32_t primary_width = 0;
+ uint32_t primary_height = 0;
+ hwc_display_[HWC_DISPLAY_PRIMARY]->GetFrameBufferResolution(&primary_width, &primary_height);
+
+ // Create hdmi display
+ int status = HWCDisplayExternal::Create(core_intf_, &hwc_procs_, primary_width,
+ primary_height, &hwc_display_[HWC_DISPLAY_EXTERNAL]);
+ if (status) {
+ return status;
+ }
+
+ hwc_display_[HWC_DISPLAY_EXTERNAL]->SetSecureDisplay(secure_display_active_);
+ } else {
+ // Acquire concurrency lock as well as global sequence lock.
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+ if (!hwc_display_[HWC_DISPLAY_EXTERNAL]) {
+ DLOGE("HDMI not connected");
return -1;
}
- }
- if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
- DLOGE("HDMI already connected");
- return -1;
- }
- uint32_t primary_width = 0;
- uint32_t primary_height = 0;
- hwc_display_[HWC_DISPLAY_PRIMARY]->GetFrameBufferResolution(&primary_width, &primary_height);
- // Create hdmi display
- int status = HWCDisplayExternal::Create(core_intf_, &hwc_procs_, primary_width,
- primary_height, &hwc_display_[HWC_DISPLAY_EXTERNAL]);
- if (status) {
- return status;
+ HWCDisplayExternal::Destroy(hwc_display_[HWC_DISPLAY_EXTERNAL]);
+ hwc_display_[HWC_DISPLAY_EXTERNAL] = NULL;
}
- if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
- hwc_display_[HWC_DISPLAY_EXTERNAL]->SetSecureDisplay(secure_display_active_);
- }
- } else {
- SEQUENCE_WAIT_SCOPE_LOCK(locker_);
- if (!hwc_display_[HWC_DISPLAY_EXTERNAL]) {
- DLOGE("HDMI not connected");
- return -1;
- }
- HWCDisplayExternal::Destroy(hwc_display_[HWC_DISPLAY_EXTERNAL]);
- hwc_display_[HWC_DISPLAY_EXTERNAL] = 0;
}
// notify client and trigger a screen refresh
@@ -1204,5 +1258,31 @@
}
}
+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_DISPLAY_VIRTUAL) {
+ return android::BAD_VALUE;;
+ }
+
+ if (!hwc_display_[dpy]) {
+ return android::NO_INIT;
+ }
+
+ hwc_rect_t visible_rect = {0, 0, 0, 0};
+ int error = hwc_display_[dpy]->GetVisibleDisplayRect(&visible_rect);
+ if (error < 0) {
+ return error;
+ }
+
+ output_parcel->writeInt32(visible_rect.left);
+ output_parcel->writeInt32(visible_rect.top);
+ output_parcel->writeInt32(visible_rect.right);
+ output_parcel->writeInt32(visible_rect.bottom);
+
+ return android::NO_ERROR;
+}
+
} // namespace sdm
diff --git a/sdm/libs/hwc/hwc_session.h b/sdm/libs/hwc/hwc_session.h
index 22574dc..1dde96e 100644
--- a/sdm/libs/hwc/hwc_session.h
+++ b/sdm/libs/hwc/hwc_session.h
@@ -80,7 +80,7 @@
int GetEventValue(const char *uevent_data, int length, const char *event_info);
int HotPlugHandler(bool connected);
void ResetPanel();
- int HandleVirtualDisplayLifeCycle(hwc_display_contents_1_t *content_list);
+ void HandleVirtualDisplayLifeCycle(hwc_display_contents_1_t *content_list);
void HandleSecureDisplaySession(hwc_display_contents_1_t **displays);
// QClient methods
@@ -90,7 +90,8 @@
void SetFrameDumpConfig(const android::Parcel *input_parcel);
android::status_t SetMaxMixerStages(const android::Parcel *input_parcel);
android::status_t SetDisplayMode(const android::Parcel *input_parcel);
- android::status_t SetSecondaryDisplayStatus(const android::Parcel *input_parcel);
+ android::status_t SetSecondaryDisplayStatus(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel);
android::status_t ToggleScreenUpdates(const android::Parcel *input_parcel,
android::Parcel *output_parcel);
android::status_t ConfigureRefreshRate(const android::Parcel *input_parcel);
@@ -112,8 +113,11 @@
android::Parcel *output_parcel);
android::status_t HandleGetDisplayAttributesForConfig(const android::Parcel *input_parcel,
android::Parcel *output_parcel);
+ android::status_t GetVisibleDisplayRect(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel);
static Locker locker_;
+ static Locker concurrency_locker_;
CoreInterface *core_intf_ = NULL;
hwc_procs_t hwc_procs_default_;
hwc_procs_t const *hwc_procs_ = &hwc_procs_default_;