Merge "hwc: Add null check for copybit context and source handler"
diff --git a/displayengine/include/utils/constants.h b/displayengine/include/utils/constants.h
index 6f98b07..329dd86 100644
--- a/displayengine/include/utils/constants.h
+++ b/displayengine/include/utils/constants.h
@@ -53,6 +53,9 @@
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#define ROUND_UP_ALIGN_DOWN(value, a) FLOAT(FloorToMultipleOf(UINT32(value + 0.5f), UINT32(a)))
+#define ROUND_UP_ALIGN_UP(value, a) FLOAT(CeilToMultipleOf(UINT32(value + 0.5f), UINT32(a)))
+
template <class T>
inline void Swap(T &a, T &b) {
T c(a);
diff --git a/displayengine/include/utils/debug.h b/displayengine/include/utils/debug.h
index 65079a9..5f65834 100644
--- a/displayengine/include/utils/debug.h
+++ b/displayengine/include/utils/debug.h
@@ -63,6 +63,8 @@
static uint32_t GetSimulationFlag();
static uint32_t GetHDMIResolution();
static uint32_t GetIdleTimeoutMs();
+ static bool IsRotatorDownScaleDisabled();
+ static bool IsDecimationDisabled();
private:
Debug();
diff --git a/displayengine/include/utils/rect.h b/displayengine/include/utils/rect.h
index f009cfd..0730529 100644
--- a/displayengine/include/utils/rect.h
+++ b/displayengine/include/utils/rect.h
@@ -40,7 +40,7 @@
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 &factor, LayerRect *rect);
+ void NormalizeRect(const uint32_t &align_x, const uint32_t &align_y, LayerRect *rect);
} // namespace sde
diff --git a/displayengine/libs/core/Android.mk b/displayengine/libs/core/Android.mk
index 56167e1..c4c3d87 100644
--- a/displayengine/libs/core/Android.mk
+++ b/displayengine/libs/core/Android.mk
@@ -9,7 +9,7 @@
LOCAL_CFLAGS := -Wno-missing-field-initializers -Wno-unused-parameter \
-Wconversion -Wall -Werror \
-DLOG_TAG=\"SDE\"
-LOCAL_SHARED_LIBRARIES := libdl libsdeutils
+LOCAL_SHARED_LIBRARIES := libdl libsdeutils libcutils
LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
LOCAL_SRC_FILES := core_interface.cpp \
core_impl.cpp \
diff --git a/displayengine/libs/core/comp_manager.cpp b/displayengine/libs/core/comp_manager.cpp
index 7e888ee..06028a2 100644
--- a/displayengine/libs/core/comp_manager.cpp
+++ b/displayengine/libs/core/comp_manager.cpp
@@ -144,6 +144,10 @@
DisplayCompositionContext *display_comp_ctx =
reinterpret_cast<DisplayCompositionContext *>(comp_handle);
+ if (!display_comp_ctx) {
+ return kErrorParameters;
+ }
+
res_mgr_.UnregisterDisplay(display_comp_ctx->display_resource_ctx);
destroy_strategy_intf_(display_comp_ctx->strategy_intf);
@@ -154,11 +158,8 @@
"display type %d", registered_displays_, configured_displays_,
display_comp_ctx->display_type);
- if (display_comp_ctx) {
- delete display_comp_ctx;
- display_comp_ctx = NULL;
- }
-
+ delete display_comp_ctx;
+ display_comp_ctx = NULL;
return kErrorNone;
}
diff --git a/displayengine/libs/core/display_base.cpp b/displayengine/libs/core/display_base.cpp
index 058bacc..dac17fd 100644
--- a/displayengine/libs/core/display_base.cpp
+++ b/displayengine/libs/core/display_base.cpp
@@ -298,7 +298,7 @@
DisplayError error = kErrorNone;
- DLOGI("Set state = %d", state);
+ DLOGI("Set state = %d, display %d", state, display_type_);
if (state == state_) {
DLOGI("Same state transition is requested.");
@@ -307,13 +307,12 @@
switch (state) {
case kStateOff:
- // Invoke flush during suspend for HDMI and virtual displays. StateOff is handled
- // separately for primary in DisplayPrimary::SetDisplayState() function.
+ hw_layers_.info.count = 0;
error = hw_intf_->Flush(hw_device_);
if (error == kErrorNone) {
comp_manager_->Purge(display_comp_ctx_);
- state_ = state;
- hw_layers_.info.count = 0;
+
+ error = hw_intf_->PowerOff(hw_device_);
}
break;
diff --git a/displayengine/libs/core/display_primary.cpp b/displayengine/libs/core/display_primary.cpp
index ac44fe3..8eed8ee 100644
--- a/displayengine/libs/core/display_primary.cpp
+++ b/displayengine/libs/core/display_primary.cpp
@@ -35,29 +35,5 @@
CompManager *comp_manager, OfflineCtrl *offline_ctrl)
: DisplayBase(kPrimary, event_handler, kDevicePrimary, hw_intf, comp_manager, offline_ctrl) { }
-DisplayError DisplayPrimary::SetDisplayState(DisplayState state) {
- DisplayError error = kErrorNone;
-
- DLOGI("Set state = %d", state);
-
- if (state == kStateOff) {
- SCOPE_LOCK(locker_);
- if (state == state_) {
- DLOGI("Same state transition is requested.");
- return kErrorNone;
- }
- error = hw_intf_->PowerOff(hw_device_);
- if (error == kErrorNone) {
- comp_manager_->Purge(display_comp_ctx_);
- state_ = state;
- hw_layers_.info.count = 0;
- }
- } else {
- error = DisplayBase::SetDisplayState(state);
- }
-
- return error;
-}
-
} // namespace sde
diff --git a/displayengine/libs/core/display_primary.h b/displayengine/libs/core/display_primary.h
index 79fbddf..ea4cf2b 100644
--- a/displayengine/libs/core/display_primary.h
+++ b/displayengine/libs/core/display_primary.h
@@ -33,7 +33,6 @@
public:
DisplayPrimary(DisplayEventHandler *event_handler, HWInterface *hw_intf,
CompManager *comp_manager, OfflineCtrl *offline_ctrl);
- virtual DisplayError SetDisplayState(DisplayState state);
};
} // namespace sde
diff --git a/displayengine/libs/core/hw_framebuffer.cpp b/displayengine/libs/core/hw_framebuffer.cpp
index 4a361da..69d1efa 100644
--- a/displayengine/libs/core/hw_framebuffer.cpp
+++ b/displayengine/libs/core/hw_framebuffer.cpp
@@ -542,49 +542,33 @@
return kErrorNone;
}
-DisplayError HWFrameBuffer::OpenRotatorSession(Handle device, HWLayers *hw_layers) {
+DisplayError HWFrameBuffer::OpenRotatorSession(Handle device, HWRotateInfo *rotate_info) {
HWContext *hw_context = reinterpret_cast<HWContext *>(device);
HWRotator *hw_rotator = &hw_context->hw_rotator;
+ LayerBuffer *input_buffer = rotate_info->input_buffer;
+ HWBufferInfo *rot_buf_info = &rotate_info->hw_buffer_info;
hw_rotator->Reset();
- HWLayersInfo &hw_layer_info = hw_layers->info;
+ STRUCT_VAR(mdp_rotation_config, mdp_rot_config);
+ mdp_rot_config.version = MDP_ROTATION_REQUEST_VERSION_1_0;
+ mdp_rot_config.input.width = input_buffer->width;
+ mdp_rot_config.input.height = input_buffer->height;
+ SetFormat(input_buffer->format, &mdp_rot_config.input.format);
+ mdp_rot_config.output.width = rot_buf_info->output_buffer.width;
+ mdp_rot_config.output.height = rot_buf_info->output_buffer.height;
+ SetFormat(rot_buf_info->output_buffer.format, &mdp_rot_config.output.format);
+ mdp_rot_config.frame_rate = rotate_info->frame_rate;
- for (uint32_t i = 0; i < hw_layer_info.count; i++) {
- Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
- LayerBuffer *input_buffer = layer.input_buffer;
- bool rot90 = (layer.transform.rotation == 90.0f);
-
- for (uint32_t count = 0; count < 2; count++) {
- HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
-
- if (rotate_info->valid) {
- HWBufferInfo *rot_buf_info = &rotate_info->hw_buffer_info;
-
- if (rot_buf_info->session_id < 0) {
- STRUCT_VAR(mdp_rotation_config, mdp_rot_config);
- mdp_rot_config.version = MDP_ROTATION_REQUEST_VERSION_1_0;
- mdp_rot_config.input.width = input_buffer->width;
- mdp_rot_config.input.height = input_buffer->height;
- SetFormat(input_buffer->format, &mdp_rot_config.input.format);
- mdp_rot_config.output.width = rot_buf_info->output_buffer.width;
- mdp_rot_config.output.height = rot_buf_info->output_buffer.height;
- SetFormat(rot_buf_info->output_buffer.format, &mdp_rot_config.output.format);
- mdp_rot_config.frame_rate = layer.frame_rate;
-
- if (ioctl_(hw_context->device_fd, MDSS_ROTATION_OPEN, &mdp_rot_config) < 0) {
- IOCTL_LOGE(MDSS_ROTATION_OPEN, hw_context->type);
- return kErrorHardware;
- }
-
- rot_buf_info->session_id = mdp_rot_config.session_id;
-
- DLOGV_IF(kTagDriverConfig, "session_id %d", rot_buf_info->session_id);
- }
- }
- }
+ if (ioctl_(hw_context->device_fd, MDSS_ROTATION_OPEN, &mdp_rot_config) < 0) {
+ IOCTL_LOGE(MDSS_ROTATION_OPEN, hw_context->type);
+ return kErrorHardware;
}
+ rot_buf_info->session_id = mdp_rot_config.session_id;
+
+ DLOGV_IF(kTagDriverConfig, "session_id %d", rot_buf_info->session_id);
+
return kErrorNone;
}
@@ -911,7 +895,7 @@
return kErrorNone;
}
-DisplayError HWFrameBuffer::RotatorValidate(HWContext *hw_context, HWLayers *hw_layers) {
+void HWFrameBuffer::SetRotatorCtrlParams(HWContext *hw_context, HWLayers *hw_layers) {
HWRotator *hw_rotator = &hw_context->hw_rotator;
DLOGV_IF(kTagDriverConfig, "************************* %s Validate Input ************************",
GetDeviceString(hw_context->type));
@@ -978,17 +962,9 @@
}
}
}
-
- mdp_rot_request->flags = MDSS_ROTATION_REQUEST_VALIDATE;
- if (ioctl_(hw_context->device_fd, MDSS_ROTATION_REQUEST, mdp_rot_request) < 0) {
- IOCTL_LOGE(MDSS_ROTATION_REQUEST, hw_context->type);
- return kErrorHardware;
- }
-
- return kErrorNone;
}
-DisplayError HWFrameBuffer::RotatorCommit(HWContext *hw_context, HWLayers *hw_layers) {
+void HWFrameBuffer::SetRotatorBufferParams(HWContext *hw_context, HWLayers *hw_layers) {
HWRotator *hw_rotator = &hw_context->hw_rotator;
mdp_rotation_request *mdp_rot_request = &hw_rotator->mdp_rot_req;
HWLayersInfo &hw_layer_info = hw_layers->info;
@@ -1041,14 +1017,36 @@
}
}
}
+}
- mdp_rot_request->flags &= ~MDSS_ROTATION_REQUEST_VALIDATE;
- if (ioctl_(hw_context->device_fd, MDSS_ROTATION_REQUEST, mdp_rot_request) < 0) {
+DisplayError HWFrameBuffer::RotatorValidate(HWContext *hw_context, HWLayers *hw_layers) {
+ HWRotator *hw_rotator = &hw_context->hw_rotator;
+ SetRotatorCtrlParams(hw_context, hw_layers);
+
+ hw_rotator->mdp_rot_req.flags = MDSS_ROTATION_REQUEST_VALIDATE;
+ if (ioctl_(hw_context->device_fd, MDSS_ROTATION_REQUEST, &hw_rotator->mdp_rot_req) < 0) {
IOCTL_LOGE(MDSS_ROTATION_REQUEST, hw_context->type);
return kErrorHardware;
}
- rot_count = 0;
+ return kErrorNone;
+}
+
+DisplayError HWFrameBuffer::RotatorCommit(HWContext *hw_context, HWLayers *hw_layers) {
+ HWRotator *hw_rotator = &hw_context->hw_rotator;
+ HWLayersInfo &hw_layer_info = hw_layers->info;
+ uint32_t rot_count = 0;
+
+ SetRotatorCtrlParams(hw_context, hw_layers);
+
+ SetRotatorBufferParams(hw_context, hw_layers);
+
+ hw_rotator->mdp_rot_req.flags &= ~MDSS_ROTATION_REQUEST_VALIDATE;
+ if (ioctl_(hw_context->device_fd, MDSS_ROTATION_REQUEST, &hw_rotator->mdp_rot_req) < 0) {
+ IOCTL_LOGE(MDSS_ROTATION_REQUEST, hw_context->type);
+ return kErrorHardware;
+ }
+
for (uint32_t i = 0; i < hw_layer_info.count; i++) {
Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
@@ -1059,7 +1057,7 @@
if (rotate_info->valid) {
HWBufferInfo *rot_buf_info = &rotate_info->hw_buffer_info;
- mdp_rotation_item *mdp_rot_item = &mdp_rot_request->list[rot_count];
+ mdp_rotation_item *mdp_rot_item = &hw_rotator->mdp_rot_req.list[rot_count];
SyncMerge(layer.input_buffer->release_fence_fd, dup(mdp_rot_item->output.fence),
&layer.input_buffer->release_fence_fd);
@@ -1079,14 +1077,26 @@
HWContext *hw_context = reinterpret_cast<HWContext *>(device);
HWDisplay *hw_display = &hw_context->hw_display;
- hw_display->Reset();
- mdp_layer_commit_v1 &mdp_commit = hw_display->mdp_disp_commit.commit_v1;
- mdp_commit.input_layer_cnt = 0;
- mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
+ switch (hw_context->type) {
+ case kDevicePrimary:
+ case kDeviceHDMI:
+ case kDeviceVirtual:
+ {
+ hw_display->Reset();
+ mdp_layer_commit_v1 &mdp_commit = hw_display->mdp_disp_commit.commit_v1;
+ mdp_commit.input_layer_cnt = 0;
+ mdp_commit.output_layer = NULL;
- if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_display->mdp_disp_commit) == -1) {
- IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, hw_context->type);
- return kErrorHardware;
+ mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
+ if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_display->mdp_disp_commit) < 0) {
+ IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, hw_context->type);
+ return kErrorHardware;
+ }
+ }
+ break;
+ default:
+ DLOGE("Flush is not supported for the device %s", GetDeviceString(hw_context->type));
+ return kErrorNotSupported;
}
return kErrorNone;
diff --git a/displayengine/libs/core/hw_framebuffer.h b/displayengine/libs/core/hw_framebuffer.h
index 5c01e5f..68a0674 100644
--- a/displayengine/libs/core/hw_framebuffer.h
+++ b/displayengine/libs/core/hw_framebuffer.h
@@ -56,7 +56,7 @@
virtual DisplayError Doze(Handle device);
virtual DisplayError SetVSyncState(Handle device, bool enable);
virtual DisplayError Standby(Handle device);
- virtual DisplayError OpenRotatorSession(Handle device, HWLayers *hw_layers);
+ virtual DisplayError OpenRotatorSession(Handle device, HWRotateInfo *rotate_info);
virtual DisplayError CloseRotatorSession(Handle device, int32_t session_id);
virtual DisplayError Validate(Handle device, HWLayers *hw_layers);
virtual DisplayError Commit(Handle device, HWLayers *hw_layers);
@@ -86,6 +86,7 @@
mdp_disp_commit.commit_v1.input_layers = mdp_in_layers;
mdp_disp_commit.commit_v1.output_layer = &mdp_out_layer;
mdp_disp_commit.commit_v1.release_fence = -1;
+ mdp_disp_commit.commit_v1.retire_fence = -1;
}
mdp_scale_data* GetScaleRef(uint32_t index) { return &scale_data[index]; }
@@ -192,6 +193,9 @@
DisplayError DisplayValidate(HWContext *device_ctx, HWLayers *hw_layers);
DisplayError DisplayCommit(HWContext *device_ctx, HWLayers *hw_layers);
+ void SetRotatorCtrlParams(HWContext *device_ctx, HWLayers *hw_layers);
+ void SetRotatorBufferParams(HWContext *device_ctx, HWLayers *hw_layers);
+
DisplayError RotatorValidate(HWContext *device_ctx, HWLayers *hw_layers);
DisplayError RotatorCommit(HWContext *device_ctx, HWLayers *hw_layers);
diff --git a/displayengine/libs/core/hw_interface.h b/displayengine/libs/core/hw_interface.h
index 084768e..9e003bb 100644
--- a/displayengine/libs/core/hw_interface.h
+++ b/displayengine/libs/core/hw_interface.h
@@ -107,6 +107,7 @@
};
struct HWRotateInfo {
+ LayerBuffer *input_buffer;
uint32_t pipe_id;
LayerRect src_roi;
LayerRect dst_roi;
@@ -116,9 +117,11 @@
float downscale_ratio_y;
HWBufferInfo hw_buffer_info;
bool valid;
+ uint32_t frame_rate;
- HWRotateInfo() : pipe_id(0), dst_format(kFormatInvalid), writeback_id(kHWWriteback0),
- downscale_ratio_x(1.0f), downscale_ratio_y(1.0f), valid(false) { }
+ HWRotateInfo() : input_buffer(NULL), pipe_id(0), dst_format(kFormatInvalid),
+ writeback_id(kHWWriteback0), downscale_ratio_x(1.0f), downscale_ratio_y(1.0f),
+ valid(false), frame_rate(0) { }
void Reset() { *this = HWRotateInfo(); }
};
@@ -195,7 +198,7 @@
virtual DisplayError Doze(Handle device) = 0;
virtual DisplayError SetVSyncState(Handle device, bool enable) = 0;
virtual DisplayError Standby(Handle device) = 0;
- virtual DisplayError OpenRotatorSession(Handle device, HWLayers *hw_layers) = 0;
+ virtual DisplayError OpenRotatorSession(Handle device, HWRotateInfo *rotate_info) = 0;
virtual DisplayError CloseRotatorSession(Handle device, int32_t session_id) = 0;
virtual DisplayError Validate(Handle device, HWLayers *hw_layers) = 0;
virtual DisplayError Commit(Handle device, HWLayers *hw_layers) = 0;
diff --git a/displayengine/libs/core/offline_ctrl.cpp b/displayengine/libs/core/offline_ctrl.cpp
index 5ffaf22..8794074 100644
--- a/displayengine/libs/core/offline_ctrl.cpp
+++ b/displayengine/libs/core/offline_ctrl.cpp
@@ -85,34 +85,30 @@
DisplayOfflineContext *disp_offline_ctx = reinterpret_cast<DisplayOfflineContext *>(display_ctx);
+ disp_offline_ctx->pending_rot_commit = false;
+
if (!hw_rotator_device_ && IsRotationRequired(hw_layers)) {
DLOGV_IF(kTagOfflineCtrl, "No Rotator device found");
return kErrorHardware;
}
- disp_offline_ctx->pending_rot_commit = false;
-
- uint32_t i = 0;
- while (hw_layers->closed_session_ids[i] >= 0) {
- error = hw_intf_->CloseRotatorSession(hw_rotator_device_, hw_layers->closed_session_ids[i]);
- if (LIKELY(error != kErrorNone)) {
- DLOGE("Rotator close session failed");
- return error;
- }
- hw_layers->closed_session_ids[i++] = -1;
+ error = CloseRotatorSession(hw_layers);
+ if (LIKELY(error != kErrorNone)) {
+ DLOGE("Close rotator session failed for display %d", disp_offline_ctx->display_type);
+ return error;
}
if (IsRotationRequired(hw_layers)) {
- error = hw_intf_->OpenRotatorSession(hw_rotator_device_, hw_layers);
+ error = OpenRotatorSession(hw_layers);
if (LIKELY(error != kErrorNone)) {
- DLOGE("Rotator open session failed");
+ DLOGE("Open rotator session failed for display %d", disp_offline_ctx->display_type);
return error;
}
error = hw_intf_->Validate(hw_rotator_device_, hw_layers);
if (LIKELY(error != kErrorNone)) {
- DLOGE("Rotator validation failed");
+ DLOGE("Rotator validation failed for display %d", disp_offline_ctx->display_type);
return error;
}
disp_offline_ctx->pending_rot_commit = true;
@@ -129,7 +125,7 @@
if (disp_offline_ctx->pending_rot_commit) {
error = hw_intf_->Commit(hw_rotator_device_, hw_layers);
if (error != kErrorNone) {
- DLOGE("Rotator commit failed");
+ DLOGE("Rotator commit failed for display %d", disp_offline_ctx->display_type);
return error;
}
disp_offline_ctx->pending_rot_commit = false;
@@ -138,6 +134,50 @@
return kErrorNone;
}
+DisplayError OfflineCtrl::OpenRotatorSession(HWLayers *hw_layers) {
+ HWLayersInfo &hw_layer_info = hw_layers->info;
+ DisplayError error = kErrorNone;
+
+ for (uint32_t i = 0; i < hw_layer_info.count; i++) {
+ Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
+ bool rot90 = (layer.transform.rotation == 90.0f);
+
+ for (uint32_t count = 0; count < 2; count++) {
+ HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
+ HWBufferInfo *rot_buf_info = &rotate_info->hw_buffer_info;
+
+ if (!rotate_info->valid || rot_buf_info->session_id >= 0) {
+ continue;
+ }
+
+ rotate_info->input_buffer = layer.input_buffer;
+ rotate_info->frame_rate = layer.frame_rate;
+
+ error = hw_intf_->OpenRotatorSession(hw_rotator_device_, rotate_info);
+ if (LIKELY(error != kErrorNone)) {
+ return error;
+ }
+ }
+ }
+
+ return kErrorNone;
+}
+
+DisplayError OfflineCtrl::CloseRotatorSession(HWLayers *hw_layers) {
+ DisplayError error = kErrorNone;
+ uint32_t i = 0;
+
+ while (hw_layers->closed_session_ids[i] >= 0) {
+ error = hw_intf_->CloseRotatorSession(hw_rotator_device_, hw_layers->closed_session_ids[i]);
+ if (LIKELY(error != kErrorNone)) {
+ return error;
+ }
+ hw_layers->closed_session_ids[i++] = -1;
+ }
+
+ return kErrorNone;
+}
+
bool OfflineCtrl::IsRotationRequired(HWLayers *hw_layers) {
HWLayersInfo &layer_info = hw_layers->info;
diff --git a/displayengine/libs/core/offline_ctrl.h b/displayengine/libs/core/offline_ctrl.h
index fafdf7c..fa8b264 100644
--- a/displayengine/libs/core/offline_ctrl.h
+++ b/displayengine/libs/core/offline_ctrl.h
@@ -50,6 +50,8 @@
DisplayOfflineContext() : display_type(kPrimary), pending_rot_commit(false) { }
};
+ DisplayError OpenRotatorSession(HWLayers *hw_layers);
+ DisplayError CloseRotatorSession(HWLayers *hw_layers);
bool IsRotationRequired(HWLayers *hw_layers);
HWInterface *hw_intf_;
diff --git a/displayengine/libs/core/res_config.cpp b/displayengine/libs/core/res_config.cpp
index d3c2d26..72edeb6 100644
--- a/displayengine/libs/core/res_config.cpp
+++ b/displayengine/libs/core/res_config.cpp
@@ -52,15 +52,29 @@
// downscale when doing rotation
if (IsRotationNeeded(transform.rotation)) {
+ if (rotate->downscale_ratio_x > 1.0f) {
+ src_height = ROUND_UP_ALIGN_DOWN(src_height, rotate->downscale_ratio_x);
+ src_rect->bottom = src_rect->top + src_height;
+ }
+ if (rotate->downscale_ratio_y > 1.0f) {
+ src_width = ROUND_UP_ALIGN_DOWN(src_width, rotate->downscale_ratio_y);
+ src_rect->right = src_rect->left + src_width;
+ }
dst_rect.right = src_height / rotate->downscale_ratio_x;
dst_rect.bottom = src_width / rotate->downscale_ratio_y;
} else {
+ if (rotate->downscale_ratio_x > 1.0f) {
+ src_width = ROUND_UP_ALIGN_DOWN(src_width, rotate->downscale_ratio_x);
+ src_rect->right = src_rect->left + src_width;
+ }
+ if (rotate->downscale_ratio_y > 1.0f) {
+ src_height = ROUND_UP_ALIGN_DOWN(src_height, rotate->downscale_ratio_y);
+ src_rect->bottom = src_rect->top + src_height;
+ }
dst_rect.right = src_width / rotate->downscale_ratio_x;
dst_rect.bottom = src_height / rotate->downscale_ratio_y;
}
- dst_rect.right = floorf(dst_rect.right);
- dst_rect.bottom = floorf(dst_rect.bottom);
rotate->src_roi = *src_rect;
rotate->valid = true;
rotate->dst_roi = dst_rect;
@@ -72,7 +86,8 @@
DisplayError ResManager::SrcSplitConfig(DisplayResourceContext *display_resource_ctx,
const LayerTransform &transform, const LayerRect &src_rect,
- const LayerRect &dst_rect, HWLayerConfig *layer_config) {
+ const LayerRect &dst_rect, HWLayerConfig *layer_config,
+ uint32_t align_x) {
HWDisplayAttributes &display_attributes = display_resource_ctx->display_attributes;
HWPipeInfo *left_pipe = &layer_config->left_pipe;
HWPipeInfo *right_pipe = &layer_config->right_pipe;
@@ -80,7 +95,7 @@
if ((src_rect.right - src_rect.left) > kMaxSourcePipeWidth ||
(dst_rect.right - dst_rect.left) > kMaxInterfaceWidth || hw_res_info_.always_src_split) {
SplitRect(transform.flip_horizontal, src_rect, dst_rect, &left_pipe->src_roi,
- &left_pipe->dst_roi, &right_pipe->src_roi, &right_pipe->dst_roi);
+ &left_pipe->dst_roi, &right_pipe->src_roi, &right_pipe->dst_roi, align_x);
left_pipe->valid = true;
right_pipe->valid = true;
} else {
@@ -96,7 +111,7 @@
DisplayError ResManager::DisplaySplitConfig(DisplayResourceContext *display_resource_ctx,
const LayerTransform &transform,
const LayerRect &src_rect, const LayerRect &dst_rect,
- HWLayerConfig *layer_config) {
+ HWLayerConfig *layer_config, uint32_t align_x) {
LayerRect scissor_dst_left, scissor_dst_right;
HWDisplayAttributes &display_attributes = display_resource_ctx->display_attributes;
@@ -111,36 +126,43 @@
dst_left = dst_rect;
crop_right = crop_left;
dst_right = dst_left;
- CalculateCropRects(scissor, transform, &crop_left, &dst_left);
+ bool crop_left_valid = CalculateCropRects(scissor, transform, &crop_left, &dst_left);
scissor.left = FLOAT(display_attributes.split_left);
scissor.top = 0.0f;
scissor.right = FLOAT(display_attributes.x_pixels);
scissor.bottom = FLOAT(display_attributes.y_pixels);
- CalculateCropRects(scissor, transform, &crop_right, &dst_right);
- if ((crop_left.right - crop_left.left) > kMaxSourcePipeWidth) {
- if (crop_right.right != crop_right.left) {
+ bool crop_right_valid = false;
+
+ if (IsValidRect(scissor)) {
+ crop_right_valid = CalculateCropRects(scissor, transform, &crop_right, &dst_right);
+ }
+
+ if (crop_left_valid && (crop_left.right - crop_left.left) > kMaxSourcePipeWidth) {
+ if (crop_right_valid) {
DLOGV_IF(kTagResources, "Need more than 2 pipes: left width = %.0f, right width = %.0f",
crop_left.right - crop_left.left, crop_right.right - crop_right.left);
return kErrorNotSupported;
}
// 2 pipes both are on the left
SplitRect(transform.flip_horizontal, crop_left, dst_left, &left_pipe->src_roi,
- &left_pipe->dst_roi, &right_pipe->src_roi, &right_pipe->dst_roi);
+ &left_pipe->dst_roi, &right_pipe->src_roi, &right_pipe->dst_roi, align_x);
left_pipe->valid = true;
right_pipe->valid = true;
- } else if ((crop_right.right - crop_right.left) > kMaxSourcePipeWidth) {
- if (crop_left.right != crop_left.left) {
+ crop_right_valid = true;
+ } else if (crop_right_valid && (crop_right.right - crop_right.left) > kMaxSourcePipeWidth) {
+ if (crop_left_valid) {
DLOGV_IF(kTagResources, "Need more than 2 pipes: left width = %.0f, right width = %.0f",
crop_left.right - crop_left.left, crop_right.right - crop_right.left);
return kErrorNotSupported;
}
// 2 pipes both are on the right
SplitRect(transform.flip_horizontal, crop_right, dst_right, &left_pipe->src_roi,
- &left_pipe->dst_roi, &right_pipe->src_roi, &right_pipe->dst_roi);
+ &left_pipe->dst_roi, &right_pipe->src_roi, &right_pipe->dst_roi, align_x);
left_pipe->valid = true;
right_pipe->valid = true;
- } else if (UINT32(dst_left.right) > UINT32(dst_left.left)) {
+ crop_left_valid = true;
+ } else if (crop_left_valid) {
// assign left pipe
left_pipe->src_roi = crop_left;
left_pipe->dst_roi = dst_left;
@@ -151,7 +173,7 @@
}
// assign right pipe if needed
- if (UINT32(dst_right.right) > UINT32(dst_right.left)) {
+ if (crop_right_valid) {
if (left_pipe->valid) {
right_pipe->src_roi = crop_right;
right_pipe->dst_roi = dst_right;
@@ -168,6 +190,12 @@
right_pipe->Reset();
}
+ // TODO(user) remove this when zorder is assigned properly, check num_blending_stages on pipes
+ if (!display_attributes.is_device_split && right_pipe->valid) {
+ DLOGV_IF(kTagResources, "Non display split, do not support 2 pipes for now");
+ return kErrorNotSupported;
+ }
+
return kErrorNone;
}
@@ -193,14 +221,30 @@
dst_rect = layer.dst_rect;
scissor.right = FLOAT(display_attributes.x_pixels);
scissor.bottom = FLOAT(display_attributes.y_pixels);
- CalculateCropRects(scissor, layer.transform, &src_rect, &dst_rect);
-
- if (ValidateScaling(layer, src_rect, dst_rect, &rot_scale_x, &rot_scale_y))
- return kErrorNotSupported;
struct HWLayerConfig *layer_config = &hw_layers->config[i];
HWPipeInfo &left_pipe = layer_config->left_pipe;
HWPipeInfo &right_pipe = layer_config->right_pipe;
+
+ if (!CalculateCropRects(scissor, layer.transform, &src_rect, &dst_rect)) {
+ layer_config->Reset();
+ left_pipe.Reset();
+ right_pipe.Reset();
+ continue;
+ }
+
+ uint32_t align_x = 1, align_y = 1;
+ if (IsYuvFormat(layer.input_buffer->format)) {
+ // TODO(user) Select x and y alignment according to the format
+ align_x = 2;
+ align_y = 2;
+ NormalizeRect(align_x, align_y, &src_rect);
+ }
+
+ if (ValidateScaling(layer, src_rect, dst_rect, &rot_scale_x, &rot_scale_y)) {
+ return kErrorNotSupported;
+ }
+
// config rotator first
for (uint32_t j = 0; j < kMaxRotatePerLayer; j++) {
layer_config->rotates[j].Reset();
@@ -218,31 +262,23 @@
if (hw_res_info_.is_src_split) {
error = SrcSplitConfig(display_resource_ctx, transform, src_rect,
- dst_rect, layer_config);
+ dst_rect, layer_config, align_x);
} else {
error = DisplaySplitConfig(display_resource_ctx, transform, src_rect,
- dst_rect, layer_config);
+ dst_rect, layer_config, align_x);
}
- if (error != kErrorNone)
+ if (error != kErrorNone) {
break;
-
- // 1. Normalize Video layer source rectangle to multiple of 2, as MDP hardware require source
- // rectangle of video layer to be even.
- // 2. Normalize source and destination rect of a layer to multiple of 1.
- uint32_t factor = (1 << layer.input_buffer->flags.video);
- if (left_pipe.valid) {
- NormalizeRect(factor, &left_pipe.src_roi);
- NormalizeRect(1, &left_pipe.dst_roi);
}
- if (right_pipe.valid) {
- NormalizeRect(factor, &right_pipe.src_roi);
- NormalizeRect(1, &right_pipe.dst_roi);
+ error = AlignPipeConfig(layer, transform, &left_pipe, &right_pipe, align_x, align_y);
+ if (error != kErrorNone) {
+ break;
}
- DLOGV_IF(kTagResources, "layer = %d, left pipe_id = %x",
- i, layer_config->left_pipe.pipe_id);
+ 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);
for (uint32_t k = 0; k < layer_config->num_rotate; k++) {
@@ -251,11 +287,12 @@
LogRect(kTagResources, "rotate src", layer_config->rotates[k].src_roi);
LogRect(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);
- if (hw_layers->config[i].right_pipe.pipe_id) {
+ 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);
}
@@ -267,50 +304,52 @@
DisplayError ResManager::ValidateScaling(const Layer &layer, const LayerRect &crop,
const LayerRect &dst, float *rot_scale_x,
float *rot_scale_y) {
- bool rotated90 = IsRotationNeeded(layer.transform.rotation);
+ bool rotated90 = IsRotationNeeded(layer.transform.rotation) && (rot_scale_x != NULL);
float crop_width = rotated90 ? crop.bottom - crop.top : crop.right - crop.left;
float crop_height = rotated90 ? crop.right - crop.left : crop.bottom - crop.top;
float dst_width = dst.right - dst.left;
float dst_height = dst.bottom - dst.top;
if ((dst_width < 1.0f) || (dst_height < 1.0f)) {
- DLOGV_IF(kTagResources, "Destination region is too small w = %d, h = %d",
- dst_width, dst_height);
+ DLOGV_IF(kTagResources, "dst ROI is too small w = %.0f, h = %.0f, right = %.0f, bottom = %.0f",
+ dst_width, dst_height, dst.right, dst.bottom);
return kErrorNotSupported;
}
if ((crop_width < 1.0f) || (crop_height < 1.0f)) {
- DLOGV_IF(kTagResources, "source region is too small w = %d, h = %d", crop_width, crop_height);
+ DLOGV_IF(kTagResources, "src ROI is too small w = %.0f, h = %.0f, right = %.0f, bottom = %.0f",
+ crop_width, crop_height, crop.right, crop.bottom);
return kErrorNotSupported;
}
- if (((crop_width - dst_width) == 1) || ((crop_height - dst_height) == 1)) {
- DLOGV_IF(kTagResources, "One pixel downscaling detected crop_w %d, dst_w %d, crop_h %d, " \
- "dst_h %d", crop_width, dst_width, crop_height, dst_height);
+ if ((UINT32(crop_width - dst_width) == 1) || (UINT32(crop_height - dst_height) == 1)) {
+ DLOGV_IF(kTagResources, "One pixel downscaling detected crop_w = %.0f, dst_w = %.0f, " \
+ "crop_h = %.0f, dst_h = %.0f", crop_width, dst_width, crop_height, dst_height);
return kErrorNotSupported;
}
float scale_x = crop_width / dst_width;
float scale_y = crop_height / dst_height;
+ bool use_rotator = false;
if ((UINT32(scale_x) > 1) || (UINT32(scale_y) > 1)) {
- const uint32_t max_scale_down = hw_res_info_.max_scale_down;
- uint32_t max_downscale_with_rotator;
+ uint32_t max_scale_down = hw_res_info_.max_scale_down;
- if (hw_res_info_.has_rotator_downscale)
- max_downscale_with_rotator = max_scale_down * kMaxRotateDownScaleRatio;
- else
- max_downscale_with_rotator = max_scale_down;
+ if (hw_res_info_.has_rotator_downscale && !property_setting_.disable_rotator_downscaling &&
+ rot_scale_x) {
+ max_scale_down *= kMaxRotateDownScaleRatio;
+ use_rotator = true;
+ } else if (hw_res_info_.has_decimation && !property_setting_.disable_decimation &&
+ !IsMacroTileFormat(layer.input_buffer)) {
+ max_scale_down *= kMaxDecimationDownScaleRatio;
+ }
- if (((!hw_res_info_.has_decimation) || (IsMacroTileFormat(layer.input_buffer))) &&
- (scale_x > max_scale_down || scale_y > max_scale_down)) {
+ if (scale_x > FLOAT(max_scale_down) || scale_y > FLOAT(max_scale_down)) {
DLOGV_IF(kTagResources,
- "Scaling down is over the limit is_tile = %d, scale_x = %d, scale_y = %d",
- IsMacroTileFormat(layer.input_buffer), scale_x, scale_y);
- return kErrorNotSupported;
- } else if (scale_x > max_downscale_with_rotator || scale_y > max_downscale_with_rotator) {
- DLOGV_IF(kTagResources, "Scaling down is over the limit scale_x = %d, scale_y = %d",
- scale_x, scale_y);
+ "Scaling down is over the limit: is_tile = %d, scale_x = %.0f, scale_y = %.0f, " \
+ "crop_w = %.0f, dst_w = %.0f, has_deci = %d, disable_deci = %d",
+ IsMacroTileFormat(layer.input_buffer), scale_x, scale_y, crop_width, dst_width,
+ hw_res_info_.has_decimation, property_setting_.disable_decimation);
return kErrorNotSupported;
}
}
@@ -318,33 +357,36 @@
const uint32_t max_scale_up = hw_res_info_.max_scale_up;
if (UINT32(scale_x) < 1 && scale_x > 0.0f) {
if ((1.0f / scale_x) > max_scale_up) {
- DLOGV_IF(kTagResources, "Scaling up is over limit scale_x = %d", 1.0f / scale_x);
+ DLOGV_IF(kTagResources, "Scaling up is over limit scale_x = %f", 1.0f / scale_x);
return kErrorNotSupported;
}
}
if (UINT32(scale_y) < 1 && scale_y > 0.0f) {
if ((1.0f / scale_y) > max_scale_up) {
- DLOGV_IF(kTagResources, "Scaling up is over limit scale_y = %d", 1.0f / scale_y);
+ DLOGV_IF(kTagResources, "Scaling up is over limit scale_y = %f", 1.0f / scale_y);
return kErrorNotSupported;
}
}
- // Calculate rotator downscale ratio
- float rot_scale = 1.0f;
- while (scale_x > hw_res_info_.max_scale_down) {
- scale_x /= 2;
- rot_scale *= 2;
+ if (rot_scale_x == NULL) {
+ return kErrorNone;
}
- *rot_scale_x = rot_scale;
- rot_scale = 1.0f;
- while (scale_y > hw_res_info_.max_scale_down) {
- scale_y /= 2;
- rot_scale *= 2;
+ // Calculate rotator downscale ratio
+ if (scale_x > hw_res_info_.max_scale_down && use_rotator) {
+ *rot_scale_x = FLOAT(1 << UINT32(ceilf(log2f(scale_x / FLOAT(hw_res_info_.max_scale_down)))));
+ } else {
+ *rot_scale_x = 1.0f;
}
- *rot_scale_y = rot_scale;
- DLOGV_IF(kTagResources, "rotator scaling hor = %.0f, ver = %.0f", *rot_scale_x, *rot_scale_y);
+
+ if (scale_y > hw_res_info_.max_scale_down && use_rotator) {
+ *rot_scale_y = FLOAT(1 << UINT32(ceilf(log2f(scale_y / FLOAT(hw_res_info_.max_scale_down)))));
+ } else {
+ *rot_scale_y = 1.0f;
+ }
+ DLOGV_IF(kTagResources, "scale_x = %.0f, scale_y = %.0f, rot_scale_x = %.0f, rot_scale_y = %.0f",
+ scale_x, scale_y, *rot_scale_x, *rot_scale_y);
return kErrorNone;
}
@@ -370,7 +412,7 @@
}
}
-void ResManager::CalculateCropRects(const LayerRect &scissor, const LayerTransform &transform,
+bool ResManager::CalculateCropRects(const LayerRect &scissor, const LayerTransform &transform,
LayerRect *crop, LayerRect *dst) {
float &crop_left = crop->left;
float &crop_top = crop->top;
@@ -419,7 +461,7 @@
}
if (!need_cut)
- return;
+ return true;
CalculateCut(transform, &left_cut_ratio, &top_cut_ratio, &right_cut_ratio, &bottom_cut_ratio);
@@ -427,6 +469,12 @@
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))
+ return true;
+ else
+ return false;
}
bool ResManager::IsValidDimension(const LayerRect &src, const LayerRect &dst) {
@@ -468,8 +516,9 @@
return kErrorNotSupported;
}
- if ((down_scale_w <= max_down_scale) && (down_scale_h <= max_down_scale))
+ if ((down_scale_w <= max_down_scale) && (down_scale_h <= max_down_scale)) {
return kErrorNone;
+ }
// Decimation is the remaining downscale factor after doing max SDE downscale.
// In SDE, decimation is supported in powers of 2.
@@ -486,18 +535,22 @@
void ResManager::SplitRect(bool flip_horizontal, const LayerRect &src_rect,
const LayerRect &dst_rect, LayerRect *src_left, LayerRect *dst_left,
- LayerRect *src_right, LayerRect *dst_right) {
+ LayerRect *src_right, LayerRect *dst_right, uint32_t align_x) {
// Split rectangle horizontally and evenly into two.
float src_width = src_rect.right - src_rect.left;
float dst_width = dst_rect.right - dst_rect.left;
+ float src_width_ori = src_width;
+ src_width = ROUND_UP_ALIGN_DOWN(src_width / 2, align_x);
+ dst_width = ROUND_UP_ALIGN_DOWN(dst_width * src_width / src_width_ori, 1);
+
if (flip_horizontal) {
src_left->top = src_rect.top;
src_left->left = src_rect.left;
- src_left->right = src_rect.left + (src_width / 2);
+ src_left->right = src_rect.left + src_width;
src_left->bottom = src_rect.bottom;
dst_left->top = dst_rect.top;
- dst_left->left = dst_rect.left + (dst_width / 2);
+ dst_left->left = dst_rect.left + dst_width;
dst_left->right = dst_rect.right;
dst_left->bottom = dst_rect.bottom;
@@ -513,12 +566,12 @@
} else {
src_left->top = src_rect.top;
src_left->left = src_rect.left;
- src_left->right = src_rect.left + (src_width / 2);
+ src_left->right = src_rect.left + src_width;
src_left->bottom = src_rect.bottom;
dst_left->top = dst_rect.top;
dst_left->left = dst_rect.left;
- dst_left->right = dst_rect.left + (dst_width / 2);
+ dst_left->right = dst_rect.left + dst_width;
dst_left->bottom = dst_rect.bottom;
src_right->top = src_rect.top;
@@ -652,4 +705,49 @@
return true;
}
+DisplayError ResManager::AlignPipeConfig(const Layer &layer, const LayerTransform &transform,
+ HWPipeInfo *left_pipe, HWPipeInfo *right_pipe,
+ uint32_t align_x, uint32_t align_y) {
+ DisplayError error = kErrorNone;
+ if (!left_pipe->valid) {
+ DLOGE_IF(kTagResources, "left_pipe should not be invalid");
+ return kErrorNotSupported;
+ }
+ // 1. Normalize video layer source rectangle to multiple of 2, as MDP hardware require source
+ // rectangle of video layer to be even.
+ // 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);
+
+ if (right_pipe->valid) {
+ NormalizeRect(align_x, align_y, &right_pipe->src_roi);
+ NormalizeRect(1, 1, &right_pipe->dst_roi);
+ }
+
+ if (right_pipe->valid) {
+ // Make sure the left and right ROI are conjunct
+ right_pipe->src_roi.left = left_pipe->src_roi.right;
+ if (transform.flip_horizontal) {
+ right_pipe->dst_roi.right = left_pipe->dst_roi.left;
+ } else {
+ right_pipe->dst_roi.left = left_pipe->dst_roi.right;
+ }
+ }
+ error = ValidateScaling(layer, left_pipe->src_roi, left_pipe->dst_roi, NULL, NULL);
+ if (error != kErrorNone) {
+ goto PipeConfigExit;
+ }
+
+ if (right_pipe->valid) {
+ error = ValidateScaling(layer, right_pipe->src_roi, right_pipe->dst_roi, NULL, NULL);
+ }
+PipeConfigExit:
+ if (error != kErrorNone) {
+ DLOGV_IF(kTagResources, "AlignPipeConfig failed");
+ }
+ return error;
+}
+
} // namespace sde
diff --git a/displayengine/libs/core/res_manager.cpp b/displayengine/libs/core/res_manager.cpp
index fb8f2eb..dfd1e0a 100644
--- a/displayengine/libs/core/res_manager.cpp
+++ b/displayengine/libs/core/res_manager.cpp
@@ -248,6 +248,9 @@
}
}
+ property_setting_.disable_rotator_downscaling = Debug::IsRotatorDownScaleDisabled();
+ property_setting_.disable_decimation = Debug::IsDecimationDisabled();
+
return kErrorNone;
}
@@ -266,20 +269,23 @@
DisplayError error = kErrorNone;
const struct HWLayersInfo &layer_info = hw_layers->info;
+ HWBlockType hw_block_id = display_resource_ctx->hw_block_id;
- if (layer_info.count > num_pipe_) {
+ DLOGV_IF(kTagResources, "==== Resource reserving start: hw_block = %d ====", hw_block_id);
+
+ if (layer_info.count > num_pipe_ || layer_info.count >= hw_res_info_.num_blending_stages) {
return kErrorResources;
}
uint32_t rotate_count = 0;
error = Config(display_resource_ctx, hw_layers, &rotate_count);
if (error != kErrorNone) {
+ DLOGV_IF(kTagResources, "Resource config failed");
return error;
}
uint32_t left_index = kPipeIdMax;
bool need_scale = false;
- HWBlockType hw_block_id = display_resource_ctx->hw_block_id;
HWBlockType rotator_block = kHWBlockMax;
// Clear reserved marking
@@ -319,6 +325,10 @@
need_scale = IsScalingNeeded(pipe_info);
left_index = GetPipe(hw_block_id, is_yuv, need_scale, false, use_non_dma_pipe);
if (left_index >= num_pipe_) {
+ DLOGV_IF(kTagResources, "Get left pipe failed: hw_block_id = %d, is_yuv = %d, " \
+ "need_scale = %d, use_non_dma_pipe= %d",
+ hw_block_id, is_yuv, need_scale, use_non_dma_pipe);
+ ResourceStateLog();
goto CleanupOnError;
}
src_pipes_[left_index].reserved_hw_block = hw_block_id;
@@ -336,6 +346,8 @@
layer_config.left_pipe.pipe_id = src_pipes_[left_index].mdss_pipe_id;
src_pipes_[left_index].at_right = false;
}
+ DLOGV_IF(kTagResources, "1 pipe acquired, layer index = %d, left_pipe = %x",
+ i, layer_config.left_pipe.pipe_id);
continue;
}
@@ -344,6 +356,10 @@
uint32_t right_index;
right_index = GetPipe(hw_block_id, is_yuv, need_scale, true, use_non_dma_pipe);
if (right_index >= num_pipe_) {
+ DLOGV_IF(kTagResources, "Get right pipe failed: hw_block_id = %d, is_yuv = %d, " \
+ "need_scale = %d, use_non_dma_pipe= %d",
+ hw_block_id, is_yuv, need_scale, use_non_dma_pipe);
+ ResourceStateLog();
goto CleanupOnError;
}
@@ -364,8 +380,8 @@
goto CleanupOnError;
}
- DLOGV_IF(kTagResources, "Pipe acquired, layer index = %d, left_pipe = %x, right_pipe = %x",
- i, layer_config.left_pipe.pipe_id, pipe_info->pipe_id);
+ DLOGV_IF(kTagResources, "2 pipes acquired, layer index = %d, left_pipe = %x, right_pipe = %x",
+ i, layer_config.left_pipe.pipe_id, pipe_info->pipe_id);
}
error = AllocRotatorBuffer(display_ctx, hw_layers);
@@ -626,15 +642,17 @@
for (uint32_t i = 0; i < layer_info.count; i++) {
Layer& layer = layer_info.stack->layers[layer_info.index[i]];
HWRotateInfo *rotate = &hw_layers->config[i].rotates[0];
+ bool rot90 = (layer.transform.rotation == 90.0f);
if (rotate->valid) {
LayerBufferFormat rot_ouput_format;
- SetRotatorOutputFormat(layer.input_buffer->format, false, true, &rot_ouput_format);
+ SetRotatorOutputFormat(layer.input_buffer->format, false, rot90, &rot_ouput_format);
HWBufferInfo *hw_buffer_info = &rotate->hw_buffer_info;
hw_buffer_info->buffer_config.width = UINT32(rotate->dst_roi.right - rotate->dst_roi.left);
hw_buffer_info->buffer_config.height = UINT32(rotate->dst_roi.bottom - rotate->dst_roi.top);
hw_buffer_info->buffer_config.format = rot_ouput_format;
+ // Allocate two rotator output buffers by default for double buffering.
hw_buffer_info->buffer_config.buffer_count = 2;
hw_buffer_info->buffer_config.secure = layer.input_buffer->flags.secure;
@@ -647,12 +665,13 @@
rotate = &hw_layers->config[i].rotates[1];
if (rotate->valid) {
LayerBufferFormat rot_ouput_format;
- SetRotatorOutputFormat(layer.input_buffer->format, false, true, &rot_ouput_format);
+ SetRotatorOutputFormat(layer.input_buffer->format, false, rot90, &rot_ouput_format);
HWBufferInfo *hw_buffer_info = &rotate->hw_buffer_info;
hw_buffer_info->buffer_config.width = UINT32(rotate->dst_roi.right - rotate->dst_roi.left);
hw_buffer_info->buffer_config.height = UINT32(rotate->dst_roi.bottom - rotate->dst_roi.top);
hw_buffer_info->buffer_config.format = rot_ouput_format;
+ // Allocate two rotator output buffers by default for double buffering.
hw_buffer_info->buffer_config.buffer_count = 2;
hw_buffer_info->buffer_config.secure = layer.input_buffer->flags.secure;
@@ -802,6 +821,7 @@
src_pipes_[i].ResetState();
}
ClearRotator(display_resource_ctx);
+ DLOGV_IF(kTagResources, "display id = %d", display_resource_ctx->hw_block_id);
}
uint32_t ResManager::GetMdssPipeId(PipeType type, uint32_t index) {
@@ -973,6 +993,27 @@
}
}
+void ResManager::ResourceStateLog() {
+ DLOGV_IF(kTagResources, "==== resource manager pipe state ====");
+ uint32_t i;
+ for (i = 0; i < num_pipe_; i++) {
+ SourcePipe *src_pipe = &src_pipes_[i];
+ DLOGV_IF(kTagResources,
+ "index = %d, id = %x, reserved = %d, state = %d, hw_block = %d, dedicated = %d",
+ src_pipe->index, src_pipe->mdss_pipe_id, src_pipe->reserved_hw_block,
+ src_pipe->state, src_pipe->hw_block_id, src_pipe->dedicated_hw_block);
+ }
+
+ for (i = 0; i < hw_res_info_.num_rotator; i++) {
+ if (rotators_[i].client_bit_mask || rotators_[i].request_bit_mask) {
+ DLOGV_IF(kTagResources,
+ "rotator = %d, pipe index = %x, client_bit_mask = %x, request_bit_mask = %x",
+ i, rotators_[i].pipe_index, rotators_[i].client_bit_mask,
+ rotators_[i].request_bit_mask);
+ }
+ }
+}
+
DisplayError ResManager::AcquireRotator(DisplayResourceContext *display_resource_ctx,
const uint32_t rotate_count) {
if (rotate_count == 0)
diff --git a/displayengine/libs/core/res_manager.h b/displayengine/libs/core/res_manager.h
index c80dc2c..eae6730 100644
--- a/displayengine/libs/core/res_manager.h
+++ b/displayengine/libs/core/res_manager.h
@@ -88,6 +88,7 @@
kMaxSourcePipeWidth = 2048,
kMaxInterfaceWidth = 2048,
kMaxRotateDownScaleRatio = 8,
+ kMaxDecimationDownScaleRatio = 8,
kMaxNumRotator = 2,
};
@@ -150,7 +151,11 @@
CLEAR_BIT(request_bit_mask, block); }
};
- static const int kPipeIdNeedsAssignment = -1;
+ struct PropertySetting {
+ bool disable_rotator_downscaling;
+ bool disable_decimation;
+ PropertySetting() : disable_rotator_downscaling(false), disable_decimation(false) { }
+ };
uint32_t GetMdssPipeId(PipeType pipe_type, uint32_t index);
uint32_t NextPipe(PipeType pipe_type, HWBlockType hw_block_id, bool at_right);
@@ -163,15 +168,17 @@
uint32_t *rotate_count);
DisplayError DisplaySplitConfig(DisplayResourceContext *display_resource_ctx,
const LayerTransform &transform, const LayerRect &src_rect,
- const LayerRect &dst_rect, HWLayerConfig *layer_config);
+ const LayerRect &dst_rect, HWLayerConfig *layer_config,
+ uint32_t align_x);
DisplayError ValidateScaling(const Layer &layer, const LayerRect &crop,
const LayerRect &dst, float *rot_scale_x, float *rot_scale_y);
DisplayError SrcSplitConfig(DisplayResourceContext *display_resource_ctx,
const LayerTransform &transform, const LayerRect &src_rect,
- const LayerRect &dst_rect, HWLayerConfig *layer_config);
+ const LayerRect &dst_rect, HWLayerConfig *layer_config,
+ uint32_t align_x);
void CalculateCut(const LayerTransform &transform, float *left_cut_ratio, float *top_cut_ratio,
float *right_cut_ratio, float *bottom_cut_ratio);
- void CalculateCropRects(const LayerRect &scissor, const LayerTransform &transform,
+ bool CalculateCropRects(const LayerRect &scissor, const LayerTransform &transform,
LayerRect *crop, LayerRect *dst);
bool IsValidDimension(const LayerRect &src, const LayerRect &dst);
bool CheckBandwidth(DisplayResourceContext *display_ctx, HWLayers *hw_layers);
@@ -182,7 +189,7 @@
float GetBpp(LayerBufferFormat format);
void SplitRect(bool flip_horizontal, const LayerRect &src_rect, const LayerRect &dst_rect,
LayerRect *src_left, LayerRect *dst_left, LayerRect *src_right,
- LayerRect *dst_right);
+ LayerRect *dst_right, uint32_t align_x);
bool IsMacroTileFormat(const LayerBuffer *buffer) { return buffer->flags.macro_tile; }
bool IsYuvFormat(LayerBufferFormat format) { return (format >= kFormatYCbCr420Planar); }
bool IsRotationNeeded(float rotation)
@@ -198,6 +205,10 @@
void SetRotatorOutputFormat(const LayerBufferFormat &input_format, bool bwc, bool rot90,
LayerBufferFormat *output_format);
bool ConfigureScaling(HWLayers *hw_layers);
+ DisplayError AlignPipeConfig(const Layer &layer, const LayerTransform &transform,
+ HWPipeInfo *left_pipe, HWPipeInfo *right_pipe,
+ uint32_t align_x, uint32_t align_y);
+ void ResourceStateLog(void);
Locker locker_;
HWResourceInfo hw_res_info_;
@@ -218,6 +229,7 @@
// the display engine's client
static void* lib_scalar_handle_; // Scalar library handle
static int (*ScalarConfigureScale)(struct scalar::LayerInfo* layer);
+ PropertySetting property_setting_;
};
} // namespace sde
diff --git a/displayengine/libs/hwc/hwc_session.cpp b/displayengine/libs/hwc/hwc_session.cpp
index 3bc4fd1..1b686bf 100644
--- a/displayengine/libs/hwc/hwc_session.cpp
+++ b/displayengine/libs/hwc/hwc_session.cpp
@@ -329,17 +329,18 @@
switch (disp) {
case HWC_DISPLAY_PRIMARY:
status = hwc_session->display_primary_->SetPowerMode(mode);
+ // Set the power mode for virtual display while setting power mode for primary, as surfaceflinger
+ // does not invoke SetPowerMode() for virtual display.
+ case HWC_DISPLAY_VIRTUAL:
+ if (hwc_session->display_virtual_) {
+ status = hwc_session->display_virtual_->SetPowerMode(mode);
+ }
break;
case HWC_DISPLAY_EXTERNAL:
if (hwc_session->display_external_) {
status = hwc_session->display_external_->SetPowerMode(mode);
}
break;
- case HWC_DISPLAY_VIRTUAL:
- if (hwc_session->display_virtual_) {
- status = hwc_session->display_virtual_->SetPowerMode(mode);
- }
- break;
default:
status = -EINVAL;
}
diff --git a/displayengine/libs/utils/debug_android.cpp b/displayengine/libs/utils/debug_android.cpp
index 1b08fe9..7503999 100644
--- a/displayengine/libs/utils/debug_android.cpp
+++ b/displayengine/libs/utils/debug_android.cpp
@@ -70,5 +70,23 @@
return 0;
}
+bool Debug::IsRotatorDownScaleDisabled() {
+ char property[PROPERTY_VALUE_MAX];
+ if (property_get("sde.disable_rotator_downscaling", property, NULL) > 0) {
+ return (atoi(property) ? 0 : false, true);
+ }
+
+ return false;
+}
+
+bool Debug::IsDecimationDisabled() {
+ char property[PROPERTY_VALUE_MAX];
+ if (property_get("sde.disable_decimation", property, NULL) > 0) {
+ return (atoi(property) ? 0 : false, true);
+ }
+
+ return false;
+}
+
} // namespace sde
diff --git a/displayengine/libs/utils/rect.cpp b/displayengine/libs/utils/rect.cpp
index 2725750..8dfd7dd 100644
--- a/displayengine/libs/utils/rect.cpp
+++ b/displayengine/libs/utils/rect.cpp
@@ -64,16 +64,11 @@
prefix, roi.left, roi.top, roi.right, roi.bottom);
}
-void NormalizeRect(const uint32_t &factor, LayerRect *rect) {
- uint32_t left = UINT32(ceilf(rect->left));
- uint32_t top = UINT32(ceilf(rect->top));
- uint32_t right = UINT32(floorf(rect->right));
- uint32_t bottom = UINT32(floorf(rect->bottom));
-
- rect->left = FLOAT(CeilToMultipleOf(left, factor));
- rect->top = FLOAT(CeilToMultipleOf(top, factor));
- rect->right = FLOAT(FloorToMultipleOf(right, factor));
- rect->bottom = FLOAT(FloorToMultipleOf(bottom, factor));
+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);
}
} // namespace sde
diff --git a/libgralloc/adreno_utils.h b/libgralloc/adreno_utils.h
index 6cb7810..78f49da 100644
--- a/libgralloc/adreno_utils.h
+++ b/libgralloc/adreno_utils.h
@@ -36,6 +36,7 @@
ADRENO_PIXELFORMAT_NV12 = 103,
ADRENO_PIXELFORMAT_YUY2 = 107,
ADRENO_PIXELFORMAT_B4G4R4A4 = 115,
+ ADRENO_PIXELFORMAT_NV12_EXT = 506, // NV12 with non-std alignment and offsets
ADRENO_PIXELFORMAT_R8G8B8 = 508, // GL_RGB8
ADRENO_PIXELFORMAT_A1B5G5R5 = 519, // GL_RGB5_A1
ADRENO_PIXELFORMAT_R8G8B8X8_SRGB = 520, // GL_SRGB8
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index fd98154..f70ead3 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -308,9 +308,10 @@
case HAL_PIXEL_FORMAT_sRGB_A_8888:
return ADRENO_PIXELFORMAT_R8G8B8A8_SRGB;
case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+ return ADRENO_PIXELFORMAT_NV12;
case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
- return ADRENO_PIXELFORMAT_NV12;
+ return ADRENO_PIXELFORMAT_NV12_EXT;
default:
ALOGE("%s: No map for format: 0x%x", __FUNCTION__, hal_format);
break;
diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h
index e9b9d9d..f973b76 100755
--- a/libgralloc/gralloc_priv.h
+++ b/libgralloc/gralloc_priv.h
@@ -33,44 +33,42 @@
#define ROUND_UP_PAGESIZE(x) ( (((unsigned long)(x)) + PAGE_SIZE-1) & \
(~(PAGE_SIZE-1)) )
-enum {
- /* gralloc usage bits indicating the type
- * of allocation that should be used */
+/* Gralloc usage bits indicating the type of allocation that should be used */
+/* SYSTEM heap comes from kernel vmalloc, can never be uncached,
+ * is not secured */
+#define GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP GRALLOC_USAGE_PRIVATE_0
- /* SYSTEM heap comes from kernel vmalloc,
- * can never be uncached, is not secured*/
- GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP = GRALLOC_USAGE_PRIVATE_0,
+/* Non linear, Universal Bandwidth Compression */
+#define GRALLOC_USAGE_PRIVATE_ALLOC_UBWC GRALLOC_USAGE_PRIVATE_1
- /* Non linear, Universal Bandwidth Compression */
- GRALLOC_USAGE_PRIVATE_ALLOC_UBWC = GRALLOC_USAGE_PRIVATE_1,
+/* IOMMU heap comes from manually allocated pages, can be cached/uncached,
+ * is not secured */
+#define GRALLOC_USAGE_PRIVATE_IOMMU_HEAP GRALLOC_USAGE_PRIVATE_2
- /* IOMMU heap comes from manually allocated pages,
- * can be cached/uncached, is not secured */
- GRALLOC_USAGE_PRIVATE_IOMMU_HEAP = GRALLOC_USAGE_PRIVATE_2,
- /* MM heap is a carveout heap for video, can be secured*/
- GRALLOC_USAGE_PRIVATE_MM_HEAP = GRALLOC_USAGE_PRIVATE_3,
- /* ADSP heap is a carveout heap, is not secured*/
- GRALLOC_USAGE_PRIVATE_ADSP_HEAP = 0x01000000,
+/* MM heap is a carveout heap for video, can be secured */
+#define GRALLOC_USAGE_PRIVATE_MM_HEAP GRALLOC_USAGE_PRIVATE_3
- /* Set this for allocating uncached memory (using O_DSYNC)
- * cannot be used with noncontiguous heaps */
- GRALLOC_USAGE_PRIVATE_UNCACHED = 0x02000000,
+/* ADSP heap is a carveout heap, is not secured */
+#define GRALLOC_USAGE_PRIVATE_ADSP_HEAP 0x01000000
- /* Buffer content should be displayed on an primary display only */
- GRALLOC_USAGE_PRIVATE_INTERNAL_ONLY = 0x04000000,
+/* Set this for allocating uncached memory (using O_DSYNC),
+ * cannot be used with noncontiguous heaps */
+#define GRALLOC_USAGE_PRIVATE_UNCACHED 0x02000000
- /* Buffer content should be displayed on an external display only */
- GRALLOC_USAGE_PRIVATE_EXTERNAL_ONLY = 0x08000000,
+/* Buffer content should be displayed on an primary display only */
+#define GRALLOC_USAGE_PRIVATE_INTERNAL_ONLY 0x04000000
- /* This flag is set for WFD usecase */
- GRALLOC_USAGE_PRIVATE_WFD = 0x00200000,
+/* Buffer content should be displayed on an external display only */
+#define GRALLOC_USAGE_PRIVATE_EXTERNAL_ONLY 0x08000000
- /* CAMERA heap is a carveout heap for camera, is not secured*/
- GRALLOC_USAGE_PRIVATE_CAMERA_HEAP = 0x00400000,
+/* This flag is set for WFD usecase */
+#define GRALLOC_USAGE_PRIVATE_WFD 0x00200000
- /* This flag is used for SECURE display usecase */
- GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY = 0x00800000,
-};
+/* CAMERA heap is a carveout heap for camera, is not secured */
+#define GRALLOC_USAGE_PRIVATE_CAMERA_HEAP 0x00400000
+
+/* This flag is used for SECURE display usecase */
+#define GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY 0x00800000
/* define Gralloc perform */
#define GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER 1
@@ -84,6 +82,7 @@
#define GRALLOC_MODULE_PERFORM_GET_COLOR_SPACE_FROM_HANDLE 6
#define GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO 7
#define GRALLOC_MODULE_PERFORM_GET_MAP_SECURE_BUFFER_INFO 8
+#define GRALLOC_MODULE_PERFORM_GET_UBWC_FLAG 9
#define GRALLOC_HEAP_MASK (GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP |\
GRALLOC_USAGE_PRIVATE_IOMMU_HEAP |\
diff --git a/libgralloc/mapper.cpp b/libgralloc/mapper.cpp
index 44f4fb2..5382300 100644
--- a/libgralloc/mapper.cpp
+++ b/libgralloc/mapper.cpp
@@ -447,6 +447,17 @@
}
} break;
+ case GRALLOC_MODULE_PERFORM_GET_UBWC_FLAG:
+ {
+ private_handle_t* hnd = va_arg(args, private_handle_t*);
+ int *flag = va_arg(args, int *);
+ if (private_handle_t::validate(hnd)) {
+ return res;
+ }
+ *flag = hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
+ res = 0;
+ } break;
+
default:
break;
}
diff --git a/libhdmi/hdmi.cpp b/libhdmi/hdmi.cpp
index bca7a0b..1b2ffe0 100644
--- a/libhdmi/hdmi.cpp
+++ b/libhdmi/hdmi.cpp
@@ -95,6 +95,7 @@
mUnderscanSupported(false), mMDPDownscaleEnabled(false)
{
memset(&mVInfo, 0, sizeof(mVInfo));
+ mFbNum = qdutils::getHDMINode();
mDisplayId = HWC_DISPLAY_EXTERNAL;
// Update the display if HDMI is connected as primary
@@ -102,7 +103,6 @@
mDisplayId = HWC_DISPLAY_PRIMARY;
}
- mFbNum = overlay::Overlay::getInstance()->getFbForDpy(mDisplayId);
// 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
@@ -684,8 +684,7 @@
}
bool HDMIDisplay::isHDMIPrimaryDisplay() {
- int hdmiNode = qdutils::getHDMINode();
- return (hdmiNode == HWC_DISPLAY_PRIMARY);
+ return (mFbNum == HWC_DISPLAY_PRIMARY);
}
int HDMIDisplay::getConnectedState() {
@@ -739,6 +738,124 @@
return 0;
}
+static const char* getS3DStringFromMode(int s3dMode) {
+ const char* ret ;
+ switch(s3dMode) {
+ case HDMI_S3D_NONE:
+ ret = "None";
+ break;
+ case HDMI_S3D_SIDE_BY_SIDE:
+ ret = "SSH";
+ break;
+ case HDMI_S3D_TOP_AND_BOTTOM:
+ ret = "TAB";
+ break;
+ //FP (FramePacked) mode is not supported in the HAL
+ default:
+ ALOGD("%s: Unsupported s3d mode: %d", __FUNCTION__, s3dMode);
+ ret = NULL;
+ }
+ return ret;
+}
+
+bool HDMIDisplay::isS3DModeSupported(int s3dMode) {
+ if(s3dMode == HDMI_S3D_NONE)
+ return true;
+
+ char s3dEdidStr[PAGE_SIZE] = {'\0'};
+
+ const char *s3dModeString = getS3DStringFromMode(s3dMode);
+
+ if(s3dModeString == NULL)
+ return false;
+
+ int s3dEdidNode = openDeviceNode("edid_3d_modes", O_RDONLY);
+ if(s3dEdidNode >= 0) {
+ ssize_t len = read(s3dEdidNode, s3dEdidStr, sizeof(s3dEdidStr)-1);
+ if (len > 0) {
+ ALOGI("%s: s3dEdidStr: %s mCurrentMode:%d", __FUNCTION__,
+ s3dEdidStr, mCurrentMode);
+ //Three level inception!
+ //The string looks like 16=SSH,4=FP:TAB:SSH,5=FP:SSH,32=FP:TAB:SSH
+ char *saveptr_l1, *saveptr_l2, *saveptr_l3;
+ char *l1, *l2, *l3;
+ int mode = 0;
+ l1 = strtok_r(s3dEdidStr,",", &saveptr_l1);
+ while (l1 != NULL) {
+ l2 = strtok_r(l1, "=", &saveptr_l2);
+ if (l2 != NULL)
+ mode = atoi(l2);
+ while (l2 != NULL) {
+ if (mode != mCurrentMode) {
+ break;
+ }
+ l3 = strtok_r(l2, ":", &saveptr_l3);
+ while (l3 != NULL) {
+ if (strncmp(l3, s3dModeString,
+ strlen(s3dModeString)) == 0) {
+ close(s3dEdidNode);
+ return true;
+ }
+ l3 = strtok_r(NULL, ":", &saveptr_l3);
+ }
+ l2 = strtok_r(NULL, "=", &saveptr_l2);
+ }
+ l1 = strtok_r(NULL, ",", &saveptr_l1);
+ }
+
+ }
+ } else {
+ ALOGI("%s: /sys/class/graphics/fb%d/edid_3d_modes could not be opened : %s",
+ __FUNCTION__, mFbNum, strerror(errno));
+ }
+ close(s3dEdidNode);
+ return false;
+}
+
+bool HDMIDisplay::writeS3DMode(int s3dMode) {
+ bool ret = true;
+ if(mFbNum != -1) {
+ int hdmiS3DModeFile = openDeviceNode("s3d_mode", O_RDWR);
+ if(hdmiS3DModeFile >=0 ) {
+ char curModeStr[PROPERTY_VALUE_MAX];
+ int currentS3DMode = -1;
+ size_t len = read(hdmiS3DModeFile, curModeStr, sizeof(curModeStr) - 1);
+ if(len > 0) {
+ currentS3DMode = atoi(curModeStr);
+ } else {
+ ret = false;
+ ALOGE("%s: Failed to read s3d_mode", __FUNCTION__);
+ }
+
+ if (currentS3DMode >=0 && currentS3DMode != s3dMode) {
+ ssize_t err = -1;
+ ALOGD_IF(DEBUG, "%s: mode = %d",
+ __FUNCTION__, s3dMode);
+ char mode[PROPERTY_VALUE_MAX];
+ snprintf(mode,sizeof(mode),"%d",s3dMode);
+ err = write(hdmiS3DModeFile, mode, sizeof(mode));
+ if (err <= 0) {
+ ALOGE("%s: file write failed 's3d_mode'", __FUNCTION__);
+ ret = false;
+ }
+ }
+ close(hdmiS3DModeFile);
+ }
+ }
+ return ret;
+}
+
+bool HDMIDisplay::configure3D(int s3dMode) {
+ if(isS3DModeSupported(s3dMode)) {
+ if(!writeS3DMode(s3dMode))
+ return false;
+ } else {
+ ALOGE("%s: 3D mode: %d is not supported", __FUNCTION__, s3dMode);
+ return false;
+ }
+ return true;
+}
+
// returns false if the xres or yres of the new config do
// not match the current config
bool HDMIDisplay::isValidConfigChange(int newConfig) {
diff --git a/libhdmi/hdmi.h b/libhdmi/hdmi.h
index 32c48ff..d1d5759 100644
--- a/libhdmi/hdmi.h
+++ b/libhdmi/hdmi.h
@@ -64,6 +64,8 @@
int getAttrForConfig(int config, uint32_t& xres,
uint32_t& yres, uint32_t& refresh, uint32_t& fps) const;
int getDisplayConfigs(uint32_t* configs, size_t* numConfigs) const;
+ bool configure3D(int s3dMode);
+ bool isS3DModeSupported(int s3dMode);
private:
int getModeCount() const;
@@ -87,6 +89,7 @@
void requestNewPage(int pageNumber);
void readConfigs();
bool readResFile(char* configBuffer);
+ bool writeS3DMode(int s3dMode);
int mFd;
int mFbNum;
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index 65482d7..68f168a 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -131,8 +131,10 @@
return renderArea;
}
-bool CopyBit::isLayerChanging(hwc_display_contents_1_t *list, int k) {
+bool CopyBit::isLayerChanging(hwc_context_t *ctx,
+ hwc_display_contents_1_t *list, int k) {
if((mLayerCache.hnd[k] != list->hwLayers[k].handle) ||
+ (mLayerCache.drop[k] != ctx->copybitDrop[k]) ||
(mLayerCache.displayFrame[k].left !=
list->hwLayers[k].displayFrame.left) ||
(mLayerCache.displayFrame[k].top !=
@@ -161,7 +163,7 @@
int updatingLayerCount = 0;
for (int k = ctx->listStats[dpy].numAppLayers-1; k >= 0 ; k--){
//swap rect will kick in only for single updating layer
- if(isLayerChanging(list, k)) {
+ if(isLayerChanging(ctx, list, k)) {
updatingLayerCount ++;
if(updatingLayerCount == 1)
changingLayerIndex = k;
@@ -1233,6 +1235,7 @@
for (int i=0; i<ctx->listStats[dpy].numAppLayers; i++){
hnd[i] = list->hwLayers[i].handle;
displayFrame[i] = list->hwLayers[i].displayFrame;
+ drop[i] = ctx->copybitDrop[i];
}
}
diff --git a/libhwcomposer/hwc_copybit.h b/libhwcomposer/hwc_copybit.h
index 6ead4a7..4442afc 100644
--- a/libhwcomposer/hwc_copybit.h
+++ b/libhwcomposer/hwc_copybit.h
@@ -61,6 +61,7 @@
int layerCount;
buffer_handle_t hnd[MAX_NUM_APP_LAYERS];
hwc_rect_t displayFrame[MAX_NUM_APP_LAYERS];
+ bool drop[MAX_NUM_APP_LAYERS];
/* c'tor */
LayerCache();
/* clear caching info*/
@@ -135,7 +136,8 @@
int dpy);
int checkDirtyRect(hwc_context_t *ctx, hwc_display_contents_1_t *list,
int dpy);
- bool isLayerChanging(hwc_display_contents_1_t *list, int k);
+ bool isLayerChanging(hwc_context_t *ctx,
+ hwc_display_contents_1_t *list, int k);
};
}; //namespace qhwc
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index 8660740..ef83008 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -25,6 +25,7 @@
#include <overlayRotator.h>
#include "hwc_fbupdate.h"
#include "mdp_version.h"
+#include <video/msm_hdmi_modes.h>
using namespace qdutils;
using namespace overlay;
@@ -499,10 +500,25 @@
hwc_rect_t dstL = displayFrame;
hwc_rect_t dstR = displayFrame;
+ if(ctx->dpyAttr[mDpy].s3dMode == HDMI_S3D_SIDE_BY_SIDE) {
+ dstL.left = displayFrame.left/2;
+ dstL.right = displayFrame.right/2;
+
+ dstR.left = mAlignedFBWidth/2 + displayFrame.left/2;
+ dstR.right = mAlignedFBWidth/2 + displayFrame.right/2;
+ } else if(ctx->dpyAttr[mDpy].s3dMode == HDMI_S3D_TOP_AND_BOTTOM) {
+ dstL.top = displayFrame.top/2;
+ dstL.bottom = displayFrame.bottom/2;
+
+ dstR.top = mAlignedFBHeight/2 + displayFrame.top/2;
+ dstR.bottom = mAlignedFBHeight/2 + displayFrame.bottom/2;
+ }
+
//Request left pipe (or 1 by default)
Overlay::PipeSpecs pipeSpecs;
pipeSpecs.formatClass = Overlay::FORMAT_RGB;
- pipeSpecs.needsScaling = qhwc::needsScaling(layer);
+ pipeSpecs.needsScaling = (qhwc::needsScaling(layer) ||
+ needs3DComposition(ctx,mDpy));
pipeSpecs.dpy = mDpy;
pipeSpecs.mixer = Overlay::MIXER_DEFAULT;
pipeSpecs.fb = true;
@@ -519,6 +535,7 @@
a) FB's width is > Mixer width or
b) On primary, driver has indicated with caps to split always. This is
based on an empirically derived value of panel height.
+ c) The composition is 3D
*/
const bool primarySplitAlways = (mDpy == HWC_DISPLAY_PRIMARY) and
@@ -533,7 +550,8 @@
if((cropWidth > qdutils::MDPVersion::getInstance().getMaxPipeWidth()) or
(primarySplitAlways and
- (cropWidth > lSplit or layerClock > mixerClock))) {
+ (cropWidth > lSplit or layerClock > mixerClock)) or
+ needs3DComposition(ctx, mDpy)) {
destR = ov.getPipe(pipeSpecs);
if(destR == ovutils::OV_INVALID) {
ALOGE("%s: No pipes available to configure fb for dpy %d's right"
@@ -546,10 +564,12 @@
}
//Split crop equally when using 2 pipes
- cropL.right = (sourceCrop.right + sourceCrop.left) / 2;
- cropR.left = cropL.right;
- dstL.right = (displayFrame.right + displayFrame.left) / 2;
- dstR.left = dstL.right;
+ if(!needs3DComposition(ctx, mDpy)) {
+ cropL.right = (sourceCrop.right + sourceCrop.left) / 2;
+ cropR.left = cropL.right;
+ dstL.right = (displayFrame.right + displayFrame.left) / 2;
+ dstR.left = dstL.right;
+ }
}
mDestLeft = destL;
@@ -563,6 +583,12 @@
}
}
+ // XXX: Figure out why we need this with source split
+ // Currently, the driver silently fails to configure the right pipe
+ // if we don't increment the zorder
+ if (needs3DComposition(ctx, mDpy))
+ parg.zorder = eZorder(parg.zorder + 1);
+
//configure right pipe
if(destR != OV_INVALID) {
if(configMdp(ctx->mOverlay, parg, orient,
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index caa1344..b45279f 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -806,6 +806,10 @@
return false;
}
+ // No MDP composition for 3D
+ if(needs3DComposition(ctx, mDpy))
+ return false;
+
// check for action safe flag and MDP scaling mode which requires scaling.
if(ctx->dpyAttr[mDpy].mActionSafePresent
|| ctx->dpyAttr[mDpy].mMDPScalingMode) {
@@ -1340,7 +1344,7 @@
if(mCurrentFrame.fbCount)
mCurrentFrame.fbZ = mCurrentFrame.mdpCount;
- if(sEnableYUVsplit){
+ if(sEnableYUVsplit || needs3DComposition(ctx, mDpy)){
adjustForSourceSplit(ctx, list);
}
@@ -1370,6 +1374,10 @@
return false;
}
+ // No MDP composition for 3D
+ if(needs3DComposition(ctx,mDpy))
+ return false;
+
const bool secureOnly = true;
return mdpOnlyLayersComp(ctx, list, not secureOnly) or
mdpOnlyLayersComp(ctx, list, secureOnly);
@@ -1831,6 +1839,9 @@
}
continue;
}
+ if(needs3DComposition(ctx,mDpy) && get3DFormat(hnd) != HAL_NO_3D) {
+ mdpNextZOrder++;
+ }
if(configure(ctx, layer, mCurrentFrame.mdpToLayer[mdpIndex]) != 0 ){
ALOGD_IF(isDebug(), "%s: Failed to configure overlay for \
layer %d",__FUNCTION__, index);
@@ -2083,7 +2094,7 @@
return ret;
}
-bool MDPComp::allocSplitVGPipesfor4k2k(hwc_context_t *ctx, int index) {
+bool MDPComp::allocSplitVGPipes(hwc_context_t *ctx, int index) {
bool bRet = true;
int mdpIndex = mCurrentFrame.layerToMDP[index];
@@ -2186,7 +2197,7 @@
hwc_layer_1_t* layer = &list->hwLayers[index];
private_handle_t *hnd = (private_handle_t *)layer->handle;
if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
- if(allocSplitVGPipesfor4k2k(ctx, index)){
+ if(allocSplitVGPipes(ctx, index)){
continue;
}
}
@@ -2363,7 +2374,9 @@
mdpNextZOrder++;
hwc_layer_1_t* layer = &list->hwLayers[index];
private_handle_t *hnd = (private_handle_t *)layer->handle;
- if(isYUVSplitNeeded(hnd)) {
+ if(isYUVSplitNeeded(hnd) ||
+ (needs3DComposition(ctx,mDpy) &&
+ get3DFormat(hnd) != HAL_NO_3D)) {
hwc_rect_t dst = layer->displayFrame;
if((dst.left > lSplit) || (dst.right < lSplit)) {
mCurrentFrame.mdpCount += 1;
@@ -2426,11 +2439,16 @@
const int lSplit = getLeftSplit(ctx, mDpy);
if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
if((dst.left > lSplit)||(dst.right < lSplit)){
- if(allocSplitVGPipesfor4k2k(ctx, index)){
+ if(allocSplitVGPipes(ctx, index)){
continue;
}
}
}
+ //XXX: Check for forced 2D composition
+ if(needs3DComposition(ctx, mDpy) && get3DFormat(hnd) != HAL_NO_3D)
+ if(allocSplitVGPipes(ctx,index))
+ continue;
+
int mdpIndex = mCurrentFrame.layerToMDP[index];
PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
info.pipeInfo = new MdpPipeInfoSplit;
@@ -2493,7 +2511,9 @@
}
// Set the Handle timeout to true for MDP or MIXED composition.
- if(sIdleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount) {
+ if(sIdleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount &&
+ !(needs3DComposition(ctx, HWC_DISPLAY_PRIMARY) ||
+ needs3DComposition(ctx, HWC_DISPLAY_EXTERNAL))) {
sHandleTimeout = true;
}
@@ -2518,7 +2538,8 @@
int mdpIndex = mCurrentFrame.layerToMDP[i];
- if(isYUVSplitNeeded(hnd) && sEnableYUVsplit)
+ if((isYUVSplitNeeded(hnd) && sEnableYUVsplit) ||
+ (needs3DComposition(ctx, mDpy) && get3DFormat(hnd) != HAL_NO_3D))
{
MdpYUVPipeInfo& pipe_info =
*(MdpYUVPipeInfo*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
@@ -2826,6 +2847,7 @@
int rotFlags = ROT_FLAGS_NONE;
uint32_t format = ovutils::getMdpFormat(hnd->format, hnd->flags);
Whf whf(getWidth(hnd), getHeight(hnd), format, hnd->size);
+ eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
"dest_pipeR: %d",__FUNCTION__, layer, z, lDest, rDest);
@@ -2841,6 +2863,12 @@
trimAgainstROI(ctx, crop, dst);
}
+ if(needs3DComposition(ctx, mDpy) &&
+ get3DFormat(hnd) != HAL_NO_3D){
+ return configure3DVideo(ctx, layer, mDpy, mdpFlags, z, lDest,
+ rDest, &PipeLayerPair.rot);
+ }
+
// Handle R/B swap
if (layer->flags & HWC_FORMAT_RB_SWAP) {
if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
@@ -2857,7 +2885,6 @@
calcExtDisplayPosition(ctx, hnd, mDpy, crop, dst, transform, orient);
int downscale = getRotDownscale(ctx, layer);
- eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
setMdpFlags(ctx, layer, mdpFlags, downscale, transform);
if(lDest != OV_INVALID && rDest != OV_INVALID) {
@@ -3044,9 +3071,7 @@
int perfHint = 0x4501; // 45-display layer hint, 01-Enable
sPerfLockHandle = sPerfLockAcquire(0 /*handle*/, 0/*duration*/,
&perfHint, sizeof(perfHint)/sizeof(int));
- if(sPerfLockHandle < 0) {
- ALOGE("Perf Lock Acquire Failed");
- } else {
+ if(sPerfLockHandle > 0) {
perflockFlag = 1;
}
}
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 7c46c1a..a83f51f 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -270,7 +270,7 @@
//Enable 4kx2k yuv layer split
static bool sEnableYUVsplit;
bool mModeOn; // if prepare happened
- bool allocSplitVGPipesfor4k2k(hwc_context_t *ctx, int index);
+ bool allocSplitVGPipes(hwc_context_t *ctx, int index);
//Enable Partial Update for MDP3 targets
static bool enablePartialUpdateForMDP3;
static void *sLibPerfHint;
diff --git a/libhwcomposer/hwc_qclient.cpp b/libhwcomposer/hwc_qclient.cpp
index 09013c6..487ec77 100644
--- a/libhwcomposer/hwc_qclient.cpp
+++ b/libhwcomposer/hwc_qclient.cpp
@@ -35,6 +35,8 @@
#include <hwc_virtual.h>
#include <overlay.h>
#include <display_config.h>
+#include <hdmi.h>
+#include <video/msm_hdmi_modes.h>
#define QCLIENT_DEBUG 0
@@ -338,6 +340,21 @@
}
}
+static void setS3DMode(hwc_context_t* ctx, int mode) {
+ if (ctx->mHDMIDisplay) {
+ if(ctx->mHDMIDisplay->isS3DModeSupported(mode)) {
+ ALOGD("%s: Force S3D mode to %d", __FUNCTION__, mode);
+ Locker::Autolock _sl(ctx->mDrawLock);
+ ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].s3dModeForced = true;
+ setup3DMode(ctx, HWC_DISPLAY_EXTERNAL, mode);
+ } else {
+ ALOGD("%s: mode %d is not supported", __FUNCTION__, mode);
+ }
+ } else {
+ ALOGE("%s: No HDMI Display detected", __FUNCTION__);
+ }
+}
+
status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel,
Parcel* outParcel) {
status_t ret = NO_ERROR;
@@ -398,6 +415,9 @@
case IQService::TOGGLE_SCREEN_UPDATE:
toggleScreenUpdate(mHwcContext, inParcel->readInt32());
break;
+ case IQService::SET_S3D_MODE:
+ setS3DMode(mHwcContext, inParcel->readInt32());
+ break;
default:
ret = NO_ERROR;
}
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 9ea8246..05ab503 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -45,6 +45,7 @@
#include "qd_utils.h"
#include <sys/sysinfo.h>
#include <dlfcn.h>
+#include <video/msm_hdmi_modes.h>
using namespace qClient;
using namespace qService;
@@ -351,8 +352,14 @@
ctx->dpyAttr[i].mActionSafePresent = false;
ctx->dpyAttr[i].mAsWidthRatio = 0;
ctx->dpyAttr[i].mAsHeightRatio = 0;
+ ctx->dpyAttr[i].s3dMode = HDMI_S3D_NONE;
+ ctx->dpyAttr[i].s3dModeForced = false;
}
+ //Make sure that the 3D mode is unset at bootup
+ //This makes sure that the state is accurate on framework reboots
+ ctx->mHDMIDisplay->configure3D(HDMI_S3D_NONE);
+
for (uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
ctx->mPrevHwLayerCount[i] = 0;
}
@@ -1008,6 +1015,8 @@
ctx->listStats[dpy].refreshRateRequest = ctx->dpyAttr[dpy].refreshRate;
uint32_t refreshRate = 0;
qdutils::MDPVersion& mdpHw = qdutils::MDPVersion::getInstance();
+ int s3dFormat = HAL_NO_3D;
+ int s3dLayerCount = 0;
ctx->listStats[dpy].mAIVVideoMode = false;
resetROI(ctx, dpy);
@@ -1063,6 +1072,14 @@
ctx->listStats[dpy].yuv4k2kIndices[yuv4k2kCount] = (int)i;
yuv4k2kCount++;
}
+
+ // Gets set if one YUV layer is 3D
+ if (displaySupports3D(ctx,dpy)) {
+ s3dFormat = get3DFormat(hnd);
+ if(s3dFormat != HAL_NO_3D)
+ s3dLayerCount++;
+ }
+
}
if(layer->blending == HWC_BLENDING_PREMULT)
ctx->listStats[dpy].preMultipliedAlpha = true;
@@ -1089,6 +1106,17 @@
}
#endif
}
+
+ //Set the TV's 3D mode based on format if it was not forced
+ //Only one 3D YUV layer is supported on external
+ //If there is more than one 3D YUV layer, the switch to 3D cannot occur.
+ if( !ctx->dpyAttr[dpy].s3dModeForced && (s3dLayerCount <= 1)) {
+ //XXX: Rapidly going in and out of 3D mode in some cases such
+ // as rotation might cause flickers. The OEMs are recommended to disable
+ // rotation on HDMI globally or in the app that plays 3D video
+ setup3DMode(ctx, dpy, convertS3DFormatToMode(s3dFormat));
+ }
+
if(ctx->listStats[dpy].yuvCount > 0) {
if (property_get("hw.cabl.yuv", property, NULL) > 0) {
if (atoi(property) != 1) {
@@ -2197,6 +2225,113 @@
return 0;
}
+int configure3DVideo(hwc_context_t *ctx, hwc_layer_1_t *layer,
+ const int& dpy, eMdpFlags& mdpFlagsL, eZorder& z,
+ const eDest& lDest, const eDest& rDest,
+ Rotator **rot) {
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+ if(!hnd) {
+ ALOGE("%s: layer handle is NULL", __FUNCTION__);
+ return -1;
+ }
+ //Both pipes are configured to the same mixer
+ eZorder lz = z;
+ eZorder rz = (eZorder)(z + 1);
+
+ MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+
+ hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
+ hwc_rect_t dst = layer->displayFrame;
+ int transform = layer->transform;
+ eTransform orient = static_cast<eTransform>(transform);
+ int rotFlags = ROT_FLAGS_NONE;
+ uint32_t format = ovutils::getMdpFormat(hnd->format, hnd->flags);
+ Whf whf(getWidth(hnd), getHeight(hnd), format, (uint32_t)hnd->size);
+
+ int downscale = getRotDownscale(ctx, layer);
+ setMdpFlags(ctx, layer, mdpFlagsL, downscale, transform);
+
+ //XXX: Check if rotation is supported and valid for 3D
+ if((has90Transform(layer) or downscale) and isRotationDoable(ctx, hnd)) {
+ (*rot) = ctx->mRotMgr->getNext();
+ if((*rot) == NULL) return -1;
+ ctx->mLayerRotMap[dpy]->add(layer, *rot);
+ //Configure rotator for pre-rotation
+ if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {
+ ALOGE("%s: configRotator failed!", __FUNCTION__);
+ return -1;
+ }
+ updateSource(orient, whf, crop, *rot);
+ rotFlags |= ROT_PREROTATED;
+ }
+
+ eMdpFlags mdpFlagsR = mdpFlagsL;
+
+ hwc_rect_t cropL = crop, dstL = dst;
+ hwc_rect_t cropR = crop, dstR = dst;
+ int hw_w = ctx->dpyAttr[dpy].xres;
+ int hw_h = ctx->dpyAttr[dpy].yres;
+
+ if(get3DFormat(hnd) == HAL_3D_SIDE_BY_SIDE_L_R ||
+ get3DFormat(hnd) == HAL_3D_SIDE_BY_SIDE_R_L) {
+ // Calculate Left rects
+ // XXX: This assumes crop.right/2 is the center point of the video
+ cropL.right = crop.right/2;
+ dstL.left = dst.left/2;
+ dstL.right = dst.right/2;
+
+ // Calculate Right rects
+ cropR.left = crop.right/2;
+ dstR.left = hw_w/2 + dst.left/2;
+ dstR.right = hw_w/2 + dst.right/2;
+ } else if(get3DFormat(hnd) == HAL_3D_TOP_BOTTOM) {
+ // Calculate Left rects
+ cropL.bottom = crop.bottom/2;
+ dstL.top = dst.top/2;
+ dstL.bottom = dst.bottom/2;
+
+ // Calculate Right rects
+ cropR.top = crop.bottom/2;
+ dstR.top = hw_h/2 + dst.top/2;
+ dstR.bottom = hw_h/2 + dst.bottom/2;
+ } else {
+ ALOGE("%s: Unsupported 3D mode ", __FUNCTION__);
+ return -1;
+ }
+
+ //For the mdp, since either we are pre-rotating or MDP does flips
+ orient = OVERLAY_TRANSFORM_0;
+ transform = 0;
+
+ //configure left pipe
+ if(lDest != OV_INVALID) {
+ PipeArgs pargL(mdpFlagsL, whf, lz,
+ static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
+ (ovutils::eBlending) getBlending(layer->blending));
+
+ if(configMdp(ctx->mOverlay, pargL, orient,
+ cropL, dstL, metadata, lDest) < 0) {
+ ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
+ return -1;
+ }
+ }
+
+ //configure right pipe
+ if(rDest != OV_INVALID) {
+ PipeArgs pargR(mdpFlagsR, whf, rz,
+ static_cast<eRotFlags>(rotFlags),
+ layer->planeAlpha,
+ (ovutils::eBlending) getBlending(layer->blending));
+ if(configMdp(ctx->mOverlay, pargR, orient,
+ cropR, dstR, metadata, rDest) < 0) {
+ ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
int configureSourceSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
const int& dpy, eMdpFlags& mdpFlagsL, eZorder& z,
const eDest& lDest, const eDest& rDest,
@@ -2810,4 +2945,41 @@
ctx->dpyAttr[dpy].isActive = false;
}
+int convertS3DFormatToMode(int s3DFormat) {
+ int ret;
+ switch(s3DFormat) {
+ case HAL_3D_SIDE_BY_SIDE_L_R:
+ case HAL_3D_SIDE_BY_SIDE_R_L:
+ ret = HDMI_S3D_SIDE_BY_SIDE;
+ break;
+ case HAL_3D_TOP_BOTTOM:
+ ret = HDMI_S3D_TOP_AND_BOTTOM;
+ break;
+ default:
+ ret = HDMI_S3D_NONE;
+ }
+ return ret;
+}
+
+bool needs3DComposition(hwc_context_t* ctx, int dpy) {
+ return (displaySupports3D(ctx, dpy) && ctx->dpyAttr[dpy].connected &&
+ ctx->dpyAttr[dpy].s3dMode != HDMI_S3D_NONE);
+}
+
+void setup3DMode(hwc_context_t *ctx, int dpy, int s3dMode) {
+ if (ctx->dpyAttr[dpy].s3dMode != s3dMode) {
+ ALOGD("%s: setup 3D mode: %d", __FUNCTION__, s3dMode);
+ if(ctx->mHDMIDisplay->configure3D(s3dMode)) {
+ ctx->dpyAttr[dpy].s3dMode = s3dMode;
+ }
+ }
+}
+
+bool displaySupports3D(hwc_context_t* ctx, int dpy) {
+ return ((dpy == HWC_DISPLAY_EXTERNAL) ||
+ ((dpy == HWC_DISPLAY_PRIMARY) &&
+ ctx->mHDMIDisplay->isHDMIPrimaryDisplay()));
+}
+
+
};//namespace qhwc
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index a97c59b..f11eed5 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -117,6 +117,18 @@
uint32_t xres_new;
uint32_t yres_new;
+ // This is the 3D mode to which the TV is set
+ // The mode may be set via the appearance of a layer with 3D format
+ // or by forcing the mode via binder.
+ // If the mode is set via binder, the s3dModeForced flag is set, so that the
+ // mode is not changed back when the 3D video layer drops out.
+ // If the forced mode is different from the one in 3D video, the results
+ // are unpredictable. The assumption is made here that the caller forcing
+ // the mode via binder knows the right formats to use.
+ // The s3dModeForced flag is also used to force 2D if the s3dMode is
+ // HDMI_S3D_NONE
+ int s3dMode;
+ bool s3dModeForced;
};
struct ListStats {
@@ -411,6 +423,15 @@
const ovutils::eDest& lDest,
const ovutils::eDest& rDest, overlay::Rotator **rot);
+//Check if the current round needs 3D composition
+bool needs3DComposition(hwc_context_t* ctx, int dpy);
+
+//Routine to configure 3D video
+int configure3DVideo(hwc_context_t *ctx, hwc_layer_1_t *layer, const int& dpy,
+ ovutils::eMdpFlags& mdpFlags, ovutils::eZorder& z,
+ const ovutils::eDest& lDest,
+ const ovutils::eDest& rDest, overlay::Rotator **rot);
+
//Routine to split and configure high resolution YUV layer (> 2048 width)
int configureSourceSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
const int& dpy,
@@ -444,6 +465,16 @@
// Checks if boot animation has completed and applies default mode
void processBootAnimCompleted(hwc_context_t *ctx);
+//The gralloc API and driver have different formats
+//The format needs to be converted before passing to libhdmi
+int convertS3DFormatToMode(int s3DFormat);
+
+//Configure resources for 3D mode
+void setup3DMode(hwc_context_t* ctx, int dpy, int s3dMode);
+
+//Checks if this display supports 3D
+bool displaySupports3D(hwc_context_t* ctx, int dpy);
+
// Inline utility functions
static inline bool isSkipLayer(const hwc_layer_1_t* l) {
return (UNLIKELY(l && (l->flags & HWC_SKIP_LAYER)));
@@ -489,6 +520,14 @@
return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY));
}
+static inline uint32_t get3DFormat(const private_handle_t* hnd) {
+ MetaData_t *metadata = reinterpret_cast<MetaData_t*>(hnd->base_metadata);
+ if(isYuvBuffer(hnd) && metadata && metadata->operation & S3D_FORMAT) {
+ return metadata->s3dFormat;
+ }
+ return HAL_NO_3D;
+}
+
static inline int getWidth(const private_handle_t* hnd) {
MetaData_t *metadata = reinterpret_cast<MetaData_t*>(hnd->base_metadata);
if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
@@ -644,7 +683,7 @@
bool mBWCEnabled;
// Provides a way for OEM's to disable setting dynfps via metadata.
bool mUseMetaDataRefreshRate;
- // Stores the hpd enabled status- avoids re-enabling HDP on suspend resume.
+ // Stores the hpd enabled status- avoids re-enabling HDP on suspend resume.
bool mHPDEnabled;
//Used to notify that boot has completed
bool mBootAnimCompleted;
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index cd2d116..796e506 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -60,6 +60,7 @@
SET_PARTIAL_UPDATE = 19, // Preference on partial update feature
TOGGLE_SCREEN_UPDATE = 20, // Provides ability to disable screen updates
SET_FRAME_DUMP_CONFIG = 21, // Provides ability to set the frame dump config
+ SET_S3D_MODE = 22, // Set the 3D mode as specified in msm_hdmi_modes.h
COMMAND_LIST_END = 400,
};