summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEdward Wang <ewang@cyngn.com>2016-06-29 12:41:27 -0700
committerEdward Wang <ewang@cyngn.com>2016-06-29 14:10:41 -0700
commitc005f560bc796e354a07829419a52c9884d9e5e2 (patch)
treed7713e1f8e50c08422abd918fb5fed38baef01ab
parent17f2d38f94275d9245f5df2584ad5e3ebc7135e5 (diff)
parent079eaeba924056fa4dacfa5cb2a12b0ee9c6cfe5 (diff)
downloadandroid_hardware_qcom_display-stable/cm-13.0-caf-8996-ZNH2K.tar.gz
android_hardware_qcom_display-stable/cm-13.0-caf-8996-ZNH2K.tar.bz2
android_hardware_qcom_display-stable/cm-13.0-caf-8996-ZNH2K.zip
Merge remote-tracking branch 'remotes/github/staging/LA.HB.1.3.1.c1-05300' into HEADstable/cm-13.0-caf-8996-ZNH2K
Change-Id: Iae4c1f2147aff4b1d6286bc663b0b8fe47bc7b8c Ticket: CYNGNOS-3131
-rw-r--r--libgralloc/alloc_controller.cpp9
-rw-r--r--libgralloc/alloc_controller.h7
-rw-r--r--libgralloc/gpu.cpp6
-rw-r--r--libgralloc/mapper.cpp6
-rw-r--r--libmemtrack/kgsl.c8
-rw-r--r--libqdutils/display_config.h8
-rw-r--r--sdm/include/core/buffer_allocator.h11
-rw-r--r--sdm/include/core/layer_buffer.h29
-rw-r--r--sdm/include/core/layer_stack.h4
-rw-r--r--sdm/include/private/color_params.h1
-rw-r--r--sdm/include/private/hw_info_types.h42
-rw-r--r--sdm/include/utils/debug.h1
-rw-r--r--sdm/include/utils/locker.h4
-rw-r--r--sdm/libs/core/color_manager.cpp1
-rw-r--r--sdm/libs/core/comp_manager.cpp2
-rw-r--r--sdm/libs/core/display_base.cpp41
-rw-r--r--sdm/libs/core/display_hdmi.cpp129
-rw-r--r--sdm/libs/core/display_hdmi.h6
-rw-r--r--sdm/libs/core/fb/hw_device.cpp47
-rw-r--r--sdm/libs/core/fb/hw_device.h2
-rw-r--r--sdm/libs/core/fb/hw_hdmi.cpp140
-rw-r--r--sdm/libs/core/fb/hw_hdmi.h10
-rw-r--r--sdm/libs/core/fb/hw_info.cpp38
-rw-r--r--sdm/libs/core/fb/hw_primary.cpp6
-rw-r--r--sdm/libs/core/fb/hw_primary.h1
-rw-r--r--sdm/libs/core/fb/hw_virtual.cpp4
-rw-r--r--sdm/libs/core/fb/hw_virtual.h1
-rw-r--r--sdm/libs/core/hw_interface.h1
-rw-r--r--sdm/libs/core/resource_default.cpp106
-rw-r--r--sdm/libs/core/resource_default.h30
-rw-r--r--sdm/libs/core/strategy.cpp2
-rw-r--r--sdm/libs/hwc/Android.mk8
-rw-r--r--sdm/libs/hwc/blit_engine_c2d.cpp8
-rw-r--r--sdm/libs/hwc/blit_engine_c2d.h7
-rw-r--r--sdm/libs/hwc/hwc_buffer_allocator.cpp37
-rw-r--r--sdm/libs/hwc/hwc_buffer_allocator.h1
-rw-r--r--sdm/libs/hwc/hwc_display.cpp97
-rw-r--r--sdm/libs/hwc/hwc_display.h7
-rw-r--r--[-rwxr-xr-x]sdm/libs/hwc/hwc_display_external.cpp17
-rw-r--r--[-rwxr-xr-x]sdm/libs/hwc/hwc_display_primary.cpp50
-rw-r--r--sdm/libs/hwc/hwc_display_primary.h2
-rw-r--r--sdm/libs/hwc/hwc_display_virtual.cpp14
-rw-r--r--sdm/libs/hwc/hwc_session.cpp76
-rw-r--r--sdm/libs/hwc/hwc_session.h2
-rw-r--r--sdm/libs/utils/debug.cpp7
45 files changed, 764 insertions, 272 deletions
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index 7411c38e5..430d7fda7 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -413,6 +413,10 @@ IAllocController* IAllocController::getInstance(void)
IonController::IonController()
{
allocateIonMem();
+
+ char property[PROPERTY_VALUE_MAX];
+ property_get("video.disable.ubwc", property, "0");
+ mDisableUBWCForEncode = atoi(property);
}
void IonController::allocateIonMem()
@@ -906,6 +910,11 @@ bool isUBwcEnabled(int format, int usage)
if (isUBwcFormat(format))
return true;
+ if ((usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) &&
+ gralloc::IAllocController::getInstance()->isDisableUBWCForEncoder()) {
+ return false;
+ }
+
// Allow UBWC, if an OpenGL client sets UBWC usage flag and GPU plus MDP
// support the format. OR if a non-OpenGL client like Rotator, sets UBWC
// usage flag and MDP supports the format.
diff --git a/libgralloc/alloc_controller.h b/libgralloc/alloc_controller.h
index 919e5724f..8216b0c88 100644
--- a/libgralloc/alloc_controller.h
+++ b/libgralloc/alloc_controller.h
@@ -56,6 +56,8 @@ class IAllocController {
virtual IMemAlloc* getAllocator(int flags) = 0;
+ virtual bool isDisableUBWCForEncoder();
+
virtual ~IAllocController() {};
static IAllocController* getInstance(void);
@@ -72,10 +74,15 @@ class IonController : public IAllocController {
virtual IMemAlloc* getAllocator(int flags);
+ virtual bool isDisableUBWCForEncoder() {
+ return mDisableUBWCForEncode;
+ }
+
IonController();
private:
IonAlloc* mIonAlloc;
+ bool mDisableUBWCForEncode;
void allocateIonMem();
};
diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp
index 203ab9d99..0eee65e53 100644
--- a/libgralloc/gpu.cpp
+++ b/libgralloc/gpu.cpp
@@ -136,6 +136,11 @@ int gpu_context_t::gralloc_alloc_buffer(unsigned int size, int usage,
flags |= private_handle_t::PRIV_FLAGS_CPU_RENDERED;
}
+ ColorSpace_t colorSpace = ITU_R_601;
+ if (usage & GRALLOC_USAGE_HW_CAMERA_MASK) {
+ colorSpace = ITU_R_601_FR;
+ }
+
if (usage & (GRALLOC_USAGE_HW_VIDEO_ENCODER |
GRALLOC_USAGE_HW_CAMERA_WRITE |
GRALLOC_USAGE_HW_RENDER |
@@ -160,7 +165,6 @@ int gpu_context_t::gralloc_alloc_buffer(unsigned int size, int usage,
hnd->offset = data.offset;
hnd->base = (uint64_t)(data.base) + data.offset;
hnd->gpuaddr = 0;
- ColorSpace_t colorSpace = ITU_R_601;
setMetaData(hnd, UPDATE_COLOR_SPACE, (void*) &colorSpace);
*pHandle = hnd;
diff --git a/libgralloc/mapper.cpp b/libgralloc/mapper.cpp
index dcf2ee896..421069f44 100644
--- a/libgralloc/mapper.cpp
+++ b/libgralloc/mapper.cpp
@@ -484,10 +484,10 @@ int gralloc_perform(struct gralloc_module_t const* module,
{
private_handle_t* hnd = va_arg(args, private_handle_t*);
uint32_t *enable = va_arg(args, uint32_t*);
- if (private_handle_t::validate(hnd)) {
- return res;
+ if (!private_handle_t::validate(hnd)) {
+ setMetaData(hnd, SET_SINGLE_BUFFER_MODE, enable);
+ res = 0;
}
- setMetaData(hnd, SET_SINGLE_BUFFER_MODE, enable);
} break;
default:
break;
diff --git a/libmemtrack/kgsl.c b/libmemtrack/kgsl.c
index 958859ae7..4ad94ce81 100644
--- a/libmemtrack/kgsl.c
+++ b/libmemtrack/kgsl.c
@@ -85,7 +85,7 @@ int kgsl_memtrack_get_memory(pid_t pid, enum memtrack_type type,
while (1) {
unsigned long size;
char line_type[7];
- char flags[7];
+ char flags[8];
char line_usage[19];
int ret;
@@ -95,9 +95,9 @@ int kgsl_memtrack_get_memory(pid_t pid, enum memtrack_type type,
/* Format:
* gpuaddr useraddr size id flags type usage sglen
- * 545ba000 545ba000 4096 1 ----pY gpumem arraybuffer 1
+ * 545ba000 545ba000 4096 1 -----pY gpumem arraybuffer 1
*/
- ret = sscanf(line, "%*x %*x %lu %*d %6s %6s %18s %*d\n",
+ ret = sscanf(line, "%*x %*x %lu %*d %7s %6s %18s %*d\n",
&size, flags, line_type, line_usage);
if (ret != 4) {
continue;
@@ -105,7 +105,7 @@ int kgsl_memtrack_get_memory(pid_t pid, enum memtrack_type type,
if (type == MEMTRACK_TYPE_GL && strcmp(line_type, "gpumem") == 0) {
- if (flags[5] == 'Y')
+ if (flags[6] == 'Y')
accounted_size += size;
else
unaccounted_size += size;
diff --git a/libqdutils/display_config.h b/libqdutils/display_config.h
index 2cf5c80bf..9ba60f2b8 100644
--- a/libqdutils/display_config.h
+++ b/libqdutils/display_config.h
@@ -47,10 +47,10 @@ namespace qdutils {
// Use this enum to specify the dpy parameters where needed
enum {
- DISPLAY_PRIMARY = HWC_DISPLAY_PRIMARY,
- DISPLAY_EXTERNAL = HWC_DISPLAY_EXTERNAL,
- DISPLAY_TERTIARY = HWC_DISPLAY_TERTIARY,
- DISPLAY_VIRTUAL = HWC_DISPLAY_VIRTUAL,
+ DISPLAY_PRIMARY = 0,
+ DISPLAY_EXTERNAL,
+ DISPLAY_TERTIARY,
+ DISPLAY_VIRTUAL,
};
// External Display states - used in setSecondaryDisplayStatus()
diff --git a/sdm/include/core/buffer_allocator.h b/sdm/include/core/buffer_allocator.h
index 5e8353711..0fd938886 100644
--- a/sdm/include/core/buffer_allocator.h
+++ b/sdm/include/core/buffer_allocator.h
@@ -108,6 +108,17 @@ class BufferAllocator {
*/
virtual DisplayError FreeBuffer(BufferInfo *buffer_info) = 0;
+
+ /*! @brief Method to get the buffer size.
+
+ @details This method returns buffer size for a specific configuration mentioned in buffer info.
+
+ @param[in] buffer_info \link BufferInfo \endlink
+
+ @return \link unsigned int \endlink
+ */
+ virtual uint32_t GetBufferSize(BufferInfo *buffer_info) = 0;
+
protected:
virtual ~BufferAllocator() { }
};
diff --git a/sdm/include/core/layer_buffer.h b/sdm/include/core/layer_buffer.h
index 5d48a04ac..c437dab29 100644
--- a/sdm/include/core/layer_buffer.h
+++ b/sdm/include/core/layer_buffer.h
@@ -107,6 +107,10 @@ enum LayerBufferFormat {
kFormatYCbCr420SPVenusUbwc, //!< UBWC aligned YCbCr420SemiPlanarVenus format
+ kFormatYCrCb420SemiPlanarVenus, //!< Y-plane: y(0), y(1), y(2) ... y(n)
+ //!< 2x2 subsampled interleaved UV-plane:
+ //!< v(0), u(0), v(2), u(2) ... v(n-1), u(n-1)
+
/* All YUV-Packed formats, Any new format will be added towards end of this group to maintain
backward compatibility.
*/
@@ -118,6 +122,19 @@ enum LayerBufferFormat {
kFormatInvalid = 0xFFFFFFFF,
};
+
+/*! @brief This enum represents different types of 3D formats supported.
+
+ @sa LayerBufferS3DFormat
+*/
+enum LayerBufferS3DFormat {
+ kS3dFormatNone, //!< Layer buffer content is not 3D content.
+ kS3dFormatLeftRight, //!< Left and Right view of a 3D content stitched left and right.
+ kS3dFormatRightLeft, //!< Right and Left view of a 3D content stitched left and right.
+ kS3dFormatTopBottom, //!< Left and RightView of a 3D content stitched top and bottom.
+ kS3dFormatFramePacking //!< Left and right view of 3D content coded in consecutive frames.
+};
+
/*! @brief This structure defines a color sample plane belonging to a buffer format. RGB buffer
formats have 1 plane whereas YUV buffer formats may have upto 4 planes.
@@ -149,13 +166,12 @@ struct LayerBufferFlags {
uint32_t interlace : 1; //!< This flag shall be set by the client to indicate that
//!< the buffer has interlaced content.
- uint32_t secure_display : 1;
- //!< This flag shall be set by the client to indicate that the
+ uint32_t secure_display : 1; //!< This flag shall be set by the client to indicate that the
//!< secure display session is in progress. Secure display
//!< session can not coexist with non-secure session.
- };
+ };
- uint32_t flags = 0; //!< For initialization purpose only.
+ uint32_t flags = 0; //!< For initialization purpose only.
//!< Client shall not refer to it directly.
};
};
@@ -198,6 +214,11 @@ struct LayerBuffer {
//!< read/write.
LayerBufferFlags flags; //!< Flags associated with this buffer.
+
+ LayerBufferS3DFormat s3d_format = kS3dFormatNone;
+ //!< Represents the format of the buffer content in 3D.
+ uint64_t buffer_id __attribute__((aligned(8))) = 0;
+ //!< Specifies the buffer id.
};
} // namespace sdm
diff --git a/sdm/include/core/layer_stack.h b/sdm/include/core/layer_stack.h
index 9b012026b..34c68fec6 100644
--- a/sdm/include/core/layer_stack.h
+++ b/sdm/include/core/layer_stack.h
@@ -192,6 +192,10 @@ struct LayerStackFlags {
//!< stack contains cursor layer.
uint32_t single_buffered_layer_present : 1; //!< Set if stack has single buffered layer
+
+ uint32_t s3d_mode_present : 1; //!< This flag will be set to true, if the current layer
+ //!< stack contains s3d layer, and the layer stack can enter
+ //!< s3d mode.
};
uint32_t flags = 0; //!< For initialization purpose only.
diff --git a/sdm/include/private/color_params.h b/sdm/include/private/color_params.h
index 2a261ee6c..2b0c3994f 100644
--- a/sdm/include/private/color_params.h
+++ b/sdm/include/private/color_params.h
@@ -108,6 +108,7 @@ struct PPFeatureVersion {
struct PPHWAttributes : HWResourceInfo, HWPanelInfo, DisplayConfigVariableInfo {
char panel_name[256] = "generic_panel";
PPFeatureVersion version;
+ int panel_max_brightness = 0;
void Set(const HWResourceInfo &hw_res, const HWPanelInfo &panel_info,
const DisplayConfigVariableInfo &attr, const PPFeatureVersion &feature_ver);
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index 3b668b899..9c8d0890f 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -28,6 +28,7 @@
#include <stdint.h>
#include <core/display_interface.h>
#include <core/core_interface.h>
+#include <vector>
namespace sdm {
@@ -66,12 +67,25 @@ enum HWDisplayPort {
kPortEDP,
};
+enum PipeType {
+ kPipeTypeUnused,
+ kPipeTypeVIG,
+ kPipeTypeRGB,
+ kPipeTypeDMA,
+ kPipeTypeCursor,
+};
+
struct HWDynBwLimitInfo {
uint32_t cur_mode = kBwDefault;
uint32_t total_bw_limit[kBwModeMax] = { 0 };
uint32_t pipe_bw_limit[kBwModeMax] = { 0 };
};
+struct HWPipeCaps {
+ PipeType type = kPipeTypeUnused;
+ uint32_t id = 0;
+};
+
struct HWResourceInfo {
uint32_t hw_version = 0;
uint32_t hw_revision = 0;
@@ -111,6 +125,7 @@ struct HWResourceInfo {
bool perf_calc = false;
bool has_dyn_bw_support = false;
HWDynBwLimitInfo dyn_bw_info;
+ std::vector<HWPipeCaps> hw_pipes;
void Reset() { *this = HWResourceInfo(); }
};
@@ -128,6 +143,15 @@ struct HWSplitInfo {
}
};
+enum HWS3DMode {
+ kS3DModeNone,
+ kS3DModeLR,
+ kS3DModeRL,
+ kS3DModeTB,
+ kS3DModeFP,
+ kS3DModeMax,
+};
+
struct HWPanelInfo {
HWDisplayPort port = kPortDefault; // Display port
HWDisplayMode mode = kModeDefault; // Display mode
@@ -143,8 +167,11 @@ struct HWPanelInfo {
uint32_t min_fps = 0; // Min fps supported by panel
uint32_t max_fps = 0; // Max fps supported by panel
bool is_primary_panel = false; // Panel is primary display
+ bool is_pluggable = false; // Panel is pluggable
HWSplitInfo split_info; // Panel split configuration
char panel_name[256] = {0}; // Panel name
+ HWS3DMode s3d_mode = kS3DModeNone; // Panel's current s3d mode.
+ int panel_max_brightness = 0; // Max panel brightness
bool operator !=(const HWPanelInfo &panel_info) {
return ((port != panel_info.port) || (mode != panel_info.mode) ||
@@ -156,7 +183,8 @@ struct HWPanelInfo {
(needs_roi_merge != panel_info.needs_roi_merge) ||
(dynamic_fps != panel_info.dynamic_fps) || (min_fps != panel_info.min_fps) ||
(max_fps != panel_info.max_fps) || (is_primary_panel != panel_info.is_primary_panel) ||
- (split_info != panel_info.split_info));
+ (split_info != panel_info.split_info) ||
+ (s3d_mode != panel_info.s3d_mode));
}
bool operator ==(const HWPanelInfo &panel_info) {
@@ -165,12 +193,8 @@ struct HWPanelInfo {
};
struct HWSessionConfig {
- uint32_t src_width = 0;
- uint32_t src_height = 0;
- LayerBufferFormat src_format = kFormatInvalid;
- uint32_t dst_width = 0;
- uint32_t dst_height = 0;
- LayerBufferFormat dst_format = kFormatInvalid;
+ LayerRect src_rect;
+ LayerRect dst_rect;
uint32_t buffer_count = 0;
bool secure = false;
bool cache = false;
@@ -195,6 +219,7 @@ struct HWRotatorSession {
LayerTransform transform;
HWSessionConfig hw_session_config;
LayerBuffer output_buffer;
+ LayerBuffer input_buffer;
int session_id = -1;
float input_compression = 1.0f;
float output_compression = 1.0f;
@@ -260,6 +285,8 @@ struct HWLayersInfo {
uint32_t index[kMaxSDELayers]; // Indexes of the layers from the layer stack which need to be
// programmed on hardware.
+ LayerRect updated_src_rect[kMaxSDELayers]; // Updated layer src rects in s3d mode
+ LayerRect updated_dst_rect[kMaxSDELayers]; // Updated layer dst rects in s3d mode
uint32_t count = 0; // Total number of layers which need to be set on hardware.
@@ -286,6 +313,7 @@ struct HWDisplayAttributes : DisplayConfigVariableInfo {
uint32_t v_back_porch = 0; //!< Vertical back porch of panel
uint32_t v_pulse_width = 0; //!< Vertical pulse width of panel
uint32_t h_total = 0; //!< Total width of panel (hActive + hFP + hBP + hPulseWidth)
+ uint32_t s3d_config = 0; //!< Stores the bit mask of S3D modes
void Reset() { *this = HWDisplayAttributes(); }
diff --git a/sdm/include/utils/debug.h b/sdm/include/utils/debug.h
index b4a286a08..251e195cc 100644
--- a/sdm/include/utils/debug.h
+++ b/sdm/include/utils/debug.h
@@ -64,6 +64,7 @@ class Debug {
static int GetSimulationFlag();
static int GetHDMIResolution();
static int GetIdleTimeoutMs();
+ static int GetBootAnimLayerCount();
static bool IsRotatorDownScaleDisabled();
static bool IsDecimationDisabled();
static int GetMaxPipesPerMixer(DisplayType display_type);
diff --git a/sdm/include/utils/locker.h b/sdm/include/utils/locker.h
index bc24ad5de..fffe634a2 100644
--- a/sdm/include/utils/locker.h
+++ b/sdm/include/utils/locker.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
@@ -89,7 +89,7 @@ class Locker {
explicit SequenceWaitScopeLock(Locker& locker) : locker_(locker), error_(false) {
locker_.Lock();
- if (locker_.sequence_wait_ == 1) {
+ while (locker_.sequence_wait_ == 1) {
locker_.Wait();
error_ = (locker_.sequence_wait_ == -1);
}
diff --git a/sdm/libs/core/color_manager.cpp b/sdm/libs/core/color_manager.cpp
index 1d224ade6..5dee0628b 100644
--- a/sdm/libs/core/color_manager.cpp
+++ b/sdm/libs/core/color_manager.cpp
@@ -207,6 +207,7 @@ void PPHWAttributes::Set(const HWResourceInfo &hw_res,
DisplayConfigVariableInfo &attributes = *this;
attributes = attr;
version = feature_ver;
+ panel_max_brightness = panel_info.panel_max_brightness;
if (strlen(panel_info.panel_name)) {
snprintf(&panel_name[0], sizeof(panel_name), "%s", &panel_info.panel_name[0]);
diff --git a/sdm/libs/core/comp_manager.cpp b/sdm/libs/core/comp_manager.cpp
index c08b41319..41c521333 100644
--- a/sdm/libs/core/comp_manager.cpp
+++ b/sdm/libs/core/comp_manager.cpp
@@ -418,7 +418,7 @@ bool CompManager::SupportLayerAsCursor(Handle comp_handle, HWLayers *hw_layers)
return supported;
}
- for (int32_t i = layer_stack->layer_count; i >= 0; i--) {
+ for (int32_t i = layer_stack->layer_count - 1; i >= 0; i--) {
Layer &layer = layer_stack->layers[i];
if (layer.composition == kCompositionGPUTarget) {
gpu_index = i;
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 979e48180..f0b78b3b2 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
@@ -535,11 +535,6 @@ void DisplayBase::AppendDump(char *buffer, uint32_t length) {
num_modes, active_index);
DisplayConfigVariableInfo &info = attrib;
- DumpImpl::AppendString(buffer, length, "\nres:%u x %u, dpi:%.2f x %.2f, fps:%u,"
- "vsync period: %u", info.x_pixels, info.y_pixels, info.x_dpi,
- info.y_dpi, info.fps, info.vsync_period_ns);
-
- DumpImpl::AppendString(buffer, length, "\n");
uint32_t num_hw_layers = 0;
if (hw_layers_.info.stack) {
@@ -551,6 +546,18 @@ void DisplayBase::AppendDump(char *buffer, uint32_t length) {
return;
}
+ LayerBuffer *out_buffer = hw_layers_.info.stack->output_buffer;
+ if (out_buffer) {
+ DumpImpl::AppendString(buffer, length, "\nres:%u x %u format: %s", out_buffer->width,
+ out_buffer->height, GetName(out_buffer->format));
+ } else {
+ DumpImpl::AppendString(buffer, length, "\nres:%u x %u, dpi:%.2f x %.2f, fps:%u,"
+ "vsync period: %u", info.x_pixels, info.y_pixels, info.x_dpi,
+ info.y_dpi, info.fps, info.vsync_period_ns);
+ }
+
+ DumpImpl::AppendString(buffer, length, "\n");
+
HWLayersInfo &layer_info = hw_layers_.info;
LayerRect &l_roi = layer_info.left_partial_update;
LayerRect &r_roi = layer_info.right_partial_update;
@@ -562,9 +569,9 @@ void DisplayBase::AppendDump(char *buffer, uint32_t length) {
INT(r_roi.top), INT(r_roi.right), INT(r_roi.bottom));
}
- const char *header = "\n| Idx | Comp Type | Split | WB | Pipe | W x H | Format | Src Rect (L T R B) | Dst Rect (L T R B) | Z | Flags | Deci(HxV) |"; //NOLINT
- const char *newline = "\n|-----|-------------|--------|----|-------|-------------|--------------------------|---------------------|---------------------|----|------------|-----------|"; //NOLINT
- const char *format = "\n| %3s | %11s " "| %6s " "| %2s | 0x%03x | %4d x %4d | %24s " "| %4d %4d %4d %4d " "| %4d %4d %4d %4d " "| %2s | %10s " "| %9s |"; //NOLINT
+ const char *header = "\n| Idx | Comp Type | Split | WB | Pipe | W x H | Format | Src Rect (L T R B) | Dst Rect (L T R B) | Z | Flags | Deci(HxV) | CS |"; //NOLINT
+ const char *newline = "\n|-----|-------------|--------|----|-------|-------------|--------------------------|---------------------|---------------------|----|------------|-----------|----|"; //NOLINT
+ const char *format = "\n| %3s | %11s " "| %6s " "| %2s | 0x%03x | %4d x %4d | %24s " "| %4d %4d %4d %4d " "| %4d %4d %4d %4d " "| %2s | %10s " "| %9s | %2s |"; //NOLINT
DumpImpl::AppendString(buffer, length, "\n");
DumpImpl::AppendString(buffer, length, newline);
@@ -587,7 +594,7 @@ void DisplayBase::AppendDump(char *buffer, uint32_t length) {
snprintf(idx, sizeof(idx), "%d", layer_index);
for (uint32_t count = 0; count < hw_rotator_session.hw_block_count; count++) {
- char writeback_id[8];
+ char writeback_id[8] = { 0 };
HWRotateInfo &rotate = hw_rotator_session.hw_rotate_info[count];
LayerRect &src_roi = rotate.src_roi;
LayerRect &dst_roi = rotate.dst_roi;
@@ -599,7 +606,7 @@ void DisplayBase::AppendDump(char *buffer, uint32_t length) {
input_buffer->height, buffer_format, INT(src_roi.left),
INT(src_roi.top), INT(src_roi.right), INT(src_roi.bottom),
INT(dst_roi.left), INT(dst_roi.top), INT(dst_roi.right),
- INT(dst_roi.bottom), "-", "- ", "- ");
+ INT(dst_roi.bottom), "-", "- ", "- ", "-");
// print the below only once per layer block, fill with spaces for rest.
idx[0] = 0;
@@ -612,9 +619,11 @@ void DisplayBase::AppendDump(char *buffer, uint32_t length) {
}
for (uint32_t count = 0; count < 2; count++) {
- char decimation[16];
- char flags[16];
- char z_order[8];
+ char decimation[16] = { 0 };
+ char flags[16] = { 0 };
+ char z_order[8] = { 0 };
+ char csc[8] = { 0 };
+
HWPipeInfo &pipe = (count == 0) ? layer_config.left_pipe : layer_config.right_pipe;
if (!pipe.valid) {
@@ -628,13 +637,14 @@ void DisplayBase::AppendDump(char *buffer, uint32_t length) {
snprintf(flags, sizeof(flags), "0x%08x", layer.flags.flags);
snprintf(decimation, sizeof(decimation), "%3d x %3d", pipe.horizontal_decimation,
pipe.vertical_decimation);
+ snprintf(csc, sizeof(csc), "%d", layer.csc);
DumpImpl::AppendString(buffer, length, format, idx, comp_type, comp_split[count],
"-", pipe.pipe_id, input_buffer->width, input_buffer->height,
buffer_format, INT(src_roi.left), INT(src_roi.top),
INT(src_roi.right), INT(src_roi.bottom), INT(dst_roi.left),
INT(dst_roi.top), INT(dst_roi.right), INT(dst_roi.bottom),
- z_order, flags, decimation);
+ z_order, flags, decimation, csc);
// print the below only once per layer block, fill with spaces for rest.
idx[0] = 0;
@@ -695,6 +705,7 @@ const char * DisplayBase::GetName(const LayerBufferFormat &format) {
case kFormatYCbCr420SemiPlanar: return "Y_CBCR_420";
case kFormatYCrCb420SemiPlanar: return "Y_CRCB_420";
case kFormatYCbCr420SemiPlanarVenus: return "Y_CBCR_420_VENUS";
+ case kFormatYCrCb420SemiPlanarVenus: return "Y_CRCB_420_VENUS";
case kFormatYCbCr422H1V2SemiPlanar: return "Y_CBCR_422_H1V2";
case kFormatYCrCb422H1V2SemiPlanar: return "Y_CRCB_422_H1V2";
case kFormatYCbCr422H2V1SemiPlanar: return "Y_CBCR_422_H2V1";
diff --git a/sdm/libs/core/display_hdmi.cpp b/sdm/libs/core/display_hdmi.cpp
index d812f0cfd..123e300fa 100644
--- a/sdm/libs/core/display_hdmi.cpp
+++ b/sdm/libs/core/display_hdmi.cpp
@@ -24,6 +24,8 @@
#include <utils/constants.h>
#include <utils/debug.h>
+#include <map>
+#include <utility>
#include "display_hdmi.h"
#include "hw_interface.h"
@@ -50,7 +52,14 @@ DisplayError DisplayHDMI::Init() {
return error;
}
- uint32_t active_mode_index = GetBestConfig();
+ uint32_t active_mode_index;
+ char value[64] = "0";
+ Debug::GetProperty("sdm.hdmi.s3d_enable", value);
+ if (atoi(value) != 0) {
+ active_mode_index = GetBestConfig(kS3DModeLR);
+ } else {
+ active_mode_index = GetBestConfig(kS3DModeNone);
+ }
error = hw_intf_->SetDisplayAttributes(active_mode_index);
if (error != kErrorNone) {
@@ -65,6 +74,16 @@ DisplayError DisplayHDMI::Init() {
GetScanSupport();
underscan_supported_ = (scan_support_ == kScanAlwaysUnderscanned) || (scan_support_ == kScanBoth);
+ s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode>
+ (kS3dFormatNone, kS3DModeNone));
+ s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode>
+ (kS3dFormatLeftRight, kS3DModeLR));
+ s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode>
+ (kS3dFormatRightLeft, kS3DModeRL));
+ s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode>
+ (kS3dFormatTopBottom, kS3DModeTB));
+ s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode>
+ (kS3dFormatFramePacking, kS3DModeFP));
return error;
}
@@ -79,6 +98,9 @@ DisplayError DisplayHDMI::Deinit() {
DisplayError DisplayHDMI::Prepare(LayerStack *layer_stack) {
SCOPE_LOCK(locker_);
+
+ SetS3DMode(layer_stack);
+
return DisplayBase::Prepare(layer_stack);
}
@@ -181,39 +203,50 @@ DisplayError DisplayHDMI::OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level)
return hw_intf_->OnMinHdcpEncryptionLevelChange(min_enc_level);
}
-int DisplayHDMI::GetBestConfig() {
- uint32_t best_index = 0;
+int DisplayHDMI::GetBestConfig(HWS3DMode s3d_mode) {
+ uint32_t best_index = 0, index;
uint32_t num_modes = 0;
HWDisplayAttributes best_attrib;
hw_intf_->GetNumDisplayAttributes(&num_modes);
- if (num_modes == 1) {
- return best_index;
+
+ // Get display attribute for each mode
+ HWDisplayAttributes *attrib = new HWDisplayAttributes[num_modes];
+ for (index = 0; index < num_modes; index++) {
+ hw_intf_->GetDisplayAttributes(index, &attrib[index]);
}
- hw_intf_->GetDisplayAttributes(0, &best_attrib);
-
- // From the available configs, select the best
- // Ex: 1920x1080@60Hz is better than 1920x1080@30 and 1920x1080@30 is better than 1280x720@60
- for (uint32_t index = 1; index < num_modes; index++) {
- HWDisplayAttributes current_attrib;
- hw_intf_->GetDisplayAttributes(index, &current_attrib);
- // compare the two modes: in the order of Resolution followed by refreshrate
- if (current_attrib.y_pixels > best_attrib.y_pixels) {
- best_index = index;
- } else if (current_attrib.y_pixels == best_attrib.y_pixels) {
- if (current_attrib.x_pixels > best_attrib.x_pixels) {
- best_index = index;
- } else if (current_attrib.x_pixels == best_attrib.x_pixels) {
- if (current_attrib.vsync_period_ns < best_attrib.vsync_period_ns) {
+ // Select best config for s3d_mode. If s3d is not enabled, s3d_mode is kS3DModeNone
+ for (index = 0; index < num_modes; index ++) {
+ if (IS_BIT_SET(attrib[index].s3d_config, s3d_mode)) {
+ break;
+ }
+ }
+ if (index < num_modes) {
+ best_index = index;
+ for (size_t index = best_index + 1; index < num_modes; index ++) {
+ if (!IS_BIT_SET(attrib[index].s3d_config, s3d_mode))
+ continue;
+
+ // From the available configs, select the best
+ // Ex: 1920x1080@60Hz is better than 1920x1080@30 and 1920x1080@30 is better than 1280x720@60
+ if (attrib[index].y_pixels > attrib[best_index].y_pixels) {
+ best_index = index;
+ } else if (attrib[index].y_pixels == attrib[best_index].y_pixels) {
+ if (attrib[index].x_pixels > attrib[best_index].x_pixels) {
best_index = index;
+ } else if (attrib[index].x_pixels == attrib[best_index].x_pixels) {
+ if (attrib[index].vsync_period_ns < attrib[best_index].vsync_period_ns) {
+ best_index = index;
+ }
}
}
}
- if (best_index == index) {
- best_attrib = current_attrib;
- }
+ } else {
+ DLOGW("%s, could not support S3D mode from EDID info. S3D mode is %d",
+ __FUNCTION__, s3d_mode);
}
+ delete[] attrib;
// Used for changing HDMI Resolution - override the best with user set config
uint32_t user_config = Debug::GetHDMIResolution();
@@ -271,5 +304,55 @@ DisplayError DisplayHDMI::SetCursorPosition(int x, int y) {
return DisplayBase::SetCursorPosition(x, y);
}
+void DisplayHDMI::SetS3DMode(LayerStack *layer_stack) {
+ uint32_t s3d_layer_count = 0;
+ HWS3DMode s3d_mode = kS3DModeNone;
+ HWPanelInfo panel_info;
+ HWDisplayAttributes display_attributes;
+ uint32_t active_index = 0;
+ uint32_t layer_count = layer_stack->layer_count;
+
+ // S3D mode is supported for the following scenarios:
+ // 1. Layer stack containing only one s3d layer which is not skip
+ // 2. Layer stack containing only one secure layer along with one s3d layer
+ for (uint32_t i = 0; i < layer_count; i++) {
+ Layer &layer = layer_stack->layers[i];
+ LayerBuffer *layer_buffer = layer.input_buffer;
+
+ if (layer_buffer->s3d_format != kS3dFormatNone) {
+ s3d_layer_count++;
+ if (s3d_layer_count > 1 || layer.flags.skip) {
+ s3d_mode = kS3DModeNone;
+ break;
+ }
+
+ std::map<LayerBufferS3DFormat, HWS3DMode>::iterator it =
+ s3d_format_to_mode_.find(layer_buffer->s3d_format);
+ if (it != s3d_format_to_mode_.end()) {
+ s3d_mode = it->second;
+ }
+ } else if (layer_buffer->flags.secure && layer_count > 2) {
+ s3d_mode = kS3DModeNone;
+ break;
+ }
+ }
+
+ if (hw_intf_->SetS3DMode(s3d_mode) != kErrorNone) {
+ hw_intf_->SetS3DMode(kS3DModeNone);
+ layer_stack->flags.s3d_mode_present = false;
+ } else if (s3d_mode != kS3DModeNone) {
+ layer_stack->flags.s3d_mode_present = true;
+ }
+
+ hw_intf_->GetHWPanelInfo(&panel_info);
+ hw_intf_->GetActiveConfig(&active_index);
+ hw_intf_->GetDisplayAttributes(active_index, &display_attributes);
+
+ if (panel_info != hw_panel_info_) {
+ comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes, panel_info);
+ hw_panel_info_ = panel_info;
+ }
+}
+
} // namespace sdm
diff --git a/sdm/libs/core/display_hdmi.h b/sdm/libs/core/display_hdmi.h
index ce22104e1..3d2fcc6d4 100644
--- a/sdm/libs/core/display_hdmi.h
+++ b/sdm/libs/core/display_hdmi.h
@@ -25,6 +25,8 @@
#ifndef __DISPLAY_HDMI_H__
#define __DISPLAY_HDMI_H__
+#include <map>
+
#include "display_base.h"
#include "dump_impl.h"
@@ -64,11 +66,13 @@ class DisplayHDMI : public DisplayBase, DumpImpl {
virtual DisplayError SetCursorPosition(int x, int y);
private:
- virtual int GetBestConfig();
+ virtual int GetBestConfig(HWS3DMode s3d_mode);
virtual void GetScanSupport();
+ virtual void SetS3DMode(LayerStack *layer_stack);
Locker locker_;
HWScanSupport scan_support_;
+ std::map<LayerBufferS3DFormat, HWS3DMode> s3d_format_to_mode_;
};
} // namespace sdm
diff --git a/sdm/libs/core/fb/hw_device.cpp b/sdm/libs/core/fb/hw_device.cpp
index ea6232512..0309ea693 100644
--- a/sdm/libs/core/fb/hw_device.cpp
+++ b/sdm/libs/core/fb/hw_device.cpp
@@ -43,6 +43,8 @@
#include <utils/constants.h>
#include <utils/debug.h>
#include <utils/sys.h>
+#include <vector>
+#include <algorithm>
#include "hw_device.h"
#include "hw_info_interface.h"
@@ -428,6 +430,10 @@ DisplayError HWDevice::Commit(HWLayers *hw_layers) {
// MDP returns only one release fence for the entire layer stack. Duplicate this fence into all
// layers being composed by MDP.
+
+ std::vector<uint32_t> fence_dup_flag;
+ fence_dup_flag.clear();
+
for (uint32_t i = 0; i < hw_layer_info.count; i++) {
uint32_t layer_index = hw_layer_info.index[i];
LayerBuffer *input_buffer = stack->layers[layer_index].input_buffer;
@@ -437,8 +443,14 @@ DisplayError HWDevice::Commit(HWLayers *hw_layers) {
input_buffer = &hw_rotator_session->output_buffer;
}
- input_buffer->release_fence_fd = Sys::dup_(mdp_commit.release_fence);
+ // Make sure the release fence is duplicated only once for each buffer.
+ if (std::find(fence_dup_flag.begin(), fence_dup_flag.end(), layer_index) ==
+ fence_dup_flag.end()) {
+ input_buffer->release_fence_fd = Sys::dup_(mdp_commit.release_fence);
+ fence_dup_flag.push_back(layer_index);
+ }
}
+ fence_dup_flag.clear();
hw_layer_info.sync_handle = Sys::dup_(mdp_commit.release_fence);
@@ -634,7 +646,7 @@ int HWDevice::GetFBNodeIndex(HWDeviceType device_type) {
}
break;
case kDeviceHDMI:
- if (panel_info.port == kPortDTv) {
+ if (panel_info.is_pluggable == true) {
return i;
}
break;
@@ -749,6 +761,8 @@ void HWDevice::GetHWPanelInfoByNode(int device_node, HWPanelInfo *panel_info) {
panel_info->max_fps = atoi(tokens[1]);
} else if (!strncmp(tokens[0], "primary_panel", strlen("primary_panel"))) {
panel_info->is_primary_panel = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "is_pluggable", strlen("is_pluggable"))) {
+ panel_info->is_pluggable = atoi(tokens[1]);
}
}
}
@@ -756,6 +770,7 @@ void HWDevice::GetHWPanelInfoByNode(int device_node, HWPanelInfo *panel_info) {
GetHWDisplayPortAndMode(device_node, &panel_info->port, &panel_info->mode);
GetSplitInfo(device_node, panel_info);
GetHWPanelNameByNode(device_node, panel_info);
+ GetHWPanelMaxBrightnessFromNode(panel_info);
}
void HWDevice::GetHWDisplayPortAndMode(int device_node, HWDisplayPort *port, HWDisplayMode *mode) {
@@ -838,6 +853,30 @@ void HWDevice::GetSplitInfo(int device_node, HWPanelInfo *panel_info) {
Sys::fclose_(fileptr);
}
+void HWDevice::GetHWPanelMaxBrightnessFromNode(HWPanelInfo *panel_info) {
+ char brightness[kMaxStringLength] = { 0 };
+ char kMaxBrightnessNode[64] = { 0 };
+
+ snprintf(kMaxBrightnessNode, sizeof(kMaxBrightnessNode), "%s",
+ "/sys/class/leds/lcd-backlight/max_brightness");
+
+ panel_info->panel_max_brightness = 0;
+ int fd = Sys::open_(kMaxBrightnessNode, O_RDONLY);
+ if (fd < 0) {
+ DLOGW("Failed to open max brightness node = %s, error = %s", kMaxBrightnessNode,
+ strerror(errno));
+ return;
+ }
+
+ if (Sys::pread_(fd, brightness, sizeof(brightness), 0) > 0) {
+ panel_info->panel_max_brightness = atoi(brightness);
+ DLOGW("Max brightness level = %d", panel_info->panel_max_brightness);
+ } else {
+ DLOGW("Failed to read max brightness level. error = %s", strerror(errno));
+ }
+ Sys::close_(fd);
+}
+
int HWDevice::ParseLine(char *input, char *tokens[], const uint32_t max_token, uint32_t *count) {
char *tmp_token = NULL;
char *temp_ptr;
@@ -1067,5 +1106,9 @@ ssize_t HWDevice::SysFsWrite(const char* file_node, const char* value, ssize_t l
return len;
}
+DisplayError HWDevice::SetS3DMode(HWS3DMode s3d_mode) {
+ return kErrorNotSupported;
+}
+
} // namespace sdm
diff --git a/sdm/libs/core/fb/hw_device.h b/sdm/libs/core/fb/hw_device.h
index 3f6737fe6..a0eeca634 100644
--- a/sdm/libs/core/fb/hw_device.h
+++ b/sdm/libs/core/fb/hw_device.h
@@ -73,6 +73,7 @@ class HWDevice : public HWInterface {
virtual DisplayError OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level);
virtual DisplayError GetPanelBrightness(int *level);
virtual DisplayError SetAutoRefresh(bool enable) { return kErrorNone; }
+ virtual DisplayError SetS3DMode(HWS3DMode s3d_mode);
// For HWDevice derivatives
virtual DisplayError Init(HWEventHandler *eventhandler);
@@ -103,6 +104,7 @@ class HWDevice : public HWInterface {
void GetHWPanelNameByNode(int device_node, HWPanelInfo *panel_info);
void GetHWDisplayPortAndMode(int device_node, HWDisplayPort *port, HWDisplayMode *mode);
void GetSplitInfo(int device_node, HWPanelInfo *panel_info);
+ void GetHWPanelMaxBrightnessFromNode(HWPanelInfo *panel_info);
int ParseLine(char *input, char *tokens[], const uint32_t max_token, uint32_t *count);
int ParseLine(char *input, const char *delim, 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 9c1e7c335..2d91b9d5d 100644
--- a/sdm/libs/core/fb/hw_hdmi.cpp
+++ b/sdm/libs/core/fb/hw_hdmi.cpp
@@ -36,6 +36,9 @@
#include <linux/videodev2.h>
#include <utils/debug.h>
#include <utils/sys.h>
+#include <vector>
+#include <map>
+#include <utility>
#include "hw_hdmi.h"
@@ -142,6 +145,17 @@ DisplayError HWHDMI::Init(HWEventHandler *eventhandler) {
ReadScanInfo();
+ s3d_mode_sdm_to_mdp_.insert(std::pair<HWS3DMode, msm_hdmi_s3d_mode>
+ (kS3DModeNone, HDMI_S3D_NONE));
+ s3d_mode_sdm_to_mdp_.insert(std::pair<HWS3DMode, msm_hdmi_s3d_mode>
+ (kS3DModeLR, HDMI_S3D_SIDE_BY_SIDE));
+ s3d_mode_sdm_to_mdp_.insert(std::pair<HWS3DMode, msm_hdmi_s3d_mode>
+ (kS3DModeRL, HDMI_S3D_SIDE_BY_SIDE));
+ s3d_mode_sdm_to_mdp_.insert(std::pair<HWS3DMode, msm_hdmi_s3d_mode>
+ (kS3DModeTB, HDMI_S3D_TOP_AND_BOTTOM));
+ s3d_mode_sdm_to_mdp_.insert(std::pair<HWS3DMode, msm_hdmi_s3d_mode>
+ (kS3DModeFP, HDMI_S3D_FRAME_PACKING));
+
return error;
}
@@ -245,6 +259,8 @@ DisplayError HWHDMI::GetDisplayAttributes(uint32_t index,
display_attributes->h_total += h_blanking;
}
+ GetDisplayS3DSupport(index, display_attributes);
+
return kErrorNone;
}
@@ -301,6 +317,19 @@ DisplayError HWHDMI::SetDisplayAttributes(uint32_t index) {
active_config_index_ = index;
+ // Get the supported s3d modes for current active config index
+ HWDisplayAttributes attrib;
+ GetDisplayS3DSupport(index, &attrib);
+ supported_s3d_modes_.clear();
+ supported_s3d_modes_.push_back(kS3DModeNone);
+ for (uint32_t mode = kS3DModeNone + 1; mode < kS3DModeMax; mode ++) {
+ if (IS_BIT_SET(attrib.s3d_config, (HWS3DMode)mode)) {
+ supported_s3d_modes_.push_back((HWS3DMode)mode);
+ }
+ }
+
+ SetS3DMode(kS3DModeNone);
+
return kErrorNone;
}
@@ -554,5 +583,116 @@ void HWHDMI::SetSourceProductInformation(const char *node, const char *name) {
}
}
+DisplayError HWHDMI::GetDisplayS3DSupport(uint32_t index,
+ HWDisplayAttributes *attrib) {
+ ssize_t length = -1;
+ char edid_s3d_str[kPageSize] = {'\0'};
+ char edid_s3d_path[kMaxStringLength] = {'\0'};
+ snprintf(edid_s3d_path, sizeof(edid_s3d_path), "%s%d/edid_3d_modes", fb_path_, fb_node_index_);
+
+ if (index > hdmi_mode_count_) {
+ return kErrorNotSupported;
+ }
+
+ SET_BIT(attrib->s3d_config, kS3DModeNone);
+
+ // Three level inception!
+ // The string looks like 16=SSH,4=FP:TAB:SSH,5=FP:SSH,32=FP:TAB:SSH
+ char *saveptr_l1, *saveptr_l2, *saveptr_l3;
+ char *l1, *l2, *l3;
+
+ int edid_s3d_node = Sys::open_(edid_s3d_path, O_RDONLY);
+ if (edid_s3d_node < 0) {
+ DLOGW("%s could not be opened : %s", edid_s3d_path, strerror(errno));
+ return kErrorNotSupported;
+ }
+
+ length = Sys::pread_(edid_s3d_node, edid_s3d_str, sizeof(edid_s3d_str)-1, 0);
+ if (length <= 0) {
+ Sys::close_(edid_s3d_node);
+ return kErrorNotSupported;
+ }
+
+ l1 = strtok_r(edid_s3d_str, ",", &saveptr_l1);
+ while (l1 != NULL) {
+ l2 = strtok_r(l1, "=", &saveptr_l2);
+ if (l2 != NULL) {
+ if (hdmi_modes_[index] == (uint32_t)atoi(l2)) {
+ l3 = strtok_r(saveptr_l2, ":", &saveptr_l3);
+ while (l3 != NULL) {
+ if (strncmp("SSH", l3, strlen("SSH")) == 0) {
+ SET_BIT(attrib->s3d_config, kS3DModeLR);
+ SET_BIT(attrib->s3d_config, kS3DModeRL);
+ } else if (strncmp("TAB", l3, strlen("TAB")) == 0) {
+ SET_BIT(attrib->s3d_config, kS3DModeTB);
+ } else if (strncmp("FP", l3, strlen("FP")) == 0) {
+ SET_BIT(attrib->s3d_config, kS3DModeFP);
+ }
+ l3 = strtok_r(NULL, ":", &saveptr_l3);
+ }
+ }
+ }
+ l1 = strtok_r(NULL, ",", &saveptr_l1);
+ }
+
+ Sys::close_(edid_s3d_node);
+ return kErrorNone;
+}
+
+bool HWHDMI::IsSupportedS3DMode(HWS3DMode s3d_mode) {
+ for (uint32_t i = 0; i < supported_s3d_modes_.size(); i++) {
+ if (supported_s3d_modes_[i] == s3d_mode) {
+ return true;
+ }
+ }
+ return false;
+}
+
+DisplayError HWHDMI::SetS3DMode(HWS3DMode s3d_mode) {
+ if (!IsSupportedS3DMode(s3d_mode)) {
+ DLOGW("S3D mode is not supported s3d_mode = %d", s3d_mode);
+ return kErrorNotSupported;
+ }
+
+ std::map<HWS3DMode, msm_hdmi_s3d_mode>::iterator it = s3d_mode_sdm_to_mdp_.find(s3d_mode);
+ if (it == s3d_mode_sdm_to_mdp_.end()) {
+ return kErrorNotSupported;
+ }
+ msm_hdmi_s3d_mode s3d_mdp_mode = it->second;
+
+ if (active_mdp_s3d_mode_ == s3d_mdp_mode) {
+ // HDMI_S3D_SIDE_BY_SIDE is an mdp mapping for kS3DModeLR and kS3DModeRL s3d modes. So no need
+ // to update the s3d_mode node. hw_panel_info needs to be updated to differentiate these two s3d
+ // modes in strategy
+ hw_panel_info_.s3d_mode = s3d_mode;
+ return kErrorNone;
+ }
+
+ ssize_t length = -1;
+ char s3d_mode_path[kMaxStringLength] = {'\0'};
+ char s3d_mode_string[kMaxStringLength] = {'\0'};
+ snprintf(s3d_mode_path, sizeof(s3d_mode_path), "%s%d/s3d_mode", fb_path_, fb_node_index_);
+
+ int s3d_mode_node = Sys::open_(s3d_mode_path, O_RDWR);
+ if (s3d_mode_node < 0) {
+ DLOGW("%s could not be opened : %s", s3d_mode_path, strerror(errno));
+ return kErrorNotSupported;
+ }
+
+ snprintf(s3d_mode_string, sizeof(s3d_mode_string), "%d", s3d_mdp_mode);
+ length = Sys::pwrite_(s3d_mode_node, s3d_mode_string, sizeof(s3d_mode_string), 0);
+ if (length <= 0) {
+ DLOGW("Failed to write into s3d node: %s", strerror(errno));
+ Sys::close_(s3d_mode_node);
+ return kErrorNotSupported;
+ }
+
+ active_mdp_s3d_mode_ = s3d_mdp_mode;
+ Sys::close_(s3d_mode_node);
+
+ DLOGI_IF(kTagDriverConfig, "s3d mode %d", hw_panel_info_.s3d_mode);
+ return kErrorNone;
+}
+
} // namespace sdm
diff --git a/sdm/libs/core/fb/hw_hdmi.h b/sdm/libs/core/fb/hw_hdmi.h
index 2457ee0c6..09eab2372 100644
--- a/sdm/libs/core/fb/hw_hdmi.h
+++ b/sdm/libs/core/fb/hw_hdmi.h
@@ -26,6 +26,9 @@
#define __HW_HDMI_H__
#include <video/msm_hdmi_modes.h>
+#include <map>
+#include <vector>
+
#include "hw_device.h"
namespace sdm {
@@ -52,6 +55,7 @@ class HWHDMI : public HWDevice {
virtual DisplayError SetDisplayAttributes(uint32_t index);
virtual DisplayError GetConfigIndex(uint32_t mode, uint32_t *index);
virtual DisplayError Validate(HWLayers *hw_layers);
+ virtual DisplayError SetS3DMode(HWS3DMode s3d_mode);
private:
DisplayError ReadEDIDInfo();
@@ -63,6 +67,9 @@ class HWHDMI : public HWDevice {
bool ReadResolutionFile(char *config_buffer);
bool IsResolutionFilePresent();
void SetSourceProductInformation(const char *node, const char *name);
+ DisplayError GetDisplayS3DSupport(uint32_t num_modes,
+ HWDisplayAttributes *attrib);
+ bool IsSupportedS3DMode(HWS3DMode s3d_mode);
uint32_t hdmi_mode_count_;
uint32_t hdmi_modes_[256];
@@ -70,6 +77,9 @@ class HWHDMI : public HWDevice {
msm_hdmi_mode_timing_info *supported_video_modes_;
HWScanInfo hw_scan_info_;
uint32_t active_config_index_;
+ std::map<HWS3DMode, msm_hdmi_s3d_mode> s3d_mode_sdm_to_mdp_;
+ std::vector<HWS3DMode> supported_s3d_modes_;
+ int active_mdp_s3d_mode_ = HDMI_S3D_NONE;
};
} // namespace sdm
diff --git a/sdm/libs/core/fb/hw_info.cpp b/sdm/libs/core/fb/hw_info.cpp
index e163f9a56..1bd8e8c70 100644
--- a/sdm/libs/core/fb/hw_info.cpp
+++ b/sdm/libs/core/fb/hw_info.cpp
@@ -41,7 +41,7 @@ int HWInfo::ParseLine(char *input, char *tokens[], const uint32_t max_token, uin
char *tmp_token = NULL;
char *temp_ptr;
uint32_t index = 0;
- const char *delim = ", =\n";
+ const char *delim = ":, =\n";
if (!input) {
return -1;
}
@@ -166,14 +166,6 @@ DisplayError HWInfo::GetHWResourceInfo(HWResourceInfo *hw_resource) {
if (!ParseLine(line, tokens, max_count, &token_count)) {
if (!strncmp(tokens[0], "hw_rev", strlen("hw_rev"))) {
hw_resource->hw_revision = UINT32(atoi(tokens[1])); // HW Rev, v1/v2
- } else if (!strncmp(tokens[0], "rgb_pipes", strlen("rgb_pipes"))) {
- hw_resource->num_rgb_pipe = UINT8(atoi(tokens[1]));
- } else if (!strncmp(tokens[0], "vig_pipes", strlen("vig_pipes"))) {
- hw_resource->num_vig_pipe = UINT8(atoi(tokens[1]));
- } else if (!strncmp(tokens[0], "dma_pipes", strlen("dma_pipes"))) {
- hw_resource->num_dma_pipe = UINT8(atoi(tokens[1]));
- } else if (!strncmp(tokens[0], "cursor_pipes", strlen("cursor_pipes"))) {
- hw_resource->num_cursor_pipe = UINT8(atoi(tokens[1]));
} else if (!strncmp(tokens[0], "blending_stages", strlen("blending_stages"))) {
hw_resource->num_blending_stages = UINT8(atoi(tokens[1]));
} else if (!strncmp(tokens[0], "max_downscale_ratio", strlen("max_downscale_ratio"))) {
@@ -226,6 +218,34 @@ DisplayError HWInfo::GetHWResourceInfo(HWResourceInfo *hw_resource) {
hw_resource->has_dyn_bw_support = true;
}
}
+ } else if (!strncmp(tokens[0], "pipe_count", strlen("pipe_count"))) {
+ uint32_t pipe_count = UINT8(atoi(tokens[1]));
+ for (uint32_t i = 0; i < pipe_count; i++) {
+ read = Sys::getline_(&line, &len, fileptr);
+ if (!ParseLine(line, tokens, max_count, &token_count)) {
+ HWPipeCaps pipe_caps;
+ for (uint32_t j = 0; j < token_count; j += 2) {
+ if (!strncmp(tokens[j], "pipe_type", strlen("pipe_type"))) {
+ if (!strncmp(tokens[j+1], "vig", strlen("vig"))) {
+ pipe_caps.type = kPipeTypeVIG;
+ hw_resource->num_vig_pipe++;
+ } else if (!strncmp(tokens[j+1], "rgb", strlen("rgb"))) {
+ pipe_caps.type = kPipeTypeRGB;
+ hw_resource->num_rgb_pipe++;
+ } else if (!strncmp(tokens[j+1], "dma", strlen("dma"))) {
+ pipe_caps.type = kPipeTypeDMA;
+ hw_resource->num_dma_pipe++;
+ } else if (!strncmp(tokens[j+1], "cursor", strlen("cursor"))) {
+ pipe_caps.type = kPipeTypeCursor;
+ hw_resource->num_cursor_pipe++;
+ }
+ } else if (!strncmp(tokens[j], "pipe_ndx", strlen("pipe_ndx"))) {
+ pipe_caps.id = UINT32(atoi(tokens[j+1]));
+ }
+ }
+ hw_resource->hw_pipes.push_back(pipe_caps);
+ }
+ }
}
}
}
diff --git a/sdm/libs/core/fb/hw_primary.cpp b/sdm/libs/core/fb/hw_primary.cpp
index 9a2c897cf..93d1f42e3 100644
--- a/sdm/libs/core/fb/hw_primary.cpp
+++ b/sdm/libs/core/fb/hw_primary.cpp
@@ -669,10 +669,16 @@ DisplayError HWPrimary::SetAutoRefresh(bool enable) {
char buffer[kWriteLength] = {'\0'};
ssize_t bytes = snprintf(buffer, kWriteLength, "%d", enable);
+ if (enable == auto_refresh_) {
+ return kErrorNone;
+ }
+
if (HWDevice::SysFsWrite(kAutoRefreshNode, buffer, bytes) <= 0) { // Returns bytes written
return kErrorUndefined;
}
+ auto_refresh_ = enable;
+
return kErrorNone;
}
diff --git a/sdm/libs/core/fb/hw_primary.h b/sdm/libs/core/fb/hw_primary.h
index 629171e55..9e2cea351 100644
--- a/sdm/libs/core/fb/hw_primary.h
+++ b/sdm/libs/core/fb/hw_primary.h
@@ -96,6 +96,7 @@ class HWPrimary : public HWDevice {
uint32_t active_config_index_ = 0;
const char *kBrightnessNode = "/sys/class/leds/lcd-backlight/brightness";
const char *kAutoRefreshNode = "/sys/devices/virtual/graphics/fb0/msm_cmd_autorefresh_en";
+ bool auto_refresh_ = false;
};
} // namespace sdm
diff --git a/sdm/libs/core/fb/hw_virtual.cpp b/sdm/libs/core/fb/hw_virtual.cpp
index 27c979ae4..033159f44 100644
--- a/sdm/libs/core/fb/hw_virtual.cpp
+++ b/sdm/libs/core/fb/hw_virtual.cpp
@@ -74,9 +74,5 @@ DisplayError HWVirtual::Validate(HWLayers *hw_layers) {
return HWDevice::Validate(hw_layers);
}
-DisplayError HWVirtual::Flush() {
- return kErrorNone;
-}
-
} // namespace sdm
diff --git a/sdm/libs/core/fb/hw_virtual.h b/sdm/libs/core/fb/hw_virtual.h
index c0591b310..2b740d565 100644
--- a/sdm/libs/core/fb/hw_virtual.h
+++ b/sdm/libs/core/fb/hw_virtual.h
@@ -39,7 +39,6 @@ class HWVirtual : public HWDevice {
HWVirtual(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf);
virtual DisplayError Init(HWEventHandler *eventhandler);
virtual DisplayError Validate(HWLayers *hw_layers);
- virtual DisplayError Flush();
};
} // namespace sdm
diff --git a/sdm/libs/core/hw_interface.h b/sdm/libs/core/hw_interface.h
index c9c73b9c7..9e9114f24 100644
--- a/sdm/libs/core/hw_interface.h
+++ b/sdm/libs/core/hw_interface.h
@@ -91,6 +91,7 @@ class HWInterface {
virtual DisplayError OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) = 0;
virtual DisplayError GetPanelBrightness(int *level) = 0;
virtual DisplayError SetAutoRefresh(bool enable) = 0;
+ virtual DisplayError SetS3DMode(HWS3DMode s3d_mode) = 0;
protected:
virtual ~HWInterface() { }
diff --git a/sdm/libs/core/resource_default.cpp b/sdm/libs/core/resource_default.cpp
index ca73c36c6..46582b8d6 100644
--- a/sdm/libs/core/resource_default.cpp
+++ b/sdm/libs/core/resource_default.cpp
@@ -36,38 +36,40 @@ namespace sdm {
DisplayError ResourceDefault::Init(const HWResourceInfo &hw_res_info) {
DisplayError error = kErrorNone;
- uint32_t num_pipe = 0;
- num_pipe = hw_res_info.num_vig_pipe + hw_res_info.num_rgb_pipe + hw_res_info.num_dma_pipe;
+ num_pipe_ = hw_res_info.num_vig_pipe + hw_res_info.num_rgb_pipe + hw_res_info.num_dma_pipe;
- if (num_pipe > kPipeIdMax) {
- DLOGE("Number of pipe is over the limit! %d", num_pipe);
+ if (!num_pipe_) {
+ DLOGE("Number of H/W pipes is Zero!");
return kErrorParameters;
}
- num_pipe_ = num_pipe;
+ src_pipes_ = new SourcePipe[num_pipe_];
hw_res_info_ = hw_res_info;
- // Init pipe info
- vig_pipes_ = &src_pipes_[0];
- rgb_pipes_ = &src_pipes_[hw_res_info_.num_vig_pipe];
- dma_pipes_ = &src_pipes_[hw_res_info_.num_vig_pipe + hw_res_info_.num_rgb_pipe];
-
- for (uint32_t i = 0; i < hw_res_info_.num_vig_pipe; i++) {
- vig_pipes_[i].type = kPipeTypeVIG;
- vig_pipes_[i].index = i;
- vig_pipes_[i].mdss_pipe_id = GetMdssPipeId(vig_pipes_[i].type, i);
- }
- for (uint32_t i = 0; i < hw_res_info_.num_rgb_pipe; i++) {
- rgb_pipes_[i].type = kPipeTypeRGB;
- rgb_pipes_[i].index = i + hw_res_info_.num_vig_pipe;
- rgb_pipes_[i].mdss_pipe_id = GetMdssPipeId(rgb_pipes_[i].type, i);
- }
+ // Priority order of pipes: VIG, RGB, DMA
+ uint32_t vig_index = 0;
+ uint32_t rgb_index = hw_res_info_.num_vig_pipe;
+ uint32_t dma_index = rgb_index + hw_res_info_.num_rgb_pipe;
- for (uint32_t i = 0; i < hw_res_info_.num_dma_pipe; i++) {
- dma_pipes_[i].type = kPipeTypeDMA;
- dma_pipes_[i].index = i + hw_res_info_.num_vig_pipe + hw_res_info_.num_rgb_pipe;
- dma_pipes_[i].mdss_pipe_id = GetMdssPipeId(dma_pipes_[i].type, i);
+ for (uint32_t i = 0; i < num_pipe_; i++) {
+ const HWPipeCaps &pipe_caps = hw_res_info_.hw_pipes.at(i);
+ if (pipe_caps.type == kPipeTypeVIG) {
+ src_pipes_[vig_index].type = kPipeTypeVIG;
+ src_pipes_[vig_index].index = i;
+ src_pipes_[vig_index].mdss_pipe_id = pipe_caps.id;
+ vig_index++;
+ } else if (pipe_caps.type == kPipeTypeRGB) {
+ src_pipes_[rgb_index].type = kPipeTypeRGB;
+ src_pipes_[rgb_index].index = i;
+ src_pipes_[rgb_index].mdss_pipe_id = pipe_caps.id;
+ rgb_index++;
+ } else if (pipe_caps.type == kPipeTypeDMA) {
+ src_pipes_[dma_index].type = kPipeTypeDMA;
+ src_pipes_[dma_index].index = i;
+ src_pipes_[dma_index].mdss_pipe_id = pipe_caps.id;
+ dma_index++;
+ }
}
for (uint32_t i = 0; i < num_pipe_; i++) {
@@ -86,14 +88,16 @@ DisplayError ResourceDefault::Init(const HWResourceInfo &hw_res_info) {
// TODO(user): clean it up, query from driver for initial pipe status.
#ifndef SDM_VIRTUAL_DRIVER
- rgb_pipes_[0].owner = kPipeOwnerKernelMode;
- rgb_pipes_[1].owner = kPipeOwnerKernelMode;
+ rgb_index = hw_res_info_.num_vig_pipe;
+ src_pipes_[rgb_index].owner = kPipeOwnerKernelMode;
+ src_pipes_[rgb_index + 1].owner = kPipeOwnerKernelMode;
#endif
return error;
}
DisplayError ResourceDefault::Deinit() {
+ delete[] src_pipes_;
return kErrorNone;
}
@@ -212,8 +216,8 @@ DisplayError ResourceDefault::Acquire(Handle display_ctx, HWLayers *hw_layers) {
}
}
- uint32_t left_index = kPipeIdMax;
- uint32_t right_index = kPipeIdMax;
+ uint32_t left_index = num_pipe_;
+ uint32_t right_index = num_pipe_;
bool need_scale = false;
struct HWLayerConfig &layer_config = hw_layers->config[0];
@@ -332,45 +336,9 @@ DisplayError ResourceDefault::SetMaxMixerStages(Handle display_ctx, uint32_t max
return kErrorNone;
}
-uint32_t ResourceDefault::GetMdssPipeId(PipeType type, uint32_t index) {
- uint32_t mdss_id = kPipeIdMax;
- switch (type) {
- case kPipeTypeVIG:
- if (index < 3) {
- mdss_id = kPipeIdVIG0 + index;
- } else if (index == 3) {
- mdss_id = kPipeIdVIG3;
- } else {
- DLOGE("vig pipe index is over the limit! %d", index);
- }
- break;
- case kPipeTypeRGB:
- if (index < 3) {
- mdss_id = kPipeIdRGB0 + index;
- } else if (index == 3) {
- mdss_id = kPipeIdRGB3;
- } else {
- DLOGE("rgb pipe index is over the limit! %d", index);
- }
- break;
- case kPipeTypeDMA:
- if (index < 2) {
- mdss_id = kPipeIdDMA0 + index;
- } else {
- DLOGE("dma pipe index is over the limit! %d", index);
- }
- break;
- default:
- DLOGE("wrong pipe type! %d", type);
- break;
- }
-
- return (1 << mdss_id);
-}
-
uint32_t ResourceDefault::SearchPipe(HWBlockType hw_block_id, SourcePipe *src_pipes,
uint32_t num_pipe) {
- uint32_t index = kPipeIdMax;
+ uint32_t index = num_pipe_;
SourcePipe *src_pipe;
// search the pipe being used
@@ -392,16 +360,16 @@ uint32_t ResourceDefault::NextPipe(PipeType type, HWBlockType hw_block_id) {
switch (type) {
case kPipeTypeVIG:
- src_pipes = vig_pipes_;
+ src_pipes = &src_pipes_[0];
num_pipe = hw_res_info_.num_vig_pipe;
break;
case kPipeTypeRGB:
- src_pipes = rgb_pipes_;
+ src_pipes = &src_pipes_[hw_res_info_.num_vig_pipe];
num_pipe = hw_res_info_.num_rgb_pipe;
break;
case kPipeTypeDMA:
default:
- src_pipes = dma_pipes_;
+ src_pipes = &src_pipes_[hw_res_info_.num_vig_pipe + hw_res_info_.num_rgb_pipe];
num_pipe = hw_res_info_.num_dma_pipe;
break;
}
@@ -410,7 +378,7 @@ uint32_t ResourceDefault::NextPipe(PipeType type, HWBlockType hw_block_id) {
}
uint32_t ResourceDefault::GetPipe(HWBlockType hw_block_id, bool need_scale) {
- uint32_t index = kPipeIdMax;
+ uint32_t index = num_pipe_;
// The default behavior is to assume RGB and VG pipes have scalars
if (!need_scale) {
diff --git a/sdm/libs/core/resource_default.h b/sdm/libs/core/resource_default.h
index 67bb0fd3c..1dc51ad79 100644
--- a/sdm/libs/core/resource_default.h
+++ b/sdm/libs/core/resource_default.h
@@ -56,28 +56,6 @@ class ResourceDefault : public ResourceInterface {
DisplayError SetMaxBandwidthMode(HWBwModes mode);
private:
- enum PipeId {
- kPipeIdVIG0,
- kPipeIdVIG1,
- kPipeIdVIG2,
- kPipeIdRGB0,
- kPipeIdRGB1,
- kPipeIdRGB2,
- kPipeIdDMA0,
- kPipeIdDMA1,
- kPipeIdVIG3,
- kPipeIdRGB3,
- kPipeIdMax,
- };
-
- enum PipeType {
- kPipeTypeUnused,
- kPipeTypeVIG,
- kPipeTypeRGB,
- kPipeTypeDMA,
- kPipeTypeMax,
- };
-
enum PipeOwner {
kPipeOwnerUserMode, // Pipe state when it is available for reservation
kPipeOwnerKernelMode, // Pipe state when pipe is owned by kernel
@@ -96,7 +74,7 @@ class ResourceDefault : public ResourceInterface {
HWBlockType hw_block_id;
int priority;
- SourcePipe() : type(kPipeTypeUnused), owner(kPipeOwnerUserMode), mdss_pipe_id(kPipeIdMax),
+ SourcePipe() : type(kPipeTypeUnused), owner(kPipeOwnerUserMode), mdss_pipe_id(0),
index(0), hw_block_id(kHWBlockMax), priority(0) { }
inline void ResetState() { hw_block_id = kHWBlockMax;}
@@ -115,7 +93,6 @@ class ResourceDefault : public ResourceInterface {
HWBlockContext() : is_in_use(false) { }
};
- uint32_t GetMdssPipeId(PipeType pipe_type, uint32_t index);
uint32_t NextPipe(PipeType pipe_type, HWBlockType hw_block_id);
uint32_t SearchPipe(HWBlockType hw_block_id, SourcePipe *src_pipes, uint32_t num_pipe);
uint32_t GetPipe(HWBlockType hw_block_id, bool need_scale);
@@ -146,11 +123,8 @@ class ResourceDefault : public ResourceInterface {
Locker locker_;
HWResourceInfo hw_res_info_;
HWBlockContext hw_block_ctx_[kHWBlockMax];
- SourcePipe src_pipes_[kPipeIdMax];
+ SourcePipe *src_pipes_ = NULL;
uint32_t num_pipe_ = 0;
- SourcePipe *vig_pipes_ = NULL;
- SourcePipe *rgb_pipes_ = NULL;
- SourcePipe *dma_pipes_ = NULL;
};
} // namespace sdm
diff --git a/sdm/libs/core/strategy.cpp b/sdm/libs/core/strategy.cpp
index 0b7bd3cdf..582fda7d3 100644
--- a/sdm/libs/core/strategy.cpp
+++ b/sdm/libs/core/strategy.cpp
@@ -138,6 +138,8 @@ DisplayError Strategy::GetNextStrategy(StrategyConstraints *constraints) {
for (uint32_t i = 0; i < layer_stack->layer_count; i++) {
LayerComposition &composition = layer_stack->layers[i].composition;
if (composition == kCompositionGPUTarget) {
+ hw_layers_info_->updated_src_rect[hw_layer_count] = layer_stack->layers[i].src_rect;
+ hw_layers_info_->updated_dst_rect[hw_layer_count] = layer_stack->layers[i].dst_rect;
hw_layers_info_->index[hw_layer_count++] = i;
} else if (composition != kCompositionBlitTarget) {
composition = kCompositionGPU;
diff --git a/sdm/libs/hwc/Android.mk b/sdm/libs/hwc/Android.mk
index 93b5acc64..ead0034fb 100644
--- a/sdm/libs/hwc/Android.mk
+++ b/sdm/libs/hwc/Android.mk
@@ -13,7 +13,7 @@ LOCAL_C_INCLUDES := $(call project-path-for,qcom-display)/sdm/inclu
LOCAL_CFLAGS := -Wno-missing-field-initializers -Wno-unused-parameter \
-Wall -Werror -std=c++11 -fcolor-diagnostics\
- -DLOG_TAG=\"SDM\"
+ -DLOG_TAG=\"SDM\" -DDEBUG_CALC_FPS
LOCAL_CLANG := true
# TODO: Move this to the common makefile
@@ -21,6 +21,12 @@ ifeq ($(call is-board-platform-in-list, msm8996),true)
LOCAL_CFLAGS += -DMASTER_SIDE_CP
endif
+
+ifeq ($(TARGET_USES_QCOM_BSP),true)
+# Enable QCOM Display features
+LOCAL_CFLAGS += -DQTI_BSP
+endif
+
LOCAL_SHARED_LIBRARIES := libsdmcore libqservice libbinder libhardware libhardware_legacy \
libutils libcutils libsync libmemalloc libqdutils libdl \
libpowermanager libsdmutils libc++
diff --git a/sdm/libs/hwc/blit_engine_c2d.cpp b/sdm/libs/hwc/blit_engine_c2d.cpp
index be8c6f962..a7f621d54 100644
--- a/sdm/libs/hwc/blit_engine_c2d.cpp
+++ b/sdm/libs/hwc/blit_engine_c2d.cpp
@@ -57,6 +57,7 @@
#include <utils/rect.h>
#include "blit_engine_c2d.h"
+#include "hwc_debugger.h"
#define __CLASS__ "BlitEngineC2D"
@@ -88,11 +89,13 @@ int BlitEngineC2d::RegionIterator::iterate(copybit_region_t const *self, copybit
return 0;
}
-BlitEngineC2d::BlitEngineC2d() : blit_active_(false), dump_frame_count_(0), dump_frame_index_(0) {
+BlitEngineC2d::BlitEngineC2d() {
for (uint32_t i = 0; i < kNumBlitTargetBuffers; i++) {
blit_target_buffer_[i] = NULL;
release_fence_fd_[i] = -1;
}
+
+ HWCDebugHandler::Get()->GetProperty("persist.hwc.blit.comp", &blit_supported_);
}
BlitEngineC2d::~BlitEngineC2d() {
@@ -250,8 +253,7 @@ int BlitEngineC2d::Prepare(LayerStack *layer_stack) {
for (i = 0; i < layer_stack->layer_count; i++) {
Layer &layer = layer_stack->layers[i];
- if (IsUBWCFormat(layer.input_buffer->format)) {
- // UBWC is not currently supported
+ if (!blit_supported_) {
return -1;
}
if (layer.composition == kCompositionGPUTarget) {
diff --git a/sdm/libs/hwc/blit_engine_c2d.h b/sdm/libs/hwc/blit_engine_c2d.h
index 74c4b813e..5400611b9 100644
--- a/sdm/libs/hwc/blit_engine_c2d.h
+++ b/sdm/libs/hwc/blit_engine_c2d.h
@@ -112,9 +112,10 @@ class BlitEngineC2d : public BlitEngine {
int release_fence_fd_[kNumBlitTargetBuffers];
uint32_t num_blit_target_;
int blit_target_start_index_;
- bool blit_active_;
- uint32_t dump_frame_count_;
- uint32_t dump_frame_index_;
+ bool blit_active_ = false;
+ uint32_t dump_frame_count_ = 0;
+ uint32_t dump_frame_index_ = 0;
+ int blit_supported_ = 0;
};
} // namespace sdm
diff --git a/sdm/libs/hwc/hwc_buffer_allocator.cpp b/sdm/libs/hwc/hwc_buffer_allocator.cpp
index 314971847..10c719bde 100644
--- a/sdm/libs/hwc/hwc_buffer_allocator.cpp
+++ b/sdm/libs/hwc/hwc_buffer_allocator.cpp
@@ -150,6 +150,42 @@ DisplayError HWCBufferAllocator::FreeBuffer(BufferInfo *buffer_info) {
return kErrorNone;
}
+uint32_t HWCBufferAllocator::GetBufferSize(BufferInfo *buffer_info) {
+ uint32_t align = getpagesize();
+
+ const BufferConfig &buffer_config = buffer_info->buffer_config;
+
+ int alloc_flags = INT(GRALLOC_USAGE_PRIVATE_IOMMU_HEAP);
+
+ int width = INT(buffer_config.width);
+ int height = INT(buffer_config.height);
+ int format;
+
+ if (buffer_config.secure) {
+ alloc_flags = INT(GRALLOC_USAGE_PRIVATE_MM_HEAP);
+ alloc_flags |= INT(GRALLOC_USAGE_PROTECTED);
+ align = SECURE_ALIGN;
+ }
+
+ if (buffer_config.cache == false) {
+ // Allocate uncached buffers
+ alloc_flags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
+ }
+
+ if (SetBufferInfo(buffer_config.format, &format, &alloc_flags) < 0) {
+ return 0;
+ }
+
+ int aligned_width = 0;
+ int aligned_height = 0;
+ uint32_t buffer_size = getBufferSizeAndDimensions(width, height, format, alloc_flags,
+ aligned_width, aligned_height);
+
+ buffer_size = ROUND_UP(buffer_size, align) * buffer_config.buffer_count;
+
+ return buffer_size;
+}
+
int HWCBufferAllocator::SetBufferInfo(LayerBufferFormat format, int *target, int *flags) {
switch (format) {
case kFormatRGBA8888: *target = HAL_PIXEL_FORMAT_RGBA_8888; break;
@@ -164,6 +200,7 @@ int HWCBufferAllocator::SetBufferInfo(LayerBufferFormat format, int *target, int
case kFormatYCbCr422H2V1Packed: *target = HAL_PIXEL_FORMAT_YCbCr_422_I; break;
case kFormatYCbCr422H2V1SemiPlanar: *target = HAL_PIXEL_FORMAT_YCbCr_422_SP; break;
case kFormatYCbCr420SemiPlanarVenus: *target = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS; break;
+ case kFormatYCrCb420SemiPlanarVenus: *target = HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS; break;
case kFormatYCbCr420SPVenusUbwc: *target = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC; break;
case kFormatRGBA5551: *target = HAL_PIXEL_FORMAT_RGBA_5551; break;
case kFormatRGBA4444: *target = HAL_PIXEL_FORMAT_RGBA_4444; break;
diff --git a/sdm/libs/hwc/hwc_buffer_allocator.h b/sdm/libs/hwc/hwc_buffer_allocator.h
index b3f8add63..e576fe81e 100644
--- a/sdm/libs/hwc/hwc_buffer_allocator.h
+++ b/sdm/libs/hwc/hwc_buffer_allocator.h
@@ -48,6 +48,7 @@ class HWCBufferAllocator : public BufferAllocator {
DisplayError AllocateBuffer(BufferInfo *buffer_info);
DisplayError FreeBuffer(BufferInfo *buffer_info);
+ uint32_t GetBufferSize(BufferInfo *buffer_info);
private:
struct MetaBufferInfo {
diff --git a/sdm/libs/hwc/hwc_display.cpp b/sdm/libs/hwc/hwc_display.cpp
index a3b8a9084..ebb5c7b28 100644
--- a/sdm/libs/hwc/hwc_display.cpp
+++ b/sdm/libs/hwc/hwc_display.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2016, 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,17 +36,19 @@
#include <utils/debug.h>
#include <sync/sync.h>
#include <cutils/properties.h>
+#include <map>
+#include <utility>
#include "hwc_display.h"
#include "hwc_debugger.h"
#include "blit_engine_c2d.h"
-#define __CLASS__ "HWCDisplay"
-
-#if 0
-#include <exhwcomposer_defs.h>
+#ifdef QTI_BSP
+#include <hardware/display_defs.h>
#endif
+#define __CLASS__ "HWCDisplay"
+
namespace sdm {
static void AssignLayerRegionsAddress(LayerRectArray *region, uint32_t rect_count,
@@ -112,6 +114,14 @@ int HWCDisplay::Init() {
display_intf_->GetRefreshRateRange(&min_refresh_rate_, &max_refresh_rate_);
current_refresh_rate_ = max_refresh_rate_;
+ s3d_format_hwc_to_sdm_.insert(std::pair<int, LayerBufferS3DFormat>(HAL_NO_3D, kS3dFormatNone));
+ s3d_format_hwc_to_sdm_.insert(std::pair<int, LayerBufferS3DFormat>(HAL_3D_SIDE_BY_SIDE_L_R,
+ kS3dFormatLeftRight));
+ s3d_format_hwc_to_sdm_.insert(std::pair<int, LayerBufferS3DFormat>(HAL_3D_SIDE_BY_SIDE_R_L,
+ kS3dFormatRightLeft));
+ s3d_format_hwc_to_sdm_.insert(std::pair<int, LayerBufferS3DFormat>(HAL_3D_TOP_BOTTOM,
+ kS3dFormatTopBottom));
+
return 0;
}
@@ -245,11 +255,6 @@ int HWCDisplay::GetDisplayAttributes(uint32_t config, const uint32_t *attributes
case HWC_DISPLAY_DPI_Y:
values[i] = INT32(variable_config.y_dpi * 1000.0f);
break;
-#if 0
- case HWC_DISPLAY_SECURE:
- values[i] = INT32(true); // For backward compatibility. All Physical displays are secure
- break;
-#endif
default:
DLOGW("Spurious attribute type = %d", attributes[i]);
return -EINVAL;
@@ -567,10 +572,9 @@ int HWCDisplay::PrePrepareLayerStack(hwc_display_contents_1_t *content_list) {
layer.flags.updating = true;
if (num_hw_layers <= kMaxLayerCount) {
- LayerCache layer_cache = layer_stack_cache_.layer_cache[i];
- layer.flags.updating = IsLayerUpdating(hwc_layer, layer_cache);
+ layer.flags.updating = IsLayerUpdating(content_list, i);
}
-#if 0
+#ifdef QTI_BSP
if (hwc_layer.flags & HWC_SCREENSHOT_ANIMATOR_LAYER) {
layer_stack_.flags.animating = true;
}
@@ -588,6 +592,8 @@ int HWCDisplay::PrePrepareLayerStack(hwc_display_contents_1_t *content_list) {
} else {
layer.frame_rate = current_refresh_rate_;
}
+
+ layer.input_buffer->buffer_id = reinterpret_cast<uint64_t>(hwc_layer.handle);
}
// Prepare the Blit Target
@@ -794,8 +800,15 @@ int HWCDisplay::PostCommitLayerStack(hwc_display_contents_1_t *content_list) {
bool HWCDisplay::NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list) {
uint32_t layer_count = layer_stack_.layer_count;
+ // Handle ongoing animation and end here, start is handled below
if (layer_stack_cache_.animating) {
- return false;
+ if (!layer_stack_.flags.animating) {
+ // Animation is ending.
+ return true;
+ } else {
+ // Animation is going on.
+ return false;
+ }
}
// Frame buffer needs to be refreshed for the following reasons:
@@ -808,10 +821,14 @@ bool HWCDisplay::NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list)
}
for (uint32_t i = 0; i < layer_count; i++) {
- hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
Layer &layer = layer_stack_.layers[i];
LayerCache &layer_cache = layer_stack_cache_.layer_cache[i];
+ // need FB refresh for s3d case
+ if (layer.input_buffer->s3d_format != kS3dFormatNone) {
+ return true;
+ }
+
if (layer.composition == kCompositionGPUTarget) {
continue;
}
@@ -820,7 +837,7 @@ bool HWCDisplay::NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list)
return true;
}
- if ((layer.composition == kCompositionGPU) && IsLayerUpdating(hwc_layer, layer_cache)) {
+ if ((layer.composition == kCompositionGPU) && IsLayerUpdating(content_list, i)) {
return true;
}
}
@@ -828,22 +845,30 @@ bool HWCDisplay::NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list)
return false;
}
-bool HWCDisplay::IsLayerUpdating(const hwc_layer_1_t &hwc_layer, const LayerCache &layer_cache) {
+bool HWCDisplay::IsLayerUpdating(hwc_display_contents_1_t *content_list, int layer_index) {
+ hwc_layer_1_t &hwc_layer = content_list->hwLayers[layer_index];
+ LayerCache &layer_cache = layer_stack_cache_.layer_cache[layer_index];
+
const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer.handle);
const MetaData_t *meta_data = pvt_handle ?
reinterpret_cast<MetaData_t *>(pvt_handle->base_metadata) : NULL;
- // If a layer is in single buffer mode, it should be considered as updating always
+ // Layer should be considered updating if
+ // a) layer is in single buffer mode, or
+ // b) layer handle has changed, or
+ // c) layer plane alpha has changed, or
+ // d) layer stack geometry has changed
return ((meta_data && (meta_data->operation & SET_SINGLE_BUFFER_MODE) &&
- meta_data->isSingleBufferMode) ||
+ meta_data->isSingleBufferMode) ||
(layer_cache.handle != hwc_layer.handle) ||
- (layer_cache.plane_alpha != hwc_layer.planeAlpha));
+ (layer_cache.plane_alpha != hwc_layer.planeAlpha) ||
+ (content_list->flags & HWC_GEOMETRY_CHANGED));
}
void HWCDisplay::CacheLayerStackInfo(hwc_display_contents_1_t *content_list) {
uint32_t layer_count = layer_stack_.layer_count;
- if (layer_count > kMaxLayerCount) {
+ if (layer_count > kMaxLayerCount || layer_stack_.flags.animating) {
ResetLayerCacheStack();
return;
}
@@ -955,6 +980,7 @@ LayerBufferFormat HWCDisplay::GetSDMFormat(const int32_t &source, const int flag
case HAL_PIXEL_FORMAT_BGR_565: format = kFormatBGR565; break;
case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS: format = kFormatYCbCr420SemiPlanarVenus; break;
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS: format = kFormatYCrCb420SemiPlanarVenus; break;
case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC: format = kFormatYCbCr420SPVenusUbwc; break;
case HAL_PIXEL_FORMAT_YV12: format = kFormatYCrCb420PlanarStride16; break;
case HAL_PIXEL_FORMAT_YCrCb_420_SP: format = kFormatYCrCb420SemiPlanar; break;
@@ -1067,6 +1093,8 @@ const char *HWCDisplay::GetHALPixelFormatString(int format) {
return "INTERLACE";
case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
return "YCbCr_420_SP_VENUS";
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
+ return "YCrCb_420_SP_VENUS";
case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
return "YCbCr_420_SP_VENUS_UBWC";
default:
@@ -1194,6 +1222,7 @@ void HWCDisplay::GetPanelResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
int HWCDisplay::SetDisplayStatus(uint32_t display_status) {
int status = 0;
+ const hwc_procs_t *hwc_procs = *hwc_procs_;
switch (display_status) {
case kDisplayStatusResume:
@@ -1211,6 +1240,11 @@ int HWCDisplay::SetDisplayStatus(uint32_t display_status) {
return -EINVAL;
}
+ if (display_status == kDisplayStatusResume ||
+ display_status == kDisplayStatusPause) {
+ hwc_procs->invalidate(hwc_procs);
+ }
+
return status;
}
@@ -1251,15 +1285,6 @@ void HWCDisplay::MarkLayersForGPUBypass(hwc_display_contents_1_t *content_list)
}
}
-void HWCDisplay::CloseAcquireFences(hwc_display_contents_1_t *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;
- }
- }
-}
-
uint32_t HWCDisplay::RoundToStandardFPS(uint32_t fps) {
static const uint32_t standard_fps[4] = {30, 24, 48, 60};
@@ -1350,6 +1375,16 @@ DisplayError HWCDisplay::SetMetaData(const private_handle_t *pvt_handle, Layer *
layer_stack_.flags.single_buffered_layer_present |= meta_data->isSingleBufferMode;
}
+ if (meta_data->operation & S3D_FORMAT) {
+ std::map<int, LayerBufferS3DFormat>::iterator it =
+ s3d_format_hwc_to_sdm_.find(meta_data->s3dFormat);
+ if (it != s3d_format_hwc_to_sdm_.end()) {
+ layer->input_buffer->s3d_format = it->second;
+ } else {
+ DLOGW("Invalid S3D format %d", meta_data->s3dFormat);
+ }
+ }
+
return kErrorNone;
}
@@ -1368,7 +1403,9 @@ int HWCDisplay::GetPanelBrightness(int *level) {
}
int HWCDisplay::ToggleScreenUpdates(bool enable) {
+ const hwc_procs_t *hwc_procs = *hwc_procs_;
display_paused_ = enable ? false : true;
+ hwc_procs->invalidate(hwc_procs);
return 0;
}
diff --git a/sdm/libs/hwc/hwc_display.h b/sdm/libs/hwc/hwc_display.h
index 53d9c40e7..abf7ec62c 100644
--- a/sdm/libs/hwc/hwc_display.h
+++ b/sdm/libs/hwc/hwc_display.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
@@ -29,6 +29,7 @@
#include <core/core_interface.h>
#include <qdMetaData.h>
#include <private/color_params.h>
+#include <map>
namespace sdm {
@@ -141,7 +142,6 @@ class HWCDisplay : public DisplayEventHandler {
const char *GetDisplayString();
void ScaleDisplayFrame(hwc_rect_t *display_frame);
void MarkLayersForGPUBypass(hwc_display_contents_1_t *content_list);
- void CloseAcquireFences(hwc_display_contents_1_t *content_list);
uint32_t RoundToStandardFPS(uint32_t fps);
virtual void ApplyScanAdjustment(hwc_rect_t *display_frame);
DisplayError SetCSC(ColorSpace_t source, LayerCSC *target);
@@ -149,7 +149,7 @@ class HWCDisplay : public DisplayEventHandler {
DisplayError SetMetaData(const private_handle_t *pvt_handle, Layer *layer);
bool NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list);
void CacheLayerStackInfo(hwc_display_contents_1_t *content_list);
- bool IsLayerUpdating(const hwc_layer_1_t &hwc_layer, const LayerCache &layer_cache);
+ bool IsLayerUpdating(hwc_display_contents_1_t *content_list, int layer_index);
bool SingleLayerUpdating(uint32_t app_layer_count);
uint32_t SanitizeRefreshRate(uint32_t req_refresh_rate);
@@ -190,6 +190,7 @@ class HWCDisplay : public DisplayEventHandler {
bool solid_fill_enable_ = false;
uint32_t solid_fill_color_ = 0;
LayerRect display_rect_;
+ std::map<int, LayerBufferS3DFormat> s3d_format_hwc_to_sdm_;
private:
bool IsFrameBufferScaled();
diff --git a/sdm/libs/hwc/hwc_display_external.cpp b/sdm/libs/hwc/hwc_display_external.cpp
index 28582f128..74a79bbce 100755..100644
--- a/sdm/libs/hwc/hwc_display_external.cpp
+++ b/sdm/libs/hwc/hwc_display_external.cpp
@@ -97,6 +97,11 @@ int HWCDisplayExternal::Prepare(hwc_display_contents_1_t *content_list) {
return status;
}
+ if (content_list->numHwLayers <= 1) {
+ flush_ = true;
+ return 0;
+ }
+
status = PrepareLayerStack(content_list);
if (status) {
return status;
@@ -109,7 +114,6 @@ int HWCDisplayExternal::Commit(hwc_display_contents_1_t *content_list) {
int status = 0;
if (secure_display_active_) {
- CloseAcquireFences(content_list);
return status;
}
@@ -151,13 +155,16 @@ void HWCDisplayExternal::ApplyScanAdjustment(hwc_rect_t *display_frame) {
return;
}
+ uint32_t new_panel_width = panel_width * (1.0f - width_ratio);
+ uint32_t new_panel_height = panel_height * (1.0f - height_ratio);
+
int x_offset = INT((FLOAT(panel_width) * width_ratio) / 2.0f);
int y_offset = INT((FLOAT(panel_height) * height_ratio) / 2.0f);
- display_frame->left = display_frame->left + x_offset;
- display_frame->top = display_frame->top + y_offset;
- display_frame->right = display_frame->right - x_offset;
- display_frame->bottom = display_frame->bottom - y_offset;
+ display_frame->left = ((display_frame->left * new_panel_width) / panel_width) + x_offset;
+ display_frame->top = ((display_frame->top * new_panel_height) / panel_height) + y_offset;
+ display_frame->right = ((display_frame->right * new_panel_width) / panel_width) + x_offset;
+ display_frame->bottom = ((display_frame->bottom * new_panel_height) / panel_height) + y_offset;
}
void HWCDisplayExternal::SetSecureDisplay(bool secure_display_active) {
diff --git a/sdm/libs/hwc/hwc_display_primary.cpp b/sdm/libs/hwc/hwc_display_primary.cpp
index fb134a971..cd08d689e 100755..100644
--- a/sdm/libs/hwc/hwc_display_primary.cpp
+++ b/sdm/libs/hwc/hwc_display_primary.cpp
@@ -97,15 +97,37 @@ int HWCDisplayPrimary::Init() {
return HWCDisplay::Init();
}
-void HWCDisplayPrimary::ProcessBootAnimCompleted() {
- char value[PROPERTY_VALUE_MAX];
+void HWCDisplayPrimary::ProcessBootAnimCompleted(hwc_display_contents_1_t *list) {
+ uint32_t numBootUpLayers = 0;
- // Applying default mode after bootanimation is finished
- property_get("init.svc.bootanim", value, "running");
- if (!strncmp(value, "stopped", strlen("stopped"))) {
- boot_animation_completed_ = true;
+ numBootUpLayers = static_cast<uint32_t>(Debug::GetBootAnimLayerCount());
- // one-shot action check if bootanimation completed then apply default display mode.
+ if (numBootUpLayers == 0) {
+ numBootUpLayers = 2;
+ }
+ /* All other checks namely "init.svc.bootanim" or
+ * HWC_GEOMETRY_CHANGED fail in correctly identifying the
+ * exact bootup transition to homescreen
+ */
+ char cryptoState[PROPERTY_VALUE_MAX];
+ char voldDecryptState[PROPERTY_VALUE_MAX];
+ bool isEncrypted = false;
+ bool main_class_services_started = false;
+ if (property_get("ro.crypto.state", cryptoState, "unencrypted")) {
+ DLOGI("%s: cryptostate= %s", __FUNCTION__, cryptoState);
+ if (!strcmp(cryptoState, "encrypted")) {
+ isEncrypted = true;
+ if (property_get("vold.decrypt", voldDecryptState, "") &&
+ !strcmp(voldDecryptState, "trigger_restart_framework"))
+ main_class_services_started = true;
+ DLOGI("%s: vold= %s", __FUNCTION__, voldDecryptState);
+ }
+ }
+ if ((!isEncrypted ||(isEncrypted && main_class_services_started)) &&
+ (list->numHwLayers > numBootUpLayers)) {
+ boot_animation_completed_ = true;
+ // Applying default mode after bootanimation is finished And
+ // If Data is Encrypted, it is ready for access.
if (display_intf_)
display_intf_->ApplyDefaultDisplayMode();
}
@@ -113,9 +135,10 @@ void HWCDisplayPrimary::ProcessBootAnimCompleted() {
int HWCDisplayPrimary::Prepare(hwc_display_contents_1_t *content_list) {
int status = 0;
+ DisplayError error = kErrorNone;
if (!boot_animation_completed_)
- ProcessBootAnimCompleted();
+ ProcessBootAnimCompleted(content_list);
if (display_paused_) {
MarkLayersForGPUBypass(content_list);
@@ -136,7 +159,10 @@ int HWCDisplayPrimary::Prepare(hwc_display_contents_1_t *content_list) {
ToggleCPUHint(one_updating_layer);
uint32_t refresh_rate = GetOptimalRefreshRate(one_updating_layer);
- DisplayError error = display_intf_->SetRefreshRate(refresh_rate);
+ if (current_refresh_rate_ != refresh_rate) {
+ error = display_intf_->SetRefreshRate(refresh_rate);
+ }
+
if (error == kErrorNone) {
// On success, set current refresh rate to new refresh rate
current_refresh_rate_ = refresh_rate;
@@ -146,6 +172,11 @@ int HWCDisplayPrimary::Prepare(hwc_display_contents_1_t *content_list) {
handle_idle_timeout_ = false;
}
+ if (content_list->numHwLayers <= 1) {
+ flush_ = true;
+ return 0;
+ }
+
status = PrepareLayerStack(content_list);
if (status) {
return status;
@@ -164,7 +195,6 @@ int HWCDisplayPrimary::Commit(hwc_display_contents_1_t *content_list) {
close(content_list->outbufAcquireFenceFd);
content_list->outbufAcquireFenceFd = -1;
}
- CloseAcquireFences(content_list);
DisplayError error = display_intf_->Flush();
if (error != kErrorNone) {
diff --git a/sdm/libs/hwc/hwc_display_primary.h b/sdm/libs/hwc/hwc_display_primary.h
index e30d20049..377371792 100644
--- a/sdm/libs/hwc/hwc_display_primary.h
+++ b/sdm/libs/hwc/hwc_display_primary.h
@@ -55,7 +55,7 @@ class HWCDisplayPrimary : public HWCDisplay {
HWCDisplayPrimary(CoreInterface *core_intf, hwc_procs_t const **hwc_procs);
void SetMetaDataRefreshRateFlag(bool enable);
virtual DisplayError SetDisplayMode(uint32_t mode);
- void ProcessBootAnimCompleted();
+ void ProcessBootAnimCompleted(hwc_display_contents_1_t *content_list);
void SetQDCMSolidFillInfo(bool enable, uint32_t color);
void ToggleCPUHint(bool set);
void ForceRefreshRate(uint32_t refresh_rate);
diff --git a/sdm/libs/hwc/hwc_display_virtual.cpp b/sdm/libs/hwc/hwc_display_virtual.cpp
index 4d8c24ec8..f216f89ee 100644
--- a/sdm/libs/hwc/hwc_display_virtual.cpp
+++ b/sdm/libs/hwc/hwc_display_virtual.cpp
@@ -163,15 +163,6 @@ int HWCDisplayVirtual::Prepare(hwc_display_contents_1_t *content_list) {
int HWCDisplayVirtual::Commit(hwc_display_contents_1_t *content_list) {
int status = 0;
if (display_paused_) {
- if (content_list->outbufAcquireFenceFd >= 0) {
- // If we do not handle the frame set retireFenceFd to outbufAcquireFenceFd,
- // which will make sure the framework waits on it and closes it.
- content_list->retireFenceFd = dup(content_list->outbufAcquireFenceFd);
- close(content_list->outbufAcquireFenceFd);
- content_list->outbufAcquireFenceFd = -1;
- }
- CloseAcquireFences(content_list);
-
DisplayError error = display_intf_->Flush();
if (error != kErrorNone) {
DLOGE("Flush failed. Error = %d", error);
@@ -191,11 +182,6 @@ int HWCDisplayVirtual::Commit(hwc_display_contents_1_t *content_list) {
return status;
}
- if (content_list->outbufAcquireFenceFd >= 0) {
- close(content_list->outbufAcquireFenceFd);
- content_list->outbufAcquireFenceFd = -1;
- }
-
return 0;
}
diff --git a/sdm/libs/hwc/hwc_session.cpp b/sdm/libs/hwc/hwc_session.cpp
index 779b44035..c84fab1d0 100644
--- a/sdm/libs/hwc/hwc_session.cpp
+++ b/sdm/libs/hwc/hwc_session.cpp
@@ -43,6 +43,7 @@
#include <display_config.h>
#include <utils/debug.h>
#include <sync/sync.h>
+#include <profiler.h>
#include "hwc_buffer_allocator.h"
#include "hwc_buffer_sync_handler.h"
@@ -302,14 +303,26 @@ int HWCSession::Prepare(hwc_composer_device_1 *device, size_t num_displays,
}
if (hotplug_connect) {
+ // notify client
hwc_procs->hotplug(hwc_procs, HWC_DISPLAY_EXTERNAL, true);
- hwc_procs->invalidate(hwc_procs);
}
-
// Return 0, else client will go into bad state
return 0;
}
+int HWCSession::GetVsyncPeriod(int disp) {
+ SCOPE_LOCK(locker_);
+ // default value
+ int32_t vsync_period = 1000000000l / 60;
+ const uint32_t attribute = HWC_DISPLAY_VSYNC_PERIOD;
+
+ if (hwc_display_[disp]) {
+ hwc_display_[disp]->GetDisplayAttributes(0, &attribute, &vsync_period);
+ }
+
+ return vsync_period;
+}
+
int HWCSession::Set(hwc_composer_device_1 *device, size_t num_displays,
hwc_display_contents_1_t **displays) {
DTRACE_SCOPED();
@@ -337,32 +350,18 @@ int HWCSession::Set(hwc_composer_device_1 *device, size_t num_displays,
// 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;
+ CloseAcquireFds(content_list);
+ if (content_list) {
+ content_list->retireFenceFd = -1;
}
- 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]) {
hwc_session->hwc_display_[dpy]->Commit(content_list);
}
+ CloseAcquireFds(content_list);
}
if (hwc_session->new_bw_mode_) {
@@ -374,10 +373,32 @@ int HWCSession::Set(hwc_composer_device_1 *device, size_t num_displays,
hwc_session->bw_mode_release_fd_ = dup(content_list->retireFenceFd);
}
+ // This is only indicative of how many times SurfaceFlinger posts
+ // frames to the display.
+ CALC_FPS();
+
// Return 0, else client will go into bad state
return 0;
}
+void HWCSession::CloseAcquireFds(hwc_display_contents_1_t *content_list) {
+ if (content_list) {
+ 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;
+ }
+ }
+}
+
int HWCSession::EventControl(hwc_composer_device_1 *device, int disp, int event, int enable) {
SEQUENCE_WAIT_SCOPE_LOCK(locker_);
@@ -1090,6 +1111,9 @@ android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel
return -1;
}
+ pending_action.action = kNoAction;
+ pending_action.params = NULL;
+
// Read display_id, payload_size and payload from in_parcel.
ret = HWCColorManager::CreatePayloadFromParcel(*input_parcel, &display_id, &req_payload);
if (!ret) {
@@ -1308,14 +1332,18 @@ int HWCSession::HotPlugHandler(bool connected) {
external_pending_connect_ = false;
}
}
-
- // notify client and trigger a screen refresh
+ if (connected && notify_hotplug) {
+ // trigger screen refresh to ensure sufficient resources are available to process new
+ // new display connection.
+ hwc_procs_->invalidate(hwc_procs_);
+ int32_t vsync_period = GetVsyncPeriod(HWC_DISPLAY_PRIMARY);
+ usleep(vsync_period * 2 / 1000);
+ }
+ // notify client
if (notify_hotplug) {
hwc_procs_->hotplug(hwc_procs_, HWC_DISPLAY_EXTERNAL, connected);
}
- hwc_procs_->invalidate(hwc_procs_);
-
return 0;
}
diff --git a/sdm/libs/hwc/hwc_session.h b/sdm/libs/hwc/hwc_session.h
index 455ea831d..561de3574 100644
--- a/sdm/libs/hwc/hwc_session.h
+++ b/sdm/libs/hwc/hwc_session.h
@@ -73,6 +73,7 @@ class HWCSession : hwc_composer_device_1_t, public qClient::BnQClient {
static int GetActiveConfig(hwc_composer_device_1 *device, int disp);
static int SetActiveConfig(hwc_composer_device_1 *device, int disp, int index);
static int SetCursorPositionAsync(hwc_composer_device_1 *device, int disp, int x, int y);
+ static void CloseAcquireFds(hwc_display_contents_1_t *content_list);
// Uevent thread
static void* HWCUeventThread(void *context);
@@ -83,6 +84,7 @@ class HWCSession : hwc_composer_device_1_t, public qClient::BnQClient {
int ConnectDisplay(int disp, hwc_display_contents_1_t *content_list);
int DisconnectDisplay(int disp);
void HandleSecureDisplaySession(hwc_display_contents_1_t **displays);
+ int GetVsyncPeriod(int disp);
// QClient methods
virtual android::status_t notifyCallback(uint32_t command, const android::Parcel *input_parcel,
diff --git a/sdm/libs/utils/debug.cpp b/sdm/libs/utils/debug.cpp
index 003be5a21..d0d21ee95 100644
--- a/sdm/libs/utils/debug.cpp
+++ b/sdm/libs/utils/debug.cpp
@@ -59,6 +59,13 @@ int Debug::GetIdleTimeoutMs() {
return value;
}
+int Debug::GetBootAnimLayerCount() {
+ int value = 0;
+ debug_.debug_handler_->GetProperty("sdm.boot_anim_layer_count", &value);
+
+ return value;
+}
+
bool Debug::IsRotatorDownScaleDisabled() {
int value = 0;
debug_.debug_handler_->GetProperty("sdm.debug.rotator_downscale", &value);