surfaceflinger: compute color mode mappings on hotplug

Populuate DisplayDevice::mColorModes when a DisplayDevice is
created.

DisplayDevice::mColorModes is a map from any possible
Dataspace/RenderIntent to supported
Dataspace/ColorMode/RenderIntent.  This makes sure we never ask the
composer to use an unsupported Dataspace/ColorMode/RenderIntent
combination.

The map is populated on hotplug because we don't want to compute the
mapping on the fly at each frame.

Bug: 79843697
Bug: 75981986
Test: manual under sRGB, P3, HDR
Change-Id: I967d09b1e8d31ea631b202db1799a7a2a0c5ee3f
Merged-In: I967d09b1e8d31ea631b202db1799a7a2a0c5ee3f
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index f6eac8b..ccd2aba 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -18,6 +18,9 @@
 #undef LOG_TAG
 #define LOG_TAG "DisplayDevice"
 
+#include <array>
+#include <unordered_set>
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -55,6 +58,7 @@
 using namespace android::hardware::configstore;
 using namespace android::hardware::configstore::V1_0;
 using android::ui::ColorMode;
+using android::ui::Dataspace;
 using android::ui::Hdr;
 using android::ui::RenderIntent;
 
@@ -65,6 +69,147 @@
 
 uint32_t DisplayDevice::sPrimaryDisplayOrientation = 0;
 
+namespace {
+
+// ordered list of known SDR color modes
+const std::array<ColorMode, 2> sSdrColorModes = {
+        ColorMode::DISPLAY_P3,
+        ColorMode::SRGB,
+};
+
+// ordered list of known HDR color modes
+const std::array<ColorMode, 2> sHdrColorModes = {
+        ColorMode::BT2100_PQ,
+        ColorMode::BT2100_HLG,
+};
+
+// ordered list of known SDR render intents
+const std::array<RenderIntent, 2> sSdrRenderIntents = {
+        RenderIntent::ENHANCE,
+        RenderIntent::COLORIMETRIC,
+};
+
+// ordered list of known HDR render intents
+const std::array<RenderIntent, 2> sHdrRenderIntents = {
+        RenderIntent::TONE_MAP_ENHANCE,
+        RenderIntent::TONE_MAP_COLORIMETRIC,
+};
+
+// map known color mode to dataspace
+Dataspace colorModeToDataspace(ColorMode mode) {
+    switch (mode) {
+        case ColorMode::SRGB:
+            return Dataspace::SRGB;
+        case ColorMode::DISPLAY_P3:
+            return Dataspace::DISPLAY_P3;
+        case ColorMode::BT2100_HLG:
+            return Dataspace::BT2020_HLG;
+        case ColorMode::BT2100_PQ:
+            return Dataspace::BT2020_PQ;
+        default:
+            return Dataspace::UNKNOWN;
+    }
+}
+
+// Return a list of candidate color modes.
+std::vector<ColorMode> getColorModeCandidates(ColorMode mode) {
+    std::vector<ColorMode> candidates;
+
+    // add mode itself
+    candidates.push_back(mode);
+
+    // check if mode is HDR
+    bool isHdr = false;
+    for (auto hdrMode : sHdrColorModes) {
+        if (hdrMode == mode) {
+            isHdr = true;
+            break;
+        }
+    }
+
+    // add other HDR candidates when mode is HDR
+    if (isHdr) {
+        for (auto hdrMode : sHdrColorModes) {
+            if (hdrMode != mode) {
+                candidates.push_back(hdrMode);
+            }
+        }
+    }
+
+    // add other SDR candidates
+    for (auto sdrMode : sSdrColorModes) {
+        if (sdrMode != mode) {
+            candidates.push_back(sdrMode);
+        }
+    }
+
+    return candidates;
+}
+
+// Return a list of candidate render intents.
+std::vector<RenderIntent> getRenderIntentCandidates(RenderIntent intent) {
+    std::vector<RenderIntent> candidates;
+
+    // add intent itself
+    candidates.push_back(intent);
+
+    // check if intent is HDR
+    bool isHdr = false;
+    for (auto hdrIntent : sHdrRenderIntents) {
+        if (hdrIntent == intent) {
+            isHdr = true;
+            break;
+        }
+    }
+
+    // add other HDR candidates when intent is HDR
+    if (isHdr) {
+        for (auto hdrIntent : sHdrRenderIntents) {
+            if (hdrIntent != intent) {
+                candidates.push_back(hdrIntent);
+            }
+        }
+    }
+
+    // add COLORIMETRIC
+    if (intent != RenderIntent::COLORIMETRIC) {
+        candidates.push_back(RenderIntent::COLORIMETRIC);
+    }
+
+    return candidates;
+}
+
+// Return the best color mode supported by HWC.
+ColorMode getHwcColorMode(
+        const std::unordered_map<ColorMode, std::vector<RenderIntent>>& hwcColorModes,
+        ColorMode mode) {
+    std::vector<ColorMode> candidates = getColorModeCandidates(mode);
+    for (auto candidate : candidates) {
+        auto iter = hwcColorModes.find(candidate);
+        if (iter != hwcColorModes.end()) {
+            return candidate;
+        }
+    }
+
+    return ColorMode::NATIVE;
+}
+
+// Return the best render intent supported by HWC.
+RenderIntent getHwcRenderIntent(const std::vector<RenderIntent>& hwcIntents, RenderIntent intent) {
+    std::vector<RenderIntent> candidates = getRenderIntentCandidates(intent);
+    for (auto candidate : candidates) {
+        for (auto hwcIntent : hwcIntents) {
+            if (candidate == hwcIntent) {
+                return candidate;
+            }
+        }
+    }
+
+    return RenderIntent::COLORIMETRIC;
+}
+
+} // anonymous namespace
+
 // clang-format off
 DisplayDevice::DisplayDevice(
         const sp<SurfaceFlinger>& flinger,
@@ -80,7 +225,7 @@
         bool hasWideColorGamut,
         const HdrCapabilities& hdrCapabilities,
         const int32_t supportedPerFrameMetadata,
-        const std::unordered_map<ui::ColorMode, std::vector<ui::RenderIntent>>& hdrAndRenderIntents,
+        const std::unordered_map<ColorMode, std::vector<RenderIntent>>& hwcColorModes,
         int initialPowerMode)
     : lastCompositionHadVisibleLayers(false),
       mFlinger(flinger),
