sdm: Add support for dynamic layer mixer resolution change.
1. Define binder API to change layer mixer resolution.
2. Honor layer mixer resolution change request only if the hardware
supports destination scaler.
3. Give preference to panel scaling over destination scaling, as panel
scaling requires less bandwidth.
4. Disable partial update for a frame on mixer resolution change.
CRs-Fixed: 1005180
Change-Id: I3d4e48c8853a941f12703915b33c3a0a4df09af2
diff --git a/sdm/libs/core/comp_manager.cpp b/sdm/libs/core/comp_manager.cpp
index 562186c..289c5d9 100644
--- a/sdm/libs/core/comp_manager.cpp
+++ b/sdm/libs/core/comp_manager.cpp
@@ -69,8 +69,12 @@
return kErrorNone;
}
-DisplayError CompManager::RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
- const HWPanelInfo &hw_panel_info, Handle *display_ctx) {
+DisplayError CompManager::RegisterDisplay(DisplayType type,
+ const HWDisplayAttributes &display_attributes,
+ const HWPanelInfo &hw_panel_info,
+ const HWMixerAttributes &mixer_attributes,
+ const DisplayConfigVariableInfo &fb_config,
+ Handle *display_ctx) {
SCOPE_LOCK(locker_);
DisplayError error = kErrorNone;
@@ -81,7 +85,8 @@
}
Strategy *&strategy = display_comp_ctx->strategy;
- strategy = new Strategy(extension_intf_, type, hw_res_info_, hw_panel_info, attributes);
+ strategy = new Strategy(extension_intf_, type, hw_res_info_, hw_panel_info, mixer_attributes,
+ display_attributes, fb_config);
if (!strategy) {
DLOGE("Unable to create strategy");
delete display_comp_ctx;
@@ -95,7 +100,7 @@
return error;
}
- error = resource_intf_->RegisterDisplay(type, attributes, hw_panel_info,
+ error = resource_intf_->RegisterDisplay(type, display_attributes, hw_panel_info, mixer_attributes,
&display_comp_ctx->display_resource_ctx);
if (error != kErrorNone) {
strategy->Deinit();
@@ -154,17 +159,25 @@
}
DisplayError CompManager::ReconfigureDisplay(Handle comp_handle,
- const HWDisplayAttributes &attributes,
- const HWPanelInfo &hw_panel_info) {
+ const HWDisplayAttributes &display_attributes,
+ const HWPanelInfo &hw_panel_info,
+ const HWMixerAttributes &mixer_attributes,
+ const DisplayConfigVariableInfo &fb_config) {
+ SCOPE_LOCK(locker_);
+
+ DisplayError error = kErrorNone;
DisplayCompositionContext *display_comp_ctx =
reinterpret_cast<DisplayCompositionContext *>(comp_handle);
- resource_intf_->ReconfigureDisplay(display_comp_ctx->display_resource_ctx, attributes,
- hw_panel_info);
+ error = resource_intf_->ReconfigureDisplay(display_comp_ctx->display_resource_ctx,
+ display_attributes, hw_panel_info, mixer_attributes);
+ if (error != kErrorNone) {
+ return error;
+ }
- DisplayError error = kErrorNone;
if (display_comp_ctx->strategy) {
- error = display_comp_ctx->strategy->Reconfigure(hw_panel_info, attributes);
+ error = display_comp_ctx->strategy->Reconfigure(hw_panel_info, display_attributes,
+ mixer_attributes, fb_config);
if (error != kErrorNone) {
DLOGE("Unable to Reconfigure strategy.");
display_comp_ctx->strategy->Deinit();
diff --git a/sdm/libs/core/comp_manager.h b/sdm/libs/core/comp_manager.h
index d6d45c1..5587ab1 100644
--- a/sdm/libs/core/comp_manager.h
+++ b/sdm/libs/core/comp_manager.h
@@ -41,11 +41,15 @@
DisplayError Init(const HWResourceInfo &hw_res_info_, ExtensionInterface *extension_intf,
BufferSyncHandler *buffer_sync_handler);
DisplayError Deinit();
- DisplayError RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
- const HWPanelInfo &hw_panel_info, Handle *res_mgr_hnd);
+ DisplayError RegisterDisplay(DisplayType type, const HWDisplayAttributes &display_attributes,
+ const HWPanelInfo &hw_panel_info,
+ const HWMixerAttributes &mixer_attributes,
+ const DisplayConfigVariableInfo &fb_config, Handle *res_mgr_hnd);
DisplayError UnregisterDisplay(Handle res_mgr_hnd);
- DisplayError ReconfigureDisplay(Handle display_ctx, const HWDisplayAttributes &attributes,
- const HWPanelInfo &hw_panel_info);
+ DisplayError ReconfigureDisplay(Handle display_ctx, const HWDisplayAttributes &display_attributes,
+ const HWPanelInfo &hw_panel_info,
+ const HWMixerAttributes &mixer_attributes,
+ const DisplayConfigVariableInfo &fb_config);
void PrePrepare(Handle display_ctx, HWLayers *hw_layers);
DisplayError Prepare(Handle display_ctx, HWLayers *hw_layers);
DisplayError PostPrepare(Handle display_ctx, HWLayers *hw_layers);
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 0f39cb0..c904e00 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -56,6 +56,18 @@
uint32_t active_index = 0;
hw_intf_->GetActiveConfig(&active_index);
hw_intf_->GetDisplayAttributes(active_index, &display_attributes_);
+ fb_config_ = display_attributes_;
+
+ HWMixerAttributes mixer_attributes;
+ error = hw_intf_->GetMixerAttributes(&mixer_attributes);
+ if (error != kErrorNone) {
+ return error;
+ }
+ mixer_attributes_ = mixer_attributes;
+
+ // Override x_pixels and y_pixels of frame buffer with mixer width and height
+ fb_config_.x_pixels = mixer_attributes.width;
+ fb_config_.y_pixels = mixer_attributes.height;
HWScaleLutInfo lut_info = {};
error = comp_manager_->GetScaleLutConfig(&lut_info);
@@ -67,8 +79,8 @@
goto CleanupOnError;
}
- error = comp_manager_->RegisterDisplay(display_type_, display_attributes_,
- hw_panel_info_, &display_comp_ctx_);
+ error = comp_manager_->RegisterDisplay(display_type_, display_attributes_, hw_panel_info_,
+ mixer_attributes, fb_config_, &display_comp_ctx_);
if (error != kErrorNone) {
goto CleanupOnError;
}
@@ -161,17 +173,24 @@
return kErrorParameters;
}
- auto gpu_target_layer_dst_xpixels = gpu_target_layer->dst_rect.right;
- auto gpu_target_layer_dst_ypixels = gpu_target_layer->dst_rect.bottom;
+ float layer_mixer_width = FLOAT(mixer_attributes_.width);
+ float layer_mixer_height = FLOAT(mixer_attributes_.height);
+ float fb_width = FLOAT(fb_config_.x_pixels);
+ float fb_height = FLOAT(fb_config_.y_pixels);
+ LayerRect src_domain = (LayerRect){0.0f, 0.0f, fb_width, fb_height};
+ LayerRect dst_domain = (LayerRect){0.0f, 0.0f, layer_mixer_width, layer_mixer_height};
+ LayerRect out_rect = gpu_target_layer->dst_rect;
- HWDisplayAttributes display_attrib;
- uint32_t active_index = 0;
- hw_intf_->GetActiveConfig(&active_index);
- hw_intf_->GetDisplayAttributes(active_index, &display_attrib);
+ ScaleRect(src_domain, dst_domain, gpu_target_layer->dst_rect, &out_rect);
- if (gpu_target_layer_dst_xpixels > display_attrib.x_pixels ||
- gpu_target_layer_dst_ypixels > display_attrib.y_pixels) {
- DLOGE("GPU target layer dst rect is not with in limits");
+ auto gpu_target_layer_dst_xpixels = out_rect.right - out_rect.left;
+ auto gpu_target_layer_dst_ypixels = out_rect.bottom - out_rect.top;
+
+ if (gpu_target_layer_dst_xpixels > mixer_attributes_.width ||
+ gpu_target_layer_dst_ypixels > mixer_attributes_.height) {
+ DLOGE("GPU target layer dst rect is not with in limits gpu wxh %fx%f mixer wxh %dx%d",
+ gpu_target_layer_dst_xpixels, gpu_target_layer_dst_ypixels, mixer_attributes_.width,
+ mixer_attributes_.height);
return kErrorParameters;
}
@@ -255,15 +274,15 @@
DisplayError DisplayBase::Commit(LayerStack *layer_stack) {
SCOPE_LOCK(locker_);
- if (!layer_stack) {
- return kErrorParameters;
- }
-
if (!active_) {
pending_commit_ = false;
return kErrorPermission;
}
+ if (!layer_stack) {
+ return kErrorParameters;
+ }
+
if (!pending_commit_) {
DLOGE("Commit: Corresponding Prepare() is not called for display = %d", display_type_);
return kErrorUndefined;
@@ -481,26 +500,7 @@
return error;
}
- HWDisplayAttributes attrib;
- error = hw_intf_->GetDisplayAttributes(index, &attrib);
- if (error != kErrorNone) {
- return error;
- }
-
- hw_intf_->GetHWPanelInfo(&hw_panel_info_);
-
- if (display_comp_ctx_) {
- comp_manager_->UnregisterDisplay(display_comp_ctx_);
- }
-
- error = comp_manager_->RegisterDisplay(display_type_, attrib, hw_panel_info_,
- &display_comp_ctx_);
-
- if (error == kErrorNone) {
- DisablePartialUpdateOneFrameLocked();
- }
-
- return error;
+ return ReconfigureDisplay();
}
DisplayError DisplayBase::SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
@@ -534,11 +534,6 @@
return kErrorNotSupported;
}
-DisplayError DisplayBase::IsScalingValid(const LayerRect &crop, const LayerRect &dst,
- bool rotate90) {
- return comp_manager_->ValidateScaling(crop, dst, rotate90);
-}
-
DisplayError DisplayBase::SetPanelBrightness(int level) {
return kErrorNotSupported;
}
@@ -871,4 +866,130 @@
return error;
}
+DisplayError DisplayBase::ReconfigureDisplay() {
+ DisplayError error = kErrorNone;
+ HWDisplayAttributes display_attributes;
+ HWMixerAttributes mixer_attributes;
+ HWPanelInfo hw_panel_info;
+ uint32_t active_index = 0;
+
+ error = hw_intf_->GetActiveConfig(&active_index);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ error = hw_intf_->GetDisplayAttributes(active_index, &display_attributes);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ error = hw_intf_->GetMixerAttributes(&mixer_attributes);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ error = hw_intf_->GetHWPanelInfo(&hw_panel_info);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ if (display_attributes == display_attributes_ && mixer_attributes == mixer_attributes_ &&
+ hw_panel_info == hw_panel_info_) {
+ return kErrorNone;
+ }
+
+ error = comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes, hw_panel_info,
+ mixer_attributes, fb_config_);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ if (mixer_attributes != mixer_attributes_) {
+ DisablePartialUpdateOneFrameLocked();
+ }
+
+ display_attributes_ = display_attributes;
+ mixer_attributes_ = mixer_attributes;
+ hw_panel_info_ = hw_panel_info;
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::SetMixerResolution(uint32_t width, uint32_t height) {
+ SCOPE_LOCK(locker_);
+ return SetMixerResolutionLocked(width, height);
+}
+
+DisplayError DisplayBase::GetMixerResolution(uint32_t *width, uint32_t *height) {
+ SCOPE_LOCK(locker_);
+ return GetMixerResolutionLocked(width, height);
+}
+
+DisplayError DisplayBase::GetMixerResolutionLocked(uint32_t *width, uint32_t *height) {
+ if (!width || !height) {
+ return kErrorParameters;
+ }
+
+ *width = mixer_attributes_.width;
+ *height = mixer_attributes_.height;
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::SetFrameBufferConfig(const DisplayConfigVariableInfo &variable_info) {
+ SCOPE_LOCK(locker_);
+ return SetFrameBufferConfigLocked(variable_info);
+}
+
+DisplayError DisplayBase::SetFrameBufferConfigLocked(
+ const DisplayConfigVariableInfo &variable_info) {
+ uint32_t width = variable_info.x_pixels;
+ uint32_t height = variable_info.y_pixels;
+
+ if (width == 0 || height == 0) {
+ DLOGE("Unsupported resolution: (%dx%d)", width, height);
+ return kErrorParameters;
+ }
+
+ // Create rects to represent the new source and destination crops
+ LayerRect crop = LayerRect(0, 0, FLOAT(width), FLOAT(height));
+ LayerRect dst = LayerRect(0, 0, FLOAT(mixer_attributes_.width), FLOAT(mixer_attributes_.height));
+ // Set rotate90 to false since this is taken care of during regular composition.
+ bool rotate90 = false;
+
+ DisplayError error = comp_manager_->ValidateScaling(crop, dst, rotate90);
+ if (error != kErrorNone) {
+ DLOGE("Unsupported resolution: (%dx%d)", width, height);
+ return kErrorParameters;
+ }
+
+ error = comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes_, hw_panel_info_,
+ mixer_attributes_, variable_info);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ fb_config_.x_pixels = width;
+ fb_config_.y_pixels = height;
+
+ DLOGI("New framebuffer resolution (%dx%d)", fb_config_.x_pixels, fb_config_.y_pixels);
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info) {
+ SCOPE_LOCK(locker_);
+ return GetFrameBufferConfigLocked(variable_info);
+}
+
+DisplayError DisplayBase::GetFrameBufferConfigLocked(DisplayConfigVariableInfo *variable_info) {
+ if (!variable_info) {
+ return kErrorParameters;
+ }
+
+ *variable_info = fb_config_;
+
+ return kErrorNone;
+}
+
} // namespace sdm
diff --git a/sdm/libs/core/display_base.h b/sdm/libs/core/display_base.h
index c761d00..e070bed 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -69,7 +69,6 @@
DisplayError ControlPartialUpdate(bool enable, uint32_t *pending) final;
DisplayError DisablePartialUpdateOneFrame() final;
virtual DisplayError SetDisplayMode(uint32_t mode);
- virtual DisplayError IsScalingValid(const LayerRect &crop, const LayerRect &dst, bool rotate90);
virtual bool IsUnderscanSupported();
virtual DisplayError SetPanelBrightness(int level);
virtual DisplayError OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level);
@@ -85,6 +84,10 @@
virtual DisplayError GetRefreshRateRange(uint32_t *min_refresh_rate, uint32_t *max_refresh_rate);
virtual DisplayError GetPanelBrightness(int *level);
virtual DisplayError SetVSyncState(bool enable);
+ DisplayError SetMixerResolution(uint32_t width, uint32_t height) final;
+ DisplayError GetMixerResolution(uint32_t *width, uint32_t *height) final;
+ DisplayError SetFrameBufferConfig(const DisplayConfigVariableInfo &variable_info) final;
+ DisplayError GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info) final;
protected:
virtual DisplayError PrepareLocked(LayerStack *layer_stack);
@@ -99,12 +102,20 @@
virtual DisplayError DisablePartialUpdateOneFrameLocked() {
return kErrorNotSupported;
}
+ virtual DisplayError SetMixerResolutionLocked(uint32_t width, uint32_t height) {
+ return kErrorNotSupported;
+ }
+ virtual DisplayError GetMixerResolutionLocked(uint32_t *width, uint32_t *height);
+ virtual DisplayError SetFrameBufferConfigLocked(const DisplayConfigVariableInfo &variable_info);
+ virtual DisplayError GetFrameBufferConfigLocked(DisplayConfigVariableInfo *variable_info);
+
// DumpImpl method
void AppendDump(char *buffer, uint32_t length);
bool IsRotationRequired(HWLayers *hw_layers);
const char *GetName(const LayerComposition &composition);
DisplayError ValidateGPUTarget(LayerStack *layer_stack);
+ DisplayError ReconfigureDisplay();
Locker locker_;
DisplayType display_type_;
@@ -112,7 +123,6 @@
HWDeviceType hw_device_type_;
HWInterface *hw_intf_ = NULL;
HWPanelInfo hw_panel_info_;
- HWDisplayAttributes display_attributes_;
BufferSyncHandler *buffer_sync_handler_ = NULL;
CompManager *comp_manager_ = NULL;
RotatorInterface *rotator_intf_ = NULL;
@@ -136,6 +146,9 @@
int32_t color_mode_ = 0;
typedef std::map<std::string, SDEDisplayMode *> ColorModeMap;
ColorModeMap color_mode_map_ = {};
+ HWDisplayAttributes display_attributes_ = {};
+ HWMixerAttributes mixer_attributes_ = {};
+ DisplayConfigVariableInfo fb_config_ = {};
private:
// Unused
diff --git a/sdm/libs/core/display_hdmi.cpp b/sdm/libs/core/display_hdmi.cpp
index c932975..11c268a 100644
--- a/sdm/libs/core/display_hdmi.cpp
+++ b/sdm/libs/core/display_hdmi.cpp
@@ -164,12 +164,6 @@
return DisplayBase::SetDisplayMode(mode);
}
-DisplayError DisplayHDMI::IsScalingValid(const LayerRect &crop, const LayerRect &dst,
- bool rotate90) {
- SCOPE_LOCK(locker_);
- return DisplayBase::IsScalingValid(crop, dst, rotate90);
-}
-
DisplayError DisplayHDMI::GetRefreshRateRange(uint32_t *min_refresh_rate,
uint32_t *max_refresh_rate) {
SCOPE_LOCK(locker_);
@@ -319,9 +313,6 @@
void DisplayHDMI::SetS3DMode(LayerStack *layer_stack) {
uint32_t s3d_layer_count = 0;
HWS3DMode s3d_mode = kS3DModeNone;
- HWPanelInfo panel_info;
- HWDisplayAttributes display_attributes;
- uint32_t active_index = 0;
uint32_t layer_count = UINT32(layer_stack->layers.size());
// S3D mode is supported for the following scenarios:
@@ -356,15 +347,7 @@
layer_stack->flags.s3d_mode_present = true;
}
- hw_intf_->GetHWPanelInfo(&panel_info);
- hw_intf_->GetActiveConfig(&active_index);
- hw_intf_->GetDisplayAttributes(active_index, &display_attributes);
-
- if (panel_info != hw_panel_info_ || display_attributes != display_attributes_) {
- comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes, panel_info);
- hw_panel_info_ = panel_info;
- display_attributes_ = display_attributes;
- }
+ DisplayBase::ReconfigureDisplay();
}
void DisplayHDMI::CECMessage(char *message) {
diff --git a/sdm/libs/core/display_hdmi.h b/sdm/libs/core/display_hdmi.h
index 543f81c..b3ec9af 100644
--- a/sdm/libs/core/display_hdmi.h
+++ b/sdm/libs/core/display_hdmi.h
@@ -53,7 +53,6 @@
virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
virtual DisplayError SetDisplayMode(uint32_t mode);
- virtual DisplayError IsScalingValid(const LayerRect &crop, const LayerRect &dst, bool rotate90);
virtual DisplayError GetRefreshRateRange(uint32_t *min_refresh_rate, uint32_t *max_refresh_rate);
virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
virtual bool IsUnderscanSupported();
diff --git a/sdm/libs/core/display_primary.cpp b/sdm/libs/core/display_primary.cpp
index 30922f6..b1b7979 100644
--- a/sdm/libs/core/display_primary.cpp
+++ b/sdm/libs/core/display_primary.cpp
@@ -24,6 +24,11 @@
#include <utils/constants.h>
#include <utils/debug.h>
+#include <utils/rect.h>
+#include <map>
+#include <algorithm>
+#include <functional>
+#include <vector>
#include "display_primary.h"
#include "hw_interface.h"
@@ -86,13 +91,26 @@
return error;
}
+DisplayError DisplayPrimary::PrepareLocked(LayerStack *layer_stack) {
+ DisplayError error = kErrorNone;
+ uint32_t new_mixer_width = 0;
+ uint32_t new_mixer_height = 0;
+ uint32_t display_width = display_attributes_.x_pixels;
+ uint32_t display_height = display_attributes_.y_pixels;
+
+ if (NeedsMixerReconfiguration(layer_stack, &new_mixer_width, &new_mixer_height)) {
+ error = ReconfigureMixer(new_mixer_width, new_mixer_height);
+ if (error != kErrorNone) {
+ ReconfigureMixer(display_width, display_height);
+ }
+ }
+
+ return DisplayBase::PrepareLocked(layer_stack);
+}
+
DisplayError DisplayPrimary::CommitLocked(LayerStack *layer_stack) {
DisplayError error = kErrorNone;
- HWPanelInfo panel_info;
- HWDisplayAttributes display_attributes;
- uint32_t active_index = 0;
-
// Enabling auto refresh is async and needs to happen before commit ioctl
if (hw_panel_info_.mode == kModeCommand) {
hw_intf_->SetAutoRefresh(layer_stack->flags.single_buffered_layer_present);
@@ -105,14 +123,7 @@
return error;
}
- hw_intf_->GetHWPanelInfo(&panel_info);
- hw_intf_->GetActiveConfig(&active_index);
- hw_intf_->GetDisplayAttributes(active_index, &display_attributes);
-
- if (panel_info != hw_panel_info_) {
- error = comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes, panel_info);
- hw_panel_info_ = panel_info;
- }
+ DisplayBase::ReconfigureDisplay();
if (hw_panel_info_.mode == kModeVideo) {
if (set_idle_timeout && !layer_stack->flags.single_buffered_layer_present) {
@@ -241,12 +252,6 @@
return hw_intf_->SetPanelBrightness(level);
}
-DisplayError DisplayPrimary::IsScalingValid(const LayerRect &crop, const LayerRect &dst,
- bool rotate90) {
- SCOPE_LOCK(locker_);
- return DisplayBase::IsScalingValid(crop, dst, rotate90);
-}
-
DisplayError DisplayPrimary::GetRefreshRateRange(uint32_t *min_refresh_rate,
uint32_t *max_refresh_rate) {
SCOPE_LOCK(locker_);
@@ -279,21 +284,7 @@
return error;
}
- HWDisplayAttributes display_attributes;
- uint32_t active_index = 0;
- error = hw_intf_->GetActiveConfig(&active_index);
- if (error != kErrorNone) {
- return error;
- }
-
- error = hw_intf_->GetDisplayAttributes(active_index, &display_attributes);
- if (error != kErrorNone) {
- return error;
- }
-
- comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes, hw_panel_info_);
-
- return kErrorNone;
+ return DisplayBase::ReconfigureDisplay();
}
void DisplayPrimary::AppendDump(char *buffer, uint32_t length) {
@@ -370,5 +361,92 @@
return kErrorNone;
}
+DisplayError DisplayPrimary::SetMixerResolutionLocked(uint32_t width, uint32_t height) {
+ return ReconfigureMixer(width, height);
+}
+
+DisplayError DisplayPrimary::ReconfigureMixer(uint32_t width, uint32_t height) {
+ DisplayError error = kErrorNone;
+
+ HWMixerAttributes mixer_attributes;
+ mixer_attributes.width = width;
+ mixer_attributes.height = height;
+
+ error = hw_intf_->SetMixerAttributes(mixer_attributes);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ return DisplayBase::ReconfigureDisplay();
+}
+
+bool DisplayPrimary::NeedsMixerReconfiguration(LayerStack *layer_stack, uint32_t *new_mixer_width,
+ uint32_t *new_mixer_height) {
+ uint32_t layer_count = UINT32(layer_stack->layers.size());
+
+ uint32_t fb_width = fb_config_.x_pixels;
+ uint32_t fb_height = fb_config_.y_pixels;
+ uint32_t fb_area = fb_width * fb_height;
+ LayerRect fb_rect = (LayerRect) {0.0f, 0.0f, FLOAT(fb_width), FLOAT(fb_height)};
+ uint32_t mixer_width = mixer_attributes_.width;
+ uint32_t mixer_height = mixer_attributes_.height;
+
+ RectOrientation fb_orientation = GetOrientation(fb_rect);
+ uint32_t max_layer_area = 0;
+ uint32_t max_area_layer_index = 0;
+ std::vector<Layer *> layers = layer_stack->layers;
+
+ for (uint32_t i = 0; i < layer_count; i++) {
+ Layer *layer = layers.at(i);
+ LayerBuffer *layer_buffer = layer->input_buffer;
+
+ if (!layer_buffer->flags.video) {
+ continue;
+ }
+
+ uint32_t layer_width = UINT32(layer->src_rect.right - layer->src_rect.left);
+ uint32_t layer_height = UINT32(layer->src_rect.bottom - layer->src_rect.top);
+ uint32_t layer_area = layer_width * layer_height;
+
+ if (layer_area > max_layer_area) {
+ max_layer_area = layer_area;
+ max_area_layer_index = i;
+ }
+ }
+
+ if (max_layer_area > fb_area) {
+ Layer *layer = layers.at(max_area_layer_index);
+
+ uint32_t layer_width = UINT32(layer->src_rect.right - layer->src_rect.left);
+ uint32_t layer_height = UINT32(layer->src_rect.bottom - layer->src_rect.top);
+ LayerRect layer_rect = (LayerRect){0.0f, 0.0f, FLOAT(layer_width), FLOAT(layer_height)};
+
+ RectOrientation layer_orientation = GetOrientation(layer_rect);
+ if (layer_orientation != kOrientationUnknown &&
+ fb_orientation != kOrientationUnknown) {
+ if (layer_orientation != fb_orientation) {
+ Swap(layer_width, layer_height);
+ }
+ }
+
+ // Align the width and height according to fb's aspect ratio
+ layer_width = UINT32((FLOAT(fb_width) / FLOAT(fb_height)) * layer_height);
+
+ *new_mixer_width = layer_width;
+ *new_mixer_height = layer_height;
+
+ return true;
+ } else {
+ if (fb_width != mixer_width || fb_height != mixer_height) {
+ *new_mixer_width = fb_width;
+ *new_mixer_height = fb_height;
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
} // namespace sdm
diff --git a/sdm/libs/core/display_primary.h b/sdm/libs/core/display_primary.h
index a699923..15c9dfa 100644
--- a/sdm/libs/core/display_primary.h
+++ b/sdm/libs/core/display_primary.h
@@ -52,7 +52,6 @@
virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
virtual DisplayError SetDisplayMode(uint32_t mode);
- virtual DisplayError IsScalingValid(const LayerRect &crop, const LayerRect &dst, bool rotate90);
virtual DisplayError GetRefreshRateRange(uint32_t *min_refresh_rate, uint32_t *max_refresh_rate);
virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
virtual bool IsUnderscanSupported();
@@ -69,9 +68,15 @@
virtual void CECMessage(char *message) { }
private:
+ virtual DisplayError PrepareLocked(LayerStack *layer_stack);
virtual DisplayError CommitLocked(LayerStack *layer_stack);
virtual DisplayError ControlPartialUpdateLocked(bool enable, uint32_t *pending);
virtual DisplayError DisablePartialUpdateOneFrameLocked();
+ virtual DisplayError SetMixerResolutionLocked(uint32_t width, uint32_t height);
+
+ bool NeedsMixerReconfiguration(LayerStack *layer_stack, uint32_t *new_mixer_width,
+ uint32_t *new_mixer_height);
+ DisplayError ReconfigureMixer(uint32_t width, uint32_t height);
uint32_t idle_timeout_ms_ = 0;
std::vector<const char *> event_list_ = {"vsync_event", "show_blank_event", "idle_notify",
diff --git a/sdm/libs/core/display_virtual.cpp b/sdm/libs/core/display_virtual.cpp
index 5bd40f7..cafb986 100644
--- a/sdm/libs/core/display_virtual.cpp
+++ b/sdm/libs/core/display_virtual.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
@@ -113,8 +113,6 @@
}
DisplayError DisplayVirtual::SetActiveConfigLocked(DisplayConfigVariableInfo *variable_info) {
- DisplayError error = kErrorNone;
-
if (!variable_info) {
return kErrorParameters;
}
@@ -123,19 +121,17 @@
display_attributes_.y_pixels = variable_info->y_pixels;
display_attributes_.fps = variable_info->fps;
+ HWMixerAttributes mixer_attributes;
+ mixer_attributes.width = variable_info->x_pixels;;
+ mixer_attributes.height = variable_info->y_pixels;
// if display is already connected, unregister display from composition manager and register
// the display with new configuration.
if (display_comp_ctx_) {
comp_manager_->UnregisterDisplay(display_comp_ctx_);
}
- error = comp_manager_->RegisterDisplay(display_type_, display_attributes_, hw_panel_info_,
- &display_comp_ctx_);
- if (error != kErrorNone) {
- return error;
- }
-
- return error;
+ return comp_manager_->RegisterDisplay(display_type_, display_attributes_, hw_panel_info_,
+ mixer_attributes, fb_config_, &display_comp_ctx_);
}
DisplayError DisplayVirtual::SetVSyncState(bool enable) {
@@ -155,12 +151,6 @@
return DisplayBase::SetDisplayMode(mode);
}
-DisplayError DisplayVirtual::IsScalingValid(const LayerRect &crop, const LayerRect &dst,
- bool rotate90) {
- SCOPE_LOCK(locker_);
- return DisplayBase::IsScalingValid(crop, dst, rotate90);
-}
-
DisplayError DisplayVirtual::GetRefreshRateRange(uint32_t *min_refresh_rate,
uint32_t *max_refresh_rate) {
SCOPE_LOCK(locker_);
diff --git a/sdm/libs/core/display_virtual.h b/sdm/libs/core/display_virtual.h
index e1af95e..ba164ae 100644
--- a/sdm/libs/core/display_virtual.h
+++ b/sdm/libs/core/display_virtual.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
@@ -51,7 +51,6 @@
virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
virtual DisplayError SetDisplayMode(uint32_t mode);
- virtual DisplayError IsScalingValid(const LayerRect &crop, const LayerRect &dst, bool rotate90);
virtual DisplayError GetRefreshRateRange(uint32_t *min_refresh_rate, uint32_t *max_refresh_rate);
virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
virtual bool IsUnderscanSupported();
@@ -64,7 +63,6 @@
return kErrorNotSupported;
}
virtual DisplayError SetActiveConfigLocked(DisplayConfigVariableInfo *variable_info);
- HWDisplayAttributes display_attributes_;
};
} // namespace sdm
diff --git a/sdm/libs/core/fb/hw_device.cpp b/sdm/libs/core/fb/hw_device.cpp
index 546490a..6b7dd2e 100644
--- a/sdm/libs/core/fb/hw_device.cpp
+++ b/sdm/libs/core/fb/hw_device.cpp
@@ -238,8 +238,10 @@
mdp_layer.bg_color = layer->solid_fill_color;
// HWScaleData to MDP driver
- hw_scale_->SetHWScaleData(pipe_info->scale_data, mdp_layer_count, &mdp_layer);
- mdp_layer.scale = hw_scale_->GetScaleDataRef(mdp_layer_count);
+ hw_scale_->SetHWScaleData(pipe_info->scale_data, mdp_layer_count, &mdp_commit,
+ pipe_info->sub_block_type);
+ mdp_layer.scale = hw_scale_->GetScaleDataRef(mdp_layer_count, pipe_info->sub_block_type);
+
mdp_layer_count++;
DLOGV_IF(kTagDriverConfig, "******************* Layer[%d] %s pipe Input ******************",
diff --git a/sdm/libs/core/fb/hw_device.h b/sdm/libs/core/fb/hw_device.h
index 7311271..d5b18de 100644
--- a/sdm/libs/core/fb/hw_device.h
+++ b/sdm/libs/core/fb/hw_device.h
@@ -84,6 +84,12 @@
virtual DisplayError SetAutoRefresh(bool enable) { return kErrorNone; }
virtual DisplayError SetS3DMode(HWS3DMode s3d_mode);
virtual DisplayError SetScaleLutConfig(HWScaleLutInfo *lut_info);
+ virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes) {
+ return kErrorNotSupported;
+ }
+ virtual DisplayError GetMixerAttributes(HWMixerAttributes *mixer_attributes) {
+ return kErrorNotSupported;
+ }
// For HWDevice derivatives
virtual DisplayError Init();
diff --git a/sdm/libs/core/fb/hw_hdmi.cpp b/sdm/libs/core/fb/hw_hdmi.cpp
index db7a2d9..3dfac8a 100644
--- a/sdm/libs/core/fb/hw_hdmi.cpp
+++ b/sdm/libs/core/fb/hw_hdmi.cpp
@@ -252,10 +252,8 @@
display_attributes->y_dpi = 0;
display_attributes->fps = timing_mode->refresh_rate / 1000;
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;
display_attributes->h_total += h_blanking;
}
@@ -755,5 +753,21 @@
return kErrorNone;
}
+DisplayError HWHDMI::GetMixerAttributes(HWMixerAttributes *mixer_attributes) {
+ if (!mixer_attributes) {
+ return kErrorParameters;
+ }
+
+ HWDisplayAttributes display_attributes;
+ GetDisplayAttributes(active_config_index_, &display_attributes);
+
+ mixer_attributes->width = display_attributes.x_pixels;
+ mixer_attributes->height = display_attributes.y_pixels;
+ mixer_attributes->split_left = display_attributes.is_device_split ?
+ (display_attributes.x_pixels / 2) : mixer_attributes->width;
+
+ return kErrorNone;
+}
+
} // namespace sdm
diff --git a/sdm/libs/core/fb/hw_hdmi.h b/sdm/libs/core/fb/hw_hdmi.h
index aa5e2a0..833b3d3 100644
--- a/sdm/libs/core/fb/hw_hdmi.h
+++ b/sdm/libs/core/fb/hw_hdmi.h
@@ -69,6 +69,7 @@
virtual DisplayError Validate(HWLayers *hw_layers);
virtual DisplayError SetS3DMode(HWS3DMode s3d_mode);
virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
+ virtual DisplayError GetMixerAttributes(HWMixerAttributes *mixer_attributes);
private:
DisplayError ReadEDIDInfo();
diff --git a/sdm/libs/core/fb/hw_info.cpp b/sdm/libs/core/fb/hw_info.cpp
index f6f664a..25bb01c 100644
--- a/sdm/libs/core/fb/hw_info.cpp
+++ b/sdm/libs/core/fb/hw_info.cpp
@@ -31,6 +31,7 @@
#include <utils/constants.h>
#include <utils/debug.h>
#include <utils/sys.h>
+#include <dlfcn.h>
#include <algorithm>
#include <iostream>
@@ -241,6 +242,16 @@
hw_resource->system_overhead_lines = UINT32(atoi(tokens[1]));
} else if (!strncmp(tokens[0], "wb_intf_index", strlen("wb_intf_index"))) {
hw_resource->writeback_index = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "dest_scaler_count", strlen("dest_scaler_count"))) {
+ hw_resource->hw_dest_scalar_info.count = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "max_dest_scale_up", strlen("max_dest_scale_up"))) {
+ hw_resource->hw_dest_scalar_info.max_scale_up = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "max_dest_scaler_input_width",
+ strlen("max_dest_scaler_input_width"))) {
+ hw_resource->hw_dest_scalar_info.max_input_width = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "max_dest_scaler_output_width",
+ strlen("max_dest_scaler_output_width"))) {
+ hw_resource->hw_dest_scalar_info.max_output_width = UINT32(atoi(tokens[1]));
} else if (!strncmp(tokens[0], "features", strlen("features"))) {
for (uint32_t i = 0; i < token_count; i++) {
if (!strncmp(tokens[i], "bwc", strlen("bwc"))) {
@@ -316,6 +327,14 @@
}
}
+ // Disable destination scalar count to 0 if extension library is not present
+ void *extension_lib = ::dlopen("libsdmextension.so", RTLD_NOW);
+ if (!extension_lib) {
+ hw_resource->hw_dest_scalar_info.count = 0;
+ } else {
+ ::dlclose(extension_lib);
+ }
+
Sys::fclose_(fileptr);
DLOGI("SDE Version = %d, SDE Revision = %x, RGB = %d, VIG = %d, DMA = %d, Cursor = %d",
diff --git a/sdm/libs/core/fb/hw_primary.cpp b/sdm/libs/core/fb/hw_primary.cpp
index 84eea2a..3d0c776 100644
--- a/sdm/libs/core/fb/hw_primary.cpp
+++ b/sdm/libs/core/fb/hw_primary.cpp
@@ -40,6 +40,7 @@
#include <utils/sys.h>
#include <core/display_interface.h>
#include <linux/msm_mdp_ext.h>
+#include <utils/rect.h>
#include <string>
@@ -99,11 +100,18 @@
return error;
}
+ uint32_t dest_scalar_count = hw_resource_.hw_dest_scalar_info.count;
+ if (dest_scalar_count) {
+ mdp_dest_scalar_data_ = new mdp_destination_scaler_data[dest_scalar_count];
+ }
+
error = PopulateDisplayAttributes();
if (error != kErrorNone) {
return error;
}
+ UpdateMixerAttributes();
+
// Disable HPD at start if HDMI is external, it will be enabled later when the display powers on
// This helps for framework reboot or adb shell stop/start
EnableHotPlugDetection(0);
@@ -199,6 +207,8 @@
}
DisplayError HWPrimary::Deinit() {
+ delete [] mdp_dest_scalar_data_;
+
return HWDevice::Deinit();
}
@@ -273,8 +283,6 @@
display_attributes_.vsync_period_ns = UINT32(1000000000L / display_attributes_.fps);
display_attributes_.is_device_split = (hw_panel_info_.split_info.left_split ||
(var_screeninfo.xres > hw_resource_.max_mixer_width)) ? true : false;
- display_attributes_.split_left = hw_panel_info_.split_info.left_split ?
- hw_panel_info_.split_info.left_split : display_attributes_.x_pixels / 2;
display_attributes_.h_total += display_attributes_.is_device_split ? h_blanking : 0;
return kErrorNone;
@@ -305,6 +313,7 @@
DLOGI("Successfully set config %u", index);
PopulateHWPanelInfo();
PopulateDisplayAttributes();
+ UpdateMixerAttributes();
active_config_index_ = index;
} else {
DLOGE("Writing config index %u failed with error: %s", index, strerror(errno));
@@ -381,15 +390,27 @@
return kErrorNone;
}
-DisplayError HWPrimary::Validate(HWLayers *hw_layers) {
- LayerStack *stack = hw_layers->info.stack;
+void HWPrimary::ResetDisplayParams() {
+ uint32_t dst_scalar_cnt = hw_resource_.hw_dest_scalar_info.count;
HWDevice::ResetDisplayParams();
+ if (mdp_dest_scalar_data_) {
+ memset(mdp_dest_scalar_data_, 0, sizeof(mdp_dest_scalar_data_) * dst_scalar_cnt);
+ mdp_disp_commit_.commit_v1.dest_scaler = mdp_dest_scalar_data_;
+ }
+}
+
+DisplayError HWPrimary::Validate(HWLayers *hw_layers) {
+ HWLayersInfo &hw_layer_info = hw_layers->info;
+ LayerStack *stack = hw_layer_info.stack;
+
+ ResetDisplayParams();
+
mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1;
- LayerRect left_roi = hw_layers->info.left_partial_update;
- LayerRect right_roi = hw_layers->info.right_partial_update;
+ LayerRect left_roi = hw_layer_info.left_partial_update;
+ LayerRect right_roi = hw_layer_info.right_partial_update;
mdp_commit.left_roi.x = UINT32(left_roi.left);
mdp_commit.left_roi.y = UINT32(left_roi.top);
mdp_commit.left_roi.w = UINT32(left_roi.right - left_roi.left);
@@ -398,8 +419,8 @@
// SDM treats ROI as one full coordinate system.
// In case source split is disabled, However, Driver assumes Mixer to operate in
// different co-ordinate system.
- if (!hw_resource_.is_src_split) {
- mdp_commit.right_roi.x = UINT32(right_roi.left) - hw_panel_info_.split_info.left_split;
+ if (!hw_resource_.is_src_split && IsValid(right_roi)) {
+ mdp_commit.right_roi.x = UINT32(right_roi.left) - mixer_attributes_.split_left;
mdp_commit.right_roi.y = UINT32(right_roi.top);
mdp_commit.right_roi.w = UINT32(right_roi.right - right_roi.left);
mdp_commit.right_roi.h = UINT32(right_roi.bottom - right_roi.top);
@@ -424,6 +445,40 @@
DLOGI_IF(kTagDriverConfig, "****************************************************************");
}
+ uint32_t index = 0;
+ for (uint32_t i = 0; i < hw_resource_.hw_dest_scalar_info.count; i++) {
+ DestScaleInfoMap::iterator it = hw_layer_info.dest_scale_info_map.find(i);
+
+ if (it == hw_layer_info.dest_scale_info_map.end()) {
+ continue;
+ }
+
+ HWDestScaleInfo *dest_scale_info = it->second;
+
+ mdp_destination_scaler_data *dest_scalar_data = &mdp_dest_scalar_data_[index];
+ hw_scale_->SetHWScaleData(dest_scale_info->scale_data, index, &mdp_commit,
+ kHWDestinationScalar);
+
+ if (dest_scale_info->scale_update) {
+ dest_scalar_data->flags |= MDP_DESTSCALER_SCALE_UPDATE;
+ }
+
+ dest_scalar_data->dest_scaler_ndx = i;
+ dest_scalar_data->lm_width = dest_scale_info->mixer_width;
+ dest_scalar_data->lm_height = dest_scale_info->mixer_height;
+ dest_scalar_data->scale = reinterpret_cast <uint64_t>
+ (hw_scale_->GetScaleDataRef(index, kHWDestinationScalar));
+
+ index++;
+
+ DLOGV_IF(kTagDriverConfig, "************************ DestScalar[%d] **************************",
+ dest_scalar_data->dest_scaler_ndx);
+ DLOGV_IF(kTagDriverConfig, "Mixer WxH %dx%d", dest_scalar_data->lm_width,
+ dest_scalar_data->lm_height);
+ DLOGI_IF(kTagDriverConfig, "*****************************************************************");
+ }
+ mdp_commit.dest_scaler_cnt = UINT32(hw_layer_info.dest_scale_info_map.size());
+
return HWDevice::Validate(hw_layers);
}
@@ -640,5 +695,76 @@
return kErrorNone;
}
+DisplayError HWPrimary::SetMixerAttributes(const HWMixerAttributes &mixer_attributes) {
+ if (IsResolutionSwitchEnabled() || !hw_resource_.hw_dest_scalar_info.count) {
+ return kErrorNotSupported;
+ }
+
+ if (mixer_attributes.width > display_attributes_.x_pixels ||
+ mixer_attributes.height > display_attributes_.y_pixels) {
+ DLOGW("Input resolution exceeds display resolution! input: res %dx%d display: res %dx%d",
+ mixer_attributes.width, mixer_attributes.height, display_attributes_.x_pixels,
+ display_attributes_.y_pixels);
+ return kErrorNotSupported;
+ }
+
+ uint32_t max_input_width = hw_resource_.hw_dest_scalar_info.max_input_width;
+ if (display_attributes_.is_device_split) {
+ max_input_width *= 2;
+ }
+
+ if (mixer_attributes.width > max_input_width) {
+ DLOGW("Input width exceeds width limit! input_width %d width_limit %d", mixer_attributes.width,
+ max_input_width);
+ return kErrorNotSupported;
+ }
+
+ float mixer_aspect_ratio = FLOAT(mixer_attributes.width) / FLOAT(mixer_attributes.height);
+ float display_aspect_ratio =
+ FLOAT(display_attributes_.x_pixels) / FLOAT(display_attributes_.y_pixels);
+
+ if (display_aspect_ratio != mixer_aspect_ratio) {
+ DLOGW("Aspect ratio mismatch! input: res %dx%d display: res %dx%d", mixer_attributes.width,
+ mixer_attributes.height, display_attributes_.x_pixels, display_attributes_.y_pixels);
+ return kErrorNotSupported;
+ }
+
+ float scale_x = FLOAT(display_attributes_.x_pixels) / FLOAT(mixer_attributes.width);
+ float scale_y = FLOAT(display_attributes_.y_pixels) / FLOAT(mixer_attributes.height);
+ float max_scale_up = hw_resource_.hw_dest_scalar_info.max_scale_up;
+ if (scale_x > max_scale_up || scale_y > max_scale_up) {
+ DLOGW("Up scaling ratio exceeds for destination scalar upscale limit scale_x %f scale_y %f " \
+ "max_scale_up %f", scale_x, scale_y, max_scale_up);
+ return kErrorNotSupported;
+ }
+
+ float mixer_split_ratio = FLOAT(mixer_attributes_.split_left) / FLOAT(mixer_attributes_.width);
+
+ mixer_attributes_ = mixer_attributes;
+ mixer_attributes_.split_left = mixer_attributes_.width;
+ if (display_attributes_.is_device_split) {
+ mixer_attributes_.split_left = UINT32(FLOAT(mixer_attributes.width) * mixer_split_ratio);
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWPrimary::GetMixerAttributes(HWMixerAttributes *mixer_attributes) {
+ if (!mixer_attributes) {
+ return kErrorParameters;
+ }
+
+ *mixer_attributes = mixer_attributes_;
+
+ return kErrorNone;
+}
+
+void HWPrimary::UpdateMixerAttributes() {
+ mixer_attributes_.width = display_attributes_.x_pixels;
+ mixer_attributes_.height = display_attributes_.y_pixels;
+ mixer_attributes_.split_left = display_attributes_.is_device_split ?
+ hw_panel_info_.split_info.left_split : mixer_attributes_.width;
+}
+
} // namespace sdm
diff --git a/sdm/libs/core/fb/hw_primary.h b/sdm/libs/core/fb/hw_primary.h
index 999c41a..36b3f63 100644
--- a/sdm/libs/core/fb/hw_primary.h
+++ b/sdm/libs/core/fb/hw_primary.h
@@ -65,6 +65,8 @@
virtual DisplayError SetPPFeatures(PPFeaturesConfig *feature_list);
virtual DisplayError GetPanelBrightness(int *level);
virtual DisplayError SetAutoRefresh(bool enable);
+ virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes);
+ virtual DisplayError GetMixerAttributes(HWMixerAttributes *mixer_attributes);
private:
// Panel modes for the MSMFB_LPM_ENABLE ioctl
@@ -77,6 +79,8 @@
void InitializeConfigs();
bool IsResolutionSwitchEnabled() { return !display_configs_.empty(); }
bool GetCurrentModeFromSysfs(size_t *curr_x_pixels, size_t *curr_y_pixels);
+ void UpdateMixerAttributes();
+ void ResetDisplayParams();
HWDisplayAttributes display_attributes_;
std::vector<DisplayConfigVariableInfo> display_configs_;
@@ -85,6 +89,8 @@
const char *kBrightnessNode = "/sys/class/leds/lcd-backlight/brightness";
const char *kAutoRefreshNode = "/sys/devices/virtual/graphics/fb0/msm_cmd_autorefresh_en";
bool auto_refresh_ = false;
+ HWMixerAttributes mixer_attributes_ = {};
+ mdp_destination_scaler_data *mdp_dest_scalar_data_ = NULL;
};
} // namespace sdm
diff --git a/sdm/libs/core/fb/hw_scale.cpp b/sdm/libs/core/fb/hw_scale.cpp
index f18727f..06277fc 100644
--- a/sdm/libs/core/fb/hw_scale.cpp
+++ b/sdm/libs/core/fb/hw_scale.cpp
@@ -47,11 +47,16 @@
}
void HWScaleV1::SetHWScaleData(const HWScaleData &scale_data, uint32_t index,
- mdp_input_layer *mdp_layer) {
+ mdp_layer_commit_v1 *mdp_commit, HWSubBlockType sub_block_type) {
if (!scale_data.enable.scale) {
return;
}
+ if (sub_block_type == kHWDestinationScalar) {
+ return;
+ }
+
+ mdp_input_layer *mdp_layer = &mdp_commit->input_layers[index];
mdp_layer->flags |= MDP_LAYER_ENABLE_PIXEL_EXT;
mdp_scale_data *mdp_scale = &scale_data_v1_.at(index);
mdp_scale->enable_pxl_ext = scale_data.enable.scale;
@@ -84,8 +89,12 @@
return;
}
-void* HWScaleV1::GetScaleDataRef(uint32_t index) {
- return &scale_data_v1_.at(index);
+void* HWScaleV1::GetScaleDataRef(uint32_t index, HWSubBlockType sub_block_type) {
+ if (sub_block_type != kHWDestinationScalar) {
+ return &scale_data_v1_.at(index);
+ }
+
+ return NULL;
}
void HWScaleV1::DumpScaleData(void *mdp_scale) {
@@ -112,14 +121,32 @@
}
void HWScaleV2::SetHWScaleData(const HWScaleData &scale_data, uint32_t index,
- mdp_input_layer *mdp_layer) {
+ mdp_layer_commit_v1 *mdp_commit, HWSubBlockType sub_block_type) {
if (!scale_data.enable.scale && !scale_data.enable.direction_detection &&
!scale_data.enable.detail_enhance ) {
return;
}
- mdp_scale_data_v2 *mdp_scale = &scale_data_v2_.at(index);
- mdp_layer->flags |= MDP_LAYER_ENABLE_QSEED3_SCALE;
+ mdp_scale_data_v2 *mdp_scale;
+ if (sub_block_type != kHWDestinationScalar) {
+ mdp_input_layer *mdp_layer = &mdp_commit->input_layers[index];
+ mdp_layer->flags |= MDP_LAYER_ENABLE_QSEED3_SCALE;
+ mdp_scale = &scale_data_v2_.at(index);
+ } else {
+ mdp_scale_data_v2 mdp_dest_scale;
+ mdp_destination_scaler_data *dest_scalar =
+ reinterpret_cast<mdp_destination_scaler_data *>(mdp_commit->dest_scaler);
+
+ dest_scalar[index].flags = MDP_DESTSCALER_ENABLE;
+
+ if (scale_data.enable.detail_enhance) {
+ dest_scalar[index].flags |= MDP_DESTSCALER_ENHANCER_UPDATE;
+ }
+
+ dest_scale_data_v2_.insert(std::make_pair(index, mdp_dest_scale));
+ mdp_scale = &dest_scale_data_v2_[index];
+ }
+
mdp_scale->enable = (scale_data.enable.scale ? ENABLE_SCALE : 0) |
(scale_data.enable.direction_detection ? ENABLE_DIRECTION_DETECTION : 0) |
(scale_data.enable.detail_enhance ? ENABLE_DETAIL_ENHANCE : 0);
@@ -206,8 +233,12 @@
return;
}
-void* HWScaleV2::GetScaleDataRef(uint32_t index) {
- return &scale_data_v2_.at(index);
+void* HWScaleV2::GetScaleDataRef(uint32_t index, HWSubBlockType sub_block_type) {
+ if (sub_block_type != kHWDestinationScalar) {
+ return &scale_data_v2_.at(index);
+ } else {
+ return &dest_scale_data_v2_[index];
+ }
}
uint32_t HWScaleV2::GetMDPScalingFilter(HWScalingFilter filter_cfg) {
diff --git a/sdm/libs/core/fb/hw_scale.h b/sdm/libs/core/fb/hw_scale.h
index 0891d42..022d5a1 100644
--- a/sdm/libs/core/fb/hw_scale.h
+++ b/sdm/libs/core/fb/hw_scale.h
@@ -30,6 +30,7 @@
#include <cstring>
#include <array>
+#include <map>
namespace sdm {
@@ -39,8 +40,8 @@
static DisplayError Destroy(HWScale *intf);
virtual void SetHWScaleData(const HWScaleData &scale, uint32_t index,
- mdp_input_layer *mdp_layer) = 0;
- virtual void* GetScaleDataRef(uint32_t index) = 0;
+ mdp_layer_commit_v1 *mdp_commit, HWSubBlockType sub_block_type) = 0;
+ virtual void* GetScaleDataRef(uint32_t index, HWSubBlockType sub_block_type) = 0;
virtual void DumpScaleData(void *mdp_scale) = 0;
virtual void ResetScaleParams() = 0;
protected:
@@ -50,8 +51,8 @@
class HWScaleV1 : public HWScale {
public:
virtual void SetHWScaleData(const HWScaleData &scale, uint32_t index,
- mdp_input_layer *mdp_layer);
- virtual void* GetScaleDataRef(uint32_t index);
+ mdp_layer_commit_v1 *mdp_commit, HWSubBlockType sub_block_type);
+ virtual void* GetScaleDataRef(uint32_t index, HWSubBlockType sub_block_type);
virtual void DumpScaleData(void *mdp_scale);
virtual void ResetScaleParams() { scale_data_v1_ = {}; }
@@ -63,14 +64,15 @@
class HWScaleV2 : public HWScale {
public:
virtual void SetHWScaleData(const HWScaleData &scale, uint32_t index,
- mdp_input_layer *mdp_layer);
- virtual void* GetScaleDataRef(uint32_t index);
+ mdp_layer_commit_v1 *mdp_commit, HWSubBlockType sub_block_type);
+ virtual void* GetScaleDataRef(uint32_t index, HWSubBlockType sub_block_type);
virtual void DumpScaleData(void *mdp_scale);
- virtual void ResetScaleParams() { scale_data_v2_ = {}; }
+ virtual void ResetScaleParams() { scale_data_v2_ = {}; dest_scale_data_v2_ = {}; }
protected:
~HWScaleV2() {}
std::array<mdp_scale_data_v2, (kMaxSDELayers * 2)> scale_data_v2_ = {};
+ std::map<uint32_t, mdp_scale_data_v2> dest_scale_data_v2_ = {};
private:
uint32_t GetMDPAlphaInterpolation(HWAlphaInterpolation alpha_filter_cfg);
diff --git a/sdm/libs/core/hw_interface.h b/sdm/libs/core/hw_interface.h
index 75d92b9..0ff5126 100644
--- a/sdm/libs/core/hw_interface.h
+++ b/sdm/libs/core/hw_interface.h
@@ -95,6 +95,8 @@
virtual DisplayError SetAutoRefresh(bool enable) = 0;
virtual DisplayError SetS3DMode(HWS3DMode s3d_mode) = 0;
virtual DisplayError SetScaleLutConfig(HWScaleLutInfo *lut_info) = 0;
+ virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes) = 0;
+ virtual DisplayError GetMixerAttributes(HWMixerAttributes *mixer_attributes) = 0;
protected:
virtual ~HWInterface() { }
diff --git a/sdm/libs/core/resource_default.cpp b/sdm/libs/core/resource_default.cpp
index e13150b..312f55f 100644
--- a/sdm/libs/core/resource_default.cpp
+++ b/sdm/libs/core/resource_default.cpp
@@ -104,8 +104,9 @@
}
DisplayError ResourceDefault::RegisterDisplay(DisplayType type,
- const HWDisplayAttributes &attributes,
+ const HWDisplayAttributes &display_attributes,
const HWPanelInfo &hw_panel_info,
+ const HWMixerAttributes &mixer_attributes,
Handle *display_ctx) {
DisplayError error = kErrorNone;
@@ -139,12 +140,9 @@
hw_block_ctx_[hw_block_id].is_in_use = true;
- display_resource_ctx->display_attributes = attributes;
+ display_resource_ctx->display_attributes = display_attributes;
display_resource_ctx->hw_block_id = hw_block_id;
-
- if (!display_resource_ctx->display_attributes.is_device_split) {
- display_resource_ctx->display_attributes.split_left = attributes.x_pixels;
- }
+ display_resource_ctx->mixer_attributes = mixer_attributes;
*display_ctx = display_resource_ctx;
return error;
@@ -162,14 +160,19 @@
return kErrorNone;
}
-void ResourceDefault::ReconfigureDisplay(Handle display_ctx, const HWDisplayAttributes &attributes,
- const HWPanelInfo &hw_panel_info) {
+DisplayError ResourceDefault::ReconfigureDisplay(Handle display_ctx,
+ const HWDisplayAttributes &display_attributes,
+ const HWPanelInfo &hw_panel_info,
+ const HWMixerAttributes &mixer_attributes) {
SCOPE_LOCK(locker_);
DisplayResourceContext *display_resource_ctx =
reinterpret_cast<DisplayResourceContext *>(display_ctx);
- display_resource_ctx->display_attributes = attributes;
+ display_resource_ctx->display_attributes = display_attributes;
+ display_resource_ctx->mixer_attributes = mixer_attributes;
+
+ return kErrorNone;
}
DisplayError ResourceDefault::Start(Handle display_ctx) {
@@ -447,20 +450,20 @@
DisplayError ResourceDefault::DisplaySplitConfig(DisplayResourceContext *display_resource_ctx,
const LayerRect &src_rect, const LayerRect &dst_rect,
HWLayerConfig *layer_config) {
- HWDisplayAttributes &display_attributes = display_resource_ctx->display_attributes;
+ HWMixerAttributes &mixer_attributes = display_resource_ctx->mixer_attributes;
// for display split case
HWPipeInfo *left_pipe = &layer_config->left_pipe;
HWPipeInfo *right_pipe = &layer_config->right_pipe;
LayerRect scissor_left, scissor_right, dst_left, crop_left, crop_right, dst_right;
- scissor_left.right = FLOAT(display_attributes.split_left);
- scissor_left.bottom = FLOAT(display_attributes.y_pixels);
+ scissor_left.right = FLOAT(mixer_attributes.split_left);
+ scissor_left.bottom = FLOAT(mixer_attributes.height);
- scissor_right.left = FLOAT(display_attributes.split_left);
+ scissor_right.left = FLOAT(mixer_attributes.split_left);
scissor_right.top = 0.0f;
- scissor_right.right = FLOAT(display_attributes.x_pixels);
- scissor_right.bottom = FLOAT(display_attributes.y_pixels);
+ scissor_right.right = FLOAT(mixer_attributes.width);
+ scissor_right.bottom = FLOAT(mixer_attributes.height);
crop_left = src_rect;
dst_left = dst_rect;
diff --git a/sdm/libs/core/resource_default.h b/sdm/libs/core/resource_default.h
index ce6dd5f..29258e6 100644
--- a/sdm/libs/core/resource_default.h
+++ b/sdm/libs/core/resource_default.h
@@ -37,11 +37,16 @@
public:
DisplayError Init(const HWResourceInfo &hw_resource_info);
DisplayError Deinit();
- virtual DisplayError RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
- const HWPanelInfo &hw_panel_info, Handle *display_ctx);
+ virtual DisplayError RegisterDisplay(DisplayType type,
+ const HWDisplayAttributes &display_attributes,
+ const HWPanelInfo &hw_panel_info,
+ const HWMixerAttributes &mixer_attributes,
+ Handle *display_ctx);
virtual DisplayError UnregisterDisplay(Handle display_ctx);
- virtual void ReconfigureDisplay(Handle display_ctx, const HWDisplayAttributes &attributes,
- const HWPanelInfo &hw_panel_info);
+ virtual DisplayError ReconfigureDisplay(Handle display_ctx,
+ const HWDisplayAttributes &display_attributes,
+ const HWPanelInfo &hw_panel_info,
+ const HWMixerAttributes &mixer_attributes);
virtual DisplayError Start(Handle display_ctx);
virtual DisplayError Stop(Handle display_ctx);
virtual DisplayError Acquire(Handle display_ctx, HWLayers *hw_layers);
@@ -84,6 +89,7 @@
HWDisplayAttributes display_attributes;
HWBlockType hw_block_id;
uint64_t frame_count;
+ HWMixerAttributes mixer_attributes;
DisplayResourceContext() : hw_block_id(kHWBlockMax), frame_count(0) { }
};
diff --git a/sdm/libs/core/strategy.cpp b/sdm/libs/core/strategy.cpp
index b8a499e..c1b8aa5 100644
--- a/sdm/libs/core/strategy.cpp
+++ b/sdm/libs/core/strategy.cpp
@@ -33,9 +33,12 @@
Strategy::Strategy(ExtensionInterface *extension_intf, DisplayType type,
const HWResourceInfo &hw_resource_info, const HWPanelInfo &hw_panel_info,
- const HWDisplayAttributes &hw_display_attributes)
+ const HWMixerAttributes &mixer_attributes,
+ const HWDisplayAttributes &display_attributes,
+ const DisplayConfigVariableInfo &fb_config)
: extension_intf_(extension_intf), display_type_(type), hw_resource_info_(hw_resource_info),
- hw_panel_info_(hw_panel_info), hw_display_attributes_(hw_display_attributes) {
+ hw_panel_info_(hw_panel_info), mixer_attributes_(mixer_attributes),
+ display_attributes_(display_attributes), fb_config_(fb_config) {
}
DisplayError Strategy::Init() {
@@ -43,7 +46,8 @@
if (extension_intf_) {
error = extension_intf_->CreateStrategyExtn(display_type_, hw_panel_info_.mode,
- hw_panel_info_.s3d_mode, &strategy_intf_);
+ hw_panel_info_.s3d_mode, mixer_attributes_,
+ fb_config_, &strategy_intf_);
if (error != kErrorNone) {
DLOGE("Failed to create strategy");
return error;
@@ -75,7 +79,6 @@
hw_layers_info_ = hw_layers_info;
extn_start_success_ = false;
tried_default_ = false;
-
uint32_t i = 0;
LayerStack *layer_stack = hw_layers_info_->stack;
uint32_t layer_count = UINT32(layer_stack->layers.size());
@@ -167,29 +170,34 @@
return;
}
- float disp_x_res = hw_display_attributes_.x_pixels;
- float disp_y_res = hw_display_attributes_.y_pixels;
+ float layer_mixer_width = mixer_attributes_.width;
+ float layer_mixer_height = mixer_attributes_.height;
if (!hw_resource_info_.is_src_split &&
- ((disp_x_res > hw_resource_info_.max_mixer_width) ||
+ ((layer_mixer_width > hw_resource_info_.max_mixer_width) ||
((display_type_ == kPrimary) && hw_panel_info_.split_info.right_split))) {
split_display = true;
}
if (split_display) {
- float left_split = FLOAT(hw_panel_info_.split_info.left_split);
- hw_layers_info_->left_partial_update = (LayerRect) {0.0f, 0.0f, left_split, disp_y_res};
- hw_layers_info_->right_partial_update = (LayerRect) {left_split, 0.0f, disp_x_res, disp_y_res};
+ float left_split = FLOAT(mixer_attributes_.split_left);
+ hw_layers_info_->left_partial_update = (LayerRect) {0.0f, 0.0f, left_split, layer_mixer_height};
+ hw_layers_info_->right_partial_update = (LayerRect) {left_split, 0.0f, layer_mixer_width,
+ layer_mixer_height};
} else {
- hw_layers_info_->left_partial_update = (LayerRect) {0.0f, 0.0f, disp_x_res, disp_y_res};
+ hw_layers_info_->left_partial_update = (LayerRect) {0.0f, 0.0f, layer_mixer_width,
+ layer_mixer_height};
hw_layers_info_->right_partial_update = (LayerRect) {0.0f, 0.0f, 0.0f, 0.0f};
}
}
DisplayError Strategy::Reconfigure(const HWPanelInfo &hw_panel_info,
- const HWDisplayAttributes &hw_display_attributes) {
+ const HWDisplayAttributes &display_attributes,
+ const HWMixerAttributes &mixer_attributes,
+ const DisplayConfigVariableInfo &fb_config) {
hw_panel_info_ = hw_panel_info;
- hw_display_attributes_ = hw_display_attributes;
+ display_attributes_ = display_attributes;
+ mixer_attributes_ = mixer_attributes;
if (!extension_intf_) {
return kErrorNone;
@@ -205,7 +213,8 @@
extension_intf_->CreatePartialUpdate(display_type_, hw_resource_info_,
hw_panel_info_, &partial_update_intf_);
- return strategy_intf_->Reconfigure(hw_panel_info_.mode, hw_panel_info_.s3d_mode);
+ return strategy_intf_->Reconfigure(hw_panel_info_.mode, hw_panel_info_.s3d_mode, mixer_attributes,
+ fb_config);
}
} // namespace sdm
diff --git a/sdm/libs/core/strategy.h b/sdm/libs/core/strategy.h
index 5f14d28..b284d61 100644
--- a/sdm/libs/core/strategy.h
+++ b/sdm/libs/core/strategy.h
@@ -34,7 +34,8 @@
public:
Strategy(ExtensionInterface *extension_intf, DisplayType type,
const HWResourceInfo &hw_resource_info, const HWPanelInfo &hw_panel_info,
- const HWDisplayAttributes &hw_display_attributes);
+ const HWMixerAttributes &mixer_attributes, const HWDisplayAttributes &display_attributes,
+ const DisplayConfigVariableInfo &fb_config);
DisplayError Init();
DisplayError Deinit();
@@ -44,7 +45,9 @@
DisplayError GetNextStrategy(StrategyConstraints *constraints);
DisplayError Stop();
DisplayError Reconfigure(const HWPanelInfo &hw_panel_info,
- const HWDisplayAttributes &hw_display_attributes);
+ const HWDisplayAttributes &hw_display_attributes,
+ const HWMixerAttributes &mixer_attributes,
+ const DisplayConfigVariableInfo &fb_config);
private:
void GenerateROI();
@@ -56,7 +59,9 @@
HWResourceInfo hw_resource_info_;
HWPanelInfo hw_panel_info_;
HWLayersInfo *hw_layers_info_ = NULL;
- HWDisplayAttributes hw_display_attributes_;
+ HWMixerAttributes mixer_attributes_ = {};
+ HWDisplayAttributes display_attributes_ = {};
+ DisplayConfigVariableInfo fb_config_ = {};
uint32_t fb_layer_index_ = 0;
bool extn_start_success_ = false;
bool tried_default_ = false;
diff --git a/sdm/libs/hwc/hwc_color_manager.cpp b/sdm/libs/hwc/hwc_color_manager.cpp
index 27115b5..7c12ec0 100644
--- a/sdm/libs/hwc/hwc_color_manager.cpp
+++ b/sdm/libs/hwc/hwc_color_manager.cpp
@@ -254,7 +254,7 @@
uint32_t primary_width = 0;
uint32_t primary_height = 0;
- hwc_display->GetPanelResolution(&primary_width, &primary_height);
+ hwc_display->GetMixerResolution(&primary_width, &primary_height);
uint8_t *buf = new uint8_t[size]();
// handle for solid fill layer with fd = -1.
private_handle_t *handle =
diff --git a/sdm/libs/hwc/hwc_display.cpp b/sdm/libs/hwc/hwc_display.cpp
index 2945674..97e6c02 100644
--- a/sdm/libs/hwc/hwc_display.cpp
+++ b/sdm/libs/hwc/hwc_display.cpp
@@ -83,13 +83,6 @@
swap_interval_zero_ = true;
}
- framebuffer_config_ = new DisplayConfigVariableInfo();
- if (!framebuffer_config_) {
- DLOGV("Failed to allocate memory for custom framebuffer config.");
- core_intf_->DestroyDisplay(display_intf_);
- return -EINVAL;
- }
-
int blit_enabled = 0;
HWCDebugHandler::Get()->GetProperty("persist.hwc.blit.comp", &blit_enabled);
if (needs_blit_ && blit_enabled) {
@@ -126,8 +119,6 @@
return -EINVAL;
}
- delete framebuffer_config_;
-
if (blit_engine_) {
blit_engine_->DeInit();
delete blit_engine_;
@@ -224,11 +215,17 @@
return 0;
}
-int HWCDisplay::GetDisplayAttributes(uint32_t config, const uint32_t *attributes, int32_t *values) {
- DisplayConfigVariableInfo variable_config = *framebuffer_config_;
+int HWCDisplay::GetDisplayAttributes(uint32_t config, const uint32_t *display_attributes,
+ int32_t *values) {
+ DisplayConfigVariableInfo variable_config;
+ DisplayError error = display_intf_->GetFrameBufferConfig(&variable_config);
+ if (error != kErrorNone) {
+ DLOGV("Get variable config failed. Error = %d", error);
+ return -EINVAL;
+ }
- for (int i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; i++) {
- switch (attributes[i]) {
+ for (int i = 0; display_attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; i++) {
+ switch (display_attributes[i]) {
case HWC_DISPLAY_VSYNC_PERIOD:
values[i] = INT32(variable_config.vsync_period_ns);
break;
@@ -245,7 +242,7 @@
values[i] = INT32(variable_config.y_dpi * 1000.0f);
break;
default:
- DLOGW("Spurious attribute type = %d", attributes[i]);
+ DLOGW("Spurious attribute type = %d", display_attributes[i]);
return -EINVAL;
}
}
@@ -261,6 +258,10 @@
return -1;
}
+DisplayError HWCDisplay::SetMixerResolution(uint32_t width, uint32_t height) {
+ return kErrorNotSupported;
+}
+
void HWCDisplay::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
dump_frame_count_ = count;
dump_frame_index_ = 0;
@@ -450,7 +451,6 @@
}
hwc_rect_t scaled_display_frame = hwc_layer.displayFrame;
- ScaleDisplayFrame(&scaled_display_frame);
ApplyScanAdjustment(&scaled_display_frame);
SetRect(scaled_display_frame, &layer->dst_rect);
@@ -1032,108 +1032,49 @@
}
int HWCDisplay::SetFrameBufferResolution(uint32_t x_pixels, uint32_t y_pixels) {
- if (x_pixels <= 0 || y_pixels <= 0) {
- DLOGV("Unsupported config: x_pixels=%d, y_pixels=%d", x_pixels, y_pixels);
- return -EINVAL;
- }
-
- if (framebuffer_config_->x_pixels == x_pixels && framebuffer_config_->y_pixels == y_pixels) {
- return 0;
- }
-
- DisplayConfigVariableInfo active_config;
- uint32_t active_config_index = 0;
- display_intf_->GetActiveConfig(&active_config_index);
- DisplayError error = display_intf_->GetConfig(active_config_index, &active_config);
+ DisplayConfigVariableInfo fb_config;
+ DisplayError error = display_intf_->GetFrameBufferConfig(&fb_config);
if (error != kErrorNone) {
- DLOGV("GetConfig variable info failed. Error = %d", error);
+ DLOGV("Get frame buffer config failed. Error = %d", error);
return -EINVAL;
}
- if (active_config.x_pixels <= 0 || active_config.y_pixels <= 0) {
- DLOGV("Invalid panel resolution (%dx%d)", active_config.x_pixels, active_config.y_pixels);
- return -EINVAL;
- }
+ fb_config.x_pixels = x_pixels;
+ fb_config.y_pixels = y_pixels;
- // Create rects to represent the new source and destination crops
- LayerRect crop = LayerRect(0, 0, FLOAT(x_pixels), FLOAT(y_pixels));
- LayerRect dst = LayerRect(0, 0, FLOAT(active_config.x_pixels), FLOAT(active_config.y_pixels));
- // Set rotate90 to false since this is taken care of during regular composition.
- bool rotate90 = false;
- error = display_intf_->IsScalingValid(crop, dst, rotate90);
+ error = display_intf_->SetFrameBufferConfig(fb_config);
if (error != kErrorNone) {
- DLOGV("Unsupported resolution: (%dx%d)", x_pixels, y_pixels);
+ DLOGV("Set frame buffer config failed. Error = %d", error);
return -EINVAL;
}
- framebuffer_config_->x_pixels = x_pixels;
- framebuffer_config_->y_pixels = y_pixels;
- framebuffer_config_->vsync_period_ns = active_config.vsync_period_ns;
- framebuffer_config_->x_dpi = active_config.x_dpi;
- framebuffer_config_->y_dpi = active_config.y_dpi;
-
- DLOGI("New framebuffer resolution (%dx%d)", framebuffer_config_->x_pixels,
- framebuffer_config_->y_pixels);
+ DLOGI("New framebuffer resolution (%dx%d)", x_pixels, y_pixels);
return 0;
}
void HWCDisplay::GetFrameBufferResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
- *x_pixels = framebuffer_config_->x_pixels;
- *y_pixels = framebuffer_config_->y_pixels;
+ DisplayConfigVariableInfo fb_config;
+ display_intf_->GetFrameBufferConfig(&fb_config);
+
+ *x_pixels = fb_config.x_pixels;
+ *y_pixels = fb_config.y_pixels;
}
-void HWCDisplay::ScaleDisplayFrame(hwc_rect_t *display_frame) {
- if (!IsFrameBufferScaled()) {
- return;
- }
-
- uint32_t active_config_index = 0;
- display_intf_->GetActiveConfig(&active_config_index);
- DisplayConfigVariableInfo active_config;
- DisplayError error = display_intf_->GetConfig(active_config_index, &active_config);
- if (error != kErrorNone) {
- DLOGE("GetConfig variable info failed. Error = %d", error);
- return;
- }
-
- float custom_x_pixels = FLOAT(framebuffer_config_->x_pixels);
- float custom_y_pixels = FLOAT(framebuffer_config_->y_pixels);
- float active_x_pixels = FLOAT(active_config.x_pixels);
- float active_y_pixels = FLOAT(active_config.y_pixels);
- float x_pixels_ratio = active_x_pixels / custom_x_pixels;
- float y_pixels_ratio = active_y_pixels / custom_y_pixels;
- float layer_width = FLOAT(display_frame->right - display_frame->left);
- float layer_height = FLOAT(display_frame->bottom - display_frame->top);
-
- display_frame->left = INT(x_pixels_ratio * FLOAT(display_frame->left));
- display_frame->top = INT(y_pixels_ratio * FLOAT(display_frame->top));
- display_frame->right = INT(FLOAT(display_frame->left) + layer_width * x_pixels_ratio);
- display_frame->bottom = INT(FLOAT(display_frame->top) + layer_height * y_pixels_ratio);
+DisplayError HWCDisplay::GetMixerResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
+ return display_intf_->GetMixerResolution(x_pixels, y_pixels);
}
-bool HWCDisplay::IsFrameBufferScaled() {
- if (framebuffer_config_->x_pixels == 0 || framebuffer_config_->y_pixels == 0) {
- return false;
- }
- uint32_t panel_x_pixels = 0;
- uint32_t panel_y_pixels = 0;
- GetPanelResolution(&panel_x_pixels, &panel_y_pixels);
- return (framebuffer_config_->x_pixels != panel_x_pixels) ||
- (framebuffer_config_->y_pixels != panel_y_pixels);
-}
void HWCDisplay::GetPanelResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
- DisplayConfigVariableInfo active_config;
- uint32_t active_config_index = 0;
- display_intf_->GetActiveConfig(&active_config_index);
- DisplayError error = display_intf_->GetConfig(active_config_index, &active_config);
- if (error != kErrorNone) {
- DLOGE("GetConfig variable info failed. Error = %d", error);
- return;
- }
- *x_pixels = active_config.x_pixels;
- *y_pixels = active_config.y_pixels;
+ DisplayConfigVariableInfo display_config;
+ uint32_t active_index = 0;
+
+ display_intf_->GetActiveConfig(&active_index);
+ display_intf_->GetConfig(active_index, &display_config);
+
+ *x_pixels = display_config.x_pixels;
+ *y_pixels = display_config.y_pixels;
}
int HWCDisplay::SetDisplayStatus(uint32_t display_status) {
@@ -1355,8 +1296,9 @@
return display_intf_->GetNumVariableInfoConfigs(count) == kErrorNone ? 0 : -1;
}
-int HWCDisplay::GetDisplayAttributesForConfig(int config, DisplayConfigVariableInfo *attributes) {
- return display_intf_->GetConfig(UINT32(config), attributes) == kErrorNone ? 0 : -1;
+int HWCDisplay::GetDisplayAttributesForConfig(int config,
+ DisplayConfigVariableInfo *display_attributes) {
+ return display_intf_->GetConfig(UINT32(config), display_attributes) == kErrorNone ? 0 : -1;
}
// TODO(user): HWC needs to know updating for dyn_fps, cpu hint features,
diff --git a/sdm/libs/hwc/hwc_display.h b/sdm/libs/hwc/hwc_display.h
index d07420f..1dfface 100644
--- a/sdm/libs/hwc/hwc_display.h
+++ b/sdm/libs/hwc/hwc_display.h
@@ -59,7 +59,8 @@
// Framebuffer configurations
virtual int GetDisplayConfigs(uint32_t *configs, size_t *num_configs);
- virtual int GetDisplayAttributes(uint32_t config, const uint32_t *attributes, int32_t *values);
+ virtual int GetDisplayAttributes(uint32_t config, const uint32_t *display_attributes,
+ int32_t *values);
virtual int GetActiveConfig();
virtual int SetActiveConfig(int index);
@@ -72,12 +73,14 @@
virtual uint32_t GetLastPowerMode();
virtual int SetFrameBufferResolution(uint32_t x_pixels, uint32_t y_pixels);
virtual void GetFrameBufferResolution(uint32_t *x_pixels, uint32_t *y_pixels);
- virtual void GetPanelResolution(uint32_t *x_pixels, uint32_t *y_pixels);
virtual int SetDisplayStatus(uint32_t display_status);
virtual int OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level);
virtual int Perform(uint32_t operation, ...);
virtual int SetCursorPosition(int x, int y);
virtual void SetSecureDisplay(bool secure_display_active);
+ virtual DisplayError SetMixerResolution(uint32_t width, uint32_t height);
+ virtual DisplayError GetMixerResolution(uint32_t *width, uint32_t *height);
+ virtual void GetPanelResolution(uint32_t *width, uint32_t *height);
// Captures frame output in the buffer specified by output_buffer_info. The API is
// non-blocking and the client is expected to check operation status later on.
@@ -95,7 +98,8 @@
virtual int SetActiveDisplayConfig(int config);
virtual int GetActiveDisplayConfig(uint32_t *config);
virtual int GetDisplayConfigCount(uint32_t *count);
- virtual int GetDisplayAttributesForConfig(int config, DisplayConfigVariableInfo *attributes);
+ virtual int GetDisplayAttributesForConfig(int config,
+ DisplayConfigVariableInfo *display_attributes);
int SetPanelBrightness(int level);
int GetPanelBrightness(int *level);
@@ -150,7 +154,6 @@
LayerBufferFormat GetSDMFormat(const int32_t &source, const int flags);
const char *GetHALPixelFormatString(int format);
const char *GetDisplayString();
- void ScaleDisplayFrame(hwc_rect_t *display_frame);
void MarkLayersForGPUBypass(hwc_display_contents_1_t *content_list);
virtual void ApplyScanAdjustment(hwc_rect_t *display_frame);
DisplayError SetCSC(ColorSpace_t source, LayerCSC *target);
@@ -181,7 +184,6 @@
bool dump_input_layers_ = false;
uint32_t last_power_mode_;
bool swap_interval_zero_ = false;
- DisplayConfigVariableInfo *framebuffer_config_ = NULL;
bool display_paused_ = false;
uint32_t min_refresh_rate_ = 0;
uint32_t max_refresh_rate_ = 0;
@@ -201,7 +203,6 @@
bool animating_ = false;
private:
- bool IsFrameBufferScaled();
void DumpInputBuffers(hwc_display_contents_1_t *content_list);
int PrepareLayerParams(hwc_layer_1_t *hwc_layer, Layer *layer);
void CommitLayerParams(hwc_layer_1_t *hwc_layer, Layer *layer);
diff --git a/sdm/libs/hwc/hwc_display_external.cpp b/sdm/libs/hwc/hwc_display_external.cpp
index a647517..ad8690c 100644
--- a/sdm/libs/hwc/hwc_display_external.cpp
+++ b/sdm/libs/hwc/hwc_display_external.cpp
@@ -50,6 +50,7 @@
uint32_t external_width = 0;
uint32_t external_height = 0;
int drc_enabled = 0;
+ DisplayError error = kErrorNone;
HWCDisplay *hwc_display_external = new HWCDisplayExternal(core_intf, hwc_procs, qservice);
int status = hwc_display_external->Init();
@@ -58,7 +59,10 @@
return status;
}
- hwc_display_external->GetPanelResolution(&external_width, &external_height);
+ error = hwc_display_external->GetMixerResolution(&external_width, &external_height);
+ if (error != kErrorNone) {
+ return -EINVAL;
+ }
if (primary_width && primary_height) {
// use_primary_res means HWCDisplayExternal should directly set framebuffer resolution to the
@@ -180,28 +184,28 @@
return;
}
- uint32_t panel_width = 0;
- uint32_t panel_height = 0;
- GetPanelResolution(&panel_width, &panel_height);
+ uint32_t mixer_width = 0;
+ uint32_t mixer_height = 0;
+ GetMixerResolution(&mixer_width, &mixer_height);
- if (panel_width == 0 || panel_height == 0) {
- DLOGV("Invalid panel dimensions (%d, %d)", panel_width, panel_height);
+ if (mixer_width == 0 || mixer_height == 0) {
+ DLOGV("Invalid mixer dimensions (%d, %d)", mixer_width, mixer_height);
return;
}
- uint32_t new_panel_width = UINT32(panel_width * FLOAT(1.0f - width_ratio));
- uint32_t new_panel_height = UINT32(panel_height * FLOAT(1.0f - height_ratio));
+ uint32_t new_mixer_width = UINT32(mixer_width * FLOAT(1.0f - width_ratio));
+ uint32_t new_mixer_height = UINT32(mixer_height * FLOAT(1.0f - height_ratio));
- int x_offset = INT((FLOAT(panel_width) * width_ratio) / 2.0f);
- int y_offset = INT((FLOAT(panel_height) * height_ratio) / 2.0f);
+ int x_offset = INT((FLOAT(mixer_width) * width_ratio) / 2.0f);
+ int y_offset = INT((FLOAT(mixer_height) * height_ratio) / 2.0f);
- display_frame->left = (display_frame->left * INT32(new_panel_width) / INT32(panel_width))
+ display_frame->left = (display_frame->left * INT32(new_mixer_width) / INT32(mixer_width))
+ x_offset;
- display_frame->top = (display_frame->top * INT32(new_panel_height) / INT32(panel_height)) +
+ display_frame->top = (display_frame->top * INT32(new_mixer_height) / INT32(mixer_height)) +
y_offset;
- display_frame->right = ((display_frame->right * INT32(new_panel_width)) / INT32(panel_width)) +
+ display_frame->right = ((display_frame->right * INT32(new_mixer_width)) / INT32(mixer_width)) +
x_offset;
- display_frame->bottom = ((display_frame->bottom * INT32(new_panel_height)) / INT32(panel_height))
+ display_frame->bottom = ((display_frame->bottom * INT32(new_mixer_height)) / INT32(mixer_height))
+ y_offset;
}
diff --git a/sdm/libs/hwc/hwc_display_null.cpp b/sdm/libs/hwc/hwc_display_null.cpp
index 11cf47a..649f40c 100644
--- a/sdm/libs/hwc/hwc_display_null.cpp
+++ b/sdm/libs/hwc/hwc_display_null.cpp
@@ -97,12 +97,12 @@
#define NULL_DISPLAY_FPS 60
-int HWCDisplayNull::GetDisplayAttributes(uint32_t config, const uint32_t *attributes,
+int HWCDisplayNull::GetDisplayAttributes(uint32_t config, const uint32_t *display_attributes,
int32_t *values) {
- for (int i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; i++) {
+ for (int i = 0; display_attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; i++) {
// We fake display resolution as 1080P by default, though it can be overriden through a call to
// SetResolution(), and DPI as 160, though what the DPI value does is not clear
- switch (attributes[i]) {
+ switch (display_attributes[i]) {
case HWC_DISPLAY_VSYNC_PERIOD:
values[i] = INT32(1000000000L / NULL_DISPLAY_FPS);
break;
diff --git a/sdm/libs/hwc/hwc_display_null.h b/sdm/libs/hwc/hwc_display_null.h
index 2f6438a..297e870 100644
--- a/sdm/libs/hwc/hwc_display_null.h
+++ b/sdm/libs/hwc/hwc_display_null.h
@@ -48,7 +48,8 @@
return HWCDisplay::GetDisplayConfigs(configs, num_configs);
}
- virtual int GetDisplayAttributes(uint32_t config, const uint32_t *attributes, int32_t *values);
+ virtual int GetDisplayAttributes(uint32_t config, const uint32_t *display_attributes,
+ int32_t *values);
virtual int GetActiveConfig() { return 0; }
virtual int SetActiveConfig(int index) { return -1; }
@@ -79,7 +80,8 @@
virtual int SetActiveDisplayConfig(int config) { return 0; }
virtual int GetActiveDisplayConfig(uint32_t *config) { return -1; }
virtual int GetDisplayConfigCount(uint32_t *count) { return -1; }
- virtual int GetDisplayAttributesForConfig(int config, DisplayConfigVariableInfo *attributes) {
+ virtual int GetDisplayAttributesForConfig(int config,
+ DisplayConfigVariableInfo *display_attributes) {
return -1;
}
virtual bool IsValidContentList(hwc_display_contents_1_t *content_list) {
diff --git a/sdm/libs/hwc/hwc_display_primary.cpp b/sdm/libs/hwc/hwc_display_primary.cpp
index 4a43e4d..f92ab43 100644
--- a/sdm/libs/hwc/hwc_display_primary.cpp
+++ b/sdm/libs/hwc/hwc_display_primary.cpp
@@ -56,7 +56,7 @@
return status;
}
- hwc_display_primary->GetPanelResolution(&primary_width, &primary_height);
+ hwc_display_primary->GetMixerResolution(&primary_width, &primary_height);
int width = 0, height = 0;
HWCDebugHandler::Get()->GetProperty("sdm.fb_size_width", &width);
HWCDebugHandler::Get()->GetProperty("sdm.fb_size_height", &height);
@@ -507,5 +507,13 @@
return error;
}
+DisplayError HWCDisplayPrimary::SetMixerResolution(uint32_t width, uint32_t height) {
+ return display_intf_->SetMixerResolution(width, height);
+}
+
+DisplayError HWCDisplayPrimary::GetMixerResolution(uint32_t *width, uint32_t *height) {
+ return display_intf_->GetMixerResolution(width, height);
+}
+
} // namespace sdm
diff --git a/sdm/libs/hwc/hwc_display_primary.h b/sdm/libs/hwc/hwc_display_primary.h
index 072507b..81e510f 100644
--- a/sdm/libs/hwc/hwc_display_primary.h
+++ b/sdm/libs/hwc/hwc_display_primary.h
@@ -70,6 +70,8 @@
void HandleFrameOutput();
void HandleFrameCapture();
void HandleFrameDump();
+ DisplayError SetMixerResolution(uint32_t width, uint32_t height);
+ DisplayError GetMixerResolution(uint32_t *width, uint32_t *height);
BufferAllocator *buffer_allocator_ = nullptr;
CPUHint *cpu_hint_ = nullptr;
diff --git a/sdm/libs/hwc/hwc_display_virtual.cpp b/sdm/libs/hwc/hwc_display_virtual.cpp
index ef7198c..1363839 100644
--- a/sdm/libs/hwc/hwc_display_virtual.cpp
+++ b/sdm/libs/hwc/hwc_display_virtual.cpp
@@ -67,7 +67,7 @@
return status;
}
- hwc_display_virtual->GetPanelResolution(&virtual_width, &virtual_height);
+ hwc_display_virtual->GetMixerResolution(&virtual_width, &virtual_height);
if (content_list->numHwLayers < 1) {
Destroy(hwc_display_virtual);
diff --git a/sdm/libs/hwc/hwc_session.cpp b/sdm/libs/hwc/hwc_session.cpp
index 8df0555..a31c331 100644
--- a/sdm/libs/hwc/hwc_session.cpp
+++ b/sdm/libs/hwc/hwc_session.cpp
@@ -560,10 +560,10 @@
}
int HWCSession::GetDisplayAttributes(hwc_composer_device_1 *device, int disp, uint32_t config,
- const uint32_t *attributes, int32_t *values) {
+ const uint32_t *display_attributes, int32_t *values) {
SCOPE_LOCK(locker_);
- if (!device || !attributes || !values) {
+ if (!device || !display_attributes || !values) {
return -EINVAL;
}
@@ -574,7 +574,8 @@
HWCSession *hwc_session = static_cast<HWCSession *>(device);
int status = -EINVAL;
if (hwc_session->hwc_display_[disp]) {
- status = hwc_session->hwc_display_[disp]->GetDisplayAttributes(config, attributes, values);
+ status = hwc_session->hwc_display_[disp]->GetDisplayAttributes(config, display_attributes,
+ values);
}
return status;
@@ -780,6 +781,10 @@
status = GetBWTransactionStatus(input_parcel, output_parcel);
break;
+ case qService::IQService::SET_LAYER_MIXER_RESOLUTION:
+ status = SetMixerResolution(input_parcel);
+ break;
+
default:
DLOGW("QService command = %d is not supported", command);
return -EINVAL;
@@ -952,22 +957,22 @@
int config = input_parcel->readInt32();
int dpy = input_parcel->readInt32();
int error = android::BAD_VALUE;
- DisplayConfigVariableInfo attributes;
+ DisplayConfigVariableInfo display_attributes;
if (dpy > HWC_DISPLAY_VIRTUAL) {
return android::BAD_VALUE;
}
if (hwc_display_[dpy]) {
- error = hwc_display_[dpy]->GetDisplayAttributesForConfig(config, &attributes);
+ error = hwc_display_[dpy]->GetDisplayAttributesForConfig(config, &display_attributes);
if (error == 0) {
- output_parcel->writeInt32(INT(attributes.vsync_period_ns));
- output_parcel->writeInt32(INT(attributes.x_pixels));
- output_parcel->writeInt32(INT(attributes.y_pixels));
- output_parcel->writeFloat(attributes.x_dpi);
- output_parcel->writeFloat(attributes.y_dpi);
+ output_parcel->writeInt32(INT(display_attributes.vsync_period_ns));
+ output_parcel->writeInt32(INT(display_attributes.x_pixels));
+ output_parcel->writeInt32(INT(display_attributes.y_pixels));
+ output_parcel->writeFloat(display_attributes.x_dpi);
+ output_parcel->writeFloat(display_attributes.y_dpi);
output_parcel->writeInt32(0); // Panel type, unsupported.
- output_parcel->writeInt32(attributes.is_yuv);
+ output_parcel->writeInt32(display_attributes.is_yuv);
}
}
@@ -1121,6 +1126,31 @@
}
}
+android::status_t HWCSession::SetMixerResolution(const android::Parcel *input_parcel) {
+ DisplayError error = kErrorNone;
+ uint32_t dpy = UINT32(input_parcel->readInt32());
+
+ if (dpy != HWC_DISPLAY_PRIMARY) {
+ DLOGI("Resoulution change not supported for this display %d", dpy);
+ return -EINVAL;
+ }
+
+ if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
+ DLOGI("Primary display is not initialized");
+ return -EINVAL;
+ }
+
+ uint32_t width = UINT32(input_parcel->readInt32());
+ uint32_t height = UINT32(input_parcel->readInt32());
+
+ error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMixerResolution(width, height);
+ if (error != kErrorNone) {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
void HWCSession::DynamicDebug(const android::Parcel *input_parcel) {
int type = input_parcel->readInt32();
bool enable = (input_parcel->readInt32() > 0);
diff --git a/sdm/libs/hwc/hwc_session.h b/sdm/libs/hwc/hwc_session.h
index efcafcf..2bdae2b 100644
--- a/sdm/libs/hwc/hwc_session.h
+++ b/sdm/libs/hwc/hwc_session.h
@@ -68,7 +68,7 @@
static int GetDisplayConfigs(hwc_composer_device_1 *device, int disp, uint32_t *configs,
size_t *numConfigs);
static int GetDisplayAttributes(hwc_composer_device_1 *device, int disp, uint32_t config,
- const uint32_t *attributes, int32_t *values);
+ const uint32_t *display_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);
static int SetCursorPositionAsync(hwc_composer_device_1 *device, int disp, int x, int y);
@@ -123,6 +123,8 @@
android::Parcel *output_parcel);
android::status_t GetBWTransactionStatus(const android::Parcel *input_parcel,
android::Parcel *output_parcel);
+ android::status_t SetMixerResolution(const android::Parcel *input_parcel);
+
static Locker locker_;
CoreInterface *core_intf_ = NULL;
hwc_procs_t hwc_procs_default_;
diff --git a/sdm/libs/utils/rect.cpp b/sdm/libs/utils/rect.cpp
index e756464..1872df2 100644
--- a/sdm/libs/utils/rect.cpp
+++ b/sdm/libs/utils/rect.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -198,5 +198,40 @@
}
}
+void ScaleRect(const LayerRect &src_domain, const LayerRect &dst_domain, const LayerRect &in_rect,
+ LayerRect *out_rect) {
+ if (!IsValid(src_domain) || !IsValid(dst_domain) || !IsValid(in_rect)) {
+ return;
+ }
+
+ float src_domain_width = src_domain.right - src_domain.left;
+ float src_domain_height = src_domain.bottom - src_domain.top;
+ float dst_domain_width = dst_domain.right - dst_domain.left;
+ float dst_domain_height = dst_domain.bottom - dst_domain.top;
+
+ float width_ratio = dst_domain_width / src_domain_width;
+ float height_ratio = dst_domain_height / src_domain_height;
+
+ out_rect->left = width_ratio * in_rect.left;
+ out_rect->top = height_ratio * in_rect.top;
+ out_rect->right = width_ratio * in_rect.right;
+ out_rect->bottom = height_ratio * in_rect.bottom;
+}
+
+RectOrientation GetOrientation(const LayerRect &in_rect) {
+ if (!IsValid(in_rect)) {
+ return kOrientationUnknown;
+ }
+
+ float input_width = in_rect.right - in_rect.left;
+ float input_height = in_rect.bottom - in_rect.top;
+
+ if (input_width < input_height) {
+ return kOrientationPortrait;
+ }
+
+ return kOrientationLandscape;
+}
+
} // namespace sdm