Merge "hwc: Separate out hwc_sync into mdss and rotator functions"
diff --git a/displayengine/include/core/display_interface.h b/displayengine/include/core/display_interface.h
index f4c4415..782d8fc 100644
--- a/displayengine/include/core/display_interface.h
+++ b/displayengine/include/core/display_interface.h
@@ -95,9 +95,10 @@
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).
+ uint32_t h_total; //!< Total width of panel (hActive + hFP + hBP + hPulseWidth).
DisplayConfigVariableInfo() : x_pixels(0), y_pixels(0), x_dpi(0.0f), y_dpi(0.0f),
- fps(0.0f), vsync_period_ns(0) { }
+ fps(0.0f), vsync_period_ns(0), v_total(0), h_total(0) { }
};
/*! @brief Event data associated with VSync event.
diff --git a/displayengine/include/core/layer_stack.h b/displayengine/include/core/layer_stack.h
index 96ec20f..d85fd98 100644
--- a/displayengine/include/core/layer_stack.h
+++ b/displayengine/include/core/layer_stack.h
@@ -44,8 +44,6 @@
@sa Layer
*/
enum LayerBlending {
- kBlendingNone, //!< Blend operation is not specified.
-
kBlendingOpaque, //!< Pixel color is expressed using straight alpha in color tuples. It
//!< is constant blend operation. The layer would appear opaque if plane
//!< alpha is 0xFF.
@@ -203,7 +201,7 @@
uint32_t frame_rate; //!< Rate at which frames are being updated for this layer.
- Layer() : input_buffer(NULL), composition(kCompositionGPU), blending(kBlendingNone),
+ Layer() : input_buffer(NULL), composition(kCompositionGPU), blending(kBlendingOpaque),
plane_alpha(0), frame_rate(0) { }
};
diff --git a/displayengine/include/private/hw_info_types.h b/displayengine/include/private/hw_info_types.h
index c6c2a0a..49abafe 100644
--- a/displayengine/include/private/hw_info_types.h
+++ b/displayengine/include/private/hw_info_types.h
@@ -69,6 +69,7 @@
uint32_t max_sde_clk;
float clk_fudge_factor;
bool has_bwc;
+ bool has_ubwc;
bool has_decimation;
bool has_macrotile;
bool has_rotator_downscale;
@@ -80,7 +81,7 @@
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(1),
max_scale_down(1), max_bandwidth_low(0), max_bandwidth_high(0), max_mixer_width(2048),
- max_pipe_bw(0), max_sde_clk(0), clk_fudge_factor(1.0f), has_bwc(false),
+ max_pipe_bw(0), max_sde_clk(0), clk_fudge_factor(1.0f), has_bwc(false), has_ubwc(false),
has_decimation(false), has_macrotile(false), has_rotator_downscale(false),
has_non_scalar_rgb(false), is_src_split(false) { }
diff --git a/displayengine/include/private/strategy_interface.h b/displayengine/include/private/strategy_interface.h
index eac88cc..df01c7f 100644
--- a/displayengine/include/private/strategy_interface.h
+++ b/displayengine/include/private/strategy_interface.h
@@ -31,6 +31,7 @@
#include <core/sde_types.h>
#include <core/display_interface.h>
+#include "hw_info_types.h"
namespace sde {
@@ -88,11 +89,14 @@
@param[in] version \link STRATEGY_VERSION_TAG \endlink
@param[in] type \link DisplayType \endlink
+ @param[in] hw_resource_info \link HWResourceInfo \endlink
+ @param[in] hw_panel_info \link HWPanelInfo \endlink
@param[out] interface \link StrategyInterface \endlink
@return \link DisplayError \endlink
*/
typedef DisplayError (*CreateStrategyInterface)(uint16_t version, DisplayType type,
+ const HWResourceInfo *hw_resource_info, const HWPanelInfo *hw_panel_info,
StrategyInterface **interface);
/*! @brief Function to destroy composer strategy interface.
@@ -139,6 +143,13 @@
uint32_t count; //!< Total number of layers which need to be set on hardware.
+ LayerRect left_partial_update;
+ //!< Left ROI.
+
+ LayerRect right_partial_update;
+ //!< Right ROI.
+
+
HWLayersInfo() : stack(NULL), count(0) { }
};
diff --git a/displayengine/include/utils/debug.h b/displayengine/include/utils/debug.h
index 5f65834..2cef5d7 100644
--- a/displayengine/include/utils/debug.h
+++ b/displayengine/include/utils/debug.h
@@ -65,6 +65,7 @@
static uint32_t GetIdleTimeoutMs();
static bool IsRotatorDownScaleDisabled();
static bool IsDecimationDisabled();
+ static bool IsPartialUpdate();
private:
Debug();
diff --git a/displayengine/include/utils/rect.h b/displayengine/include/utils/rect.h
index 0730529..dd60672 100644
--- a/displayengine/include/utils/rect.h
+++ b/displayengine/include/utils/rect.h
@@ -37,11 +37,14 @@
namespace sde {
- bool IsValidRect(const LayerRect &rect);
- LayerRect GetIntersection(const LayerRect &rect1, const LayerRect &rect2);
- void LogRect(DebugTag debug_tag, const char *prefix, const LayerRect &roi);
- void NormalizeRect(const uint32_t &align_x, const uint32_t &align_y, LayerRect *rect);
-
+ bool IsValid(const LayerRect &rect);
+ bool IsCongruent(const LayerRect &rect1, const LayerRect &rect2);
+ void Log(DebugTag debug_tag, const char *prefix, const LayerRect &roi);
+ void Normalize(const uint32_t &align_x, const uint32_t &align_y, LayerRect *rect);
+ LayerRect Union(const LayerRect &rect1, const LayerRect &rect2);
+ LayerRect Intersection(const LayerRect &rect1, const LayerRect &rect2);
+ LayerRect Subtract(const LayerRect &rect1, const LayerRect &rect2);
+ LayerRect Reposition(const LayerRect &rect1, const int &x_offset, const int &y_offset);
} // namespace sde
#endif // __RECT_H__
diff --git a/displayengine/libs/core/comp_manager.cpp b/displayengine/libs/core/comp_manager.cpp
index cc58465..1ca7c16 100644
--- a/displayengine/libs/core/comp_manager.cpp
+++ b/displayengine/libs/core/comp_manager.cpp
@@ -80,6 +80,8 @@
destroy_strategy_intf_ = StrategyDefault::DestroyStrategyInterface;
}
+ hw_res_info_ = hw_res_info;
+
return error;
}
@@ -96,7 +98,7 @@
}
DisplayError CompManager::RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
- Handle *display_ctx) {
+ const HWPanelInfo &hw_panel_info, Handle *display_ctx) {
SCOPE_LOCK(locker_);
DisplayError error = kErrorNone;
@@ -106,7 +108,7 @@
return kErrorMemory;
}
- if (create_strategy_intf_(STRATEGY_VERSION_TAG, type,
+ if (create_strategy_intf_(STRATEGY_VERSION_TAG, type, &hw_res_info_, &hw_panel_info,
&display_comp_ctx->strategy_intf) != kErrorNone) {
DLOGW("Unable to create strategy interface");
delete display_comp_ctx;
@@ -114,7 +116,8 @@
return kErrorUndefined;
}
- error = res_mgr_.RegisterDisplay(type, attributes, &display_comp_ctx->display_resource_ctx);
+ error = res_mgr_.RegisterDisplay(type, attributes, hw_panel_info,
+ &display_comp_ctx->display_resource_ctx);
if (error != kErrorNone) {
destroy_strategy_intf_(display_comp_ctx->strategy_intf);
delete display_comp_ctx;
@@ -170,8 +173,8 @@
constraints->safe_mode = safe_mode_;
- // Limit 2 layer SDE Comp on HDMI
- if (display_comp_ctx->display_type == kHDMI) {
+ // Limit 2 layer SDE Comp on HDMI/Virtual
+ if (display_comp_ctx->display_type != kPrimary) {
constraints->max_layers = 2;
}
@@ -180,7 +183,7 @@
constraints->safe_mode = true;
}
- if (display_comp_ctx->idle_fallback) {
+ if (display_comp_ctx->idle_fallback || display_comp_ctx->fallback_) {
constraints->safe_mode = true;
}
}
@@ -318,6 +321,19 @@
return false;
}
+void CompManager::ProcessThermalEvent(Handle display_ctx, int64_t thermal_level) {
+ SCOPE_LOCK(locker_);
+
+ DisplayCompositionContext *display_comp_ctx =
+ reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+
+ if (thermal_level >= kMaxThermalLevel) {
+ display_comp_ctx->fallback_ = true;
+ } else {
+ display_comp_ctx->fallback_ = false;
+ }
+}
+
DisplayError CompManager::SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages) {
SCOPE_LOCK(locker_);
diff --git a/displayengine/libs/core/comp_manager.h b/displayengine/libs/core/comp_manager.h
index 0a21ee0..c445418 100644
--- a/displayengine/libs/core/comp_manager.h
+++ b/displayengine/libs/core/comp_manager.h
@@ -40,7 +40,7 @@
BufferSyncHandler *buffer_sync_handler_);
DisplayError Deinit();
DisplayError RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
- Handle *res_mgr_hnd);
+ const HWPanelInfo &hw_panel_info, 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);
@@ -48,12 +48,15 @@
DisplayError PostCommit(Handle display_ctx, HWLayers *hw_layers);
void Purge(Handle display_ctx);
bool ProcessIdleTimeout(Handle display_ctx);
+ void ProcessThermalEvent(Handle display_ctx, int64_t thermal_level);
DisplayError SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages);
// DumpImpl method
virtual void AppendDump(char *buffer, uint32_t length);
private:
+ static const int kMaxThermalLevel = 3;
+
void PrepareStrategyConstraints(Handle display_ctx, HWLayers *hw_layers);
struct DisplayCompositionContext {
@@ -65,10 +68,12 @@
uint32_t remaining_strategies;
bool idle_fallback;
bool handle_idle_timeout;
+ bool fallback_;
DisplayCompositionContext()
: display_resource_ctx(NULL), display_type(kPrimary), max_strategies(0),
- remaining_strategies(0), idle_fallback(false), handle_idle_timeout(true) { }
+ remaining_strategies(0), idle_fallback(false), handle_idle_timeout(true),
+ fallback_(false) { }
};
Locker locker_;
@@ -81,6 +86,7 @@
bool safe_mode_; // Flag to notify all displays to be in resource crunch
// mode, where strategy manager chooses the best strategy
// that uses optimal number of pipes for each display
+ HWResourceInfo hw_res_info_;
};
} // namespace sde
diff --git a/displayengine/libs/core/display_base.cpp b/displayengine/libs/core/display_base.cpp
index e58b4f8..a70a7c9 100644
--- a/displayengine/libs/core/display_base.cpp
+++ b/displayengine/libs/core/display_base.cpp
@@ -74,7 +74,7 @@
}
error = comp_manager_->RegisterDisplay(display_type_, display_attributes_[active_mode_index_],
- &display_comp_ctx_);
+ hw_panel_info_, &display_comp_ctx_);
if (error != kErrorNone) {
goto CleanupOnError;
}
@@ -327,7 +327,8 @@
comp_manager_->UnregisterDisplay(display_comp_ctx_);
}
- error = comp_manager_->RegisterDisplay(display_type_, display_attributes, &display_comp_ctx_);
+ error = comp_manager_->RegisterDisplay(display_type_, display_attributes, hw_panel_info_,
+ &display_comp_ctx_);
if (error != kErrorNone) {
return error;
}
@@ -355,7 +356,7 @@
comp_manager_->UnregisterDisplay(display_comp_ctx_);
}
- error = comp_manager_->RegisterDisplay(display_type_, display_attributes_[index],
+ error = comp_manager_->RegisterDisplay(display_type_, display_attributes_[index], hw_panel_info_,
&display_comp_ctx_);
return error;
diff --git a/displayengine/libs/core/display_primary.cpp b/displayengine/libs/core/display_primary.cpp
index 6f705f7..1dcd05b 100644
--- a/displayengine/libs/core/display_primary.cpp
+++ b/displayengine/libs/core/display_primary.cpp
@@ -166,7 +166,7 @@
void DisplayPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
SCOPE_LOCK(locker_);
// Idle fallback feature is supported only for video mode panel.
- if (hw_panel_info_.mode == kModeCommand) {
+ if (hw_panel_info_.mode == kModeVideo) {
hw_primary_intf_->SetIdleTimeoutMs(timeout_ms);
}
}
@@ -243,5 +243,10 @@
}
}
+void DisplayPrimary::ThermalEvent(int64_t thermal_level) {
+ SCOPE_LOCK(locker_);
+ comp_manager_->ProcessThermalEvent(display_comp_ctx_, thermal_level);
+}
+
} // namespace sde
diff --git a/displayengine/libs/core/display_primary.h b/displayengine/libs/core/display_primary.h
index 8ce4f28..da84fe6 100644
--- a/displayengine/libs/core/display_primary.h
+++ b/displayengine/libs/core/display_primary.h
@@ -61,6 +61,7 @@
virtual DisplayError VSync(int64_t timestamp);
virtual DisplayError Blank(bool blank);
virtual void IdleTimeout();
+ virtual void ThermalEvent(int64_t thermal_level);
private:
Locker locker_;
diff --git a/displayengine/libs/core/fb/hw_device.h b/displayengine/libs/core/fb/hw_device.h
index 07d9e4d..c1dc99d 100644
--- a/displayengine/libs/core/fb/hw_device.h
+++ b/displayengine/libs/core/fb/hw_device.h
@@ -69,7 +69,7 @@
static const int kMaxStringLength = 1024;
static const int kNumPhysicalDisplays = 2;
- static const int kNumDisplayEvents = 3;
+ static const int kNumDisplayEvents = 4;
void DumpLayerCommit(mdp_layer_commit &layer_commit);
DisplayError SetFormat(const LayerBufferFormat &source, uint32_t *target);
diff --git a/displayengine/libs/core/fb/hw_hdmi.cpp b/displayengine/libs/core/fb/hw_hdmi.cpp
index bc97cf6..d45a620 100644
--- a/displayengine/libs/core/fb/hw_hdmi.cpp
+++ b/displayengine/libs/core/fb/hw_hdmi.cpp
@@ -222,6 +222,8 @@
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->h_total = timing_mode->active_h + timing_mode->front_porch_h +
+ timing_mode->back_porch_h + timing_mode->pulse_width_h;
display_attributes->x_dpi = 0;
display_attributes->y_dpi = 0;
display_attributes->fps = FLOAT(timing_mode->refresh_rate) / 1000.0f;
diff --git a/displayengine/libs/core/fb/hw_primary.cpp b/displayengine/libs/core/fb/hw_primary.cpp
index 3b22054..33f28bb 100644
--- a/displayengine/libs/core/fb/hw_primary.cpp
+++ b/displayengine/libs/core/fb/hw_primary.cpp
@@ -75,7 +75,8 @@
DisplayError error = kErrorNone;
char node_path[kMaxStringLength] = {0};
char data[kMaxStringLength] = {0};
- const char* event_name[kNumDisplayEvents] = {"vsync_event", "show_blank_event", "idle_notify"};
+ const char* event_name[kNumDisplayEvents] = {"vsync_event", "show_blank_event", "idle_notify",
+ "msm_fb_thermal_level"};
error = HWDevice::Init();
if (error != kErrorNone) {
@@ -190,6 +191,8 @@
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->h_total = var_screeninfo.xres + var_screeninfo.right_margin +
+ var_screeninfo.left_margin + var_screeninfo.hsync_len;
display_attributes->x_dpi =
(FLOAT(var_screeninfo.xres) * 25.4f) / FLOAT(var_screeninfo.width);
display_attributes->y_dpi =
@@ -285,7 +288,8 @@
typedef void (HWPrimary::*EventHandler)(char*);
EventHandler event_handler[kNumDisplayEvents] = { &HWPrimary::HandleVSync,
&HWPrimary::HandleBlank,
- &HWPrimary::HandleIdleTimeout };
+ &HWPrimary::HandleIdleTimeout,
+ &HWPrimary::HandleThermal };
while (!exit_threads_) {
int error = poll_(poll_fds_, kNumDisplayEvents, -1);
@@ -330,6 +334,17 @@
event_handler_->IdleTimeout();
}
+void HWPrimary::HandleThermal(char *data) {
+ int64_t thermal_level = 0;
+ if (!strncmp(data, "thermal_level=", strlen("thermal_level="))) {
+ thermal_level = strtoull(data + strlen("thermal_level="), NULL, 0);
+ }
+
+ DLOGI("Received thermal notification with thermal level = %d",thermal_level);
+
+ event_handler_->ThermalEvent(thermal_level);
+}
+
void HWPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
char node_path[kMaxStringLength] = {0};
diff --git a/displayengine/libs/core/fb/hw_primary.h b/displayengine/libs/core/fb/hw_primary.h
index b008c92..8d61d74 100644
--- a/displayengine/libs/core/fb/hw_primary.h
+++ b/displayengine/libs/core/fb/hw_primary.h
@@ -68,6 +68,7 @@
void HandleVSync(char *data);
void HandleBlank(char *data);
void HandleIdleTimeout(char *data);
+ void HandleThermal(char *data);
pollfd poll_fds_[kNumDisplayEvents];
pthread_t event_thread_;
diff --git a/displayengine/libs/core/hw_interface.h b/displayengine/libs/core/hw_interface.h
index e8e0c63..8cd608e 100644
--- a/displayengine/libs/core/hw_interface.h
+++ b/displayengine/libs/core/hw_interface.h
@@ -123,6 +123,7 @@
virtual DisplayError VSync(int64_t timestamp) = 0;
virtual DisplayError Blank(bool blank) = 0;
virtual void IdleTimeout() = 0;
+ virtual void ThermalEvent(int64_t thermal_level) = 0;
protected:
virtual ~HWEventHandler() { }
};
diff --git a/displayengine/libs/core/res_config.cpp b/displayengine/libs/core/res_config.cpp
index ea90dfb..ecd8ef1 100644
--- a/displayengine/libs/core/res_config.cpp
+++ b/displayengine/libs/core/res_config.cpp
@@ -42,13 +42,13 @@
}
}
-void ResManager::RotationConfig(LayerBufferFormat format, const LayerTransform &transform,
- const float &downscale, LayerRect *src_rect,
+void ResManager::RotationConfig(const Layer &layer, const float &downscale, LayerRect *src_rect,
struct HWLayerConfig *layer_config, uint32_t *rotate_count) {
HWRotateInfo *rotate = &layer_config->rotates[0];
float src_width = src_rect->right - src_rect->left;
float src_height = src_rect->bottom - src_rect->top;
- bool rot90 = IsRotationNeeded(transform.rotation);
+ bool rot90 = IsRotationNeeded(layer.transform.rotation);
+ bool is_opaque = (layer.blending == kBlendingOpaque);
LayerRect dst_rect;
// Rotate output is a temp buffer, always output to the top left corner for saving memory
dst_rect.top = 0.0f;
@@ -56,7 +56,7 @@
rotate->downscale_ratio = downscale;
uint32_t align_x, align_y;
- GetAlignFactor(format, &align_x, &align_y);
+ GetAlignFactor(layer.input_buffer->format, &align_x, &align_y);
// downscale when doing rotation
if (rot90) {
@@ -84,10 +84,11 @@
rotate->dst_roi = dst_rect;
// Set WHF for Rotator output
- LayerBufferFormat ouput_format;
- SetRotatorOutputFormat(format, false /* bwc */, rot90, downscale, &ouput_format);
+ LayerBufferFormat output_format;
+ SetRotatorOutputFormat(layer.input_buffer->format, is_opaque, rot90, (downscale > 1.0f),
+ &output_format);
HWBufferInfo *hw_buffer_info = &rotate->hw_buffer_info;
- hw_buffer_info->buffer_config.format = ouput_format;
+ hw_buffer_info->buffer_config.format = output_format;
hw_buffer_info->buffer_config.width = UINT32(rotate->dst_roi.right);
hw_buffer_info->buffer_config.height = UINT32(rotate->dst_roi.bottom);
@@ -167,7 +168,7 @@
scissor.bottom = FLOAT(display_attributes.y_pixels);
bool crop_right_valid = false;
- if (IsValidRect(scissor)) {
+ if (IsValid(scissor)) {
crop_right_valid = CalculateCropRects(scissor, transform, &crop_right, &dst_right);
}
@@ -239,8 +240,8 @@
float rot_scale = 1.0f;
if (!IsValidDimension(layer.src_rect, layer.dst_rect)) {
DLOGV_IF(kTagResources, "Input is invalid");
- LogRect(kTagResources, "input layer src_rect", layer.src_rect);
- LogRect(kTagResources, "input layer dst_rect", layer.dst_rect);
+ Log(kTagResources, "input layer src_rect", layer.src_rect);
+ Log(kTagResources, "input layer dst_rect", layer.dst_rect);
return kErrorNotSupported;
}
@@ -264,7 +265,7 @@
uint32_t align_x, align_y;
GetAlignFactor(layer.input_buffer->format, &align_x, &align_y);
if (align_x > 1 || align_y > 1) {
- NormalizeRect(align_x, align_y, &src_rect);
+ Normalize(align_x, align_y, &src_rect);
}
if (ValidateScaling(layer, src_rect, dst_rect, &rot_scale)) {
@@ -279,8 +280,7 @@
LayerTransform transform = layer.transform;
if (IsRotationNeeded(transform.rotation) || UINT32(rot_scale) != 1) {
- RotationConfig(layer.input_buffer->format, layer.transform, rot_scale, &src_rect,
- layer_config, rotate_count);
+ RotationConfig(layer, rot_scale, &src_rect, layer_config, rotate_count);
// rotator will take care of flipping, reset tranform
transform = LayerTransform();
}
@@ -304,21 +304,21 @@
DLOGV_IF(kTagResources, "==== layer = %d, left pipe valid = %d ====",
i, layer_config->left_pipe.valid);
- LogRect(kTagResources, "input layer src_rect", layer.src_rect);
- LogRect(kTagResources, "input layer dst_rect", layer.dst_rect);
+ Log(kTagResources, "input layer src_rect", layer.src_rect);
+ Log(kTagResources, "input layer dst_rect", layer.dst_rect);
for (uint32_t k = 0; k < layer_config->num_rotate; k++) {
DLOGV_IF(kTagResources, "rotate num = %d, scale_x = %.2f", k, rot_scale);
- LogRect(kTagResources, "rotate src", layer_config->rotates[k].src_roi);
- LogRect(kTagResources, "rotate dst", layer_config->rotates[k].dst_roi);
+ Log(kTagResources, "rotate src", layer_config->rotates[k].src_roi);
+ Log(kTagResources, "rotate dst", layer_config->rotates[k].dst_roi);
}
- LogRect(kTagResources, "cropped src_rect", src_rect);
- LogRect(kTagResources, "cropped dst_rect", dst_rect);
- LogRect(kTagResources, "left pipe src", layer_config->left_pipe.src_roi);
- LogRect(kTagResources, "left pipe dst", layer_config->left_pipe.dst_roi);
+ Log(kTagResources, "cropped src_rect", src_rect);
+ Log(kTagResources, "cropped dst_rect", dst_rect);
+ Log(kTagResources, "left pipe src", layer_config->left_pipe.src_roi);
+ Log(kTagResources, "left pipe dst", layer_config->left_pipe.dst_roi);
if (hw_layers->config[i].right_pipe.valid) {
- LogRect(kTagResources, "right pipe src", layer_config->right_pipe.src_roi);
- LogRect(kTagResources, "right pipe dst", layer_config->right_pipe.dst_roi);
+ Log(kTagResources, "right pipe src", layer_config->right_pipe.src_roi);
+ Log(kTagResources, "right pipe dst", layer_config->right_pipe.dst_roi);
}
// set z_order, left_pipe should always be valid
left_pipe.z_order = z_order;
@@ -507,9 +507,9 @@
crop_top += crop_height * top_cut_ratio;
crop_right -= crop_width * right_cut_ratio;
crop_bottom -= crop_height * bottom_cut_ratio;
- NormalizeRect(1, 1, crop);
- NormalizeRect(1, 1, dst);
- if (IsValidRect(*crop) && IsValidRect(*dst))
+ Normalize(1, 1, crop);
+ Normalize(1, 1, dst);
+ if (IsValid(*crop) && IsValid(*dst))
return true;
else
return false;
@@ -612,12 +612,12 @@
// 2. Normalize source and destination rect of a layer to multiple of 1.
// TODO(user) Check buffer format and check if rotate is involved.
- NormalizeRect(align_x, align_y, &left_pipe->src_roi);
- NormalizeRect(1, 1, &left_pipe->dst_roi);
+ Normalize(align_x, align_y, &left_pipe->src_roi);
+ Normalize(1, 1, &left_pipe->dst_roi);
if (right_pipe->valid) {
- NormalizeRect(align_x, align_y, &right_pipe->src_roi);
- NormalizeRect(1, 1, &right_pipe->dst_roi);
+ Normalize(align_x, align_y, &right_pipe->src_roi);
+ Normalize(1, 1, &right_pipe->dst_roi);
}
if (right_pipe->valid) {
diff --git a/displayengine/libs/core/res_manager.cpp b/displayengine/libs/core/res_manager.cpp
index 09b64ab..cdb994f 100644
--- a/displayengine/libs/core/res_manager.cpp
+++ b/displayengine/libs/core/res_manager.cpp
@@ -122,6 +122,8 @@
#ifdef USES_SCALAR
ScalarHelper::GetInstance()->Init();
#endif
+
+ max_system_bw_ = FLOAT(hw_res_info_.max_bandwidth_high);
return kErrorNone;
}
@@ -133,7 +135,7 @@
}
DisplayError ResManager::RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
- Handle *display_ctx) {
+ const HWPanelInfo &hw_panel_info, Handle *display_ctx) {
DisplayError error = kErrorNone;
HWBlockType hw_block_id = kHWBlockMax;
@@ -170,6 +172,7 @@
return kErrorMemory;
}
+ display_resource_ctx->hw_panel_info_ = hw_panel_info;
display_resource_ctx->buffer_manager = new BufferManager(buffer_allocator_, buffer_sync_handler_);
if (display_resource_ctx->buffer_manager == NULL) {
delete display_resource_ctx;
@@ -445,7 +448,9 @@
right_pipe_bw[i] = right_pipe->valid ? GetPipeBw(display_ctx, 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);
+ DLOGV_IF(kTagResources, "Pipe bandwidth exceeds limit for layer index=%d !" \
+ " left_pipe_bw=%f, right_pipe_bw=%f, max_pipe_bw=%f",
+ i, left_pipe_bw[i], right_pipe_bw[i], max_pipe_bw);
return false;
}
@@ -466,9 +471,14 @@
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!");
+ // If system has Video mode panel, then bw limit is max_bandwidth_low
+ if (display_ctx->hw_panel_info_.mode == kModeVideo) {
+ max_system_bw_ = FLOAT(hw_res_info_.max_bandwidth_low);
+ }
+
+ if ((display_bw + bw_claimed_) > (max_system_bw_ / 1000000)) {
+ DLOGV_IF(kTagResources, "Overlap bandwidth: %f exceeds system limit: %f (GBps)!",
+ (display_bw + bw_claimed_), (max_system_bw_ / 1000000));
return false;
}
@@ -480,7 +490,8 @@
// 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!");
+ DLOGV_IF(kTagResources, "Clock requirement: %f exceeds system limit: %f (MHz)!",
+ (system_clk * hw_res_info_.clk_fudge_factor), max_sde_clk);
return false;
}
@@ -512,6 +523,15 @@
// (v_total / v_active) * (v_active / dst_h)
bw *= FLOAT(display_attributes.v_total) / dst_h;
+ // Bandwidth is the rate at which data needs to be fetched from source to MDP (bytes/time).
+ // On Video mode panel, there is no transfer of data from MDP to panel in horizontal blanking
+ // time (hBP + hFP + hPW). So MDP gets this extra time to fetch data from source. But on the
+ // Command mode panel, data gets transferred from MDP to panel during blanking time as well,
+ // which means MDP needs to fetch the data faster. So pipe bandwidth needs to be adjusted.
+ if (display_ctx->hw_panel_info_.mode == kModeCommand) {
+ bw *= FLOAT(display_attributes.h_total) / FLOAT(display_attributes.x_pixels);
+ }
+
// Bandwidth in GBps
return (bw / 1000000000.0f);
}
@@ -1113,38 +1133,77 @@
}
}
-void ResManager::SetRotatorOutputFormat(const LayerBufferFormat &input_format, bool bwc, bool rot90,
- bool downscale, LayerBufferFormat *output_format) {
+void ResManager::SetRotatorOutputFormat(const LayerBufferFormat &input_format,
+ const bool &is_opaque, const bool &rot90,
+ const bool &downscale, LayerBufferFormat *output_format) {
+ // Initialize the output format with input format by default.
*output_format = input_format;
switch (input_format) {
- case kFormatRGB565:
- if (rot90)
- *output_format = kFormatRGB888;
- break;
+ case kFormatARGB8888:
case kFormatRGBA8888:
- if (bwc)
- *output_format = kFormatBGRA8888;
+ if (is_opaque) {
+ *output_format = kFormatRGB888;
+ }
break;
- case kFormatYCbCr420SemiPlanarVenus:
+ case kFormatBGRA8888:
+ if (is_opaque) {
+ *output_format = kFormatBGR888;
+ }
+ break;
+ case kFormatBGRX8888:
+ *output_format = kFormatBGR888;
+ break;
+ case kFormatXRGB8888:
+ case kFormatRGBX8888:
+ *output_format = kFormatRGB888;
+ break;
case kFormatYCbCr420SemiPlanar:
- if (rot90)
- *output_format = kFormatYCrCb420SemiPlanar;
- break;
- case kFormatYCbCr420SPVenusUbwc:
- if (downscale)
- *output_format = kFormatYCrCb420SemiPlanar;
- break;
- case kFormatYCbCr420Planar:
- case kFormatYCrCb420Planar:
- *output_format = kFormatYCrCb420SemiPlanar;
+ case kFormatYCbCr420SemiPlanarVenus:
+ *output_format = kFormatYCbCr420SemiPlanar;
break;
default:
+ *output_format = input_format;
break;
}
- DLOGV_IF(kTagResources, "Input format %x, Output format = %x, rot90 %d", input_format,
- *output_format, rot90);
+ // TODO(user): UBWC RGB formats will be handled separately
+ if (downscale) {
+ switch (input_format) {
+ case kFormatYCbCr420SPVenusUbwc:
+ *output_format = kFormatYCbCr420SemiPlanar;
+ break;
+ default:
+ break;
+ }
+ } else {
+ if (hw_res_info_.has_ubwc) {
+ switch (input_format) {
+ case kFormatYCbCr420SemiPlanar:
+ case kFormatYCbCr420SemiPlanarVenus:
+ *output_format = kFormatYCbCr420SPVenusUbwc;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ if (rot90) {
+ if (input_format == kFormatYCbCr422H2V1SemiPlanar) {
+ *output_format = kFormatYCbCr422H1V2SemiPlanar;
+ } else if (input_format == kFormatYCbCr422H1V2SemiPlanar) {
+ *output_format = kFormatYCbCr422H2V1SemiPlanar;
+ } else if (input_format == kFormatYCrCb422H2V1SemiPlanar) {
+ *output_format = kFormatYCrCb422H1V2SemiPlanar;
+ } else if (input_format == kFormatYCrCb422H1V2SemiPlanar) {
+ *output_format = kFormatYCrCb422H2V1SemiPlanar;
+ }
+ }
+
+ DLOGV_IF(kTagResources, "Input format = %x, Output format = %x, rot90 = %d, ubwc = %d,"
+ "downscale = %d", input_format, *output_format, rot90, hw_res_info_.has_ubwc,
+ downscale);
return;
}
diff --git a/displayengine/libs/core/res_manager.h b/displayengine/libs/core/res_manager.h
index 7f78b29..1653c0a 100644
--- a/displayengine/libs/core/res_manager.h
+++ b/displayengine/libs/core/res_manager.h
@@ -42,7 +42,7 @@
BufferSyncHandler *buffer_sync_handler);
DisplayError Deinit();
DisplayError RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
- Handle *display_ctx);
+ const HWPanelInfo &hw_panel_info, Handle *display_ctx);
DisplayError UnregisterDisplay(Handle display_ctx);
DisplayError Start(Handle display_ctx);
DisplayError Stop(Handle display_ctx);
@@ -120,6 +120,7 @@
BufferManager *buffer_manager;
DisplayType display_type;
HWBlockType hw_block_id;
+ HWPanelInfo hw_panel_info_;
uint64_t frame_count;
int32_t session_id; // applicable for virtual display sessions only
uint32_t rotate_count;
@@ -196,16 +197,16 @@
bool IsMacroTileFormat(const LayerBuffer *buffer) { return buffer->flags.macro_tile; }
bool IsRotationNeeded(float rotation)
{ return (UINT32(rotation) == 90 || UINT32(rotation) == 270); }
- void RotationConfig(LayerBufferFormat format, const LayerTransform &transform,
- const float &downscale, LayerRect *src_rect,
- struct HWLayerConfig *layer_config, uint32_t *rotate_count);
+ void RotationConfig(const Layer &layer, const float &downscale, LayerRect *src_rect,
+ HWLayerConfig *layer_config, uint32_t *rotate_count);
DisplayError AcquireRotator(DisplayResourceContext *display_resource_ctx,
const uint32_t roate_cnt);
void AssignRotator(HWRotateInfo *rotate, uint32_t *rotate_cnt);
void ClearRotator(DisplayResourceContext *display_resource_ctx);
DisplayError AllocRotatorBuffer(Handle display_ctx, HWLayers *hw_layers);
- void SetRotatorOutputFormat(const LayerBufferFormat &input_format, bool bwc, bool rot90,
- bool downscale, LayerBufferFormat *output_format);
+ void SetRotatorOutputFormat(const LayerBufferFormat &input_format, const bool &is_opaque,
+ const bool &rot90, const bool &downscale,
+ LayerBufferFormat *output_format);
DisplayError AlignPipeConfig(const Layer &layer, const LayerTransform &transform,
HWPipeInfo *left_pipe, HWPipeInfo *right_pipe,
uint32_t align_x, uint32_t align_y);
@@ -224,6 +225,7 @@
float bw_claimed_; // Bandwidth claimed by other display
float clk_claimed_; // Clock claimed by other display
float last_primary_bw_;
+ float max_system_bw_;
uint32_t virtual_count_;
struct HWRotator rotators_[kMaxNumRotator];
BufferAllocator *buffer_allocator_;
diff --git a/displayengine/libs/core/strategy_default.cpp b/displayengine/libs/core/strategy_default.cpp
index e3270b7..48fc79d 100644
--- a/displayengine/libs/core/strategy_default.cpp
+++ b/displayengine/libs/core/strategy_default.cpp
@@ -35,6 +35,8 @@
}
DisplayError StrategyDefault::CreateStrategyInterface(uint16_t version, DisplayType type,
+ const HWResourceInfo *hw_resource_info,
+ const HWPanelInfo *hw_panel_info,
StrategyInterface **interface) {
StrategyDefault *strategy_default = new StrategyDefault();
diff --git a/displayengine/libs/core/strategy_default.h b/displayengine/libs/core/strategy_default.h
index 2ba19f8..7b6f594 100644
--- a/displayengine/libs/core/strategy_default.h
+++ b/displayengine/libs/core/strategy_default.h
@@ -35,6 +35,8 @@
StrategyDefault();
static DisplayError CreateStrategyInterface(uint16_t version, DisplayType type,
+ const HWResourceInfo *hw_resource_info,
+ const HWPanelInfo *hw_panel_info,
StrategyInterface **interface);
static DisplayError DestroyStrategyInterface(StrategyInterface *interface);
diff --git a/displayengine/libs/hwc/hwc_display.cpp b/displayengine/libs/hwc/hwc_display.cpp
index e2327c5..cd21c8a 100644
--- a/displayengine/libs/hwc/hwc_display.cpp
+++ b/displayengine/libs/hwc/hwc_display.cpp
@@ -596,7 +596,7 @@
switch (source) {
case HWC_BLENDING_PREMULT: *target = kBlendingPremultiplied; break;
case HWC_BLENDING_COVERAGE: *target = kBlendingCoverage; break;
- default: *target = kBlendingNone; break;
+ default: *target = kBlendingOpaque; break;
}
}
diff --git a/displayengine/libs/utils/debug_android.cpp b/displayengine/libs/utils/debug_android.cpp
index 96339df..77c82b0 100644
--- a/displayengine/libs/utils/debug_android.cpp
+++ b/displayengine/libs/utils/debug_android.cpp
@@ -89,5 +89,15 @@
return false;
}
+// This property serves to disable/enable partial update
+bool Debug::IsPartialUpdate() {
+ char property[PROPERTY_VALUE_MAX];
+ if (property_get("sde.hwc.partial_update", property, NULL) > 0) {
+ return (atoi(property) ? 1 : true, false);
+ }
+
+ return false;
+}
+
} // namespace sde
diff --git a/displayengine/libs/utils/rect.cpp b/displayengine/libs/utils/rect.cpp
index 8dfd7dd..9b05951 100644
--- a/displayengine/libs/utils/rect.cpp
+++ b/displayengine/libs/utils/rect.cpp
@@ -35,15 +35,33 @@
namespace sde {
-bool IsValidRect(const LayerRect &rect) {
+bool IsValid(const LayerRect &rect) {
return ((rect.bottom > rect.top) && (rect.right > rect.left));
}
+bool IsCongruent(const LayerRect &rect1, const LayerRect &rect2) {
+ return ((rect1.left == rect2.left) &&
+ (rect1.top == rect2.top) &&
+ (rect1.right == rect2.right) &&
+ (rect1.bottom == rect2.bottom));
+}
-LayerRect GetIntersection(const LayerRect &rect1, const LayerRect &rect2) {
+void Log(DebugTag debug_tag, const char *prefix, const LayerRect &roi) {
+ DLOGV_IF(debug_tag, "%s: left = %.0f, top = %.0f, right = %.0f, bottom = %.0f",
+ prefix, roi.left, roi.top, roi.right, roi.bottom);
+}
+
+void Normalize(const uint32_t &align_x, const uint32_t &align_y, LayerRect *rect) {
+ rect->left = ROUND_UP_ALIGN_UP(rect->left, align_x);
+ rect->right = ROUND_UP_ALIGN_DOWN(rect->right, align_x);
+ rect->top = ROUND_UP_ALIGN_UP(rect->top, align_y);
+ rect->bottom = ROUND_UP_ALIGN_DOWN(rect->bottom, align_y);
+}
+
+LayerRect Intersection(const LayerRect &rect1, const LayerRect &rect2) {
LayerRect res;
- if (!IsValidRect(rect1) || !IsValidRect(rect2)) {
+ if (!IsValid(rect1) || !IsValid(rect2)) {
return LayerRect();
}
@@ -52,23 +70,72 @@
res.right = MIN(rect1.right, rect2.right);
res.bottom = MIN(rect1.bottom, rect2.bottom);
- if (!IsValidRect(res)) {
+ if (!IsValid(res)) {
return LayerRect();
}
return res;
}
-void LogRect(DebugTag debug_tag, const char *prefix, const LayerRect &roi) {
- DLOGV_IF(debug_tag, "%s: left = %.0f, top = %.0f, right = %.0f, bottom = %.0f",
- prefix, roi.left, roi.top, roi.right, roi.bottom);
+LayerRect Reposition(const LayerRect &rect, const int &x_offset, const int &y_offset) {
+ LayerRect res;
+
+ if (!IsValid(rect)) {
+ return LayerRect();
+ }
+
+ res.left = rect.left + FLOAT(x_offset);
+ res.top = rect.top + FLOAT(y_offset);
+ res.right = rect.right + FLOAT(x_offset);
+ res.bottom = rect.bottom + FLOAT(y_offset);
+
+ return res;
}
-void NormalizeRect(const uint32_t &align_x, const uint32_t &align_y, LayerRect *rect) {
- rect->left = ROUND_UP_ALIGN_UP(rect->left, align_x);
- rect->right = ROUND_UP_ALIGN_DOWN(rect->right, align_x);
- rect->top = ROUND_UP_ALIGN_UP(rect->top, align_y);
- rect->bottom = ROUND_UP_ALIGN_DOWN(rect->bottom, align_y);
+// Not a geometrical rect deduction. Deducts rect2 from rect1 only if it results a single rect
+LayerRect Subtract(const LayerRect &rect1, const LayerRect &rect2) {
+ LayerRect res;
+
+ res = rect1;
+
+ if ((rect1.left == rect2.left) && (rect1.right == rect2.right)) {
+ if ((rect1.top == rect2.top) && (rect2.bottom <= rect1.bottom)) {
+ res.top = rect2.bottom;
+ } else if ((rect1.bottom == rect2.bottom) && (rect2.top >= rect1.top)) {
+ res.bottom = rect2.top;
+ }
+ } else if ((rect1.top == rect2.top) && (rect1.bottom == rect2.bottom)) {
+ if ((rect1.left == rect2.left) && (rect2.right <= rect1.right)) {
+ res.left = rect2.right;
+ } else if ((rect1.right == rect2.right) && (rect2.left >= rect1.left)) {
+ res.right = rect2.left;
+ }
+ }
+
+ return res;
+}
+
+LayerRect Union(const LayerRect &rect1, const LayerRect &rect2) {
+ LayerRect res;
+
+ if (!IsValid(rect1) && !IsValid(rect2)) {
+ return LayerRect();
+ }
+
+ if(!IsValid(rect1)){
+ return rect2;
+ }
+
+ if(!IsValid(rect2)){
+ return rect1;
+ }
+
+ res.left = MIN(rect1.left, rect2.left);
+ res.top = MIN(rect1.top, rect2.top);
+ res.right = MAX(rect1.right, rect2.right);
+ res.bottom = MAX(rect1.bottom, rect2.bottom);
+
+ return res;
}
} // namespace sde
diff --git a/libgralloc/mapper.cpp b/libgralloc/mapper.cpp
index 8b38952..acac5b4 100644
--- a/libgralloc/mapper.cpp
+++ b/libgralloc/mapper.cpp
@@ -328,18 +328,20 @@
native_handle_t** handle = va_arg(args, native_handle_t**);
private_handle_t* hnd = (private_handle_t*)native_handle_create(
private_handle_t::sNumFds, private_handle_t::sNumInts());
- hnd->magic = private_handle_t::sMagic;
- hnd->fd = fd;
- hnd->flags = private_handle_t::PRIV_FLAGS_USES_ION;
- hnd->size = size;
- hnd->offset = offset;
- hnd->base = uint64_t(base) + offset;
- hnd->gpuaddr = 0;
- hnd->width = width;
- hnd->height = height;
- hnd->format = format;
- *handle = (native_handle_t *)hnd;
- res = 0;
+ if (hnd) {
+ hnd->magic = private_handle_t::sMagic;
+ hnd->fd = fd;
+ hnd->flags = private_handle_t::PRIV_FLAGS_USES_ION;
+ hnd->size = size;
+ hnd->offset = offset;
+ hnd->base = uint64_t(base) + offset;
+ hnd->gpuaddr = 0;
+ hnd->width = width;
+ hnd->height = height;
+ hnd->format = format;
+ *handle = (native_handle_t *)hnd;
+ res = 0;
+ }
break;
}
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 087fe1e..fdd7f0f 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -924,6 +924,15 @@
}
}
+ if(!mDpy && isSecondaryConnected(ctx) &&
+ (qdutils::MDPVersion::getInstance().is8x16() ||
+ qdutils::MDPVersion::getInstance().is8x26() ||
+ qdutils::MDPVersion::getInstance().is8x39()) &&
+ isYuvPresent(ctx, HWC_DISPLAY_VIRTUAL)) {
+ ALOGD_IF(isDebug(), "%s: YUV layer present on secondary", __FUNCTION__);
+ return false;
+ }
+
mCurrentFrame.fbCount = 0;
memcpy(&mCurrentFrame.isFBComposed, &mCurrentFrame.drop,
sizeof(mCurrentFrame.isFBComposed));
@@ -982,6 +991,15 @@
}
}
+ if(!mDpy && isSecondaryConnected(ctx) &&
+ (qdutils::MDPVersion::getInstance().is8x16() ||
+ qdutils::MDPVersion::getInstance().is8x26() ||
+ qdutils::MDPVersion::getInstance().is8x39()) &&
+ isYuvPresent(ctx, HWC_DISPLAY_VIRTUAL)) {
+ ALOGD_IF(isDebug(), "%s: YUV layer present on secondary", __FUNCTION__);
+ return false;
+ }
+
/* We cannot use this composition mode, if:
1. A below layer needs scaling.
2. Overlap is not peripheral to display.