unplugged-vendor/frameworks/native/services/surfaceflinger/mediatek/SurfaceFlinger.cpp

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