448 lines
17 KiB
C++
448 lines
17 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"
|
|
#include "FrontEnd/LayerHandle.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,
|
|
[](const sp<IBinder>& binder) {
|
|
sp<Layer> layer = nullptr;
|
|
if (binder) {
|
|
layer = LayerHandle::getLayer(binder);
|
|
}
|
|
return layer.get();
|
|
},
|
|
[this](const sp<IBinder>& binder) {
|
|
if (binder) {
|
|
return mFlinger->mBufferCountTracker.getBufferCount(binder->localBinder());
|
|
}
|
|
return 0;
|
|
},
|
|
[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]() {
|
|
if (auto schedule = mFlinger->mScheduler->getVsyncSchedule()) {
|
|
return schedule->period().ns();
|
|
}
|
|
return static_cast<nsecs_t>(0);
|
|
},
|
|
[this](bool bTriggerVsyncCallback) {
|
|
//if (auto schedule = mFlinger->mScheduler->getVsyncSchedule()) {
|
|
mFlinger->mScheduler->msyncVsyncCallback(bTriggerVsyncCallback);
|
|
//}
|
|
},
|
|
[this]() {
|
|
mFlinger->mScheduler->scheduleFrame();
|
|
},
|
|
[this]() {
|
|
#ifdef MTK_COMPOSER_EXT
|
|
if (mFlinger->mMtkComposerExtIntf) {
|
|
::ComposerExt::ClientInterface* intf = mFlinger->mMtkComposerExtIntf;
|
|
const auto hwcDisplayId = mFlinger->getHwComposer().getPrimaryHwcDisplayId();
|
|
|
|
//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().getPrimaryHwcDisplayId();
|
|
|
|
//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::commit() {
|
|
if (mFuncCommit) {
|
|
mFuncCommit(mMSyncController);
|
|
}
|
|
}
|
|
|
|
void MSyncSfApi::composite(sp<const DisplayDevice> display,
|
|
const std::vector<sp<DisplayDevice>>& displays) {
|
|
if (!mFuncComposite) {
|
|
return;
|
|
}
|
|
|
|
//ATRACE_NAME("msync2_sf: composite");
|
|
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;
|
|
}
|
|
}
|
|
|
|
mFuncComposite(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::setSFInProgress(bool bSFInProgress) {
|
|
if (mFuncSetSFInProgress) {
|
|
mFuncSetSFInProgress(mMSyncController, bSFInProgress);
|
|
}
|
|
}
|
|
|
|
bool MSyncSfApi::isQ2QFull() {
|
|
if (mFuncIsQ2QFull) {
|
|
return mFuncIsQ2QFull(mMSyncController);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void MSyncSfApi::setTransactionState(const std::vector<std::tuple<sp<IBinder>, bool, bool, sp<Fence>>>& states, nsecs_t lastVsyncWakeupTime) {
|
|
if (!mFuncSetTransactionState) {
|
|
return;
|
|
}
|
|
|
|
/*std::vector<std::tuple<sp<IBinder>, bool, bool, sp<Fence>>> layerStates;
|
|
for (const Msync2TransactionState& state : states) {
|
|
//const layer_state_t& s = state.state;
|
|
|
|
layerStates.emplace_back(s.surface,
|
|
s.hasBufferChanges(),
|
|
s.bufferData && s.bufferData->flags.test(
|
|
BufferData::BufferDataChange::fenceChanged),
|
|
s.bufferData ? s.bufferData->acquireFence : nullptr);
|
|
sp<Layer> layer = Layer::fromHandle(s.surface).promote();
|
|
std::string result = base::StringPrintf("Msync2: setTransactionState, name=%s, hasBufferChanges=%d", layer->getName().c_str(), s.hasBufferChanges());
|
|
ALOGI("%s", result.c_str());
|
|
ATRACE_NAME(result.c_str());
|
|
}*/
|
|
|
|
mFuncSetTransactionState(mMSyncController, states, lastVsyncWakeupTime);
|
|
}
|
|
|
|
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(mFuncCommit, FuncCommit, "commit");
|
|
FN_DLSYM(mFuncComposite, FuncComposite, "composite");
|
|
FN_DLSYM(mFuncSetTransactionState, FuncSetTransactionState, "setTransactionState");
|
|
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");
|
|
FN_DLSYM(mFuncSetSFInProgress, FuncSetSFInProgress, "setSFInProgress");
|
|
FN_DLSYM(mFuncIsQ2QFull, FuncIsQ2QFull, "isQ2QFull");
|
|
} 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().getPrimaryHwcDisplayId();
|
|
/*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().getPrimaryHwcDisplayId();
|
|
/*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
|