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

Commit 251e612d authored by Dominik Laskowski's avatar Dominik Laskowski
Browse files

SF: Let DM resize framebuffer on resolution change

The goal of this change is to synchronize resolution switching across SF
and DM. The lack of synchronization causes glitches, which are currently
papered over in HWC by dropping frames whose size don't match the active
resolution.

A mode set involving a resolution switch was finalized by destroying the
DisplayDevice and thus its HWC layers. Remove this special case in favor
of letting DM call SurfaceControl.setDisplaySize right after requesting
the mode set via setDesiredDisplayModeSpecs.

Emit a mode change event to DM as soon as the DisplayModeRequest becomes
the desired mode. In response, DM sends the transaction that resizes the
display via setDisplaySize, so wait until that commit before modesetting
to the new resolution, and resize the framebuffer in that same frame.

Display projection depends on display size, so update the latter first
when committing DisplayDeviceState.

Fixes: 355427258
Flag: com.android.graphics.surfaceflinger.flags.synced_resolution_switch
Test: Internal (caiman) and external displays, with different rotations.
Test: Inner display (comet) with install orientation.
Change-Id: Ifaf300f3b5f907f7cd10b8db2aa6165ad2106530
parent 23069b31
Loading
Loading
Loading
Loading
+9 −3
Original line number Diff line number Diff line
@@ -504,12 +504,18 @@ struct DisplayState {
    Rect layerStackSpaceRect = Rect::EMPTY_RECT;
    Rect orientedDisplaySpaceRect = Rect::EMPTY_RECT;

    // Exclusive to virtual displays: The sink surface into which the virtual display is rendered,
    // and an optional resolution that overrides its default dimensions.
    sp<IGraphicBufferProducer> surface;
    // For physical displays, this is the resolution, which must match the active display mode. To
    // change the resolution, the client must first call SurfaceControl.setDesiredDisplayModeSpecs
    // with the new DesiredDisplayModeSpecs#defaultMode, then commit the matching width and height.
    //
    // For virtual displays, this is an optional resolution that overrides its default dimensions.
    //
    uint32_t width = 0;
    uint32_t height = 0;

    // For virtual displays, this is the sink surface into which the virtual display is rendered.
    sp<IGraphicBufferProducer> surface;

    status_t write(Parcel& output) const;
    status_t read(const Parcel& input);
};
+2 −1
Original line number Diff line number Diff line
@@ -26,7 +26,8 @@ namespace android::display {
struct DisplayModeRequest {
    scheduler::FrameRateMode mode;

    // Whether to emit DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE.
    // Whether to emit DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE for a change in refresh rate
    // or render rate. Ignored for resolution changes, which always emit the event.
    bool emitEvent = false;

    // Whether to force the request to be applied, even if the mode is unchanged.
+1 −3
Original line number Diff line number Diff line
@@ -223,9 +223,7 @@ void DisplayDevice::setFlags(uint32_t flags) {
    mFlags = flags;
}

void DisplayDevice::setDisplaySize(int width, int height) {
    LOG_FATAL_IF(!isVirtual(), "Changing the display size is supported only for virtual displays.");
    const auto size = ui::Size(width, height);
void DisplayDevice::setDisplaySize(ui::Size size) {
    mCompositionDisplay->setDisplaySize(size);
    if (mRefreshRateOverlay) {
        mRefreshRateOverlay->setViewport(size);
+1 −1
Original line number Diff line number Diff line
@@ -98,7 +98,7 @@ public:
    ui::Size getSize() const { return {getWidth(), getHeight()}; }

    void setLayerFilter(ui::LayerFilter);
    void setDisplaySize(int width, int height);
    void setDisplaySize(ui::Size);
    void setProjection(ui::Rotation orientation, Rect viewport, Rect frame);
    void stageBrightness(float brightness) REQUIRES(kMainThreadContext);
    void persistBrightness(bool needsComposite) REQUIRES(kMainThreadContext);
+4 −0
Original line number Diff line number Diff line
@@ -33,6 +33,10 @@ struct FrameRateMode {
    }

    bool operator!=(const FrameRateMode& other) const { return !(*this == other); }

    bool matchesResolution(const FrameRateMode& other) const {
        return modePtr->getResolution() == other.modePtr->getResolution();
    }
};

inline std::string to_string(const FrameRateMode& mode) {
Loading