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

Commit 72128ee8 authored by Chia-I Wu's avatar Chia-I Wu Committed by Android (Google) Code Review
Browse files

Merge "surfaceflinger: fix color tranform matrix races" into pi-dev

parents 0102ad2d 28f320b4
Loading
Loading
Loading
Loading
+46 −36
Original line number Original line Diff line number Diff line
@@ -244,7 +244,6 @@ SurfaceFlinger::SurfaceFlinger(SurfaceFlinger::SkipInitializationTag)
        mPrimaryDispSync("PrimaryDispSync"),
        mPrimaryDispSync("PrimaryDispSync"),
        mPrimaryHWVsyncEnabled(false),
        mPrimaryHWVsyncEnabled(false),
        mHWVsyncAvailable(false),
        mHWVsyncAvailable(false),
        mHasColorMatrix(false),
        mHasPoweredOff(false),
        mHasPoweredOff(false),
        mNumLayers(0),
        mNumLayers(0),
        mVrFlingerRequestsDisplay(false),
        mVrFlingerRequestsDisplay(false),
@@ -723,10 +722,13 @@ void SurfaceFlinger::init() {
}
}


void SurfaceFlinger::readPersistentProperties() {
void SurfaceFlinger::readPersistentProperties() {
    Mutex::Autolock _l(mStateLock);

    char value[PROPERTY_VALUE_MAX];
    char value[PROPERTY_VALUE_MAX];


    property_get("persist.sys.sf.color_saturation", value, "1.0");
    property_get("persist.sys.sf.color_saturation", value, "1.0");
    mGlobalSaturationFactor = atof(value);
    mGlobalSaturationFactor = atof(value);
    updateColorMatrixLocked();
    ALOGV("Saturation is set to %.2f", mGlobalSaturationFactor);
    ALOGV("Saturation is set to %.2f", mGlobalSaturationFactor);


    property_get("persist.sys.sf.native_mode", value, "0");
    property_get("persist.sys.sf.native_mode", value, "0");
@@ -1868,22 +1870,6 @@ void SurfaceFlinger::rebuildLayerStacks() {
    }
    }
}
}


mat4 SurfaceFlinger::computeSaturationMatrix() const {
    if (mGlobalSaturationFactor == 1.0f) {
        return mat4();
    }

    // Rec.709 luma coefficients
    float3 luminance{0.213f, 0.715f, 0.072f};
    luminance *= 1.0f - mGlobalSaturationFactor;
    return mat4(
        vec4{luminance.r + mGlobalSaturationFactor, luminance.r, luminance.r, 0.0f},
        vec4{luminance.g, luminance.g + mGlobalSaturationFactor, luminance.g, 0.0f},
        vec4{luminance.b, luminance.b, luminance.b + mGlobalSaturationFactor, 0.0f},
        vec4{0.0f, 0.0f, 0.0f, 1.0f}
    );
}

// Returns a dataspace that fits all visible layers.  The returned dataspace
// Returns a dataspace that fits all visible layers.  The returned dataspace
// can only be one of
// can only be one of
//
//
@@ -2009,9 +1995,6 @@ void SurfaceFlinger::setUpHWComposer() {
        }
        }
    }
    }



    mat4 colorMatrix = mColorMatrix * computeSaturationMatrix() * mDaltonizer();

    // Set the per-frame data
    // Set the per-frame data
    for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
    for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
        auto& displayDevice = mDisplays[displayId];
        auto& displayDevice = mDisplays[displayId];
@@ -2020,9 +2003,9 @@ void SurfaceFlinger::setUpHWComposer() {
        if (hwcId < 0) {
        if (hwcId < 0) {
            continue;
            continue;
        }
        }
        if (colorMatrix != mPreviousColorMatrix) {
        if (mDrawingState.colorMatrixChanged) {
            displayDevice->setColorTransform(colorMatrix);
            displayDevice->setColorTransform(mDrawingState.colorMatrix);
            status_t result = getBE().mHwc->setColorTransform(hwcId, colorMatrix);
            status_t result = getBE().mHwc->setColorTransform(hwcId, mDrawingState.colorMatrix);
            ALOGE_IF(result != NO_ERROR, "Failed to set color transform on "
            ALOGE_IF(result != NO_ERROR, "Failed to set color transform on "
                    "display %zd: %d", displayId, result);
                    "display %zd: %d", displayId, result);
        }
        }
@@ -2055,7 +2038,7 @@ void SurfaceFlinger::setUpHWComposer() {
        }
        }
    }
    }


    mPreviousColorMatrix = colorMatrix;
    mDrawingState.colorMatrixChanged = false;


    for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
    for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
        auto& displayDevice = mDisplays[displayId];
        auto& displayDevice = mDisplays[displayId];
@@ -2644,6 +2627,9 @@ void SurfaceFlinger::commitTransaction()
    mAnimCompositionPending = mAnimTransactionPending;
    mAnimCompositionPending = mAnimTransactionPending;


    mDrawingState = mCurrentState;
    mDrawingState = mCurrentState;
    // clear the "changed" flags in current state
    mCurrentState.colorMatrixChanged = false;

    mDrawingState.traverseInZOrder([](Layer* layer) {
    mDrawingState.traverseInZOrder([](Layer* layer) {
        layer->commitChildList();
        layer->commitChildList();
    });
    });
