Merge "sde: Add support for flush."

This commit is contained in:
Linux Build Service Account
2015-01-28 10:44:03 -08:00
committed by Gerrit - the friendly Code Review server
10 changed files with 143 additions and 64 deletions

View File

@@ -135,6 +135,8 @@ DisplayError DisplayBase::Prepare(LayerStack *layer_stack) {
}
}
comp_manager_->PostPrepare(display_comp_ctx_, &hw_layers_);
} else {
return kErrorNotSupported;
}
return error;
@@ -149,18 +151,19 @@ DisplayError DisplayBase::Commit(LayerStack *layer_stack) {
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 @@ DisplayError DisplayBase::Commit(LayerStack *layer_stack) {
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_);

View File

@@ -43,6 +43,7 @@ class DisplayBase : public DisplayInterface, HWEventHandler, DumpImpl {
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);

View File

@@ -77,5 +77,29 @@ int DisplayHDMI::GetBestConfig() {
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

View File

@@ -33,6 +33,7 @@ class DisplayHDMI : public DisplayBase {
public:
DisplayHDMI(DisplayEventHandler *event_handler, HWInterface *hw_intf, CompManager *comp_manager);
virtual int GetBestConfig();
virtual DisplayError SetDisplayState(DisplayState state);
};
} // namespace sde

View File

@@ -392,17 +392,19 @@ DisplayError HWFrameBuffer::SetDisplayAttributes(Handle device, uint32_t index)
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 @@ DisplayError HWFrameBuffer::PowerOff(Handle device) {
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;
}
@@ -638,6 +627,22 @@ DisplayError HWFrameBuffer::Commit(Handle device, HWLayers *hw_layers) {
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;
@@ -782,16 +787,16 @@ void HWFrameBuffer::PopulateFBNodeIndex() {
// 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;
@@ -823,27 +828,27 @@ void HWFrameBuffer::PopulatePanelInfo(int fb_index) {
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]);
}
}
}
@@ -1077,3 +1082,4 @@ bool HWFrameBuffer::MapHDMIDisplayTiming(const msm_hdmi_mode_timing_info *mode,
}
} // namespace sde

View File

@@ -58,6 +58,7 @@ class HWFrameBuffer : public HWInterface {
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 @@ class HWFrameBuffer : public HWInterface {
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 @@ class HWFrameBuffer : public HWInterface {
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];

View File

@@ -169,6 +169,7 @@ class HWInterface {
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() { }

View File

@@ -35,7 +35,8 @@ namespace sde {
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 @@ int HWCDisplay::PrepareLayerStack(hwc_display_contents_1_t *content_list) {
size_t num_hw_layers = content_list->numHwLayers;
if (num_hw_layers <= 1) {
flush_ = true;
return 0;
}
@@ -338,9 +340,14 @@ int HWCDisplay::PrepareLayerStack(hwc_display_contents_1_t *content_list) {
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);
@@ -378,38 +385,39 @@ int HWCDisplay::CommitLayerStack(hwc_display_contents_1_t *content_list) {
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++) {

View File

@@ -97,6 +97,7 @@ class HWCDisplay : public DisplayEventHandler {
LayerStackMemory layer_stack_memory_;
LayerStack layer_stack_;
LayerStackCache layer_stack_cache_;
bool flush_;
};
} // namespace sde