hwc3: call present again if no changes after validate
In PresentOrValidateDisplay, SF expects HWC to either already call
presentDisplay or just call validateDisplay. If HWC fallback to
validateDisplay and there's no change, we should call
presentDisplay directly to reduce unnecessary binder transaction.
Bug: 295447985
Test: scrolling youtube and check traces
Change-Id: I7195ede2a4915f63114bbedad5e768debfb6d4dd
diff --git a/base/hwc3/ComposerCommandEngine.cpp b/base/hwc3/ComposerCommandEngine.cpp
index 3b06fef..d43ac5f 100644
--- a/base/hwc3/ComposerCommandEngine.cpp
+++ b/base/hwc3/ComposerCommandEngine.cpp
@@ -15,6 +15,9 @@
*/
#include "ComposerCommandEngine.h"
+
+#include <hardware/hwcomposer2.h>
+
#include "Util.h"
/// The command engine interface is not 'pure' aidl. Conversion to aidl
@@ -121,7 +124,7 @@
&displayRequestMask, &requestedLayers, &requestMasks,
&clientTargetProperty);
mResources->setDisplayMustValidateState(display, false);
- if (!err) {
+ if (err == HWC2_ERROR_NONE || err == HWC2_ERROR_HAS_CHANGES) {
mWriter->setChangedCompositionTypes(display, changedLayers, compositionTypes);
mWriter->setDisplayRequests(display, displayRequestMask, requestedLayers, requestMasks);
} else {
@@ -207,17 +210,31 @@
int64_t display, const std::optional<ClockMonotonicTimestamp> expectedPresentTime) {
executeSetExpectedPresentTimeInternal(display, expectedPresentTime);
// First try to Present as is.
- auto err = mResources->mustValidateDisplay(display) ? IComposerClient::EX_NOT_VALIDATED
- : executePresentDisplay(display);
- if (!err) {
+ auto presentErr = mResources->mustValidateDisplay(display) ? IComposerClient::EX_NOT_VALIDATED
+ : executePresentDisplay(display);
+ if (!presentErr) {
mWriter->setPresentOrValidateResult(display, PresentOrValidate::Result::Presented);
return;
}
// Fallback to validate
- err = executeValidateDisplayInternal(display);
- if (!err) {
+ auto validateErr = executeValidateDisplayInternal(display);
+ if (validateErr != HWC2_ERROR_NONE && validateErr != HWC2_ERROR_HAS_CHANGES) return;
+
+ bool hasClientComp = false;
+ bool cannotPresentDirectly = (validateErr == HWC2_ERROR_HAS_CHANGES) ||
+ (mHal->getHasClientComposition(display, hasClientComp) == HWC2_ERROR_NONE &&
+ hasClientComp);
+ if (cannotPresentDirectly) {
mWriter->setPresentOrValidateResult(display, PresentOrValidate::Result::Validated);
+ return;
+ }
+
+ // Try to call present again
+ executeAcceptDisplayChanges(display);
+ presentErr = executePresentDisplay(display);
+ if (!presentErr) {
+ mWriter->setPresentOrValidateResult(display, PresentOrValidate::Result::Presented);
}
}
diff --git a/base/hwc3/impl/HalImpl.cpp b/base/hwc3/impl/HalImpl.cpp
index a711113..e6023f3 100644
--- a/base/hwc3/impl/HalImpl.cpp
+++ b/base/hwc3/impl/HalImpl.cpp
@@ -637,6 +637,15 @@
return mDevice->setClientTarget(halDisplay, target, hwcFence, hwcDataspace);
}
+int32_t HalImpl::getHasClientComposition(int64_t display, bool& outHasClientComp) {
+ ExynosDisplay* halDisplay;
+ RET_IF_ERR(getHalDisplay(display, halDisplay));
+
+ outHasClientComp = halDisplay->hasClientComposition();
+
+ return HWC2_ERROR_NONE;
+}
+
int32_t HalImpl::setColorMode(int64_t display, ColorMode mode, RenderIntent intent) {
ExynosDisplay* halDisplay;
RET_IF_ERR(getHalDisplay(display, halDisplay));
@@ -975,7 +984,7 @@
h2a::translate(hwcProperty, *outClientTargetProperty);
} // else ignore this error
- return HWC2_ERROR_NONE;
+ return err;
}
int HalImpl::setExpectedPresentTime(
diff --git a/base/hwc3/impl/HalImpl.h b/base/hwc3/impl/HalImpl.h
index 23d190a..197d2dc 100644
--- a/base/hwc3/impl/HalImpl.h
+++ b/base/hwc3/impl/HalImpl.h
@@ -98,6 +98,7 @@
int32_t setClientTarget(int64_t display, buffer_handle_t target,
const ndk::ScopedFileDescriptor& fence, common::Dataspace dataspace,
const std::vector<common::Rect>& damage) override;
+ int32_t getHasClientComposition(int64_t display, bool& outHasClientComp) override;
int32_t setColorMode(int64_t display, ColorMode mode, RenderIntent intent) override;
int32_t setColorTransform(int64_t display, const std::vector<float>& matrix) override;
int32_t setContentType(int64_t display, ContentType contentType) override;
diff --git a/base/hwc3/include/IComposerHal.h b/base/hwc3/include/IComposerHal.h
index f79c4a8..8d6aaf1 100644
--- a/base/hwc3/include/IComposerHal.h
+++ b/base/hwc3/include/IComposerHal.h
@@ -169,6 +169,7 @@
const ndk::ScopedFileDescriptor& fence,
common::Dataspace dataspace,
const std::vector<common::Rect>& damage) = 0; // cmd
+ virtual int32_t getHasClientComposition(int64_t display, bool& outHasClientComp) = 0;
virtual int32_t setColorMode(int64_t display, ColorMode mode, RenderIntent intent) = 0;
virtual int32_t setColorTransform(int64_t display, const std::vector<float>& matrix) = 0; // cmd
virtual int32_t setContentType(int64_t display, ContentType contentType) = 0;
diff --git a/base/libhwc2.1/display/ExynosDisplay.cpp b/base/libhwc2.1/display/ExynosDisplay.cpp
index 50a2fd6..4c94504 100644
--- a/base/libhwc2.1/display/ExynosDisplay.cpp
+++ b/base/libhwc2.1/display/ExynosDisplay.cpp
@@ -4209,6 +4209,10 @@
return ret;
}
+bool ExynosDisplay::hasClientComposition() {
+ return mClientCompositionInfo.mHasCompositionLayer;
+}
+
int32_t ExynosDisplay::handleSandwitchedExynosCompositionLayer(
std::vector<int32_t> &highPriLayers, float totalUsedCapa,
bool &invalidFlag, int32_t &changeFlag) {
diff --git a/base/libhwc2.1/display/ExynosDisplay.h b/base/libhwc2.1/display/ExynosDisplay.h
index 8bda068..ace105f 100644
--- a/base/libhwc2.1/display/ExynosDisplay.h
+++ b/base/libhwc2.1/display/ExynosDisplay.h
@@ -563,6 +563,7 @@
int32_t addClientCompositionLayer(uint32_t layerIndex,
uint32_t *isExynosCompositionChanged = NULL);
int32_t removeClientCompositionLayer(uint32_t layerIndex);
+ bool hasClientComposition();
int32_t handleSandwitchedExynosCompositionLayer(
std::vector<int32_t> &highPriLayers, float totalUsedCapa,
bool &invalidFlag, int32_t &changeFlag);