diff options
17 files changed, 479 insertions, 1 deletions
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 546757ba90..ec5f37467c 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -525,6 +525,88 @@ public: return static_cast<status_t>(reply.readInt32()); } + virtual status_t getAutoLowLatencyModeSupport(const sp<IBinder>& display, + bool* outSupport) const { + Parcel data, reply; + data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + status_t result = data.writeStrongBinder(display); + if (result != NO_ERROR) { + ALOGE("getAutoLowLatencyModeSupport failed to writeStrongBinder: %d", result); + return result; + } + result = remote()->transact(BnSurfaceComposer::GET_AUTO_LOW_LATENCY_MODE_SUPPORT, data, + &reply); + if (result != NO_ERROR) { + ALOGE("getAutoLowLatencyModeSupport failed to transact: %d", result); + return result; + } + return reply.readBool(outSupport); + } + + virtual void setAutoLowLatencyMode(const sp<IBinder>& display, bool on) { + Parcel data, reply; + status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + if (result != NO_ERROR) { + ALOGE("setAutoLowLatencyMode failed to writeInterfaceToken: %d", result); + return; + } + + result = data.writeStrongBinder(display); + if (result != NO_ERROR) { + ALOGE("setAutoLowLatencyMode failed to writeStrongBinder: %d", result); + return; + } + result = data.writeBool(on); + if (result != NO_ERROR) { + ALOGE("setAutoLowLatencyMode failed to writeBool: %d", result); + return; + } + result = remote()->transact(BnSurfaceComposer::SET_AUTO_LOW_LATENCY_MODE, data, &reply); + if (result != NO_ERROR) { + ALOGE("setAutoLowLatencyMode failed to transact: %d", result); + return; + } + } + + virtual status_t getGameContentTypeSupport(const sp<IBinder>& display, bool* outSupport) const { + Parcel data, reply; + data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + status_t result = data.writeStrongBinder(display); + if (result != NO_ERROR) { + ALOGE("getGameContentTypeSupport failed to writeStrongBinder: %d", result); + return result; + } + result = remote()->transact(BnSurfaceComposer::GET_GAME_CONTENT_TYPE_SUPPORT, data, &reply); + if (result != NO_ERROR) { + ALOGE("getGameContentTypeSupport failed to transact: %d", result); + return result; + } + return reply.readBool(outSupport); + } + + virtual void setGameContentType(const sp<IBinder>& display, bool on) { + Parcel data, reply; + status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + if (result != NO_ERROR) { + ALOGE("setGameContentType failed to writeInterfaceToken: %d", result); + return; + } + result = data.writeStrongBinder(display); + if (result != NO_ERROR) { + ALOGE("setGameContentType failed to writeStrongBinder: %d", result); + return; + } + result = data.writeBool(on); + if (result != NO_ERROR) { + ALOGE("setGameContentType failed to writeBool: %d", result); + return; + } + result = remote()->transact(BnSurfaceComposer::SET_GAME_CONTENT_TYPE, data, &reply); + if (result != NO_ERROR) { + ALOGE("setGameContentType failed to transact: %d", result); + } + } + virtual status_t clearAnimationFrameStats() { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); @@ -1407,6 +1489,75 @@ status_t BnSurfaceComposer::onTransact( result = reply->writeInt32(result); return result; } + + case GET_AUTO_LOW_LATENCY_MODE_SUPPORT: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + sp<IBinder> display = nullptr; + status_t result = data.readStrongBinder(&display); + if (result != NO_ERROR) { + ALOGE("getAutoLowLatencyModeSupport failed to readStrongBinder: %d", result); + return result; + } + bool supported = false; + result = getAutoLowLatencyModeSupport(display, &supported); + if (result == NO_ERROR) { + result = reply->writeBool(supported); + } + return result; + } + + case SET_AUTO_LOW_LATENCY_MODE: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + sp<IBinder> display = nullptr; + status_t result = data.readStrongBinder(&display); + if (result != NO_ERROR) { + ALOGE("setAutoLowLatencyMode failed to readStrongBinder: %d", result); + return result; + } + bool setAllm = false; + result = data.readBool(&setAllm); + if (result != NO_ERROR) { + ALOGE("setAutoLowLatencyMode failed to readBool: %d", result); + return result; + } + setAutoLowLatencyMode(display, setAllm); + return result; + } + + case GET_GAME_CONTENT_TYPE_SUPPORT: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + sp<IBinder> display = nullptr; + status_t result = data.readStrongBinder(&display); + if (result != NO_ERROR) { + ALOGE("getGameContentTypeSupport failed to readStrongBinder: %d", result); + return result; + } + bool supported = false; + result = getGameContentTypeSupport(display, &supported); + if (result == NO_ERROR) { + result = reply->writeBool(supported); + } + return result; + } + + case SET_GAME_CONTENT_TYPE: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + sp<IBinder> display = nullptr; + status_t result = data.readStrongBinder(&display); + if (result != NO_ERROR) { + ALOGE("setGameContentType failed to readStrongBinder: %d", result); + return result; + } + bool setGameContentTypeOn = false; + result = data.readBool(&setGameContentTypeOn); + if (result != NO_ERROR) { + ALOGE("setGameContentType failed to readBool: %d", result); + return result; + } + setGameContentType(display, setGameContentTypeOn); + 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 9d7d7d0ca6..524d7a9491 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1656,6 +1656,26 @@ status_t SurfaceComposerClient::setActiveColorMode(const sp<IBinder>& display, return ComposerService::getComposerService()->setActiveColorMode(display, colorMode); } +bool SurfaceComposerClient::getAutoLowLatencyModeSupport(const sp<IBinder>& display) { + bool supported = false; + ComposerService::getComposerService()->getAutoLowLatencyModeSupport(display, &supported); + return supported; +} + +void SurfaceComposerClient::setAutoLowLatencyMode(const sp<IBinder>& display, bool on) { + ComposerService::getComposerService()->setAutoLowLatencyMode(display, on); +} + +bool SurfaceComposerClient::getGameContentTypeSupport(const sp<IBinder>& display) { + bool supported = false; + ComposerService::getComposerService()->getGameContentTypeSupport(display, &supported); + return supported; +} + +void SurfaceComposerClient::setGameContentType(const sp<IBinder>& display, bool on) { + ComposerService::getComposerService()->setGameContentType(display, on); +} + void SurfaceComposerClient::setDisplayPowerMode(const sp<IBinder>& token, int mode) { ComposerService::getComposerService()->setPowerMode(token, mode); diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 345425d8d2..e539fcbf11 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -195,6 +195,37 @@ public: ui::ColorMode colorMode) = 0; /** + * Returns true if the connected display reports support for HDMI 2.1 Auto + * Low Latency Mode. + * For more information, see the HDMI 2.1 specification. + */ + virtual status_t getAutoLowLatencyModeSupport(const sp<IBinder>& display, + bool* outSupport) const = 0; + + /** + * Switches Auto Low Latency Mode on/off on the connected display, if it is + * available. This should only be called if #getAutoLowLatencyMode returns + * true. + * For more information, see the HDMI 2.1 specification. + */ + virtual void setAutoLowLatencyMode(const sp<IBinder>& display, bool on) = 0; + + /** + * Returns true if the connected display reports support for Game Content Type. + * For more information, see the HDMI 1.4 specification. + */ + virtual status_t getGameContentTypeSupport(const sp<IBinder>& display, + bool* outSupport) const = 0; + + /** + * This will start sending infoframes to the connected display with + * ContentType=Game (if on=true). This will switch the disply to Game mode. + * This should only be called if #getGameContentTypeSupport returns true. + * For more information, see the HDMI 1.4 specification. + */ + virtual void setGameContentType(const sp<IBinder>& display, bool on) = 0; + + /** * Capture the specified screen. This requires READ_FRAME_BUFFER * permission. This function will fail if there is a secure window on * screen. @@ -532,6 +563,10 @@ public: CAPTURE_SCREEN_BY_ID, NOTIFY_POWER_HINT, SET_GLOBAL_SHADOW_SETTINGS, + GET_AUTO_LOW_LATENCY_MODE_SUPPORT, + SET_AUTO_LOW_LATENCY_MODE, + GET_GAME_CONTENT_TYPE_SUPPORT, + SET_GAME_CONTENT_TYPE, // Always append new enum to the end. }; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 2c0b143c81..b5ca029edf 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -160,6 +160,21 @@ public: static status_t setActiveColorMode(const sp<IBinder>& display, ui::ColorMode colorMode); + // Reports whether the connected display supports Auto Low Latency Mode + static bool getAutoLowLatencyModeSupport(const sp<IBinder>& display); + + // Switches on/off Auto Low Latency Mode on the connected display. This should only be + // called if the connected display supports Auto Low Latency Mode as reported by + // #getAutoLowLatencyModeSupport + static void setAutoLowLatencyMode(const sp<IBinder>& display, bool on); + + // Reports whether the connected display supports Game content type + static bool getGameContentTypeSupport(const sp<IBinder>& display); + + // Turns Game mode on/off on the connected display. This should only be called + // if the display supports Game content type, as reported by #getGameContentTypeSupport + static void setGameContentType(const sp<IBinder>& display, bool on); + /* Triggers screen on/off or low power mode and waits for it to complete */ static void setDisplayPowerMode(const sp<IBinder>& display, int mode); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 3d90369a12..1730ec3d1d 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -750,6 +750,16 @@ public: bool /*captureSecureLayers*/) override { return NO_ERROR; } + status_t getAutoLowLatencyModeSupport(const sp<IBinder>& /*display*/, + bool* /*outSupport*/) const override { + return NO_ERROR; + } + void setAutoLowLatencyMode(const sp<IBinder>& /*display*/, bool /*on*/) override {} + status_t getGameContentTypeSupport(const sp<IBinder>& /*display*/, + bool* /*outSupport*/) const override { + return NO_ERROR; + } + void setGameContentType(const sp<IBinder>& /*display*/, bool /*on*/) override {} status_t captureScreen(uint64_t /*displayOrLayerStack*/, ui::Dataspace* /*outDataspace*/, sp<GraphicBuffer>* /*outBuffer*/) override { return NO_ERROR; diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h index 364661bed5..99717913dd 100644 --- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h +++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h @@ -86,6 +86,9 @@ public: MOCK_METHOD4(setActiveConfigWithConstraints, status_t(DisplayId, size_t, const HWC2::VsyncPeriodChangeConstraints&, HWC2::VsyncPeriodChangeTimeline*)); + MOCK_METHOD2(setAutoLowLatencyMode, status_t(DisplayId, bool)); + MOCK_METHOD2(getSupportedContentTypes, status_t(DisplayId, std::vector<HWC2::ContentType>*)); + MOCK_METHOD2(setContentType, status_t(DisplayId, HWC2::ContentType)); MOCK_CONST_METHOD1(dump, void(std::string&)); MOCK_CONST_METHOD0(getComposer, android::Hwc2::Composer*()); diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp index dc71128a3c..eb032f3fe8 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp @@ -1281,6 +1281,45 @@ V2_4::Error Composer::setActiveConfigWithConstraints( return error; } +V2_4::Error Composer::setAutoLowLatencyMode(Display display, bool on) { + using Error = V2_4::Error; + if (!mClient_2_4) { + return Error::UNSUPPORTED; + } + + return mClient_2_4->setAutoLowLatencyMode(display, on); +} + +V2_4::Error Composer::getSupportedContentTypes( + Display displayId, std::vector<IComposerClient::ContentType>* outSupportedContentTypes) { + using Error = V2_4::Error; + if (!mClient_2_4) { + return Error::UNSUPPORTED; + } + + Error error = kDefaultError_2_4; + mClient_2_4->getSupportedContentTypes(displayId, + [&](const auto& tmpError, + const auto& tmpSupportedContentTypes) { + error = tmpError; + if (error != Error::NONE) { + return; + } + + *outSupportedContentTypes = tmpSupportedContentTypes; + }); + return error; +} + +V2_4::Error Composer::setContentType(Display display, IComposerClient::ContentType contentType) { + using Error = V2_4::Error; + if (!mClient_2_4) { + return Error::UNSUPPORTED; + } + + return mClient_2_4->setContentType(display, contentType); +} + CommandReader::~CommandReader() { resetData(); diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h index 336fdd887d..301f54fa6a 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.h +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h @@ -221,6 +221,13 @@ public: Display display, Config config, const IComposerClient::VsyncPeriodChangeConstraints& vsyncPeriodChangeConstraints, VsyncPeriodChangeTimeline* outTimeline) = 0; + + virtual V2_4::Error setAutoLowLatencyMode(Display displayId, bool on) = 0; + virtual V2_4::Error getSupportedContentTypes( + Display displayId, + std::vector<IComposerClient::ContentType>* outSupportedContentTypes) = 0; + virtual V2_4::Error setContentType(Display displayId, + IComposerClient::ContentType contentType) = 0; }; namespace impl { @@ -442,6 +449,12 @@ public: Display display, Config config, const IComposerClient::VsyncPeriodChangeConstraints& vsyncPeriodChangeConstraints, VsyncPeriodChangeTimeline* outTimeline) override; + V2_4::Error setAutoLowLatencyMode(Display displayId, bool on) override; + V2_4::Error getSupportedContentTypes( + Display displayId, + std::vector<IComposerClient::ContentType>* outSupportedContentTypes) override; + V2_4::Error setContentType(Display displayId, + IComposerClient::ContentType contentType) override; private: #if defined(USE_VR_COMPOSER) && USE_VR_COMPOSER diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index 34254e05a0..66d3ce9f50 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -799,6 +799,26 @@ Error Display::setDisplayBrightness(float brightness) const { return static_cast<Error>(intError); } +Error Display::setAutoLowLatencyMode(bool on) const { + auto intError = mComposer.setAutoLowLatencyMode(mId, on); + return static_cast<Error>(intError); +} + +Error Display::getSupportedContentTypes(std::vector<ContentType>* outSupportedContentTypes) const { + std::vector<Hwc2::IComposerClient::ContentType> tmpSupportedContentTypes; + auto intError = mComposer.getSupportedContentTypes(mId, &tmpSupportedContentTypes); + for (Hwc2::IComposerClient::ContentType contentType : tmpSupportedContentTypes) { + outSupportedContentTypes->push_back(static_cast<ContentType>(contentType)); + } + return static_cast<Error>(intError); +} + +Error Display::setContentType(ContentType contentType) const { + using Hwc2_ContentType = Hwc2::IComposerClient::ContentType; + auto intError = mComposer.setContentType(mId, static_cast<Hwc2_ContentType>(contentType)); + return static_cast<Error>(intError); +} + // For use by Device void Display::setConnected(bool connected) { diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h index 81ae3b617b..6a2ea495ff 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.h +++ b/services/surfaceflinger/DisplayHardware/HWC2.h @@ -285,6 +285,10 @@ public: const std::shared_ptr<const HWC2::Display::Config>& config, const VsyncPeriodChangeConstraints& constraints, VsyncPeriodChangeTimeline* outTimeline) = 0; + [[clang::warn_unused_result]] virtual Error setAutoLowLatencyMode(bool on) const = 0; + [[clang::warn_unused_result]] virtual Error getSupportedContentTypes( + std::vector<HWC2::ContentType>*) const = 0; + [[clang::warn_unused_result]] virtual Error setContentType(HWC2::ContentType) const = 0; }; namespace impl { @@ -348,7 +352,10 @@ public: Error setActiveConfigWithConstraints(const std::shared_ptr<const HWC2::Display::Config>& config, const VsyncPeriodChangeConstraints& constraints, VsyncPeriodChangeTimeline* outTimeline) override; - + Error setAutoLowLatencyMode(bool on) const override; + Error getSupportedContentTypes( + std::vector<HWC2::ContentType>* outSupportedContentTypes) const override; + Error setContentType(HWC2::ContentType contentType) const override; // Other Display methods hwc2_display_t getId() const override { return mId; } bool isConnected() const override { return mIsConnected; } diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index d8dad0b0ca..9accefb7e1 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -722,6 +722,44 @@ bool HWComposer::isUsingVrComposer() const { return getComposer()->isUsingVrComposer(); } +status_t HWComposer::setAutoLowLatencyMode(DisplayId displayId, bool on) { + RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); + const auto error = mDisplayData[displayId].hwcDisplay->setAutoLowLatencyMode(on); + if (error == HWC2::Error::Unsupported) { + RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION); + } + if (error == HWC2::Error::BadParameter) { + RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE); + } + RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR); + return NO_ERROR; +} + +status_t HWComposer::getSupportedContentTypes( + DisplayId displayId, std::vector<HWC2::ContentType>* outSupportedContentTypes) { + RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); + const auto error = + mDisplayData[displayId].hwcDisplay->getSupportedContentTypes(outSupportedContentTypes); + + RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR); + + return NO_ERROR; +} + +status_t HWComposer::setContentType(DisplayId displayId, HWC2::ContentType contentType) { + RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); + const auto error = mDisplayData[displayId].hwcDisplay->setContentType(contentType); + if (error == HWC2::Error::Unsupported) { + RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION); + } + if (error == HWC2::Error::BadParameter) { + RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE); + } + RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR); + + return NO_ERROR; +} + void HWComposer::dump(std::string& result) const { // TODO: In order to provide a dump equivalent to HWC1, we need to shadow // all the state going into the layers. This is probably better done in diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 077e452af9..c51002c447 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -184,6 +184,10 @@ public: DisplayId displayId, size_t configId, const HWC2::VsyncPeriodChangeConstraints& constraints, HWC2::VsyncPeriodChangeTimeline* outTimeline) = 0; + virtual status_t setAutoLowLatencyMode(DisplayId displayId, bool on) = 0; + virtual status_t getSupportedContentTypes( + DisplayId displayId, std::vector<HWC2::ContentType>* outSupportedContentTypes) = 0; + virtual status_t setContentType(DisplayId displayId, HWC2::ContentType contentType) = 0; // for debugging ---------------------------------------------------------- virtual void dump(std::string& out) const = 0; @@ -313,6 +317,10 @@ public: status_t setActiveConfigWithConstraints(DisplayId displayId, size_t configId, const HWC2::VsyncPeriodChangeConstraints& constraints, HWC2::VsyncPeriodChangeTimeline* outTimeline) override; + status_t setAutoLowLatencyMode(DisplayId displayId, bool) override; + status_t getSupportedContentTypes(DisplayId displayId, + std::vector<HWC2::ContentType>*) override; + status_t setContentType(DisplayId displayId, HWC2::ContentType) override; // for debugging ---------------------------------------------------------- void dump(std::string& out) const override; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 8e945299e5..64fcb612f3 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1111,6 +1111,86 @@ status_t SurfaceFlinger::setActiveColorMode(const sp<IBinder>& displayToken, Col return NO_ERROR; } +status_t SurfaceFlinger::getAutoLowLatencyModeSupport(const sp<IBinder>& displayToken, + bool* outSupport) const { + Mutex::Autolock _l(mStateLock); + + if (!displayToken) { + ALOGE("getAutoLowLatencyModeSupport() failed. Missing display token."); + return BAD_VALUE; + } + const auto displayId = getPhysicalDisplayIdLocked(displayToken); + if (!displayId) { + ALOGE("getAutoLowLatencyModeSupport() failed. Display id for display token %p not found.", + displayToken.get()); + return NAME_NOT_FOUND; + } + *outSupport = getHwComposer().hasDisplayCapability(displayId, + HWC2::DisplayCapability::AutoLowLatencyMode); + return NO_ERROR; +} + +void SurfaceFlinger::setAutoLowLatencyMode(const sp<IBinder>& displayToken, bool on) { + postMessageAsync(new LambdaMessage([=] { setAutoLowLatencyModeInternal(displayToken, on); })); +} + +void SurfaceFlinger::setAutoLowLatencyModeInternal(const sp<IBinder>& displayToken, bool on) { + if (!displayToken) { + ALOGE("setAutoLowLatencyMode() failed. Missing display token."); + return; + } + const auto displayId = getPhysicalDisplayIdLocked(displayToken); + if (!displayId) { + ALOGE("setAutoLowLatencyMode() failed. Display id for display token %p not found.", + displayToken.get()); + return; + } + + getHwComposer().setAutoLowLatencyMode(*displayId, on); +} + +status_t SurfaceFlinger::getGameContentTypeSupport(const sp<IBinder>& displayToken, + bool* outSupport) const { + Mutex::Autolock _l(mStateLock); + + if (!displayToken) { + ALOGE("getGameContentTypeSupport() failed. Missing display token."); + return BAD_VALUE; + } + const auto displayId = getPhysicalDisplayIdLocked(displayToken); + if (!displayId) { + ALOGE("getGameContentTypeSupport() failed. Display id for display token %p not found.", + displayToken.get()); + return NAME_NOT_FOUND; + } + + std::vector<HWC2::ContentType> outSupportedContentTypes; + getHwComposer().getSupportedContentTypes(*displayId, &outSupportedContentTypes); + *outSupport = std::find(outSupportedContentTypes.begin(), outSupportedContentTypes.end(), + HWC2::ContentType::Game) != outSupportedContentTypes.end(); + return NO_ERROR; +} + +void SurfaceFlinger::setGameContentType(const sp<IBinder>& displayToken, bool on) { + postMessageAsync(new LambdaMessage([=] { setGameContentTypeInternal(displayToken, on); })); +} + +void SurfaceFlinger::setGameContentTypeInternal(const sp<IBinder>& displayToken, bool on) { + if (!displayToken) { + ALOGE("setGameContentType() failed. Missing display token."); + return; + } + const auto displayId = getPhysicalDisplayIdLocked(displayToken); + if (!displayId) { + ALOGE("setGameContentType() failed. Display id for display token %p not found.", + displayToken.get()); + return; + } + + const HWC2::ContentType type = on ? HWC2::ContentType::Game : HWC2::ContentType::None; + getHwComposer().setContentType(*displayId, type); +} + status_t SurfaceFlinger::clearAnimationFrameStats() { Mutex::Autolock _l(mStateLock); mAnimFrameTracker.clearStats(); @@ -4438,6 +4518,10 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { case SET_DESIRED_DISPLAY_CONFIG_SPECS: case GET_DESIRED_DISPLAY_CONFIG_SPECS: case SET_ACTIVE_COLOR_MODE: + case GET_AUTO_LOW_LATENCY_MODE_SUPPORT: + case SET_AUTO_LOW_LATENCY_MODE: + case GET_GAME_CONTENT_TYPE_SUPPORT: + case SET_GAME_CONTENT_TYPE: case INJECT_VSYNC: case SET_POWER_MODE: case GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES: diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 53b8908641..be47e94f94 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -449,6 +449,12 @@ private: ui::DisplayPrimaries &primaries); ui::ColorMode getActiveColorMode(const sp<IBinder>& displayToken) override; status_t setActiveColorMode(const sp<IBinder>& displayToken, ui::ColorMode colorMode) override; + status_t getAutoLowLatencyModeSupport(const sp<IBinder>& displayToken, + bool* outSupported) const override; + void setAutoLowLatencyMode(const sp<IBinder>& displayToken, bool on) override; + status_t getGameContentTypeSupport(const sp<IBinder>& displayToken, + bool* outSupported) const override; + void setGameContentType(const sp<IBinder>& displayToken, bool on) override; void setPowerMode(const sp<IBinder>& displayToken, int mode) override; status_t setActiveConfig(const sp<IBinder>& displayToken, int id) override; status_t clearAnimationFrameStats() override; @@ -563,6 +569,10 @@ private: void setAllowedDisplayConfigsInternal(const sp<DisplayDevice>& display, const std::vector<int32_t>& allowedConfigs) REQUIRES(mStateLock); + // called on the main thread in response to setAutoLowLatencyMode() + void setAutoLowLatencyModeInternal(const sp<IBinder>& displayToken, bool on); + // called on the main thread in response to setGameContentType() + void setGameContentTypeInternal(const sp<IBinder>& displayToken, bool on); // Returns whether the transaction actually modified any state bool handleMessageTransaction(); diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp index 6d7961520f..0c370a6fdb 100644 --- a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp +++ b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp @@ -760,6 +760,22 @@ V2_4::Error FakeComposerClient::setActiveConfigWithConstraints( return V2_4::Error::UNSUPPORTED; } +V2_4::Error FakeComposerClient::setAutoLowLatencyMode(Display, bool) { + ALOGV("setAutoLowLatencyMode"); + return V2_4::Error::UNSUPPORTED; +} + +V2_4::Error FakeComposerClient::getSupportedContentTypes( + Display, std::vector<IComposerClient::ContentType>*) { + ALOGV("getSupportedContentTypes"); + return V2_4::Error::UNSUPPORTED; +} + +V2_4::Error FakeComposerClient::setContentType(Display, IComposerClient::ContentType) { + ALOGV("setContentType"); + return V2_4::Error::UNSUPPORTED; +} + ////////////////////////////////////////////////////////////////// void FakeComposerClient::requestVSync(uint64_t vsyncTime) { diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.h b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.h index 2a08b9ba5e..f9ff2bf74a 100644 --- a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.h +++ b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.h @@ -246,6 +246,11 @@ public: Display display, Config config, const V2_4::IComposerClient::VsyncPeriodChangeConstraints& vsyncPeriodChangeConstraints, VsyncPeriodChangeTimeline* outTimeline) override; + V2_4::Error setAutoLowLatencyMode(Display display, bool on) override; + V2_4::Error getSupportedContentTypes( + Display display, + std::vector<IComposerClient::ContentType>* outSupportedContentTypes) override; + V2_4::Error setContentType(Display display, IComposerClient::ContentType type) override; void setClient(ComposerClient* client); diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h index 2453ccb291..0f9dd5b47a 100644 --- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h +++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h @@ -130,6 +130,10 @@ public: MOCK_METHOD4(setActiveConfigWithConstraints, V2_4::Error(Display, Config, const IComposerClient::VsyncPeriodChangeConstraints&, VsyncPeriodChangeTimeline*)); + MOCK_METHOD2(setAutoLowLatencyMode, V2_4::Error(Display, bool)); + MOCK_METHOD2(getSupportedContentTypes, + V2_4::Error(Display, std::vector<IComposerClient::ContentType>*)); + MOCK_METHOD2(setContentType, V2_4::Error(Display, IComposerClient::ContentType)); }; } // namespace mock |