@@ -105,13 +250,11 @@
       mHasHdr10(false),
       mHasHLG(false),
       mHasDolbyVision(false),
-      mSupportedPerFrameMetadata(supportedPerFrameMetadata),
-      mHasBT2100PQColorimetric(false),
-      mHasBT2100PQEnhance(false),
-      mHasBT2100HLGColorimetric(false),
-      mHasBT2100HLGEnhance(false)
+      mSupportedPerFrameMetadata(supportedPerFrameMetadata)
 {
     // clang-format on
+    populateColorModes(hwcColorModes);
+
     std::vector<Hdr> types = hdrCapabilities.getSupportedHdrTypes();
     for (Hdr hdrType : types) {
         switch (hdrType) {
@@ -149,18 +292,6 @@
     }
     mHdrCapabilities = HdrCapabilities(types, maxLuminance, maxAverageLuminance, minLuminance);
 
-    auto iter = hdrAndRenderIntents.find(ColorMode::BT2100_PQ);
-    if (iter != hdrAndRenderIntents.end()) {
-        hasToneMapping(iter->second,
-                       &mHasBT2100PQColorimetric, &mHasBT2100PQEnhance);
-    }
-
-    iter = hdrAndRenderIntents.find(ColorMode::BT2100_HLG);
-    if (iter != hdrAndRenderIntents.end()) {
-        hasToneMapping(iter->second,
-                       &mHasBT2100HLGColorimetric, &mHasBT2100HLGEnhance);
-    }
-
     // initialize the display orientation transform.
     setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
 }
@@ -545,20 +676,88 @@
     result.append(surfaceDump);
 }
 
