summaryrefslogtreecommitdiff
path: root/sdm/libs/hwc2
diff options
context:
space:
mode:
authorRamkumar Radhakrishnan <ramkumar@codeaurora.org>2018-01-17 11:39:33 -0800
committerRamkumar Radhakrishnan <ramkumar@codeaurora.org>2018-02-06 14:29:46 -0800
commit00698decef667ee7700b663091e1f6c4fbefbf71 (patch)
tree7a6469cb987745447c67872d910d0c60e8f561f8 /sdm/libs/hwc2
parentf5464da30116baa43cc1e4e9e5a6af980dca11ac (diff)
downloaddisplay-00698decef667ee7700b663091e1f6c4fbefbf71.tar.gz
sdm: Merge release fence after set power mode
On SetPowerMode() with retain pipes, DRM driver triggers the kick off that enables MDP to read the previously queued buffer, Since the fence created during SetPowerMode() is not merged with the previously queued buffer, it may result in tearing. Hence get the release fence from driver on SetPowerMode and propagate it to hwcomposer to merge it with the previous release fence of all layer buffers to avoid tearing. Change-Id: I81c078a1b05dd3fb34f10b9b70e25cfbcfabd117 CRs-Fixed: 2184515
Diffstat (limited to 'sdm/libs/hwc2')
-rw-r--r--sdm/libs/hwc2/display_null.cpp4
-rw-r--r--sdm/libs/hwc2/display_null.h4
-rw-r--r--sdm/libs/hwc2/hwc_display.cpp27
-rw-r--r--sdm/libs/hwc2/hwc_display_external.cpp15
-rw-r--r--sdm/libs/hwc2/hwc_layers.cpp26
-rw-r--r--sdm/libs/hwc2/hwc_layers.h9
6 files changed, 61 insertions, 24 deletions
diff --git a/sdm/libs/hwc2/display_null.cpp b/sdm/libs/hwc2/display_null.cpp
index 16f4da66..7e52911c 100644
--- a/sdm/libs/hwc2/display_null.cpp
+++ b/sdm/libs/hwc2/display_null.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -50,7 +50,7 @@ DisplayError DisplayNull::GetDisplayState(DisplayState *state) {
return kErrorNone;
}
-DisplayError DisplayNull::SetDisplayState(DisplayState state) {
+DisplayError DisplayNull::SetDisplayState(DisplayState state, int *release_fence) {
state_ = state;
return kErrorNone;
}
diff --git a/sdm/libs/hwc2/display_null.h b/sdm/libs/hwc2/display_null.h
index f6c0ddaa..bd49a162 100644
--- a/sdm/libs/hwc2/display_null.h
+++ b/sdm/libs/hwc2/display_null.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -44,7 +44,7 @@ class DisplayNull : public DisplayInterface {
virtual ~DisplayNull() { }
virtual DisplayError Commit(LayerStack *layer_stack);
virtual DisplayError GetDisplayState(DisplayState *state);
- virtual DisplayError SetDisplayState(DisplayState state);
+ virtual DisplayError SetDisplayState(DisplayState state, int *release_fence);
virtual DisplayError SetFrameBufferConfig(const DisplayConfigVariableInfo &variable_info);
virtual DisplayError GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info);
virtual bool IsUnderscanSupported() { return true; }
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index 870b8b64..02801944 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright 2015 The Android Open Source Project
@@ -748,9 +748,10 @@ HWC2::Error HWCDisplay::SetPowerMode(HWC2::PowerMode mode) {
default:
return HWC2::Error::BadParameter;
}
+ int release_fence = -1;
ATRACE_INT("SetPowerMode ", state);
- DisplayError error = display_intf_->SetDisplayState(state);
+ DisplayError error = display_intf_->SetDisplayState(state, &release_fence);
validated_ = false;
if (error == kErrorNone) {
@@ -764,6 +765,20 @@ HWC2::Error HWCDisplay::SetPowerMode(HWC2::PowerMode mode) {
return HWC2::Error::BadParameter;
}
+ if (release_fence >= 0) {
+ for (auto hwc_layer : layer_set_) {
+ auto fence = hwc_layer->PopBackReleaseFence();
+ auto merged_fence = -1;
+ if (fence >= 0) {
+ merged_fence = sync_merge("sync_merge", release_fence, fence);
+ ::close(fence);
+ } else {
+ merged_fence = ::dup(release_fence);
+ }
+ hwc_layer->PushBackReleaseFence(merged_fence);
+ }
+ ::close(release_fence);
+ }
return HWC2::Error::None;
}
@@ -1135,7 +1150,7 @@ HWC2::Error HWCDisplay::GetReleaseFences(uint32_t *out_num_elements, hwc2_layer_
for (uint32_t i = 0; i < *out_num_elements; i++, it++) {
auto hwc_layer = *it;
out_layers[i] = hwc_layer->GetId();
- out_fences[i] = hwc_layer->PopReleaseFence();
+ out_fences[i] = hwc_layer->PopFrontReleaseFence();
}
} else {
*out_num_elements = UINT32(layer_set_.size());
@@ -1306,15 +1321,15 @@ HWC2::Error HWCDisplay::PostCommitLayerStack(int32_t *out_retire_fence) {
if (swap_interval_zero_ || layer->flags.single_buffer) {
close(layer_buffer->release_fence_fd);
} else if (layer->composition != kCompositionGPU) {
- hwc_layer->PushReleaseFence(layer_buffer->release_fence_fd);
+ hwc_layer->PushBackReleaseFence(layer_buffer->release_fence_fd);
} else {
- hwc_layer->PushReleaseFence(-1);
+ hwc_layer->PushBackReleaseFence(-1);
}
} else {
// In case of flush, we don't return an error to f/w, so it will get a release fence out of
// the hwc_layer's release fence queue. We should push a -1 to preserve release fence
// circulation semantics.
- hwc_layer->PushReleaseFence(-1);
+ hwc_layer->PushBackReleaseFence(-1);
}
layer_buffer->release_fence_fd = -1;
diff --git a/sdm/libs/hwc2/hwc_display_external.cpp b/sdm/libs/hwc2/hwc_display_external.cpp
index 2bc2d189..675484b8 100644
--- a/sdm/libs/hwc2/hwc_display_external.cpp
+++ b/sdm/libs/hwc2/hwc_display_external.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -230,9 +230,12 @@ int HWCDisplayExternal::SetState(bool connected) {
DLOGW("Set frame buffer config failed. Error = %d", error);
return -1;
}
-
+ int release_fence = -1;
display_null_.GetDisplayState(&state);
- display_intf_->SetDisplayState(state);
+ display_intf_->SetDisplayState(state, &release_fence);
+ if (release_fence >= 0) {
+ ::close(release_fence);
+ }
validated_ = false;
SetVsyncEnabled(HWC2::Vsync::Enable);
@@ -244,10 +247,14 @@ int HWCDisplayExternal::SetState(bool connected) {
}
} else {
if (!display_null_.IsActive()) {
+ int release_fence = -1;
// Preserve required attributes of HDMI display that surfaceflinger sees.
// Restore HDMI attributes when display is reconnected.
display_intf_->GetDisplayState(&state);
- display_null_.SetDisplayState(state);
+ display_null_.SetDisplayState(state, &release_fence);
+ if (release_fence >= 0) {
+ ::close(release_fence);
+ }
error = display_intf_->GetFrameBufferConfig(&fb_config);
if (error != kErrorNone) {
diff --git a/sdm/libs/hwc2/hwc_layers.cpp b/sdm/libs/hwc2/hwc_layers.cpp
index d611352e..1193ec46 100644
--- a/sdm/libs/hwc2/hwc_layers.cpp
+++ b/sdm/libs/hwc2/hwc_layers.cpp
@@ -174,14 +174,14 @@ HWCLayer::HWCLayer(hwc2_display_t display_id, HWCBufferAllocator *buf_allocator)
layer_ = new Layer();
// Fences are deferred, so the first time this layer is presented, return -1
// TODO(user): Verify that fences are properly obtained on suspend/resume
- release_fences_.push(-1);
+ release_fences_.push_back(-1);
}
HWCLayer::~HWCLayer() {
// Close any fences left for this layer
while (!release_fences_.empty()) {
::close(release_fences_.front());
- release_fences_.pop();
+ release_fences_.pop_front();
}
if (layer_) {
if (layer_->input_buffer.acquire_fence_fd >= 0) {
@@ -892,14 +892,28 @@ void HWCLayer::SetComposition(const LayerComposition &sdm_composition) {
return;
}
-void HWCLayer::PushReleaseFence(int32_t fence) {
- release_fences_.push(fence);
+
+void HWCLayer::PushBackReleaseFence(int32_t fence) {
+ release_fences_.push_back(fence);
}
-int32_t HWCLayer::PopReleaseFence(void) {
+
+int32_t HWCLayer::PopBackReleaseFence() {
if (release_fences_.empty())
return -1;
+
+ auto fence = release_fences_.back();
+ release_fences_.pop_back();
+
+ return fence;
+}
+
+int32_t HWCLayer::PopFrontReleaseFence() {
+ if (release_fences_.empty())
+ return -1;
+
auto fence = release_fences_.front();
- release_fences_.pop();
+ release_fences_.pop_front();
+
return fence;
}
diff --git a/sdm/libs/hwc2/hwc_layers.h b/sdm/libs/hwc2/hwc_layers.h
index ed03c50c..a7d7f011 100644
--- a/sdm/libs/hwc2/hwc_layers.h
+++ b/sdm/libs/hwc2/hwc_layers.h
@@ -32,7 +32,7 @@
#undef HWC2_INCLUDE_STRINGIFICATION
#undef HWC2_USE_CPP11
#include <map>
-#include <queue>
+#include <deque>
#include <set>
#include "core/buffer_allocator.h"
#include "hwc_buffer_allocator.h"
@@ -88,8 +88,9 @@ class HWCLayer {
int32_t GetLayerDataspace() { return dataspace_; }
uint32_t GetGeometryChanges() { return geometry_changes_; }
void ResetGeometryChanges() { geometry_changes_ = GeometryChanges::kNone; }
- void PushReleaseFence(int32_t fence);
- int32_t PopReleaseFence(void);
+ void PushBackReleaseFence(int32_t fence);
+ int32_t PopBackReleaseFence(void);
+ int32_t PopFrontReleaseFence(void);
bool ValidateAndSetCSC();
bool SupportLocalConversion(ColorPrimaries working_primaries);
void ResetValidation() { needs_validate_ = false; }
@@ -104,7 +105,7 @@ class HWCLayer {
const hwc2_layer_t id_;
const hwc2_display_t display_id_;
static std::atomic<hwc2_layer_t> next_id_;
- std::queue<int32_t> release_fences_;
+ std::deque<int32_t> release_fences_;
HWCBufferAllocator *buffer_allocator_ = NULL;
int32_t dataspace_ = HAL_DATASPACE_UNKNOWN;
LayerTransform layer_transform_ = {};