337 lines
11 KiB
C++
337 lines
11 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) 2010. 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.
|
|
*/
|
|
|
|
//#define LOG_NDEBUG 0
|
|
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
|
|
|
|
#include "SurfaceFlinger.h"
|
|
#include "mediatek/SFProperty.h"
|
|
|
|
#ifdef MTK_COMPOSER_EXT
|
|
#include <composer_ext_intf/client_interface.h>
|
|
#endif
|
|
|
|
#ifdef MTK_SF_MSYNC
|
|
#include "mediatek/MSync/MSyncSfApi.h"
|
|
#endif
|
|
|
|
#ifdef MTK_SF_CPU_POLICY
|
|
#include "mediatek/SfCpuPolicyAdapter/SfCpuPolicyAdapter.h"
|
|
#endif
|
|
|
|
#ifdef MTK_SF_OVL_ONLY_FOR_WIFI_DISPLAY
|
|
// This name will send form WifiDisplayAdapter.java
|
|
// function name "addDisplayDeviceLocked" to create WFD
|
|
#define WIFI_DISPLAY_PATTERN "isWifiDpyForHWC"
|
|
#endif
|
|
|
|
#ifdef MTK_SF_NOTIFY_EXPECTED_PRESENT_TIME
|
|
#ifdef MTK_COMPOSER_EXT
|
|
#include "Layer.h"
|
|
static std::vector<const char*> gEarlyPresentList = {
|
|
"com.tencent.tmgp.pubgmhd"
|
|
// , "com.tencent.tmgp"
|
|
// , "com.tencent.lolm"
|
|
// , "com.miHoYo"
|
|
// , "com.netease.hyxd"
|
|
// , "com.oplus.camera"
|
|
};
|
|
#endif
|
|
#endif
|
|
|
|
namespace android {
|
|
|
|
#ifdef MTK_SF_OVL_ONLY_FOR_WIFI_DISPLAY
|
|
bool SurfaceFlinger::specificKindDisplay(const std::string& dpyName) const {
|
|
if (mOvlOnlyForWifiDisplay == false) {
|
|
return false;
|
|
}
|
|
|
|
// For Wifi display
|
|
if (std::string::npos != dpyName.find(WIFI_DISPLAY_PATTERN)) {
|
|
ALOGI("%s dpyName:%s is WIFI display", __func__, dpyName.c_str());
|
|
return true;
|
|
} else {
|
|
ALOGI("%s dpyName:%s is not WIFI display", __func__, dpyName.c_str());
|
|
}
|
|
return false;
|
|
}
|
|
#endif
|
|
|
|
#ifdef MTK_SF_DEBUG_SUPPORT
|
|
void SurfaceFlinger::mtkDump(std::string& result) {
|
|
// for run-time enable property
|
|
SFProperty::getInstance().setMTKProperties(result, mDebugRegion);
|
|
}
|
|
|
|
status_t SurfaceFlinger::getProcessName(int pid, std::string& name) {
|
|
FILE *fp = fopen(String8::format("/proc/%d/cmdline", pid), "r");
|
|
if (fp != NULL) {
|
|
const size_t size = 64;
|
|
char proc_name[size] = {0};
|
|
char* result = fgets(proc_name, size - 1, fp);
|
|
int ret = fclose(fp);
|
|
if (CC_UNLIKELY(ret != 0)) {
|
|
ALOGE("%s(), fclose fail", __FUNCTION__);
|
|
}
|
|
if (CC_LIKELY(result != nullptr)) {
|
|
name = proc_name;
|
|
return NO_ERROR;
|
|
}
|
|
}
|
|
|
|
return INVALID_OPERATION;
|
|
}
|
|
#endif
|
|
|
|
#ifdef MTK_COMPOSER_EXT
|
|
class MtkComposerExtCallbackHandler : public ::ComposerExt::ConfigCallback {
|
|
public:
|
|
MtkComposerExtCallbackHandler(SurfaceFlinger& flinger)
|
|
: mFlinger(flinger) {
|
|
}
|
|
void NotifyTestCallback(bool value) {
|
|
ALOGI("NotifyTestCallback, %p, value %d", &mFlinger, value);
|
|
}
|
|
void NotifyHwcHwBinderTidCallback(int tid) {
|
|
ALOGI("NotifyHwcHwBinderTidCallback, %p, tid %d", &mFlinger, tid);
|
|
#ifdef MTK_SF_CPU_POLICY
|
|
mFlinger.notifyHwcHwbinderTid(tid);
|
|
#endif
|
|
}
|
|
private:
|
|
SurfaceFlinger& mFlinger;
|
|
};
|
|
|
|
MtkComposerExtCallbackHandler* mMtkComposerExtCallbackHandler = nullptr;
|
|
|
|
void SurfaceFlinger::initMtkComposerExt() {
|
|
if (mMtkComposerExtIntf) {
|
|
return;
|
|
}
|
|
|
|
mMtkComposerExtCallbackHandler = new MtkComposerExtCallbackHandler(*this);
|
|
int ret = ::ComposerExt::ClientInterface::create("SurfaceFlinger" + std::to_string(0),
|
|
mMtkComposerExtCallbackHandler,
|
|
&mMtkComposerExtIntf);
|
|
if (ret || !mMtkComposerExtIntf) {
|
|
ALOGE("ComposerExt HIDL not present\n");
|
|
mMtkComposerExtIntf = nullptr;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef MTK_VDS_HDCP
|
|
void SurfaceFlinger::setNextDisplayUsage(bool isWFD, bool isSecure) {
|
|
ALOGV("setNextDisplayUsage %d, %d", (isWFD?1:0), (isSecure?1:0));
|
|
#ifdef MTK_COMPOSER_EXT
|
|
if (mMtkComposerExtIntf) {
|
|
uint32_t vdsUsage = static_cast<uint32_t>(ComposerExt::DisplayUsage::kUnknown);
|
|
if (isWFD) vdsUsage |= static_cast<uint32_t>(ComposerExt::DisplayUsage::kIsWFD);
|
|
if (isSecure) vdsUsage |= static_cast<uint32_t>(ComposerExt::DisplayUsage::kIsSecure);
|
|
mMtkComposerExtIntf->setNextDisplayUsage(static_cast<ComposerExt::DisplayUsage>(vdsUsage));
|
|
ALOGI("mMtkComposerExtIntf->setNextDisplayUsage(%" PRIu32 ")", vdsUsage);
|
|
} else {
|
|
ALOGI("mMtkComposerExtIntf null");
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifdef MTK_ATRACE_PRESENT_FENCE
|
|
class FenceMonitor {
|
|
public:
|
|
explicit FenceMonitor(const char* name) : mName(name) {
|
|
std::thread thread(&FenceMonitor::loop, this);
|
|
pthread_setname_np(thread.native_handle(), mName);
|
|
thread.detach();
|
|
}
|
|
|
|
void queueFence(const sp<Fence>& fence) {
|
|
char message[64];
|
|
|
|
std::lock_guard<std::mutex> lock(mMutex);
|
|
if (fence->getSignalTime() != Fence::SIGNAL_TIME_PENDING) {
|
|
snprintf(message, sizeof(message), "%s fence %d has signaled", mName, fence->get());
|
|
ATRACE_NAME(message);
|
|
// Need an increment on both to make the trace number correct.
|
|
return;
|
|
}
|
|
snprintf(message, sizeof(message), "Trace %s fence %d", mName, fence->get());
|
|
ATRACE_NAME(message);
|
|
|
|
mQueue.push_back(fence);
|
|
mCondition.notify_one();
|
|
ATRACE_INT(mName, int32_t(mQueue.size()));
|
|
}
|
|
|
|
private:
|
|
#pragma clang diagnostic push
|
|
#pragma clang diagnostic ignored "-Wmissing-noreturn"
|
|
void loop() {
|
|
while (true) {
|
|
threadLoop();
|
|
}
|
|
}
|
|
#pragma clang diagnostic pop
|
|
|
|
void threadLoop() {
|
|
sp<Fence> fence;
|
|
{
|
|
std::unique_lock<std::mutex> lock(mMutex);
|
|
while (mQueue.empty()) {
|
|
mCondition.wait(lock);
|
|
}
|
|
fence = mQueue[0];
|
|
}
|
|
{
|
|
char message[64];
|
|
snprintf(message, sizeof(message), "waiting for %s %d", mName, fence->get());
|
|
ATRACE_NAME(message);
|
|
|
|
status_t result = fence->waitForever(message);
|
|
if (result != OK) {
|
|
ALOGE("Error waiting for fence: %d", result);
|
|
}
|
|
}
|
|
{
|
|
std::lock_guard<std::mutex> lock(mMutex);
|
|
mQueue.pop_front();
|
|
ATRACE_INT(mName, int32_t(mQueue.size()));
|
|
}
|
|
}
|
|
|
|
const char* mName;
|
|
std::deque<sp<Fence>> mQueue;
|
|
std::condition_variable mCondition;
|
|
std::mutex mMutex;
|
|
};
|
|
|
|
void SurfaceFlinger::trackPresentFence(const sp<Fence>& fence) {
|
|
static FenceMonitor presentFenceMonitor("presentFence");
|
|
presentFenceMonitor.queueFence(fence);
|
|
}
|
|
#endif
|
|
|
|
#ifdef MTK_SF_HINT_DISPLAY_INFO
|
|
void SurfaceFlinger::hintDisplayInfo(const int& policy, const bool& enable)
|
|
{
|
|
switch(policy) {
|
|
case Hwc2::impl::PowerAdvisor::MULTI_DISPLAY: {
|
|
const auto defaultdisplay = getDefaultDisplayDeviceLocked();
|
|
if (defaultdisplay && mRefreshRateConfigs) {
|
|
int32_t fps =
|
|
static_cast<int32_t>(mRefreshRateConfigs->getRefreshRateFromModeId(
|
|
defaultdisplay->getActiveMode()->getId()).getFps().getIntValue());
|
|
mPowerAdvisor.hintMultiDisplay(enable, fps);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef MTK_SF_MSYNC
|
|
bool SurfaceFlinger::isMsyncOn() const {
|
|
return mMSyncSfApi && mMSyncSfApi->isOn();
|
|
}
|
|
#endif
|
|
|
|
#ifdef MTK_COMPOSER_EXT
|
|
#ifdef MTK_SF_CPU_POLICY
|
|
void SurfaceFlinger::notifyHwcHwbinderTid(const int& tid) {
|
|
if (SfCpuPolicyAdapter::isEnabled()) {
|
|
SfCpuPolicyAdapter::getInstance(*mFrameTimeline).notifyHwcHwbinderTid(tid);
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef MTK_SF_CPU_POLICY
|
|
void SurfaceFlinger::notifyVpLpEnable(bool enable) {
|
|
if (SfCpuPolicyAdapter::isEnabled()) {
|
|
SfCpuPolicyAdapter::getInstance(*mFrameTimeline).notifyVpLpEnable(enable);
|
|
}
|
|
}
|
|
|
|
void SurfaceFlinger::notifyLayerConnect(const void * token, const std::string& name){
|
|
if (SfCpuPolicyAdapter::isEnabled()) {
|
|
SfCpuPolicyAdapter::getInstance(*mFrameTimeline).notifyLayerConnect(token, name);
|
|
}
|
|
}
|
|
void SurfaceFlinger::notifyLayerDisconnect(const void * token) {
|
|
if (SfCpuPolicyAdapter::isEnabled()) {
|
|
SfCpuPolicyAdapter::getInstance(*mFrameTimeline).notifyLayerDisconnect(token);
|
|
}
|
|
}
|
|
void SurfaceFlinger::notifyLayerSetBuffer(const void * token, const sp<GraphicBuffer>& buffer){
|
|
if (SfCpuPolicyAdapter::isEnabled()) {
|
|
SfCpuPolicyAdapter::getInstance(*mFrameTimeline).notifyLayerSetBuffer(token, buffer);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef MTK_SF_NOTIFY_EXPECTED_PRESENT_TIME
|
|
#ifdef MTK_COMPOSER_EXT
|
|
bool SurfaceFlinger::needSkipNotifyPresentTime(Layer *layer) {
|
|
if (layer == nullptr) {
|
|
ALOGE("needSkipNotifyPresentTime layer should not be null");
|
|
return false;
|
|
}
|
|
if (layer->getDebugName() == nullptr) {
|
|
ALOGE("needSkipNotifyPresentTime layer name should not be null");
|
|
return false;
|
|
}
|
|
if (layer->getNotifyState() == Layer::NotifyState::UNKNOWN) {
|
|
layer->setNotifyState(Layer::NotifyState::NOTIFY);
|
|
for (const auto& name : gEarlyPresentList) {
|
|
if (strstr(layer->getDebugName(), name) != nullptr) {
|
|
layer->setNotifyState(Layer::NotifyState::SKIP);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (layer->getNotifyState() == Layer::NotifyState::NOTIFY) {
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
}; // namespace android
|