-void DisplayDevice::hasToneMapping(const std::vector<RenderIntent>& renderIntents,
-                                   bool* outColorimetric, bool *outEnhance) {
-    for (auto intent : renderIntents) {
-        switch (intent) {
-            case RenderIntent::TONE_MAP_COLORIMETRIC:
-                *outColorimetric = true;
-                break;
-            case RenderIntent::TONE_MAP_ENHANCE:
-                *outEnhance = true;
-                break;
-            default:
-                break;
+// Map dataspace/intent to the best matched dataspace/colorMode/renderIntent
+// supported by HWC.
+void DisplayDevice::addColorMode(
+        const std::unordered_map<ColorMode, std::vector<RenderIntent>>& hwcColorModes,
+        const ColorMode mode, const RenderIntent intent) {
+    // find the best color mode
+    const ColorMode hwcColorMode = getHwcColorMode(hwcColorModes, mode);
+
+    // find the best render intent
+    auto iter = hwcColorModes.find(hwcColorMode);
+    const auto& hwcIntents =
+            iter != hwcColorModes.end() ? iter->second : std::vector<RenderIntent>();
+    const RenderIntent hwcIntent = getHwcRenderIntent(hwcIntents, intent);
+
+    const Dataspace dataspace = colorModeToDataspace(mode);
+    const Dataspace hwcDataspace = colorModeToDataspace(hwcColorMode);
+
+    ALOGV("DisplayDevice %d/%d: map (%s, %s) to (%s, %s, %s)", mType, mHwcDisplayId,
+          dataspaceDetails(static_cast<android_dataspace_t>(dataspace)).c_str(),
+          decodeRenderIntent(intent).c_str(),
+          dataspaceDetails(static_cast<android_dataspace_t>(hwcDataspace)).c_str(),
+          decodeColorMode(hwcColorMode).c_str(), decodeRenderIntent(hwcIntent).c_str());
+
+    mColorModes[getColorModeKey(dataspace, intent)] = {hwcDataspace, hwcColorMode, hwcIntent};
+}
+
+void DisplayDevice::populateColorModes(
+        const std::unordered_map<ColorMode, std::vector<RenderIntent>>& hwcColorModes) {
+    if (!hasWideColorGamut()) {
+        return;
+    }
+
+    // add known SDR combinations
+    for (auto intent : sSdrRenderIntents) {
+        for (auto mode : sSdrColorModes) {
+            addColorMode(hwcColorModes, mode, intent);
         }
     }
+
+    // add known HDR combinations
+    for (auto intent : sHdrRenderIntents) {
+        for (auto mode : sHdrColorModes) {
+            addColorMode(hwcColorModes, mode, intent);
+        }
+    }
+}
+
+bool DisplayDevice::hasRenderIntent(RenderIntent intent) const {
+    // assume a render intent is supported when SRGB supports it; we should
+    // get rid of that assumption.
+    auto iter = mColorModes.find(getColorModeKey(Dataspace::SRGB, intent));
+    return iter != mColorModes.end() && iter->second.renderIntent == intent;
+}
+
+bool DisplayDevice::hasModernHdrSupport(Dataspace dataspace) const {
+    if ((dataspace == Dataspace::BT2020_PQ && hasHDR10Support()) ||
+        (dataspace == Dataspace::BT2020_HLG && hasHLGSupport())) {
+        auto iter =
+                mColorModes.find(getColorModeKey(dataspace, RenderIntent::TONE_MAP_COLORIMETRIC));
+        return iter != mColorModes.end() && iter->second.dataspace == dataspace;
+    }
+
+    return false;
+}
+
+void DisplayDevice::getBestColorMode(Dataspace dataspace, RenderIntent intent,
+                                     Dataspace* outDataspace, ColorMode* outMode,
+                                     RenderIntent* outIntent) const {
+    auto iter = mColorModes.find(getColorModeKey(dataspace, intent));
+    if (iter != mColorModes.end()) {
+        *outDataspace = iter->second.dataspace;
+        *outMode = iter->second.colorMode;
+        *outIntent = iter->second.renderIntent;
+    } else {
+        ALOGE("map unknown (%s)/(%s) to default color mode",
+              dataspaceDetails(static_cast<android_dataspace_t>(dataspace)).c_str(),
+              decodeRenderIntent(intent).c_str());
+
+        *outDataspace = Dataspace::UNKNOWN;
+        *outMode = ColorMode::NATIVE;
+        *outIntent = RenderIntent::COLORIMETRIC;
+    }
 }
 
 std::atomic<int32_t> DisplayDeviceState::nextDisplayId(1);
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 883f533..b3859b6 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -91,7 +91,7 @@
             bool hasWideColorGamut,
             const HdrCapabilities& hdrCapabilities,
             const int32_t supportedPerFrameMetadata,
-            const std::unordered_map<ui::ColorMode, std::vector<ui::RenderIntent>>& hdrAndRenderIntents,
+            const std::unordered_map<ui::ColorMode, std::vector<ui::RenderIntent>>& hwcColorModes,
             int initialPowerMode);
     // clang-format on
 
@@ -143,11 +143,17 @@
     // machine happy without actually queueing a buffer if nothing has changed
     status_t beginFrame(bool mustRecompose) const;
     status_t prepareFrame(HWComposer& hwc);
+
     bool hasWideColorGamut() const { return mHasWideColorGamut; }
     // Whether h/w composer has native support for specific HDR type.
     bool hasHDR10Support() const { return mHasHdr10; }
     bool hasHLGSupport() const { return mHasHLG; }
     bool hasDolbyVisionSupport() const { return mHasDolbyVision; }
+
+    // Return true if the corresponding color mode for the HDR dataspace is
+    // supported.
+    bool hasModernHdrSupport(ui::Dataspace dataspace) const;
+
     // The returned HdrCapabilities is the combination of HDR capabilities from
     // hardware composer and RenderEngine. When the DisplayDevice supports wide
     // color gamut, RenderEngine is able to simulate HDR support in Display P3
@@ -156,13 +162,12 @@
     // respectively if hardware composer doesn't return meaningful values.
     const HdrCapabilities& getHdrCapabilities() const { return mHdrCapabilities; }
 
-    // Whether h/w composer has BT2100_PQ color mode.
-    bool hasBT2100PQColorimetricSupport() const { return mHasBT2100PQColorimetric; }
-    bool hasBT2100PQEnhanceSupport() const { return mHasBT2100PQEnhance; }
+    // Return true if intent is supported by the display.
+    bool hasRenderIntent(ui::RenderIntent intent) const;
 
-    // Whether h/w composer has BT2100_HLG color mode.
-    bool hasBT2100HLGColorimetricSupport() const { return mHasBT2100HLGColorimetric; }
-    bool hasBT2100HLGEnhanceSupport() const { return mHasBT2100HLGEnhance; }
+    void getBestColorMode(ui::Dataspace dataspace, ui::RenderIntent intent,
+                          ui::Dataspace* outDataspace, ui::ColorMode* outMode,
+                          ui::RenderIntent* outIntent) const;
 
     void swapBuffers(HWComposer& hwc) const;
 
@@ -214,9 +219,6 @@
     void dump(String8& result) const;
 
 private:
-    void hasToneMapping(const std::vector<ui::RenderIntent>& renderIntents,
-                        bool* outColorimetric, bool *outEnhance);
-
     /*
      *  Constants, set during initialization
      */
@@ -288,12 +290,26 @@
     bool mHasDolbyVision;
     HdrCapabilities mHdrCapabilities;
     const int32_t mSupportedPerFrameMetadata;
-    // Whether h/w composer has BT2100_PQ and BT2100_HLG color mode with
-    // colorimetrical tone mapping or enhanced tone mapping.
-    bool mHasBT2100PQColorimetric;
-    bool mHasBT2100PQEnhance;
-    bool mHasBT2100HLGColorimetric;
-    bool mHasBT2100HLGEnhance;
+
+    // Mappings from desired Dataspace/RenderIntent to the supported
+    // Dataspace/ColorMode/RenderIntent.
+    using ColorModeKey = uint64_t;
+    struct ColorModeValue {
+        ui::Dataspace dataspace;
+        ui::ColorMode colorMode;
+        ui::RenderIntent renderIntent;
+    };
+
+    static ColorModeKey getColorModeKey(ui::Dataspace dataspace, ui::RenderIntent intent) {
+        return (static_cast<uint64_t>(dataspace) << 32) | static_cast<uint32_t>(intent);
+    }
+    void populateColorModes(
+            const std::unordered_map<ui::ColorMode, std::vector<ui::RenderIntent>>& hwcColorModes);
+    void addColorMode(
+            const std::unordered_map<ui::ColorMode, std::vector<ui::RenderIntent>>& hwcColorModes,
+            const ui::ColorMode mode, const ui::RenderIntent intent);
+
+    std::unordered_map<ColorModeKey, ColorModeValue> mColorModes;
 };
 
 struct DisplayDeviceState {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e7892ef..e7e3eb3 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1868,7 +1868,6 @@
 // can only be one of
 //  - Dataspace::SRGB (use legacy dataspace and let HWC saturate when colors are enhanced)
 //  - Dataspace::DISPLAY_P3
-//  - Dataspace::V0_SCRGB_LINEAR
 // The returned HDR data space is one of
 //  - Dataspace::UNKNOWN
 //  - Dataspace::BT2020_HLG
@@ -1882,12 +1881,8 @@
         switch (layer->getDataSpace()) {
             case Dataspace::V0_SCRGB:
             case Dataspace::V0_SCRGB_LINEAR:
-                bestDataSpace = Dataspace::V0_SCRGB_LINEAR;
-                break;
             case Dataspace::DISPLAY_P3:
-                if (bestDataSpace == Dataspace::SRGB) {
-                    bestDataSpace = Dataspace::DISPLAY_P3;
-                }
+                bestDataSpace = Dataspace::DISPLAY_P3;
                 break;
             case Dataspace::BT2020_PQ:
             case Dataspace::BT2020_ITU_PQ:
@@ -1923,104 +1918,17 @@
     Dataspace hdrDataSpace;
     Dataspace bestDataSpace = getBestDataspace(displayDevice, &hdrDataSpace);
 
-    if (hdrDataSpace == Dataspace::BT2020_PQ) {
-        // Hardware composer can handle BT2100 ColorMode only when
-        // - colorimetrical tone mapping is supported, or
-        // - Auto mode is turned on and enhanced tone mapping is supported.
-        if (displayDevice->hasBT2100PQColorimetricSupport() ||
-            (mDisplayColorSetting == DisplayColorSetting::ENHANCED &&
-             displayDevice->hasBT2100PQEnhanceSupport())) {
-            *outMode = ColorMode::BT2100_PQ;
-            *outDataSpace = Dataspace::BT2020_PQ;
-        } else if (displayDevice->hasHDR10Support()) {
-            // Legacy HDR support.  HDR layers are treated as UNKNOWN layers.
-            hdrDataSpace = Dataspace::UNKNOWN;
-        } else {
-            // Simulate PQ through RenderEngine, pick DISPLAY_P3 color mode.
-            *outMode = ColorMode::DISPLAY_P3;
-            *outDataSpace = Dataspace::DISPLAY_P3;
-        }
-    } else if (hdrDataSpace == Dataspace::BT2020_HLG) {
-        if (displayDevice->hasBT2100HLGColorimetricSupport() ||
-            (mDisplayColorSetting == DisplayColorSetting::ENHANCED &&
-             displayDevice->hasBT2100HLGEnhanceSupport())) {
-            *outMode = ColorMode::BT2100_HLG;
-            *outDataSpace = Dataspace::BT2020_HLG;
-        } else if (displayDevice->hasHLGSupport()) {
-            // Legacy HDR support.  HDR layers are treated as UNKNOWN layers.
-            hdrDataSpace = Dataspace::UNKNOWN;
-        } else {
-            // Simulate HLG through RenderEngine, pick DISPLAY_P3 color mode.
-            *outMode = ColorMode::DISPLAY_P3;
-            *outDataSpace = Dataspace::DISPLAY_P3;
-        }
+    RenderIntent intent = mDisplayColorSetting == DisplayColorSetting::ENHANCED ?
+        RenderIntent::ENHANCE : RenderIntent::COLORIMETRIC;
+
+    // respect hdrDataSpace only when there is modern HDR support
+    if (hdrDataSpace != Dataspace::UNKNOWN && displayDevice->hasModernHdrSupport(hdrDataSpace)) {
+        bestDataSpace = hdrDataSpace;
+        intent = mDisplayColorSetting == DisplayColorSetting::ENHANCED ?
+            RenderIntent::TONE_MAP_ENHANCE : RenderIntent::TONE_MAP_COLORIMETRIC;
     }
 
-    // At this point, there's no HDR layer.
-    if (hdrDataSpace == Dataspace::UNKNOWN) {
-        switch (bestDataSpace) {
-            case Dataspace::DISPLAY_P3:
-            case Dataspace::V0_SCRGB_LINEAR:
-                *outMode = ColorMode::DISPLAY_P3;
-                *outDataSpace = Dataspace::DISPLAY_P3;
-                break;
-            default:
-                *outMode = ColorMode::SRGB;
-                *outDataSpace = Dataspace::SRGB;
-                break;
-        }
-    }
-    *outRenderIntent = pickRenderIntent(displayDevice, *outMode);
-}
-
-RenderIntent SurfaceFlinger::pickRenderIntent(const sp<DisplayDevice>& displayDevice,
-                                              ColorMode colorMode) const {
-    // Native Mode means the display is not color managed, and whichever
-    // render intent is picked doesn't matter, thus return
-    // RenderIntent::COLORIMETRIC as default here.
-    if (mDisplayColorSetting == DisplayColorSetting::UNMANAGED) {
-        return RenderIntent::COLORIMETRIC;
-    }
-
-    // In Auto Color Mode, we want to strech to panel color space, right now
-    // only the built-in display supports it.
-    if (mDisplayColorSetting == DisplayColorSetting::ENHANCED &&
-        mBuiltinDisplaySupportsEnhance &&
-        displayDevice->getDisplayType() == DisplayDevice::DISPLAY_PRIMARY) {
-        switch (colorMode) {
-            case ColorMode::DISPLAY_P3:
-            case ColorMode::SRGB:
-                return RenderIntent::ENHANCE;
-            // In Auto Color Mode, BT2100_PQ and BT2100_HLG will only be picked
-            // when TONE_MAP_ENHANCE or TONE_MAP_COLORIMETRIC is supported.
-            // If TONE_MAP_ENHANCE is not supported, fall back to TONE_MAP_COLORIMETRIC.
-            case ColorMode::BT2100_PQ:
-                return displayDevice->hasBT2100PQEnhanceSupport() ?
-                    RenderIntent::TONE_MAP_ENHANCE : RenderIntent::TONE_MAP_COLORIMETRIC;
-            case ColorMode::BT2100_HLG:
-                return displayDevice->hasBT2100HLGEnhanceSupport() ?
-                    RenderIntent::TONE_MAP_ENHANCE : RenderIntent::TONE_MAP_COLORIMETRIC;
-            // This statement shouldn't be reached, switch cases will always
-            // cover all possible ColorMode returned by pickColorMode.
-            default:
-                return RenderIntent::COLORIMETRIC;
-        }
-    }
-
-    // Either enhance is not supported or we are in natural mode.
-
-    // Natural Mode means it's color managed and the color must be right,
-    // thus we pick RenderIntent::COLORIMETRIC as render intent for non-HDR
-    // content and pick RenderIntent::TONE_MAP_COLORIMETRIC for HDR content.
-    switch (colorMode) {
-        // In Natural Color Mode, BT2100_PQ and BT2100_HLG will only be picked
-        // when TONE_MAP_COLORIMETRIC is supported.
-        case ColorMode::BT2100_PQ:
-        case ColorMode::BT2100_HLG:
-            return RenderIntent::TONE_MAP_COLORIMETRIC;
-        default:
-            return RenderIntent::COLORIMETRIC;
-    }
+    displayDevice->getBestColorMode(bestDataSpace, intent, outDataSpace, outMode, outRenderIntent);
 }
 
 void SurfaceFlinger::setUpHWComposer() {
@@ -2332,7 +2240,7 @@
         const wp<IBinder>& display, int hwcId, const DisplayDeviceState& state,
         const sp<DisplaySurface>& dispSurface, const sp<IGraphicBufferProducer>& producer) {
     bool hasWideColorGamut = false;
-    std::unordered_map<ColorMode, std::vector<RenderIntent>> hdrAndRenderIntents;
+    std::unordered_map<ColorMode, std::vector<RenderIntent>> hwcColorModes;
 
     if (hasWideColorDisplay) {
         std::vector<ColorMode> modes = getHwComposer().getColorModes(hwcId);
@@ -2349,18 +2257,7 @@
 
             std::vector<RenderIntent> renderIntents = getHwComposer().getRenderIntents(hwcId,
                                                                                        colorMode);
-            if (state.type == DisplayDevice::DISPLAY_PRIMARY) {
-                for (auto intent : renderIntents) {
-                    if (intent == RenderIntent::ENHANCE) {
-                        mBuiltinDisplaySupportsEnhance = true;
-                        break;
-                    }
-                }
-            }
-
-            if (colorMode == ColorMode::BT2100_PQ || colorMode == ColorMode::BT2100_HLG) {
-                hdrAndRenderIntents.emplace(colorMode, renderIntents);
-            }
+            hwcColorModes.emplace(colorMode, renderIntents);
         }
     }
 
@@ -2400,17 +2297,21 @@
                               dispSurface, std::move(renderSurface), displayWidth, displayHeight,
                               hasWideColorGamut, hdrCapabilities,
                               getHwComposer().getSupportedPerFrameMetadata(hwcId),
-                              hdrAndRenderIntents, initialPowerMode);
+                              hwcColorModes, initialPowerMode);
 
     if (maxFrameBufferAcquiredBuffers >= 3) {
         nativeWindowSurface->preallocateBuffers();
     }
 
+    if (hw->isPrimary() && hw->hasRenderIntent(RenderIntent::ENHANCE)) {
+        mBuiltinDisplaySupportsEnhance = true;
+    }
+
     ColorMode defaultColorMode = ColorMode::NATIVE;
     Dataspace defaultDataSpace = Dataspace::UNKNOWN;
     if (hasWideColorGamut) {
         defaultColorMode = ColorMode::SRGB;
-        defaultDataSpace = Dataspace::V0_SRGB;
+        defaultDataSpace = Dataspace::SRGB;
     }
     setActiveColorModeInternal(hw, defaultColorMode, defaultDataSpace,
                                RenderIntent::COLORIMETRIC);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index d9cf946..f889beb 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -664,8 +664,6 @@
                        ui::ColorMode* outMode,
                        ui::Dataspace* outDataSpace,
                        ui::RenderIntent* outRenderIntent) const;
-    ui::RenderIntent pickRenderIntent(const sp<DisplayDevice>& displayDevice,
-                                      ui::ColorMode colorMode) const;
 
     void setUpHWComposer();
     void doComposition();