From 28f24d0ab481bd9c6fd5618414fee694e837c5c6 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Tue, 12 Jul 2016 13:30:53 -0700 Subject: [PATCH] Color transforms are now color modes. Rename color transforms to color modes for all interfaces exposed to surfaceflinger clients. Also split it out to be a separate configuration value from display modes. Bug: 29044347 Change-Id: I87e937f7c954a50c946e8e2c606797caa416c5d8 --- include/gui/ISurfaceComposer.h | 9 ++ include/gui/SurfaceComposerClient.h | 10 ++ include/ui/DisplayInfo.h | 1 - libs/gui/ISurfaceComposer.cpp | 128 +++++++++++++++++++++ libs/gui/SurfaceComposerClient.cpp | 16 +++ services/surfaceflinger/DisplayDevice.cpp | 11 ++ services/surfaceflinger/DisplayDevice.h | 9 ++ services/surfaceflinger/DisplayHardware/HWC2.cpp | 9 +- services/surfaceflinger/DisplayHardware/HWC2.h | 4 +- .../DisplayHardware/HWC2On1Adapter.cpp | 78 +++++++------ .../DisplayHardware/HWC2On1Adapter.h | 21 ++-- .../surfaceflinger/DisplayHardware/HWComposer.cpp | 25 +++- .../surfaceflinger/DisplayHardware/HWComposer.h | 4 +- .../DisplayHardware/HWComposer_hwc1.cpp | 13 ++- .../DisplayHardware/HWComposer_hwc1.h | 13 ++- services/surfaceflinger/SurfaceFlinger.cpp | 109 ++++++++++++++++-- services/surfaceflinger/SurfaceFlinger.h | 19 +++ services/surfaceflinger/SurfaceFlinger_hwc1.cpp | 68 ++++++++--- 18 files changed, 465 insertions(+), 82 deletions(-) diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h index af26721b35..74a4123bb6 100644 --- a/include/gui/ISurfaceComposer.h +++ b/include/gui/ISurfaceComposer.h @@ -137,6 +137,12 @@ public: * should be used */ virtual status_t setActiveConfig(const sp& display, int id) = 0; + virtual status_t getDisplayColorModes(const sp& display, + Vector* outColorModes) = 0; + virtual android_color_mode_t getActiveColorMode(const sp& display) = 0; + virtual status_t setActiveColorMode(const sp& display, + android_color_mode_t colorMode) = 0; + /* Capture the specified screen. requires READ_FRAME_BUFFER permission * This function will fail if there is a secure window on screen. */ @@ -193,6 +199,9 @@ public: SET_POWER_MODE, GET_DISPLAY_STATS, GET_HDR_CAPABILITIES, + GET_DISPLAY_COLOR_MODES, + GET_ACTIVE_COLOR_MODE, + SET_ACTIVE_COLOR_MODE, }; virtual status_t onTransact(uint32_t code, const Parcel& data, diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h index 95e8b70c61..b8ee331736 100644 --- a/include/gui/SurfaceComposerClient.h +++ b/include/gui/SurfaceComposerClient.h @@ -83,6 +83,16 @@ public: // returned by getDisplayInfo static status_t setActiveConfig(const sp& display, int id); + // Gets the list of supported color modes for the given display + static status_t getDisplayColorModes(const sp& display, + Vector* outColorModes); + + // Gets the active color mode for the given display + static android_color_mode_t getActiveColorMode(const sp& display); + + // Sets the active color mode for the given display + static status_t setActiveColorMode(const sp& display, android_color_mode_t colorMode); + /* Triggers screen on/off or low power mode and waits for it to complete */ static void setDisplayPowerMode(const sp& display, int mode); diff --git a/include/ui/DisplayInfo.h b/include/ui/DisplayInfo.h index ad73ee72f9..799944f3ee 100644 --- a/include/ui/DisplayInfo.h +++ b/include/ui/DisplayInfo.h @@ -36,7 +36,6 @@ struct DisplayInfo { bool secure; nsecs_t appVsyncOffset; nsecs_t presentationDeadline; - int colorTransform; }; /* Display orientations as defined in Surface.java and ISurfaceComposer.h. */ diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index a8b4fa8226..f0b0ada270 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -32,6 +32,8 @@ #include +#include + #include #include #include @@ -269,6 +271,82 @@ public: return reply.readInt32(); } + virtual status_t getDisplayColorModes(const sp& display, + Vector* outColorModes) { + Parcel data, reply; + status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + if (result != NO_ERROR) { + ALOGE("getDisplayColorModes failed to writeInterfaceToken: %d", result); + return result; + } + result = data.writeStrongBinder(display); + if (result != NO_ERROR) { + ALOGE("getDisplayColorModes failed to writeStrongBinder: %d", result); + return result; + } + result = remote()->transact(BnSurfaceComposer::GET_DISPLAY_COLOR_MODES, data, &reply); + if (result != NO_ERROR) { + ALOGE("getDisplayColorModes failed to transact: %d", result); + return result; + } + result = static_cast(reply.readInt32()); + if (result == NO_ERROR) { + size_t numModes = reply.readUint32(); + outColorModes->clear(); + outColorModes->resize(numModes); + for (size_t i = 0; i < numModes; ++i) { + outColorModes->replaceAt(static_cast(reply.readInt32()), i); + } + } + return result; + } + + virtual android_color_mode_t getActiveColorMode(const sp& display) { + Parcel data, reply; + status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + if (result != NO_ERROR) { + ALOGE("getActiveColorMode failed to writeInterfaceToken: %d", result); + return static_cast(result); + } + result = data.writeStrongBinder(display); + if (result != NO_ERROR) { + ALOGE("getActiveColorMode failed to writeStrongBinder: %d", result); + return static_cast(result); + } + result = remote()->transact(BnSurfaceComposer::GET_ACTIVE_COLOR_MODE, data, &reply); + if (result != NO_ERROR) { + ALOGE("getActiveColorMode failed to transact: %d", result); + return static_cast(result); + } + return static_cast(reply.readInt32()); + } + + virtual status_t setActiveColorMode(const sp& display, + android_color_mode_t colorMode) { + Parcel data, reply; + status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + if (result != NO_ERROR) { + ALOGE("setActiveColorMode failed to writeInterfaceToken: %d", result); + return result; + } + result = data.writeStrongBinder(display); + if (result != NO_ERROR) { + ALOGE("setActiveColorMode failed to writeStrongBinder: %d", result); + return result; + } + result = data.writeInt32(colorMode); + if (result != NO_ERROR) { + ALOGE("setActiveColorMode failed to writeInt32: %d", result); + return result; + } + result = remote()->transact(BnSurfaceComposer::SET_ACTIVE_COLOR_MODE, data, &reply); + if (result != NO_ERROR) { + ALOGE("setActiveColorMode failed to transact: %d", result); + return result; + } + return static_cast(reply.readInt32()); + } + virtual status_t clearAnimationFrameStats() { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); @@ -469,6 +547,56 @@ status_t BnSurfaceComposer::onTransact( reply->writeInt32(result); return NO_ERROR; } + case GET_DISPLAY_COLOR_MODES: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + Vector colorModes; + sp display = nullptr; + status_t result = data.readStrongBinder(&display); + if (result != NO_ERROR) { + ALOGE("getDisplayColorModes failed to readStrongBinder: %d", result); + return result; + } + result = getDisplayColorModes(display, &colorModes); + reply->writeInt32(result); + if (result == NO_ERROR) { + reply->writeUint32(static_cast(colorModes.size())); + for (size_t i = 0; i < colorModes.size(); ++i) { + reply->writeInt32(colorModes[i]); + } + } + return NO_ERROR; + } + case GET_ACTIVE_COLOR_MODE: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + sp display = nullptr; + status_t result = data.readStrongBinder(&display); + if (result != NO_ERROR) { + ALOGE("getActiveColorMode failed to readStrongBinder: %d", result); + return result; + } + android_color_mode_t colorMode = getActiveColorMode(display); + result = reply->writeInt32(static_cast(colorMode)); + return result; + } + case SET_ACTIVE_COLOR_MODE: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + sp display = nullptr; + status_t result = data.readStrongBinder(&display); + if (result != NO_ERROR) { + ALOGE("getActiveColorMode failed to readStrongBinder: %d", result); + return result; + } + int32_t colorModeInt = 0; + result = data.readInt32(&colorModeInt); + if (result != NO_ERROR) { + ALOGE("setActiveColorMode failed to readInt32: %d", result); + return result; + } + result = setActiveColorMode(display, + static_cast(colorModeInt)); + result = reply->writeInt32(result); + return result; + } case CLEAR_ANIMATION_FRAME_STATS: { CHECK_INTERFACE(ISurfaceComposer, data, reply); status_t result = clearAnimationFrameStats(); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 26b2209e6a..3df5f74fc9 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -29,6 +29,8 @@ #include #include +#include + #include #include @@ -771,6 +773,20 @@ status_t SurfaceComposerClient::setActiveConfig(const sp& display, int return ComposerService::getComposerService()->setActiveConfig(display, id); } +status_t SurfaceComposerClient::getDisplayColorModes(const sp& display, + Vector* outColorModes) { + return ComposerService::getComposerService()->getDisplayColorModes(display, outColorModes); +} + +android_color_mode_t SurfaceComposerClient::getActiveColorMode(const sp& display) { + return ComposerService::getComposerService()->getActiveColorMode(display); +} + +status_t SurfaceComposerClient::setActiveColorMode(const sp& display, + android_color_mode_t colorMode) { + return ComposerService::getComposerService()->setActiveColorMode(display, colorMode); +} + void SurfaceComposerClient::setDisplayPowerMode(const sp& token, int mode) { ComposerService::getComposerService()->setPowerMode(token, mode); diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index a67b3ffa22..5c2c0adf3a 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -415,6 +415,17 @@ int DisplayDevice::getActiveConfig() const { } // ---------------------------------------------------------------------------- +#ifdef USE_HWC2 +void DisplayDevice::setActiveColorMode(android_color_mode_t mode) { + mActiveColorMode = mode; +} + +android_color_mode_t DisplayDevice::getActiveColorMode() const { + return mActiveColorMode; +} +#endif + +// ---------------------------------------------------------------------------- void DisplayDevice::setLayerStack(uint32_t stack) { mLayerStack = stack; diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index dd9b104f4e..105e980ab4 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -182,6 +182,11 @@ public: void setPowerMode(int mode); bool isDisplayOn() const; +#ifdef USE_HWC2 + android_color_mode_t getActiveColorMode() const; + void setActiveColorMode(android_color_mode_t mode); +#endif + /* ------------------------------------------------------------------------ * Display active config management. */ @@ -252,6 +257,10 @@ private: int mPowerMode; // Current active config int mActiveConfig; +#ifdef USE_HWC2 + // current active color mode + android_color_mode_t mActiveColorMode; +#endif }; }; // namespace android diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index 87a0e9a13a..4fe3cfd03e 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -581,7 +581,7 @@ Error Display::getChangedCompositionTypes( return Error::None; } -Error Display::getColorModes(std::vector* outModes) const +Error Display::getColorModes(std::vector* outModes) const { uint32_t numModes = 0; int32_t intError = mDevice.mGetColorModes(mDevice.mHwcDevice, mId, @@ -599,7 +599,10 @@ Error Display::getColorModes(std::vector* outModes) const return error; } - std::swap(*outModes, modes); + outModes->resize(numModes); + for (size_t i = 0; i < numModes; i++) { + (*outModes)[i] = static_cast(modes[i]); + } return Error::None; } @@ -805,7 +808,7 @@ Error Display::setClientTarget(buffer_handle_t target, return static_cast(intError); } -Error Display::setColorMode(int32_t mode) +Error Display::setColorMode(android_color_mode_t mode) { int32_t intError = mDevice.mSetColorMode(mDevice.mHwcDevice, mId, mode); return static_cast(intError); diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h index beb7bc6689..fb04af877e 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.h +++ b/services/surfaceflinger/DisplayHardware/HWC2.h @@ -282,7 +282,7 @@ public: [[clang::warn_unused_result]] Error getChangedCompositionTypes( std::unordered_map, Composition>* outTypes); [[clang::warn_unused_result]] Error getColorModes( - std::vector* outModes) const; + std::vector* outModes) const; // Doesn't call into the HWC2 device, so no errors are possible std::vector> getConfigs() const; @@ -307,7 +307,7 @@ public: buffer_handle_t target, const android::sp& acquireFence, android_dataspace_t dataspace); - [[clang::warn_unused_result]] Error setColorMode(int32_t mode); + [[clang::warn_unused_result]] Error setColorMode(android_color_mode_t mode); [[clang::warn_unused_result]] Error setColorTransform( const android::mat4& matrix, android_color_transform_t hint); [[clang::warn_unused_result]] Error setOutputBuffer( diff --git a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp index e739ef45f5..8bcee39b9d 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp @@ -75,7 +75,7 @@ static hwc2_function_pointer_t asFP(T function) using namespace HWC2; -static constexpr Attribute ColorTransform = static_cast(6); +static constexpr Attribute ColorMode = static_cast(6); namespace android { @@ -268,9 +268,7 @@ hwc2_function_pointer_t HWC2On1Adapter::doGetFunction( &Display::setClientTarget, buffer_handle_t, int32_t, int32_t, hwc_region_t>); case FunctionDescriptor::SetColorMode: - return asFP( - displayHook); + return asFP(setColorModeHook); case FunctionDescriptor::SetColorTransform: return asFP(setColorTransformHook); case FunctionDescriptor::SetOutputBuffer: @@ -894,7 +892,7 @@ Error HWC2On1Adapter::Display::setClientTarget(buffer_handle_t target, return Error::None; } -Error HWC2On1Adapter::Display::setColorMode(int32_t mode) +Error HWC2On1Adapter::Display::setColorMode(android_color_mode_t mode) { std::unique_lock lock (mStateMutex); @@ -1198,11 +1196,14 @@ void HWC2On1Adapter::Display::populateConfigs() newConfig->setAttribute(Attribute::DpiY, values[attributeMap[HWC_DISPLAY_DPI_Y]]); if (hasColor) { - newConfig->setAttribute(ColorTransform, + // In HWC1, color modes are referred to as color transforms. To avoid confusion with + // the HWC2 concept of color transforms, we internally refer to them as color modes for + // both HWC1 and 2. + newConfig->setAttribute(ColorMode, values[attributeMap[HWC_DISPLAY_COLOR_TRANSFORM]]); } - // We can only do this after attempting to read the color transform + // We can only do this after attempting to read the color mode newConfig->setHwc1Id(hwc1ConfigId); for (auto& existingConfig : mConfigs) { @@ -1678,8 +1679,8 @@ int32_t HWC2On1Adapter::Display::Config::getAttribute(Attribute attribute) const void HWC2On1Adapter::Display::Config::setHwc1Id(uint32_t id) { - int32_t colorTransform = getAttribute(ColorTransform); - mHwc1Ids.emplace(colorTransform, id); + android_color_mode_t colorMode = static_cast(getAttribute(ColorMode)); + mHwc1Ids.emplace(colorMode, id); } bool HWC2On1Adapter::Display::Config::hasHwc1Id(uint32_t id) const @@ -1692,18 +1693,20 @@ bool HWC2On1Adapter::Display::Config::hasHwc1Id(uint32_t id) const return false; } -int32_t HWC2On1Adapter::Display::Config::getColorModeForHwc1Id( - uint32_t id) const +Error HWC2On1Adapter::Display::Config::getColorModeForHwc1Id( + uint32_t id, android_color_mode_t* outMode) const { for (const auto& idPair : mHwc1Ids) { if (id == idPair.second) { - return idPair.first; + *outMode = idPair.first; + return Error::None; } } - return -1; + ALOGE("Unable to find color mode for HWC ID %" PRIu32 " on config %u", id, mId); + return Error::BadParameter; } -Error HWC2On1Adapter::Display::Config::getHwc1IdForColorMode(int32_t mode, +Error HWC2On1Adapter::Display::Config::getHwc1IdForColorMode(android_color_mode_t mode, uint32_t* outId) const { for (const auto& idPair : mHwc1Ids) { @@ -1726,25 +1729,26 @@ bool HWC2On1Adapter::Display::Config::merge(const Config& other) return false; } } - int32_t otherColorTransform = other.getAttribute(ColorTransform); - if (mHwc1Ids.count(otherColorTransform) != 0) { + android_color_mode_t otherColorMode = + static_cast(other.getAttribute(ColorMode)); + if (mHwc1Ids.count(otherColorMode) != 0) { ALOGE("Attempted to merge two configs (%u and %u) which appear to be " - "identical", mHwc1Ids.at(otherColorTransform), - other.mHwc1Ids.at(otherColorTransform)); + "identical", mHwc1Ids.at(otherColorMode), + other.mHwc1Ids.at(otherColorMode)); return false; } - mHwc1Ids.emplace(otherColorTransform, - other.mHwc1Ids.at(otherColorTransform)); + mHwc1Ids.emplace(otherColorMode, + other.mHwc1Ids.at(otherColorMode)); return true; } -std::set HWC2On1Adapter::Display::Config::getColorTransforms() const +std::set HWC2On1Adapter::Display::Config::getColorModes() const { - std::set colorTransforms; + std::set colorModes; for (const auto& idPair : mHwc1Ids) { - colorTransforms.emplace(idPair.first); + colorModes.emplace(idPair.first); } - return colorTransforms; + return colorModes; } std::string HWC2On1Adapter::Display::Config::toString(bool splitLine) const @@ -1787,15 +1791,15 @@ std::string HWC2On1Adapter::Display::Config::toString(bool splitLine) const for (const auto& id : mHwc1Ids) { - int32_t colorTransform = id.first; + android_color_mode_t colorMode = id.first; uint32_t hwc1Id = id.second; std::memset(buffer, 0, BUFFER_SIZE); - if (colorTransform == mDisplay.mActiveColorMode) { + if (colorMode == mDisplay.mActiveColorMode) { writtenBytes = snprintf(buffer, BUFFER_SIZE, " [%u/%d]", hwc1Id, - colorTransform); + colorMode); } else { writtenBytes = snprintf(buffer, BUFFER_SIZE, " %u/%d", hwc1Id, - colorTransform); + colorMode); } output.append(buffer, writtenBytes); } @@ -1814,10 +1818,10 @@ std::shared_ptr void HWC2On1Adapter::Display::populateColorModes() { - mColorModes = mConfigs[0]->getColorTransforms(); + mColorModes = mConfigs[0]->getColorModes(); for (const auto& config : mConfigs) { - std::set intersection; - auto configModes = config->getColorTransforms(); + std::set intersection; + auto configModes = config->getColorModes(); std::set_intersection(mColorModes.cbegin(), mColorModes.cend(), configModes.cbegin(), configModes.cend(), std::inserter(intersection, intersection.begin())); @@ -1830,7 +1834,7 @@ void HWC2On1Adapter::Display::initializeActiveConfig() if (mDevice.mHwc1Device->getActiveConfig == nullptr) { ALOGV("getActiveConfig is null, choosing config 0"); mActiveConfig = mConfigs[0]; - mActiveColorMode = -1; + mActiveColorMode = HAL_COLOR_MODE_NATIVE; return; } @@ -1842,7 +1846,13 @@ void HWC2On1Adapter::Display::initializeActiveConfig() ALOGV("Setting active config to %d for HWC1 config %u", config->getId(), activeConfig); mActiveConfig = config; - mActiveColorMode = config->getColorModeForHwc1Id(activeConfig); + if (config->getColorModeForHwc1Id(activeConfig, &mActiveColorMode) != Error::None) { + // This should never happen since we checked for the config's presence before + // setting it as active. + ALOGE("Unable to find color mode for active HWC1 config %d", + config->getId()); + mActiveColorMode = HAL_COLOR_MODE_NATIVE; + } break; } } @@ -1850,7 +1860,7 @@ void HWC2On1Adapter::Display::initializeActiveConfig() ALOGV("Unable to find active HWC1 config %u, defaulting to " "config 0", activeConfig); mActiveConfig = mConfigs[0]; - mActiveColorMode = -1; + mActiveColorMode = HAL_COLOR_MODE_NATIVE; } } } diff --git a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h index dc7c355617..bdacc737c6 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h +++ b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h @@ -213,7 +213,7 @@ private: HWC2::Error setClientTarget(buffer_handle_t target, int32_t acquireFence, int32_t dataspace, hwc_region_t damage); - HWC2::Error setColorMode(int32_t mode); + HWC2::Error setColorMode(android_color_mode_t mode); HWC2::Error setColorTransform(android_color_transform_t hint); HWC2::Error setOutputBuffer(buffer_handle_t buffer, int32_t releaseFence); @@ -258,8 +258,9 @@ private: void setHwc1Id(uint32_t id); bool hasHwc1Id(uint32_t id) const; - int32_t getColorModeForHwc1Id(uint32_t id) const; - HWC2::Error getHwc1IdForColorMode(int32_t mode, + HWC2::Error getColorModeForHwc1Id(uint32_t id, + android_color_mode_t *outMode) const; + HWC2::Error getHwc1IdForColorMode(android_color_mode_t mode, uint32_t* outId) const; void setId(hwc2_config_t id) { mId = id; } @@ -269,7 +270,7 @@ private: // mode. Returns whether the merge was successful bool merge(const Config& other); - std::set getColorTransforms() const; + std::set getColorModes() const; // splitLine divides the output into two lines suitable for // dumpsys SurfaceFlinger @@ -281,7 +282,7 @@ private: std::unordered_map mAttributes; // Maps from color transform to HWC1 config ID - std::unordered_map mHwc1Ids; + std::unordered_map mHwc1Ids; }; class Changes { @@ -378,8 +379,8 @@ private: std::vector> mConfigs; std::shared_ptr mActiveConfig; - std::set mColorModes; - int32_t mActiveColorMode; + std::set mColorModes; + android_color_mode_t mActiveColorMode; std::string mName; HWC2::DisplayType mType; HWC2::PowerMode mPowerMode; @@ -432,6 +433,12 @@ private: hint); } + static int32_t setColorModeHook(hwc2_device_t* device, + hwc2_display_t display, int32_t /*android_color_mode_t*/ intMode) { + auto mode = static_cast(intMode); + return callDisplayFunction(device, display, &Display::setColorMode, mode); + } + static int32_t setPowerModeHook(hwc2_device_t* device, hwc2_display_t display, int32_t intMode) { auto mode = static_cast(intMode); diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 199848f767..4ac58c5984 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -364,8 +364,8 @@ std::shared_ptr return config; } -std::vector HWComposer::getColorModes(int32_t displayId) const { - std::vector modes; +std::vector HWComposer::getColorModes(int32_t displayId) const { + std::vector modes; if (!isValidDisplay(displayId)) { ALOGE("getColorModes: Attempted to access invalid display %d", @@ -379,12 +379,31 @@ std::vector HWComposer::getColorModes(int32_t displayId) const { if (error != HWC2::Error::None) { ALOGE("getColorModes failed for display %d: %s (%d)", displayId, to_string(error).c_str(), static_cast(error)); - return std::vector(); + return std::vector(); } return modes; } +status_t HWComposer::setActiveColorMode(int32_t displayId, android_color_mode_t mode) { + if (!isValidDisplay(displayId)) { + ALOGE("setActiveColorMode: Display %d is not valid", displayId); + return BAD_INDEX; + } + + auto& displayData = mDisplayData[displayId]; + auto error = displayData.hwcDisplay->setColorMode(mode); + if (error != HWC2::Error::None) { + ALOGE("setActiveConfig: Failed to set color mode %d on display %d: " + "%s (%d)", mode, displayId, to_string(error).c_str(), + static_cast(error)); + return UNKNOWN_ERROR; + } + + return NO_ERROR; +} + + void HWComposer::setVsyncEnabled(int32_t disp, HWC2::Vsync enabled) { if (disp < 0 || disp >= HWC_DISPLAY_VIRTUAL) { ALOGD("setVsyncEnabled: Ignoring for virtual display %d", disp); diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 17676ae5f0..41671f62fd 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -154,7 +154,9 @@ public: std::shared_ptr getActiveConfig(int32_t displayId) const; - std::vector getColorModes(int32_t displayId) const; + std::vector getColorModes(int32_t displayId) const; + + status_t setActiveColorMode(int32_t displayId, android_color_mode_t mode); // for debugging ---------------------------------------------------------- void dump(String8& out) const; diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp index 4afd8a2dce..ef416581a2 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp @@ -42,6 +42,8 @@ #include #include +#include + #include "HWComposer.h" #include "../Layer.h" // needed only for debugging @@ -403,7 +405,7 @@ status_t HWComposer::queryDisplayProperties(int disp) { config.ydpi = values[i] / 1000.0f; break; case HWC_DISPLAY_COLOR_TRANSFORM: - config.colorTransform = values[i]; + config.colorMode = static_cast(values[i]); break; default: ALOG_ASSERT(false, "unknown display attribute[%zu] %#x", @@ -519,6 +521,11 @@ nsecs_t HWComposer::getRefreshPeriod(int disp) const { return mDisplayData[disp].configs[currentConfig].refresh; } +android_color_mode_t HWComposer::getColorMode(int disp) const { + size_t currentConfig = mDisplayData[disp].currentConfig; + return mDisplayData[disp].configs[currentConfig].colorMode; +} + const Vector& HWComposer::getConfigs(int disp) const { return mDisplayData[disp].configs; } @@ -1182,10 +1189,10 @@ void HWComposer::dump(String8& result) const { for (size_t c = 0; c < disp.configs.size(); ++c) { const DisplayConfig& config(disp.configs[c]); result.appendFormat(" %s%zd: %ux%u, xdpi=%f, ydpi=%f" - ", refresh=%" PRId64 ", colorTransform=%d\n", + ", refresh=%" PRId64 ", colorMode=%d\n", c == disp.currentConfig ? "* " : "", c, config.width, config.height, config.xdpi, config.ydpi, - config.refresh, config.colorTransform); + config.refresh, config.colorMode); } if (disp.list) { diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h index c86181781b..170e382330 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h @@ -22,6 +22,8 @@ #include +#include + #include #include @@ -257,7 +259,15 @@ public: float xdpi; float ydpi; nsecs_t refresh; - int colorTransform; + android_color_mode_t colorMode; + bool operator==(const DisplayConfig& rhs) const { + return width == rhs.width && + height == rhs.height && + xdpi == rhs.xdpi && + ydpi == rhs.ydpi && + refresh == rhs.refresh && + colorMode == rhs.colorMode; + } }; // Query display parameters. Pass in a display index (e.g. @@ -274,6 +284,7 @@ public: float getDpiX(int disp) const; float getDpiY(int disp) const; nsecs_t getRefreshPeriod(int disp) const; + android_color_mode_t getColorMode(int disp) const; const Vector& getConfigs(int disp) const; size_t getCurrentConfig(int disp) const; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index f298399ac5..3050d1cd7a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -631,18 +631,7 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp& display, // All non-virtual displays are currently considered secure. info.secure = true; - // DisplayManager expects each color mode to be its own display - // info record. - std::vector modes = getHwComposer().getColorModes(type); - - if (modes.size() == 0) { - info.colorTransform = 0; - configs->push_back(info); - } - for (int32_t mode : modes) { - info.colorTransform = mode; - configs->push_back(info); - } + configs->push_back(info); } return NO_ERROR; @@ -704,6 +693,7 @@ status_t SurfaceFlinger::setActiveConfig(const sp& display, int mode) { if (mMode < 0 || mMode >= static_cast(configs.size())) { ALOGE("Attempt to set active config = %d for display with %zu configs", mMode, configs.size()); + return true; } sp hw(mFlinger.getDisplayDevice(mDisplay)); if (hw == NULL) { @@ -722,6 +712,101 @@ status_t SurfaceFlinger::setActiveConfig(const sp& display, int mode) { postMessageSync(msg); return NO_ERROR; } +status_t SurfaceFlinger::getDisplayColorModes(const sp& display, + Vector* outColorModes) { + if ((outColorModes == nullptr) || (display.get() == nullptr)) { + return BAD_VALUE; + } + + if (!display.get()) { + return NAME_NOT_FOUND; + } + + int32_t type = NAME_NOT_FOUND; + for (int i=0 ; i modes = getHwComposer().getColorModes(type); + outColorModes->clear(); + std::copy(modes.cbegin(), modes.cend(), std::back_inserter(*outColorModes)); + + return NO_ERROR; +} + +android_color_mode_t SurfaceFlinger::getActiveColorMode(const sp& display) { + sp device(getDisplayDevice(display)); + if (device != nullptr) { + return device->getActiveColorMode(); + } + return static_cast(BAD_VALUE); +} + +void SurfaceFlinger::setActiveColorModeInternal(const sp& hw, + android_color_mode_t mode) { + ALOGD("Set active color mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(), + this); + int32_t type = hw->getDisplayType(); + android_color_mode_t currentMode = hw->getActiveColorMode(); + + if (mode == currentMode) { + ALOGD("Screen type=%d is already in color mode=%d", hw->getDisplayType(), mode); + return; + } + + if (type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) { + ALOGW("Trying to set config for virtual display"); + return; + } + + hw->setActiveColorMode(mode); + getHwComposer().setActiveColorMode(type, mode); +} + + +status_t SurfaceFlinger::setActiveColorMode(const sp& display, + android_color_mode_t colorMode) { + class MessageSetActiveColorMode: public MessageBase { + SurfaceFlinger& mFlinger; + sp mDisplay; + android_color_mode_t mMode; + public: + MessageSetActiveColorMode(SurfaceFlinger& flinger, const sp& disp, + android_color_mode_t mode) : + mFlinger(flinger), mDisplay(disp) { mMode = mode; } + virtual bool handler() { + Vector modes; + mFlinger.getDisplayColorModes(mDisplay, &modes); + bool exists = std::find(std::begin(modes), std::end(modes), mMode) != std::end(modes); + if (mMode < 0 || !exists) { + ALOGE("Attempt to set invalid active color mode = %d for display %p", mMode, + mDisplay.get()); + return true; + } + sp hw(mFlinger.getDisplayDevice(mDisplay)); + if (hw == nullptr) { + ALOGE("Attempt to set active color mode = %d for null display %p", + mMode, mDisplay.get()); + } else if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL) { + ALOGW("Attempt to set active color mode= %d for virtual display", + mMode); + } else { + mFlinger.setActiveColorModeInternal(hw, mMode); + } + return true; + } + }; + sp msg = new MessageSetActiveColorMode(*this, display, colorMode); + postMessageSync(msg); + return NO_ERROR; +} status_t SurfaceFlinger::clearAnimationFrameStats() { Mutex::Autolock _l(mStateLock); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index f063aaf2c6..5cb99027b4 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -46,6 +46,8 @@ #include +#include + #include #include "Barrier.h" @@ -222,6 +224,10 @@ private: virtual status_t getDisplayConfigs(const sp& display, Vector* configs); virtual int getActiveConfig(const sp& display); + virtual status_t getDisplayColorModes(const sp& display, + Vector* configs); + virtual android_color_mode_t getActiveColorMode(const sp& display); + virtual status_t setActiveColorMode(const sp& display, android_color_mode_t colorMode); virtual void setPowerMode(const sp& display, int mode); virtual status_t setActiveConfig(const sp& display, int id); virtual status_t clearAnimationFrameStats(); @@ -260,6 +266,9 @@ private: // called on the main thread in response to setPowerMode() void setPowerModeInternal(const sp& hw, int mode); + // Called on the main thread in response to setActiveColorMode() + void setActiveColorModeInternal(const sp& hw, android_color_mode_t colorMode); + // Returns whether the transaction actually modified any state bool handleMessageTransaction(); @@ -368,6 +377,16 @@ private: return mDisplays.valueFor(dpy); } + int32_t getDisplayType(const sp& display) { + if (!display.get()) return NAME_NOT_FOUND; + for (int i = 0; i < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES; ++i) { + if (display == mBuiltinDisplays[i]) { + return i; + } + } + return NAME_NOT_FOUND; + } + // mark a region of a layer stack dirty. this updates the dirty // region of all screens presenting this layer stack. void invalidateLayerStack(uint32_t layerStack, const Region& dirty); diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp index 7062ea2511..6fe2358634 100644 --- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp +++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp @@ -59,6 +59,8 @@ #include #include +#include + #include "Client.h" #include "clz.h" #include "Colorizer.h" @@ -574,20 +576,8 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp& display, return BAD_VALUE; } - if (!display.get()) - return NAME_NOT_FOUND; - - int32_t type = NAME_NOT_FOUND; - for (int i=0 ; i& display, info.ydpi = ydpi; info.fps = float(1e9 / hwConfig.refresh); info.appVsyncOffset = VSYNC_EVENT_PHASE_OFFSET_NS; - info.colorTransform = hwConfig.colorTransform; // This is how far in advance a buffer must be queued for // presentation at a given time. If you want a buffer to appear @@ -750,6 +739,55 @@ status_t SurfaceFlinger::setActiveConfig(const sp& display, int mode) { return NO_ERROR; } +status_t SurfaceFlinger::getDisplayColorModes(const sp& display, + Vector* outColorModes) { + if (outColorModes == nullptr || display.get() == nullptr) { + return BAD_VALUE; + } + + int32_t type = getDisplayType(display); + if (type < 0) return type; + + std::set colorModes; + for (const HWComposer::DisplayConfig& hwConfig : getHwComposer().getConfigs(type)) { + colorModes.insert(hwConfig.colorMode); + } + + outColorModes->clear(); + std::copy(colorModes.cbegin(), colorModes.cend(), std::back_inserter(*outColorModes)); + + return NO_ERROR; +} + +android_color_mode_t SurfaceFlinger::getActiveColorMode(const sp& display) { + if (display.get() == nullptr) return static_cast(BAD_VALUE); + + int32_t type = getDisplayType(display); + if (type < 0) return static_cast(type); + + return getHwComposer().getColorMode(type); +} + +status_t SurfaceFlinger::setActiveColorMode(const sp& display, + android_color_mode_t colorMode) { + if (display.get() == nullptr || colorMode < 0) { + return BAD_VALUE; + } + + int32_t type = getDisplayType(display); + if (type < 0) return type; + const Vector& hwConfigs = getHwComposer().getConfigs(type); + HWComposer::DisplayConfig desiredConfig = hwConfigs[getHwComposer().getCurrentConfig(type)]; + desiredConfig.colorMode = colorMode; + for (size_t c = 0; c < hwConfigs.size(); ++c) { + const HWComposer::DisplayConfig config = hwConfigs[c]; + if (config == desiredConfig) { + return setActiveConfig(display, c); + } + } + return BAD_VALUE; +} + status_t SurfaceFlinger::clearAnimationFrameStats() { Mutex::Autolock _l(mStateLock); mAnimFrameTracker.clearStats(); -- 2.11.0