/* Copyright Statement: * * This software/firmware and related documentation ("MediaTek Software") are * protected under relevant copyright laws. The information contained herein is * confidential and proprietary to MediaTek Inc. and/or its licensors. Without * the prior written permission of MediaTek inc. and/or its licensors, any * reproduction, modification, use or disclosure of MediaTek Software, and * information contained herein, in whole or in part, shall be strictly * prohibited. * * MediaTek Inc. (C) 2021. All rights reserved. * * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. * * The following software/firmware and/or related documentation ("MediaTek * Software") have been modified by MediaTek Inc. All revisions are subject to * any receiver's applicable license agreements with MediaTek Inc. */ #undef LOG_TAG #define LOG_TAG "MSyncSfApi" #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include "MSyncSfApi.h" #include #include #include #include #include #include "DisplayDevice.h" #include "Layer.h" #include "Scheduler/MessageQueue.h" #include "SurfaceFlinger.h" #ifdef MTK_COMPOSER_EXT #include #endif #define LIBRARY_NAME "libmtk_sf_msync_2_0.so" using std::endl; namespace android { #ifdef MTK_SF_MSYNC MSyncSfApi::MSyncSfApi(const sp& flinger, bool useList) : mFlinger(flinger) { mSoHandle = dlopen(LIBRARY_NAME, RTLD_LAZY); if (mSoHandle) { int ret = loadMSyncApi(); if (ret) { ALOGE("loadMSyncApi() fail, ret %d", ret); } else { if (mFuncCreateMSyncController) { mMSyncController = mFuncCreateMSyncController(useList, [this](const sp& binder) { sp layer = nullptr; if (binder) { layer = mFlinger->fromHandle(binder).promote(); } return layer.get(); }, [this](std::function func) { mFlinger->mDrawingState.traverseInZOrder([&](Layer* layer) { if (layer->isVisible()) { func(layer); } }); }, [this](std::function func) { std::vector layerPtrs; mFlinger->mDrawingState.traverseInZOrder([&](Layer* layer) { if (layer->isVisible() && layer->getType() && strncmp(layer->getType(), "Buffer", strlen("Buffer")) == 0) { const Rect layerScreenBound = layer->getScreenBounds(); const float layerArea = layerScreenBound.getWidth() * layerScreenBound.getHeight(); const auto frameRateSelectionPriority = layer->getFrameRateSelectionPriority(); const bool focused = Layer::isLayerFocusedBasedOnPriority(frameRateSelectionPriority); func(layer, layerArea, focused); } }); }, [this]() { return mFlinger->mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod(); }, [this]() { mFlinger->mEventQueue->msyncTriggerDispatchInvalidate( mFlinger->mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod()); }, [this]() { mFlinger->mEventQueue->invalidate(); }, [this]() { #ifdef MTK_COMPOSER_EXT if (mFlinger->mMtkComposerExtIntf) { ::ComposerExt::ClientInterface* intf = mFlinger->mMtkComposerExtIntf; const auto hwcDisplayId = mFlinger->getHwComposer().getInternalHwcDisplayId(); if (hwcDisplayId) { int ret = intf->msyncSetEnable(*hwcDisplayId, ComposerExt::MSyncEnableType::kOn); ALOGE_IF(ret, "msyncSetEnable kOn fail"); } else { ALOGE("internal hwcDisplayId invalid"); } } #else ALOGE("msync, MTK_COMPOSER_EXT not defined, %p", this); #endif }, [this]() { #ifdef MTK_COMPOSER_EXT if (mFlinger->mMtkComposerExtIntf) { ::ComposerExt::ClientInterface* intf = mFlinger->mMtkComposerExtIntf; const auto hwcDisplayId = mFlinger->getHwComposer().getInternalHwcDisplayId(); if (hwcDisplayId) { int ret = intf->msyncSetEnable(*hwcDisplayId, ComposerExt::MSyncEnableType::kOff); ALOGE_IF(ret, "msyncSetEnable kOff fail"); } else { ALOGE("internal hwcDisplayId invalid"); } } #else ALOGE("msync, MTK_COMPOSER_EXT not defined, %p", this); #endif }); } } } else { ALOGE("failed to open library[%s]", LIBRARY_NAME); } } MSyncSfApi::~MSyncSfApi() { if (mMSyncController != nullptr) { mFuncDestroyMSyncController(mMSyncController); } if (mSoHandle != nullptr) { dlclose(mSoHandle); } } void MSyncSfApi::dump(std::string& result) const { if (mFuncDump) { mFuncDump(mMSyncController, result); } } void MSyncSfApi::reloadConfigThenDump(std::string& result) { if (mFuncReloadConfigThenDump) { mFuncReloadConfigThenDump(mMSyncController, result); } } void MSyncSfApi::registerLayer(const Layer* layer) { if (mFuncRegisterLayer) { mFuncRegisterLayer(mMSyncController, layer, layer->getName()); } } void MSyncSfApi::destroyLayer(const Layer* layer) { if (mFuncDestroyLayer) { mFuncDestroyLayer(mMSyncController, layer); } } void MSyncSfApi::onMessageInvalidate() { if (mFuncOnMessageInvalidate) { mFuncOnMessageInvalidate(mMSyncController); } } void MSyncSfApi::onMessageRefresh(sp display, const std::vector>& displays) { if (!mFuncOnMessageRefresh) { return; } ATRACE_CALL(); bool hasExternalDisp = false; bool hasGpuVirtualDisp = false; for (auto& disp : displays) { if (disp->isVirtual()) { if (GpuVirtualDisplayId::tryCast(disp->getVirtualId())) { //ALOGI("%s: hasGpuVirtualDisp", __func__); hasGpuVirtualDisp = true; } } else if (!disp->isPrimary()) { // external not support hasExternalDisp = true; break; } } mFuncOnMessageRefresh(mMSyncController, hasExternalDisp, hasGpuVirtualDisp, static_cast(display->getWidth() * display->getHeight())); } bool MSyncSfApi::isOn() const { if (mFuncIsOn) { return mFuncIsOn(mMSyncController); } return false; } void MSyncSfApi::setMSyncEnable(bool enable) { if (mFuncSetMSyncEnable) { mFuncSetMSyncEnable(mMSyncController, enable); } } void MSyncSfApi::setTargetLayer(const void* layerPtr) { if (mFuncSetTargetLayer) { mFuncSetTargetLayer(mMSyncController, layerPtr); } } void MSyncSfApi::setHasOtherUI(bool bHasOtherUI) { if (mFuncSetHasOtherUI) { mFuncSetHasOtherUI(mMSyncController, bHasOtherUI); } } void MSyncSfApi::setPreviousPresentFence(const sp& previousPresentFence) { if (mFuncSetPreviousPresentFence) { mFuncSetPreviousPresentFence(mMSyncController, previousPresentFence); } } void MSyncSfApi::setTransactionState(const Vector& states) { if (!mFuncSetTransactionState) { return; } std::vector, bool, bool, sp>> layerStates; for (const ComposerState& state : states) { const layer_state_t& s = state.state; layerStates.emplace_back(s.surface, s.hasBufferChanges(), s.what & layer_state_t::eAcquireFenceChanged, s.acquireFence); } mFuncSetTransactionState(mMSyncController, layerStates); } void MSyncSfApi::requestInvalidate() { if (mFuncRequestInvalidate) { mFuncRequestInvalidate(mMSyncController); } } void MSyncSfApi::onActiveModeUpdated() { if (mFuncOnActiveModeUpdated) { mFuncOnActiveModeUpdated(mMSyncController); } } void MSyncSfApi::setHasPendingBuffer(const Layer* layer) { if (mFuncSetHasPendingBuffer) { mFuncSetHasPendingBuffer(mMSyncController, layer); } } #define FN_DLSYM(funcVar, funcType, funcName) ({ \ funcVar = reinterpret_cast(dlsym(mSoHandle, funcName)); \ if (funcVar == nullptr) { \ ALOGW("failed to find " funcName); \ return -EFAULT; \ } \ }) \ int MSyncSfApi::loadMSyncApi() { if (mSoHandle != nullptr) { FN_DLSYM(mFuncCreateMSyncController, FuncCreateMSyncController, "createMSyncController"); FN_DLSYM(mFuncDestroyMSyncController, FuncDestroyMSyncController, "destroyMSyncController"); FN_DLSYM(mFuncDump, FuncDump, "dump"); FN_DLSYM(mFuncReloadConfigThenDump, FuncReloadConfigThenDump, "reloadConfigThenDump"); FN_DLSYM(mFuncRegisterLayer, FuncRegisterLayer, "registerLayer"); FN_DLSYM(mFuncDestroyLayer, FuncDestroyLayer, "destroyLayer"); FN_DLSYM(mFuncOnMessageInvalidate, FuncOnMessageInvalidate, "onMessageInvalidate"); FN_DLSYM(mFuncOnMessageRefresh, FuncOnMessageRefresh, "onMessageRefresh"); FN_DLSYM(mFuncSetTransactionState, FuncSetTransactionState, "setTransactionState"); FN_DLSYM(mFuncRequestInvalidate, FuncRequestInvalidate, "requestInvalidate"); FN_DLSYM(mFuncOnActiveModeUpdated, FuncOnActiveModeUpdated, "onActiveModeUpdated"); FN_DLSYM(mFuncSetHasPendingBuffer, FuncSetHasPendingBuffer, "setHasPendingBuffer"); FN_DLSYM(mFuncIsOn, FuncIsOn, "isOn"); FN_DLSYM(mFuncSetMSyncEnable, FuncSetMSyncEnable, "setMSyncEnable"); FN_DLSYM(mFuncSetTargetLayer, FuncSetTargetLayer, "setTargetLayer"); FN_DLSYM(mFuncSetHasOtherUI, FuncSetHasOtherUI, "setHasOtherUI"); FN_DLSYM(mFuncSetPreviousPresentFence, FuncSetPreviousPresentFence, "setPreviousPresentFence"); } else { return -ENOENT; } return 0; } void MSyncSfApi::setMSyncParamTable(const Parcel& data) { // adb shell service call SurfaceFlinger 9526104 i32 'number of record' [i32 'level_id' i32 'level_fps' i32 'max_fps' i32 'min_fps'] #ifdef MTK_COMPOSER_EXT if (mFlinger->mMtkComposerExtIntf) { int numRecords = 0; numRecords = data.readInt32(); if (numRecords == 0) { ALOGE("%s: the number of records is 0, just eturn", __func__); return; } ::ComposerExt::ClientInterface* intf = mFlinger->mMtkComposerExtIntf; const auto hwcDisplayId = mFlinger->getHwComposer().getInternalHwcDisplayId(); if (hwcDisplayId) { ComposerExt::MSyncParamTableStruct mptb; mptb.disp_id = *hwcDisplayId; mptb.level_num = static_cast(numRecords); for (int i = 0; i < numRecords; i++) { ComposerExt::MSyncLevelTableStruct mltb; mltb.level_id = static_cast(data.readInt32()); mltb.level_fps = static_cast(data.readInt32()); mltb.max_fps = static_cast(data.readInt32()); mltb.min_fps = static_cast(data.readInt32()); mptb.level_tables.push_back(mltb); } mptb.max_fps = mptb.level_tables[0].max_fps; mptb.min_fps = mptb.level_tables[static_cast(numRecords-1)].min_fps; ALOGI("%s: max_fps=%u, min_fps=%u, level_num=%u", __func__, mptb.max_fps, mptb.min_fps, mptb.level_num); for (size_t i = 0; i < mptb.level_tables.size(); i++) { ALOGI("%s: level_id=%u, level_fps=%u, max_fps=%u, min_fps=%u", __func__, mptb.level_tables[i].level_id, mptb.level_tables[i].level_fps, mptb.level_tables[i].max_fps, mptb.level_tables[i].min_fps); } int ret = intf->msyncSetParamTable(mptb); ALOGE_IF(ret, "%s: msyncSetParamTable fail", __func__); } else { ALOGE("%s: internal hwcDisplayId invalid", __func__); } } else { ALOGE("%s: Cannot find hwcomposer ext", __func__); } #else ALOGE("%s: msync, MTK_COMPOSER_EXT not defined", __func__); #endif } void MSyncSfApi::getMSyncParamTable(Parcel* reply) { // adb shell service call SurfaceFlinger 9526105 #ifdef MTK_COMPOSER_EXT if (mFlinger->mMtkComposerExtIntf) { ::ComposerExt::ClientInterface* intf = mFlinger->mMtkComposerExtIntf; const auto hwcDisplayId = mFlinger->getHwComposer().getInternalHwcDisplayId(); if (hwcDisplayId) { ComposerExt::MSyncParamTableStruct tb; int ret = intf->msyncGetDefaultParamTable(*hwcDisplayId, tb); ALOGE_IF(ret, "%s: msyncGetDefaultParamTable fail", __func__); ALOGI("%s: max_fps=%u, min_fps=%u, level_num=%u", __func__, tb.max_fps, tb.min_fps, tb.level_num); if (reply != nullptr) { reply->writeUint32(tb.level_num); } for (size_t i = 0; i < tb.level_tables.size(); i++) { ALOGI("%s: level_id=%u, level_fps=%u, max_fps=%u, min_fps=%u", __func__, tb.level_tables[i].level_id, tb.level_tables[i].level_fps, tb.level_tables[i].max_fps, tb.level_tables[i].min_fps); if (reply != nullptr) { reply->writeUint32(tb.level_tables[i].level_id); reply->writeUint32(tb.level_tables[i].level_fps); reply->writeUint32(tb.level_tables[i].max_fps); reply->writeUint32(tb.level_tables[i].min_fps); } } } else { ALOGE("%s: internal hwcDisplayId invalid", __func__); } } else { ALOGE("%s: Cannot find hwcomposer ext", __func__); } #else ALOGE("%s: msync, MTK_COMPOSER_EXT not defined", __func__); #endif } #endif }; // namespace android