Merge "hwc: avoid composition for static screen use-cases"
diff --git a/displayengine/include/core/display_interface.h b/displayengine/include/core/display_interface.h
index 9aae0a1..f4c4415 100644
--- a/displayengine/include/core/display_interface.h
+++ b/displayengine/include/core/display_interface.h
@@ -322,6 +322,14 @@
*/
virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages) = 0;
+ /*! @brief Method to set the mode of the primary display.
+
+ @param[in] mode the new display mode.
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError SetDisplayMode(uint32_t mode) = 0;
+
protected:
virtual ~DisplayInterface() { }
};
diff --git a/displayengine/include/core/layer_buffer.h b/displayengine/include/core/layer_buffer.h
index 9f7110a..e4a73c3 100644
--- a/displayengine/include/core/layer_buffer.h
+++ b/displayengine/include/core/layer_buffer.h
@@ -49,7 +49,10 @@
kFormatXRGB8888, //!< 8-bits Padding, Red, Green, Blue interleaved in XRGB order. No Alpha.
kFormatRGBX8888, //!< 8-bits Red, Green, Blue, Padding interleaved in RGBX order. No Alpha.
kFormatBGRX8888, //!< 8-bits Blue, Green, Red, Padding interleaved in BGRX order. No Alpha.
+ kFormatRGBA5551, //!< 5-bits Red, Green, Blue, and 1 bit Alpha interleaved in RGBA order.
+ kFormatRGBA4444, //!< 4-bits Red, Green, Blue, Alpha interleaved in RGBA order.
kFormatRGB888, //!< 8-bits Red, Green, Blue interleaved in RGB order. No Alpha.
+ kFormatBGR888, //!< 8-bits Blue, Green, Red interleaved in BGR order. No Alpha.
kFormatRGB565, //!< 5-bit Red, 6-bit Green, 5-bit Blue interleaved in RGB order. No Alpha.
/* All YUV-Planar formats, Any new format will be added towards end of this group to maintain
@@ -80,13 +83,29 @@
//!< 2x2 subsampled interleaved UV-plane:
//!< u(0), v(0), u(2), v(2) ... u(n-1), v(n-1)
+ kFormatYCbCr422H1V2SemiPlanar, //!< Y-plane: y(0), y(1), y(2) ... y(n)
+ //!< vertically subsampled interleaved UV-plane:
+ //!< u(0), v(1), u(2), v(3) ... u(n-1), v(n)
+
+ kFormatYCrCb422H1V2SemiPlanar, //!< Y-plane: y(0), y(1), y(2) ... y(n)
+ //!< vertically subsampled interleaved VU-plane:
+ //!< v(0), u(1), v(2), u(3) ... v(n-1), u(n)
+
+ kFormatYCbCr422H2V1SemiPlanar, //!< Y-plane: y(0), y(1), y(2) ... y(n)
+ //!< horizontally subsampled interleaved UV-plane:
+ //!< u(0), v(1), u(2), v(3) ... u(n-1), v(n)
+
+ kFormatYCrCb422H2V1SemiPlanar, //!< Y-plane: y(0), y(1), y(2) ... y(n)
+ //!< horizontally subsampled interleaved VU-plane:
+ //!< v(0), u(1), v(2), u(3) ... v(n-1), u(n)
+
/* All YUV-Packed formats, Any new format will be added towards end of this group to maintain
backward compatibility.
*/
- kFormatYCbCr422Packed = 0x300, //!< Y-plane interleaved with horizontally subsampled U/V by
+ kFormatYCbCr422H2V1Packed = 0x300, //!< Y-plane interleaved with horizontally subsampled U/V by
//!< factor of 2
- //!< u(0), y(0), v(0), y(1), u(2), y(2), v(2), y(3)
- //!< u(n-1), y(n-1), v(n-1), y(n)
+ //!< y(0), u(0), y(1), v(0), y(2), u(2), y(3), v(2)
+ //!< y(n-1), u(n-1), y(n), v(n-1)
/* All UBWC aligned formats. Any new format will be added towards end of this group to maintain
backward compatibility.
diff --git a/displayengine/include/private/hw_info_types.h b/displayengine/include/private/hw_info_types.h
index d842167..c6c2a0a 100644
--- a/displayengine/include/private/hw_info_types.h
+++ b/displayengine/include/private/hw_info_types.h
@@ -87,15 +87,21 @@
void Reset() { *this = HWResourceInfo(); }
};
-/*! @brief This enumeration holds the all possible panel types. */
-enum HWPanelType {
- kNoPanel,
- kCommandModePanel,
- kVideoModePanel,
- kDTvPanel,
- kWriteBackPanel,
- kLVDSPanel,
- kEDPPanel,
+/*! @brief This enumeration holds the possible display modes. */
+enum HWDisplayMode {
+ kModeDefault,
+ kModeVideo,
+ kModeCommand,
+};
+
+/*! @brief This enumeration holds the all possible display port types. */
+enum HWDisplayPort {
+ kPortDefault,
+ kPortDSI,
+ kPortDTv,
+ kPortWriteBack,
+ kPortLVDS,
+ kPortEDP,
};
/*! @brief This structure describes the split configuration of a display panel. */
@@ -103,12 +109,14 @@
uint32_t left_split;
uint32_t right_split;
bool always_src_split;
+
HWSplitInfo() : left_split(0), right_split(0), always_src_split(false) { }
};
/*! @brief This structure describes properties of a display panel. */
struct HWPanelInfo {
- HWPanelType type; //!< Panel type
+ HWDisplayPort port; //!< Display port
+ HWDisplayMode mode; //!< Display mode
bool partial_update; //!< Partial update feature
int left_align; //!< ROI left alignment restriction
int width_align; //!< ROI width alignment restriction
@@ -123,8 +131,8 @@
bool is_primary_panel; //!< Panel is primary display
HWSplitInfo split_info; //!< Panel split configuration
- HWPanelInfo() : type(kNoPanel), partial_update(false), left_align(false), width_align(false),
- top_align(false), height_align(false), min_roi_width(0), min_roi_height(0),
+ HWPanelInfo() : port(kPortDefault), mode(kModeDefault), partial_update(false), left_align(false),
+ width_align(false), top_align(false), height_align(false), min_roi_width(0), min_roi_height(0),
needs_roi_merge(false), dynamic_fps(false), min_fps(0), max_fps(0) { }
};
diff --git a/displayengine/include/utils/constants.h b/displayengine/include/utils/constants.h
index 8630d45..1a7d62a 100644
--- a/displayengine/include/utils/constants.h
+++ b/displayengine/include/utils/constants.h
@@ -27,9 +27,6 @@
#include <stdlib.h>
-#define LIKELY(exp) __builtin_expect((exp) != 0, true)
-#define UNLIKELY(exp) __builtin_expect((exp) != 0, false)
-
#define INT(exp) static_cast<int>(exp)
#define FLOAT(exp) static_cast<float>(exp)
#define UINT8(exp) static_cast<uint8_t>(exp)
@@ -59,6 +56,8 @@
#define IDLE_TIMEOUT_DEFAULT_MS 70
+#define IS_RGB_FORMAT(format) (((format) < kFormatYCbCr420Planar) ? true: false)
+
template <class T>
inline void Swap(T &a, T &b) {
T c(a);
diff --git a/displayengine/libs/core/core_impl.cpp b/displayengine/libs/core/core_impl.cpp
index 2732889..f04bbb9 100644
--- a/displayengine/libs/core/core_impl.cpp
+++ b/displayengine/libs/core/core_impl.cpp
@@ -123,7 +123,7 @@
return kErrorParameters;
}
- if (UNLIKELY(!display_base)) {
+ if (!display_base) {
return kErrorMemory;
}
diff --git a/displayengine/libs/core/core_interface.cpp b/displayengine/libs/core/core_interface.cpp
index c982b4d..0cfec66 100644
--- a/displayengine/libs/core/core_interface.cpp
+++ b/displayengine/libs/core/core_interface.cpp
@@ -64,16 +64,16 @@
// Check compatibility of client and core.
uint32_t lib_version = SDE_VERSION_TAG;
- if (UNLIKELY(GET_REVISION(client_version) > GET_REVISION(lib_version))) {
+ if (GET_REVISION(client_version) > GET_REVISION(lib_version)) {
return kErrorVersion;
- } else if (UNLIKELY(GET_DATA_ALIGNMENT(client_version) != GET_DATA_ALIGNMENT(lib_version))) {
+ } else if (GET_DATA_ALIGNMENT(client_version) != GET_DATA_ALIGNMENT(lib_version)) {
return kErrorDataAlignment;
- } else if (UNLIKELY(GET_INSTRUCTION_SET(client_version) != GET_INSTRUCTION_SET(lib_version))) {
+ } else if (GET_INSTRUCTION_SET(client_version) != GET_INSTRUCTION_SET(lib_version)) {
return kErrorInstructionSet;
}
CoreImpl *&core_impl = g_core.core_impl;
- if (UNLIKELY(core_impl)) {
+ if (core_impl) {
return kErrorUndefined;
}
@@ -86,12 +86,12 @@
return kErrorNotSupported;
}
- if (UNLIKELY(!core_impl)) {
+ if (!core_impl) {
return kErrorMemory;
}
DisplayError error = core_impl->Init();
- if (UNLIKELY(error != kErrorNone)) {
+ if (error != kErrorNone) {
delete core_impl;
core_impl = NULL;
return error;
@@ -109,7 +109,7 @@
DLOGI("Close handle");
CoreImpl *&core_impl = g_core.core_impl;
- if (UNLIKELY(!core_impl)) {
+ if (!core_impl) {
return kErrorUndefined;
}
diff --git a/displayengine/libs/core/display_base.cpp b/displayengine/libs/core/display_base.cpp
index b61d3a6..e58b4f8 100644
--- a/displayengine/libs/core/display_base.cpp
+++ b/displayengine/libs/core/display_base.cpp
@@ -45,17 +45,8 @@
DisplayError DisplayBase::Init() {
DisplayError error = kErrorNone;
-
- error = hw_intf_->Open(this);
- if (error != kErrorNone) {
- return error;
- }
-
- panel_info_ = HWPanelInfo();
- hw_intf_->GetHWPanelInfo(&panel_info_);
-
- // Set the idle timeout value to driver through sysfs node
- SetIdleTimeoutMs(Debug::GetIdleTimeoutMs());
+ hw_panel_info_ = HWPanelInfo();
+ hw_intf_->GetHWPanelInfo(&hw_panel_info_);
error = hw_intf_->GetNumDisplayAttributes(&num_modes_);
if (error != kErrorNone) {
@@ -89,7 +80,7 @@
}
error = offline_ctrl_->RegisterDisplay(display_type_, &display_offline_ctx_);
- if (UNLIKELY(error != kErrorNone)) {
+ if (error != kErrorNone) {
goto CleanupOnError;
}
@@ -126,8 +117,6 @@
}
DisplayError DisplayBase::Prepare(LayerStack *layer_stack) {
- SCOPE_LOCK(locker_);
-
DisplayError error = kErrorNone;
if (!layer_stack) {
@@ -167,8 +156,6 @@
}
DisplayError DisplayBase::Commit(LayerStack *layer_stack) {
- SCOPE_LOCK(locker_);
-
DisplayError error = kErrorNone;
if (!layer_stack) {
@@ -203,8 +190,6 @@
}
DisplayError DisplayBase::Flush() {
- SCOPE_LOCK(locker_);
-
DisplayError error = kErrorNone;
if (state_ != kStateOn) {
@@ -224,8 +209,6 @@
}
DisplayError DisplayBase::GetDisplayState(DisplayState *state) {
- SCOPE_LOCK(locker_);
-
if (!state) {
return kErrorParameters;
}
@@ -235,8 +218,6 @@
}
DisplayError DisplayBase::GetNumVariableInfoConfigs(uint32_t *count) {
- SCOPE_LOCK(locker_);
-
if (!count) {
return kErrorParameters;
}
@@ -247,8 +228,6 @@
}
DisplayError DisplayBase::GetConfig(DisplayConfigFixedInfo *fixed_info) {
- SCOPE_LOCK(locker_);
-
if (!fixed_info) {
return kErrorParameters;
}
@@ -257,8 +236,6 @@
}
DisplayError DisplayBase::GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info) {
- SCOPE_LOCK(locker_);
-
if (!variable_info || index >= num_modes_) {
return kErrorParameters;
}
@@ -269,8 +246,6 @@
}
DisplayError DisplayBase::GetActiveConfig(uint32_t *index) {
- SCOPE_LOCK(locker_);
-
if (!index) {
return kErrorParameters;
}
@@ -281,8 +256,6 @@
}
DisplayError DisplayBase::GetVSyncState(bool *enabled) {
- SCOPE_LOCK(locker_);
-
if (!enabled) {
return kErrorParameters;
}
@@ -291,8 +264,6 @@
}
DisplayError DisplayBase::SetDisplayState(DisplayState state) {
- SCOPE_LOCK(locker_);
-
DisplayError error = kErrorNone;
DLOGI("Set state = %d, display %d", state, display_type_);
@@ -338,7 +309,6 @@
}
DisplayError DisplayBase::SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
- SCOPE_LOCK(locker_);
DisplayError error = kErrorNone;
if (!variable_info) {
@@ -368,7 +338,6 @@
}
DisplayError DisplayBase::SetActiveConfig(uint32_t index) {
- SCOPE_LOCK(locker_);
DisplayError error = kErrorNone;
if (index >= num_modes_) {
@@ -392,15 +361,7 @@
return error;
}
-DisplayError DisplayBase::SetVSyncState(bool enable) {
- return kErrorNotSupported;
-}
-
-void DisplayBase::SetIdleTimeoutMs(uint32_t timeout_ms) { }
-
DisplayError DisplayBase::SetMaxMixerStages(uint32_t max_mixer_stages) {
- SCOPE_LOCK(locker_);
-
DisplayError error = kErrorNone;
if (comp_manager_) {
@@ -410,39 +371,21 @@
return error;
}
-DisplayError DisplayBase::VSync(int64_t timestamp) {
- if (vsync_enable_) {
- DisplayEventVSync vsync;
- vsync.timestamp = timestamp;
- event_handler_->VSync(vsync);
- }
-
- return kErrorNone;
-}
-
-DisplayError DisplayBase::Blank(bool blank) {
- return kErrorNone;
-}
-
-void DisplayBase::IdleTimeout() {
- bool need_refresh = comp_manager_->ProcessIdleTimeout(display_comp_ctx_);
- if (need_refresh) {
- event_handler_->Refresh();
- }
+DisplayError DisplayBase::SetDisplayMode(uint32_t mode) {
+ return kErrorNotSupported;
}
void DisplayBase::AppendDump(char *buffer, uint32_t length) {
- SCOPE_LOCK(locker_);
-
- AppendString(buffer, length, "\n-----------------------");
- AppendString(buffer, length, "\ndevice type: %u", display_type_);
- AppendString(buffer, length, "\nstate: %u, vsync on: %u", state_, INT(vsync_enable_));
- AppendString(buffer, length, "\nnum configs: %u, active config index: %u",
- num_modes_, active_mode_index_);
+ DumpImpl::AppendString(buffer, length, "\n-----------------------");
+ DumpImpl::AppendString(buffer, length, "\ndevice type: %u", display_type_);
+ DumpImpl::AppendString(buffer, length, "\nstate: %u, vsync on: %u", state_, INT(vsync_enable_));
+ DumpImpl::AppendString(buffer, length, "\nnum configs: %u, active config index: %u",
+ num_modes_, active_mode_index_);
DisplayConfigVariableInfo &info = display_attributes_[active_mode_index_];
- AppendString(buffer, length, "\nres:%ux%u, dpi:%.2fx%.2f, fps:%.2f, 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, "\nres:%ux%u, dpi:%.2fx%.2f, fps:%.2f, vsync period: %u",
+ info.x_pixels, info.y_pixels, info.x_dpi, info.y_dpi, info.fps,
+ info.vsync_period_ns);
uint32_t num_layers = 0;
uint32_t num_hw_layers = 0;
@@ -451,8 +394,8 @@
num_hw_layers = hw_layers_.info.count;
}
- AppendString(buffer, length, "\n\nnum actual layers: %u, num sde layers: %u",
- num_layers, num_hw_layers);
+ DumpImpl::AppendString(buffer, length, "\n\nnum actual layers: %u, num sde layers: %u",
+ num_layers, num_hw_layers);
for (uint32_t i = 0; i < num_hw_layers; i++) {
Layer &layer = hw_layers_.info.stack->layers[hw_layers_.info.index[i]];
@@ -463,36 +406,37 @@
HWRotateInfo &left_rotate = hw_layers_.config[i].rotates[0];
HWRotateInfo &right_rotate = hw_layers_.config[i].rotates[1];
- AppendString(buffer, length, "\n\nsde idx: %u, actual idx: %u", i, hw_layers_.info.index[i]);
- AppendString(buffer, length, "\nw: %u, h: %u, fmt: %u",
- input_buffer->width, input_buffer->height, input_buffer->format);
+ DumpImpl::AppendString(buffer, length, "\n\nsde idx: %u, actual idx: %u", i,
+ hw_layers_.info.index[i]);
+ DumpImpl::AppendString(buffer, length, "\nw: %u, h: %u, fmt: %u",
+ input_buffer->width, input_buffer->height, input_buffer->format);
AppendRect(buffer, length, "\nsrc_rect:", &layer.src_rect);
AppendRect(buffer, length, "\ndst_rect:", &layer.dst_rect);
if (left_rotate.valid) {
- AppendString(buffer, length, "\n\tleft rotate =>");
- AppendString(buffer, length, "\n\t pipe id: 0x%x", left_rotate.pipe_id);
+ DumpImpl::AppendString(buffer, length, "\n\tleft rotate =>");
+ DumpImpl::AppendString(buffer, length, "\n\t pipe id: 0x%x", left_rotate.pipe_id);
AppendRect(buffer, length, "\n\t src_roi:", &left_rotate.src_roi);
AppendRect(buffer, length, "\n\t dst_roi:", &left_rotate.dst_roi);
}
if (right_rotate.valid) {
- AppendString(buffer, length, "\n\tright rotate =>");
- AppendString(buffer, length, "\n\t pipe id: 0x%x", right_rotate.pipe_id);
+ DumpImpl::AppendString(buffer, length, "\n\tright rotate =>");
+ DumpImpl::AppendString(buffer, length, "\n\t pipe id: 0x%x", right_rotate.pipe_id);
AppendRect(buffer, length, "\n\t src_roi:", &right_rotate.src_roi);
AppendRect(buffer, length, "\n\t dst_roi:", &right_rotate.dst_roi);
}
if (left_pipe.valid) {
- AppendString(buffer, length, "\n\tleft pipe =>");
- AppendString(buffer, length, "\n\t pipe id: 0x%x", left_pipe.pipe_id);
+ DumpImpl::AppendString(buffer, length, "\n\tleft pipe =>");
+ DumpImpl::AppendString(buffer, length, "\n\t pipe id: 0x%x", left_pipe.pipe_id);
AppendRect(buffer, length, "\n\t src_roi:", &left_pipe.src_roi);
AppendRect(buffer, length, "\n\t dst_roi:", &left_pipe.dst_roi);
}
if (right_pipe.valid) {
- AppendString(buffer, length, "\n\tright pipe =>");
- AppendString(buffer, length, "\n\t pipe id: 0x%x", right_pipe.pipe_id);
+ DumpImpl::AppendString(buffer, length, "\n\tright pipe =>");
+ DumpImpl::AppendString(buffer, length, "\n\t pipe id: 0x%x", right_pipe.pipe_id);
AppendRect(buffer, length, "\n\t src_roi:", &right_pipe.src_roi);
AppendRect(buffer, length, "\n\t dst_roi:", &right_pipe.dst_roi);
}
@@ -501,8 +445,8 @@
void DisplayBase::AppendRect(char *buffer, uint32_t length, const char *rect_name,
LayerRect *rect) {
- AppendString(buffer, length, "%s %.1f, %.1f, %.1f, %.1f",
- rect_name, rect->left, rect->top, rect->right, rect->bottom);
+ DumpImpl::AppendString(buffer, length, "%s %.1f, %.1f, %.1f, %.1f",
+ rect_name, rect->left, rect->top, rect->right, rect->bottom);
}
int DisplayBase::GetBestConfig() {
diff --git a/displayengine/libs/core/display_base.h b/displayengine/libs/core/display_base.h
index 51b0ac3..6d107a0 100644
--- a/displayengine/libs/core/display_base.h
+++ b/displayengine/libs/core/display_base.h
@@ -38,7 +38,7 @@
class OfflineCtrl;
-class DisplayBase : public DisplayInterface, HWEventHandler, DumpImpl {
+class DisplayBase : public DisplayInterface {
public:
DisplayBase(DisplayType display_type, DisplayEventHandler *event_handler,
HWDeviceType hw_device_type, BufferSyncHandler *buffer_sync_handler,
@@ -58,28 +58,21 @@
virtual DisplayError SetDisplayState(DisplayState state);
virtual DisplayError SetActiveConfig(DisplayConfigVariableInfo *variable_info);
virtual DisplayError SetActiveConfig(uint32_t index);
- virtual DisplayError SetVSyncState(bool enable);
- virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
-
- // Implement the HWEventHandlers
- virtual DisplayError VSync(int64_t timestamp);
- virtual DisplayError Blank(bool blank);
- virtual void IdleTimeout();
-
- // DumpImpl method
- virtual void AppendDump(char *buffer, uint32_t length);
- void AppendRect(char *buffer, uint32_t length, const char *rect_name, LayerRect *rect);
+ virtual DisplayError SetDisplayMode(uint32_t mode);
protected:
+ // DumpImpl method
+ void AppendDump(char *buffer, uint32_t length);
+ void AppendRect(char *buffer, uint32_t length, const char *rect_name, LayerRect *rect);
+
virtual int GetBestConfig();
- Locker locker_;
DisplayType display_type_;
DisplayEventHandler *event_handler_;
HWDeviceType hw_device_type_;
HWInterface *hw_intf_;
- HWPanelInfo panel_info_;
+ HWPanelInfo hw_panel_info_;
BufferSyncHandler *buffer_sync_handler_;
CompManager *comp_manager_;
OfflineCtrl *offline_ctrl_;
diff --git a/displayengine/libs/core/display_hdmi.cpp b/displayengine/libs/core/display_hdmi.cpp
index 045c06c..2b6ba81 100644
--- a/displayengine/libs/core/display_hdmi.cpp
+++ b/displayengine/libs/core/display_hdmi.cpp
@@ -48,7 +48,12 @@
if (error != kErrorNone) {
return error;
}
+
DisplayBase::hw_intf_ = hw_hdmi_intf_;
+ error = hw_hdmi_intf_->Open(NULL);
+ if (error != kErrorNone) {
+ return error;
+ }
error = DisplayBase::Init();
if (error != kErrorNone) {
@@ -70,6 +75,83 @@
return error;
}
+DisplayError DisplayHDMI::Prepare(LayerStack *layer_stack) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::Prepare(layer_stack);
+}
+
+DisplayError DisplayHDMI::Commit(LayerStack *layer_stack) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::Commit(layer_stack);
+}
+
+DisplayError DisplayHDMI::Flush() {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::Flush();
+}
+
+DisplayError DisplayHDMI::GetDisplayState(DisplayState *state) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::GetDisplayState(state);
+}
+
+DisplayError DisplayHDMI::GetNumVariableInfoConfigs(uint32_t *count) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::GetNumVariableInfoConfigs(count);
+}
+
+DisplayError DisplayHDMI::GetConfig(DisplayConfigFixedInfo *fixed_info) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::GetConfig(fixed_info);
+}
+
+DisplayError DisplayHDMI::GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::GetConfig(index, variable_info);
+}
+
+DisplayError DisplayHDMI::GetActiveConfig(uint32_t *index) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::GetActiveConfig(index);
+}
+
+DisplayError DisplayHDMI::GetVSyncState(bool *enabled) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::GetVSyncState(enabled);
+}
+
+DisplayError DisplayHDMI::SetDisplayState(DisplayState state) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::SetDisplayState(state);
+}
+
+DisplayError DisplayHDMI::SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::SetActiveConfig(variable_info);
+}
+
+DisplayError DisplayHDMI::SetActiveConfig(uint32_t index) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::SetActiveConfig(index);
+}
+
+DisplayError DisplayHDMI::SetVSyncState(bool enable) {
+ SCOPE_LOCK(locker_);
+ return kErrorNotSupported;
+}
+
+void DisplayHDMI::SetIdleTimeoutMs(uint32_t timeout_ms) { }
+
+DisplayError DisplayHDMI::SetMaxMixerStages(uint32_t max_mixer_stages) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::SetMaxMixerStages(max_mixer_stages);
+}
+
+DisplayError DisplayHDMI::SetDisplayMode(uint32_t mode) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::SetDisplayMode(mode);
+}
+
int DisplayHDMI::GetBestConfig() {
uint32_t best_config_mode = 0;
HWDisplayAttributes *best = &display_attributes_[0];
@@ -111,5 +193,10 @@
return best_config_mode;
}
+void DisplayHDMI::AppendDump(char *buffer, uint32_t length) {
+ SCOPE_LOCK(locker_);
+ DisplayBase::AppendDump(buffer, length);
+}
+
} // namespace sde
diff --git a/displayengine/libs/core/display_hdmi.h b/displayengine/libs/core/display_hdmi.h
index 506329b..fc2be21 100644
--- a/displayengine/libs/core/display_hdmi.h
+++ b/displayengine/libs/core/display_hdmi.h
@@ -32,16 +32,35 @@
class HWHDMIInterface;
class HWInfoInterface;
-class DisplayHDMI : public DisplayBase {
+class DisplayHDMI : public DisplayBase, DumpImpl {
public:
DisplayHDMI(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
BufferSyncHandler *buffer_sync_handler, CompManager *comp_manager,
OfflineCtrl *offline_ctrl);
virtual DisplayError Init();
virtual DisplayError Deinit();
- virtual int GetBestConfig();
+ virtual DisplayError Prepare(LayerStack *layer_stack);
+ virtual DisplayError Commit(LayerStack *layer_stack);
+ virtual DisplayError Flush();
+ virtual DisplayError GetDisplayState(DisplayState *state);
+ virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count);
+ virtual DisplayError GetConfig(DisplayConfigFixedInfo *fixed_info);
+ virtual DisplayError GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info);
+ virtual DisplayError GetActiveConfig(uint32_t *index);
+ virtual DisplayError GetVSyncState(bool *enabled);
+ virtual DisplayError SetDisplayState(DisplayState state);
+ virtual DisplayError SetActiveConfig(DisplayConfigVariableInfo *variable_info);
+ virtual DisplayError SetActiveConfig(uint32_t index);
+ virtual DisplayError SetVSyncState(bool enable);
+ virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
+ virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
+ virtual DisplayError SetDisplayMode(uint32_t mode);
+ virtual void AppendDump(char *buffer, uint32_t length);
private:
+ virtual int GetBestConfig();
+
+ Locker locker_;
HWHDMIInterface *hw_hdmi_intf_;
HWInfoInterface *hw_info_intf_;
};
diff --git a/displayengine/libs/core/display_primary.cpp b/displayengine/libs/core/display_primary.cpp
index 55e927c..6f705f7 100644
--- a/displayengine/libs/core/display_primary.cpp
+++ b/displayengine/libs/core/display_primary.cpp
@@ -50,11 +50,21 @@
}
DisplayBase::hw_intf_ = hw_primary_intf_;
+ error = hw_primary_intf_->Open(this);
+ if (error != kErrorNone) {
+ return error;
+ }
+
error = DisplayBase::Init();
if (error != kErrorNone) {
HWPrimaryInterface::Destroy(hw_primary_intf_);
}
+ // Idle fallback feature is supported only for video mode panel.
+ if (hw_panel_info_.mode == kModeVideo) {
+ hw_primary_intf_->SetIdleTimeoutMs(Debug::GetIdleTimeoutMs());
+ }
+
return error;
}
@@ -70,6 +80,76 @@
return error;
}
+DisplayError DisplayPrimary::Prepare(LayerStack *layer_stack) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::Prepare(layer_stack);
+}
+
+DisplayError DisplayPrimary::Commit(LayerStack *layer_stack) {
+ SCOPE_LOCK(locker_);
+ DisplayError error = kErrorNone;
+
+ error = DisplayBase::Commit(layer_stack);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ hw_primary_intf_->GetHWPanelInfo(&hw_panel_info_);
+ // TODO(user): Update panel info in composition manager and resource manager
+
+ return error;
+}
+
+DisplayError DisplayPrimary::Flush() {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::Flush();
+}
+
+DisplayError DisplayPrimary::GetDisplayState(DisplayState *state) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::GetDisplayState(state);
+}
+
+DisplayError DisplayPrimary::GetNumVariableInfoConfigs(uint32_t *count) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::GetNumVariableInfoConfigs(count);
+}
+
+DisplayError DisplayPrimary::GetConfig(DisplayConfigFixedInfo *fixed_info) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::GetConfig(fixed_info);
+}
+
+DisplayError DisplayPrimary::GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::GetConfig(index, variable_info);
+}
+
+DisplayError DisplayPrimary::GetActiveConfig(uint32_t *index) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::GetActiveConfig(index);
+}
+
+DisplayError DisplayPrimary::GetVSyncState(bool *enabled) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::GetVSyncState(enabled);
+}
+
+DisplayError DisplayPrimary::SetDisplayState(DisplayState state) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::SetDisplayState(state);
+}
+
+DisplayError DisplayPrimary::SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::SetActiveConfig(variable_info);
+}
+
+DisplayError DisplayPrimary::SetActiveConfig(uint32_t index) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::SetActiveConfig(index);
+}
+
DisplayError DisplayPrimary::SetVSyncState(bool enable) {
SCOPE_LOCK(locker_);
DisplayError error = kErrorNone;
@@ -84,12 +164,83 @@
}
void DisplayPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
+ SCOPE_LOCK(locker_);
// Idle fallback feature is supported only for video mode panel.
- if (panel_info_.type == kCommandModePanel) {
- return;
+ if (hw_panel_info_.mode == kModeCommand) {
+ hw_primary_intf_->SetIdleTimeoutMs(timeout_ms);
+ }
+}
+
+DisplayError DisplayPrimary::SetMaxMixerStages(uint32_t max_mixer_stages) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::SetMaxMixerStages(max_mixer_stages);
+}
+
+DisplayError DisplayPrimary::SetDisplayMode(uint32_t mode) {
+ SCOPE_LOCK(locker_);
+ DisplayError error = kErrorNone;
+ HWDisplayMode hw_display_mode = kModeDefault;
+
+ if (state_ != kStateOn) {
+ DLOGW("Invalid display state (%d). Panel must be on.", state_);
+ return kErrorNotSupported;
}
- hw_primary_intf_->SetIdleTimeoutMs(timeout_ms);
+ switch(mode) {
+ case kModeVideo:
+ hw_display_mode = kModeVideo;
+ break;
+ case kModeCommand:
+ hw_display_mode = kModeCommand;
+ break;
+ default:
+ DLOGW("Invalid panel mode parameters. Requested (%d)", mode);
+ return kErrorParameters;
+ }
+
+ if (hw_display_mode == hw_panel_info_.mode) {
+ DLOGW("Same display mode requested. Current (%d) Requested (%d)", hw_panel_info_.mode,
+ hw_display_mode);
+ return kErrorNone;
+ }
+
+ error = hw_primary_intf_->SetDisplayMode(hw_display_mode);
+ if (error != kErrorNone) {
+ DLOGW("Retaining current display mode. Current (%d), Requested (%d)", hw_panel_info_.mode,
+ hw_display_mode);
+ return error;
+ }
+
+ return error;
+}
+
+void DisplayPrimary::AppendDump(char *buffer, uint32_t length) {
+ SCOPE_LOCK(locker_);
+ DisplayBase::AppendDump(buffer, length);
+}
+
+DisplayError DisplayPrimary::VSync(int64_t timestamp) {
+ SCOPE_LOCK(locker_);
+ if (vsync_enable_) {
+ DisplayEventVSync vsync;
+ vsync.timestamp = timestamp;
+ event_handler_->VSync(vsync);
+ }
+
+ return kErrorNone;
+}
+
+DisplayError DisplayPrimary::Blank(bool blank) {
+ SCOPE_LOCK(locker_);
+ return kErrorNone;
+}
+
+void DisplayPrimary::IdleTimeout() {
+ SCOPE_LOCK(locker_);
+ bool need_refresh = comp_manager_->ProcessIdleTimeout(display_comp_ctx_);
+ if (need_refresh) {
+ event_handler_->Refresh();
+ }
}
} // namespace sde
diff --git a/displayengine/libs/core/display_primary.h b/displayengine/libs/core/display_primary.h
index 76fbb06..8ce4f28 100644
--- a/displayengine/libs/core/display_primary.h
+++ b/displayengine/libs/core/display_primary.h
@@ -32,17 +32,38 @@
class HWPrimaryInterface;
class HWInfoInterface;
-class DisplayPrimary : public DisplayBase {
+class DisplayPrimary : public DisplayBase, DumpImpl, HWEventHandler {
public:
DisplayPrimary(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
BufferSyncHandler *buffer_sync_handler, CompManager *comp_manager,
OfflineCtrl *offline_ctrl);
virtual DisplayError Init();
virtual DisplayError Deinit();
+ virtual DisplayError Prepare(LayerStack *layer_stack);
+ virtual DisplayError Commit(LayerStack *layer_stack);
+ virtual DisplayError Flush();
+ virtual DisplayError GetDisplayState(DisplayState *state);
+ virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count);
+ virtual DisplayError GetConfig(DisplayConfigFixedInfo *fixed_info);
+ virtual DisplayError GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info);
+ virtual DisplayError GetActiveConfig(uint32_t *index);
+ virtual DisplayError GetVSyncState(bool *enabled);
+ virtual DisplayError SetDisplayState(DisplayState state);
+ virtual DisplayError SetActiveConfig(DisplayConfigVariableInfo *variable_info);
+ virtual DisplayError SetActiveConfig(uint32_t index);
virtual DisplayError SetVSyncState(bool enable);
virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
+ virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
+ virtual DisplayError SetDisplayMode(uint32_t mode);
+ virtual void AppendDump(char *buffer, uint32_t length);
+
+ // Implement the HWEventHandlers
+ virtual DisplayError VSync(int64_t timestamp);
+ virtual DisplayError Blank(bool blank);
+ virtual void IdleTimeout();
private:
+ Locker locker_;
HWPrimaryInterface *hw_primary_intf_;
HWInfoInterface *hw_info_intf_;
};
diff --git a/displayengine/libs/core/display_virtual.cpp b/displayengine/libs/core/display_virtual.cpp
index 359e6a3..a5af9bf 100644
--- a/displayengine/libs/core/display_virtual.cpp
+++ b/displayengine/libs/core/display_virtual.cpp
@@ -48,7 +48,12 @@
if (error != kErrorNone) {
return error;
}
+
DisplayBase::hw_intf_ = hw_virtual_intf_;
+ error = hw_virtual_intf_->Open(NULL);
+ if (error != kErrorNone) {
+ return error;
+ }
error = DisplayBase::Init();
if (error != kErrorNone) {
@@ -70,5 +75,87 @@
return error;
}
+DisplayError DisplayVirtual::Prepare(LayerStack *layer_stack) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::Prepare(layer_stack);
+}
+
+DisplayError DisplayVirtual::Commit(LayerStack *layer_stack) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::Commit(layer_stack);
+}
+
+DisplayError DisplayVirtual::Flush() {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::Flush();
+}
+
+DisplayError DisplayVirtual::GetDisplayState(DisplayState *state) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::GetDisplayState(state);
+}
+
+DisplayError DisplayVirtual::GetNumVariableInfoConfigs(uint32_t *count) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::GetNumVariableInfoConfigs(count);
+}
+
+DisplayError DisplayVirtual::GetConfig(DisplayConfigFixedInfo *fixed_info) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::GetConfig(fixed_info);
+}
+
+DisplayError DisplayVirtual::GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::GetConfig(index, variable_info);
+}
+
+DisplayError DisplayVirtual::GetActiveConfig(uint32_t *index) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::GetActiveConfig(index);
+}
+
+DisplayError DisplayVirtual::GetVSyncState(bool *enabled) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::GetVSyncState(enabled);
+}
+
+DisplayError DisplayVirtual::SetDisplayState(DisplayState state) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::SetDisplayState(state);
+}
+
+DisplayError DisplayVirtual::SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::SetActiveConfig(variable_info);
+}
+
+DisplayError DisplayVirtual::SetActiveConfig(uint32_t index) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::SetActiveConfig(index);
+}
+
+DisplayError DisplayVirtual::SetVSyncState(bool enable) {
+ SCOPE_LOCK(locker_);
+ return kErrorNotSupported;
+}
+
+void DisplayVirtual::SetIdleTimeoutMs(uint32_t timeout_ms) { }
+
+DisplayError DisplayVirtual::SetMaxMixerStages(uint32_t max_mixer_stages) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::SetMaxMixerStages(max_mixer_stages);
+}
+
+DisplayError DisplayVirtual::SetDisplayMode(uint32_t mode) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::SetDisplayMode(mode);
+}
+
+void DisplayVirtual::AppendDump(char *buffer, uint32_t length) {
+ SCOPE_LOCK(locker_);
+ DisplayBase::AppendDump(buffer, length);
+}
+
} // namespace sde
diff --git a/displayengine/libs/core/display_virtual.h b/displayengine/libs/core/display_virtual.h
index 7dee9fa..419c6ec 100644
--- a/displayengine/libs/core/display_virtual.h
+++ b/displayengine/libs/core/display_virtual.h
@@ -32,15 +32,33 @@
class HWVirtualInterface;
class HWInfoInterface;
-class DisplayVirtual : public DisplayBase {
+class DisplayVirtual : public DisplayBase, DumpImpl {
public:
DisplayVirtual(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
BufferSyncHandler *buffer_sync_handler, CompManager *comp_manager,
OfflineCtrl *offline_ctrl);
virtual DisplayError Init();
virtual DisplayError Deinit();
+ virtual DisplayError Prepare(LayerStack *layer_stack);
+ virtual DisplayError Commit(LayerStack *layer_stack);
+ virtual DisplayError Flush();
+ virtual DisplayError GetDisplayState(DisplayState *state);
+ virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count);
+ virtual DisplayError GetConfig(DisplayConfigFixedInfo *fixed_info);
+ virtual DisplayError GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info);
+ virtual DisplayError GetActiveConfig(uint32_t *index);
+ virtual DisplayError GetVSyncState(bool *enabled);
+ virtual DisplayError SetDisplayState(DisplayState state);
+ virtual DisplayError SetActiveConfig(DisplayConfigVariableInfo *variable_info);
+ virtual DisplayError SetActiveConfig(uint32_t index);
+ virtual DisplayError SetVSyncState(bool enable);
+ virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
+ virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
+ virtual DisplayError SetDisplayMode(uint32_t mode);
+ virtual void AppendDump(char *buffer, uint32_t length);
private:
+ Locker locker_;
HWVirtualInterface *hw_virtual_intf_;
HWInfoInterface *hw_info_intf_;
};
diff --git a/displayengine/libs/core/fb/hw_device.cpp b/displayengine/libs/core/fb/hw_device.cpp
index ed19d80..a0a0fe2 100644
--- a/displayengine/libs/core/fb/hw_device.cpp
+++ b/displayengine/libs/core/fb/hw_device.cpp
@@ -61,7 +61,7 @@
HWDevice::HWDevice(BufferSyncHandler *buffer_sync_handler)
: fb_node_index_(-1), fb_path_("/sys/devices/virtual/graphics/fb"), hotplug_enabled_(false),
- buffer_sync_handler_(buffer_sync_handler) {
+ buffer_sync_handler_(buffer_sync_handler), synchronous_commit_(false) {
// Pointer to actual driver interfaces.
ioctl_ = ::ioctl;
open_ = ::open;
@@ -146,7 +146,7 @@
}
DisplayError HWDevice::GetHWPanelInfo(HWPanelInfo *panel_info) {
- *panel_info = panel_info_;
+ *panel_info = hw_panel_info_;
return kErrorNone;
}
@@ -425,9 +425,13 @@
mdp_commit.release_fence = -1;
mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
+ if (synchronous_commit_) {
+ mdp_commit.flags |= MDP_COMMIT_WAIT_FOR_FINISH;
+ }
if (ioctl_(device_fd_, MSMFB_ATOMIC_COMMIT, &mdp_disp_commit_) < 0) {
IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, device_type_);
DumpLayerCommit(mdp_disp_commit_);
+ synchronous_commit_ = false;
return kErrorHardware;
}
@@ -463,6 +467,13 @@
close_(mdp_commit.release_fence);
+ if (synchronous_commit_) {
+ // A synchronous commit can be requested when changing the display mode so we need to update
+ // panel info.
+ PopulateHWPanelInfo();
+ synchronous_commit_ = false;
+ }
+
return kErrorNone;
}
@@ -488,13 +499,20 @@
case kFormatBGRA8888: *target = MDP_BGRA_8888; break;
case kFormatRGBX8888: *target = MDP_RGBX_8888; break;
case kFormatBGRX8888: *target = MDP_BGRX_8888; break;
+ case kFormatRGBA5551: *target = MDP_RGBA_5551; break;
+ case kFormatRGBA4444: *target = MDP_RGBA_4444; break;
case kFormatRGB888: *target = MDP_RGB_888; break;
+ case kFormatBGR888: *target = MDP_BGR_888; break;
case kFormatRGB565: *target = MDP_RGB_565; break;
case kFormatYCbCr420Planar: *target = MDP_Y_CB_CR_H2V2; break;
case kFormatYCrCb420Planar: *target = MDP_Y_CR_CB_H2V2; break;
case kFormatYCbCr420SemiPlanar: *target = MDP_Y_CBCR_H2V2; break;
case kFormatYCrCb420SemiPlanar: *target = MDP_Y_CRCB_H2V2; break;
- case kFormatYCbCr422Packed: *target = MDP_YCBYCR_H2V1; break;
+ case kFormatYCbCr422H1V2SemiPlanar: *target = MDP_Y_CBCR_H1V2; break;
+ case kFormatYCrCb422H1V2SemiPlanar: *target = MDP_Y_CRCB_H1V2; break;
+ case kFormatYCbCr422H2V1SemiPlanar: *target = MDP_Y_CBCR_H2V1; break;
+ case kFormatYCrCb422H2V1SemiPlanar: *target = MDP_Y_CRCB_H2V1; break;
+ case kFormatYCbCr422H2V1Packed: *target = MDP_YCBYCR_H2V1; break;
case kFormatYCbCr420SemiPlanarVenus: *target = MDP_Y_CBCR_H2V2_VENUS; break;
case kFormatRGBA8888Ubwc: *target = MDP_RGBA_8888_UBWC; break;
case kFormatRGB565Ubwc: *target = MDP_RGB_565_UBWC; break;
@@ -525,6 +543,7 @@
*target = width * 4;
break;
case kFormatRGB888:
+ case kFormatBGR888:
*target = width * 3;
break;
case kFormatRGB565:
@@ -538,7 +557,13 @@
case kFormatYCrCb420SemiPlanar:
*target = width;
break;
- case kFormatYCbCr422Packed:
+ case kFormatYCbCr422H2V1Packed:
+ case kFormatYCrCb422H2V1SemiPlanar:
+ case kFormatYCrCb422H1V2SemiPlanar:
+ case kFormatYCbCr422H2V1SemiPlanar:
+ case kFormatYCbCr422H1V2SemiPlanar:
+ case kFormatRGBA5551:
+ case kFormatRGBA4444:
*target = width * 2;
break;
default:
@@ -586,12 +611,12 @@
}
break;
case kDeviceHDMI:
- if (panel_info->type == kDTvPanel) {
+ if (panel_info->port == kPortDTv) {
fb_node_index = i;
}
break;
case kDeviceVirtual:
- if (panel_info->type == kWriteBackPanel) {
+ if (panel_info->port == kPortWriteBack) {
fb_node_index = i;
}
break;
@@ -603,21 +628,23 @@
}
void HWDevice::PopulateHWPanelInfo() {
- panel_info_ = HWPanelInfo();
- GetHWPanelInfoByNode(fb_node_index_, &panel_info_);
- DLOGI("Device type = %d, Panel Type = %d, Device Node = %d, Is Primary = %d",
- device_type_, panel_info_.type, fb_node_index_, panel_info_.is_primary_panel);
+ hw_panel_info_ = HWPanelInfo();
+ GetHWPanelInfoByNode(fb_node_index_, &hw_panel_info_);
+ DLOGI("Device type = %d, Display Port = %d, Display Mode = %d, Device Node = %d, Is Primary = %d",
+ device_type_, hw_panel_info_.port, hw_panel_info_.mode, fb_node_index_,
+ hw_panel_info_.is_primary_panel);
DLOGI("Partial Update = %d, Dynamic FPS = %d",
- panel_info_.partial_update, panel_info_.dynamic_fps);
+ hw_panel_info_.partial_update, hw_panel_info_.dynamic_fps);
DLOGI("Align: left = %d, width = %d, top = %d, height = %d",
- panel_info_.left_align, panel_info_.width_align,
- panel_info_.top_align, panel_info_.height_align);
+ hw_panel_info_.left_align, hw_panel_info_.width_align,
+ hw_panel_info_.top_align, hw_panel_info_.height_align);
DLOGI("ROI: min_width = %d, min_height = %d, need_merge = %d",
- panel_info_.min_roi_width, panel_info_.min_roi_height, panel_info_.needs_roi_merge);
- DLOGI("FPS: min = %d, max =%d", panel_info_.min_fps, panel_info_.max_fps);
- DLOGI("Left Split = %d, Right Split = %d", panel_info_.split_info.left_split,
- panel_info_.split_info.right_split);
- DLOGI("Source Split Always = %d", panel_info_.split_info.always_src_split);
+ hw_panel_info_.min_roi_width, hw_panel_info_.min_roi_height,
+ hw_panel_info_.needs_roi_merge);
+ 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) {
@@ -636,7 +663,7 @@
size_t len = kMaxStringLength;
ssize_t read;
- char *line = stringbuffer;
+ char *line = NULL;
while ((read = getline(&line, &len, fileptr)) != -1) {
uint32_t token_count = 0;
const uint32_t max_count = 10;
@@ -670,45 +697,80 @@
}
}
fclose(fileptr);
- panel_info->type = GetHWPanelType(device_node);
+ free(line);
+ panel_info->port = GetHWDisplayPort(device_node);
+ panel_info->mode = GetHWDisplayMode(device_node);
GetSplitInfo(device_node, panel_info);
}
-HWPanelType HWDevice::GetHWPanelType(int device_node) {
+HWDisplayPort HWDevice::GetHWDisplayPort(int device_node) {
char stringbuffer[kMaxStringLength];
DisplayError error = kErrorNone;
- char *line = stringbuffer;
+ char *line = NULL;
size_t len = kMaxStringLength;
ssize_t read;
- HWPanelType panel_type = kNoPanel;
+ HWDisplayPort port = kPortDefault;
snprintf(stringbuffer, sizeof(stringbuffer), "%s%d/msm_fb_type", fb_path_, device_node);
FILE *fileptr = fopen(stringbuffer, "r");
if (!fileptr) {
DLOGW("File not found %s", stringbuffer);
- return panel_type;
+ return port;
}
read = getline(&line, &len, fileptr);
if (read == -1) {
fclose(fileptr);
- return panel_type;
+ return port;
}
if ((strncmp(line, "mipi dsi cmd panel", strlen("mipi dsi cmd panel")) == 0)) {
- panel_type = kCommandModePanel;
+ port = kPortDSI;
} else if ((strncmp(line, "mipi dsi video panel", strlen("mipi dsi video panel")) == 0)) {
- panel_type = kVideoModePanel;
+ port = kPortDSI;
} else if ((strncmp(line, "lvds panel", strlen("lvds panel")) == 0)) {
- panel_type = kLVDSPanel;
+ port = kPortLVDS;
} else if ((strncmp(line, "edp panel", strlen("edp panel")) == 0)) {
- panel_type = kEDPPanel;
+ port = kPortEDP;
} else if ((strncmp(line, "dtv panel", strlen("dtv panel")) == 0)) {
- panel_type = kDTvPanel;
+ port = kPortDTv;
} else if ((strncmp(line, "writeback panel", strlen("writeback panel")) == 0)) {
- panel_type = kWriteBackPanel;
+ port = kPortWriteBack;
+ } else {
+ port = kPortDefault;
}
fclose(fileptr);
+ free(line);
+ return port;
+}
- return panel_type;
+HWDisplayMode HWDevice::GetHWDisplayMode(int device_node) {
+ char stringbuffer[kMaxStringLength];
+ DisplayError error = kErrorNone;
+ char *line = NULL;
+ size_t len = kMaxStringLength;
+ ssize_t read;
+ HWDisplayMode mode = kModeDefault;
+
+ snprintf(stringbuffer, sizeof(stringbuffer), "%s%d/msm_fb_type", fb_path_, device_node);
+ FILE *fileptr = fopen(stringbuffer, "r");
+ if (!fileptr) {
+ DLOGW("File not found %s", stringbuffer);
+ return mode;
+ }
+ read = getline(&line, &len, fileptr);
+ if (read == -1) {
+ fclose(fileptr);
+ return mode;
+ }
+ if ((strncmp(line, "mipi dsi cmd panel", strlen("mipi dsi cmd panel")) == 0)) {
+ mode = kModeCommand;
+ } else if ((strncmp(line, "mipi dsi video panel", strlen("mipi dsi video panel")) == 0)) {
+ mode = kModeVideo;
+ } else {
+ mode = kModeDefault;
+ }
+ fclose(fileptr);
+ free(line);
+ return mode;
}
void HWDevice::GetSplitInfo(int device_node, HWPanelInfo *panel_info) {
@@ -716,7 +778,7 @@
FILE *fileptr = NULL;
size_t len = kMaxStringLength;
ssize_t read;
- char *line = stringbuffer;
+ char *line = NULL;
uint32_t token_count = 0;
const uint32_t max_count = 10;
char *tokens[max_count] = { NULL };
@@ -755,6 +817,7 @@
}
}
fclose(fileptr);
+ free(line);
}
int HWDevice::ParseLine(char *input, char *tokens[], const uint32_t max_token, uint32_t *count) {
diff --git a/displayengine/libs/core/fb/hw_device.h b/displayengine/libs/core/fb/hw_device.h
index 2a240c6..07d9e4d 100644
--- a/displayengine/libs/core/fb/hw_device.h
+++ b/displayengine/libs/core/fb/hw_device.h
@@ -84,7 +84,8 @@
// Populates HWPanelInfo based on node index
void PopulateHWPanelInfo();
void GetHWPanelInfoByNode(int device_node, HWPanelInfo *panel_info);
- HWPanelType GetHWPanelType(int device_node);
+ HWDisplayPort GetHWDisplayPort(int device_node);
+ HWDisplayMode GetHWDisplayMode(int device_node);
void GetSplitInfo(int device_node, HWPanelInfo *panel_info);
int ParseLine(char *input, char *tokens[], const uint32_t max_token, uint32_t *count);
mdp_scale_data* GetScaleDataRef(uint32_t index) { return &scale_data_[index]; }
@@ -106,7 +107,7 @@
// Store the Device EventHandler - used for callback
HWEventHandler *event_handler_;
HWResourceInfo hw_resource_;
- HWPanelInfo panel_info_;
+ HWPanelInfo hw_panel_info_;
HWInfoInterface *hw_info_intf_;
int fb_node_index_;
const char *fb_path_;
@@ -119,6 +120,7 @@
mdp_scale_data scale_data_[kMaxSDELayers * 2];
mdp_output_layer mdp_out_layer_;
const char *device_name_;
+ bool synchronous_commit_;
};
} // namespace sde
diff --git a/displayengine/libs/core/fb/hw_primary.cpp b/displayengine/libs/core/fb/hw_primary.cpp
index 0dd0db2..3b22054 100644
--- a/displayengine/libs/core/fb/hw_primary.cpp
+++ b/displayengine/libs/core/fb/hw_primary.cpp
@@ -91,7 +91,7 @@
for (int event = 0; event < kNumDisplayEvents; event++) {
pollfd &poll_fd = poll_fds_[event];
- if ((panel_info_.type == kCommandModePanel) &&
+ if ((hw_panel_info_.mode == kModeCommand) &&
(!strncmp(event_name[event], "idle_notify", strlen("idle_notify")))) {
continue;
}
@@ -196,11 +196,11 @@
(FLOAT(var_screeninfo.yres) * 25.4f) / FLOAT(var_screeninfo.height);
display_attributes->fps = FLOAT(meta_data.data.panel_frame_rate);
display_attributes->vsync_period_ns = UINT32(1000000000L / display_attributes->fps);
- display_attributes->is_device_split = (panel_info_.split_info.left_split ||
+ display_attributes->is_device_split = (hw_panel_info_.split_info.left_split ||
(var_screeninfo.xres > hw_resource_.max_mixer_width)) ? true : false;
- display_attributes->split_left = panel_info_.split_info.left_split ?
- panel_info_.split_info.left_split : display_attributes->x_pixels / 2;
- display_attributes->always_src_split = panel_info_.split_info.always_src_split;
+ 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;
return kErrorNone;
}
@@ -368,5 +368,33 @@
return kErrorNone;
}
+DisplayError HWPrimary::SetDisplayMode(const HWDisplayMode hw_display_mode) {
+ DisplayError error = kErrorNone;
+ uint32_t mode = -1;
+
+ switch (hw_display_mode) {
+ case kModeVideo:
+ mode = kModeLPMVideo;
+ break;
+ case kModeCommand:
+ mode = kModeLPMCommand;
+ break;
+ default:
+ DLOGW("Failed to translate SDE display mode %d to a MSMFB_LPM_ENABLE mode",
+ hw_display_mode);
+ return kErrorParameters;
+ }
+
+ if (ioctl_(device_fd_, MSMFB_LPM_ENABLE, &mode) < 0) {
+ IOCTL_LOGE(MSMFB_LPM_ENABLE, device_type_);
+ return kErrorHardware;
+ }
+
+ DLOGI("Triggering display mode change to %d on next commit.", hw_display_mode);
+ synchronous_commit_ = true;
+
+ return kErrorNone;
+}
+
} // namespace sde
diff --git a/displayengine/libs/core/fb/hw_primary.h b/displayengine/libs/core/fb/hw_primary.h
index 8ede12d..b008c92 100644
--- a/displayengine/libs/core/fb/hw_primary.h
+++ b/displayengine/libs/core/fb/hw_primary.h
@@ -52,8 +52,15 @@
virtual DisplayError Flush();
virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
virtual DisplayError SetVSyncState(bool enable);
+ virtual DisplayError SetDisplayMode(const HWDisplayMode hw_display_mode);
private:
+ // Panel modes for the MSMFB_LPM_ENABLE ioctl
+ enum {
+ kModeLPMVideo,
+ kModeLPMCommand,
+ };
+
// Event Thread to receive vsync/blank events
static void* DisplayEventThread(void *context);
void* DisplayEventThreadHandler();
diff --git a/displayengine/libs/core/fb/hw_virtual.cpp b/displayengine/libs/core/fb/hw_virtual.cpp
index 2d7cd3e..81b31d0 100644
--- a/displayengine/libs/core/fb/hw_virtual.cpp
+++ b/displayengine/libs/core/fb/hw_virtual.cpp
@@ -41,7 +41,7 @@
hw_virtual = new HWVirtual(buffer_sync_handler, hw_info_intf);
error = hw_virtual->Init();
- if (UNLIKELY(error != kErrorNone)) {
+ if (error != kErrorNone) {
delete hw_virtual;
} else {
*intf = hw_virtual;
diff --git a/displayengine/libs/core/hw_primary_interface.h b/displayengine/libs/core/hw_primary_interface.h
index 31df694..d195348 100644
--- a/displayengine/libs/core/hw_primary_interface.h
+++ b/displayengine/libs/core/hw_primary_interface.h
@@ -37,6 +37,7 @@
static DisplayError Destroy(HWPrimaryInterface *intf);
virtual DisplayError SetVSyncState(bool enable) = 0;
virtual void SetIdleTimeoutMs(uint32_t timeout_ms) = 0;
+ virtual DisplayError SetDisplayMode(const HWDisplayMode hw_display_mode) = 0;
protected:
virtual ~HWPrimaryInterface() { }
diff --git a/displayengine/libs/core/res_config.cpp b/displayengine/libs/core/res_config.cpp
index b4aa779..ea90dfb 100644
--- a/displayengine/libs/core/res_config.cpp
+++ b/displayengine/libs/core/res_config.cpp
@@ -33,6 +33,15 @@
namespace sde {
+static void GetAlignFactor(const LayerBufferFormat &format, uint32_t *align_x, uint32_t *align_y) {
+ *align_x = 1;
+ *align_y = 1;
+ if (!IS_RGB_FORMAT(format)) {
+ *align_x = 2;
+ *align_y = 2;
+ }
+}
+
void ResManager::RotationConfig(LayerBufferFormat format, const LayerTransform &transform,
const float &downscale, LayerRect *src_rect,
struct HWLayerConfig *layer_config, uint32_t *rotate_count) {
@@ -46,22 +55,24 @@
dst_rect.left = 0.0f;
rotate->downscale_ratio = downscale;
+ uint32_t align_x, align_y;
+ GetAlignFactor(format, &align_x, &align_y);
// downscale when doing rotation
if (rot90) {
if (downscale > 1.0f) {
- src_height = ROUND_UP_ALIGN_DOWN(src_height, downscale);
+ src_height = ROUND_UP_ALIGN_DOWN(src_height, downscale * FLOAT(align_x));
src_rect->bottom = src_rect->top + src_height;
- src_width = ROUND_UP_ALIGN_DOWN(src_width, downscale);
+ src_width = ROUND_UP_ALIGN_DOWN(src_width, downscale * FLOAT(align_y));
src_rect->right = src_rect->left + src_width;
}
dst_rect.right = src_height / downscale;
dst_rect.bottom = src_width / downscale;
} else {
if (downscale > 1.0f) {
- src_width = ROUND_UP_ALIGN_DOWN(src_width, downscale);
+ src_width = ROUND_UP_ALIGN_DOWN(src_width, downscale * FLOAT(align_x));
src_rect->right = src_rect->left + src_width;
- src_height = ROUND_UP_ALIGN_DOWN(src_height, downscale);
+ src_height = ROUND_UP_ALIGN_DOWN(src_height, downscale * FLOAT(align_y));
src_rect->bottom = src_rect->top + src_height;
}
dst_rect.right = src_width / downscale;
@@ -250,11 +261,9 @@
continue;
}
- uint32_t align_x = 1, align_y = 1;
- if (IsYuvFormat(layer.input_buffer->format)) {
- // TODO(user) Select x and y alignment according to the format
- align_x = 2;
- align_y = 2;
+ uint32_t align_x, align_y;
+ GetAlignFactor(layer.input_buffer->format, &align_x, &align_y);
+ if (align_x > 1 || align_y > 1) {
NormalizeRect(align_x, align_y, &src_rect);
}
diff --git a/displayengine/libs/core/res_manager.cpp b/displayengine/libs/core/res_manager.cpp
index 238dfa8..09b64ab 100644
--- a/displayengine/libs/core/res_manager.cpp
+++ b/displayengine/libs/core/res_manager.cpp
@@ -325,8 +325,7 @@
HWPipeInfo *pipe_info = &layer_config.left_pipe;
- // Should have a generic macro
- bool is_yuv = IsYuvFormat(layer.input_buffer->format);
+ bool is_yuv = !IS_RGB_FORMAT(layer.input_buffer->format);
// left pipe is needed
if (pipe_info->valid) {
@@ -619,9 +618,16 @@
case kFormatBGRX8888:
return 4.0f;
case kFormatRGB888:
+ case kFormatBGR888:
return 3.0f;
case kFormatRGB565:
- case kFormatYCbCr422Packed:
+ case kFormatRGBA5551:
+ case kFormatRGBA4444:
+ case kFormatYCbCr422H2V1Packed:
+ case kFormatYCrCb422H2V1SemiPlanar:
+ case kFormatYCrCb422H1V2SemiPlanar:
+ case kFormatYCbCr422H2V1SemiPlanar:
+ case kFormatYCbCr422H1V2SemiPlanar:
return 2.0f;
case kFormatYCbCr420Planar:
case kFormatYCrCb420Planar:
diff --git a/displayengine/libs/core/res_manager.h b/displayengine/libs/core/res_manager.h
index b2ddcb9..7f78b29 100644
--- a/displayengine/libs/core/res_manager.h
+++ b/displayengine/libs/core/res_manager.h
@@ -194,7 +194,6 @@
LayerRect *src_left, LayerRect *dst_left, LayerRect *src_right,
LayerRect *dst_right, uint32_t align_x);
bool IsMacroTileFormat(const LayerBuffer *buffer) { return buffer->flags.macro_tile; }
- bool IsYuvFormat(LayerBufferFormat format) { return (format >= kFormatYCbCr420Planar); }
bool IsRotationNeeded(float rotation)
{ return (UINT32(rotation) == 90 || UINT32(rotation) == 270); }
void RotationConfig(LayerBufferFormat format, const LayerTransform &transform,
diff --git a/displayengine/libs/core/scalar_helper.cpp b/displayengine/libs/core/scalar_helper.cpp
old mode 100755
new mode 100644
index 22488b3..55b462f
--- a/displayengine/libs/core/scalar_helper.cpp
+++ b/displayengine/libs/core/scalar_helper.cpp
@@ -75,13 +75,20 @@
case kFormatXRGB8888: format = scalar::XRGB_8888; break;
case kFormatRGBX8888: format = scalar::RGBX_8888; break;
case kFormatBGRX8888: format = scalar::BGRX_8888; break;
+ case kFormatRGBA5551: format = scalar::RGBA_5551; break;
+ case kFormatRGBA4444: format = scalar::RGBA_4444; break;
case kFormatRGB888: format = scalar::RGB_888; break;
+ case kFormatBGR888: format = scalar::BGR_888; break;
case kFormatRGB565: format = scalar::RGB_565; break;
case kFormatYCbCr420Planar: format = scalar::Y_CB_CR_H2V2; break;
case kFormatYCrCb420Planar: format = scalar::Y_CR_CB_H2V2; break;
case kFormatYCbCr420SemiPlanar: format = scalar::Y_CBCR_H2V2; break;
case kFormatYCrCb420SemiPlanar: format = scalar::Y_CRCB_H2V2; break;
- case kFormatYCbCr422Packed: format = scalar::YCBYCR_H2V1; break;
+ case kFormatYCbCr422H1V2SemiPlanar: format = scalar::Y_CBCR_H1V2; break;
+ case kFormatYCrCb422H1V2SemiPlanar: format = scalar::Y_CRCB_H1V2; break;
+ case kFormatYCbCr422H2V1SemiPlanar: format = scalar::Y_CBCR_H2V1; break;
+ case kFormatYCrCb422H2V1SemiPlanar: format = scalar::Y_CRCB_H2V1; break;
+ case kFormatYCbCr422H2V1Packed: format = scalar::YCBYCR_H2V1; break;
case kFormatYCbCr420SemiPlanarVenus: format = scalar::Y_CBCR_H2V2_VENUS; break;
case kFormatRGBA8888Ubwc: format = scalar::RGBA_8888_UBWC; break;
case kFormatRGB565Ubwc: format = scalar::RGB_565_UBWC; break;
diff --git a/displayengine/libs/hwc/hwc_buffer_allocator.cpp b/displayengine/libs/hwc/hwc_buffer_allocator.cpp
index f2383b2..2adfc3a 100644
--- a/displayengine/libs/hwc/hwc_buffer_allocator.cpp
+++ b/displayengine/libs/hwc/hwc_buffer_allocator.cpp
@@ -157,9 +157,12 @@
case kFormatYCrCb420Planar: *target = HAL_PIXEL_FORMAT_YV12; break;
case kFormatYCrCb420SemiPlanar: *target = HAL_PIXEL_FORMAT_YCrCb_420_SP; break;
case kFormatYCbCr420SemiPlanar: *target = HAL_PIXEL_FORMAT_YCbCr_420_SP; break;
- case kFormatYCbCr422Packed: *target = HAL_PIXEL_FORMAT_YCbCr_422_I; break;
+ 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 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;
default:
DLOGE("Unsupported format = 0x%x", format);
diff --git a/displayengine/libs/hwc/hwc_display.cpp b/displayengine/libs/hwc/hwc_display.cpp
index 1be682d..e2327c5 100644
--- a/displayengine/libs/hwc/hwc_display.cpp
+++ b/displayengine/libs/hwc/hwc_display.cpp
@@ -49,7 +49,7 @@
int HWCDisplay::Init() {
DisplayError error = core_intf_->CreateDisplay(type_, this, &display_intf_);
- if (UNLIKELY(error != kErrorNone)) {
+ if (error != kErrorNone) {
DLOGE("Display create failed. Error = %d display_type %d event_handler %p disp_intf %p",
error, type_, this, &display_intf_);
return -EINVAL;
@@ -60,7 +60,7 @@
int HWCDisplay::Deinit() {
DisplayError error = core_intf_->DestroyDisplay(display_intf_);
- if (UNLIKELY(error != kErrorNone)) {
+ if (error != kErrorNone) {
DLOGE("Display destroy failed. Error = %d", error);
return -EINVAL;
}
@@ -87,7 +87,7 @@
DLOGW("Unsupported event = %d", event);
}
- if (UNLIKELY(error != kErrorNone)) {
+ if (error != kErrorNone) {
DLOGE("Failed. event = %d, enable = %d, error = %d", event, enable, error);
return -EINVAL;
}
@@ -105,17 +105,19 @@
break;
case HWC_POWER_MODE_NORMAL:
state = kStateOn;
+ last_power_mode_ = HWC_POWER_MODE_NORMAL;
break;
case HWC_POWER_MODE_DOZE:
case HWC_POWER_MODE_DOZE_SUSPEND:
state = kStateDoze;
+ last_power_mode_ = HWC_POWER_MODE_DOZE;
break;
default:
return -EINVAL;
}
DisplayError error = display_intf_->SetDisplayState(state);
- if (UNLIKELY(error != kErrorNone)) {
+ if (error != kErrorNone) {
DLOGE("Set state failed. Error = %d", error);
return -EINVAL;
}
@@ -137,7 +139,7 @@
DisplayConfigVariableInfo variable_config;
error = display_intf_->GetConfig(config, &variable_config);
- if (UNLIKELY(error != kErrorNone)) {
+ if (error != kErrorNone) {
DLOGE("GetConfig variable info failed. Error = %d", error);
return -EINVAL;
}
@@ -208,6 +210,10 @@
DLOGI("num_frame_dump %d, input_layer_dump_enable %d", dump_frame_count_, dump_input_layers_);
}
+uint32_t HWCDisplay::GetLastPowerMode() {
+ return last_power_mode_;
+}
+
DisplayError HWCDisplay::VSync(const DisplayEventVSync &vsync) {
if (*hwc_procs_) {
(*hwc_procs_)->vsync(*hwc_procs_, id_, vsync.timestamp);
@@ -243,8 +249,8 @@
// Layer array may be large enough to hold current number of layers.
// If not, re-allocate it now.
- if (UNLIKELY(layer_stack_memory_.size < required_size)) {
- if (LIKELY(layer_stack_memory_.raw)) {
+ if (layer_stack_memory_.size < required_size) {
+ if (layer_stack_memory_.raw) {
delete[] layer_stack_memory_.raw;
layer_stack_memory_.size = 0;
}
@@ -253,7 +259,7 @@
required_size = ROUND_UP(required_size, layer_stack_memory_.kSizeSteps);
layer_stack_memory_.raw = new uint8_t[required_size];
- if (UNLIKELY(!layer_stack_memory_.raw)) {
+ if (!layer_stack_memory_.raw) {
return -ENOMEM;
}
@@ -628,6 +634,8 @@
switch (source) {
case HAL_PIXEL_FORMAT_RGBA_8888: format = kFormatRGBA8888; break;
+ case HAL_PIXEL_FORMAT_RGBA_5551: format = kFormatRGBA5551; break;
+ case HAL_PIXEL_FORMAT_RGBA_4444: format = kFormatRGBA4444; break;
case HAL_PIXEL_FORMAT_BGRA_8888: format = kFormatBGRA8888; break;
case HAL_PIXEL_FORMAT_RGBX_8888: format = kFormatRGBX8888; break;
case HAL_PIXEL_FORMAT_BGRX_8888: format = kFormatBGRX8888; break;
@@ -637,6 +645,8 @@
case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS: format = kFormatYCbCr420SemiPlanarVenus; break;
case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC: format = kFormatYCbCr420SPVenusUbwc; break;
case HAL_PIXEL_FORMAT_YCrCb_420_SP: format = kFormatYCrCb420SemiPlanar; break;
+ case HAL_PIXEL_FORMAT_YCbCr_422_SP: format = kFormatYCbCr422H2V1SemiPlanar; break;
+ case HAL_PIXEL_FORMAT_YCbCr_422_I: format = kFormatYCbCr422H2V1Packed; break;
default:
DLOGW("Unsupported format type = %d", source);
return kFormatInvalid;
diff --git a/displayengine/libs/hwc/hwc_display.h b/displayengine/libs/hwc/hwc_display.h
index 8feddf6..7ef8187 100644
--- a/displayengine/libs/hwc/hwc_display.h
+++ b/displayengine/libs/hwc/hwc_display.h
@@ -46,6 +46,7 @@
virtual int SetActiveConfig(hwc_display_contents_1_t *content_list);
virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
+ virtual uint32_t GetLastPowerMode();
protected:
// Maximum number of layers supported by display engine.
@@ -117,6 +118,7 @@
uint32_t dump_frame_count_;
uint32_t dump_frame_index_;
bool dump_input_layers_;
+ uint32_t last_power_mode_;
};
} // namespace sde
diff --git a/displayengine/libs/hwc/hwc_display_primary.cpp b/displayengine/libs/hwc/hwc_display_primary.cpp
index 6dbb723..d1cd2d2 100644
--- a/displayengine/libs/hwc/hwc_display_primary.cpp
+++ b/displayengine/libs/hwc/hwc_display_primary.cpp
@@ -72,5 +72,15 @@
return 0;
}
+DisplayError HWCDisplayPrimary::SetDisplayMode(uint32_t mode) {
+ DisplayError error = kErrorNone;
+
+ if (display_intf_) {
+ error = display_intf_->SetDisplayMode(mode);
+ }
+
+ return error;
+}
+
} // namespace sde
diff --git a/displayengine/libs/hwc/hwc_display_primary.h b/displayengine/libs/hwc/hwc_display_primary.h
index 4e9e93f..5015fff 100644
--- a/displayengine/libs/hwc/hwc_display_primary.h
+++ b/displayengine/libs/hwc/hwc_display_primary.h
@@ -34,6 +34,7 @@
explicit HWCDisplayPrimary(CoreInterface *core_intf, hwc_procs_t const **hwc_procs);
virtual int Prepare(hwc_display_contents_1_t *content_list);
virtual int Commit(hwc_display_contents_1_t *content_list);
+ virtual DisplayError SetDisplayMode(uint32_t mode);
};
} // namespace sde
diff --git a/displayengine/libs/hwc/hwc_session.cpp b/displayengine/libs/hwc/hwc_session.cpp
index b6d0c18..652d7e0 100644
--- a/displayengine/libs/hwc/hwc_session.cpp
+++ b/displayengine/libs/hwc/hwc_session.cpp
@@ -44,6 +44,9 @@
#define __CLASS__ "HWCSession"
+#define HWC_UEVENT_SWITCH_HDMI "change@/devices/virtual/switch/hdmi"
+#define HWC_UEVENT_GRAPHICS_FB0 "change@/devices/virtual/graphics/fb0"
+
static sde::HWCSession::HWCModuleMethods g_hwc_module_methods;
hwc_module_t HAL_MODULE_INFO_SYM = {
@@ -63,10 +66,11 @@
namespace sde {
Locker HWCSession::locker_;
+bool HWCSession::reset_panel_ = false;
HWCSession::HWCSession(const hw_module_t *module) : core_intf_(NULL), hwc_procs_(NULL),
display_primary_(NULL), display_external_(NULL), display_virtual_(NULL),
- hotplug_thread_exit_(false), hotplug_thread_name_("HWC_HotPlugThread") {
+ uevent_thread_exit_(false), uevent_thread_name_("HWC_UeventThread") {
hwc_composer_device_1_t::common.tag = HARDWARE_DEVICE_TAG;
hwc_composer_device_1_t::common.version = HWC_DEVICE_API_VERSION_1_4;
hwc_composer_device_1_t::common.module = const_cast<hw_module_t*>(module);
@@ -141,8 +145,8 @@
return status;
}
- if (pthread_create(&hotplug_thread_, NULL, &HWCHotPlugThread, this) < 0) {
- DLOGE("Failed to start = %s, error = %s HDMI display Not supported", hotplug_thread_name_);
+ if (pthread_create(&uevent_thread_, NULL, &HWCUeventThread, this) < 0) {
+ DLOGE("Failed to start = %s, error = %s", uevent_thread_name_);
display_primary_->Deinit();
delete display_primary_;
CoreInterface::DestroyCore();
@@ -156,8 +160,8 @@
display_primary_->SetPowerMode(HWC_POWER_MODE_OFF);
display_primary_->Deinit();
delete display_primary_;
- hotplug_thread_exit_ = true;
- pthread_join(hotplug_thread_, NULL);
+ uevent_thread_exit_ = true;
+ pthread_join(uevent_thread_, NULL);
DisplayError error = CoreInterface::DestroyCore();
if (error != kErrorNone) {
@@ -218,6 +222,11 @@
HWCSession *hwc_session = static_cast<HWCSession *>(device);
+ if (reset_panel_) {
+ DLOGW("panel is in bad state, resetting the panel");
+ hwc_session->ResetPanel();
+ }
+
for (ssize_t i = (num_displays-1); i >= 0; i--) {
hwc_display_contents_1_t *content_list = displays[i];
@@ -588,6 +597,10 @@
status = SetMaxMixerStages(input_parcel);
break;
+ case qService::IQService::SET_DISPLAY_MODE:
+ status = SetDisplayMode(input_parcel);
+ break;
+
default:
DLOGW("QService command = %d is not supported", command);
return -EINVAL;
@@ -596,6 +609,18 @@
return status;
}
+android::status_t HWCSession::SetDisplayMode(const android::Parcel *input_parcel) {
+ DisplayError error = kErrorNone;
+ uint32_t mode = UINT32(input_parcel->readInt32());
+
+ error = display_primary_->SetDisplayMode(mode);
+ if (error != kErrorNone) {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
android::status_t HWCSession::SetMaxMixerStages(const android::Parcel *input_parcel) {
DisplayError error = kErrorNone;
uint32_t bit_mask_display_type = UINT32(input_parcel->readInt32());
@@ -690,18 +715,18 @@
}
}
-void* HWCSession::HWCHotPlugThread(void *context) {
+void* HWCSession::HWCUeventThread(void *context) {
if (context) {
- return reinterpret_cast<HWCSession *>(context)->HWCHotPlugThreadHandler();
+ return reinterpret_cast<HWCSession *>(context)->HWCUeventThreadHandler();
}
return NULL;
}
-void* HWCSession::HWCHotPlugThreadHandler() {
+void* HWCSession::HWCUeventThreadHandler() {
static char uevent_data[PAGE_SIZE];
int length = 0;
- prctl(PR_SET_NAME, hotplug_thread_name_, 0, 0, 0);
+ prctl(PR_SET_NAME, uevent_thread_name_, 0, 0, 0);
setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
if (!uevent_init()) {
DLOGE("Failed to init uevent");
@@ -709,19 +734,28 @@
return NULL;
}
- while (!hotplug_thread_exit_) {
+ while (!uevent_thread_exit_) {
// keep last 2 zeroes to ensure double 0 termination
length = uevent_next_event(uevent_data, INT32(sizeof(uevent_data)) - 2);
- if (!strcasestr("change@/devices/virtual/switch/hdmi", uevent_data)) {
- continue;
- }
- DLOGI("Uevent HDMI = %s", uevent_data);
- int connected = GetHDMIConnectedState(uevent_data, length);
- if (connected >= 0) {
- DLOGI("HDMI = %s", connected ? "connected" : "disconnected");
- if (HotPlugHandler(connected) == -1) {
- DLOGE("Failed handling Hotplug = %s", connected ? "connected" : "disconnected");
+ if (strcasestr(HWC_UEVENT_SWITCH_HDMI, uevent_data)) {
+ DLOGI("Uevent HDMI = %s", uevent_data);
+ int connected = GetEventValue(uevent_data, length, "SWITCH_STATE=");
+ if (connected >= 0) {
+ DLOGI("HDMI = %s", connected ? "connected" : "disconnected");
+ if (HotPlugHandler(connected) == -1) {
+ DLOGE("Failed handling Hotplug = %s", connected ? "connected" : "disconnected");
+ }
+ }
+ } else if (strcasestr(HWC_UEVENT_GRAPHICS_FB0, uevent_data)) {
+ DLOGI("Uevent FB0 = %s", uevent_data);
+ int panel_reset = GetEventValue(uevent_data, length, "PANEL_ALIVE=");
+ if (panel_reset == 0) {
+ if (hwc_procs_) {
+ reset_panel_ = true;
+ hwc_procs_->invalidate(hwc_procs_);
+ } else
+ DLOGW("Ignore resetpanel - hwc_proc not registered");
}
}
}
@@ -730,18 +764,43 @@
return NULL;
}
-int HWCSession::GetHDMIConnectedState(const char *uevent_data, int length) {
- const char* iterator_str = uevent_data;
+int HWCSession::GetEventValue(const char *uevent_data, int length, const char *event_info) {
+ const char *iterator_str = uevent_data;
while (((iterator_str - uevent_data) <= length) && (*iterator_str)) {
- char* pstr = strstr(iterator_str, "SWITCH_STATE=");
+ char *pstr = strstr(iterator_str, event_info);
if (pstr != NULL) {
- return (atoi(iterator_str + strlen("SWITCH_STATE=")));
+ return (atoi(iterator_str + strlen(event_info)));
}
iterator_str += strlen(iterator_str) + 1;
}
+
return -1;
}
+void HWCSession::ResetPanel() {
+ int status = -EINVAL;
+
+ DLOGI("Powering off primary");
+ status = display_primary_->SetPowerMode(HWC_POWER_MODE_OFF);
+ if (status) {
+ DLOGE("power-off on primary failed with error = %d",status);
+ }
+
+ DLOGI("Restoring power mode on primary");
+ uint32_t mode = display_primary_->GetLastPowerMode();
+ status = display_primary_->SetPowerMode(mode);
+ if (status) {
+ DLOGE("Setting power mode = %d on primary failed with error = %d", mode,status);
+ }
+
+ status = display_primary_->EventControl(HWC_EVENT_VSYNC, 1);
+ if (status) {
+ DLOGE("enabling vsync failed for primary with error = %d",status);
+ }
+
+ reset_panel_ = false;
+}
+
int HWCSession::HotPlugHandler(bool connected) {
if (!hwc_procs_) {
DLOGW("Ignore hotplug - hwc_proc not registered");
diff --git a/displayengine/libs/hwc/hwc_session.h b/displayengine/libs/hwc/hwc_session.h
index 1608ce5..dffa864 100644
--- a/displayengine/libs/hwc/hwc_session.h
+++ b/displayengine/libs/hwc/hwc_session.h
@@ -68,11 +68,12 @@
static int GetActiveConfig(hwc_composer_device_1 *device, int disp);
static int SetActiveConfig(hwc_composer_device_1 *device, int disp, int index);
- // Hotplug thread for HDMI connect/disconnect
- static void* HWCHotPlugThread(void *context);
- void* HWCHotPlugThreadHandler();
- int GetHDMIConnectedState(const char *uevent_data, int length);
+ // Uevent thread
+ static void* HWCUeventThread(void *context);
+ void* HWCUeventThreadHandler();
+ int GetEventValue(const char *uevent_data, int length, const char *event_info);
int HotPlugHandler(bool connected);
+ void ResetPanel();
bool ValidateContentList(hwc_display_contents_1_t *content_list);
int CreateVirtualDisplay(HWCSession *hwc_session, hwc_display_contents_1_t *content_list);
int DestroyVirtualDisplay(HWCSession *hwc_session);
@@ -86,6 +87,7 @@
void DynamicDebug(const android::Parcel *input_parcel);
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);
static Locker locker_;
CoreInterface *core_intf_;
@@ -93,9 +95,10 @@
HWCDisplayPrimary *display_primary_;
HWCDisplayExternal *display_external_;
HWCDisplayVirtual *display_virtual_;
- pthread_t hotplug_thread_;
- bool hotplug_thread_exit_;
- const char *hotplug_thread_name_;
+ pthread_t uevent_thread_;
+ bool uevent_thread_exit_;
+ static bool reset_panel_;
+ const char *uevent_thread_name_;
HWCBufferAllocator *buffer_allocator_;
HWCBufferSyncHandler *buffer_sync_handler_;
};
diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk
index c344045..5be5d00 100644
--- a/libhwcomposer/Android.mk
+++ b/libhwcomposer/Android.mk
@@ -8,6 +8,13 @@
LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes) \
$(TOP)/external/skia/include/core \
$(TOP)/external/skia/include/images
+
+ifeq ($(strip $(TARGET_USES_QCOM_DISPLAY_PP)),true)
+LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/qdcm/inc \
+ $(TARGET_OUT_HEADERS)/common/inc \
+ $(TARGET_OUT_HEADERS)/pp/inc
+endif
+
LOCAL_SHARED_LIBRARIES := $(common_libs) libEGL liboverlay \
libhdmi libqdutils libhardware_legacy \
libdl libmemalloc libqservice libsync \
@@ -38,4 +45,18 @@
hwc_dump_layers.cpp \
hwc_ad.cpp \
hwc_virtual.cpp
+
+TARGET_MIGRATE_QDCM_LIST := msm8909
+TARGET_MIGRATE_QDCM := $(call is-board-platform-in-list,$(TARGET_MIGRATE_QDCM_LIST))
+
+ifeq ($(TARGET_MIGRATE_QDCM), true)
+ifeq ($(strip $(TARGET_USES_QCOM_DISPLAY_PP)),true)
+LOCAL_SRC_FILES += hwc_qdcm.cpp
+else
+LOCAL_SRC_FILES += hwc_qdcm_legacy.cpp
+endif
+else
+LOCAL_SRC_FILES += hwc_qdcm_legacy.cpp
+endif
+
include $(BUILD_SHARED_LIBRARY)
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index 85e5d1b..7423c29 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -29,6 +29,7 @@
#include <overlay.h>
#include <overlayRotator.h>
#include <overlayWriteback.h>
+#include <overlayCursor.h>
#include <mdp_version.h>
#include "hwc_utils.h"
#include "hwc_fbupdate.h"
@@ -39,9 +40,11 @@
#include "hwc_ad.h"
#include "profiler.h"
#include "hwc_virtual.h"
+#include "hwc_qdcm.h"
using namespace qhwc;
using namespace overlay;
+using namespace qQdcm;
#define VSYNC_DEBUG 0
#define POWER_MODE_DEBUG 1
@@ -278,6 +281,7 @@
hwc_context_t* ctx = (hwc_context_t*)(dev);
const int dpy = HWC_DISPLAY_PRIMARY;
bool fbComp = false;
+
if (!ctx->mBootAnimCompleted)
processBootAnimCompleted(ctx);
if (LIKELY(list && list->numHwLayers > 1) && ctx->dpyAttr[dpy].connected &&
@@ -443,6 +447,30 @@
return ret;
}
+static int hwc_setCursorPositionAsync(struct hwc_composer_device_1* dev,
+ int dpy, int x, int y) {
+ int ret = -1;
+ hwc_context_t* ctx = (hwc_context_t*)(dev);
+ switch(dpy) {
+ case HWC_DISPLAY_PRIMARY:
+ {
+ ATRACE_CALL();
+ HWCursor* hwCursor = HWCursor::getInstance();
+ ctx->mDrawLock.lock();
+ if (hwCursor->isCursorSet() &&
+ hwCursor->setPositionAsync(ctx->dpyAttr[dpy].fd, x, y)) {
+ ret = 0;
+ }
+ ctx->mDrawLock.unlock();
+ break;
+ }
+ default:
+ ret = 0;
+ break;
+ }
+ return ret;
+}
+
static int hwc_setPowerMode(struct hwc_composer_device_1* dev, int dpy,
int mode)
{
@@ -462,6 +490,7 @@
ctx->mOverlay->configBegin();
ctx->mOverlay->configDone();
ctx->mRotMgr->clear();
+ HWCursor::getInstance()->free(ctx->dpyAttr[dpy].fd);
// If VDS is connected, do not clear WB object as it
// will end up detaching IOMMU. This is required
// to send black frame to WFD sink on power suspend.
@@ -922,17 +951,20 @@
if(ctx->mMDPComp[dpy])
ctx->mMDPComp[dpy]->dump(aBuf, ctx);
}
- char ovDump[2048] = {'\0'};
- ctx->mOverlay->getDump(ovDump, 2048);
+ char ovDump[3072] = {'\0'};
+ ctx->mOverlay->getDump(ovDump, 3072);
dumpsys_log(aBuf, ovDump);
ovDump[0] = '\0';
ctx->mRotMgr->getDump(ovDump, 1024);
dumpsys_log(aBuf, ovDump);
ovDump[0] = '\0';
- if(Writeback::getDump(ovDump, 1024)) {
+ if(Writeback::getDump(ovDump, 512)) {
dumpsys_log(aBuf, ovDump);
ovDump[0] = '\0';
}
+ HWCursor::getInstance()->getDump(ovDump, 512);
+ dumpsys_log(aBuf, ovDump);
+ ovDump[0] = '\0';
dumpsys_log(aBuf, "Copybit::isAbcInUse=%d\n\n",isAbcInUse(ctx) ? 1 : 0);
strlcpy(buff, aBuf.string(), buff_len);
}
@@ -1029,6 +1061,7 @@
dev->device.getDisplayAttributes = hwc_getDisplayAttributes;
dev->device.getActiveConfig = hwc_getActiveConfig;
dev->device.setActiveConfig = hwc_setActiveConfig;
+ dev->device.setCursorPositionAsync = hwc_setCursorPositionAsync;
*device = &dev->device.common;
status = 0;
}
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 5572cc4..087fe1e 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -18,7 +18,6 @@
#include <math.h>
#include "hwc_mdpcomp.h"
-#include <sys/ioctl.h>
#include <dlfcn.h>
#include "hdmi.h"
#include "qdMetaData.h"
@@ -26,6 +25,7 @@
#include "hwc_fbupdate.h"
#include "hwc_ad.h"
#include <overlayRotator.h>
+#include <overlayCursor.h>
#include "hwc_copybit.h"
#include "qd_utils.h"
@@ -56,6 +56,8 @@
int (*MDPComp::sPerfLockRelease)(int value) = NULL;
int MDPComp::sPerfHintWindow = -1;
+enum AllocOrder { FORMAT_YUV, FORMAT_RGB, FORMAT_MAX };
+
MDPComp* MDPComp::getObject(hwc_context_t *ctx, const int& dpy) {
if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
sSrcSplitEnabled = true;
@@ -77,8 +79,8 @@
(mDpy == 0) ? "\"PRIMARY\"" :
(mDpy == 1) ? "\"EXTERNAL\"" : "\"VIRTUAL\"");
dumpsys_log(buf,"CURR_FRAME: layerCount:%2d mdpCount:%2d "
- "fbCount:%2d \n", mCurrentFrame.layerCount,
- mCurrentFrame.mdpCount, mCurrentFrame.fbCount);
+ "fbCount:%2d dropCount:%2d\n", mCurrentFrame.layerCount,
+ mCurrentFrame.mdpCount, mCurrentFrame.fbCount, mCurrentFrame.dropCount);
dumpsys_log(buf,"needsFBRedraw:%3s pipesUsed:%2d MaxPipesPerMixer: %d \n",
(mCurrentFrame.needsRedraw? "YES" : "NO"),
mCurrentFrame.mdpCount, sMaxPipesPerMixer);
@@ -106,7 +108,8 @@
(mCurrentFrame.isFBComposed[index] ? "YES" : "NO"),
mCurrentFrame.layerToMDP[index],
(mCurrentFrame.isFBComposed[index] ?
- (mCurrentFrame.drop[index] ? "DROP" :
+ (mCurrentFrame.drop[index] ?
+ ((mCurrentFrame.hwCursorIndex == index) ? "CURSOR": "DROP"):
(mCurrentFrame.needsRedraw ? "GLES" : "CACHE")) : "MDP"),
(mCurrentFrame.isFBComposed[index] ? mCurrentFrame.fbZ :
mCurrentFrame.mdpToLayer[mCurrentFrame.layerToMDP[index]].pipeInfo->zOrder));
@@ -301,7 +304,11 @@
/* Drop the layer when its already present in FB OR when it lies
* outside frame's ROI */
if(!mCurrentFrame.needsRedraw || mCurrentFrame.drop[index]) {
- layer->compositionType = HWC_OVERLAY;
+ if(index == mCurrentFrame.hwCursorIndex) {
+ layer->compositionType = HWC_CURSOR_OVERLAY;
+ } else {
+ layer->compositionType = HWC_OVERLAY;
+ }
}
}
}
@@ -946,6 +953,9 @@
hwc_display_contents_1_t* list) {
const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+ // PTOR does not qualify when there are layers dropped, but if
+ // dropped layer is only a cursor, PTOR could qualify
+ const int numNonCursorLayers = numAppLayers - mCurrentFrame.dropCount;
const int stagesForMDP = min(sMaxPipesPerMixer,
ctx->mOverlay->availablePipes(mDpy, Overlay::MIXER_DEFAULT));
@@ -955,10 +965,11 @@
return false;
}
- // Frame level checks
+ // Frame level checks - consider PTOR in case of dropCount only if the cursor
+ // layer is dropped, otherwise bail out of PTOR
if ((numAppLayers > stagesForMDP) || isSkipPresent(ctx, mDpy) ||
- isYuvPresent(ctx, mDpy) || mCurrentFrame.dropCount ||
- isSecurePresent(ctx, mDpy)) {
+ isYuvPresent(ctx, mDpy) || isSecurePresent(ctx, mDpy) ||
+ (mCurrentFrame.dropCount - (int)isCursorPresent(ctx, mDpy))) {
ALOGD_IF(isDebug(), "%s: Frame not supported!", __FUNCTION__);
return false;
}
@@ -983,7 +994,7 @@
memset(overlapRect, 0, sizeof(overlapRect));
int layerPixelCount, minPixelCount = 0;
int numPTORLayersFound = 0;
- for (int i = numAppLayers-1; (i >= 0 &&
+ for (int i = numNonCursorLayers - 1; (i >= 0 &&
numPTORLayersFound < MAX_PTOR_LAYERS); i--) {
hwc_layer_1_t* layer = &list->hwLayers[i];
hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
@@ -1028,9 +1039,9 @@
return false;
// Store the displayFrame and the sourceCrops of the layers
- hwc_rect_t displayFrame[numAppLayers];
- hwc_rect_t sourceCrop[numAppLayers];
- for(int i = 0; i < numAppLayers; i++) {
+ hwc_rect_t displayFrame[numNonCursorLayers];
+ hwc_rect_t sourceCrop[numNonCursorLayers];
+ for(int i = 0; i < numNonCursorLayers; i++) {
hwc_layer_1_t* layer = &list->hwLayers[i];
displayFrame[i] = layer->displayFrame;
sourceCrop[i] = integerizeSourceCrop(layer->sourceCropf);
@@ -1119,11 +1130,11 @@
}
}
- mCurrentFrame.mdpCount = numAppLayers;
+ mCurrentFrame.mdpCount = numNonCursorLayers;
mCurrentFrame.fbCount = 0;
mCurrentFrame.fbZ = -1;
- for (int j = 0; j < numAppLayers; j++) {
+ for (int j = 0; j < numNonCursorLayers; j++) {
if(isValidRect(list->hwLayers[j].displayFrame)) {
mCurrentFrame.isFBComposed[j] = false;
} else {
@@ -1135,7 +1146,7 @@
bool result = postHeuristicsHandling(ctx, list);
// Restore layer attributes
- for(int i = 0; i < numAppLayers; i++) {
+ for(int i = 0; i < numNonCursorLayers; i++) {
hwc_layer_1_t* layer = &list->hwLayers[i];
layer->displayFrame = displayFrame[i];
layer->sourceCropf.left = (float)sourceCrop[i].left;
@@ -1342,7 +1353,9 @@
hwc_display_contents_1_t* list){
if(!qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() ||
isSkipPresent(ctx, mDpy) || (list->flags & HWC_GEOMETRY_CHANGED) ||
- !sIsPartialUpdateActive || mDpy ) {
+ isCursorPresent(ctx, mDpy) || !sIsPartialUpdateActive || mDpy) {
+ // On Async position update, the ROI becomes invalid, hence disable PU
+ // when cursor is present
return false;
}
if(ctx->listStats[mDpy].secureUI)
@@ -1910,7 +1923,20 @@
bool MDPComp::resourceCheck(hwc_context_t* ctx,
hwc_display_contents_1_t* list) {
const bool fbUsed = mCurrentFrame.fbCount;
- if(mCurrentFrame.mdpCount > sMaxPipesPerMixer - fbUsed) {
+ int cursorInUse = 0;
+ if(mDpy == HWC_DISPLAY_PRIMARY) {
+ // check if cursor is in use for primary
+ cursorInUse = HWCursor::getInstance()->isCursorSet();
+ }
+ int maxStages = qdutils::MDPVersion::getInstance().getBlendStages();
+ // HW Cursor needs one blending stage, account for that in the check below
+ // On high end targets(8994) has 8 blending stages, HAL is configured to use < 8.
+ // Make use of the remaining stages for HW Cursor so that the composition
+ // strategy would not fail due to this limitation.
+ if (maxStages > sMaxPipesPerMixer) {
+ cursorInUse = 0;
+ }
+ if(mCurrentFrame.mdpCount > (sMaxPipesPerMixer - fbUsed - cursorInUse)) {
ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
return false;
}
@@ -1985,6 +2011,52 @@
return true;
}
+static bool validForCursor(hwc_context_t* ctx, int dpy, hwc_layer_1_t* layer) {
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+ hwc_rect dst = layer->displayFrame;
+ hwc_rect src = integerizeSourceCrop(layer->sourceCropf);
+ int srcW = src.right - src.left;
+ int srcH = src.bottom - src.top;
+ int dstW = dst.right - dst.left;
+ int dstH = dst.bottom - dst.top;
+ qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
+ uint32_t maxCursorSize = mdpVersion.getMaxCursorSize();
+ uint32_t numHwCursors = mdpVersion.getCursorPipes();
+ bool primarySplit = isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY);
+ uint32_t cursorPipesNeeded = 1; // One cursor pipe needed(default)
+ bool ret = false;
+
+ if(dpy > HWC_DISPLAY_PRIMARY) {
+ // Cursor not supported on secondary displays, as it involves scaling
+ // in most of the cases
+ return false;
+ } else if (isSkipLayer(layer)) {
+ return false;
+ // Checks for HW limitation
+ } else if (numHwCursors == 0 || maxCursorSize <= 0) {
+ return false;
+ } else if (needsScaling(layer)) {
+ return false;
+ } else if (layer->transform != 0) {
+ return false;
+ } else if (hnd->format != HAL_PIXEL_FORMAT_RGBA_8888) {
+ return false;
+ } else if (srcW > (int)maxCursorSize || srcH > (int)maxCursorSize) {
+ return false;
+ }
+
+ if (isDisplaySplit(ctx, dpy) && !mdpVersion.isSrcSplit()) {
+ // In case of split display with no srcSplit, the driver allocates two
+ // pipes to support async position update across mixers, hence
+ // need to account for that here.
+ cursorPipesNeeded = 2;
+ }
+ if (cursorPipesNeeded <= numHwCursors) {
+ ret = true;
+ }
+ return ret;
+}
+
// Checks only if videos or single layer(RGB) is updating
// which is used for setting dynamic fps or perf hint for single
// layer video playback
@@ -2029,9 +2101,10 @@
int ret = 0;
char property[PROPERTY_VALUE_MAX];
- if(!ctx || !list) {
- ALOGE("%s: Invalid context or list",__FUNCTION__);
+ if(!list) {
+ ALOGE("%s: Invalid list", __FUNCTION__);
mCachedFrame.reset();
+ freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
return -1;
}
@@ -2052,6 +2125,7 @@
mCurrentFrame.reset(numLayers);
memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
mCurrentFrame.dropCount = 0;
+ mCurrentFrame.hwCursorIndex = -1;
//Do not cache the information for next draw cycle.
if(numLayers > MAX_NUM_APP_LAYERS or (!numLayers)) {
@@ -2061,6 +2135,7 @@
#ifdef DYNAMIC_FPS
setDynRefreshRate(ctx, list);
#endif
+ freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
return -1;
}
@@ -2077,6 +2152,7 @@
#ifdef DYNAMIC_FPS
setDynRefreshRate(ctx, list);
#endif
+ freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
ret = -1;
return ret;
} else {
@@ -2106,6 +2182,23 @@
dropNonAIVLayers(ctx, list);
}
+ // Configure the cursor if present
+ int topIndex = ctx->listStats[mDpy].numAppLayers - 1;
+ if(ctx->listStats[mDpy].cursorLayerPresent &&
+ validForCursor(ctx, mDpy, &(list->hwLayers[topIndex]))) {
+ if(configHwCursor(ctx->dpyAttr[mDpy].fd, mDpy,
+ &(list->hwLayers[topIndex]))) {
+ // As cursor is configured, mark that layer as dropped, so that
+ // it wont be considered for composition by other strategies.
+ mCurrentFrame.hwCursorIndex = topIndex;
+ mCurrentFrame.drop[topIndex] = true;
+ mCurrentFrame.dropCount++;
+ }
+ } else {
+ // Release the hw cursor
+ freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
+ }
+
// if tryFullFrame fails, try to push all video and secure RGB layers
// to MDP for composition.
mModeOn = tryFullFrame(ctx, list) || tryMDPOnlyLayers(ctx, list) ||
@@ -2117,6 +2210,12 @@
reset(ctx);
memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
mCurrentFrame.dropCount = 0;
+ // Check if cursor is in use for primary and mark accordingly
+ if(!mDpy && HWCursor::getInstance()->isCursorSet()) {
+ int topIndex = ctx->listStats[mDpy].numAppLayers - 1;
+ hwc_layer_1_t *layer = &(list->hwLayers[topIndex]);
+ layer->compositionType = HWC_CURSOR_OVERLAY;
+ }
ret = -1;
ALOGE_IF(sSimulationFlags && (mDpy == HWC_DISPLAY_PRIMARY),
"MDP Composition Strategies Failed");
@@ -2131,6 +2230,8 @@
}
ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
__FUNCTION__);
+ // Release the hw cursor
+ freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
ret = -1;
}
@@ -2248,39 +2349,48 @@
bool MDPCompNonSplit::allocLayerPipes(hwc_context_t *ctx,
hwc_display_contents_1_t* list) {
- for(int index = 0; index < mCurrentFrame.layerCount; index++) {
+ for(uint32_t formatType = FORMAT_YUV; formatType < FORMAT_MAX;
+ formatType++) {
+ for(int index = 0; index < mCurrentFrame.layerCount; index++) {
+ if(mCurrentFrame.isFBComposed[index]) continue;
- if(mCurrentFrame.isFBComposed[index]) continue;
-
- hwc_layer_1_t* layer = &list->hwLayers[index];
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
- if(allocSplitVGPipes(ctx, index)){
+ hwc_layer_1_t* layer = &list->hwLayers[index];
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+ if(formatType == FORMAT_YUV && !isYuvBuffer(hnd))
continue;
+ if(formatType == FORMAT_RGB && isYuvBuffer(hnd))
+ continue;
+
+ if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
+ if(allocSplitVGPipes(ctx, index)){
+ continue;
+ }
}
- }
- int mdpIndex = mCurrentFrame.layerToMDP[index];
- PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
- info.pipeInfo = new MdpPipeInfoNonSplit;
- info.rot = NULL;
- MdpPipeInfoNonSplit& pipe_info = *(MdpPipeInfoNonSplit*)info.pipeInfo;
+ int mdpIndex = mCurrentFrame.layerToMDP[index];
+ PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
+ info.pipeInfo = new MdpPipeInfoNonSplit;
+ info.rot = NULL;
+ MdpPipeInfoNonSplit& pipe_info =
+ *(MdpPipeInfoNonSplit*)info.pipeInfo;
- Overlay::PipeSpecs pipeSpecs;
- pipeSpecs.formatClass = isYuvBuffer(hnd) ?
- Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
- pipeSpecs.needsScaling = qhwc::needsScaling(layer) or
- (qdutils::MDPVersion::getInstance().is8x26() and
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres > 1024);
- pipeSpecs.dpy = mDpy;
- pipeSpecs.fb = false;
- pipeSpecs.numActiveDisplays = ctx->numActiveDisplays;
+ Overlay::PipeSpecs pipeSpecs;
+ pipeSpecs.formatClass = isYuvBuffer(hnd) ?
+ Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
+ pipeSpecs.needsScaling = qhwc::needsScaling(layer) or
+ (qdutils::MDPVersion::getInstance().is8x26() and
+ ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres > 1024);
+ pipeSpecs.dpy = mDpy;
+ pipeSpecs.fb = false;
+ pipeSpecs.numActiveDisplays = ctx->numActiveDisplays;
- pipe_info.index = ctx->mOverlay->getPipe(pipeSpecs);
+ pipe_info.index = ctx->mOverlay->getPipe(pipeSpecs);
- if(pipe_info.index == ovutils::OV_INVALID) {
- ALOGD_IF(isDebug(), "%s: Unable to get pipe", __FUNCTION__);
- return false;
+ if(pipe_info.index == ovutils::OV_INVALID) {
+ ALOGD_IF(isDebug(), "%s: Unable to get pipe for layer %d of "\
+ "format type %d", __FUNCTION__, index, formatType);
+ return false;
+ }
}
}
return true;
@@ -2482,36 +2592,43 @@
bool MDPCompSplit::allocLayerPipes(hwc_context_t *ctx,
hwc_display_contents_1_t* list) {
- for(int index = 0 ; index < mCurrentFrame.layerCount; index++) {
+ for(uint32_t formatType = FORMAT_YUV; formatType < FORMAT_MAX;
+ formatType++) {
+ for(int index = 0 ; index < mCurrentFrame.layerCount; index++) {
+ if(mCurrentFrame.isFBComposed[index]) continue;
- if(mCurrentFrame.isFBComposed[index]) continue;
-
- hwc_layer_1_t* layer = &list->hwLayers[index];
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- hwc_rect_t dst = layer->displayFrame;
- const int lSplit = getLeftSplit(ctx, mDpy);
- if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
- if((dst.left > lSplit)||(dst.right < lSplit)){
- if(allocSplitVGPipes(ctx, index)){
- continue;
- }
- }
- }
- //XXX: Check for forced 2D composition
- if(needs3DComposition(ctx, mDpy) && get3DFormat(hnd) != HAL_NO_3D)
- if(allocSplitVGPipes(ctx,index))
+ hwc_layer_1_t* layer = &list->hwLayers[index];
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+ if(formatType == FORMAT_YUV && !isYuvBuffer(hnd))
+ continue;
+ if(formatType == FORMAT_RGB && isYuvBuffer(hnd))
continue;
- int mdpIndex = mCurrentFrame.layerToMDP[index];
- PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
- info.pipeInfo = new MdpPipeInfoSplit;
- info.rot = NULL;
- MdpPipeInfoSplit& pipe_info = *(MdpPipeInfoSplit*)info.pipeInfo;
+ hwc_rect_t dst = layer->displayFrame;
+ const int lSplit = getLeftSplit(ctx, mDpy);
+ if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
+ if((dst.left > lSplit)||(dst.right < lSplit)){
+ if(allocSplitVGPipes(ctx, index)){
+ continue;
+ }
+ }
+ }
+ //XXX: Check for forced 2D composition
+ if(needs3DComposition(ctx, mDpy) && get3DFormat(hnd) != HAL_NO_3D)
+ if(allocSplitVGPipes(ctx,index))
+ continue;
- if(!acquireMDPPipes(ctx, layer, pipe_info)) {
- ALOGD_IF(isDebug(), "%s: Unable to get pipe for type",
- __FUNCTION__);
- return false;
+ int mdpIndex = mCurrentFrame.layerToMDP[index];
+ PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
+ info.pipeInfo = new MdpPipeInfoSplit;
+ info.rot = NULL;
+ MdpPipeInfoSplit& pipe_info = *(MdpPipeInfoSplit*)info.pipeInfo;
+
+ if(!acquireMDPPipes(ctx, layer, pipe_info)) {
+ ALOGD_IF(isDebug(), "%s: Unable to get pipe for layer %d of "\
+ "format type %d", __FUNCTION__, index, formatType);
+ return false;
+ }
}
}
return true;
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 676bf24..db68e82 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -119,6 +119,7 @@
bool needsRedraw;
int fbZ;
+ int hwCursorIndex;
/* c'tor */
FrameInfo();
diff --git a/libhwcomposer/hwc_qclient.cpp b/libhwcomposer/hwc_qclient.cpp
index 34de2e6..f18ad36 100644
--- a/libhwcomposer/hwc_qclient.cpp
+++ b/libhwcomposer/hwc_qclient.cpp
@@ -37,6 +37,7 @@
#include <display_config.h>
#include <hdmi.h>
#include <video/msm_hdmi_modes.h>
+#include <hwc_qdcm.h>
#define QCLIENT_DEBUG 0
@@ -45,6 +46,7 @@
using namespace qhwc;
using namespace overlay;
using namespace qdutils;
+using namespace qQdcm;
namespace qClient {
@@ -554,6 +556,8 @@
case IQService::GET_DISPLAY_ATTRIBUTES_FOR_CONFIG:
ret = getDisplayAttributesForConfig(mHwcContext, inParcel,
outParcel);
+ case IQService::QDCM_SVC_CMDS:
+ qdcmCmdsHandler(mHwcContext, inParcel, outParcel);
break;
default:
ret = NO_ERROR;
diff --git a/libhwcomposer/hwc_qdcm.cpp b/libhwcomposer/hwc_qdcm.cpp
new file mode 100644
index 0000000..9821e4e
--- /dev/null
+++ b/libhwcomposer/hwc_qdcm.cpp
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <hwc_qdcm.h>
+#include <hwc_utils.h>
+#include <utils/String16.h>
+#include <mdp_version.h>
+#include "mode_manager.h"
+#include "libmm-disp-apis.h"
+#include "IQService.h"
+
+using namespace android;
+using namespace qService;
+using namespace qhwc;
+using namespace qmode;
+
+namespace qQdcm {
+//----------------------------------------------------------------------------
+void qdcmInitContext(hwc_context_t *ctx)
+{
+ loadQdcmLibrary(ctx);
+}
+
+void qdcmCloseContext(hwc_context_t *ctx)
+{
+ if (ctx->mQdcmInfo.mQdcmMode) {
+ unloadQdcmLibrary(ctx);
+ }
+}
+
+void qdcmApplyDefaultAfterBootAnimationDone(hwc_context_t *ctx)
+{
+ if (ctx->mQdcmInfo.mQdcmMode)
+ ctx->mQdcmInfo.mQdcmMode->applyDefaultMode(0);
+}
+
+static void qdcmSetActiveMode(hwc_context_t *ctx, const Parcel *in, Parcel *out)
+{
+ int ret = 0;
+
+ if (ctx->mQdcmInfo.mQdcmMode && in && out) {
+
+ struct SET_MODE_PROP_IN params =
+ { (disp_id_type)in->readInt32(), in->readInt32()};
+
+ ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_SET_ACTIVE_MODE,
+ (void *)¶ms, (void *)NULL);
+
+ out->writeInt32(ret); //return operation status via binder.
+ }
+}
+
+static void qdcmSetDefaultMode(hwc_context_t *ctx, const Parcel *in, Parcel *out)
+{
+ int ret = 0;
+
+ if (ctx->mQdcmInfo.mQdcmMode && in && out) {
+
+ struct SET_MODE_PROP_IN params =
+ { (disp_id_type)in->readInt32(), in->readInt32()};
+
+ ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_SET_DEFAULT_MODE,
+ (void *)¶ms, (void *)NULL);
+
+ out->writeInt32(ret); //return operation status via binder.
+ }
+}
+
+static void qdcmGetDefaultMode(hwc_context_t *ctx,
+ const Parcel *in, Parcel *out)
+{
+ int ret = 0;
+
+ if (ctx->mQdcmInfo.mQdcmMode && in && out) {
+
+ int params = in->readInt32();
+ int modeid = 0;
+
+ ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_GET_DEFAULT_MODE,
+ (const void *)¶ms, (void *)&modeid);
+
+ out->writeInt32(modeid);
+ out->writeInt32(ret); //return operation status via binder.
+ }
+}
+
+static void qdcmGetColorBalanceRange(hwc_context_t *ctx __unused,
+ const Parcel *in __unused, Parcel *out __unused)
+{
+}
+
+static void qdcmGetColorBalance(hwc_context_t *ctx,
+ const Parcel *in, Parcel *out)
+{
+ int ret = 0;
+
+ if (ctx->mQdcmInfo.mQdcmMode && in && out) {
+
+ int params = in->readInt32();
+ int warmness = 0;
+
+ ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_GET_CB,
+ (const void *)¶ms, (void *)&warmness);
+
+ out->writeInt32(warmness);
+ out->writeInt32(ret); //return operation status via binder.
+ }
+}
+
+static void qdcmSetColorBalance(hwc_context_t *ctx,
+ const Parcel *in, Parcel *out)
+{
+ int ret = 0;
+
+ if (ctx->mQdcmInfo.mQdcmMode && in && out) {
+
+ struct SET_CB_IN params =
+ { (disp_id_type)in->readInt32(), in->readInt32() };
+
+ ALOGD_IF(QDCM_DEBUG, "%s dispID = %d, warmness = %d\n",
+ __FUNCTION__, params.id, params.warmness);
+
+ ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_SET_CB,
+ (const void *)¶ms, NULL);
+
+ out->writeInt32(ret); //return operation status via binder.
+ }
+}
+
+static void qdcmSaveModeV2(hwc_context_t *ctx, const Parcel *in, Parcel *out)
+{
+ int ret = 0;
+
+ if (ctx->mQdcmInfo.mQdcmMode && in && out) {
+
+ struct SAVE_DISPLAY_MODE_V2_IN params =
+ { (disp_id_type)in->readInt32(),
+ in->readCString(),
+ (uint32_t)in->readInt32(),
+ in->readInt32()
+ };
+ int value = 0;
+
+ ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_SAVE_MODE_V2,
+ (const void *)¶ms, (void *)&value);
+
+ out->writeInt32(value);
+ out->writeInt32(ret); //return operation status via binder.
+ }
+}
+
+static void qdcmSetPaConfig(hwc_context_t *ctx, const Parcel *in, Parcel *out)
+{
+ int ret = 0;
+
+ if (ctx->mQdcmInfo.mQdcmMode && in && out) {
+
+ struct SET_PA_CONFIG_IN params;
+
+ params.id = (disp_id_type)in->readInt32();
+ params.pa.ops = in->readInt32();
+ params.pa.data.hue = in->readInt32();
+ params.pa.data.saturation = in->readInt32();
+ params.pa.data.value = in->readInt32();
+ params.pa.data.contrast = in->readInt32();
+ params.pa.data.sat_thresh = in->readInt32();
+
+ ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_SET_PA_CONFIG,
+ (const void *)¶ms, NULL);
+
+ out->writeInt32(ret); //return operation status via binder.
+ }
+}
+
+static void qdcmGetPaConfig(hwc_context_t *ctx, const Parcel *in, Parcel *out)
+{
+ int ret = 0;
+
+ if (ctx->mQdcmInfo.mQdcmMode && in && out) {
+
+ int params = in->readInt32();
+ struct disp_pa_config value;
+
+ ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_GET_PA_CONFIG,
+ (const void *)¶ms, (void *)&value);
+
+ out->writeInt32(value.ops);
+ out->writeInt32(value.data.hue);
+ out->writeInt32(value.data.saturation);
+ out->writeInt32(value.data.value);
+ out->writeInt32(value.data.contrast);
+ out->writeInt32(value.data.sat_thresh);
+
+ out->writeInt32(ret); //return operation status via binder.
+ }
+}
+
+static void qdcmGetPaRange(hwc_context_t *ctx, const Parcel *in, Parcel *out)
+{
+ int ret = 0;
+
+ if (ctx->mQdcmInfo.mQdcmMode && in && out) {
+
+ int params = in->readInt32();
+ struct disp_pa_range value;
+
+ ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_GET_PA_RANGE,
+ (const void *)¶ms, (void *)&value);
+
+ out->writeInt32(value.max.hue);
+ out->writeInt32(value.max.saturation);
+ out->writeInt32(value.max.value);
+ out->writeInt32(value.max.contrast);
+ out->writeInt32(value.max.sat_thresh);
+ out->writeInt32(value.min.hue);
+ out->writeInt32(value.min.saturation);
+ out->writeInt32(value.min.value);
+ out->writeInt32(value.min.contrast);
+ out->writeInt32(value.min.sat_thresh);
+
+ out->writeInt32(ret); //return operation status via binder.
+ }
+}
+
+void qdcmCmdsHandler(hwc_context_t *ctx, const Parcel *in, Parcel *out)
+{
+ int subcmd = in->readInt32();
+
+ ALOGD_IF(QDCM_DEBUG, "%s enter subcmd = %d\n", __FUNCTION__, subcmd);
+ switch (subcmd) {
+ case CMD_SET_ACTIVE_MODE:
+ qdcmSetActiveMode(ctx, in, out);
+ break;
+ case CMD_SET_DEFAULT_MODE:
+ qdcmSetDefaultMode(ctx, in, out);
+ break;
+ case CMD_GET_DEFAULT_MODE:
+ qdcmGetDefaultMode(ctx, in, out);
+ break;
+ case CMD_GET_CB_RANGE:
+ qdcmGetColorBalanceRange(ctx, in, out);
+ break;
+ case CMD_GET_CB:
+ qdcmGetColorBalance(ctx, in, out);
+ break;
+ case CMD_SET_CB:
+ qdcmSetColorBalance(ctx, in, out);
+ break;
+ case CMD_SAVE_MODE_V2:
+ qdcmSaveModeV2(ctx, in, out);
+ break;
+ case CMD_SET_PA_CONFIG:
+ qdcmSetPaConfig(ctx, in, out);
+ break;
+ case CMD_GET_PA_CONFIG:
+ qdcmGetPaConfig(ctx, in, out);
+ break;
+ case CMD_GET_PA_RANGE:
+ qdcmGetPaRange(ctx, in, out);
+ break;
+ }
+}
+
+
+} //namespace qQdcm
+
diff --git a/libhwcomposer/hwc_qdcm.h b/libhwcomposer/hwc_qdcm.h
new file mode 100644
index 0000000..6453159
--- /dev/null
+++ b/libhwcomposer/hwc_qdcm.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ANDROID_QDCM_H
+#define ANDROID_QDCM_H
+
+#include <utils/Errors.h>
+#include <sys/types.h>
+#include <cutils/log.h>
+#include <hwc_utils.h>
+#include <dlfcn.h>
+#include <binder/Parcel.h>
+#include <cutils/properties.h>
+
+#define QDCM_DEBUG 0
+
+namespace qmode {
+class ModeManager;
+}
+
+using namespace android;
+
+namespace qQdcm {
+// ----------------------------------------------------------------------------
+
+//function prototypes used for QDCM library and service
+static inline void loadQdcmLibrary(hwc_context_t *ctx)
+{
+ ctx->mQdcmInfo.mQdcmLib = dlopen("libmm-qdcm.so", RTLD_NOW);
+ qmode::ModeManager* (*factory)() = NULL;
+
+ if (ctx->mQdcmInfo.mQdcmLib)
+ *(void **)&factory = dlsym(ctx->mQdcmInfo.mQdcmLib, "getObject");
+
+ if (factory) {
+ ctx->mQdcmInfo.mQdcmMode = factory();
+ } else {
+ ctx->mQdcmInfo.mQdcmMode = NULL;
+ ALOGE("QDCM LIbrary load failing!");
+ }
+
+ ALOGD_IF(QDCM_DEBUG, "QDCM LIbrary loaded successfully!");
+}
+
+static inline void unloadQdcmLibrary(hwc_context_t *ctx)
+{
+ void (*destroy)(qmode::ModeManager*) = NULL;
+
+ if (ctx->mQdcmInfo.mQdcmLib) {
+ *(void **)&destroy = dlsym(ctx->mQdcmInfo.mQdcmLib, "deleteObject");
+
+ if (destroy) {
+ destroy(ctx->mQdcmInfo.mQdcmMode);
+ ctx->mQdcmInfo.mQdcmMode = NULL;
+ }
+
+ dlclose(ctx->mQdcmInfo.mQdcmLib);
+ ctx->mQdcmInfo.mQdcmLib = NULL;
+ }
+}
+
+void qdcmInitContext(hwc_context_t *);
+void qdcmCloseContext(hwc_context_t *);
+void qdcmApplyDefaultAfterBootAnimationDone(hwc_context_t *);
+void qdcmCmdsHandler(hwc_context_t*, const Parcel*, Parcel*);
+
+}; // namespace qQdcm
+#endif // ANDROID_QDCM_H
diff --git a/libhwcomposer/hwc_qdcm_legacy.cpp b/libhwcomposer/hwc_qdcm_legacy.cpp
new file mode 100644
index 0000000..9c2c7b0
--- /dev/null
+++ b/libhwcomposer/hwc_qdcm_legacy.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <hwc_qdcm.h>
+#include <hwc_utils.h>
+#include <IQService.h>
+#include <mdp_version.h>
+#include <dlfcn.h>
+
+using namespace android;
+using namespace qService;
+using namespace qhwc;
+
+namespace qQdcm {
+//----------------------------------------------------------------------------
+void qdcmInitContext(hwc_context_t *ctx)
+{
+}
+
+void qdcmCloseContext(hwc_context_t *ctx)
+{
+}
+
+void qdcmApplyDefaultAfterBootAnimationDone(hwc_context_t *ctx)
+{
+ int ret = 0;
+ int (*applyMode)(int) = NULL;
+ void *modeHandle = NULL;
+
+ modeHandle = dlopen("libmm-qdcm.so", RTLD_NOW);
+ if (modeHandle) {
+ *(void **)&applyMode = dlsym(modeHandle, "applyDefaults");
+ if (applyMode) {
+ ret = applyMode(HWC_DISPLAY_PRIMARY);
+ if (ret)
+ ALOGE("%s: Not able to apply default mode", __FUNCTION__);
+ } else {
+ ALOGE("%s: No symbol applyDefaults found", __FUNCTION__);
+ }
+ dlclose(modeHandle);
+ } else {
+ ALOGE("%s: Not able to load libmm-qdcm.so", __FUNCTION__);
+ }
+}
+
+//do nothing in case qdcm legacy implementation.
+void qdcmCmdsHandler(hwc_context_t *ctx, const Parcel *in, Parcel *out)
+{
+}
+
+
+} //namespace qQdcm
+
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index a3cb196..8efe025 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -30,6 +30,7 @@
#include <overlay.h>
#include <overlayRotator.h>
#include <overlayWriteback.h>
+#include <overlayCursor.h>
#include "hwc_utils.h"
#include "hwc_mdpcomp.h"
#include "hwc_fbupdate.h"
@@ -43,6 +44,7 @@
#include "comptype.h"
#include "hwc_virtual.h"
#include "qd_utils.h"
+#include "hwc_qdcm.h"
#include <sys/sysinfo.h>
#include <dlfcn.h>
#include <video/msm_hdmi_modes.h>
@@ -52,6 +54,7 @@
using namespace android;
using namespace overlay;
using namespace overlay::utils;
+using namespace qQdcm;
namespace ovutils = overlay::utils;
#ifdef QCOM_BSP
@@ -477,6 +480,10 @@
memset(&(ctx->mPtorInfo), 0, sizeof(ctx->mPtorInfo));
ctx->mHPDEnabled = false;
+
+ //init qdcm service related context.
+ qdcmInitContext(ctx);
+
ALOGI("Initializing Qualcomm Hardware Composer");
ALOGI("MDP version: %d", ctx->mMDP.version);
@@ -490,6 +497,9 @@
void closeContext(hwc_context_t *ctx)
{
+ //close qdcm service related context.
+ qdcmCloseContext(ctx);
+
if(ctx->mOverlay) {
delete ctx->mOverlay;
ctx->mOverlay = NULL;
@@ -1085,6 +1095,7 @@
ctx->listStats[dpy].renderBufIndexforABC = -1;
ctx->listStats[dpy].secureRGBCount = 0;
ctx->listStats[dpy].refreshRateRequest = ctx->dpyAttr[dpy].refreshRate;
+ ctx->listStats[dpy].cursorLayerPresent = false;
uint32_t refreshRate = 0;
qdutils::MDPVersion& mdpHw = qdutils::MDPVersion::getInstance();
int s3dFormat = HAL_NO_3D;
@@ -1116,6 +1127,12 @@
if(ctx->listStats[dpy].numAppLayers > MAX_NUM_APP_LAYERS)
continue;
+ // Valid cursor must be the top most layer
+ if((int)i == (ctx->listStats[dpy].numAppLayers - 1) &&
+ isCursorLayer(&list->hwLayers[i])) {
+ ctx->listStats[dpy].cursorLayerPresent = true;
+ }
+
//reset yuv indices
ctx->listStats[dpy].yuvIndices[i] = -1;
ctx->listStats[dpy].yuv4k2kIndices[i] = -1;
@@ -1942,6 +1959,46 @@
crop.bottom = transformedCrop.y + transformedCrop.h;
}
+bool configHwCursor(const int fd, int dpy, hwc_layer_1_t* layer) {
+ if(dpy > HWC_DISPLAY_PRIMARY) {
+ // HWCursor not supported on secondary displays
+ return false;
+ }
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+ hwc_rect dst = layer->displayFrame;
+ hwc_rect src = integerizeSourceCrop(layer->sourceCropf);
+ int srcW = src.right - src.left;
+ int srcH = src.bottom - src.top;
+ int dstW = dst.right - dst.left;
+ int dstH = dst.bottom - dst.top;
+
+ Whf whf(getWidth(hnd), getHeight(hnd), hnd->format);
+ Dim crop(src.left, src.top, srcW, srcH);
+ Dim dest(dst.left, dst.top, dstW, dstH);
+
+ ovutils::PipeArgs pargs(ovutils::OV_MDP_FLAGS_NONE,
+ whf,
+ Z_SYSTEM_ALLOC,
+ ovutils::ROT_FLAGS_NONE,
+ layer->planeAlpha,
+ (ovutils::eBlending)
+ getBlending(layer->blending));
+
+ ALOGD_IF(HWC_UTILS_DEBUG, "%s: CursorInfo: w = %d h = %d "
+ "crop [%d, %d, %d, %d] dst [%d, %d, %d, %d]", __FUNCTION__,
+ getWidth(hnd), getHeight(hnd), src.left, src.top, srcW, srcH,
+ dst.left, dst.top, dstW, dstH);
+
+ return HWCursor::getInstance()->config(fd, (void*)hnd->base, pargs,
+ crop, dest);
+}
+
+void freeHwCursor(const int fd, int dpy) {
+ if (dpy == HWC_DISPLAY_PRIMARY) {
+ HWCursor::getInstance()->free(fd);
+ }
+}
+
int getRotDownscale(hwc_context_t *ctx, const hwc_layer_1_t *layer) {
if(not qdutils::MDPVersion::getInstance().isRotDownscaleEnabled()) {
return 0;
@@ -2701,29 +2758,16 @@
void processBootAnimCompleted(hwc_context_t *ctx) {
char value[PROPERTY_VALUE_MAX];
int ret = -1;
- int (*applyMode)(int) = NULL;
- void *modeHandle = NULL;
// Applying default mode after bootanimation is finished
property_get("init.svc.bootanim", value, "running");
if (!strncmp(value,"stopped",strlen("stopped"))) {
- modeHandle = dlopen("libmm-qdcm.so", RTLD_NOW);
- if (modeHandle) {
- *(void **)&applyMode = dlsym(modeHandle, "applyDefaults");
- if (applyMode) {
- ret = applyMode(HWC_DISPLAY_PRIMARY);
- if (ret)
- ALOGD("%s: Not able to apply default mode", __FUNCTION__);
- } else {
- ALOGE("%s: No symbol applyDefaults found", __FUNCTION__);
- }
- dlclose(modeHandle);
- } else {
- ALOGE("%s: Not able to load libmm-qdcm.so", __FUNCTION__);
- }
-
ctx->mBootAnimCompleted = true;
+
+ //one-shot action check if bootanimation completed then apply
+ //default display mode.
+ qdcmApplyDefaultAfterBootAnimationDone(ctx);
}
}
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index af43514..f0f8e77 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -55,6 +55,10 @@
namespace ovutils = overlay::utils;
+namespace qmode {
+class ModeManager;
+}
+
namespace overlay {
class Overlay;
class Rotator;
@@ -165,6 +169,8 @@
uint32_t refreshRateRequest;
// Flag related to windowboxing feature
bool mAIVVideoMode;
+ // curser layer info
+ bool cursorLayerPresent;
};
//PTOR Comp info
@@ -414,6 +420,9 @@
void updateSource(ovutils::eTransform& orient, ovutils::Whf& whf,
hwc_rect_t& crop, overlay::Rotator *rot);
+bool configHwCursor(const int fd, int dpy, hwc_layer_1_t* layer);
+void freeHwCursor(const int fd, int dpy);
+
bool isZoomModeEnabled(hwc_rect_t crop);
void updateCropAIVVideoMode(hwc_context_t *ctx, hwc_rect_t& crop, int dpy);
void updateDestAIVVideoMode(hwc_context_t *ctx, hwc_rect_t& dst, int dpy);
@@ -497,6 +506,11 @@
return (UNLIKELY(l && (l->flags & HWC_AIV_CC)));
}
+static inline bool isCursorLayer(const hwc_layer_1_t* l) {
+ return (UNLIKELY(l && (l->flags & HWC_IS_CURSOR_LAYER)));
+}
+
+
// Returns true if the buffer is yuv
static inline bool isYuvBuffer(const private_handle_t* hnd) {
return (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO));
@@ -611,6 +625,13 @@
EGLDisplay mEGLDisplay;
};
+//struct holds the information about libmm-qdcm.so
+struct qdcm_info {
+ qmode::ModeManager *mQdcmMode;
+ void *mQdcmLib;
+ bool mBootAnimCompleted;
+};
+
// -----------------------------------------------------------------------------
// HWC context
// This structure contains overall state
@@ -698,6 +719,8 @@
bool mBootAnimCompleted;
// Display binder service
qService::QService* mQService;
+ //struct holds the information about display tuning service library.
+ struct qdcm_info mQdcmInfo;
};
namespace qhwc {
@@ -718,6 +741,10 @@
return ctx->listStats[dpy].isSecurePresent;
}
+static inline bool isCursorPresent (hwc_context_t *ctx, int dpy) {
+ return ctx->listStats[dpy].cursorLayerPresent;
+}
+
static inline bool isSecondaryConfiguring(hwc_context_t* ctx) {
return (ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isConfiguring ||
ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isConfiguring);
diff --git a/liboverlay/Android.mk b/liboverlay/Android.mk
index aa1ea24..9ea7432 100644
--- a/liboverlay/Android.mk
+++ b/liboverlay/Android.mk
@@ -17,6 +17,7 @@
overlayMdpRot.cpp \
overlayMdssRot.cpp \
overlayWriteback.cpp \
+ overlayCursor.cpp \
pipes/overlayGenPipe.cpp
include $(BUILD_SHARED_LIBRARY)
diff --git a/liboverlay/overlayCursor.cpp b/liboverlay/overlayCursor.cpp
new file mode 100644
index 0000000..c22dd39
--- /dev/null
+++ b/liboverlay/overlayCursor.cpp
@@ -0,0 +1,147 @@
+/*
+* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+//#include "overlay.h"
+#include "overlayCursor.h"
+#include "mdpWrapper.h"
+
+namespace overlay {
+
+HWCursor* HWCursor::sHwCursor = 0;
+
+//=========== class HWCursor =================================================
+HWCursor* HWCursor::getInstance() {
+ if (sHwCursor == NULL) {
+ sHwCursor = new HWCursor();
+ }
+ return sHwCursor;
+}
+
+bool HWCursor::config(const int fd, void* base, PipeArgs& pargs,
+ Dim& crop, Dim& dest) {
+ bool ret = true;
+ fb_cursor *cursor = &mfbCursor;
+ fb_image cursorImage;
+
+ cursor->set = FB_CUR_SETIMAGE | FB_CUR_SETPOS;
+ cursor->enable = (uint16_t)1;
+ cursor->rop = 0,
+ cursor->mask = NULL;
+ cursor->hot.x = (uint16_t)crop.x;
+ cursor->hot.y = (uint16_t)crop.y;
+
+ cursorImage.dx = dest.x;
+ cursorImage.dy = dest.y;
+ cursorImage.width = pargs.whf.w;
+ cursorImage.height = pargs.whf.h;
+ cursorImage.fg_color = pargs.planeAlpha; // Hint for PMA
+ cursorImage.bg_color = 0xffffff00; // RGBA
+ cursorImage.depth = 32;
+ cursorImage.data = (char*)base;
+
+ cursor->image = cursorImage;
+
+ if (!setCursor(fd)) {
+ ALOGE("%s: Failed to setup HW cursor", __FUNCTION__);
+ ret = false;
+ memset(cursor, 0, sizeof(fb_cursor));
+ }
+ return ret;
+}
+
+bool HWCursor::setPositionAsync(const int fd, int x, int y) {
+ bool ret = true;
+ if (isCursorSet()) {
+ fb_cursor *cursor = &mfbCursor;
+ cursor->set = FB_CUR_SETPOS;
+ cursor->image.dx = x;
+ cursor->image.dy = y;
+ if (!setCursor(fd)) {
+ ALOGE("%s: Failed to set position x = %d y = %d", __FUNCTION__, x, y);
+ ret = false;
+ }
+ }
+ return ret;
+}
+
+bool HWCursor::free(const int fd) {
+ fb_cursor *cursor = &mfbCursor;
+ fb_image cursorImage;
+ bool ret = true;
+
+ if(!cursor->enable) {
+ return ret;
+ }
+
+ cursor->enable = (uint16_t)0;
+
+ if (!setCursor(fd)) {
+ ALOGE("%s: Failed to free cursor hw", __FUNCTION__);
+ ret = false;
+ }
+ memset(cursor, 0, sizeof(fb_cursor));
+ return ret;
+}
+
+bool HWCursor::setCursor(const int fd) {
+ bool ret = true;
+ ATRACE_CALL();
+ fb_cursor *cursor = &mfbCursor;
+
+ if(fd <= 0) {
+ ALOGE("%s: Invalid fd", fd);
+ return false;
+ }
+
+ if (ioctl(fd, MSMFB_CURSOR, cursor) < 0) {
+ ALOGE("%s: Failed to call ioctl MSMFB_CURSOR err=%s\n", __FUNCTION__,
+ strerror(errno));
+ ret = false;
+ }
+ return ret;
+}
+
+void HWCursor::getDump(char* buf, size_t len) {
+ char cursordump[len];
+ fb_cursor* cursor = &mfbCursor;
+ if (cursor->enable) {
+ snprintf(cursordump, sizeof(cursordump),
+ "HWCursor on Primary: src w=%d h=%d\n"
+ "\tsrc_rect x=%d y=%d w=%d h=%d\n"
+ "\tdst_rect x=%d y=%d w=%d h=%d\n\n", cursor->image.width,
+ cursor->image.height, cursor->hot.x, cursor->hot.y,
+ cursor->image.width, cursor->image.height,
+ cursor->image.dx, cursor->image.dy, cursor->image.width,
+ cursor->image.height);
+ strlcat(buf, cursordump, len);
+ }
+
+}
+
+} //namespace overlay
diff --git a/liboverlay/overlayCursor.h b/liboverlay/overlayCursor.h
new file mode 100644
index 0000000..2754a8d
--- /dev/null
+++ b/liboverlay/overlayCursor.h
@@ -0,0 +1,60 @@
+/*
+* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef OVERLAY_CURSOR_H
+#define OVERLAY_CURSOR_H
+
+#include "overlay.h"
+#include "overlayUtils.h"
+
+namespace overlay {
+
+using namespace overlay;
+using namespace overlay::utils;
+
+// HW Cursor Helper
+class HWCursor {
+public:
+ static HWCursor* getInstance();
+ bool config(const int fd, void* base, PipeArgs& pargs, Dim& crop,
+ Dim& dest);
+ bool setPositionAsync(const int fd, int x, int y);
+ bool free(const int fd);
+ bool isCursorSet() { return mfbCursor.enable; }
+ void getDump(char* buf, size_t len);
+private:
+ HWCursor() { memset(&mfbCursor, 0, sizeof(mfbCursor)); }
+ bool setCursor(const int fd);
+ fb_cursor mfbCursor;
+
+ static HWCursor* sHwCursor;
+};
+}
+
+#endif // OVERLAY_CURSOR_H
diff --git a/libqdutils/display_config.cpp b/libqdutils/display_config.cpp
index 40b1ef7..350192d 100644
--- a/libqdutils/display_config.cpp
+++ b/libqdutils/display_config.cpp
@@ -262,6 +262,24 @@
return dpyattr;
}
+int setPanelMode(int mode) {
+ status_t err = (status_t) FAILED_TRANSACTION;
+ sp<IQService> binder = getBinder();
+ if(binder != NULL) {
+ Parcel inParcel, outParcel;
+ inParcel.writeInt32(mode);
+ err = binder->dispatch(IQService::SET_DISPLAY_MODE,
+ &inParcel, &outParcel);
+ if(!err) {
+ ALOGI("%s() Successfully set the display mode to %d", __FUNCTION__,
+ mode);
+ } else {
+ ALOGE("%s() failed with err %d", __FUNCTION__, err);
+ }
+ }
+ return err;
+}
+
//=============================================================================
// The functions/methods below run in the context of HWC and
// are called in response to binder calls from clients
diff --git a/libqdutils/display_config.h b/libqdutils/display_config.h
index 6a66e9f..5ff0862 100644
--- a/libqdutils/display_config.h
+++ b/libqdutils/display_config.h
@@ -64,6 +64,12 @@
SET_BINDER_DYN_REFRESH_RATE,
};
+enum {
+ DEFAULT_MODE = 0,
+ VIDEO_MODE,
+ COMMAND_MODE,
+};
+
// Display Attributes that are available to clients of this library
// Not to be confused with a similar struct in hwc_utils (in the hwc namespace)
typedef struct DisplayAttributes {
@@ -128,6 +134,9 @@
// Only primary display supported for now, value of dpy ignored
DisplayAttributes getDisplayAttributes(int configIndex, int dpy);
+// Set the primary display mode to command or video mode
+int setDisplayMode(int mode);
+
//=============================================================================
// The functions and methods below run in the context of HWC and
// are called in response to binder calls from clients
diff --git a/libqdutils/mdp_version.cpp b/libqdutils/mdp_version.cpp
index a6a1b85..c02e28d 100644
--- a/libqdutils/mdp_version.cpp
+++ b/libqdutils/mdp_version.cpp
@@ -91,6 +91,7 @@
mRGBPipes = 0;
mVGPipes = 0;
mDMAPipes = 0;
+ mCursorPipes = 0;
mFeatures = 0;
mMDPUpscale = 1;
mMDPDownscale = 1;
@@ -110,6 +111,7 @@
// Default width of MDSS SSPP. For layer resolutions beyond this, we drive
// using two SSPP's.
mMaxPipeWidth = 2048;
+ mMaxCursorSize = 0;
updatePanelInfo();
@@ -309,6 +311,10 @@
else if(!strncmp(tokens[0], "dma_pipes", strlen("dma_pipes"))) {
mDMAPipes = (uint8_t)atoi(tokens[1]);
}
+ else if(!strncmp(tokens[0], "cursor_pipes",
+ strlen("cursor_pipes"))) {
+ mCursorPipes = (uint8_t)atoi(tokens[1]);
+ }
else if(!strncmp(tokens[0], "blending_stages",
strlen("blending_stages"))) {
mBlendStages = (uint8_t)atoi(tokens[1]);
@@ -354,6 +360,9 @@
mRotDownscale = true;
}
}
+ } else if(!strncmp(tokens[0], "max_cursor_size",
+ strlen("max_cursor_size"))) {
+ mMaxCursorSize = atoi(tokens[1]);
}
}
}
@@ -389,8 +398,8 @@
}
ALOGD_IF(DEBUG, "%s: mMDPVersion: %d mMdpRev: %x mRGBPipes:%d,"
- "mVGPipes:%d", __FUNCTION__, mMDPVersion, mMdpRev,
- mRGBPipes, mVGPipes);
+ "mVGPipes:%d mCursorPipes:%d", __FUNCTION__, mMDPVersion,
+ mMdpRev, mRGBPipes, mVGPipes, mCursorPipes);
ALOGD_IF(DEBUG, "%s:mDMAPipes:%d \t mMDPDownscale:%d, mFeatures:%d",
__FUNCTION__, mDMAPipes, mMDPDownscale, mFeatures);
ALOGD_IF(DEBUG, "%s:mLowBw: %lu mHighBw: %lu", __FUNCTION__, mLowBw,
diff --git a/libqdutils/mdp_version.h b/libqdutils/mdp_version.h
index ad92c83..6ebe558 100644
--- a/libqdutils/mdp_version.h
+++ b/libqdutils/mdp_version.h
@@ -116,6 +116,7 @@
uint8_t getRGBPipes() { return mRGBPipes; }
uint8_t getVGPipes() { return mVGPipes; }
uint8_t getDMAPipes() { return mDMAPipes; }
+ uint8_t getCursorPipes() { return mCursorPipes; }
uint8_t getBlendStages() { return mBlendStages; }
bool supportsDecimation();
uint32_t getMaxMDPDownscale();
@@ -140,6 +141,7 @@
uint32_t getMaxFpsSupported() { return mPanelInfo.mMaxFps; }
uint32_t getMaxMixerWidth() const { return mMaxMixerWidth; }
uint32_t getMaxPipeWidth() const { return mMaxPipeWidth; }
+ uint32_t getMaxCursorSize() const { return mMaxCursorSize; }
bool hasMinCropWidthLimitation() const;
bool isSrcSplit() const;
bool isSrcSplitAlways() const;
@@ -166,6 +168,7 @@
uint8_t mRGBPipes;
uint8_t mVGPipes;
uint8_t mDMAPipes;
+ uint8_t mCursorPipes;
uint8_t mBlendStages;
uint32_t mFeatures;
uint32_t mMDPDownscale;
@@ -182,6 +185,7 @@
bool mRotDownscale;
uint32_t mMaxMixerWidth; //maximum x-res of a given mdss mixer.
uint32_t mMaxPipeWidth; //maximum x-res of the mdp pipe.
+ uint32_t mMaxCursorSize; //maximum size supported by hw cursor
};
}; //namespace qdutils
#endif //INCLUDE_LIBQCOMUTILS_MDPVER
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index 6a9d7f8..5054578 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -63,10 +63,12 @@
SET_FRAME_DUMP_CONFIG = 21, // Provides ability to set the frame dump config
SET_S3D_MODE = 22, // Set the 3D mode as specified in msm_hdmi_modes.h
CONNECT_HDMI_CLIENT = 23, // Connect HDMI CEC HAL Client
+ QDCM_SVC_CMDS = 24, // request QDCM services.
SET_ACTIVE_CONFIG = 25, //Set a specified display config
GET_ACTIVE_CONFIG = 26, //Get the current config index
GET_CONFIG_COUNT = 27, //Get the number of supported display configs
GET_DISPLAY_ATTRIBUTES_FOR_CONFIG = 28, //Get attr for specified config
+ SET_DISPLAY_MODE = 29, // Set display mode to command or video mode
COMMAND_LIST_END = 400,
};