Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bf769e4b authored by Alec Mouri's avatar Alec Mouri
Browse files

Add initial support for display readback

We've had readback support for testing purposes for many, many releases
now, but now fullscreen capture is becoming more common, so we want to
hook this up into production.

Readback currently must be negotiated on the main surfaceflinger thread,
so the implementation will schedule a composition request to piggyback
readback parameters on top of (this is zero overhead during steady-state
compositing), pass the readback buffer over to HWC prior to validate(),
then receive the readback fence after present().

This is flag guarded in two ways: an aconfig flag to control the
rollout wholesale, and also a device opt-in. The device opt-in is
necessary since readback on some devices may not be production-ready due
to its historical test-only status.

Also fix a minor issue where we always add an excludedLayerId set of {0}
due to aggregate initialization.

Bug: 384816457
Flag: com.android.graphics.surfaceflinger.flags.readback_screenshot
Test: builds
Test: adb screencap
Change-Id: Ic70d01140748d34880cc6cbe740685153bcf5b27
parent 5f4f8313
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -132,6 +132,7 @@ public:
        sp<Fence> presentFence{Fence::NO_FENCE};
        sp<Fence> clientTargetAcquireFence{Fence::NO_FENCE};
        std::unordered_map<HWC2::Layer*, sp<Fence>> layerFences;
        sp<Fence> readbackFence{Fence::NO_FENCE};
    };

    struct ColorProfile {
@@ -239,6 +240,7 @@ public:
    // See Output::setLayerFilter.
    virtual bool includesLayer(ui::LayerFilter) const = 0;
    virtual bool includesLayer(const sp<LayerFE>&) const = 0;
    virtual bool includesLayer(LayerFE*) const = 0;

    // Returns a pointer to the output layer corresponding to the given layer on
    // this output, or nullptr if the layer does not have one
+1 −0
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@ public:

    bool includesLayer(ui::LayerFilter) const override;
    bool includesLayer(const sp<LayerFE>&) const override;
    bool includesLayer(LayerFE*) const override;

    compositionengine::OutputLayer* getOutputLayerForLayer(const sp<LayerFE>&) const override;

+2 −0
Original line number Diff line number Diff line
@@ -173,6 +173,8 @@ struct OutputCompositionState {

    PictureProfileHandle pictureProfileHandle;

    sp<GraphicBuffer> readbackBuffer = nullptr;

    // Debugging
    void dump(std::string& result) const;
};
+1 −0
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ public:
    MOCK_METHOD(void, setLayerFilter, (ui::LayerFilter));
    MOCK_METHOD(bool, includesLayer, (ui::LayerFilter), (const));
    MOCK_METHOD(bool, includesLayer, (const sp<compositionengine::LayerFE>&), (const));
    MOCK_METHOD(bool, includesLayer, (compositionengine::LayerFE*), (const));

    MOCK_METHOD1(setColorTransform, void(const compositionengine::CompositionRefreshArgs&));
    MOCK_METHOD1(setColorProfile, void(const ColorProfile&));
+7 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include <compositionengine/impl/DumpHelpers.h>
#include <compositionengine/impl/OutputLayer.h>
#include <compositionengine/impl/RenderSurface.h>
#include <ui/DisplayId.h>

// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic push
@@ -266,6 +267,12 @@ bool Display::chooseCompositionStrategy(

    const TimePoint hwcValidateStartTime = TimePoint::now();

    const auto physicalDisplayId = getDisplayIdVariant().and_then(asPhysicalDisplayId);

    if (physicalDisplayId && getState().readbackBuffer) {
        hwc.setReadbackBuffer(*physicalDisplayId, getState().readbackBuffer, Fence::NO_FENCE);
    }

    if (status_t result = hwc.getDeviceCompositionChanges(*halDisplayId, requiresClientComposition,
                                                          getState().earliestPresentTime,
                                                          getState().expectedPresentTime,
Loading