Merge "hqd: Remove target list for MDSS_TARGET flag"
diff --git a/common.mk b/common.mk
index 701f1d9..768696a 100644
--- a/common.mk
+++ b/common.mk
@@ -7,11 +7,6 @@
common_includes += $(LOCAL_PATH)/../libhdmi
common_includes += $(LOCAL_PATH)/../libqservice
-ifeq ($(TARGET_USES_POST_PROCESSING),true)
- common_flags += -DUSES_POST_PROCESSING
- common_includes += $(TARGET_OUT_HEADERS)/pp/inc
-endif
-
common_header_export_path := qcom/display
#Common libraries external to display HAL
@@ -21,6 +16,11 @@
common_flags := -DDEBUG_CALC_FPS -Wno-missing-field-initializers
common_flags += -Wconversion -Wall -Werror
+ifeq ($(TARGET_USES_POST_PROCESSING),true)
+ common_flags += -DUSES_POST_PROCESSING
+ common_includes += $(TARGET_OUT_HEADERS)/pp/inc
+endif
+
ifeq ($(ARCH_ARM_HAVE_NEON),true)
common_flags += -D__ARM_HAVE_NEON
endif
diff --git a/displayengine/include/core/display_interface.h b/displayengine/include/core/display_interface.h
index dfe161b..bdeb8a3 100755
--- a/displayengine/include/core/display_interface.h
+++ b/displayengine/include/core/display_interface.h
@@ -94,6 +94,7 @@
float y_dpi; //!< Dots per inch in Y-direction.
float fps; //!< Frame rate per second.
uint32_t vsync_period_ns; //!< VSync period in nanoseconds.
+ uint32_t v_total; //!< Total lines in Y-direction (vActive + vFP + vBP + vPulseWidth).
DisplayConfigVariableInfo() : x_pixels(0), y_pixels(0), x_dpi(0.0f), y_dpi(0.0f),
fps(0.0f), vsync_period_ns(0) { }
@@ -235,12 +236,20 @@
/*! @brief Method to get configuration for variable properties of the display device.
- @param[in] mode index of the mode
+ @param[in] index index of the mode
@param[out] variable_info \link DisplayConfigVariableInfo \endlink
@return \link DisplayError \endlink
*/
- virtual DisplayError GetConfig(DisplayConfigVariableInfo *variable_info, uint32_t mode) = 0;
+ virtual DisplayError GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info) = 0;
+
+ /*! @brief Method to get index of active configuration of the display device.
+
+ @param[out] index index of the mode corresponding to variable properties.
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError GetActiveConfig(uint32_t *index) = 0;
/*! @brief Method to get VSync event state. Default event state is disabled.
@@ -260,13 +269,13 @@
*/
virtual DisplayError SetDisplayState(DisplayState state) = 0;
- /*! @brief Method to set configuration for variable properties of the display device.
+ /*! @brief Method to set active configuration for variable properties of the display device.
- @param[in] mode index of the mode corresponding to variable properties.
+ @param[in] index index of the mode corresponding to variable properties.
@return \link DisplayError \endlink
*/
- virtual DisplayError SetConfig(uint32_t mode) = 0;
+ virtual DisplayError SetActiveConfig(uint32_t index) = 0;
/*! @brief Method to set VSync event state. Default event state is disabled.
diff --git a/displayengine/include/core/layer_stack.h b/displayengine/include/core/layer_stack.h
index aa15753..67a812d 100755
--- a/displayengine/include/core/layer_stack.h
+++ b/displayengine/include/core/layer_stack.h
@@ -95,10 +95,12 @@
struct LayerFlags {
uint64_t skip : 1; //!< This flag shall be set by client to indicate that this layer will be
//!< handled by GPU. Display Device will not consider it for composition.
+
uint64_t updating : 1; //!< This flag shall be set by client to indicate that this is updating/
//!< non-updating. so strategy manager will mark them for SDE/GPU
//!< composition respectively when the layer stack qualifies for cache
//!< based composition.
+
LayerFlags() : skip(0), updating(0) { }
};
@@ -111,12 +113,15 @@
uint64_t geometry_changed : 1; //!< This flag shall be set by client to indicate that the layer
//!< set passed to Prepare() has changed by more than just the
//!< buffer handles and acquire fences.
+
uint64_t skip_present : 1; //!< This flag will be set to true, if the current layer stack
- //!< contains skip layers
+ //!< contains skip layers.
+
uint64_t video_present : 1; //!< This flag will be set to true, if current layer stack
- //!< contains video
+ //!< contains video.
+
uint64_t secure_present : 1; //!< This flag will be set to true, if the current layer stack
- //!< contains secure layers
+ //!< contains secure layers.
LayerStackFlags() : geometry_changed(0), skip_present(0), video_present(0), secure_present(0) { }
};
@@ -200,24 +205,24 @@
@sa DisplayInterface::Commit
*/
struct LayerStack {
- union {
- int retire_fence_fd; //!< File descriptor referring to a sync fence object which will
- //!< be signaled when this composited frame has been replaced on
- //!< screen by a subsequent frame on a physical display. The fence
- //!< object is created and returned during Commit(). Client shall
- //!< Client shall close the returned file descriptor.
- //!< NOTE: This field applies to a physical display only.
+ Layer *layers; //!< Array of layers.
+ uint32_t layer_count; //!< Total number of layers.
- LayerBuffer *output_buffer; //!< Pointer to the buffer where composed buffer would be rendered
- //!< for virtual displays.
- //!< NOTE: This field applies to a virtual display only.
- };
+ int retire_fence_fd; //!< File descriptor referring to a sync fence object which will
+ //!< be signaled when this composited frame has been replaced on
+ //!< screen by a subsequent frame on a physical display. The fence
+ //!< object is created and returned during Commit(). Client shall
+ //!< Client shall close the returned file descriptor.
+ //!< NOTE: This field applies to a physical display only.
- Layer *layers; //!< Array of layers.
- uint32_t layer_count; //!< Total number of layers.
- LayerStackFlags flags; //!< Flags associated with this layer set.
+ LayerBuffer *output_buffer; //!< Pointer to the buffer where composed buffer would be rendered
+ //!< for virtual displays.
+ //!< NOTE: This field applies to a virtual display only.
- LayerStack() : output_buffer(NULL), layers(NULL), layer_count(0) { }
+
+ LayerStackFlags flags; //!< Flags associated with this layer set.
+
+ LayerStack() : layers(NULL), layer_count(0), retire_fence_fd(-1), output_buffer(NULL) { }
};
} // namespace sde
diff --git a/displayengine/include/private/strategy_interface.h b/displayengine/include/private/strategy_interface.h
index ee9763e..b56789e 100755
--- a/displayengine/include/private/strategy_interface.h
+++ b/displayengine/include/private/strategy_interface.h
@@ -35,31 +35,31 @@
/*! @brief Strategy library name
- @details This macro defines name for the composition strategy library. This macro shall be used
- to load library using dlopen().
+ @details This macro defines name for the composition strategy library. This macro shall be used
+ to load library using dlopen().
- @sa CreateStrategyInterface
- @sa DestoryStrategyInterface
+ @sa CreateStrategyInterface
+ @sa DestoryStrategyInterface
*/
#define STRATEGY_LIBRARY_NAME "libsdestrategy.so"
/*! @brief Function name to create composer strategy interface
- @details This macro defines function name for CreateStrategyInterface() which is implemented
- in the composition strategy library. This macro shall be used to specify name of the function
- in dlsym().
+ @details This macro defines function name for CreateStrategyInterface() which is implemented in
+ the composition strategy library. This macro shall be used to specify name of the function in
+ dlsym().
- @sa CreateStrategyInterface
+ @sa CreateStrategyInterface
*/
#define CREATE_STRATEGY_INTERFACE_NAME "CreateStrategyInterface"
/*! @brief Function name to destroy composer strategy interface
- @details This macro defines function name for DestroyStrategyInterface() which is implemented
- in the composition strategy library. This macro shall be used to specify name of the function
- in dlsym().
+ @details This macro defines function name for DestroyStrategyInterface() which is implemented in
+ the composition strategy library. This macro shall be used to specify name of the function in
+ dlsym().
- @sa DestroyStrategyInterface
+ @sa DestroyStrategyInterface
*/
#define DESTROY_STRATEGY_INTERFACE_NAME "DestroyStrategyInterface"
@@ -82,23 +82,23 @@
/*! @brief Function to create composer strategy interface.
- @details This function is used to create StrategyInterface object which resides in the composer
- strategy library loaded at runtime.
+ @details This function is used to create StrategyInterface object which resides in the composer
+ strategy library loaded at runtime.
- @param[out] version \link STRATEGY_VERSION_TAG \endlink
- @param[out] interface \link StrategyInterface \endlink
+ @param[out] version \link STRATEGY_VERSION_TAG \endlink
+ @param[out] interface \link StrategyInterface \endlink
- @return \link DisplayError \endlink
+ @return \link DisplayError \endlink
*/
typedef DisplayError (*CreateStrategyInterface)(uint16_t version, StrategyInterface **interface);
/*! @brief Function to destroy composer strategy interface.
- @details This function is used to destroy StrategyInterface object.
+ @details This function is used to destroy StrategyInterface object.
- @param[in] interface \link StrategyInterface \endlink
+ @param[in] interface \link StrategyInterface \endlink
- @return \link DisplayError \endlink
+ @return \link DisplayError \endlink
*/
typedef DisplayError (*DestroyStrategyInterface)(StrategyInterface *interface);
@@ -107,9 +107,9 @@
const int kMaxSDELayers = 16;
/*! @brief This structure defines constraints and display properties that shall be considered for
- deciding a composition strategy.
+ deciding a composition strategy.
- @sa GetNextStrategy
+ @sa GetNextStrategy
*/
struct StrategyConstraints {
bool safe_mode; //!< In this mode, strategy manager chooses the composition strategy
@@ -123,9 +123,9 @@
};
/*! @brief This structure encapsulates information about the input layer stack and the layers which
- shall be programmed on hardware.
+ shall be programmed on hardware.
- @sa GetNextStrategy
+ @sa Start
*/
struct HWLayersInfo {
LayerStack *stack; //!< Input layer stack. Set by the caller.
@@ -136,34 +136,45 @@
uint32_t count; //!< Total number of layers which need to be set on hardware.
- uint32_t flags; //!< Strategy flags. Caller must reset it to 0 for a new layer stack.
- //!< A non-zero flag value indicates that a strategy has been selected
- //!< previously for the current layer stack. This flag must be
- //!< preserved between multiple GetNextStrategy() calls.
-
- HWLayersInfo() {
- Reset();
- }
-
- void Reset() {
- stack = NULL;
- count = 0;
- flags = 0;
- }
+ HWLayersInfo() : stack(NULL), count(0) { }
};
+/*! @brief Strategy interface.
+
+ @details This class defines Strategy interface. It contains methods which client shall use to
+ determine which strategy to be used for layer composition. This interface is created during
+ display device creation and remains valid until destroyed.
+*/
+
class StrategyInterface {
public:
+ /*! @brief Method to indicate start of a new strategy selection iteration for a layer stack.
+
+ @details Client shall call this method at beginning of each draw cycle before iterating
+ through strategy selection. Strategy interface implementation uses this method to do
+ preprocessing for a given layer stack.
+
+ @param[in] layers_info \link HWLayersInfo \endlink
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError Start(HWLayersInfo *hw_layers_info) = 0;
+
+
/*! @brief Method to get strategy for a layer stack. Caller can loop through this method to try
get all applicable strategies.
@param[in] constraints \link StrategyConstraints \endlink
- @param[inout] layers_info \link HWLayersInfo \endlink
@return \link DisplayError \endlink
*/
- virtual DisplayError GetNextStrategy(StrategyConstraints *constraints,
- HWLayersInfo *hw_layers_info) = 0;
+ virtual DisplayError GetNextStrategy(StrategyConstraints *constraints) = 0;
+
+ /*! @brief Method to indicate end of a strategy selection cycle.
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError Stop() = 0;
protected:
virtual ~StrategyInterface() { }
diff --git a/displayengine/include/utils/constants.h b/displayengine/include/utils/constants.h
index 44b6896..a0f2bfb 100644
--- a/displayengine/include/utils/constants.h
+++ b/displayengine/include/utils/constants.h
@@ -30,6 +30,7 @@
#define INT(exp) static_cast<int>(exp)
#define FLOAT(exp) static_cast<float>(exp)
+#define UINT8(exp) static_cast<uint8_t>(exp)
#define UINT32(exp) static_cast<uint32_t>(exp)
#define INT32(exp) static_cast<int32_t>(exp)
@@ -46,6 +47,7 @@
#define SET_BIT(value, bit) (value |= (1 << (bit)))
#define CLEAR_BIT(value, bit) (value &= (~(1 << (bit))))
#define IS_BIT_SET(value, bit) (value & (1 << (bit)))
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
namespace sde {
diff --git a/displayengine/libs/core/comp_manager.cpp b/displayengine/libs/core/comp_manager.cpp
old mode 100755
new mode 100644
index 916d558..6a9f006
--- a/displayengine/libs/core/comp_manager.cpp
+++ b/displayengine/libs/core/comp_manager.cpp
@@ -27,13 +27,15 @@
#include <utils/debug.h>
#include "comp_manager.h"
+#include "strategy_default.h"
#define __CLASS__ "CompManager"
namespace sde {
-CompManager::CompManager() : strategy_lib_(NULL), strategy_intf_(NULL), registered_displays_(0),
- configured_displays_(0), safe_mode_(false) {
+CompManager::CompManager()
+ : strategy_lib_(NULL), create_strategy_intf_(NULL), destroy_strategy_intf_(NULL),
+ registered_displays_(0), configured_displays_(0), safe_mode_(false) {
}
DisplayError CompManager::Init(const HWResourceInfo &hw_res_info) {
@@ -49,43 +51,40 @@
// Try to load strategy library & get handle to its interface.
// Default to GPU only composition on failure.
strategy_lib_ = ::dlopen(STRATEGY_LIBRARY_NAME, RTLD_NOW);
- if (!strategy_lib_) {
- DLOGW("Unable to load = %s", STRATEGY_LIBRARY_NAME);
- } else {
- CreateStrategyInterface create_strategy_intf = NULL;
- void **sym = reinterpret_cast<void **>(&create_strategy_intf);
- *sym = ::dlsym(strategy_lib_, CREATE_STRATEGY_INTERFACE_NAME);
- if (!create_strategy_intf) {
- DLOGW("Unable to find symbol for %s", CREATE_STRATEGY_INTERFACE_NAME);
- } else if (create_strategy_intf(STRATEGY_VERSION_TAG, &strategy_intf_) != kErrorNone) {
- DLOGW("Unable to create strategy interface");
- }
- }
+ if (strategy_lib_) {
+ void **create_sym = reinterpret_cast<void **>(&create_strategy_intf_);
+ void **destroy_sym = reinterpret_cast<void **>(&destroy_strategy_intf_);
- if (!strategy_intf_) {
- DLOGI("Using GPU only composition");
- if (strategy_lib_) {
+ *create_sym = ::dlsym(strategy_lib_, CREATE_STRATEGY_INTERFACE_NAME);
+ *destroy_sym = ::dlsym(strategy_lib_, DESTROY_STRATEGY_INTERFACE_NAME);
+
+ if (!create_strategy_intf_) {
+ DLOGE("Unable to find symbol for %s", CREATE_STRATEGY_INTERFACE_NAME);
+ error = kErrorUndefined;
+ }
+
+ if (!destroy_strategy_intf_) {
+ DLOGE("Unable to find symbol for %s", DESTROY_STRATEGY_INTERFACE_NAME);
+ error = kErrorUndefined;
+ }
+
+ if (error != kErrorNone) {
::dlclose(strategy_lib_);
- strategy_lib_ = NULL;
+ res_mgr_.Deinit();
}
- strategy_intf_ = &strategy_default_;
+ } else {
+ DLOGW("Unable to load = %s, using GPU only (default) composition", STRATEGY_LIBRARY_NAME);
+ create_strategy_intf_ = StrategyDefault::CreateStrategyInterface;
+ destroy_strategy_intf_ = StrategyDefault::DestroyStrategyInterface;
}
- return kErrorNone;
+ return error;
}
DisplayError CompManager::Deinit() {
SCOPE_LOCK(locker_);
if (strategy_lib_) {
- DestroyStrategyInterface destroy_strategy_intf = NULL;
- void **sym = reinterpret_cast<void **>(&destroy_strategy_intf);
- *sym = ::dlsym(strategy_lib_, DESTROY_STRATEGY_INTERFACE_NAME);
- if (!destroy_strategy_intf) {
- DLOGW("Unable to find symbol for %s", DESTROY_STRATEGY_INTERFACE_NAME);
- } else if (destroy_strategy_intf(strategy_intf_) != kErrorNone) {
- DLOGW("Unable to destroy strategy interface");
- }
::dlclose(strategy_lib_);
}
@@ -105,11 +104,19 @@
return kErrorMemory;
}
+ if (create_strategy_intf_(STRATEGY_VERSION_TAG, &display_comp_ctx->strategy_intf) != kErrorNone) {
+ DLOGW("Unable to create strategy interface");
+ delete display_comp_ctx;
+ return kErrorUndefined;
+ }
+
error = res_mgr_.RegisterDisplay(type, attributes, &display_comp_ctx->display_resource_ctx);
if (error != kErrorNone) {
+ destroy_strategy_intf_(display_comp_ctx->strategy_intf);
delete display_comp_ctx;
return error;
}
+
SET_BIT(registered_displays_, type);
display_comp_ctx->display_type = type;
*display_ctx = display_comp_ctx;
@@ -127,8 +134,11 @@
reinterpret_cast<DisplayCompositionContext *>(comp_handle);
res_mgr_.UnregisterDisplay(display_comp_ctx->display_resource_ctx);
+ destroy_strategy_intf_(display_comp_ctx->strategy_intf);
+
CLEAR_BIT(registered_displays_, display_comp_ctx->display_type);
CLEAR_BIT(configured_displays_, display_comp_ctx->display_type);
+
delete display_comp_ctx;
return kErrorNone;
@@ -140,14 +150,27 @@
StrategyConstraints *constraints = &display_comp_ctx->constraints;
constraints->safe_mode = safe_mode_;
+
+ // TODO(user): Need to enable SDE Comp on HDMI
+ if (display_comp_ctx->display_type == kHDMI) {
+ constraints->max_layers = 1;
+ }
// If validation for the best available composition strategy with driver has failed, just
// fallback to safe mode composition e.g. GPU or video only.
- if (UNLIKELY(hw_layers->info.flags)) {
+ if (display_comp_ctx->strategy_selected) {
constraints->safe_mode = true;
return;
}
}
+void CompManager::PrePrepare(Handle display_ctx, HWLayers *hw_layers) {
+ SCOPE_LOCK(locker_);
+ DisplayCompositionContext *display_comp_ctx =
+ reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+ display_comp_ctx->strategy_intf->Start(&hw_layers->info);
+ display_comp_ctx->strategy_selected = false;
+}
+
DisplayError CompManager::Prepare(Handle display_ctx, HWLayers *hw_layers) {
SCOPE_LOCK(locker_);
@@ -162,7 +185,7 @@
// Select a composition strategy, and try to allocate resources for it.
res_mgr_.Start(display_resource_ctx);
while (true) {
- error = strategy_intf_->GetNextStrategy(&display_comp_ctx->constraints, &hw_layers->info);
+ error = display_comp_ctx->strategy_intf->GetNextStrategy(&display_comp_ctx->constraints);
if (UNLIKELY(error != kErrorNone)) {
// Composition strategies exhausted. Resource Manager could not allocate resources even for
// GPU composition. This will never happen.
@@ -179,6 +202,7 @@
break;
}
}
+ display_comp_ctx->strategy_selected = true;
res_mgr_.Stop(display_resource_ctx);
return error;
@@ -186,6 +210,9 @@
void CompManager::PostPrepare(Handle display_ctx, HWLayers *hw_layers) {
SCOPE_LOCK(locker_);
+ DisplayCompositionContext *display_comp_ctx =
+ reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+ display_comp_ctx->strategy_intf->Stop();
}
void CompManager::PostCommit(Handle display_ctx, HWLayers *hw_layers) {
diff --git a/displayengine/libs/core/comp_manager.h b/displayengine/libs/core/comp_manager.h
index 13452b8..1c22618 100644
--- a/displayengine/libs/core/comp_manager.h
+++ b/displayengine/libs/core/comp_manager.h
@@ -28,7 +28,6 @@
#include <core/display_interface.h>
#include "hw_interface.h"
-#include "strategy_default.h"
#include "res_manager.h"
#include "dump_impl.h"
@@ -42,6 +41,7 @@
DisplayError RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
Handle *res_mgr_hnd);
DisplayError UnregisterDisplay(Handle res_mgr_hnd);
+ void PrePrepare(Handle display_ctx, HWLayers *hw_layers);
DisplayError Prepare(Handle display_ctx, HWLayers *hw_layers);
void PostPrepare(Handle display_ctx, HWLayers *hw_layers);
void PostCommit(Handle display_ctx, HWLayers *hw_layers);
@@ -54,15 +54,17 @@
void PrepareStrategyConstraints(Handle display_ctx, HWLayers *hw_layers);
struct DisplayCompositionContext {
+ StrategyInterface *strategy_intf;
StrategyConstraints constraints;
Handle display_resource_ctx;
DisplayType display_type;
+ bool strategy_selected;
};
Locker locker_;
void *strategy_lib_;
- StrategyInterface *strategy_intf_;
- StrategyDefault strategy_default_;
+ CreateStrategyInterface create_strategy_intf_;
+ DestroyStrategyInterface destroy_strategy_intf_;
ResManager res_mgr_;
uint64_t registered_displays_; // Stores the bit mask of registered displays
uint64_t configured_displays_; // Stores the bit mask of sucessfully configured displays
diff --git a/displayengine/libs/core/display_base.cpp b/displayengine/libs/core/display_base.cpp
old mode 100755
new mode 100644
index 6099231..7cd88e7
--- a/displayengine/libs/core/display_base.cpp
+++ b/displayengine/libs/core/display_base.cpp
@@ -45,12 +45,12 @@
DisplayError error = kErrorNone;
error = hw_intf_->Open(hw_device_type_, &hw_device_, this);
- if (UNLIKELY(error != kErrorNone)) {
+ if (error != kErrorNone) {
return error;
}
error = hw_intf_->GetNumDisplayAttributes(hw_device_, &num_modes_);
- if (UNLIKELY(error != kErrorNone)) {
+ if (error != kErrorNone) {
goto CleanupOnError;
}
@@ -62,16 +62,21 @@
for (uint32_t i = 0; i < num_modes_; i++) {
error = hw_intf_->GetDisplayAttributes(hw_device_, &display_attributes_[i], i);
- if (UNLIKELY(error != kErrorNone)) {
+ if (error != kErrorNone) {
goto CleanupOnError;
}
}
- active_mode_index_ = 0;
+ active_mode_index_ = GetBestConfig();
+
+ error = hw_intf_->SetDisplayAttributes(hw_device_, active_mode_index_);
+ if (error != kErrorNone) {
+ goto CleanupOnError;
+ }
error = comp_manager_->RegisterDisplay(display_type_, display_attributes_[active_mode_index_],
&display_comp_ctx_);
- if (UNLIKELY(error != kErrorNone)) {
+ if (error != kErrorNone) {
goto CleanupOnError;
}
@@ -104,31 +109,32 @@
DisplayError error = kErrorNone;
- if (UNLIKELY(!layer_stack)) {
+ if (!layer_stack) {
return kErrorParameters;
}
pending_commit_ = false;
- if (LIKELY(state_ == kStateOn)) {
+ if ((state_ == kStateOn)) {
// Clean hw layers for reuse.
- hw_layers_.info.Reset();
+ hw_layers_.info = HWLayersInfo();
hw_layers_.info.stack = layer_stack;
+ comp_manager_->PrePrepare(display_comp_ctx_, &hw_layers_);
while (true) {
error = comp_manager_->Prepare(display_comp_ctx_, &hw_layers_);
- if (UNLIKELY(error != kErrorNone)) {
+ if (error != kErrorNone) {
break;
}
error = hw_intf_->Validate(hw_device_, &hw_layers_);
- if (LIKELY(error == kErrorNone)) {
+ if (error == kErrorNone) {
// Strategy is successful now, wait for Commit().
- comp_manager_->PostPrepare(display_comp_ctx_, &hw_layers_);
pending_commit_ = true;
break;
}
}
+ comp_manager_->PostPrepare(display_comp_ctx_, &hw_layers_);
}
return error;
@@ -139,18 +145,18 @@
DisplayError error = kErrorNone;
- if (UNLIKELY(!layer_stack)) {
+ if (!layer_stack) {
return kErrorParameters;
}
- if (UNLIKELY(!pending_commit_)) {
+ if (!pending_commit_) {
DLOGE("Commit: Corresponding Prepare() is not called.");
return kErrorUndefined;
}
- if (LIKELY(state_ == kStateOn)) {
+ if (state_ == kStateOn) {
error = hw_intf_->Commit(hw_device_, &hw_layers_);
- if (LIKELY(error == kErrorNone)) {
+ if (error == kErrorNone) {
comp_manager_->PostCommit(display_comp_ctx_, &hw_layers_);
} else {
DLOGE("Unexpected error. Commit failed on driver.");
@@ -165,7 +171,7 @@
DisplayError DisplayBase::GetDisplayState(DisplayState *state) {
SCOPE_LOCK(locker_);
- if (UNLIKELY(!state)) {
+ if (!state) {
return kErrorParameters;
}
@@ -176,7 +182,7 @@
DisplayError DisplayBase::GetNumVariableInfoConfigs(uint32_t *count) {
SCOPE_LOCK(locker_);
- if (UNLIKELY(!count)) {
+ if (!count) {
return kErrorParameters;
}
@@ -188,21 +194,33 @@
DisplayError DisplayBase::GetConfig(DisplayConfigFixedInfo *fixed_info) {
SCOPE_LOCK(locker_);
- if (UNLIKELY(!fixed_info)) {
+ if (!fixed_info) {
return kErrorParameters;
}
return kErrorNone;
}
-DisplayError DisplayBase::GetConfig(DisplayConfigVariableInfo *variable_info, uint32_t mode) {
+DisplayError DisplayBase::GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info) {
SCOPE_LOCK(locker_);
- if (UNLIKELY(!variable_info || mode >= num_modes_)) {
+ if (!variable_info || index >= num_modes_) {
return kErrorParameters;
}
- *variable_info = display_attributes_[mode];
+ *variable_info = display_attributes_[index];
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::GetActiveConfig(uint32_t *index) {
+ SCOPE_LOCK(locker_);
+
+ if (!index) {
+ return kErrorParameters;
+ }
+
+ *index = active_mode_index_;
return kErrorNone;
}
@@ -210,7 +228,7 @@
DisplayError DisplayBase::GetVSyncState(bool *enabled) {
SCOPE_LOCK(locker_);
- if (UNLIKELY(!enabled)) {
+ if (!enabled) {
return kErrorParameters;
}
@@ -224,7 +242,7 @@
DLOGI("Set state = %d", state);
- if (UNLIKELY(state == state_)) {
+ if (state == state_) {
DLOGI("Same state transition is requested.");
return kErrorNone;
}
@@ -253,17 +271,27 @@
break;
}
- if (UNLIKELY(error == kErrorNone)) {
+ if (error == kErrorNone) {
state_ = state;
}
return error;
}
-DisplayError DisplayBase::SetConfig(uint32_t mode) {
+DisplayError DisplayBase::SetActiveConfig(uint32_t index) {
SCOPE_LOCK(locker_);
+ DisplayError error = kErrorNone;
- return kErrorNone;
+ if (index >= num_modes_) {
+ return kErrorParameters;
+ }
+
+ error = hw_intf_->SetDisplayAttributes(hw_device_, index);
+ if (error != kErrorNone) {
+ active_mode_index_ = index;
+ }
+
+ return error;
}
DisplayError DisplayBase::SetVSyncState(bool enable) {
@@ -349,5 +377,9 @@
rect_name, rect->left, rect->top, rect->right, rect->bottom);
}
+int DisplayBase::GetBestConfig() {
+ return (num_modes_ == 1) ? 0 : -1;
+}
+
} // namespace sde
diff --git a/displayengine/libs/core/display_base.h b/displayengine/libs/core/display_base.h
index 7eaa044..3f0e24f 100644
--- a/displayengine/libs/core/display_base.h
+++ b/displayengine/libs/core/display_base.h
@@ -46,10 +46,11 @@
virtual DisplayError GetDisplayState(DisplayState *state);
virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count);
virtual DisplayError GetConfig(DisplayConfigFixedInfo *fixed_info);
- virtual DisplayError GetConfig(DisplayConfigVariableInfo *variable_info, uint32_t mode);
+ 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 SetConfig(uint32_t mode);
+ virtual DisplayError SetActiveConfig(uint32_t index);
virtual DisplayError SetVSyncState(bool enable);
// Implement the HWEventHandlers
@@ -61,6 +62,8 @@
void AppendRect(char *buffer, uint32_t length, const char *rect_name, LayerRect *rect);
protected:
+ virtual int GetBestConfig();
+
Locker locker_;
DisplayType display_type_;
DisplayEventHandler *event_handler_;
diff --git a/displayengine/libs/core/display_hdmi.cpp b/displayengine/libs/core/display_hdmi.cpp
old mode 100755
new mode 100644
index 48208bf..f7c42f4
--- a/displayengine/libs/core/display_hdmi.cpp
+++ b/displayengine/libs/core/display_hdmi.cpp
@@ -36,5 +36,36 @@
: DisplayBase(kHDMI, event_handler, kDeviceHDMI, hw_intf, comp_manager) {
}
+int DisplayHDMI::GetBestConfig() {
+ uint32_t best_config_mode = 0;
+ HWDisplayAttributes *best = &display_attributes_[0];
+ if (num_modes_ == 1) {
+ return best_config_mode;
+ }
+
+ // From the available configs, select the best
+ // Ex: 1920x1080@60Hz is better than 1920x1080@30 and 1920x1080@30 is better than 1280x720@60
+ for (uint32_t index = 1; index < num_modes_; index++) {
+ HWDisplayAttributes *current = &display_attributes_[index];
+ // compare the two modes: in the order of Resolution followed by refreshrate
+ if (current->y_pixels > best->y_pixels) {
+ best_config_mode = index;
+ } else if (current->y_pixels == best->y_pixels) {
+ if (current->x_pixels > best->x_pixels) {
+ best_config_mode = index;
+ } else if (current->x_pixels == best->x_pixels) {
+ if (current->vsync_period_ns < best->vsync_period_ns) {
+ best_config_mode = index;
+ }
+ }
+ }
+ if (best_config_mode == index) {
+ best = &display_attributes_[index];
+ }
+ }
+
+ return best_config_mode;
+}
+
} // namespace sde
diff --git a/displayengine/libs/core/display_hdmi.h b/displayengine/libs/core/display_hdmi.h
index 85f53fc..0bb9dc8 100644
--- a/displayengine/libs/core/display_hdmi.h
+++ b/displayengine/libs/core/display_hdmi.h
@@ -32,6 +32,7 @@
class DisplayHDMI : public DisplayBase {
public:
DisplayHDMI(DisplayEventHandler *event_handler, HWInterface *hw_intf, CompManager *comp_manager);
+ virtual int GetBestConfig();
};
} // namespace sde
diff --git a/displayengine/libs/core/hw_framebuffer.cpp b/displayengine/libs/core/hw_framebuffer.cpp
old mode 100755
new mode 100644
index 69b4a58..3a0f2d0
--- a/displayengine/libs/core/hw_framebuffer.cpp
+++ b/displayengine/libs/core/hw_framebuffer.cpp
@@ -23,7 +23,7 @@
*/
#define __STDC_FORMAT_MACROS
-
+#include <ctype.h>
#include <math.h>
#include <fcntl.h>
#include <inttypes.h>
@@ -41,7 +41,8 @@
#define __CLASS__ "HWFrameBuffer"
-#define IOCTL_LOGE(ioctl) DLOGE("ioctl %s, errno = %d, desc = %s", #ioctl, errno, strerror(errno))
+#define IOCTL_LOGE(ioctl, type) DLOGE("ioctl %s, display = %d errno = %d, desc = %s", #ioctl, \
+ type, errno, strerror(errno))
#ifdef DISPLAY_CORE_VIRTUAL_DRIVER
extern int virtual_ioctl(int fd, int cmd, ...);
@@ -52,12 +53,16 @@
extern FILE* virtual_fopen(const char *fname, const char *mode);
extern int virtual_fclose(FILE* fileptr);
extern ssize_t virtual_getline(char **lineptr, size_t *linelen, FILE *stream);
+extern ssize_t virtual_read(int fd, void *buf, size_t count);
+extern ssize_t virtual_write(int fd, const void *buf, size_t count);
+
#endif
namespace sde {
HWFrameBuffer::HWFrameBuffer() : event_thread_name_("SDE_EventThread"), fake_vsync_(false),
- exit_threads_(false), fb_path_("/sys/class/graphics/fb") {
+ exit_threads_(false), fb_path_("/sys/devices/virtual/graphics/fb"),
+ hotplug_enabled_(false) {
// Pointer to actual driver interfaces.
ioctl_ = ::ioctl;
open_ = ::open;
@@ -67,6 +72,8 @@
fopen_ = ::fopen;
fclose_ = ::fclose;
getline_ = ::getline;
+ read_ = ::read;
+ write_ = ::write;
#ifdef DISPLAY_CORE_VIRTUAL_DRIVER
// If debug property to use virtual driver is set, point to virtual driver interfaces.
@@ -79,6 +86,8 @@
fopen_ = virtual_fopen;
fclose_ = virtual_fclose;
getline_ = virtual_getline;
+ read_ = virtual_read;
+ write_ = virtual_write;
}
#endif
for (int i = 0; i < kDeviceMax; i++) {
@@ -137,6 +146,16 @@
}
}
+ // Mode look-up table for HDMI
+ supported_video_modes_ = new msm_hdmi_mode_timing_info[HDMI_VFRMT_MAX];
+ if (!supported_video_modes_) {
+ error = kErrorMemory;
+ goto CleanupOnError;
+ }
+ // Populate the mode table for supported modes
+ MSM_HDMI_MODES_INIT_TIMINGS(supported_video_modes_);
+ MSM_HDMI_MODES_SET_SUPP_TIMINGS(supported_video_modes_, MSM_HDMI_MODES_ALL);
+
// Start the Event thread
if (pthread_create(&event_thread_, NULL, &DisplayEventThread, this) < 0) {
DLOGE("Failed to start %s, error = %s", event_thread_name_);
@@ -156,6 +175,9 @@
}
}
}
+ if (supported_video_modes_) {
+ delete supported_video_modes_;
+ }
return error;
}
@@ -169,6 +191,9 @@
close(poll_fds_[display][event].fd);
}
}
+ if (supported_video_modes_) {
+ delete supported_video_modes_;
+ }
return kErrorNone;
}
@@ -183,27 +208,27 @@
DisplayError error = kErrorNone;
HWContext *hw_context = new HWContext();
- if (UNLIKELY(!hw_context)) {
+ if (!hw_context) {
return kErrorMemory;
}
char device_name[64] = {0};
switch (type) {
- case kDevicePrimary:
- case kDeviceHDMI:
- // Store EventHandlers for two Physical displays, i.e., Primary and HDMI
- // TODO(user): Need to revisit for HDMI as Primary usecase
- event_handler_[type] = eventhandler;
- case kDeviceVirtual:
- snprintf(device_name, sizeof(device_name), "%s%d", "/dev/graphics/fb", fb_node_index_[type]);
- break;
- default:
- break;
+ case kDevicePrimary:
+ case kDeviceHDMI:
+ // Store EventHandlers for two Physical displays, i.e., Primary and HDMI
+ // TODO(user): Need to revisit for HDMI as Primary usecase
+ event_handler_[type] = eventhandler;
+ case kDeviceVirtual:
+ snprintf(device_name, sizeof(device_name), "%s%d", "/dev/graphics/fb", fb_node_index_[type]);
+ break;
+ default:
+ break;
}
hw_context->device_fd = open_(device_name, O_RDWR);
- if (UNLIKELY(hw_context->device_fd < 0)) {
+ if (hw_context->device_fd < 0) {
DLOGE("open %s failed.", device_name);
error = kErrorResources;
delete hw_context;
@@ -218,7 +243,19 @@
DisplayError HWFrameBuffer::Close(Handle device) {
HWContext *hw_context = reinterpret_cast<HWContext *>(device);
- close_(hw_context->device_fd);
+ switch (hw_context->type) {
+ case kDevicePrimary:
+ break;
+ case kDeviceHDMI:
+ hdmi_mode_count_ = 0;
+ break;
+ default:
+ break;
+ }
+
+ if (hw_context->device_fd > 0) {
+ close_(hw_context->device_fd);
+ }
delete hw_context;
return kErrorNone;
@@ -227,74 +264,186 @@
DisplayError HWFrameBuffer::GetNumDisplayAttributes(Handle device, uint32_t *count) {
HWContext *hw_context = reinterpret_cast<HWContext *>(device);
- // TODO(user): Query modes
- *count = 1;
+ switch (hw_context->type) {
+ case kDevicePrimary:
+ *count = 1;
+ break;
+ case kDeviceHDMI:
+ *count = GetHDMIModeCount();
+ if (*count <= 0) {
+ return kErrorHardware;
+ }
+ break;
+ default:
+ return kErrorParameters;
+ }
return kErrorNone;
}
DisplayError HWFrameBuffer::GetDisplayAttributes(Handle device,
HWDisplayAttributes *display_attributes,
- uint32_t mode) {
+ uint32_t index) {
HWContext *hw_context = reinterpret_cast<HWContext *>(device);
int &device_fd = hw_context->device_fd;
-
- // TODO(user): Query for respective mode index.
-
// Variable screen info
STRUCT_VAR(fb_var_screeninfo, var_screeninfo);
- if (UNLIKELY(ioctl_(device_fd, FBIOGET_VSCREENINFO, &var_screeninfo) == -1)) {
- IOCTL_LOGE(FBIOGET_VSCREENINFO);
- return kErrorHardware;
- }
- // Frame rate
- STRUCT_VAR(msmfb_metadata, meta_data);
- meta_data.op = metadata_op_frame_rate;
- if (UNLIKELY(ioctl_(device_fd, MSMFB_METADATA_GET, &meta_data) == -1)) {
- IOCTL_LOGE(MSMFB_METADATA_GET);
- return kErrorHardware;
- }
+ switch (hw_context->type) {
+ case kDevicePrimary:
+ {
+ if (ioctl_(device_fd, FBIOGET_VSCREENINFO, &var_screeninfo) == -1) {
+ IOCTL_LOGE(FBIOGET_VSCREENINFO, hw_context->type);
+ return kErrorHardware;
+ }
- // If driver doesn't return width/height information, default to 160 dpi
- if (INT(var_screeninfo.width) <= 0 || INT(var_screeninfo.height) <= 0) {
- var_screeninfo.width = INT((FLOAT(var_screeninfo.xres) * 25.4f)/160.0f + 0.5f);
- var_screeninfo.height = INT((FLOAT(var_screeninfo.yres) * 25.4f)/160.0f + 0.5f);
- }
+ // Frame rate
+ STRUCT_VAR(msmfb_metadata, meta_data);
+ meta_data.op = metadata_op_frame_rate;
+ if (ioctl_(device_fd, MSMFB_METADATA_GET, &meta_data) == -1) {
+ IOCTL_LOGE(MSMFB_METADATA_GET, hw_context->type);
+ return kErrorHardware;
+ }
- display_attributes->x_pixels = var_screeninfo.xres;
- display_attributes->y_pixels = var_screeninfo.yres;
- display_attributes->x_dpi = (FLOAT(var_screeninfo.xres) * 25.4f) / FLOAT(var_screeninfo.width);
- display_attributes->y_dpi = (FLOAT(var_screeninfo.yres) * 25.4f) / FLOAT(var_screeninfo.height);
- display_attributes->vsync_period_ns =
- UINT32(1000000000L / FLOAT(meta_data.data.panel_frame_rate));
+ // If driver doesn't return width/height information, default to 160 dpi
+ if (INT(var_screeninfo.width) <= 0 || INT(var_screeninfo.height) <= 0) {
+ var_screeninfo.width = INT(((FLOAT(var_screeninfo.xres) * 25.4f)/160.0f) + 0.5f);
+ var_screeninfo.height = INT(((FLOAT(var_screeninfo.yres) * 25.4f)/160.0f) + 0.5f);
+ }
- display_attributes->is_device_split = ((var_screeninfo.xres > hw_resource_.max_mixer_width) ||
- (hw_resource_.split_info.right_split)) ? true : false;
- if (display_attributes->is_device_split) {
- display_attributes->split_left = hw_resource_.split_info.left_split ?
- hw_resource_.split_info.left_split : display_attributes->x_pixels / 2;
+ display_attributes->x_pixels = var_screeninfo.xres;
+ display_attributes->y_pixels = var_screeninfo.yres;
+ display_attributes->v_total = var_screeninfo.yres + var_screeninfo.lower_margin +
+ var_screeninfo.upper_margin + var_screeninfo.vsync_len;
+ display_attributes->x_dpi =
+ (FLOAT(var_screeninfo.xres) * 25.4f) / FLOAT(var_screeninfo.width);
+ display_attributes->y_dpi =
+ (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 = (hw_resource_.split_info.left_split ||
+ (var_screeninfo.xres > hw_resource_.max_mixer_width)) ? true : false;
+ display_attributes->split_left = hw_resource_.split_info.left_split ?
+ hw_resource_.split_info.left_split : display_attributes->x_pixels / 2;
+ }
+ break;
+
+ case kDeviceHDMI:
+ {
+ // Get the resolution info from the look up table
+ msm_hdmi_mode_timing_info *timing_mode = &supported_video_modes_[0];
+ for (int i = 0; i < HDMI_VFRMT_MAX; i++) {
+ msm_hdmi_mode_timing_info *cur = &supported_video_modes_[i];
+ if (cur->video_format == hdmi_modes_[index]) {
+ timing_mode = cur;
+ break;
+ }
+ }
+ display_attributes->x_pixels = timing_mode->active_h;
+ display_attributes->y_pixels = timing_mode->active_v;
+ display_attributes->v_total = timing_mode->active_v + timing_mode->front_porch_v +
+ timing_mode->back_porch_v + timing_mode->pulse_width_v;
+ display_attributes->x_dpi = 0;
+ display_attributes->y_dpi = 0;
+ display_attributes->fps = FLOAT(timing_mode->refresh_rate);
+ display_attributes->vsync_period_ns = UINT32(1000000000L / display_attributes->fps);
+ display_attributes->split_left = display_attributes->x_pixels;
+ if (display_attributes->x_pixels > hw_resource_.max_mixer_width) {
+ display_attributes->is_device_split = true;
+ display_attributes->split_left = display_attributes->x_pixels / 2;
+ }
+ }
+ break;
+
+ default:
+ return kErrorParameters;
}
return kErrorNone;
}
+DisplayError HWFrameBuffer::SetDisplayAttributes(Handle device, uint32_t index) {
+ HWContext *hw_context = reinterpret_cast<HWContext *>(device);
+ DisplayError error = kErrorNone;
+
+ switch (hw_context->type) {
+ case kDevicePrimary:
+ break;
+
+ case kDeviceHDMI:
+ {
+ // Variable screen info
+ STRUCT_VAR(fb_var_screeninfo, vscreeninfo);
+ if (ioctl_(hw_context->device_fd, FBIOGET_VSCREENINFO, &vscreeninfo) == -1) {
+ IOCTL_LOGE(FBIOGET_VSCREENINFO, hw_context->type);
+ return kErrorHardware;
+ }
+
+ DLOGI("GetInfo<Mode=%d %dx%d (%d,%d,%d),(%d,%d,%d) %dMHz>", vscreeninfo.reserved[3],
+ vscreeninfo.xres, vscreeninfo.yres, vscreeninfo.right_margin, vscreeninfo.hsync_len,
+ vscreeninfo.left_margin, vscreeninfo.lower_margin, vscreeninfo.vsync_len,
+ vscreeninfo.upper_margin, vscreeninfo.pixclock/1000000);
+
+ msm_hdmi_mode_timing_info *timing_mode = &supported_video_modes_[0];
+ for (int i = 0; i < HDMI_VFRMT_MAX; i++) {
+ msm_hdmi_mode_timing_info *cur = &supported_video_modes_[i];
+ if (cur->video_format == hdmi_modes_[index]) {
+ timing_mode = cur;
+ break;
+ }
+ }
+ if (MapHDMIDisplayTiming(timing_mode, &vscreeninfo) == false) {
+ return kErrorParameters;
+ }
+ STRUCT_VAR(msmfb_metadata, metadata);
+ memset(&metadata, 0 , sizeof(metadata));
+ metadata.op = metadata_op_vic;
+ metadata.data.video_info_code = timing_mode->video_format;
+ if (ioctl(hw_context->device_fd, MSMFB_METADATA_SET, &metadata) == -1) {
+ IOCTL_LOGE(MSMFB_METADATA_SET, hw_context->type);
+ return kErrorHardware;
+ }
+ DLOGI("SetInfo<Mode=%d %dx%d (%d,%d,%d),(%d,%d,%d) %dMHz>", vscreeninfo.reserved[3] & 0xFF00,
+ vscreeninfo.xres, vscreeninfo.yres, vscreeninfo.right_margin, vscreeninfo.hsync_len,
+ vscreeninfo.left_margin, vscreeninfo.lower_margin, vscreeninfo.vsync_len,
+ vscreeninfo.upper_margin, vscreeninfo.pixclock/1000000);
+
+ vscreeninfo.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_ALL | FB_ACTIVATE_FORCE;
+ if (ioctl_(hw_context->device_fd, FBIOPUT_VSCREENINFO, &vscreeninfo) == -1) {
+ IOCTL_LOGE(FBIOGET_VSCREENINFO, hw_context->type);
+ return kErrorHardware;
+ }
+ }
+ break;
+
+ default:
+ return kErrorParameters;
+ }
+
+ return error;
+}
+
DisplayError HWFrameBuffer::PowerOn(Handle device) {
HWContext *hw_context = reinterpret_cast<HWContext *>(device);
- if (UNLIKELY(ioctl_(hw_context->device_fd, FBIOBLANK, FB_BLANK_UNBLANK) == -1)) {
- IOCTL_LOGE(FB_BLANK_UNBLANK);
+ if (ioctl_(hw_context->device_fd, FBIOBLANK, FB_BLANK_UNBLANK) == -1) {
+ IOCTL_LOGE(FB_BLANK_UNBLANK, hw_context->type);
return kErrorHardware;
}
+ // Need to turn on HPD
+ if (!hotplug_enabled_) {
+ hotplug_enabled_ = EnableHotPlugDetection(1);
+ }
+
return kErrorNone;
}
DisplayError HWFrameBuffer::PowerOff(Handle device) {
HWContext *hw_context = reinterpret_cast<HWContext *>(device);
- if (UNLIKELY(ioctl_(hw_context->device_fd, FBIOBLANK, FB_BLANK_POWERDOWN) == -1)) {
- IOCTL_LOGE(FB_BLANK_POWERDOWN);
+ if (ioctl_(hw_context->device_fd, FBIOBLANK, FB_BLANK_POWERDOWN) == -1) {
+ IOCTL_LOGE(FB_BLANK_POWERDOWN, hw_context->type);
return kErrorHardware;
}
@@ -317,7 +466,7 @@
HWContext *hw_context = reinterpret_cast<HWContext *>(device);
int vsync_on = enable ? 1 : 0;
if (ioctl_(hw_context->device_fd, MSMFB_OVERLAY_VSYNC_CTRL, &vsync_on) == -1) {
- IOCTL_LOGE(MSMFB_OVERLAY_VSYNC_CTRL);
+ IOCTL_LOGE(MSMFB_OVERLAY_VSYNC_CTRL, hw_context->type);
return kErrorHardware;
}
@@ -342,47 +491,35 @@
Layer &layer = stack->layers[layer_index];
LayerBuffer *input_buffer = layer.input_buffer;
HWLayerConfig &config = hw_layers->config[i];
- HWPipeInfo &left_pipe = config.left_pipe;
- // Configure left pipe
- mdp_input_layer &mdp_layer_left = mdp_layers[mdp_layer_count];
- mdp_layer_left.alpha = layer.plane_alpha;
- mdp_layer_left.z_order = static_cast<uint16_t>(i);
- mdp_layer_left.transp_mask = 0xffffffff;
- SetBlending(layer.blending, &mdp_layer_left.blend_op);
- SetRect(left_pipe.src_roi, &mdp_layer_left.src_rect);
- SetRect(left_pipe.dst_roi, &mdp_layer_left.dst_rect);
- mdp_layer_left.pipe_ndx = left_pipe.pipe_id;
+ uint32_t split_count = hw_layers->config[i].is_right_pipe ? 2 : 1;
+ for (uint32_t j = 0; j < split_count; j++) {
+ HWPipeInfo &pipe = (j == 0) ? config.left_pipe : config.right_pipe;
+ mdp_input_layer &mdp_layer = mdp_layers[mdp_layer_count];
+ mdp_layer.alpha = layer.plane_alpha;
+ mdp_layer.z_order = static_cast<uint16_t>(i);
+ mdp_layer.transp_mask = 0xffffffff;
+ SetBlending(layer.blending, &mdp_layer.blend_op);
+ SetRect(pipe.src_roi, &mdp_layer.src_rect);
+ SetRect(pipe.dst_roi, &mdp_layer.dst_rect);
- mdp_layer_buffer &mdp_buffer_left = mdp_layer_left.buffer;
- mdp_buffer_left.width = input_buffer->width;
- mdp_buffer_left.height = input_buffer->height;
+ mdp_layer.pipe_ndx = pipe.pipe_id;
- error = SetFormat(layer.input_buffer->format, &mdp_buffer_left.format);
- if (error != kErrorNone) {
- return error;
- }
+ mdp_layer_buffer &mdp_buffer_left = mdp_layer.buffer;
+ mdp_buffer_left.width = input_buffer->width;
+ mdp_buffer_left.height = input_buffer->height;
- mdp_layer_count++;
-
- // Configure right pipe
- if (config.is_right_pipe) {
- HWPipeInfo &right_pipe = config.right_pipe;
- mdp_input_layer &mdp_layer_right = mdp_layers[mdp_layer_count];
-
- mdp_layer_right = mdp_layer_left;
-
- mdp_layer_right.pipe_ndx = right_pipe.pipe_id;
- SetRect(right_pipe.src_roi, &mdp_layer_right.src_rect);
- SetRect(right_pipe.dst_roi, &mdp_layer_right.dst_rect);
-
+ error = SetFormat(layer.input_buffer->format, &mdp_buffer_left.format);
+ if (error != kErrorNone) {
+ return error;
+ }
mdp_layer_count++;
}
}
mdp_commit.flags |= MDP_VALIDATE_LAYER;
if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_context->mdp_commit) == -1) {
- IOCTL_LOGE(MSMFB_ATOMIC_COMMIT);
+ IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, hw_context->type);
return kErrorHardware;
}
@@ -424,7 +561,7 @@
mdp_commit.flags |= MDP_COMMIT_RETIRE_FENCE;
mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_context->mdp_commit) == -1) {
- IOCTL_LOGE(MSMFB_ATOMIC_COMMIT);
+ IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, hw_context->type);
return kErrorHardware;
}
@@ -619,8 +756,8 @@
ssize_t read;
char *line = stringbuffer;
while ((read = getline_(&line, &len, fileptr)) != -1) {
- int token_count = 0;
- const int max_count = 10;
+ uint32_t token_count = 0;
+ const uint32_t max_count = 10;
char *tokens[max_count] = { NULL };
if (!ParseLine(line, tokens, max_count, &token_count)) {
if (!strncmp(tokens[0], "pu_en", strlen("pu_en"))) {
@@ -656,8 +793,8 @@
DisplayError error = kErrorNone;
FILE *fileptr = NULL;
char stringbuffer[kMaxStringLength];
- int token_count = 0;
- const int max_count = 10;
+ uint32_t token_count = 0;
+ const uint32_t max_count = 10;
char *tokens[max_count] = { NULL };
snprintf(stringbuffer , sizeof(stringbuffer), "%s%d/mdp/caps", fb_path_,
fb_node_index_[kHWPrimary]);
@@ -697,8 +834,14 @@
hw_resource_.max_bandwidth_high = atol(tokens[1]);
} else if (!strncmp(tokens[0], "max_mixer_width", strlen("max_mixer_width"))) {
hw_resource_.max_mixer_width = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "max_pipe_bw", strlen("max_pipe_bw"))) {
+ hw_resource_.max_pipe_bw = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "max_mdp_clk", strlen("max_mdp_clk"))) {
+ hw_resource_.max_sde_clk = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "clk_fudge_factor", strlen("clk_fudge_factor"))) {
+ hw_resource_.clk_fudge_factor = FLOAT(atoi(tokens[1])) / FLOAT(atoi(tokens[2]));
} else if (!strncmp(tokens[0], "features", strlen("features"))) {
- for (int i = 0; i < token_count; i++) {
+ for (uint32_t i = 0; i < token_count; i++) {
if (!strncmp(tokens[i], "bwc", strlen("bwc"))) {
hw_resource_.has_bwc = true;
} else if (!strncmp(tokens[i], "decimation", strlen("decimation"))) {
@@ -763,14 +906,17 @@
DLOGI("SourceSplit = %d, Always = %d", hw_resource_.is_src_split, hw_resource_.always_src_split);
DLOGI("MaxLowBw = %"PRIu64", MaxHighBw = %"PRIu64"", hw_resource_.max_bandwidth_low,
hw_resource_.max_bandwidth_high);
+ DLOGI("MaxPipeBw = %"PRIu64" KBps, MaxSDEClock = %"PRIu64" Hz, ClockFudgeFactor = %f",
+ hw_resource_.max_pipe_bw, hw_resource_.max_sde_clk, hw_resource_.clk_fudge_factor);
return error;
}
-int HWFrameBuffer::ParseLine(char *input, char *tokens[], int max_token, int *count) {
+int HWFrameBuffer::ParseLine(char *input, char *tokens[], const uint32_t max_token,
+ uint32_t *count) {
char *tmp_token = NULL;
char *temp_ptr;
- int index = 0;
+ uint32_t index = 0;
const char *delim = ", =\n";
if (!input) {
return -1;
@@ -785,4 +931,87 @@
return 0;
}
+bool HWFrameBuffer::EnableHotPlugDetection(int enable) {
+ bool ret_value = true;
+ char hpdpath[kMaxStringLength];
+ snprintf(hpdpath , sizeof(hpdpath), "%s%d/hpd", fb_path_, fb_node_index_[kDeviceHDMI]);
+ int hpdfd = open_(hpdpath, O_RDWR, 0);
+ if (hpdfd < 0) {
+ DLOGE("Open failed = %s", hpdpath);
+ return kErrorHardware;
+ }
+ char value = enable ? '1' : '0';
+ ssize_t length = write_(hpdfd, &value, 1);
+ if (length <= 0) {
+ DLOGE("Write failed 'hpd' = %d", enable);
+ ret_value = false;
+ }
+ close_(hpdfd);
+
+ return ret_value;
+}
+
+int HWFrameBuffer::GetHDMIModeCount() {
+ ssize_t length = -1;
+ char edid_str[256] = {'\0'};
+ char edid_path[kMaxStringLength] = {'\0'};
+ snprintf(edid_path, sizeof(edid_path), "%s%d/edid_modes", fb_path_, fb_node_index_[kHWHDMI]);
+ int edid_file = open_(edid_path, O_RDONLY);
+ if (edid_file < 0) {
+ DLOGE("EDID file open failed.");
+ return -1;
+ }
+
+ length = read_(edid_file, edid_str, sizeof(edid_str)-1);
+ if (length <= 0) {
+ DLOGE("%s: edid_modes file empty");
+ edid_str[0] = '\0';
+ } else {
+ DLOGI("EDID mode string: %s", edid_str);
+ while (length > 1 && isspace(edid_str[length-1])) {
+ --length;
+ }
+ edid_str[length] = '\0';
+ }
+ close_(edid_file);
+
+ if (length > 0) {
+ // Get EDID modes from the EDID string
+ char *ptr = edid_str;
+ const uint32_t edid_count_max = 128;
+ char *tokens[edid_count_max] = { NULL };
+ ParseLine(ptr, tokens, edid_count_max, &hdmi_mode_count_);
+ for (uint32_t i = 0; i < hdmi_mode_count_; i++) {
+ hdmi_modes_[i] = atoi(tokens[i]);
+ }
+ }
+ return (hdmi_mode_count_ > 0) ? hdmi_mode_count_ : 0;
+}
+
+bool HWFrameBuffer::MapHDMIDisplayTiming(const msm_hdmi_mode_timing_info *mode,
+ fb_var_screeninfo *info) {
+ if (!mode || !info) {
+ return false;
+ }
+
+ info->reserved[0] = 0;
+ info->reserved[1] = 0;
+ info->reserved[2] = 0;
+ info->reserved[3] = (info->reserved[3] & 0xFFFF) | (mode->video_format << 16);
+ info->xoffset = 0;
+ info->yoffset = 0;
+ info->xres = mode->active_h;
+ info->yres = mode->active_v;
+ info->pixclock = (mode->pixel_freq) * 1000;
+ info->vmode = mode->interlaced ? FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED;
+ info->right_margin = mode->front_porch_h;
+ info->hsync_len = mode->pulse_width_h;
+ info->left_margin = mode->back_porch_h;
+ info->lower_margin = mode->front_porch_v;
+ info->vsync_len = mode->pulse_width_v;
+ info->upper_margin = mode->back_porch_v;
+
+ return true;
+}
+
} // namespace sde
diff --git a/displayengine/libs/core/hw_framebuffer.h b/displayengine/libs/core/hw_framebuffer.h
index b70b5be..5816878 100644
--- a/displayengine/libs/core/hw_framebuffer.h
+++ b/displayengine/libs/core/hw_framebuffer.h
@@ -28,6 +28,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <linux/msm_mdp_ext.h>
+#include <video/msm_hdmi_modes.h>
+
#include <poll.h>
#include <pthread.h>
@@ -45,7 +47,8 @@
virtual DisplayError Close(Handle device);
virtual DisplayError GetNumDisplayAttributes(Handle device, uint32_t *count);
virtual DisplayError GetDisplayAttributes(Handle device, HWDisplayAttributes *display_attributes,
- uint32_t mode);
+ uint32_t index);
+ virtual DisplayError SetDisplayAttributes(Handle device, uint32_t index);
virtual DisplayError PowerOn(Handle device);
virtual DisplayError PowerOff(Handle device);
virtual DisplayError Doze(Handle device);
@@ -130,7 +133,13 @@
void PopulatePanelInfo(int fb_index);
// Populates HW Capabilities
DisplayError PopulateHWCapabilities();
- int ParseLine(char *input, char *token[], int max_token, int *count);
+ int ParseLine(char *input, char *token[], const uint32_t max_token, uint32_t *count);
+
+ // HDMI Related Functions
+ bool EnableHotPlugDetection(int enable);
+ int GetHDMIModeCount();
+ bool MapHDMIDisplayTiming(const msm_hdmi_mode_timing_info *mode, fb_var_screeninfo *info);
+ void ResetHDMIModes();
// Pointers to system calls which are either mapped to actual system call or virtual driver.
int (*ioctl_)(int, int, ...);
@@ -138,9 +147,12 @@
int (*close_)(int);
int (*poll_)(struct pollfd *, nfds_t, int);
ssize_t (*pread_)(int, void *, size_t, off_t);
- FILE* (*fopen_)( const char *fname, const char *mode );;
+ FILE* (*fopen_)( const char *fname, const char *mode);
int (*fclose_)(FILE* fileptr);
ssize_t (*getline_)(char **lineptr, size_t *linelen, FILE *stream);
+ ssize_t (*read_)(int fd, void *buf, size_t count);
+ ssize_t (*write_)(int fd, const void *buf, size_t count);
+
// Store the Device EventHandlers - used for callback
HWEventHandler *event_handler_[kNumPhysicalDisplays];
@@ -153,6 +165,11 @@
int fb_node_index_[kDeviceMax];
const char* fb_path_;
PanelInfo pri_panel_info_;
+ bool hotplug_enabled_;
+ uint32_t hdmi_mode_count_;
+ uint32_t hdmi_modes_[256];
+ // Holds the hdmi timing information. Ex: resolution, fps etc.,
+ msm_hdmi_mode_timing_info *supported_video_modes_;
};
} // namespace sde
diff --git a/displayengine/libs/core/hw_interface.h b/displayengine/libs/core/hw_interface.h
index 6748538..84870b8 100644
--- a/displayengine/libs/core/hw_interface.h
+++ b/displayengine/libs/core/hw_interface.h
@@ -66,6 +66,9 @@
uint64_t max_bandwidth_low;
uint64_t max_bandwidth_high;
uint32_t max_mixer_width;
+ uint32_t max_pipe_bw;
+ uint32_t max_sde_clk;
+ float clk_fudge_factor;
struct SplitInfo {
uint32_t left_split;
uint32_t right_split;
@@ -84,7 +87,8 @@
num_cursor_pipe(0), num_blending_stages(0), num_rotator(0), num_control(0),
num_mixer_to_disp(0), smp_total(0), smp_size(0), num_smp_per_pipe(0), max_scale_up(0),
max_scale_down(0), max_bandwidth_low(0), max_bandwidth_high(0), max_mixer_width(2048),
- has_bwc(false), has_decimation(false), has_macrotile(false), has_rotator_downscale(false),
+ max_pipe_bw(0), max_sde_clk(0), clk_fudge_factor(1.0f), has_bwc(false),
+ has_decimation(false), has_macrotile(false), has_rotator_downscale(false),
has_non_scalar_rgb(false), is_src_split(false), always_src_split(false) { }
};
@@ -92,8 +96,9 @@
uint32_t pipe_id;
LayerRect src_roi;
LayerRect dst_roi;
+ uint8_t decimation;
- HWPipeInfo() : pipe_id(0) { }
+ HWPipeInfo() : pipe_id(0), decimation(1) { }
};
struct HWLayerConfig {
@@ -135,7 +140,8 @@
virtual DisplayError Close(Handle device) = 0;
virtual DisplayError GetNumDisplayAttributes(Handle device, uint32_t *count) = 0;
virtual DisplayError GetDisplayAttributes(Handle device,
- HWDisplayAttributes *display_attributes, uint32_t mode) = 0;
+ HWDisplayAttributes *display_attributes, uint32_t index) = 0;
+ virtual DisplayError SetDisplayAttributes(Handle device, uint32_t index) = 0;
virtual DisplayError PowerOn(Handle device) = 0;
virtual DisplayError PowerOff(Handle device) = 0;
virtual DisplayError Doze(Handle device) = 0;
diff --git a/displayengine/libs/core/res_config.cpp b/displayengine/libs/core/res_config.cpp
index e1b5320..73ea4a4 100755
--- a/displayengine/libs/core/res_config.cpp
+++ b/displayengine/libs/core/res_config.cpp
@@ -230,5 +230,23 @@
dst_rect->bottom = floorf(src_rect.bottom);
}
+void ResManager::SetDecimationFactor(HWPipeInfo *pipe) {
+ float max_down_scale = FLOAT(hw_res_info_.max_scale_down);
+ float src_h = pipe->src_roi.bottom - pipe->src_roi.top;
+ float dst_h = pipe->dst_roi.bottom - pipe->dst_roi.top;
+ float down_scale = src_h / dst_h;
+ pipe->decimation = 1;
+
+ if (!hw_res_info_.has_decimation || (down_scale <= max_down_scale))
+ return;
+
+ // Decimation is the remaining downscale factor after doing max SDE downscale.
+ // In SDE, decimation is supported in powers of 2.
+ // For ex: If a pipe needs downscale of 8 but max_down_scale is 4
+ // So decimation = powf(2.0, ceilf(log2f(8) - log2f(4))) = powf(2.0, 1.0) = 2
+ float decimation_factor = ceilf(log2f(down_scale) - log2f(max_down_scale));
+ pipe->decimation = UINT8(powf(2.0f, decimation_factor));
+}
+
} // namespace sde
diff --git a/displayengine/libs/core/res_manager.cpp b/displayengine/libs/core/res_manager.cpp
index ee1b25f..1ccb410 100755
--- a/displayengine/libs/core/res_manager.cpp
+++ b/displayengine/libs/core/res_manager.cpp
@@ -231,12 +231,15 @@
}
src_pipes_[left_index].reserved = true;
+ SetDecimationFactor(pipe_info);
pipe_info = &hw_layers->config[i].right_pipe;
if (pipe_info->pipe_id == 0) {
// assign single pipe
hw_layers->config[i].left_pipe.pipe_id = src_pipes_[left_index].mdss_pipe_id;
src_pipes_[left_index].at_right = false;
+ hw_layers->config[i].is_right_pipe = false;
+ src_pipes_[left_index].at_right = false;
continue;
}
@@ -260,6 +263,12 @@
src_pipes_[left_index].reserved = true;
src_pipes_[left_index].at_right = false;
hw_layers->config[i].left_pipe.pipe_id = src_pipes_[left_index].mdss_pipe_id;
+ SetDecimationFactor(pipe_info);
+ }
+
+ if (!CheckBandwidth(display_resource_ctx, hw_layers)) {
+ DLOGV_IF(kTagResources, "Bandwidth check failed!");
+ goto Acquire_failed;
}
return kErrorNone;
@@ -270,6 +279,212 @@
return kErrorResources;
}
+bool ResManager::CheckBandwidth(DisplayResourceContext *display_ctx, HWLayers *hw_layers) {
+ float max_pipe_bw = FLOAT(hw_res_info_.max_pipe_bw) / 1000000; // KBps to GBps
+ float max_sde_clk = FLOAT(hw_res_info_.max_sde_clk) / 1000000; // Hz to MHz
+ const struct HWLayersInfo &layer_info = hw_layers->info;
+
+ float left_pipe_bw[kMaxSDELayers] = {0};
+ float right_pipe_bw[kMaxSDELayers] = {0};
+ float left_max_clk = 0;
+ float right_max_clk = 0;
+
+ for (uint32_t i = 0; i < layer_info.count; i++) {
+ Layer &layer = layer_info.stack->layers[layer_info.index[i]];
+ float bpp = GetBpp(layer.input_buffer->format);
+ uint32_t left_id = hw_layers->config[i].left_pipe.pipe_id;
+ uint32_t right_id = hw_layers->config[i].right_pipe.pipe_id;
+
+ left_pipe_bw[i] = left_id ? GetPipeBw(display_ctx, &hw_layers->config[i].left_pipe, bpp) : 0;
+ right_pipe_bw[i] = right_id ? GetPipeBw(display_ctx, &hw_layers->config[i].right_pipe, bpp) : 0;
+
+ if ((left_pipe_bw[i] > max_pipe_bw) || (right_pipe_bw[i] > max_pipe_bw)) {
+ DLOGV_IF(kTagResources, "Pipe bandwidth exceeds limit for layer index = %d", i);
+ return false;
+ }
+
+ float left_clk = left_id ? GetClockForPipe(display_ctx, &hw_layers->config[i].left_pipe) : 0;
+ float right_clk = right_id ? GetClockForPipe(display_ctx, &hw_layers->config[i].right_pipe) : 0;
+
+ left_max_clk = MAX(left_clk, left_max_clk);
+ right_max_clk = MAX(right_clk, right_max_clk);
+ }
+
+ float left_mixer_bw = GetOverlapBw(hw_layers, left_pipe_bw, true);
+ float right_mixer_bw = GetOverlapBw(hw_layers, right_pipe_bw, false);
+ float display_bw = left_mixer_bw + right_mixer_bw;
+
+ // Check system bandwidth (nth External + max(nth, n-1th) Primary)
+ if (display_ctx->hw_block_id == kHWPrimary) {
+ display_bw = MAX(display_bw, last_primary_bw_);
+ last_primary_bw_ = left_mixer_bw + right_mixer_bw;
+ }
+
+ // If system has Video mode panel, use max_bandwidth_low, else use max_bandwidth_high
+ if ((display_bw + bw_claimed_) > (hw_res_info_.max_bandwidth_low / 1000000)) {
+ DLOGV_IF(kTagResources, "Overlap bandwidth exceeds limit!");
+ return false;
+ }
+
+ // Max clock requirement of display
+ float display_clk = MAX(left_max_clk, right_max_clk);
+
+ // Check max clock requirement of system
+ float system_clk = MAX(display_clk, clk_claimed_);
+
+ // Apply fudge factor to consider in-efficieny
+ if ((system_clk * hw_res_info_.clk_fudge_factor) > max_sde_clk) {
+ DLOGV_IF(kTagResources, "Clock requirement exceeds limit!");
+ return false;
+ }
+
+ // If Primary display, reset claimed bw & clk for next cycle
+ if (display_ctx->hw_block_id == kHWPrimary) {
+ bw_claimed_ = 0.0f;
+ clk_claimed_ = 0.0f;
+ } else {
+ bw_claimed_ = display_bw;
+ clk_claimed_ = display_clk;
+ }
+
+ return true;
+}
+
+float ResManager::GetPipeBw(DisplayResourceContext *display_ctx, HWPipeInfo *pipe, float bpp) {
+ HWDisplayAttributes &display_attributes = display_ctx->display_attributes;
+ float src_w = pipe->src_roi.right - pipe->src_roi.left;
+ float src_h = pipe->src_roi.bottom - pipe->src_roi.top;
+ float dst_h = pipe->dst_roi.bottom - pipe->dst_roi.top;
+
+ // Adjust src_h with pipe decimation
+ src_h /= FLOAT(pipe->decimation);
+
+ float bw = src_w * src_h * bpp * display_attributes.fps;
+
+ // Consider panel dimension
+ // (v_total / v_active) * (v_active / dst_h)
+ bw *= FLOAT(display_attributes.v_total) / dst_h;
+
+ // Bandwidth in GBps
+ return (bw / 1000000000.0f);
+}
+
+float ResManager::GetClockForPipe(DisplayResourceContext *display_ctx, HWPipeInfo *pipe) {
+ HWDisplayAttributes &display_attributes = display_ctx->display_attributes;
+ float v_total = FLOAT(display_attributes.v_total);
+ float fps = display_attributes.fps;
+
+ float src_h = pipe->src_roi.bottom - pipe->src_roi.top;
+ float dst_h = pipe->dst_roi.bottom - pipe->dst_roi.top;
+ float dst_w = pipe->dst_roi.right - pipe->dst_roi.left;
+
+ // Adjust src_h with pipe decimation
+ src_h /= FLOAT(pipe->decimation);
+
+ // SDE Clock requirement in MHz
+ float clk = (dst_w * v_total * fps) / 1000000.0f;
+
+ // Consider down-scaling
+ if (src_h > dst_h)
+ clk *= (src_h / dst_h);
+
+ return clk;
+}
+
+float ResManager::GetOverlapBw(HWLayers *hw_layers, float *pipe_bw, bool left_mixer) {
+ uint32_t count = hw_layers->info.count;
+ float overlap_bw[count][count];
+ float overall_max = 0;
+
+ memset(overlap_bw, 0, sizeof(overlap_bw));
+
+ // Algorithm:
+ // 1.Create an 'n' by 'n' sized 2D array, overlap_bw[n][n] (n = # of layers).
+ // 2.Get overlap_bw between two layers, i and j, and account for other overlaps (prev_max) if any.
+ // This will fill the bottom-left half of the array including diagonal (0 <= i < n, 0 <= j <= i)
+ // {1. pipe_bw[i], where i == j
+ // overlap_bw[i][j] = {2. 0, where i != j && !Overlap(i, j)
+ // {3. pipe_bw[i] + pipe_bw[j] + prev_max, where i != j && Overlap(i, j)
+ //
+ // Overlap(i, j) = !(bottom_i <= top_j || top_i >= bottom_j)
+ // prev_max = max(prev_max, overlap_bw[j, k]), where 0 <= k < j and prev_max initially 0
+ // prev_max = prev_max ? (prev_max - pipe_bw[j]) : 0; (to account for "double counting")
+ // 3.Get the max value in 2D array, overlap_bw[n][n], for the final overall_max bandwidth.
+ // overall_max = max(overlap_bw[i, j]), where 0 <= i < n, 0 <= j <= i
+
+ for (uint32_t i = 0; i < count; i++) {
+ HWPipeInfo &pipe1 = left_mixer ? hw_layers->config[i].left_pipe :
+ hw_layers->config[i].right_pipe;
+
+ // Non existing pipe never overlaps
+ if (pipe_bw[i] == 0)
+ continue;
+
+ float top1 = pipe1.dst_roi.top;
+ float bottom1 = pipe1.dst_roi.bottom;
+ float row_max = 0;
+
+ for (uint32_t j = 0; j <= i; j++) {
+ HWPipeInfo &pipe2 = left_mixer ? hw_layers->config[j].left_pipe :
+ hw_layers->config[j].right_pipe;
+
+ if ((pipe_bw[j] == 0) || (i == j)) {
+ overlap_bw[i][j] = pipe_bw[j];
+ row_max = MAX(pipe_bw[j], row_max);
+ continue;
+ }
+
+ float top2 = pipe2.dst_roi.top;
+ float bottom2 = pipe2.dst_roi.bottom;
+
+ if ((bottom1 <= top2) || (top1 >= bottom2)) {
+ overlap_bw[i][j] = 0;
+ continue;
+ }
+
+ overlap_bw[i][j] = pipe_bw[i] + pipe_bw[j];
+
+ float prev_max = 0;
+ for (uint32_t k = 0; k < j; k++) {
+ if (overlap_bw[j][k])
+ prev_max = MAX(overlap_bw[j][k], prev_max);
+ }
+ overlap_bw[i][j] += (prev_max > 0) ? (prev_max - pipe_bw[j]) : 0;
+ row_max = MAX(overlap_bw[i][j], row_max);
+ }
+
+ overall_max = MAX(row_max, overall_max);
+ }
+
+ return overall_max;
+}
+
+float ResManager::GetBpp(LayerBufferFormat format) {
+ switch (format) {
+ case kFormatARGB8888:
+ case kFormatRGBA8888:
+ case kFormatBGRA8888:
+ case kFormatXRGB8888:
+ case kFormatRGBX8888:
+ case kFormatBGRX8888:
+ return 4.0f;
+ case kFormatRGB888:
+ return 3.0f;
+ case kFormatRGB565:
+ case kFormatYCbCr422Packed:
+ return 2.0f;
+ case kFormatYCbCr420Planar:
+ case kFormatYCrCb420Planar:
+ case kFormatYCbCr420SemiPlanar:
+ case kFormatYCrCb420SemiPlanar:
+ case kFormatYCbCr420SemiPlanarVenus:
+ return 1.5f;
+ default:
+ DLOGE("GetBpp: Invalid buffer format: %x", format);
+ return 0.0f;
+ }
+}
+
void ResManager::PostCommit(Handle display_ctx, HWLayers *hw_layers) {
DisplayResourceContext *display_resource_ctx =
reinterpret_cast<DisplayResourceContext *>(display_ctx);
diff --git a/displayengine/libs/core/res_manager.h b/displayengine/libs/core/res_manager.h
index c4d425b..ab1c9c7 100644
--- a/displayengine/libs/core/res_manager.h
+++ b/displayengine/libs/core/res_manager.h
@@ -131,6 +131,12 @@
const LayerRect &scissor, const LayerTransform &transform);
bool IsNonIntegralSrcCrop(const LayerRect &crop);
void IntegerizeRect(LayerRect *dst_rect, const LayerRect &src_rect);
+ bool CheckBandwidth(DisplayResourceContext *display_ctx, HWLayers *hw_layers);
+ float GetPipeBw(DisplayResourceContext *display_ctx, HWPipeInfo *pipe, float bpp);
+ float GetClockForPipe(DisplayResourceContext *display_ctx, HWPipeInfo *pipe);
+ float GetOverlapBw(HWLayers *hw_layers, float *pipe_bw, bool left_mixer);
+ void SetDecimationFactor(HWPipeInfo *pipe);
+ float GetBpp(LayerBufferFormat format);
template <class T>
inline void Swap(T &a, T &b) {
@@ -148,6 +154,9 @@
SourcePipe *rgb_pipes_;
SourcePipe *dma_pipes_;
bool frame_start_;
+ float bw_claimed_; // Bandwidth claimed by other display
+ float clk_claimed_; // Clock claimed by other display
+ float last_primary_bw_;
};
} // namespace sde
diff --git a/displayengine/libs/core/strategy_default.cpp b/displayengine/libs/core/strategy_default.cpp
index 6963c6c..5c0c66f 100755
--- a/displayengine/libs/core/strategy_default.cpp
+++ b/displayengine/libs/core/strategy_default.cpp
@@ -31,17 +31,53 @@
namespace sde {
-DisplayError StrategyDefault::GetNextStrategy(StrategyConstraints *constraints,
- HWLayersInfo *hw_layers_info) {
- if (hw_layers_info->flags) {
- DLOGW("All strategies exhausted.");
- return kErrorUndefined;
+StrategyDefault::StrategyDefault() : hw_layers_info_(NULL) {
+}
+
+DisplayError StrategyDefault::CreateStrategyInterface(uint16_t version,
+ StrategyInterface **interface) {
+ StrategyDefault *strategy_default = new StrategyDefault();
+
+ if (!strategy_default) {
+ return kErrorMemory;
}
+ *interface = strategy_default;
+
+ return kErrorNone;
+}
+
+DisplayError StrategyDefault::DestroyStrategyInterface(StrategyInterface *interface) {
+ StrategyDefault *strategy_default = static_cast<StrategyDefault *>(interface);
+
+ if (!strategy_default) {
+ return kErrorParameters;
+ }
+
+ delete strategy_default;
+
+ return kErrorNone;
+}
+
+DisplayError StrategyDefault::Start(HWLayersInfo *hw_layers_info) {
+ if (!hw_layers_info) {
+ return kErrorParameters;
+ }
+
+ hw_layers_info_ = hw_layers_info;
+
+ return kErrorNone;
+}
+
+DisplayError StrategyDefault::Stop() {
+ return kErrorNone;
+}
+
+DisplayError StrategyDefault::GetNextStrategy(StrategyConstraints *constraints) {
// Mark all layers for GPU composition. Find GPU target buffer and store its index for programming
// the hardware.
- LayerStack *layer_stack = hw_layers_info->stack;
- uint32_t &hw_layer_count = hw_layers_info->count;
+ LayerStack *layer_stack = hw_layers_info_->stack;
+ uint32_t &hw_layer_count = hw_layers_info_->count;
hw_layer_count = 0;
for (uint32_t i = 0; i < layer_stack->layer_count; i++) {
@@ -49,7 +85,7 @@
if (composition != kCompositionGPUTarget) {
composition = kCompositionGPU;
} else {
- hw_layers_info->index[hw_layer_count++] = i;
+ hw_layers_info_->index[hw_layer_count++] = i;
}
}
@@ -58,8 +94,6 @@
return kErrorParameters;
}
- hw_layers_info->flags = 1;
-
return kErrorNone;
}
diff --git a/displayengine/libs/core/strategy_default.h b/displayengine/libs/core/strategy_default.h
index c4e10f4..94db9e9 100644
--- a/displayengine/libs/core/strategy_default.h
+++ b/displayengine/libs/core/strategy_default.h
@@ -32,10 +32,17 @@
class StrategyDefault : public StrategyInterface {
public:
- virtual DisplayError GetNextStrategy(StrategyConstraints *constraints,
- HWLayersInfo *hw_layers_info);
+ StrategyDefault();
+
+ static DisplayError CreateStrategyInterface(uint16_t version, StrategyInterface **interface);
+ static DisplayError DestroyStrategyInterface(StrategyInterface *interface);
+
+ virtual DisplayError Start(HWLayersInfo *hw_layers_info);
+ virtual DisplayError GetNextStrategy(StrategyConstraints *constraints);
+ virtual DisplayError Stop();
private:
+ HWLayersInfo *hw_layers_info_;
};
} // namespace sde
diff --git a/displayengine/libs/hwc/hwc_display.cpp b/displayengine/libs/hwc/hwc_display.cpp
index 801c0da..7827af2 100644
--- a/displayengine/libs/hwc/hwc_display.cpp
+++ b/displayengine/libs/hwc/hwc_display.cpp
@@ -84,10 +84,32 @@
return 0;
}
-int HWCDisplay::Blank(int blank) {
- DLOGI("blank = %d, display = %d", blank, id_);
- DisplayState state = blank ? kStateOff : kStateOn;
- return SetState(state);
+int HWCDisplay::SetPowerMode(int mode) {
+ DLOGI("display = %d, mode = %d", id_, mode);
+ DisplayState state = kStateOff;
+
+ switch (mode) {
+ case HWC_POWER_MODE_OFF:
+ state = kStateOff;
+ break;
+ case HWC_POWER_MODE_NORMAL:
+ state = kStateOn;
+ break;
+ case HWC_POWER_MODE_DOZE:
+ case HWC_POWER_MODE_DOZE_SUSPEND:
+ state = kStateDoze;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ DisplayError error = display_intf_->SetDisplayState(state);
+ if (UNLIKELY(error != kErrorNone)) {
+ DLOGE("Set state failed. Error = %d", error);
+ return -EINVAL;
+ }
+
+ return 0;
}
int HWCDisplay::GetDisplayConfigs(uint32_t *configs, size_t *num_configs) {
@@ -103,7 +125,7 @@
DisplayError error = kErrorNone;
DisplayConfigVariableInfo variable_config;
- error = display_intf_->GetConfig(&variable_config, 0);
+ error = display_intf_->GetConfig(config, &variable_config);
if (UNLIKELY(error != kErrorNone)) {
DLOGE("GetConfig variable info failed. Error = %d", error);
return -EINVAL;
@@ -127,7 +149,7 @@
values[i] = INT32(variable_config.y_dpi * 1000.0f);
break;
case HWC_DISPLAY_SECURE:
- values[i] = INT32(true); // For backward compatibility. All Physical displays are secure
+ values[i] = INT32(true); // For backward compatibility. All Physical displays are secure
break;
default:
DLOGW("Spurious attribute type = %d", attributes[i]);
@@ -138,11 +160,26 @@
return 0;
}
-int HWCDisplay::SetState(DisplayState state) {
- DisplayError error = display_intf_->SetDisplayState(state);
- if (UNLIKELY(error != kErrorNone)) {
- DLOGE("Set state failed. Error = %d", error);
- return -EINVAL;
+int HWCDisplay::GetActiveConfig() {
+ DisplayError error = kErrorNone;
+ uint32_t index = 0;
+
+ error = display_intf_->GetActiveConfig(&index);
+ if (error != kErrorNone) {
+ DLOGE("GetActiveConfig failed. Error = %d", error);
+ return -1;
+ }
+
+ return index;
+}
+
+int HWCDisplay::SetActiveConfig(int index) {
+ DisplayError error = kErrorNone;
+
+ error = display_intf_->SetActiveConfig(index);
+ if (error != kErrorNone) {
+ DLOGE("SetActiveConfig failed. Error = %d", error);
+ return -1;
}
return 0;
@@ -165,6 +202,11 @@
}
int HWCDisplay::AllocateLayerStack(hwc_display_contents_1_t *content_list) {
+ if (!content_list || !content_list->numHwLayers) {
+ DLOGW("Invalid content list");
+ return -EINVAL;
+ }
+
size_t num_hw_layers = content_list->numHwLayers;
// Allocate memory for a) total number of layers b) buffer handle for each layer c) number of
@@ -233,6 +275,11 @@
}
int HWCDisplay::PrepareLayerStack(hwc_display_contents_1_t *content_list) {
+ if (!content_list || !content_list->numHwLayers) {
+ DLOGW("Invalid content list");
+ return -EINVAL;
+ }
+
size_t num_hw_layers = content_list->numHwLayers;
if (num_hw_layers <= 1) {
return 0;
@@ -317,6 +364,11 @@
}
int HWCDisplay::CommitLayerStack(hwc_display_contents_1_t *content_list) {
+ if (!content_list || !content_list->numHwLayers) {
+ DLOGW("Invalid content list");
+ return -EINVAL;
+ }
+
size_t num_hw_layers = content_list->numHwLayers;
if (num_hw_layers <= 1) {
if (!num_hw_layers) {
diff --git a/displayengine/libs/hwc/hwc_display.h b/displayengine/libs/hwc/hwc_display.h
index 2ad1987..0ba9ca7 100644
--- a/displayengine/libs/hwc/hwc_display.h
+++ b/displayengine/libs/hwc/hwc_display.h
@@ -37,10 +37,11 @@
virtual int Prepare(hwc_display_contents_1_t *content_list) = 0;
virtual int Commit(hwc_display_contents_1_t *content_list) = 0;
virtual int EventControl(int event, int enable);
- virtual int Blank(int blank);
+ virtual int SetPowerMode(int mode);
virtual int GetDisplayConfigs(uint32_t *configs, size_t *num_configs);
virtual int GetDisplayAttributes(uint32_t config, const uint32_t *attributes, int32_t *values);
- int SetState(DisplayState state);
+ virtual int GetActiveConfig();
+ virtual int SetActiveConfig(int index);
protected:
// Maximum number of layers supported by display engine.
@@ -88,14 +89,14 @@
inline void SetBlending(const int32_t &source, LayerBlending *target);
inline int SetFormat(const int32_t &source, LayerBufferFormat *target);
- LayerStackMemory layer_stack_memory_;
- LayerStack layer_stack_;
- LayerStackCache layer_stack_cache_;
CoreInterface *core_intf_;
hwc_procs_t const **hwc_procs_;
DisplayType type_;
int id_;
DisplayInterface *display_intf_;
+ LayerStackMemory layer_stack_memory_;
+ LayerStack layer_stack_;
+ LayerStackCache layer_stack_cache_;
};
} // namespace sde
diff --git a/displayengine/libs/hwc/hwc_display_external.cpp b/displayengine/libs/hwc/hwc_display_external.cpp
old mode 100755
new mode 100644
index 386e713..468478b
--- a/displayengine/libs/hwc/hwc_display_external.cpp
+++ b/displayengine/libs/hwc/hwc_display_external.cpp
@@ -35,26 +35,16 @@
: HWCDisplay(core_intf, hwc_procs, kHDMI, HWC_DISPLAY_EXTERNAL) {
}
-int HWCDisplayExternal::Init() {
- return 0;
-}
-
-int HWCDisplayExternal::Deinit() {
- return 0;
-}
-
int HWCDisplayExternal::Prepare(hwc_display_contents_1_t *content_list) {
int status = 0;
status = AllocateLayerStack(content_list);
- if (UNLIKELY(status)) {
+ if (status) {
return status;
}
- layer_stack_.retire_fence_fd = -1;
-
status = PrepareLayerStack(content_list);
- if (UNLIKELY(status)) {
+ if (status) {
return status;
}
@@ -65,7 +55,7 @@
int status = 0;
status = HWCDisplay::CommitLayerStack(content_list);
- if (UNLIKELY(status)) {
+ if (status) {
return status;
}
@@ -74,11 +64,22 @@
return 0;
}
-int HWCDisplayExternal::PowerOn() {
- return 0;
-}
+int HWCDisplayExternal::GetDisplayConfigs(uint32_t *configs, size_t *num_configs) {
+ uint32_t config_count = 0;
+ if (*num_configs <= 0) {
+ return -EINVAL;
+ }
-int HWCDisplayExternal::PowerOff() {
+ display_intf_->GetNumVariableInfoConfigs(&config_count);
+ *num_configs = static_cast<size_t>(config_count);
+ if (*num_configs <= 0) {
+ return -EINVAL;
+ }
+
+ for (uint32_t i = 0; i < config_count; i++) {
+ configs[i] = i;
+ }
+
return 0;
}
diff --git a/displayengine/libs/hwc/hwc_display_external.h b/displayengine/libs/hwc/hwc_display_external.h
index 012c653..e268621 100644
--- a/displayengine/libs/hwc/hwc_display_external.h
+++ b/displayengine/libs/hwc/hwc_display_external.h
@@ -32,12 +32,9 @@
class HWCDisplayExternal : public HWCDisplay {
public:
explicit HWCDisplayExternal(CoreInterface *core_intf, hwc_procs_t const **hwc_procs);
- virtual int Init();
- virtual int Deinit();
virtual int Prepare(hwc_display_contents_1_t *content_list);
virtual int Commit(hwc_display_contents_1_t *content_list);
- virtual int PowerOn();
- virtual int PowerOff();
+ virtual int GetDisplayConfigs(uint32_t *configs, size_t *num_configs);
};
} // namespace sde
diff --git a/displayengine/libs/hwc/hwc_display_primary.cpp b/displayengine/libs/hwc/hwc_display_primary.cpp
old mode 100755
new mode 100644
index 95dc97e..b282ba6
--- a/displayengine/libs/hwc/hwc_display_primary.cpp
+++ b/displayengine/libs/hwc/hwc_display_primary.cpp
@@ -35,26 +35,16 @@
: HWCDisplay(core_intf, hwc_procs, kPrimary, HWC_DISPLAY_PRIMARY) {
}
-int HWCDisplayPrimary::Init() {
- return HWCDisplay::Init();
-}
-
-int HWCDisplayPrimary::Deinit() {
- return HWCDisplay::Deinit();
-}
-
int HWCDisplayPrimary::Prepare(hwc_display_contents_1_t *content_list) {
int status = 0;
status = AllocateLayerStack(content_list);
- if (UNLIKELY(status)) {
+ if (status) {
return status;
}
- layer_stack_.retire_fence_fd = -1;
-
status = PrepareLayerStack(content_list);
- if (UNLIKELY(status)) {
+ if (status) {
return status;
}
@@ -65,7 +55,7 @@
int status = 0;
status = HWCDisplay::CommitLayerStack(content_list);
- if (UNLIKELY(status)) {
+ if (status) {
return status;
}
@@ -74,13 +64,5 @@
return 0;
}
-int HWCDisplayPrimary::PowerOn() {
- return SetState(kStateOn);
-}
-
-int HWCDisplayPrimary::PowerOff() {
- return SetState(kStateOff);
-}
-
} // namespace sde
diff --git a/displayengine/libs/hwc/hwc_display_primary.h b/displayengine/libs/hwc/hwc_display_primary.h
index cd8ae0f..4e9e93f 100644
--- a/displayengine/libs/hwc/hwc_display_primary.h
+++ b/displayengine/libs/hwc/hwc_display_primary.h
@@ -32,12 +32,8 @@
class HWCDisplayPrimary : public HWCDisplay {
public:
explicit HWCDisplayPrimary(CoreInterface *core_intf, hwc_procs_t const **hwc_procs);
- virtual int Init();
- virtual int Deinit();
virtual int Prepare(hwc_display_contents_1_t *content_list);
virtual int Commit(hwc_display_contents_1_t *content_list);
- virtual int PowerOn();
- virtual int PowerOff();
};
} // namespace sde
diff --git a/displayengine/libs/hwc/hwc_display_virtual.cpp b/displayengine/libs/hwc/hwc_display_virtual.cpp
index 3ac2376..88cd073 100755
--- a/displayengine/libs/hwc/hwc_display_virtual.cpp
+++ b/displayengine/libs/hwc/hwc_display_virtual.cpp
@@ -35,14 +35,6 @@
: HWCDisplay(core_intf, hwc_procs, kVirtual, HWC_DISPLAY_VIRTUAL) {
}
-int HWCDisplayVirtual::Init() {
- return 0;
-}
-
-int HWCDisplayVirtual::Deinit() {
- return 0;
-}
-
int HWCDisplayVirtual::Prepare(hwc_display_contents_1_t *content_list) {
return 0;
}
@@ -51,13 +43,5 @@
return 0;
}
-int HWCDisplayVirtual::PowerOn() {
- return 0;
-}
-
-int HWCDisplayVirtual::PowerOff() {
- return 0;
-}
-
} // namespace sde
diff --git a/displayengine/libs/hwc/hwc_display_virtual.h b/displayengine/libs/hwc/hwc_display_virtual.h
index 6159425..796ed32 100644
--- a/displayengine/libs/hwc/hwc_display_virtual.h
+++ b/displayengine/libs/hwc/hwc_display_virtual.h
@@ -32,12 +32,8 @@
class HWCDisplayVirtual : public HWCDisplay {
public:
explicit HWCDisplayVirtual(CoreInterface *core_intf, hwc_procs_t const **hwc_procs);
- virtual int Init();
- virtual int Deinit();
virtual int Prepare(hwc_display_contents_1_t *content_list);
virtual int Commit(hwc_display_contents_1_t *content_list);
- virtual int PowerOn();
- virtual int PowerOff();
};
} // namespace sde
diff --git a/displayengine/libs/hwc/hwc_session.cpp b/displayengine/libs/hwc/hwc_session.cpp
old mode 100755
new mode 100644
index 64cd7e1..3f99a23
--- a/displayengine/libs/hwc/hwc_session.cpp
+++ b/displayengine/libs/hwc/hwc_session.cpp
@@ -25,6 +25,9 @@
#include <core/dump_interface.h>
#include <utils/constants.h>
#include <utils/String16.h>
+#include <hardware_legacy/uevent.h>
+#include <sys/resource.h>
+#include <sys/prctl.h>
#include <binder/Parcel.h>
#include <QService.h>
@@ -53,20 +56,24 @@
Locker HWCSession::locker_;
-HWCSession::HWCSession(const hw_module_t *module) : core_intf_(NULL), hwc_procs_(NULL) {
+HWCSession::HWCSession(const hw_module_t *module) : core_intf_(NULL), hwc_procs_(NULL),
+ display_primary_(NULL), display_external_(NULL), hotplug_thread_exit_(false),
+ hotplug_thread_name_("HWC_HotPlugThread") {
hwc_composer_device_1_t::common.tag = HARDWARE_DEVICE_TAG;
- hwc_composer_device_1_t::common.version = HWC_DEVICE_API_VERSION_1_3;
+ 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);
hwc_composer_device_1_t::common.close = Close;
hwc_composer_device_1_t::prepare = Prepare;
hwc_composer_device_1_t::set = Set;
hwc_composer_device_1_t::eventControl = EventControl;
- hwc_composer_device_1_t::blank = Blank;
+ hwc_composer_device_1_t::setPowerMode = SetPowerMode;
hwc_composer_device_1_t::query = Query;
hwc_composer_device_1_t::registerProcs = RegisterProcs;
hwc_composer_device_1_t::dump = Dump;
hwc_composer_device_1_t::getDisplayConfigs = GetDisplayConfigs;
hwc_composer_device_1_t::getDisplayAttributes = GetDisplayAttributes;
+ hwc_composer_device_1_t::getActiveConfig = GetActiveConfig;
+ hwc_composer_device_1_t::setActiveConfig = SetActiveConfig;
}
int HWCSession::Init() {
@@ -86,40 +93,50 @@
}
DisplayError error = CoreInterface::CreateCore(this, HWCLogHandler::Get(), &core_intf_);
- if (UNLIKELY(error != kErrorNone)) {
+ if (error != kErrorNone) {
DLOGE("Display core initialization failed. Error = %d", error);
return -EINVAL;
}
// Create and power on primary display
display_primary_ = new HWCDisplayPrimary(core_intf_, &hwc_procs_);
- if (UNLIKELY(!display_primary_)) {
+ if (!display_primary_) {
CoreInterface::DestroyCore();
return -ENOMEM;
}
status = display_primary_->Init();
- if (UNLIKELY(status)) {
+ if (status) {
CoreInterface::DestroyCore();
delete display_primary_;
return status;
}
- status = display_primary_->PowerOn();
- if (UNLIKELY(status)) {
- CoreInterface::DestroyCore();
+ status = display_primary_->SetPowerMode(HWC_POWER_MODE_NORMAL);
+ if (status) {
display_primary_->Deinit();
delete display_primary_;
+ CoreInterface::DestroyCore();
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_);
+ display_primary_->Deinit();
+ delete display_primary_;
+ CoreInterface::DestroyCore();
+ return -errno;
+ }
+
return 0;
}
int HWCSession::Deinit() {
- display_primary_->PowerOff();
+ display_primary_->SetPowerMode(HWC_POWER_MODE_OFF);
display_primary_->Deinit();
delete display_primary_;
+ hotplug_thread_exit_ = true;
+ pthread_join(hotplug_thread_, NULL);
DisplayError error = CoreInterface::DestroyCore();
if (error != kErrorNone) {
@@ -130,19 +147,19 @@
}
int HWCSession::Open(const hw_module_t *module, const char *name, hw_device_t **device) {
- if (UNLIKELY(!module || !name || !device)) {
+ if (!module || !name || !device) {
DLOGE("Invalid parameters.");
return -EINVAL;
}
- if (LIKELY(!strcmp(name, HWC_HARDWARE_COMPOSER))) {
+ if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {
HWCSession *hwc_session = new HWCSession(module);
- if (UNLIKELY(!hwc_session)) {
+ if (!hwc_session) {
return -ENOMEM;
}
int status = hwc_session->Init();
- if (UNLIKELY(status != 0)) {
+ if (status != 0) {
delete hwc_session;
return status;
}
@@ -155,7 +172,7 @@
}
int HWCSession::Close(hw_device_t *device) {
- if (UNLIKELY(!device)) {
+ if (!device) {
return -EINVAL;
}
@@ -172,74 +189,72 @@
hwc_display_contents_1_t **displays) {
SCOPE_LOCK(locker_);
- if (UNLIKELY(!device || !displays)) {
+ if (!device || !displays) {
return -EINVAL;
}
HWCSession *hwc_session = static_cast<HWCSession *>(device);
- int status = -EINVAL;
- for (size_t i = 0; i < num_displays; i++) {
+ for (ssize_t i = (num_displays-1); i >= 0; i--) {
hwc_display_contents_1_t *content_list = displays[i];
- if (UNLIKELY(!content_list || !content_list->numHwLayers)) {
- DLOGW("Invalid content list.");
- return -EINVAL;
- }
switch (i) {
case HWC_DISPLAY_PRIMARY:
- status = hwc_session->display_primary_->Prepare(content_list);
+ hwc_session->display_primary_->Prepare(content_list);
+ break;
+ case HWC_DISPLAY_EXTERNAL:
+ if (hwc_session->display_external_) {
+ hwc_session->display_external_->Prepare(content_list);
+ }
+ break;
+ case HWC_DISPLAY_VIRTUAL:
break;
default:
- status = -EINVAL;
- }
-
- if (UNLIKELY(!status)) {
break;
}
}
- return status;
+ // Return 0, else client will go into bad state
+ return 0;
}
int HWCSession::Set(hwc_composer_device_1 *device, size_t num_displays,
hwc_display_contents_1_t **displays) {
SCOPE_LOCK(locker_);
- if (UNLIKELY(!device || !displays)) {
+ if (!device || !displays) {
return -EINVAL;
}
HWCSession *hwc_session = static_cast<HWCSession *>(device);
- int status = -EINVAL;
for (size_t i = 0; i < num_displays; i++) {
hwc_display_contents_1_t *content_list = displays[i];
- if (UNLIKELY(!content_list || !content_list->numHwLayers)) {
- DLOGW("Invalid content list.");
- return -EINVAL;
- }
switch (i) {
case HWC_DISPLAY_PRIMARY:
- status = hwc_session->display_primary_->Commit(content_list);
+ hwc_session->display_primary_->Commit(content_list);
+ break;
+ case HWC_DISPLAY_EXTERNAL:
+ if (hwc_session->display_external_) {
+ hwc_session->display_external_->Commit(content_list);
+ }
+ break;
+ case HWC_DISPLAY_VIRTUAL:
break;
default:
- status = -EINVAL;
- }
-
- if (UNLIKELY(!status)) {
break;
}
}
- return status;
+ // Return 0, else client will go into bad state
+ return 0;
}
int HWCSession::EventControl(hwc_composer_device_1 *device, int disp, int event, int enable) {
SCOPE_LOCK(locker_);
- if (UNLIKELY(!device)) {
+ if (!device) {
return -EINVAL;
}
@@ -250,17 +265,22 @@
case HWC_DISPLAY_PRIMARY:
status = hwc_session->display_primary_->EventControl(event, enable);
break;
+ case HWC_DISPLAY_EXTERNAL:
+ if (hwc_session->display_external_) {
+ status = hwc_session->display_external_->EventControl(event, enable);
+ }
+ break;
default:
status = -EINVAL;
}
- return 0;
+ return status;
}
-int HWCSession::Blank(hwc_composer_device_1 *device, int disp, int blank) {
+int HWCSession::SetPowerMode(hwc_composer_device_1 *device, int disp, int mode) {
SCOPE_LOCK(locker_);
- if (UNLIKELY(!device)) {
+ if (!device) {
return -EINVAL;
}
@@ -269,7 +289,12 @@
switch (disp) {
case HWC_DISPLAY_PRIMARY:
- status = hwc_session->display_primary_->Blank(blank);
+ status = hwc_session->display_primary_->SetPowerMode(mode);
+ break;
+ case HWC_DISPLAY_EXTERNAL:
+ if (hwc_session->display_external_) {
+ status = hwc_session->display_external_->SetPowerMode(mode);
+ }
break;
default:
status = -EINVAL;
@@ -279,7 +304,7 @@
}
int HWCSession::Query(hwc_composer_device_1 *device, int param, int *value) {
- if (UNLIKELY(!device || !value)) {
+ if (!device || !value) {
return -EINVAL;
}
@@ -287,7 +312,7 @@
}
void HWCSession::RegisterProcs(hwc_composer_device_1 *device, hwc_procs_t const *procs) {
- if (UNLIKELY(!device || !procs)) {
+ if (!device || !procs) {
return;
}
@@ -298,7 +323,7 @@
void HWCSession::Dump(hwc_composer_device_1 *device, char *buffer, int length) {
SCOPE_LOCK(locker_);
- if (UNLIKELY(!device || !buffer || !length)) {
+ if (!device || !buffer || !length) {
return;
}
@@ -307,7 +332,7 @@
int HWCSession::GetDisplayConfigs(hwc_composer_device_1 *device, int disp, uint32_t *configs,
size_t *num_configs) {
- if (UNLIKELY(!device || !configs || !num_configs)) {
+ if (!device || !configs || !num_configs) {
return -EINVAL;
}
@@ -318,6 +343,11 @@
case HWC_DISPLAY_PRIMARY:
status = hwc_session->display_primary_->GetDisplayConfigs(configs, num_configs);
break;
+ case HWC_DISPLAY_EXTERNAL:
+ if (hwc_session->display_external_) {
+ status = hwc_session->display_external_->GetDisplayConfigs(configs, num_configs);
+ }
+ break;
default:
status = -EINVAL;
}
@@ -327,7 +357,7 @@
int HWCSession::GetDisplayAttributes(hwc_composer_device_1 *device, int disp, uint32_t config,
const uint32_t *attributes, int32_t *values) {
- if (UNLIKELY(!device || !attributes || !values)) {
+ if (!device || !attributes || !values) {
return -EINVAL;
}
@@ -338,6 +368,60 @@
case HWC_DISPLAY_PRIMARY:
status = hwc_session->display_primary_->GetDisplayAttributes(config, attributes, values);
break;
+ case HWC_DISPLAY_EXTERNAL:
+ if (hwc_session->display_external_) {
+ status = hwc_session->display_external_->GetDisplayAttributes(config, attributes, values);
+ }
+ break;
+ default:
+ status = -EINVAL;
+ }
+
+ return status;
+}
+
+int HWCSession::GetActiveConfig(hwc_composer_device_1 *device, int disp) {
+ if (!device) {
+ return -1;
+ }
+
+ HWCSession *hwc_session = static_cast<HWCSession *>(device);
+ int active_config = -1;
+
+ switch (disp) {
+ case HWC_DISPLAY_PRIMARY:
+ active_config = hwc_session->display_primary_->GetActiveConfig();
+ break;
+ case HWC_DISPLAY_EXTERNAL:
+ if (hwc_session->display_external_) {
+ active_config = hwc_session->display_external_->GetActiveConfig();
+ }
+ break;
+ default:
+ active_config = -1;
+ }
+
+ return active_config;
+}
+
+int HWCSession::SetActiveConfig(hwc_composer_device_1 *device, int disp, int index) {
+ if (!device) {
+ return -EINVAL;
+ }
+
+ HWCSession *hwc_session = static_cast<HWCSession *>(device);
+ int status = -EINVAL;
+
+ switch (disp) {
+ case HWC_DISPLAY_PRIMARY:
+ status = hwc_session->display_primary_->SetActiveConfig(index);
+ break;
+ case HWC_DISPLAY_EXTERNAL:
+ if (hwc_session->display_external_) {
+ // TODO(user): Uncomment it. HDMI does not support resolution change currently.
+ status = 0; // hwc_session->display_external_->SetActiveConfig(index);
+ }
+ break;
default:
status = -EINVAL;
}
@@ -390,6 +474,100 @@
DLOGW("type = %d is not supported", type);
}
}
+void* HWCSession::HWCHotPlugThread(void *context) {
+ if (context) {
+ return reinterpret_cast<HWCSession *>(context)->HWCHotPlugThreadHandler();
+ }
+
+ return NULL;
+}
+
+void* HWCSession::HWCHotPlugThreadHandler() {
+ static char uevent_data[PAGE_SIZE];
+ int length = 0;
+ prctl(PR_SET_NAME, hotplug_thread_name_, 0, 0, 0);
+ setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
+ if (!uevent_init()) {
+ DLOGE("Failed to init uevent");
+ pthread_exit(0);
+ return NULL;
+ }
+
+ while (!hotplug_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");
+ }
+ }
+ }
+ pthread_exit(0);
+
+ return NULL;
+}
+
+int HWCSession::GetHDMIConnectedState(const char *uevent_data, int length) {
+ const char* iterator_str = uevent_data;
+ while (((iterator_str - uevent_data) <= length) && (*iterator_str)) {
+ char* pstr = strstr(iterator_str, "SWITCH_STATE=");
+ if (pstr != NULL) {
+ return (atoi(iterator_str + strlen("SWITCH_STATE=")));
+ }
+ iterator_str += strlen(iterator_str) + 1;
+ }
+ return -1;
+}
+
+
+int HWCSession::HotPlugHandler(bool connected) {
+ if (!hwc_procs_) {
+ DLOGW("Ignore hotplug - hwc_proc not registered");
+ return -1;
+ }
+
+ if (connected) {
+ SCOPE_LOCK(locker_);
+ if (display_external_) {
+ DLOGE("HDMI already connected");
+ return -1;
+ }
+ // Create hdmi display
+ display_external_ = new HWCDisplayExternal(core_intf_, &hwc_procs_);
+ if (!display_external_) {
+ return -1;
+ }
+ int status = display_external_->Init();
+ if (status) {
+ delete display_external_;
+ display_external_ = NULL;
+ return -1;
+ }
+ } else {
+ SCOPE_LOCK(locker_);
+ if (!display_external_) {
+ DLOGE("HDMI not connected");
+ return -1;
+ }
+ display_external_->SetPowerMode(HWC_POWER_MODE_OFF);
+ display_external_->Deinit();
+ delete display_external_;
+ display_external_ = NULL;
+ }
+
+ // notify client and trigger a screen refresh
+ hwc_procs_->hotplug(hwc_procs_, HWC_DISPLAY_EXTERNAL, connected);
+ hwc_procs_->invalidate(hwc_procs_);
+
+ return 0;
+}
} // namespace sde
diff --git a/displayengine/libs/hwc/hwc_session.h b/displayengine/libs/hwc/hwc_session.h
index 9e37eed..488da9d 100644
--- a/displayengine/libs/hwc/hwc_session.h
+++ b/displayengine/libs/hwc/hwc_session.h
@@ -31,6 +31,7 @@
#include <IQClient.h>
#include "hwc_display_primary.h"
+#include "hwc_display_external.h"
namespace sde {
@@ -55,7 +56,7 @@
static int Set(hwc_composer_device_1 *device, size_t num_displays,
hwc_display_contents_1_t **displays);
static int EventControl(hwc_composer_device_1 *device, int disp, int event, int enable);
- static int Blank(hwc_composer_device_1 *device, int disp, int blank);
+ static int SetPowerMode(hwc_composer_device_1 *device, int disp, int mode);
static int Query(hwc_composer_device_1 *device, int param, int *value);
static void RegisterProcs(hwc_composer_device_1 *device, hwc_procs_t const *procs);
static void Dump(hwc_composer_device_1 *device, char *buffer, int length);
@@ -63,6 +64,14 @@
size_t *numConfigs);
static int GetDisplayAttributes(hwc_composer_device_1 *device, int disp, uint32_t config,
const uint32_t *attributes, int32_t *values);
+ 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);
+ int HotPlugHandler(bool connected);
// CoreEventHandler methods
virtual DisplayError Hotplug(const CoreEventHotplug &hotplug);
@@ -76,6 +85,10 @@
CoreInterface *core_intf_;
hwc_procs_t const *hwc_procs_;
HWCDisplayPrimary *display_primary_;
+ HWCDisplayExternal *display_external_;
+ pthread_t hotplug_thread_;
+ bool hotplug_thread_exit_;
+ const char *hotplug_thread_name_;
};
} // namespace sde
diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp
index da18c7b..e4624e0 100644
--- a/libcopybit/copybit.cpp
+++ b/libcopybit/copybit.cpp
@@ -505,7 +505,8 @@
int flags = 0;
private_handle_t* src_hnd = (private_handle_t*)src->handle;
- if(src_hnd != NULL && src_hnd->flags & private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH) {
+ if(src_hnd != NULL &&
+ (!(src_hnd->flags & private_handle_t::PRIV_FLAGS_CACHED))) {
flags |= MDP_BLIT_NON_CACHED;
}
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index 4167ae2..596ca77 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -76,6 +76,21 @@
return true;
}
+/* The default policy is to return cached buffers unless the client explicity
+ * sets the PRIVATE_UNCACHED flag or indicates that the buffer will be rarely
+ * read or written in software. Any combination with a _RARELY_ flag will be
+ * treated as uncached. */
+static bool useUncached(const int& usage) {
+ if((usage & GRALLOC_USAGE_PRIVATE_UNCACHED) or
+ ((usage & GRALLOC_USAGE_SW_WRITE_MASK) ==
+ GRALLOC_USAGE_SW_WRITE_RARELY) or
+ ((usage & GRALLOC_USAGE_SW_READ_MASK) ==
+ GRALLOC_USAGE_SW_READ_RARELY))
+ return true;
+
+ return false;
+}
+
//-------------- AdrenoMemInfo-----------------------//
AdrenoMemInfo::AdrenoMemInfo()
{
@@ -279,9 +294,6 @@
data.uncached = useUncached(usage);
data.allocType = 0;
- if(usage & GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP)
- ionFlags |= ION_HEAP(ION_SF_HEAP_ID);
-
if(usage & GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP)
ionFlags |= ION_HEAP(ION_SYSTEM_HEAP_ID);
@@ -292,6 +304,11 @@
if (usage & GRALLOC_USAGE_PRIVATE_MM_HEAP) {
ionFlags |= ION_HEAP(ION_CP_MM_HEAP_ID);
ionFlags |= ION_SECURE;
+#ifdef ION_FLAG_ALLOW_NON_CONTIG
+ if (!(usage & GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY)) {
+ ionFlags |= ION_FLAG_ALLOW_NON_CONTIG;
+ }
+#endif
} else {
// for targets/OEMs which do not need HW level protection
// do not set ion secure flag & MM heap. Fallback to IOMMU heap.
@@ -659,14 +676,3 @@
delete hnd;
}
-
-bool useUncached(const int& usage) {
- if(usage & GRALLOC_USAGE_PRIVATE_UNCACHED)
- return true;
-
- if(not (usage & (GRALLOC_USAGE_SW_WRITE_OFTEN |
- GRALLOC_USAGE_SW_READ_OFTEN)))
- return true;
-
- return false;
-}
diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp
index 9b98f1b..5533ffb 100644
--- a/libgralloc/gpu.cpp
+++ b/libgralloc/gpu.cpp
@@ -153,6 +153,17 @@
flags |= private_handle_t::PRIV_FLAGS_CPU_RENDERED;
}
+ if (usage & (GRALLOC_USAGE_HW_VIDEO_ENCODER |
+ GRALLOC_USAGE_HW_CAMERA_WRITE |
+ GRALLOC_USAGE_HW_RENDER |
+ GRALLOC_USAGE_HW_FB)) {
+ flags |= private_handle_t::PRIV_FLAGS_NON_CPU_WRITER;
+ }
+
+ if(false == data.uncached) {
+ flags |= private_handle_t::PRIV_FLAGS_CACHED;
+ }
+
flags |= data.allocType;
uint64_t eBaseAddr = (uint64_t)(eData.base) + eData.offset;
private_handle_t *hnd = new private_handle_t(data.fd, size, flags,
diff --git a/libgralloc/gr.h b/libgralloc/gr.h
index 37ee4e5..797d57e 100644
--- a/libgralloc/gr.h
+++ b/libgralloc/gr.h
@@ -71,10 +71,6 @@
void free_buffer(private_handle_t *hnd);
int getYUVPlaneInfo(private_handle_t* pHnd, struct android_ycbcr* ycbcr);
-// Use uncached for all scenarios except when the CPU needs to read or write
-// often
-bool useUncached(const int& usage);
-
/*****************************************************************************/
class Locker {
diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h
index d64914e..c5ecc42 100644
--- a/libgralloc/gralloc_priv.h
+++ b/libgralloc/gralloc_priv.h
@@ -40,8 +40,9 @@
/* SYSTEM heap comes from kernel vmalloc,
* can never be uncached, is not secured*/
GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP = GRALLOC_USAGE_PRIVATE_0,
- /* SF heap is used for application buffers, is not secured */
- GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP = GRALLOC_USAGE_PRIVATE_1,
+
+ /* GRALLOC_USAGE_PRIVATE_1 is unused */
+
/* IOMMU heap comes from manually allocated pages,
* can be cached/uncached, is not secured */
GRALLOC_USAGE_PRIVATE_IOMMU_HEAP = GRALLOC_USAGE_PRIVATE_2,
@@ -70,23 +71,19 @@
GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY = 0x00800000,
};
-enum {
- /* Gralloc perform enums
- */
- GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER = 1,
- // This will be deprecated from latest graphics drivers. This is kept
- // for those backward compatibility i.e., newer Display HAL + older graphics
- // libraries
- GRALLOC_MODULE_PERFORM_GET_STRIDE,
- GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE,
- GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE,
- GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES,
- GRALLOC_MODULE_PERFORM_GET_COLOR_SPACE_FROM_HANDLE,
- GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO,
-};
+/* define Gralloc perform */
+#define GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER 1
+// This will be used by the graphics drivers to know if certain features
+// are defined in this display HAL.
+// Ex: Newer GFX libraries + Older Display HAL
+#define GRALLOC_MODULE_PERFORM_GET_STRIDE 2
+#define GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE 3
+#define GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE 4
+#define GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES 5
+#define GRALLOC_MODULE_PERFORM_GET_COLOR_SPACE_FROM_HANDLE 6
+#define GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO 7
-#define GRALLOC_HEAP_MASK (GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP |\
- GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP |\
+#define GRALLOC_HEAP_MASK (GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP |\
GRALLOC_USAGE_PRIVATE_IOMMU_HEAP |\
GRALLOC_USAGE_PRIVATE_MM_HEAP |\
GRALLOC_USAGE_PRIVATE_ADSP_HEAP)
@@ -180,12 +177,9 @@
PRIV_FLAGS_USES_ION = 0x00000008,
PRIV_FLAGS_USES_ASHMEM = 0x00000010,
PRIV_FLAGS_NEEDS_FLUSH = 0x00000020,
- // Uncached memory or no CPU writers
- PRIV_FLAGS_DO_NOT_FLUSH = 0x00000040,
- PRIV_FLAGS_SW_LOCK = 0x00000080,
+ PRIV_FLAGS_NON_CPU_WRITER = 0x00000080,
PRIV_FLAGS_NONCONTIGUOUS_MEM = 0x00000100,
- // Set by HWC when storing the handle
- PRIV_FLAGS_HWC_LOCK = 0x00000200,
+ PRIV_FLAGS_CACHED = 0x00000200,
PRIV_FLAGS_SECURE_BUFFER = 0x00000400,
// For explicit synchronization
PRIV_FLAGS_UNSYNCHRONIZED = 0x00000800,
diff --git a/libgralloc/ionalloc.cpp b/libgralloc/ionalloc.cpp
index 23e225d..91a930c 100644
--- a/libgralloc/ionalloc.cpp
+++ b/libgralloc/ionalloc.cpp
@@ -77,12 +77,18 @@
ionAllocData.len = data.size;
ionAllocData.align = data.align;
ionAllocData.heap_id_mask = data.flags & ~ION_SECURE;
+#ifdef ION_FLAG_ALLOW_NON_CONTIG
+ ionAllocData.heap_id_mask &= (data.flags & ~ION_FLAG_ALLOW_NON_CONTIG);
+#endif
ionAllocData.flags = data.uncached ? 0 : ION_FLAG_CACHED;
// ToDo: replace usage of alloc data structure with
// ionallocdata structure.
if (data.flags & ION_SECURE)
ionAllocData.flags |= ION_SECURE;
-
+#ifdef ION_FLAG_ALLOW_NON_CONTIG
+ if (data.flags & ION_FLAG_ALLOW_NON_CONTIG)
+ ionAllocData.flags |= ION_FLAG_ALLOW_NON_CONTIG;
+#endif
err = open_device();
if (err)
return err;
diff --git a/libgralloc/mapper.cpp b/libgralloc/mapper.cpp
index 943e64f..bc98e07 100644
--- a/libgralloc/mapper.cpp
+++ b/libgralloc/mapper.cpp
@@ -237,36 +237,25 @@
pthread_mutex_unlock(lock);
}
if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION and
- not useUncached(usage)) {
- bool nonCPUWriters = usage & (
- GRALLOC_USAGE_HW_RENDER |
- GRALLOC_USAGE_HW_FB |
- GRALLOC_USAGE_HW_VIDEO_ENCODER |
- GRALLOC_USAGE_HW_CAMERA_WRITE);
-
+ hnd->flags & private_handle_t::PRIV_FLAGS_CACHED) {
//Invalidate if CPU reads in software and there are non-CPU
//writers. No need to do this for the metadata buffer as it is
//only read/written in software.
- //Corner case: If we reach here with a READ_RARELY, then there must
- //be a WRITE_OFTEN that caused caching to be used.
- if ((usage & GRALLOC_USAGE_SW_READ_MASK) and nonCPUWriters) {
+ if ((usage & GRALLOC_USAGE_SW_READ_MASK) and
+ (hnd->flags & private_handle_t::PRIV_FLAGS_NON_CPU_WRITER))
+ {
IMemAlloc* memalloc = getAllocator(hnd->flags) ;
err = memalloc->clean_buffer((void*)hnd->base,
hnd->size, hnd->offset, hnd->fd,
CACHE_INVALIDATE);
}
//Mark the buffer to be flushed after CPU write.
- //Corner case: If we reach here with a WRITE_RARELY, then there
- //must be a READ_OFTEN that caused caching to be used.
if (usage & GRALLOC_USAGE_SW_WRITE_MASK) {
hnd->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
}
}
}
- if(useUncached(usage))
- hnd->flags |= private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH;
-
return err;
}
@@ -314,9 +303,6 @@
hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
}
- if(hnd->flags & private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH)
- hnd->flags &= ~private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH;
-
return err;
}
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index c96eb1e..2bf421f 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -257,7 +257,8 @@
bool fbComp = false;
if (LIKELY(list && list->numHwLayers > 1) &&
(ctx->dpyAttr[dpy].isActive ||
- ctx->mHDMIDisplay->isHDMIPrimaryDisplay())) {
+ ctx->mHDMIDisplay->isHDMIPrimaryDisplay())
+ && !ctx->dpyAttr[dpy].isPause) {
// When HDMI is primary we should rely on the first valid
// draw call in order to activate the display
@@ -475,10 +476,11 @@
return -errno;
}
- if(mode == HWC_POWER_MODE_NORMAL) {
+ if(mode == HWC_POWER_MODE_NORMAL && !ctx->mHPDEnabled) {
// Enable HPD here, as during bootup POWER_MODE_NORMAL is set
// when SF is completely initialized
ctx->mHDMIDisplay->setHPD(1);
+ ctx->mHPDEnabled = true;
}
ctx->dpyAttr[dpy].isActive = not(mode == HWC_POWER_MODE_OFF);
@@ -585,7 +587,8 @@
ATRACE_CALL();
int ret = 0;
const int dpy = HWC_DISPLAY_PRIMARY;
- if (LIKELY(list) && ctx->dpyAttr[dpy].isActive) {
+ if (LIKELY(list) && ctx->dpyAttr[dpy].isActive
+ && !ctx->dpyAttr[dpy].isPause) {
size_t last = list->numHwLayers - 1;
hwc_layer_1_t *fbLayer = &list->hwLayers[last];
int fd = -1; //FenceFD from the Copybit(valid in async mode)
diff --git a/libhwcomposer/hwc_ad.cpp b/libhwcomposer/hwc_ad.cpp
index 7e96d97..b9cf5ce 100644
--- a/libhwcomposer/hwc_ad.cpp
+++ b/libhwcomposer/hwc_ad.cpp
@@ -134,7 +134,7 @@
const hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
private_handle_t *hnd = (private_handle_t *)layer->handle;
qdutils::MDPVersion& mdpHw = qdutils::MDPVersion::getInstance();
- if(hnd && hnd->width <= (int) mdpHw.getMaxMixerWidth()) {
+ if(hnd && hnd->width <= (int) mdpHw.getMaxPipeWidth()) {
mDoable = true;
}
}
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index 58cf374..08a4fb9 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -529,7 +529,7 @@
const uint32_t layerClock = getLayerClock(dstWidth, dstHeight, cropHeight);
const uint32_t mixerClock = lSplit;
- if((cropWidth > qdutils::MDPVersion::getInstance().getMaxMixerWidth()) or
+ if((cropWidth > qdutils::MDPVersion::getInstance().getMaxPipeWidth()) or
(primarySplitAlways and
(cropWidth > lSplit or layerClock > mixerClock))) {
destR = ov.getPipe(pipeSpecs);
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 975c195..a5bf0b5 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -26,6 +26,7 @@
#include "hwc_ad.h"
#include <overlayRotator.h>
#include "hwc_copybit.h"
+#include "qd_utils.h"
using namespace overlay;
using namespace qdutils;
@@ -48,6 +49,7 @@
bool MDPComp::sSrcSplitEnabled = false;
int MDPComp::sMaxSecLayers = 1;
bool MDPComp::enablePartialUpdateForMDP3 = false;
+bool MDPComp::sIsPartialUpdateActive = true;
MDPComp* MDPComp::getObject(hwc_context_t *ctx, const int& dpy) {
if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
sSrcSplitEnabled = true;
@@ -131,9 +133,7 @@
qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
- /* MDSS_MDP_STAGE_UNUSED and MDSS_MDP_STAGE_BASE are not available for MDP
- * composition. */
- sMaxPipesPerMixer = (int)mdpVersion.getBlendStages() - 2;
+ sMaxPipesPerMixer = (int)mdpVersion.getBlendStages();
if(property_get("persist.hwc.mdpcomp.maxpermixer", property, "-1") > 0) {
int val = atoi(property);
if(val >= 0)
@@ -192,6 +192,8 @@
enablePartialUpdateForMDP3 = true;
}
+ sIsPartialUpdateActive = getPartialUpdatePref(ctx);
+
return true;
}
@@ -214,24 +216,28 @@
ALOGE("%s: received empty data in timer callback", __FUNCTION__);
return;
}
- Locker::Autolock _l(ctx->mDrawLock);
+
+ ctx->mDrawLock.lock();
// Handle timeout event only if the previous composition is MDP or MIXED.
if(!sHandleTimeout) {
ALOGD_IF(isDebug(), "%s:Do not handle this timeout", __FUNCTION__);
+ ctx->mDrawLock.unlock();
return;
}
if(!ctx->proc) {
ALOGE("%s: HWC proc not registered", __FUNCTION__);
+ ctx->mDrawLock.unlock();
return;
}
sIdleFallBack = true;
+ ctx->mDrawLock.unlock();
/* Trigger SF to redraw the current frame */
ctx->proc->invalidate(ctx->proc);
}
void MDPComp::setMaxPipesPerMixer(const uint32_t value) {
qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
- uint32_t maxSupported = (int)mdpVersion.getBlendStages() - 2;
+ uint32_t maxSupported = (int)mdpVersion.getBlendStages();
if(value > maxSupported) {
ALOGW("%s: Input exceeds max value supported. Setting to"
"max value: %d", __FUNCTION__, maxSupported);
@@ -424,7 +430,7 @@
/* On targets that doesnt support Decimation (eg.,8x26)
* maximum downscale support is overlay pipe downscale.
*/
- if(crop_w > (int) mdpHw.getMaxMixerWidth() ||
+ if(crop_w > (int) mdpHw.getMaxPipeWidth() ||
w_dscale > maxMDPDownscale ||
h_dscale > maxMDPDownscale)
return false;
@@ -435,7 +441,7 @@
* 1. Src crop > Mixer limit on nonsplit MDPComp
* 2. exceeds maximum downscale limit
*/
- if(((crop_w > (int) mdpHw.getMaxMixerWidth()) &&
+ if(((crop_w > (int) mdpHw.getMaxPipeWidth()) &&
!sSrcSplitEnabled) ||
w_dscale > maxMDPDownscale ||
h_dscale > maxMDPDownscale) {
@@ -752,11 +758,11 @@
return false;
}
- // No Idle fall back, if secure display or secure RGB layers are present or
- // if there's only a single layer being composed
- if(sIdleFallBack && (!ctx->listStats[mDpy].secureUI &&
- !ctx->listStats[mDpy].secureRGBCount) &&
- (ctx->listStats[mDpy].numAppLayers != 1)) {
+ /* No Idle fall back if secure display or secure RGB layers are present
+ * or if there is only a single layer being composed */
+ if(sIdleFallBack && !ctx->listStats[mDpy].secureUI &&
+ !ctx->listStats[mDpy].secureRGBCount &&
+ (ctx->listStats[mDpy].numAppLayers > 1)) {
ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
return false;
}
@@ -1264,7 +1270,7 @@
hwc_display_contents_1_t* list){
if(!qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() ||
isSkipPresent(ctx, mDpy) || (list->flags & HWC_GEOMETRY_CHANGED) ||
- mDpy ) {
+ !sIsPartialUpdateActive || mDpy ) {
return false;
}
if(ctx->listStats[mDpy].secureUI)
@@ -1283,7 +1289,22 @@
hwc_display_contents_1_t* list, bool secureOnly) {
if(sSimulationFlags & MDPCOMP_AVOID_VIDEO_ONLY)
return false;
+
int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+ if(!isSecurePresent(ctx, mDpy)) {
+ /* Bail out if we are processing only secured video layers
+ * and we dont have any */
+ if(secureOnly) {
+ ALOGD_IF(isDebug(),"%s: No Secure Video Layers", __FUNCTION__);
+ return false;
+ }
+ /* No Idle fall back for secure video layers and if there is only
+ * single layer being composed. */
+ if(sIdleFallBack && (ctx->listStats[mDpy].numAppLayers > 1)) {
+ ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
+ return false;
+ }
+ }
mCurrentFrame.reset(numAppLayers);
mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
@@ -1295,13 +1316,6 @@
return false;
}
- /* Bail out if we are processing only secured video layers
- * and we dont have any */
- if(!isSecurePresent(ctx, mDpy) && secureOnly){
- reset(ctx);
- return false;
- }
-
if(mCurrentFrame.fbCount)
mCurrentFrame.fbZ = mCurrentFrame.mdpCount;
@@ -1342,14 +1356,22 @@
if(sSimulationFlags & MDPCOMP_AVOID_MDP_ONLY_LAYERS)
return false;
- /* Bail out if we are processing only secured video layers
- * and we dont have any */
- if(!isSecurePresent(ctx, mDpy) && secureOnly){
- reset(ctx);
- return false;
+ int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+ if(!isSecurePresent(ctx, mDpy) && !ctx->listStats[mDpy].secureUI) {
+ /* Bail out if we are processing only secured video/ui layers
+ * and we dont have any */
+ if(secureOnly) {
+ ALOGD_IF(isDebug(), "%s: No secure video/ui layers");
+ return false;
+ }
+ /* No Idle fall back for secure video/ui layers and if there is only
+ * single layer being composed. */
+ if(sIdleFallBack && (ctx->listStats[mDpy].numAppLayers > 1)) {
+ ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
+ return false;
+ }
}
- int numAppLayers = ctx->listStats[mDpy].numAppLayers;
mCurrentFrame.reset(numAppLayers);
mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
@@ -1873,6 +1895,33 @@
return true;
}
+void MDPComp::setDynRefreshRate(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+ //For primary display, set the dynamic refreshrate
+ if(!mDpy && qdutils::MDPVersion::getInstance().isDynFpsSupported() &&
+ ctx->mUseMetaDataRefreshRate) {
+ FrameInfo frame;
+ frame.reset(mCurrentFrame.layerCount);
+ memset(&frame.drop, 0, sizeof(frame.drop));
+ frame.dropCount = 0;
+ ALOGD_IF(isDebug(), "%s: Update Cache and YUVInfo for Dyn Refresh Rate",
+ __FUNCTION__);
+ updateLayerCache(ctx, list, frame);
+ updateYUV(ctx, list, false /*secure only*/, frame);
+ uint32_t refreshRate = ctx->dpyAttr[mDpy].refreshRate;
+ MDPVersion& mdpHw = MDPVersion::getInstance();
+ if(sIdleFallBack) {
+ //Set minimum panel refresh rate during idle timeout
+ refreshRate = mdpHw.getMinFpsSupported();
+ } else if((ctx->listStats[mDpy].yuvCount == frame.mdpCount) ||
+ (frame.layerCount == 1)) {
+ //Set the new fresh rate, if there is only one updating YUV layer
+ //or there is one single RGB layer with this request
+ refreshRate = ctx->listStats[mDpy].refreshRateRequest;
+ }
+ setRefreshRate(ctx, mDpy, refreshRate);
+ }
+}
+
int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
int ret = 0;
char property[PROPERTY_VALUE_MAX];
@@ -1899,19 +1948,22 @@
if(!mDpy)
memset(&(ctx->mPtorInfo), 0, sizeof(ctx->mPtorInfo));
+ //reset old data
+ mCurrentFrame.reset(numLayers);
+ memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
+ mCurrentFrame.dropCount = 0;
+
//Do not cache the information for next draw cycle.
if(numLayers > MAX_NUM_APP_LAYERS or (!numLayers)) {
ALOGI("%s: Unsupported layer count for mdp composition",
__FUNCTION__);
mCachedFrame.reset();
+#ifdef DYNAMIC_FPS
+ setDynRefreshRate(ctx, list);
+#endif
return -1;
}
- //reset old data
- mCurrentFrame.reset(numLayers);
- memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
- mCurrentFrame.dropCount = 0;
-
// Detect the start of animation and fall back to GPU only once to cache
// all the layers in FB and display FB content untill animation completes.
if(ctx->listStats[mDpy].isDisplayAnimating) {
@@ -1922,6 +1974,9 @@
}
setMDPCompLayerFlags(ctx, list);
mCachedFrame.updateCounts(mCurrentFrame);
+#ifdef DYNAMIC_FPS
+ setDynRefreshRate(ctx, list);
+#endif
ret = -1;
return ret;
} else {
@@ -1974,26 +2029,7 @@
}
#ifdef DYNAMIC_FPS
- //For primary display, set the dynamic refreshrate
- if(!mDpy && qdutils::MDPVersion::getInstance().isDynFpsSupported() &&
- ctx->mUseMetaDataRefreshRate) {
- FrameInfo frame;
- frame.reset(mCurrentFrame.layerCount);
- memset(&frame.drop, 0, sizeof(frame.drop));
- frame.dropCount = 0;
- ALOGD_IF(isDebug(), "%s: Update Cache and YUVInfo for Dyn Refresh Rate",
- __FUNCTION__);
- updateLayerCache(ctx, list, frame);
- updateYUV(ctx, list, false /*secure only*/, frame);
- uint32_t refreshRate = ctx->dpyAttr[mDpy].refreshRate;
- //Set the new fresh rate, if there is only one updating YUV layer
- //or there is one single RGB layer with this request
- if((ctx->listStats[mDpy].yuvCount == frame.mdpCount) ||
- (frame.layerCount == 1)) {
- refreshRate = ctx->listStats[mDpy].refreshRateRequest;
- }
- setRefreshRate(ctx, mDpy, refreshRate);
- }
+ setDynRefreshRate(ctx, list);
#endif
mCachedFrame.cacheAll(list);
@@ -2397,10 +2433,10 @@
eDest rDest = mdp_info.rIndex;
ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
- "dest_pipeR: %d",__FUNCTION__, layer, zOrder, lDest, rDest);
+ "dest_pipeR: %d",__FUNCTION__, layer, zOrder, lDest, rDest);
return configureSplit(ctx, layer, mDpy, mdpFlagsL, zOrder, lDest,
- rDest, &PipeLayerPair.rot);
+ rDest, &PipeLayerPair.rot);
}
bool MDPCompSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
@@ -2584,8 +2620,8 @@
//pipe line length, we are still using 2 pipes. This is fine just because
//this is source split where destination doesn't matter. Evaluate later to
//see if going through all the calcs to save a pipe is worth it
- if(dstWidth > mdpHw.getMaxMixerWidth() or
- cropWidth > mdpHw.getMaxMixerWidth() or
+ if(dstWidth > mdpHw.getMaxPipeWidth() or
+ cropWidth > mdpHw.getMaxPipeWidth() or
(primarySplitAlways and
(cropWidth > lSplit or layerClock > mixerClock))) {
pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
@@ -2737,5 +2773,49 @@
return 0;
}
+bool MDPComp::getPartialUpdatePref(hwc_context_t *ctx) {
+ Locker::Autolock _l(ctx->mDrawLock);
+ const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
+ char path[MAX_SYSFS_FILE_PATH];
+ snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
+ int fd = open(path, O_RDONLY);
+ if(fd < 0) {
+ ALOGE("%s: Failed to open sysfd node: %s", __FUNCTION__, path);
+ return -1;
+ }
+ char value[4];
+ ssize_t size_read = read(fd, value, sizeof(value)-1);
+ if(size_read <= 0) {
+ ALOGE("%s: Failed to read sysfd node: %s", __FUNCTION__, path);
+ close(fd);
+ return -1;
+ }
+ close(fd);
+ value[size_read] = '\0';
+ return atoi(value);
+}
+
+int MDPComp::setPartialUpdatePref(hwc_context_t *ctx, bool enable) {
+ Locker::Autolock _l(ctx->mDrawLock);
+ const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
+ char path[MAX_SYSFS_FILE_PATH];
+ snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
+ int fd = open(path, O_WRONLY);
+ if(fd < 0) {
+ ALOGE("%s: Failed to open sysfd node: %s", __FUNCTION__, path);
+ return -1;
+ }
+ char value[4];
+ snprintf(value, sizeof(value), "%d", (int)enable);
+ ssize_t ret = write(fd, value, strlen(value));
+ if(ret <= 0) {
+ ALOGE("%s: Failed to write to sysfd nodes: %s", __FUNCTION__, path);
+ close(fd);
+ return -1;
+ }
+ close(fd);
+ sIsPartialUpdateActive = enable;
+ return 0;
+}
}; //namespace
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 8929c40..4978182 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -56,6 +56,9 @@
static void dynamicDebug(bool enable){ sDebugLogs = enable; }
static void setIdleTimeout(const uint32_t& timeout);
static void setMaxPipesPerMixer(const uint32_t value);
+ static int setPartialUpdatePref(hwc_context_t *ctx, bool enable);
+ static bool getPartialUpdatePref(hwc_context_t *ctx);
+ void setDynRefreshRate(hwc_context_t *ctx, hwc_display_contents_1_t* list);
protected:
enum ePipeType {
@@ -257,6 +260,7 @@
static bool sSrcSplitEnabled;
static IdleInvalidator *sIdleInvalidator;
static int sMaxSecLayers;
+ static bool sIsPartialUpdateActive;
struct FrameInfo mCurrentFrame;
struct LayerCache mCachedFrame;
//Enable 4kx2k yuv layer split
diff --git a/libhwcomposer/hwc_qclient.cpp b/libhwcomposer/hwc_qclient.cpp
index b0ebb3a..09013c6 100644
--- a/libhwcomposer/hwc_qclient.cpp
+++ b/libhwcomposer/hwc_qclient.cpp
@@ -59,34 +59,39 @@
}
static void securing(hwc_context_t *ctx, uint32_t startEnd) {
- Locker::Autolock _sl(ctx->mDrawLock);
//The only way to make this class in this process subscribe to media
//player's death.
IMediaDeathNotifier::getMediaPlayerService();
+ ctx->mDrawLock.lock();
ctx->mSecuring = startEnd;
//We're done securing
if(startEnd == IQService::END)
ctx->mSecureMode = true;
+ ctx->mDrawLock.unlock();
+
if(ctx->proc)
ctx->proc->invalidate(ctx->proc);
}
static void unsecuring(hwc_context_t *ctx, uint32_t startEnd) {
- Locker::Autolock _sl(ctx->mDrawLock);
+ ctx->mDrawLock.lock();
ctx->mSecuring = startEnd;
//We're done unsecuring
if(startEnd == IQService::END)
ctx->mSecureMode = false;
+ ctx->mDrawLock.unlock();
+
if(ctx->proc)
ctx->proc->invalidate(ctx->proc);
}
void QClient::MPDeathNotifier::died() {
- Locker::Autolock _sl(mHwcContext->mDrawLock);
+ mHwcContext->mDrawLock.lock();
ALOGD_IF(QCLIENT_DEBUG, "Media Player died");
mHwcContext->mSecuring = false;
mHwcContext->mSecureMode = false;
+ mHwcContext->mDrawLock.unlock();
if(mHwcContext->proc)
mHwcContext->proc->invalidate(mHwcContext->proc);
}
@@ -306,6 +311,33 @@
}
}
+static status_t setPartialUpdatePref(hwc_context_t *ctx, uint32_t enable) {
+ ALOGD("%s: enable: %d", __FUNCTION__, enable);
+ if(qhwc::MDPComp::setPartialUpdatePref(ctx, (bool)enable) < 0)
+ return NO_INIT;
+ return NO_ERROR;
+}
+
+static void toggleScreenUpdate(hwc_context_t* ctx, uint32_t on) {
+ ALOGD("%s: toggle update: %d", __FUNCTION__, on);
+ if (on == 0) {
+ ctx->mDrawLock.lock();
+ ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isPause = true;
+ ctx->mOverlay->configBegin();
+ ctx->mOverlay->configDone();
+ ctx->mRotMgr->clear();
+ if(!Overlay::displayCommit(ctx->dpyAttr[0].fd)) {
+ ALOGE("%s: Display commit failed", __FUNCTION__);
+ }
+ ctx->mDrawLock.unlock();
+ } else {
+ ctx->mDrawLock.lock();
+ ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isPause = false;
+ ctx->mDrawLock.unlock();
+ ctx->proc->invalidate(ctx->proc);
+ }
+}
+
status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel,
Parcel* outParcel) {
status_t ret = NO_ERROR;
@@ -354,12 +386,18 @@
case IQService::SET_MAX_PIPES_PER_MIXER:
setMaxPipesPerMixer(mHwcContext, inParcel);
break;
+ case IQService::SET_PARTIAL_UPDATE:
+ ret = setPartialUpdatePref(mHwcContext, inParcel->readInt32());
+ break;
case IQService::TOGGLE_BWC:
toggleBWC(mHwcContext, inParcel);
break;
case IQService::CONFIGURE_DYN_REFRESH_RATE:
configureDynRefreshRate(mHwcContext, inParcel);
break;
+ case IQService::TOGGLE_SCREEN_UPDATE:
+ toggleScreenUpdate(mHwcContext, inParcel->readInt32());
+ break;
default:
ret = NO_ERROR;
}
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index ace0017..4f3dbf0 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -86,7 +86,7 @@
bool isValidResolution(hwc_context_t *ctx, uint32_t xres, uint32_t yres)
{
- return !((xres > qdutils::MDPVersion::getInstance().getMaxMixerWidth() &&
+ return !((xres > qdutils::MDPVersion::getInstance().getMaxPipeWidth() &&
!isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY)) ||
(xres < MIN_DISPLAY_XRES || yres < MIN_DISPLAY_YRES));
}
@@ -413,6 +413,7 @@
}
memset(&(ctx->mPtorInfo), 0, sizeof(ctx->mPtorInfo));
+ ctx->mHPDEnabled = false;
ALOGI("Initializing Qualcomm Hardware Composer");
ALOGI("MDP version: %d", ctx->mMDP.version);
}
@@ -2238,8 +2239,6 @@
(*rot) = ctx->mRotMgr->getNext();
if((*rot) == NULL) return -1;
ctx->mLayerRotMap[dpy]->add(layer, *rot);
- BwcPM::setBwc(ctx, dpy, hnd, crop, dst, transform, downscale,
- mdpFlagsL);
//Configure rotator for pre-rotation
if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {
ALOGE("%s: configRotator failed!", __FUNCTION__);
@@ -2353,7 +2352,7 @@
bool isDisplaySplit(hwc_context_t* ctx, int dpy) {
qdutils::MDPVersion& mdpHw = qdutils::MDPVersion::getInstance();
- if(ctx->dpyAttr[dpy].xres > mdpHw.getMaxMixerWidth()) {
+ if(ctx->dpyAttr[dpy].xres > mdpHw.getMaxPipeWidth()) {
return true;
}
//For testing we could split primary via device tree values
@@ -2520,7 +2519,7 @@
swap(src_w, src_h);
}
//src width > MAX mixer supported dim
- if(src_w > (int) qdutils::MDPVersion::getInstance().getMaxMixerWidth()) {
+ if(src_w > (int) qdutils::MDPVersion::getInstance().getMaxPipeWidth()) {
return;
}
//Decimation necessary, cannot use BWC. H/W requirement.
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 286ae22..797f9b0 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -96,7 +96,7 @@
//It should be active also. (UNBLANKED)
bool isActive;
// In pause state, composition is bypassed
- // used for WFD displays only
+ // used for WFD displays and in QDCM calibration mode
bool isPause;
// To trigger padding round to clean up mdp
// pipes
@@ -459,9 +459,9 @@
// Returns true if the buffer is yuv and exceeds the mixer width
static inline bool isYUVSplitNeeded(const private_handle_t* hnd) {
- int maxMixerWidth = qdutils::MDPVersion::getInstance().getMaxMixerWidth();
+ int maxPipeWidth = qdutils::MDPVersion::getInstance().getMaxPipeWidth();
return (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO) &&
- (hnd->width > maxMixerWidth));
+ (hnd->width > maxPipeWidth));
}
// Returns true if the buffer is secure
@@ -479,11 +479,6 @@
return (hnd && (private_handle_t::PRIV_FLAGS_TILE_RENDERED & hnd->flags));
}
-//Return true if buffer is marked locked
-static inline bool isBufferLocked(const private_handle_t* hnd) {
- return (hnd && (private_handle_t::PRIV_FLAGS_HWC_LOCK & hnd->flags));
-}
-
//Return true if the buffer is intended for Secure Display
static inline bool isSecureDisplayBuffer(const private_handle_t* hnd) {
return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY));
@@ -644,6 +639,8 @@
bool mBWCEnabled;
// Provides a way for OEM's to disable setting dynfps via metadata.
bool mUseMetaDataRefreshRate;
+ // Stores the hpd enabled status- avoids re-enabling HDP on suspend resume.
+ bool mHPDEnabled;
};
namespace qhwc {
diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp
index e9c0a13..c250919 100644
--- a/liboverlay/overlay.cpp
+++ b/liboverlay/overlay.cpp
@@ -47,6 +47,9 @@
initScalar();
setDMAMultiplexingSupported();
+#ifdef USES_POST_PROCESSING
+ initPostProc();
+#endif
}
Overlay::~Overlay() {
@@ -54,6 +57,9 @@
mPipeBook[i].destroy();
}
destroyScalar();
+#ifdef USES_POST_PROCESSING
+ destroyPostProc();
+#endif
}
void Overlay::configBegin() {
@@ -526,6 +532,23 @@
}
}
+void Overlay::initPostProc() {
+ sLibAblHandle = dlopen("libmm-abl.so", RTLD_NOW);
+ if (sLibAblHandle) {
+ *(void **)&sFnppParams = dlsym(sLibAblHandle,
+ "display_pp_compute_params");
+ } else {
+ ALOGE("%s: Not able to load libmm-abl.so", __FUNCTION__);
+ }
+}
+
+void Overlay::destroyPostProc() {
+ if (sLibAblHandle) {
+ dlclose(sLibAblHandle);
+ sLibAblHandle = NULL;
+ }
+}
+
void Overlay::PipeBook::init() {
mPipe = NULL;
mDisplay = DPY_UNUSED;
@@ -557,5 +580,9 @@
{utils::OV_MDP_PIPE_ANY};
void *Overlay::sLibScaleHandle = NULL;
int (*Overlay::sFnProgramScale)(struct mdp_overlay_list *) = NULL;
+/* Dynamically link ABL library */
+void *Overlay::sLibAblHandle = NULL;
+int (*Overlay::sFnppParams)(const struct compute_params *,
+ struct mdp_overlay_pp_params *) = NULL;
}; // namespace overlay
diff --git a/liboverlay/overlay.h b/liboverlay/overlay.h
index 665e23f..984b439 100644
--- a/liboverlay/overlay.h
+++ b/liboverlay/overlay.h
@@ -33,6 +33,9 @@
#include "overlayUtils.h"
#include "mdp_version.h"
#include "utils/threads.h"
+#ifdef USES_POST_PROCESSING
+#include "lib-postproc.h"
+#endif
struct MetaData_t;
@@ -186,6 +189,12 @@
/* Sets the pipe type RGB/VG/DMA*/
void setPipeType(utils::eDest pipeIndex, const utils::eMdpPipeType pType);
+ /* Dynamically link ABL library */
+ static void initPostProc();
+ static void destroyPostProc();
+ static int (*getFnPpParams())(const struct compute_params *,
+ struct mdp_overlay_pp_params *);
+
/* Just like a Facebook for pipes, but much less profile info */
struct PipeBook {
void init();
@@ -251,6 +260,10 @@
static bool sDMAMultiplexingSupported;
static void *sLibScaleHandle;
static int (*sFnProgramScale)(struct mdp_overlay_list *);
+ /* Dynamically link ABL library */
+ static void *sLibAblHandle;
+ static int (*sFnppParams)(const struct compute_params *,
+ struct mdp_overlay_pp_params *);
static bool sDebugPipeLifecycle;
friend class MdpCtrl;
@@ -345,6 +358,11 @@
return sFnProgramScale;
}
+inline int (*Overlay::getFnPpParams())(const struct compute_params *,
+ struct mdp_overlay_pp_params *) {
+ return sFnppParams;
+}
+
inline void Overlay::debugPipeLifecycle(const bool& enable) {
sDebugPipeLifecycle = enable;
}
diff --git a/liboverlay/overlayMdp.cpp b/liboverlay/overlayMdp.cpp
index 4cd52a7..3932c4c 100644
--- a/liboverlay/overlayMdp.cpp
+++ b/liboverlay/overlayMdp.cpp
@@ -21,6 +21,7 @@
#include "overlayMdp.h"
#include "mdp_version.h"
#include <overlay.h>
+#include <dlfcn.h>
#define HSIC_SETTINGS_DEBUG 0
@@ -263,7 +264,7 @@
}
if (needUpdate) {
- mParams.params.pa_params.hue = data.hsicData.hue;
+ mParams.params.pa_params.hue = (float)data.hsicData.hue;
mParams.params.pa_params.sat = data.hsicData.saturation;
mParams.params.pa_params.intensity = data.hsicData.intensity;
mParams.params.pa_params.contrast = data.hsicData.contrast;
@@ -333,7 +334,15 @@
}
if (needUpdate) {
- display_pp_compute_params(&mParams, &mOVInfo.overlay_pp_cfg);
+ int (*sFnppParams)(const struct compute_params *,
+ struct mdp_overlay_pp_params *) =
+ Overlay::getFnPpParams();
+ if(sFnppParams) {
+ int ret = sFnppParams(&mParams, &mOVInfo.overlay_pp_cfg);
+ if (ret) {
+ ALOGE("%s: Unable to set PP params", __FUNCTION__);
+ }
+ }
}
#endif
return true;
diff --git a/liboverlay/overlayUtils.cpp b/liboverlay/overlayUtils.cpp
index 32b2013..dd030ef 100644
--- a/liboverlay/overlayUtils.cpp
+++ b/liboverlay/overlayUtils.cpp
@@ -277,13 +277,14 @@
if((int)verDscale)
vertDeci = (uint8_t)log2f(verDscale);
- if(src_w > (int) mdpHw.getMaxMixerWidth()) {
+ if(src_w > (int) mdpHw.getMaxPipeWidth()) {
//If the client sends us something > what a layer mixer supports
//then it means it doesn't want to use split-pipe but wants us to
- //decimate. A minimum decimation of 2 will ensure that the width is
+ //decimate. A minimum decimation of 1 will ensure that the width is
//always within layer mixer limits.
- if(horzDeci < 2)
- horzDeci = 2;
+ const uint8_t minDeci = 1;
+ if(horzDeci < minDeci)
+ horzDeci = minDeci;
}
}
diff --git a/libqdutils/mdp_version.cpp b/libqdutils/mdp_version.cpp
index f8729a5..402e129 100644
--- a/libqdutils/mdp_version.cpp
+++ b/libqdutils/mdp_version.cpp
@@ -75,7 +75,7 @@
#define MDSS_MDP_HW_REV_109 0x10090000 //8994 v2
#endif
#ifndef MDSS_MDP_HW_REV_110
-#define MDSS_MDP_HW_REV_110 0x100a0000 //Next version
+#define MDSS_MDP_HW_REV_110 0x100a0000 //8992
#endif
#ifndef MDSS_MDP_HW_REV_200
#define MDSS_MDP_HW_REV_200 0x20000000 //8092
@@ -101,12 +101,16 @@
mSourceSplitAlways = false;
mRGBHasNoScalar = false;
mRotDownscale = false;
- mBlendStages = 6; //min no. of stages supported by MDP.
+ mBlendStages = 4; //min no. of stages supported by MDP.
// this is the default limit of mixer unless driver reports it.
- // For resolutions beyond this, we use dual/split overlay pipes.
+ // For resolutions beyond this, we use dual mixer/ping pong split.
mMaxMixerWidth = 2048;
+ // Default width of MDSS SSPP. For layer resolutions beyond this, we drive
+ // using two SSPP's.
+ mMaxPipeWidth = 2048;
+
updatePanelInfo();
if(!updateSysFsInfo()) {
@@ -324,6 +328,9 @@
} else if(!strncmp(tokens[0], "max_mixer_width",
strlen("max_mixer_width"))) {
mMaxMixerWidth = atoi(tokens[1]);
+ } else if(!strncmp(tokens[0], "max_pipe_width",
+ strlen("max_pipe_width"))) {
+ mMaxPipeWidth = atoi(tokens[1]);
} else if(!strncmp(tokens[0], "features", strlen("features"))) {
for(int i=1; i<index;i++) {
if(!strncmp(tokens[i], "bwc", strlen("bwc"))) {
diff --git a/libqdutils/mdp_version.h b/libqdutils/mdp_version.h
index dcde240..3b10010 100644
--- a/libqdutils/mdp_version.h
+++ b/libqdutils/mdp_version.h
@@ -139,6 +139,7 @@
uint32_t getMinFpsSupported() { return mPanelInfo.mMinFps; }
uint32_t getMaxFpsSupported() { return mPanelInfo.mMaxFps; }
uint32_t getMaxMixerWidth() const { return mMaxMixerWidth; }
+ uint32_t getMaxPipeWidth() const { return mMaxPipeWidth; }
bool hasMinCropWidthLimitation() const;
bool isSrcSplit() const;
bool isSrcSplitAlways() const;
@@ -179,6 +180,7 @@
bool mRGBHasNoScalar;
bool mRotDownscale;
uint32_t mMaxMixerWidth; //maximum x-res of a given mdss mixer.
+ uint32_t mMaxPipeWidth; //maximum x-res of the mdp pipe.
};
}; //namespace qdutils
#endif //INCLUDE_LIBQCOMUTILS_MDPVER
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index 683c93c..ef47475 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -57,6 +57,8 @@
TOGGLE_BWC = 17, // Toggle BWC On/Off on targets that support
/* Enable/Disable/Set refresh rate dynamically */
CONFIGURE_DYN_REFRESH_RATE = 18,
+ SET_PARTIAL_UPDATE = 19, // Preference on partial update feature
+ TOGGLE_SCREEN_UPDATE = 20, // Provides ability to disable screen updates
COMMAND_LIST_END = 400,
};
diff --git a/libqservice/QServiceUtils.h b/libqservice/QServiceUtils.h
index f53d140..71277e8 100644
--- a/libqservice/QServiceUtils.h
+++ b/libqservice/QServiceUtils.h
@@ -74,6 +74,14 @@
return sendSingleParam(qService::IQService::SCREEN_REFRESH, 1);
}
+inline android::status_t toggleScreenUpdate(uint32_t on) {
+ return sendSingleParam(qService::IQService::TOGGLE_SCREEN_UPDATE, on);
+}
+
+inline android::status_t setPartialUpdate(uint32_t enable) {
+ return sendSingleParam(qService::IQService::SET_PARTIAL_UPDATE, enable);
+}
+
inline android::status_t setExtOrientation(uint32_t orientation) {
return sendSingleParam(qService::IQService::EXTERNAL_ORIENTATION,
orientation);