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

Commit 69bf10f5 authored by Chia-I Wu's avatar Chia-I Wu
Browse files

surfaceflinger: simplify P3 support in RE

RE always knows how to convert sRGB/P3/BT2020 to P3.  The conversion
is enabled by SurfaceFlinger whenever the color mode is P3 (and when
hasWideColorDisplay is true).  This change simplifies or removes
some wide color state functions from RE, and moves the burden to
SurfaceFlinger.  It also changes GLES20RenderEngine::drawMesh to
inspect mDataSpace and mOutputDataSpace directly.

This allows us to enable the conversion in more cases more easily.
For example, we can choose to set the RE output dataspace to P3 even
when the display color mode is NATIVE.

Test: manual with UiBench
Change-Id: I5e701dd6b01764efbbab967dc4a26a4d008dfc09
parent 4b0e4ddf
Loading
Loading
Loading
Loading
+17 −43
Original line number Diff line number Diff line
@@ -210,42 +210,16 @@ void GLES20RenderEngine::setupLayerBlending(bool premultipliedAlpha, bool opaque
    }
}

void GLES20RenderEngine::setColorMode(android_color_mode mode) {
    ALOGV("setColorMode: %s (0x%x)", decodeColorMode(mode).c_str(), mode);

    if (mColorMode == mode) return;

    if (!mPlatformHasWideColor || !mDisplayHasWideColor || mode == HAL_COLOR_MODE_SRGB ||
        mode == HAL_COLOR_MODE_NATIVE) {
        // We are returning back to our default color_mode
        mUseWideColor = false;
        mWideColorFrameCount = 0;
    } else {
        mUseWideColor = true;
    }

    mColorMode = mode;
}

void GLES20RenderEngine::setSourceDataSpace(android_dataspace source) {
    if (source == HAL_DATASPACE_UNKNOWN) {
        // Treat UNKNOWN as SRGB
        source = HAL_DATASPACE_V0_SRGB;
    }
    mDataSpace = source;
}

void GLES20RenderEngine::setSourceY410BT2020(bool enable) {
    mState.setY410BT2020(enable);
}

