sde: Add support for flush.
Add support for flush on a display. This flush shall release pipes,
all pending buffers and associated fences that are currently held
by display engine.
Change-Id: I8a8d7030fb6af031b3760c172fce4f1f8ef3fedc
diff --git a/displayengine/include/core/display_interface.h b/displayengine/include/core/display_interface.h
index bdeb8a3..ff99cb8 100755
--- a/displayengine/include/core/display_interface.h
+++ b/displayengine/include/core/display_interface.h
@@ -207,6 +207,19 @@
*/
virtual DisplayError Commit(LayerStack *layer_stack) = 0;
+ /*! @brief Method to flush any pending buffers/fences submitted previously via Commit() call.
+
+ @details Client shall call this method to request the Display Engine to release all buffers and
+ respective fences currently in use. This operation may result in a blank display on the panel
+ until a new frame is submitted for composition.
+
+ @return \link DisplayError \endlink
+
+ @sa Prepare
+ @sa Commit
+ */
+ virtual DisplayError Flush() = 0;
+
/*! @brief Method to get current state of the display device.
@param[out] state \link DisplayState \endlink
diff --git a/displayengine/libs/core/display_base.cpp b/displayengine/libs/core/display_base.cpp
index 080deb7..4d8f5aa 100644
--- a/displayengine/libs/core/display_base.cpp
+++ b/displayengine/libs/core/display_base.cpp
@@ -135,6 +135,8 @@
}
}
comp_manager_->PostPrepare(display_comp_ctx_, &hw_layers_);
+ } else {
+ return kErrorNotSupported;
}
return error;
@@ -149,18 +151,19 @@
return kErrorParameters;
}
- if (!pending_commit_) {
- DLOGE("Commit: Corresponding Prepare() is not called for display = %d", display_type_);
- return kErrorUndefined;
- }
-
if (state_ == kStateOn) {
+ if (!pending_commit_) {
+ DLOGE("Commit: Corresponding Prepare() is not called for display = %d", display_type_);
+ return kErrorUndefined;
+ }
error = hw_intf_->Commit(hw_device_, &hw_layers_);
if (error == kErrorNone) {
comp_manager_->PostCommit(display_comp_ctx_, &hw_layers_);
} else {
DLOGE("Unexpected error. Commit failed on driver.");
}
+ } else {
+ return kErrorNotSupported;
}
pending_commit_ = false;
@@ -168,6 +171,27 @@
return kErrorNone;
}
+DisplayError DisplayBase::Flush() {
+ SCOPE_LOCK(locker_);
+
+ DisplayError error = kErrorNone;
+
+ if (state_ != kStateOn) {
+ return kErrorNone;
+ }
+
+ hw_layers_.info.count = 0;
+ error = hw_intf_->Flush(hw_device_);
+ if (error == kErrorNone) {
+ comp_manager_->Purge(display_comp_ctx_);
+ pending_commit_ = false;
+ } else {
+ DLOGV("Failed to flush device.");
+ }
+
+ return error;
+}
+
DisplayError DisplayBase::GetDisplayState(DisplayState *state) {
SCOPE_LOCK(locker_);
diff --git a/displayengine/libs/core/display_base.h b/displayengine/libs/core/display_base.h
index 3f0e24f..187ab8d 100644
--- a/displayengine/libs/core/display_base.h
+++ b/displayengine/libs/core/display_base.h
@@ -43,6 +43,7 @@
virtual DisplayError Deinit();
virtual DisplayError Prepare(LayerStack *layer_stack);
virtual DisplayError Commit(LayerStack *layer_stack);
+ virtual DisplayError Flush();
virtual DisplayError GetDisplayState(DisplayState *state);
virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count);
virtual DisplayError GetConfig(DisplayConfigFixedInfo *fixed_info);
diff --git a/displayengine/libs/core/display_hdmi.cpp b/displayengine/libs/core/display_hdmi.cpp
index 14a09f1..07bbca0 100644
--- a/displayengine/libs/core/display_hdmi.cpp
+++ b/displayengine/libs/core/display_hdmi.cpp
@@ -77,5 +77,29 @@
return best_config_mode;
}
+DisplayError DisplayHDMI::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_->Flush(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_hdmi.h b/displayengine/libs/core/display_hdmi.h
index 0bb9dc8..8de7fdf 100644
--- a/displayengine/libs/core/display_hdmi.h
+++ b/displayengine/libs/core/display_hdmi.h
@@ -33,6 +33,7 @@
public:
DisplayHDMI(DisplayEventHandler *event_handler, HWInterface *hw_intf, CompManager *comp_manager);
virtual int GetBestConfig();
+ virtual DisplayError SetDisplayState(DisplayState state);
};
} // namespace sde
diff --git a/displayengine/libs/core/hw_framebuffer.cpp b/displayengine/libs/core/hw_framebuffer.cpp
index 0644e7d..9789240 100644
--- a/displayengine/libs/core/hw_framebuffer.cpp
+++ b/displayengine/libs/core/hw_framebuffer.cpp
@@ -392,17 +392,19 @@
break;
}
}
+
if (MapHDMIDisplayTiming(timing_mode, &vscreeninfo) == false) {
return kErrorParameters;
}
+
STRUCT_VAR(msmfb_metadata, metadata);
- memset(&metadata, 0 , sizeof(metadata));
metadata.op = metadata_op_vic;
metadata.data.video_info_code = timing_mode->video_format;
if (ioctl(hw_context->device_fd, MSMFB_METADATA_SET, &metadata) == -1) {
IOCTL_LOGE(MSMFB_METADATA_SET, hw_context->type);
return kErrorHardware;
}
+
DLOGI("SetInfo<Mode=%d %dx%d (%d,%d,%d),(%d,%d,%d) %dMHz>", vscreeninfo.reserved[3] & 0xFF00,
vscreeninfo.xres, vscreeninfo.yres, vscreeninfo.right_margin, vscreeninfo.hsync_len,
vscreeninfo.left_margin, vscreeninfo.lower_margin, vscreeninfo.vsync_len,
@@ -476,19 +478,6 @@
return kErrorHardware;
}
break;
- case kDeviceHDMI:
- {
- hw_context->ResetMDPCommit();
- mdp_layer_commit_v1 &mdp_commit = hw_context->mdp_commit.commit_v1;
- mdp_commit.input_layer_cnt = 0;
- mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
- if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_context->mdp_commit) == -1) {
- IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, hw_context->type);
- return kErrorHardware;
- }
- }
- break;
- case kDeviceVirtual:
default:
break;
}
@@ -634,6 +623,22 @@
return kErrorNone;
}
+DisplayError HWFrameBuffer::Flush(Handle device) {
+ HWContext *hw_context = reinterpret_cast<HWContext *>(device);
+
+ hw_context->ResetMDPCommit();
+ mdp_layer_commit_v1 &mdp_commit = hw_context->mdp_commit.commit_v1;
+ mdp_commit.input_layer_cnt = 0;
+ mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
+
+ if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_context->mdp_commit) == -1) {
+ IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, hw_context->type);
+ return kErrorHardware;
+ }
+
+ return kErrorNone;
+}
+
DisplayError HWFrameBuffer::SetFormat(const LayerBufferFormat &source, uint32_t *target) {
switch (source) {
case kFormatARGB8888: *target = MDP_ARGB_8888; break;
@@ -775,16 +780,16 @@
// TODO(user): For now, assume primary to be cmd/video/lvds/edp mode panel only
// Need more concrete info from driver
if ((strncmp(line, "mipi dsi cmd panel", strlen("mipi dsi cmd panel")) == 0)) {
- pri_panel_info_.type = kCommandModePanel;
+ primary_panel_info_.type = kCommandModePanel;
fb_node_index_[kDevicePrimary] = i;
} else if ((strncmp(line, "mipi dsi video panel", strlen("mipi dsi video panel")) == 0)) {
- pri_panel_info_.type = kVideoModePanel;
+ primary_panel_info_.type = kVideoModePanel;
fb_node_index_[kDevicePrimary] = i;
} else if ((strncmp(line, "lvds panel", strlen("lvds panel")) == 0)) {
- pri_panel_info_.type = kLVDSPanel;
+ primary_panel_info_.type = kLVDSPanel;
fb_node_index_[kDevicePrimary] = i;
} else if ((strncmp(line, "edp panel", strlen("edp panel")) == 0)) {
- pri_panel_info_.type = kEDPPanel;
+ primary_panel_info_.type = kEDPPanel;
fb_node_index_[kDevicePrimary] = i;
} else if ((strncmp(line, "dtv panel", strlen("dtv panel")) == 0)) {
fb_node_index_[kDeviceHDMI] = i;
@@ -816,27 +821,27 @@
char *tokens[max_count] = { NULL };
if (!ParseLine(line, tokens, max_count, &token_count)) {
if (!strncmp(tokens[0], "pu_en", strlen("pu_en"))) {
- pri_panel_info_.partial_update = atoi(tokens[1]);
+ primary_panel_info_.partial_update = atoi(tokens[1]);
} else if (!strncmp(tokens[0], "xstart", strlen("xstart"))) {
- pri_panel_info_.left_align = atoi(tokens[1]);
+ primary_panel_info_.left_align = atoi(tokens[1]);
} else if (!strncmp(tokens[0], "walign", strlen("walign"))) {
- pri_panel_info_.width_align = atoi(tokens[1]);
+ primary_panel_info_.width_align = atoi(tokens[1]);
} else if (!strncmp(tokens[0], "ystart", strlen("ystart"))) {
- pri_panel_info_.top_align = atoi(tokens[1]);
+ primary_panel_info_.top_align = atoi(tokens[1]);
} else if (!strncmp(tokens[0], "halign", strlen("halign"))) {
- pri_panel_info_.height_align = atoi(tokens[1]);
+ primary_panel_info_.height_align = atoi(tokens[1]);
} else if (!strncmp(tokens[0], "min_w", strlen("min_w"))) {
- pri_panel_info_.min_roi_width = atoi(tokens[1]);
+ primary_panel_info_.min_roi_width = atoi(tokens[1]);
} else if (!strncmp(tokens[0], "min_h", strlen("min_h"))) {
- pri_panel_info_.min_roi_height = atoi(tokens[1]);
+ primary_panel_info_.min_roi_height = atoi(tokens[1]);
} else if (!strncmp(tokens[0], "roi_merge", strlen("roi_merge"))) {
- pri_panel_info_.needs_roi_merge = atoi(tokens[1]);
+ primary_panel_info_.needs_roi_merge = atoi(tokens[1]);
} else if (!strncmp(tokens[0], "dynamic_fps_en", strlen("dyn_fps_en"))) {
- pri_panel_info_.dynamic_fps = atoi(tokens[1]);
+ primary_panel_info_.dynamic_fps = atoi(tokens[1]);
} else if (!strncmp(tokens[0], "min_fps", strlen("min_fps"))) {
- pri_panel_info_.min_fps = atoi(tokens[1]);
+ primary_panel_info_.min_fps = atoi(tokens[1]);
} else if (!strncmp(tokens[0], "max_fps", strlen("max_fps"))) {
- pri_panel_info_.max_fps= atoi(tokens[1]);
+ primary_panel_info_.max_fps= atoi(tokens[1]);
}
}
}
@@ -1070,3 +1075,4 @@
}
} // namespace sde
+
diff --git a/displayengine/libs/core/hw_framebuffer.h b/displayengine/libs/core/hw_framebuffer.h
index 2fe5078..d9c3a47 100644
--- a/displayengine/libs/core/hw_framebuffer.h
+++ b/displayengine/libs/core/hw_framebuffer.h
@@ -58,6 +58,7 @@
virtual DisplayError Standby(Handle device);
virtual DisplayError Validate(Handle device, HWLayers *hw_layers);
virtual DisplayError Commit(Handle device, HWLayers *hw_layers);
+ virtual DisplayError Flush(Handle device);
private:
struct HWContext {
@@ -141,7 +142,6 @@
bool EnableHotPlugDetection(int enable);
int GetHDMIModeCount();
bool MapHDMIDisplayTiming(const msm_hdmi_mode_timing_info *mode, fb_var_screeninfo *info);
- void ResetHDMIModes();
// Pointers to system calls which are either mapped to actual system call or virtual driver.
int (*ioctl_)(int, int, ...);
@@ -166,7 +166,7 @@
HWResourceInfo hw_resource_;
int fb_node_index_[kDeviceMax];
const char* fb_path_;
- PanelInfo pri_panel_info_;
+ PanelInfo primary_panel_info_;
bool hotplug_enabled_;
uint32_t hdmi_mode_count_;
uint32_t hdmi_modes_[256];
diff --git a/displayengine/libs/core/hw_interface.h b/displayengine/libs/core/hw_interface.h
index f4f33f9..1b3be67 100644
--- a/displayengine/libs/core/hw_interface.h
+++ b/displayengine/libs/core/hw_interface.h
@@ -168,6 +168,7 @@
virtual DisplayError Standby(Handle device) = 0;
virtual DisplayError Validate(Handle device, HWLayers *hw_layers) = 0;
virtual DisplayError Commit(Handle device, HWLayers *hw_layers) = 0;
+ virtual DisplayError Flush(Handle device) = 0;
protected:
virtual ~HWInterface() { }
diff --git a/displayengine/libs/hwc/hwc_display.cpp b/displayengine/libs/hwc/hwc_display.cpp
index 771c07f..7590be5 100644
--- a/displayengine/libs/hwc/hwc_display.cpp
+++ b/displayengine/libs/hwc/hwc_display.cpp
@@ -35,7 +35,8 @@
HWCDisplay::HWCDisplay(CoreInterface *core_intf, hwc_procs_t const **hwc_procs, DisplayType type,
int id)
- : core_intf_(core_intf), hwc_procs_(hwc_procs), type_(type), id_(id), display_intf_(NULL) {
+ : core_intf_(core_intf), hwc_procs_(hwc_procs), type_(type), id_(id), display_intf_(NULL),
+ flush_(false) {
}
int HWCDisplay::Init() {
@@ -282,6 +283,7 @@
size_t num_hw_layers = content_list->numHwLayers;
if (num_hw_layers <= 1) {
+ flush_ = true;
return 0;
}
@@ -336,9 +338,14 @@
layer_stack_.flags.geometry_changed = ((content_list->flags & HWC_GEOMETRY_CHANGED) > 0);
DisplayError error = display_intf_->Prepare(&layer_stack_);
- if (UNLIKELY(error != kErrorNone)) {
+ if (error != kErrorNone) {
DLOGE("Prepare failed. Error = %d", error);
- return -EINVAL;
+
+ // To prevent surfaceflinger infinite wait, flush the previous frame during Commit() so that
+ // previous buffer and fences are released, and override the error.
+ flush_ = true;
+
+ return 0;
}
bool needs_fb_refresh = NeedsFrameBufferRefresh(content_list);
@@ -372,38 +379,39 @@
int status = 0;
size_t num_hw_layers = content_list->numHwLayers;
- if (num_hw_layers <= 1) {
- if (!num_hw_layers) {
- return 0;
+
+ if (!flush_) {
+ for (size_t i = 0; i < num_hw_layers; i++) {
+ hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
+ const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer.handle);
+ LayerBuffer *layer_buffer = layer_stack_.layers[i].input_buffer;
+
+ if (pvt_handle) {
+ layer_buffer->planes[0].fd = pvt_handle->fd;
+ layer_buffer->planes[0].offset = pvt_handle->offset;
+ layer_buffer->planes[0].stride = pvt_handle->width;
+ }
+
+ layer_buffer->acquire_fence_fd = hwc_layer.acquireFenceFd;
}
- // TODO(user): handle if only 1 layer(fb target) is received.
- int &acquireFenceFd = content_list->hwLayers[0].acquireFenceFd;
- if (acquireFenceFd >= 0) {
- close(acquireFenceFd);
- }
+ DisplayError error = display_intf_->Commit(&layer_stack_);
+ if (error != kErrorNone) {
+ DLOGE("Commit failed. Error = %d", error);
- return 0;
+ // To prevent surfaceflinger infinite wait, flush the previous frame during Commit() so that
+ // previous buffer and fences are released, and override the error.
+ flush_ = true;
+ }
}
- for (size_t i = 0; i < num_hw_layers; i++) {
- hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
- const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer.handle);
- LayerBuffer *layer_buffer = layer_stack_.layers[i].input_buffer;
-
- if (pvt_handle) {
- layer_buffer->planes[0].fd = pvt_handle->fd;
- layer_buffer->planes[0].offset = pvt_handle->offset;
- layer_buffer->planes[0].stride = pvt_handle->width;
+ if (flush_) {
+ DisplayError error = display_intf_->Flush();
+ if (error != kErrorNone) {
+ DLOGE("Flush failed. Error = %d", error);
}
- layer_buffer->acquire_fence_fd = hwc_layer.acquireFenceFd;
- }
-
- DisplayError error = display_intf_->Commit(&layer_stack_);
- if (UNLIKELY(error != kErrorNone)) {
- DLOGE("Commit failed. Error = %d", error);
- status = -EINVAL;
+ flush_ = false;
}
for (size_t i = 0; i < num_hw_layers; i++) {
diff --git a/displayengine/libs/hwc/hwc_display.h b/displayengine/libs/hwc/hwc_display.h
index 0ba9ca7..b5e61f3 100644
--- a/displayengine/libs/hwc/hwc_display.h
+++ b/displayengine/libs/hwc/hwc_display.h
@@ -97,6 +97,7 @@
LayerStackMemory layer_stack_memory_;
LayerStack layer_stack_;
LayerStackCache layer_stack_cache_;
+ bool flush_;
};
} // namespace sde