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

Commit 229c5228 authored by Alec Mouri's avatar Alec Mouri Committed by Android (Google) Code Review
Browse files

Merge "Plumb in local tonemapping flag into renderengine" into main

parents 5697ad6f a7e752e2
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -86,6 +86,22 @@ struct DisplaySettings {
    // Configures the rendering intent of the output display. This is used for tonemapping.
    aidl::android::hardware::graphics::composer3::RenderIntent renderIntent =
            aidl::android::hardware::graphics::composer3::RenderIntent::TONE_MAP_COLORIMETRIC;

    // Tonemapping strategy to use for each layer. This is only used for tonemapping HDR source
    // content
    enum class TonemapStrategy {
        // Use a tonemapper defined by libtonemap. This may be OEM-defined as of Android 13, aka
        // undefined.
        // This is typically a global tonemapper, designed to match what is on screen.
        Libtonemap,
        // Use a local tonemapper. Because local tonemapping uses large intermediate allocations,
        // this
        // method is primarily recommended for infrequent rendering that does not need to exactly
        // match
        // pixels that are on-screen.
        Local,
    };
    TonemapStrategy tonemapStrategy = TonemapStrategy::Libtonemap;
};

static inline bool operator==(const DisplaySettings& lhs, const DisplaySettings& rhs) {
+5 −0
Original line number Diff line number Diff line
@@ -519,6 +519,11 @@ sk_sp<SkShader> SkiaRenderEngine::createRuntimeEffectShader(
    }

    if (parameters.requiresLinearEffect) {
        if (parameters.display.tonemapStrategy == DisplaySettings::TonemapStrategy::Local) {
            // TODO: Apply a local tonemap
            // fallthrough for now
        }

        auto effect =
                shaders::LinearEffect{.inputDataspace = parameters.layer.sourceDataspace,
                                      .outputDataspace = parameters.outputDataSpace,
+10 −3
Original line number Diff line number Diff line
@@ -30,7 +30,7 @@ std::shared_ptr<ScreenCaptureOutput> createScreenCaptureOutput(ScreenCaptureOutp
            ScreenCaptureOutput, compositionengine::CompositionEngine, const RenderArea&,
            const compositionengine::Output::ColorProfile&,
            bool>(args.compositionEngine, args.renderArea, args.colorProfile, args.regionSampling,
                  args.dimInGammaSpaceForEnhancedScreenshots);
                  args.dimInGammaSpaceForEnhancedScreenshots, args.enableLocalTonemapping);
    output->editState().isSecure = args.renderArea.isSecure();
    output->editState().isProtected = args.isProtected;
    output->setCompositionEnabled(true);
@@ -63,11 +63,13 @@ std::shared_ptr<ScreenCaptureOutput> createScreenCaptureOutput(ScreenCaptureOutp

ScreenCaptureOutput::ScreenCaptureOutput(
        const RenderArea& renderArea, const compositionengine::Output::ColorProfile& colorProfile,
        bool regionSampling, bool dimInGammaSpaceForEnhancedScreenshots)
        bool regionSampling, bool dimInGammaSpaceForEnhancedScreenshots,
        bool enableLocalTonemapping)
      : mRenderArea(renderArea),
        mColorProfile(colorProfile),
        mRegionSampling(regionSampling),
        mDimInGammaSpaceForEnhancedScreenshots(dimInGammaSpaceForEnhancedScreenshots) {}
        mDimInGammaSpaceForEnhancedScreenshots(dimInGammaSpaceForEnhancedScreenshots),
        mEnableLocalTonemapping(enableLocalTonemapping) {}

void ScreenCaptureOutput::updateColorProfile(const compositionengine::CompositionRefreshArgs&) {
    auto& outputState = editState();
@@ -88,6 +90,11 @@ renderengine::DisplaySettings ScreenCaptureOutput::generateClientCompositionDisp
                aidl::android::hardware::graphics::composer3::DimmingStage::GAMMA_OETF;
    }

    if (mEnableLocalTonemapping) {
        clientCompositionDisplay.tonemapStrategy =
                renderengine::DisplaySettings::TonemapStrategy::Local;
    }

    return clientCompositionDisplay;
}

+4 −1
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ struct ScreenCaptureOutputArgs {
    bool treat170mAsSrgb;
    bool dimInGammaSpaceForEnhancedScreenshots;
    bool isProtected = false;
    bool enableLocalTonemapping = false;
};

// ScreenCaptureOutput is used to compose a set of layers into a preallocated buffer.
@@ -49,7 +50,8 @@ class ScreenCaptureOutput : public compositionengine::impl::Output {
public:
    ScreenCaptureOutput(const RenderArea& renderArea,
                        const compositionengine::Output::ColorProfile& colorProfile,
                        bool regionSampling, bool dimInGammaSpaceForEnhancedScreenshots);
                        bool regionSampling, bool dimInGammaSpaceForEnhancedScreenshots,
                        bool enableLocalTonemapping);

    void updateColorProfile(const compositionengine::CompositionRefreshArgs&) override;

@@ -67,6 +69,7 @@ private:
    const compositionengine::Output::ColorProfile& mColorProfile;
    const bool mRegionSampling;
    const bool mDimInGammaSpaceForEnhancedScreenshots;
    const bool mEnableLocalTonemapping;
};

std::shared_ptr<ScreenCaptureOutput> createScreenCaptureOutput(ScreenCaptureOutputArgs);
+25 −13
Original line number Diff line number Diff line
@@ -8331,6 +8331,9 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl(

    captureResults.capturedDataspace = requestedDataspace;

    const bool enableLocalTonemapping = FlagManager::getInstance().local_tonemap_screenshots() &&
            !renderArea->getHintForSeamlessTransition();

    {
        Mutex::Autolock lock(mStateLock);
        const DisplayDevice* display = nullptr;
@@ -8364,18 +8367,21 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl(
                displayBrightnessNits = sdrWhitePointNits;
            } else {
                displayBrightnessNits = state.displayBrightnessNits;
                // Only clamp the display brightness if this is not a seamless transition. Otherwise
                // for seamless transitions it's important to match the current display state as the
                // buffer will be shown under these same conditions, and we want to avoid any
                // flickers

                if (!enableLocalTonemapping) {
                    // Only clamp the display brightness if this is not a seamless transition.
                    // Otherwise for seamless transitions it's important to match the current
                    // display state as the buffer will be shown under these same conditions, and we
                    // want to avoid any flickers
                    if (sdrWhitePointNits > 1.0f && !renderArea->getHintForSeamlessTransition()) {
                    // Restrict the amount of HDR "headroom" in the screenshot to avoid over-dimming
                    // the SDR portion. 2.0 chosen by experimentation
                        // Restrict the amount of HDR "headroom" in the screenshot to avoid
                        // over-dimming the SDR portion. 2.0 chosen by experimentation
                        constexpr float kMaxScreenshotHeadroom = 2.0f;
                        displayBrightnessNits = std::min(sdrWhitePointNits * kMaxScreenshotHeadroom,
                                                         displayBrightnessNits);
                    }
                }
            }

            // Screenshots leaving the device should be colorimetric
            if (requestedDataspace == ui::Dataspace::UNKNOWN &&
@@ -8405,7 +8411,8 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl(
    auto present = [this, buffer = capturedBuffer, dataspace = captureResults.capturedDataspace,
                    sdrWhitePointNits, displayBrightnessNits, grayscale, isProtected,
                    layerFEs = copyLayerFEs(), layerStack, regionSampling,
                    renderArea = std::move(renderArea), renderIntent]() -> FenceResult {
                    renderArea = std::move(renderArea), renderIntent,
                    enableLocalTonemapping]() -> FenceResult {
        std::unique_ptr<compositionengine::CompositionEngine> compositionEngine =
                mFactory.createCompositionEngine();
        compositionEngine->setRenderEngine(mRenderEngine.get());
@@ -8414,7 +8421,11 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl(
                                                             .renderIntent = renderIntent};

        float targetBrightness = 1.0f;
        if (dataspace == ui::Dataspace::BT2020_HLG) {
        if (enableLocalTonemapping) {
            // Boost the whole scene so that SDR white is at 1.0 while still communicating the hdr
            // sdr ratio via display brightness / sdrWhite nits.
            targetBrightness = sdrWhitePointNits / displayBrightnessNits;
        } else if (dataspace == ui::Dataspace::BT2020_HLG) {
            const float maxBrightnessNits = displayBrightnessNits / sdrWhitePointNits * 203;
            // With a low dimming ratio, don't fit the entire curve. Otherwise mixed content
            // will appear way too bright.
@@ -8440,7 +8451,8 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl(
                                        .treat170mAsSrgb = mTreat170mAsSrgb,
                                        .dimInGammaSpaceForEnhancedScreenshots =
                                                dimInGammaSpaceForEnhancedScreenshots,
                                        .isProtected = isProtected});
                                        .isProtected = isProtected,
                                        .enableLocalTonemapping = enableLocalTonemapping});

        const float colorSaturation = grayscale ? 0 : 1;
        compositionengine::CompositionRefreshArgs refreshArgs{