Skip Validate
b/37474580
b/62806392
Test: marlin, ryu
Change-Id: I09e0c52cb7c914dcd883dc771d97a365c89f7037
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index 439adc4..9d16044 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -546,6 +546,29 @@
return Error::NONE;
}
+Error Composer::presentOrValidateDisplay(Display display, uint32_t* outNumTypes,
+ uint32_t* outNumRequests, int* outPresentFence, uint32_t* state) {
+ mWriter.selectDisplay(display);
+ mWriter.presentOrvalidateDisplay();
+
+ Error error = execute();
+ if (error != Error::NONE) {
+ return error;
+ }
+
+ mReader.takePresentOrValidateStage(display, state);
+
+ if (*state == 1) { // Present succeeded
+ mReader.takePresentFence(display, outPresentFence);
+ }
+
+ if (*state == 0) { // Validate succeeded.
+ mReader.hasChanges(display, outNumTypes, outNumRequests);
+ }
+
+ return Error::NONE;
+}
+
Error Composer::setCursorPosition(Display display, Layer layer,
int32_t x, int32_t y)
{
@@ -763,7 +786,8 @@
auto command = mWriter.getCommand(cmdErr.location);
if (command == IComposerClient::Command::VALIDATE_DISPLAY ||
- command == IComposerClient::Command::PRESENT_DISPLAY) {
+ command == IComposerClient::Command::PRESENT_DISPLAY ||
+ command == IComposerClient::Command::PRESENT_OR_VALIDATE_DISPLAY) {
error = cmdErr.error;
} else {
ALOGW("command 0x%x generated error %d",
@@ -814,6 +838,9 @@
case IComposerClient::Command::SET_RELEASE_FENCES:
parsed = parseSetReleaseFences(length);
break;
+ case IComposerClient::Command ::SET_PRESENT_OR_VALIDATE_DISPLAY_RESULT:
+ parsed = parseSetPresentOrValidateDisplayResult(length);
+ break;
default:
parsed = false;
break;
@@ -942,6 +969,15 @@
return true;
}
+bool CommandReader::parseSetPresentOrValidateDisplayResult(uint16_t length)
+{
+ if (length != CommandWriterBase::kPresentOrValidateDisplayResultLength || !mCurrentReturnData) {
+ return false;
+ }
+ mCurrentReturnData->presentOrValidateState = read();
+ return true;
+}
+
void CommandReader::resetData()
{
mErrors.clear();
@@ -1051,6 +1087,16 @@
data.presentFence = -1;
}
+void CommandReader::takePresentOrValidateStage(Display display, uint32_t* state) {
+ auto found = mReturnData.find(display);
+ if (found == mReturnData.end()) {
+ *state= -1;
+ return;
+ }
+ ReturnData& data = found->second;
+ *state = data.presentOrValidateState;
+}
+
} // namespace Hwc2
} // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 68d6e6f..96dd833 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -93,6 +93,9 @@
// Get and clear saved present fence.
void takePresentFence(Display display, int* outPresentFence);
+ // Get what stage succeeded during PresentOrValidate: Present or Validate
+ void takePresentOrValidateStage(Display display, uint32_t * state);
+
private:
void resetData();
@@ -102,6 +105,7 @@
bool parseSetDisplayRequests(uint16_t length);
bool parseSetPresentFence(uint16_t length);
bool parseSetReleaseFences(uint16_t length);
+ bool parseSetPresentOrValidateDisplayResult(uint16_t length);
struct ReturnData {
uint32_t displayRequests = 0;
@@ -116,6 +120,8 @@
std::vector<Layer> releasedLayers;
std::vector<int> releaseFences;
+
+ uint32_t presentOrValidateState;
};
std::vector<CommandError> mErrors;
@@ -202,6 +208,11 @@
Error validateDisplay(Display display, uint32_t* outNumTypes,
uint32_t* outNumRequests);
+ Error presentOrValidateDisplay(Display display, uint32_t* outNumTypes,
+ uint32_t* outNumRequests,
+ int* outPresentFence,
+ uint32_t* state);
+
Error setCursorPosition(Display display, Layer layer,
int32_t x, int32_t y);
/* see setClientTarget for the purpose of slot */
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 0366630..95689d9 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -695,6 +695,28 @@
return error;
}
+Error Display::presentOrValidate(uint32_t* outNumTypes, uint32_t* outNumRequests,
+ sp<android::Fence>* outPresentFence, uint32_t* state) {
+
+ uint32_t numTypes = 0;
+ uint32_t numRequests = 0;
+ int32_t presentFenceFd = -1;
+ auto intError = mDevice.mComposer->presentOrValidateDisplay(mId, &numTypes, &numRequests, &presentFenceFd, state);
+ auto error = static_cast<Error>(intError);
+ if (error != Error::None && error != Error::HasChanges) {
+ return error;
+ }
+
+ if (*state == 1) {
+ *outPresentFence = new Fence(presentFenceFd);
+ }
+
+ if (*state == 0) {
+ *outNumTypes = numTypes;
+ *outNumRequests = numRequests;
+ }
+ return error;
+}
// For use by Device
int32_t Display::getAttribute(hwc2_config_t configId, Attribute attribute)
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 7f26e56..4d9155c 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -255,6 +255,9 @@
[[clang::warn_unused_result]] Error setVsyncEnabled(Vsync enabled);
[[clang::warn_unused_result]] Error validate(uint32_t* outNumTypes,
uint32_t* outNumRequests);
+ [[clang::warn_unused_result]] Error presentOrValidate(uint32_t* outNumTypes,
+ uint32_t* outNumRequests,
+ android::sp<android::Fence>* outPresentFence, uint32_t* state);
// Other Display methods
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 42be935..913c43f 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -455,7 +455,33 @@
uint32_t numTypes = 0;
uint32_t numRequests = 0;
- auto error = hwcDisplay->validate(&numTypes, &numRequests);
+
+ HWC2::Error error = HWC2::Error::None;
+
+ // First try to skip validate altogether if the HWC supports it.
+ displayData.validateWasSkipped = false;
+ if (hasCapability(HWC2::Capability::SkipValidate)) {
+ sp<android::Fence> outPresentFence;
+ uint32_t state = UINT32_MAX;
+ error = hwcDisplay->presentOrValidate(&numTypes, &numRequests, &outPresentFence , &state);
+ if (error != HWC2::Error::None && error != HWC2::Error::HasChanges) {
+ ALOGV("skipValidate: Failed to Present or Validate");
+ return UNKNOWN_ERROR;
+ }
+ if (state == 1) { //Present Succeeded.
+ std::unordered_map<std::shared_ptr<HWC2::Layer>, sp<Fence>> releaseFences;
+ error = hwcDisplay->getReleaseFences(&releaseFences);
+ displayData.releaseFences = std::move(releaseFences);
+ displayData.lastPresentFence = outPresentFence;
+ displayData.validateWasSkipped = true;
+ displayData.presentError = error;
+ return NO_ERROR;
+ }
+ // Present failed but Validate ran.
+ } else {
+ error = hwcDisplay->validate(&numTypes, &numRequests);
+ }
+ ALOGV("SkipValidate failed, Falling back to SLOW validate/present");
if (error != HWC2::Error::None && error != HWC2::Error::HasChanges) {
ALOGE("prepare: validate failed for display %d: %s (%d)", displayId,
to_string(error).c_str(), static_cast<int32_t>(error));
@@ -592,6 +618,17 @@
auto& displayData = mDisplayData[displayId];
auto& hwcDisplay = displayData.hwcDisplay;
+
+ if (displayData.validateWasSkipped) {
+ auto error = displayData.presentError;
+ if (error != HWC2::Error::None) {
+ ALOGE("skipValidate: failed for display %d: %s (%d)",
+ displayId, to_string(error).c_str(), static_cast<int32_t>(error));
+ return UNKNOWN_ERROR;
+ }
+ return NO_ERROR;
+ }
+
auto error = hwcDisplay->present(&displayData.lastPresentFence);
if (error != HWC2::Error::None) {
ALOGE("presentAndGetReleaseFences: failed for display %d: %s (%d)",
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 3eb968d..7463362 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -202,6 +202,9 @@
// protected by mVsyncLock
HWC2::Vsync vsyncEnabled;
+
+ bool validateWasSkipped;
+ HWC2::Error presentError;
};
std::unique_ptr<HWC2::Device> mHwcDevice;