unplugged-vendor/frameworks/native/services/surfaceflinger/mediatek/MSync/MSyncSfApi.cpp

423 lines
16 KiB
C++

/* 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 <dlfcn.h>
#include <binder/IBinder.h>
#include <binder/Parcel.h>
#include <gui/LayerState.h>
#include <ui/Fence.h>
#include "DisplayDevice.h"
#include "Layer.h"
#include "Scheduler/MessageQueue.h"
#include "SurfaceFlinger.h"
#ifdef MTK_COMPOSER_EXT
#include <composer_ext_intf/client_interface.h>
#endif
#define LIBRARY_NAME "libmtk_sf_msync_2_0.so"
using std::endl;
namespace android {
#ifdef MTK_SF_MSYNC
MSyncSfApi::MSyncSfApi(const sp<SurfaceFlinger>& 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<IBinder>& binder) {
sp<Layer> layer = nullptr;
if (binder) {
layer = mFlinger->fromHandle(binder).promote();
}
return layer.get();
},
[this](std::function<void(const void*)> func) {
mFlinger->mDrawingState.traverseInZOrder([&](Layer* layer) {
if (layer->isVisible()) {
func(layer);
}
});
},
[this](std::function<void(const void*, float, bool)> func) {
std::vector<const void*> 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<const DisplayDevice> display,
const std::vector<sp<DisplayDevice>>& 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<uint32_t>(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<Fence>& previousPresentFence) {
if (mFuncSetPreviousPresentFence) {
mFuncSetPreviousPresentFence(mMSyncController, previousPresentFence);
}
}
void MSyncSfApi::setTransactionState(const Vector<ComposerState>& states) {
if (!mFuncSetTransactionState) {
return;
}
std::vector<std::tuple<sp<IBinder>, bool, bool, sp<Fence>>> 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<funcType>(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<uint32_t>(numRecords);
for (int i = 0; i < numRecords; i++) {
ComposerExt::MSyncLevelTableStruct mltb;
mltb.level_id = static_cast<uint32_t>(data.readInt32());
mltb.level_fps = static_cast<uint32_t>(data.readInt32());
mltb.max_fps = static_cast<uint32_t>(data.readInt32());
mltb.min_fps = static_cast<uint32_t>(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<size_t>(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