void GLES20RenderEngine::setWideColor(bool hasWideColor) {
    ALOGV("setWideColor: %s", hasWideColor ? "true" : "false");
    mDisplayHasWideColor = hasWideColor;
void GLES20RenderEngine::setSourceDataSpace(android_dataspace source) {
    mDataSpace = source;
}

bool GLES20RenderEngine::usesWideColor() {
    return mUseWideColor;
void GLES20RenderEngine::setOutputDataSpace(android_dataspace dataspace) {
    mOutputDataSpace = dataspace;
}

void GLES20RenderEngine::setupLayerTexturing(const Texture& texture) {
@@ -326,17 +300,13 @@ void GLES20RenderEngine::drawMesh(const Mesh& mesh) {
    glVertexAttribPointer(Program::position, mesh.getVertexSize(), GL_FLOAT, GL_FALSE,
                          mesh.getByteStride(), mesh.getPositions());

    if (usesWideColor()) {
    // DISPLAY_P3 is the only supported wide color output
    if (mPlatformHasWideColor && mOutputDataSpace == HAL_DATASPACE_DISPLAY_P3) {
        Description wideColorState = mState;
        switch (int(mDataSpace)) {
            case HAL_DATASPACE_DISPLAY_P3:
                // input matches output
                break;
            case HAL_DATASPACE_V0_SCRGB_LINEAR:
                wideColorState.setColorMatrix(mState.getColorMatrix() * mSrgbToDisplayP3);
                wideColorState.setInputTransferFunction(Description::TransferFunction::LINEAR);
                wideColorState.setOutputTransferFunction(Description::TransferFunction::SRGB);
                break;
            case HAL_DATASPACE_BT2020_PQ:
            case HAL_DATASPACE_BT2020_ITU_PQ:
                wideColorState.setColorMatrix(mState.getColorMatrix() * mBt2020ToDisplayP3);
@@ -345,8 +315,13 @@ void GLES20RenderEngine::drawMesh(const Mesh& mesh) {
                wideColorState.enableToneMapping(true);
                break;
            default:
                // treat all other dataspaces as sRGB
                wideColorState.setColorMatrix(mState.getColorMatrix() * mSrgbToDisplayP3);
                if ((mDataSpace & HAL_DATASPACE_TRANSFER_MASK) == HAL_DATASPACE_TRANSFER_LINEAR) {
                    wideColorState.setInputTransferFunction(Description::TransferFunction::LINEAR);
                } else {
                    wideColorState.setInputTransferFunction(Description::TransferFunction::SRGB);
                }
                wideColorState.setOutputTransferFunction(Description::TransferFunction::SRGB);
                ALOGV("drawMesh: gamut transform applied");
                break;
@@ -356,8 +331,9 @@ void GLES20RenderEngine::drawMesh(const Mesh& mesh) {
        glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());

        if (outputDebugPPMs) {
            static uint64_t wideColorFrameCount = 0;
            std::ostringstream out;
            out << "/data/texture_out" << mWideColorFrameCount++;
            out << "/data/texture_out" << wideColorFrameCount++;
            writePPM(out.str().c_str(), mVpWidth, mVpHeight);
        }
    } else {
@@ -373,11 +349,9 @@ void GLES20RenderEngine::drawMesh(const Mesh& mesh) {

void GLES20RenderEngine::dump(String8& result) {
    RenderEngine::dump(result);
    if (usesWideColor()) {
        result.append("Wide-color: On\n");
    } else {
        result.append("Wide-color: Off\n");
    }
    result.appendFormat("RenderEngine last dataspace conversion: (%s) to (%s)\n",
                        dataspaceDetails(mDataSpace).c_str(),
                        dataspaceDetails(mOutputDataSpace).c_str());
}

// ---------------------------------------------------------------------------
+7 −14
Original line number Diff line number Diff line
@@ -72,27 +72,20 @@ protected:
                                    const half4& color) override;

    // Color management related functions and state
    void setColorMode(android_color_mode mode);
    void setSourceDataSpace(android_dataspace source);
    void setSourceY410BT2020(bool enable);
    void setWideColor(bool hasWideColor);
    bool usesWideColor();

    // Current color mode of display using the render engine
    android_color_mode mColorMode = HAL_COLOR_MODE_NATIVE;
    void setSourceY410BT2020(bool enable) override;
    void setSourceDataSpace(android_dataspace source) override;
    void setOutputDataSpace(android_dataspace dataspace) override;

    // Current dataspace of layer being rendered
    android_dataspace mDataSpace = HAL_DATASPACE_V0_SRGB;
    android_dataspace mDataSpace = HAL_DATASPACE_UNKNOWN;

    // Indicate if wide-color mode is needed or not
    bool mDisplayHasWideColor = false;
    bool mUseWideColor = false;
    uint64_t mWideColorFrameCount = 0;
    // Current output dataspace of the render engine
    android_dataspace mOutputDataSpace = HAL_DATASPACE_UNKNOWN;

    // Currently only supporting sRGB, BT2020 and DisplayP3 color spaces
    const bool mPlatformHasWideColor = false;
    mat4 mSrgbToDisplayP3;
    mat4 mBt2020ToDisplayP3;
    bool mPlatformHasWideColor = false;

    virtual void setupLayerTexturing(const Texture& texture);
    virtual void setupLayerBlackedOut();
+5 −5
Original line number Diff line number Diff line
@@ -108,11 +108,6 @@ public:
                                          bool yswap, Transform::orientation_flags rotation) = 0;
    virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
                                    const half4& color) = 0;
    virtual void setColorMode(android_color_mode mode) = 0;
    virtual void setSourceDataSpace(android_dataspace source) = 0;
    virtual void setSourceY410BT2020(bool enable) = 0;
    virtual void setWideColor(bool hasWideColor) = 0;
    virtual bool usesWideColor() = 0;
    virtual void setupLayerTexturing(const Texture& texture) = 0;
    virtual void setupLayerBlackedOut() = 0;
    virtual void setupFillWithColor(float r, float g, float b, float a) = 0;
@@ -122,6 +117,11 @@ public:
    virtual void disableTexturing() = 0;
    virtual void disableBlending() = 0;

    // wide color support
    virtual void setSourceY410BT2020(bool enable) = 0;
    virtual void setSourceDataSpace(android_dataspace source) = 0;
    virtual void setOutputDataSpace(android_dataspace dataspace) = 0;

    // drawing
    virtual void drawMesh(const Mesh& mesh) = 0;

+13 −7
Original line number Diff line number Diff line
@@ -2738,10 +2738,13 @@ bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& displayDev
    if (hasClientComposition) {
        ALOGV("hasClientComposition");

        getBE().mRenderEngine->setWideColor(
                displayDevice->getWideColorSupport() && !mForceNativeColorMode);
        getBE().mRenderEngine->setColorMode(mForceNativeColorMode ?
                HAL_COLOR_MODE_NATIVE : displayDevice->getActiveColorMode());
        android_dataspace outputDataspace = HAL_DATASPACE_UNKNOWN;
        if (!mForceNativeColorMode && displayDevice->getWideColorSupport() &&
                displayDevice->getActiveColorMode() == HAL_COLOR_MODE_DISPLAY_P3) {
            outputDataspace = HAL_DATASPACE_DISPLAY_P3;
        }
        getBE().mRenderEngine->setOutputDataSpace(outputDataspace);

        if (!displayDevice->makeCurrent()) {
            ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
                  displayDevice->getDisplayName().string());
@@ -4596,9 +4599,12 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea,
        ALOGE("Invalid crop rect: b = %d (> %d)", sourceCrop.bottom, raHeight);
    }

    engine.setWideColor(renderArea.getWideColorSupport() && !mForceNativeColorMode);
    engine.setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE
                                              : renderArea.getActiveColorMode());
    android_dataspace outputDataspace = HAL_DATASPACE_UNKNOWN;
    if (!mForceNativeColorMode && renderArea.getWideColorSupport() &&
            renderArea.getActiveColorMode() == HAL_COLOR_MODE_DISPLAY_P3) {
        outputDataspace = HAL_DATASPACE_DISPLAY_P3;
    }
    getBE().mRenderEngine->setOutputDataSpace(outputDataspace);

    // make sure to clear all GL error flags
    engine.checkErrors();
+3 −5
Original line number Diff line number Diff line
@@ -57,17 +57,15 @@ public:
    MOCK_METHOD6(setViewportAndProjection,
                 void(size_t, size_t, Rect, size_t, bool, Transform::orientation_flags));
    MOCK_METHOD4(setupLayerBlending, void(bool, bool, bool, const half4&));
    MOCK_METHOD1(setColorMode, void(android_color_mode));
    MOCK_METHOD1(setSourceDataSpace, void(android_dataspace));
    MOCK_METHOD1(setSourceY410BT2020, void(bool));
    MOCK_METHOD1(setWideColor, void(bool));
    MOCK_METHOD0(usesWideColor, bool());
    MOCK_METHOD1(setupLayerTexturing, void(const Texture&));
    MOCK_METHOD0(setupLayerBlackedOut, void());
    MOCK_METHOD4(setupFillWithColor, void(float, float, float, float));
    MOCK_METHOD1(setupColorTransform, mat4(const mat4&));
    MOCK_METHOD0(disableTexturing, void());
    MOCK_METHOD0(disableBlending, void());
    MOCK_METHOD1(setSourceY410BT2020, void(bool));
    MOCK_METHOD1(setSourceDataSpace, void(android_dataspace));
    MOCK_METHOD1(setOutputDataSpace, void(android_dataspace));
    MOCK_METHOD2(bindNativeBufferAsFrameBuffer,
                 void(ANativeWindowBuffer*, RE::BindNativeBufferAsFramebuffer*));
    MOCK_METHOD1(unbindNativeBufferAsFrameBuffer, void(RE::BindNativeBufferAsFramebuffer*));