SF: Move/Refactor prepareFrame to CompositionEngine
This refactors both the SurfaceFlinger::prepareFrame() and
HWComposer::prepare() logic, moving things to to
compositionEngine::Output and compositionEngine::Display.
Along the way, the composition related state is moved out of HWComposer
up to compositionengine::OutputCompositionState.
As there were some subtleties, tests are also added to cover the
refactored logic.
Test: atest libsurfaceflinger_unittest libcompositionengine_test
Bug: 121291683
Change-Id: I2713e9e52751ca0523f6348ffdb51ead8bca5235
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 1099041..d480f7c 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -20,6 +20,8 @@
#define LOG_TAG "HWComposer"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+#include "HWComposer.h"
+
#include <compositionengine/Output.h>
#include <compositionengine/OutputLayer.h>
#include <compositionengine/impl/OutputLayerCompositionState.h>
@@ -29,12 +31,10 @@
#include <utils/Errors.h>
#include <utils/Trace.h>
-#include "HWComposer.h"
-#include "HWC2.h"
-#include "ComposerHal.h"
-
-#include "../Layer.h" // needed only for debugging
+#include "../Layer.h" // needed only for debugging
#include "../SurfaceFlinger.h"
+#include "ComposerHal.h"
+#include "HWC2.h"
#define LOG_HWC_DISPLAY_ERROR(hwcDisplayId, msg) \
ALOGE("%s failed for HWC display %" PRIu64 ": %s", __FUNCTION__, hwcDisplayId, msg)
@@ -113,31 +113,6 @@
return mDisplayData.at(*displayId).hwcDisplay->getCapabilities().count(capability) > 0;
}
-void HWComposer::validateChange(HWC2::Composition from, HWC2::Composition to) {
- bool valid = true;
- switch (from) {
- case HWC2::Composition::Client:
- valid = false;
- break;
- case HWC2::Composition::Device:
- case HWC2::Composition::SolidColor:
- valid = (to == HWC2::Composition::Client);
- break;
- case HWC2::Composition::Cursor:
- case HWC2::Composition::Sideband:
- valid = (to == HWC2::Composition::Client ||
- to == HWC2::Composition::Device);
- break;
- default:
- break;
- }
-
- if (!valid) {
- ALOGE("Invalid layer type change: %s --> %s", to_string(from).c_str(),
- to_string(to).c_str());
- }
-}
-
std::optional<DisplayIdentificationInfo> HWComposer::onHotplug(hwc2_display_t hwcDisplayId,
HWC2::Connection connection) {
std::optional<DisplayIdentificationInfo> info;
@@ -399,7 +374,9 @@
return NO_ERROR;
}
-status_t HWComposer::prepare(DisplayId displayId, const compositionengine::Output& output) {
+status_t HWComposer::getDeviceCompositionChanges(
+ DisplayId displayId, bool frameUsesClientComposition,
+ std::optional<android::HWComposer::DeviceRequestedChanges>* outChanges) {
ATRACE_CALL();
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
@@ -419,12 +396,8 @@
// composition. When there is client composition, since we haven't
// rendered to the client target yet, we should not attempt to skip
// validate.
- //
- // displayData.hasClientComposition hasn't been updated for this frame.
- // The check below is incorrect. We actually rely on HWC here to fall
- // back to validate when there is any client layer.
displayData.validateWasSkipped = false;
- if (!displayData.hasClientComposition) {
+ if (!frameUsesClientComposition) {
sp<Fence> outPresentFence;
uint32_t state = UINT32_MAX;
error = hwcDisplay->presentOrValidate(&numTypes, &numRequests, &outPresentFence , &state);
@@ -449,58 +422,19 @@
RETURN_IF_HWC_ERROR_FOR("validate", error, displayId, BAD_INDEX);
}
- std::unordered_map<HWC2::Layer*, HWC2::Composition> changedTypes;
+ android::HWComposer::DeviceRequestedChanges::ChangedTypes changedTypes;
changedTypes.reserve(numTypes);
error = hwcDisplay->getChangedCompositionTypes(&changedTypes);
RETURN_IF_HWC_ERROR_FOR("getChangedCompositionTypes", error, displayId, BAD_INDEX);
- displayData.displayRequests = static_cast<HWC2::DisplayRequest>(0);
- std::unordered_map<HWC2::Layer*, HWC2::LayerRequest> layerRequests;
+ auto displayRequests = static_cast<HWC2::DisplayRequest>(0);
+ android::HWComposer::DeviceRequestedChanges::LayerRequests layerRequests;
layerRequests.reserve(numRequests);
- error = hwcDisplay->getRequests(&displayData.displayRequests,
- &layerRequests);
+ error = hwcDisplay->getRequests(&displayRequests, &layerRequests);
RETURN_IF_HWC_ERROR_FOR("getRequests", error, displayId, BAD_INDEX);
- displayData.hasClientComposition = false;
- displayData.hasDeviceComposition = false;
- for (auto& outputLayer : output.getOutputLayersOrderedByZ()) {
- auto& state = outputLayer->editState();
- LOG_FATAL_IF(!state.hwc.);
- auto hwcLayer = (*state.hwc).hwcLayer;
-
- if (auto it = changedTypes.find(hwcLayer.get()); it != changedTypes.end()) {
- auto newCompositionType = it->second;
- validateChange(static_cast<HWC2::Composition>((*state.hwc).hwcCompositionType),
- newCompositionType);
- (*state.hwc).hwcCompositionType =
- static_cast<Hwc2::IComposerClient::Composition>(newCompositionType);
- }
-
- switch ((*state.hwc).hwcCompositionType) {
- case Hwc2::IComposerClient::Composition::CLIENT:
- displayData.hasClientComposition = true;
- break;
- case Hwc2::IComposerClient::Composition::DEVICE:
- case Hwc2::IComposerClient::Composition::SOLID_COLOR:
- case Hwc2::IComposerClient::Composition::CURSOR:
- case Hwc2::IComposerClient::Composition::SIDEBAND:
- displayData.hasDeviceComposition = true;
- break;
- default:
- break;
- }
-
- state.clearClientTarget = false;
- if (auto it = layerRequests.find(hwcLayer.get()); it != layerRequests.end()) {
- auto request = it->second;
- if (request == HWC2::LayerRequest::ClearClientTarget) {
- state.clearClientTarget = true;
- } else {
- LOG_DISPLAY_ERROR(displayId,
- ("Unknown layer request " + to_string(request)).c_str());
- }
- }
- }
+ outChanges->emplace(DeviceRequestedChanges{std::move(changedTypes), std::move(displayRequests),
+ std::move(layerRequests)});
error = hwcDisplay->acceptChanges();
RETURN_IF_HWC_ERROR_FOR("acceptChanges", error, displayId, BAD_INDEX);
@@ -508,40 +442,6 @@
return NO_ERROR;
}
-bool HWComposer::hasDeviceComposition(const std::optional<DisplayId>& displayId) const {
- if (!displayId) {
- // Displays without a corresponding HWC display are never composed by
- // the device
- return false;
- }
-
- RETURN_IF_INVALID_DISPLAY(*displayId, false);
- return mDisplayData.at(*displayId).hasDeviceComposition;
-}
-
-bool HWComposer::hasFlipClientTargetRequest(const std::optional<DisplayId>& displayId) const {
- if (!displayId) {
- // Displays without a corresponding HWC display are never composed by
- // the device
- return false;
- }
-
- RETURN_IF_INVALID_DISPLAY(*displayId, false);
- return ((static_cast<uint32_t>(mDisplayData.at(*displayId).displayRequests) &
- static_cast<uint32_t>(HWC2::DisplayRequest::FlipClientTarget)) != 0);
-}
-
-bool HWComposer::hasClientComposition(const std::optional<DisplayId>& displayId) const {
- if (!displayId) {
- // Displays without a corresponding HWC display are always composed by
- // the client
- return true;
- }
-
- RETURN_IF_INVALID_DISPLAY(*displayId, true);
- return mDisplayData.at(*displayId).hasClientComposition;
-}
-
sp<Fence> HWComposer::getPresentFence(DisplayId displayId) const {
RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE);
return mDisplayData.at(displayId).lastPresentFence;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index de863b8..e87c5c3 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -71,8 +71,26 @@
// Destroy a previously created layer
virtual void destroyLayer(DisplayId displayId, HWC2::Layer* layer) = 0;
- // Asks the HAL what it can do
- virtual status_t prepare(DisplayId displayId, const compositionengine::Output&) = 0;
+ struct DeviceRequestedChanges {
+ using ChangedTypes = std::unordered_map<HWC2::Layer*, HWC2::Composition>;
+ using DisplayRequests = HWC2::DisplayRequest;
+ using LayerRequests = std::unordered_map<HWC2::Layer*, HWC2::LayerRequest>;
+
+ ChangedTypes changedTypes;
+ DisplayRequests displayRequests;
+ LayerRequests layerRequests;
+ };
+
+ // Gets any required composition change requests from the HWC device.
+ //
+ // Note that frameUsesClientComposition must be set correctly based on
+ // whether the current frame appears to use client composition. If it is
+ // false some internal optimizations are allowed to present the display
+ // with fewer handshakes, but this does not work if client composition is
+ // expected.
+ virtual status_t getDeviceCompositionChanges(
+ DisplayId, bool frameUsesClientComposition,
+ std::optional<DeviceRequestedChanges>* outChanges) = 0;
virtual status_t setClientTarget(DisplayId displayId, uint32_t slot,
const sp<Fence>& acquireFence, const sp<GraphicBuffer>& target,
@@ -93,15 +111,6 @@
// reset state when an external, non-virtual display is disconnected
virtual void disconnectDisplay(DisplayId displayId) = 0;
- // does this display have layers handled by HWC
- virtual bool hasDeviceComposition(const std::optional<DisplayId>& displayId) const = 0;
-
- // does this display have pending request to flip client target
- virtual bool hasFlipClientTargetRequest(const std::optional<DisplayId>& displayId) const = 0;
-
- // does this display have layers handled by GLES
- virtual bool hasClientComposition(const std::optional<DisplayId>& displayId) const = 0;
-
// get the present fence received from the last call to present.
virtual sp<Fence> getPresentFence(DisplayId displayId) const = 0;
@@ -210,8 +219,9 @@
// Destroy a previously created layer
void destroyLayer(DisplayId displayId, HWC2::Layer* layer) override;
- // Asks the HAL what it can do
- status_t prepare(DisplayId displayId, const compositionengine::Output&) override;
+ status_t getDeviceCompositionChanges(
+ DisplayId, bool frameUsesClientComposition,
+ std::optional<DeviceRequestedChanges>* outChanges) override;
status_t setClientTarget(DisplayId displayId, uint32_t slot, const sp<Fence>& acquireFence,
const sp<GraphicBuffer>& target, ui::Dataspace dataspace) override;
@@ -231,15 +241,6 @@
// reset state when an external, non-virtual display is disconnected
void disconnectDisplay(DisplayId displayId) override;
- // does this display have layers handled by HWC
- bool hasDeviceComposition(const std::optional<DisplayId>& displayId) const override;
-
- // does this display have pending request to flip client target
- bool hasFlipClientTargetRequest(const std::optional<DisplayId>& displayId) const override;
-
- // does this display have layers handled by GLES
- bool hasClientComposition(const std::optional<DisplayId>& displayId) const override;
-
// get the present fence received from the last call to present.
sp<Fence> getPresentFence(DisplayId displayId) const override;
@@ -326,14 +327,10 @@
std::optional<DisplayIdentificationInfo> onHotplugConnect(hwc2_display_t hwcDisplayId);
- static void validateChange(HWC2::Composition from, HWC2::Composition to);
-
struct DisplayData {
bool isVirtual = false;
- bool hasClientComposition = false;
- bool hasDeviceComposition = false;
+
HWC2::Display* hwcDisplay = nullptr;
- HWC2::DisplayRequest displayRequests;
sp<Fence> lastPresentFence = Fence::NO_FENCE; // signals when the last set op retires
std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
buffer_handle_t outbufHandle = nullptr;