@@ -2896,9 +2882,8 @@ bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& displayDev
    mat4 legacySrgbSaturationMatrix = mLegacySrgbSaturationMatrix;
    mat4 legacySrgbSaturationMatrix = mLegacySrgbSaturationMatrix;
    const bool applyColorMatrix = !hasDeviceComposition && !skipClientColorTransform;
    const bool applyColorMatrix = !hasDeviceComposition && !skipClientColorTransform;
    if (applyColorMatrix) {
    if (applyColorMatrix) {
        mat4 colorMatrix = mColorMatrix * computeSaturationMatrix() * mDaltonizer();
        oldColorMatrix = getRenderEngine().setupColorTransform(mDrawingState.colorMatrix);
        oldColorMatrix = getRenderEngine().setupColorTransform(colorMatrix);
        legacySrgbSaturationMatrix = mDrawingState.colorMatrix * legacySrgbSaturationMatrix;
        legacySrgbSaturationMatrix = colorMatrix * legacySrgbSaturationMatrix;
    }
    }


    if (hasClientComposition) {
    if (hasClientComposition) {
@@ -4363,6 +4348,30 @@ bool SurfaceFlinger::startDdmConnection()
    return true;
    return true;
}
}


void SurfaceFlinger::updateColorMatrixLocked() {
    mat4 colorMatrix;
    if (mGlobalSaturationFactor != 1.0f) {
        // Rec.709 luma coefficients
        float3 luminance{0.213f, 0.715f, 0.072f};
        luminance *= 1.0f - mGlobalSaturationFactor;
        mat4 saturationMatrix = mat4(
            vec4{luminance.r + mGlobalSaturationFactor, luminance.r, luminance.r, 0.0f},
            vec4{luminance.g, luminance.g + mGlobalSaturationFactor, luminance.g, 0.0f},
            vec4{luminance.b, luminance.b, luminance.b + mGlobalSaturationFactor, 0.0f},
            vec4{0.0f, 0.0f, 0.0f, 1.0f}
        );
        colorMatrix = mClientColorMatrix * saturationMatrix * mDaltonizer();
    } else {
        colorMatrix = mClientColorMatrix * mDaltonizer();
    }

    if (mCurrentState.colorMatrix != colorMatrix) {
        mCurrentState.colorMatrix = colorMatrix;
        mCurrentState.colorMatrixChanged = true;
        setTransactionFlags(eTransactionNeeded);
    }
}

status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) {
status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) {
    switch (code) {
    switch (code) {
        case CREATE_CONNECTION:
        case CREATE_CONNECTION:
@@ -4497,6 +4506,7 @@ status_t SurfaceFlinger::onTransact(
                return NO_ERROR;
                return NO_ERROR;
            }
            }
            case 1014: {
            case 1014: {
                Mutex::Autolock _l(mStateLock);
                // daltonize
                // daltonize
                n = data.readInt32();
                n = data.readInt32();
                switch (n % 10) {
                switch (n % 10) {
@@ -4518,33 +4528,33 @@ status_t SurfaceFlinger::onTransact(
                } else {
                } else {
                    mDaltonizer.setMode(ColorBlindnessMode::Simulation);
                    mDaltonizer.setMode(ColorBlindnessMode::Simulation);
                }
                }
                invalidateHwcGeometry();

                repaintEverything();
                updateColorMatrixLocked();
                return NO_ERROR;
                return NO_ERROR;
            }
            }
            case 1015: {
            case 1015: {
                Mutex::Autolock _l(mStateLock);
                // apply a color matrix
                // apply a color matrix
                n = data.readInt32();
                n = data.readInt32();
                if (n) {
                if (n) {
                    // color matrix is sent as a column-major mat4 matrix
                    // color matrix is sent as a column-major mat4 matrix
                    for (size_t i = 0 ; i < 4; i++) {
                    for (size_t i = 0 ; i < 4; i++) {
                        for (size_t j = 0; j < 4; j++) {
                        for (size_t j = 0; j < 4; j++) {
                            mColorMatrix[i][j] = data.readFloat();
                            mClientColorMatrix[i][j] = data.readFloat();
                        }
                        }
                    }
                    }
                } else {
                } else {
                    mColorMatrix = mat4();
                    mClientColorMatrix = mat4();
                }
                }


                // Check that supplied matrix's last row is {0,0,0,1} so we can avoid
                // Check that supplied matrix's last row is {0,0,0,1} so we can avoid
                // the division by w in the fragment shader
                // the division by w in the fragment shader
                float4 lastRow(transpose(mColorMatrix)[3]);
                float4 lastRow(transpose(mClientColorMatrix)[3]);
                if (any(greaterThan(abs(lastRow - float4{0, 0, 0, 1}), float4{1e-4f}))) {
                if (any(greaterThan(abs(lastRow - float4{0, 0, 0, 1}), float4{1e-4f}))) {
                    ALOGE("The color transform's last row must be (0, 0, 0, 1)");
                    ALOGE("The color transform's last row must be (0, 0, 0, 1)");
                }
                }


                invalidateHwcGeometry();
                updateColorMatrixLocked();
                repaintEverything();
                return NO_ERROR;
                return NO_ERROR;
            }
            }
            // This is an experimental interface
            // This is an experimental interface
@@ -4587,10 +4597,10 @@ status_t SurfaceFlinger::onTransact(
                return NO_ERROR;
                return NO_ERROR;
            }
            }
            case 1022: { // Set saturation boost
            case 1022: { // Set saturation boost
                Mutex::Autolock _l(mStateLock);
                mGlobalSaturationFactor = std::max(0.0f, std::min(data.readFloat(), 2.0f));
                mGlobalSaturationFactor = std::max(0.0f, std::min(data.readFloat(), 2.0f));


                invalidateHwcGeometry();
                updateColorMatrixLocked();
                repaintEverything();
                return NO_ERROR;
                return NO_ERROR;
            }
            }
            case 1023: { // Set native mode
            case 1023: { // Set native mode
+14 −10
Original line number Original line Diff line number Diff line
@@ -373,6 +373,10 @@ private:
            // always uses the Drawing StateSet.
            // always uses the Drawing StateSet.
            layersSortedByZ = other.layersSortedByZ;
            layersSortedByZ = other.layersSortedByZ;
            displays = other.displays;
            displays = other.displays;
            colorMatrixChanged = other.colorMatrixChanged;
            if (colorMatrixChanged) {
                colorMatrix = other.colorMatrix;
            }
            return *this;
            return *this;
        }
        }


@@ -380,6 +384,9 @@ private:
        LayerVector layersSortedByZ;
        LayerVector layersSortedByZ;
        DefaultKeyedVector< wp<IBinder>, DisplayDeviceState> displays;
        DefaultKeyedVector< wp<IBinder>, DisplayDeviceState> displays;


        bool colorMatrixChanged = true;
        mat4 colorMatrix;

        void traverseInZOrder(const LayerVector::Visitor& visitor) const;
        void traverseInZOrder(const LayerVector::Visitor& visitor) const;
        void traverseInReverseZOrder(const LayerVector::Visitor& visitor) const;
        void traverseInReverseZOrder(const LayerVector::Visitor& visitor) const;
    };
    };
@@ -653,8 +660,6 @@ private:
                       ui::ColorMode* outMode,
                       ui::ColorMode* outMode,
                       ui::Dataspace* outDataSpace) const;
                       ui::Dataspace* outDataSpace) const;


    mat4 computeSaturationMatrix() const;

    void setUpHWComposer();
    void setUpHWComposer();
    void doComposition();
    void doComposition();
    void doDebugFlashRegions();
    void doDebugFlashRegions();
@@ -741,6 +746,8 @@ private:
    // Check to see if we should handoff to vr flinger.
    // Check to see if we should handoff to vr flinger.
    void updateVrFlinger();
    void updateVrFlinger();


    void updateColorMatrixLocked();

    /* ------------------------------------------------------------------------
    /* ------------------------------------------------------------------------
     * Attributes
     * Attributes
     */
     */
@@ -754,6 +761,11 @@ private:
    bool mAnimTransactionPending;
    bool mAnimTransactionPending;
    SortedVector< sp<Layer> > mLayersPendingRemoval;
    SortedVector< sp<Layer> > mLayersPendingRemoval;


    // global color transform states
    Daltonizer mDaltonizer;
    float mGlobalSaturationFactor = 1.0f;
    mat4 mClientColorMatrix;

    // Can't be unordered_set because wp<> isn't hashable
    // Can't be unordered_set because wp<> isn't hashable
    std::set<wp<IBinder>> mGraphicBufferProducerList;
    std::set<wp<IBinder>> mGraphicBufferProducerList;
    size_t mMaxGraphicBufferProducerListSize = MAX_LAYERS;
    size_t mMaxGraphicBufferProducerListSize = MAX_LAYERS;
@@ -844,12 +856,6 @@ private:


    bool mInjectVSyncs;
    bool mInjectVSyncs;


    Daltonizer mDaltonizer;

    mat4 mPreviousColorMatrix;
    mat4 mColorMatrix;
    bool mHasColorMatrix;

    // Static screen stats
    // Static screen stats
    bool mHasPoweredOff;
    bool mHasPoweredOff;


@@ -867,8 +873,6 @@ private:
    DisplayColorSetting mDisplayColorSetting = DisplayColorSetting::MANAGED;
    DisplayColorSetting mDisplayColorSetting = DisplayColorSetting::MANAGED;
    // Applied on sRGB layers when the render intent is non-colorimetric.
    // Applied on sRGB layers when the render intent is non-colorimetric.
    mat4 mLegacySrgbSaturationMatrix;
    mat4 mLegacySrgbSaturationMatrix;
    // Applied globally.
    float mGlobalSaturationFactor = 1.0f;
    bool mBuiltinDisplaySupportsEnhance = false;
    bool mBuiltinDisplaySupportsEnhance = false;


    using CreateBufferQueueFunction =
    using CreateBufferQueueFunction =