You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
199 lines
6.2 KiB
199 lines
6.2 KiB
4 months ago
|
/*
|
||
|
* Copyright (c) Hisilicon Technologies Co., Ltd.. 2020-2020. All rights reserved.
|
||
|
* Description: On behalf of a display device, hwcomposer is called for composition and sent for display
|
||
|
* Author: Hisilicon
|
||
|
* Created: 2020.08.04
|
||
|
*/
|
||
|
#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
|
||
|
#include <utils/Trace.h>
|
||
|
#include <log/log.h>
|
||
|
#include <securec.h>
|
||
|
#include "FenceMonitor.h"
|
||
|
|
||
|
namespace android {
|
||
|
HwcLayerFence::HwcLayerFence(const sp<Fence> &fence, hwc2_layer_t layerId, uint64_t seq)
|
||
|
: m_fence(fence), m_layerid(layerId), m_seq(seq)
|
||
|
{}
|
||
|
|
||
|
HwcLayerFence::~HwcLayerFence() {}
|
||
|
|
||
|
nsecs_t HwcLayerFence::GetSignalTime() const
|
||
|
{
|
||
|
return m_fence->getSignalTime();
|
||
|
}
|
||
|
|
||
|
status_t HwcLayerFence::WaitForever(std::string msg)
|
||
|
{
|
||
|
return m_fence->waitForever(msg.c_str());
|
||
|
}
|
||
|
|
||
|
int HwcLayerFence::Get() const
|
||
|
{
|
||
|
return m_fence->get();
|
||
|
}
|
||
|
|
||
|
bool HwcLayerFence::HasSignaled() const
|
||
|
{
|
||
|
return (m_fence->getSignalTime() != Fence::SIGNAL_TIME_PENDING);
|
||
|
}
|
||
|
|
||
|
const sp<Fence> &HwcLayerFence::GetFence()
|
||
|
{
|
||
|
return m_fence;
|
||
|
}
|
||
|
|
||
|
std::string HwcLayerFence::GetString() const
|
||
|
{
|
||
|
std::stringstream os;
|
||
|
os << " ";
|
||
|
os << "layer_id:" << m_layerid << " fence seq:" << m_seq << " State: " << (HasSignaled() ? "Signaled" : "Waiting");
|
||
|
if (!HasSignaled() && (m_timestamp != 0)) {
|
||
|
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
|
||
|
double dur = (now - m_timestamp) / static_cast<double>((TIME_CONVERSION_LEVEL * TIME_CONVERSION_LEVEL));
|
||
|
os << " for " << dur << " ms";
|
||
|
}
|
||
|
return os.str();
|
||
|
}
|
||
|
|
||
|
hwc2_layer_t HwcLayerFence::GetLayerId() const
|
||
|
{
|
||
|
return m_layerid;
|
||
|
}
|
||
|
|
||
|
uint64_t HwcLayerFence::GetSeq() const
|
||
|
{
|
||
|
return m_seq;
|
||
|
}
|
||
|
|
||
|
inline void HwcLayerFence::UpdateTimeStamp()
|
||
|
{
|
||
|
if (m_timestamp == 0) {
|
||
|
m_timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
FenceMonitor::FenceMonitor(const std::string &name) : mName(name), mFencesQueued(0), mFencesSignaled(0)
|
||
|
{
|
||
|
std::thread thread(&FenceMonitor::Loop, this);
|
||
|
pthread_setname_np(thread.native_handle(), mName.c_str());
|
||
|
thread.detach();
|
||
|
}
|
||
|
|
||
|
FenceMonitor::~FenceMonitor() {}
|
||
|
|
||
|
std::string FenceMonitor::Dump()
|
||
|
{
|
||
|
std::stringstream os;
|
||
|
std::lock_guard<std::mutex> lock(mMutex);
|
||
|
os << mName << ":" << std::endl;
|
||
|
for (auto fence = mQueue.cbegin(); fence != mQueue.cend(); ++fence) {
|
||
|
os << " " << (*fence)->GetString() << std::endl;
|
||
|
}
|
||
|
return os.str();
|
||
|
}
|
||
|
|
||
|
void FenceMonitor::QueueFence(const sp<HwcLayerFence> &fence)
|
||
|
{
|
||
|
const int maxMsgLen = 100;
|
||
|
char message[maxMsgLen] = {0};
|
||
|
std::lock_guard<std::mutex> lock(mMutex);
|
||
|
if (fence->GetSignalTime() != Fence::SIGNAL_TIME_PENDING) {
|
||
|
int ret = snprintf_s(message, sizeof(message), sizeof(message) - 1, "%s fence:%llu %llu - %llu has signaled",
|
||
|
mName.c_str(), fence->GetSeq(), fence->GetLayerId(), mFencesQueued);
|
||
|
HWC_CHK_RETURN_NOT_VALUE((ret < 0), ALOGE("snprintf_s message failed(0x%x)", ret));
|
||
|
ATRACE_NAME(message);
|
||
|
// Need an increment on both to make the trace number correct.
|
||
|
mFencesQueued++;
|
||
|
mFencesSignaled++;
|
||
|
return;
|
||
|
}
|
||
|
int ret = snprintf_s(message, sizeof(message), sizeof(message) - 1, "Trace %s fence:%llu %llu - %llu",
|
||
|
mName.c_str(), fence->GetSeq(), fence->GetLayerId(), mFencesQueued);
|
||
|
HWC_CHK_RETURN_NOT_VALUE((ret < 0), ALOGE("snprintf_s message failed(0x%x)", ret));
|
||
|
ATRACE_NAME(message);
|
||
|
fence->UpdateTimeStamp();
|
||
|
mQueue.push_back(fence);
|
||
|
mCondition.notify_one();
|
||
|
mFencesQueued++;
|
||
|
ATRACE_INT(mName.c_str(), int32_t(mQueue.size()));
|
||
|
}
|
||
|
|
||
|
#pragma clang diagnostic push
|
||
|
#pragma clang diagnostic ignored "-Wmissing-noreturn"
|
||
|
void FenceMonitor::Loop()
|
||
|
{
|
||
|
while (true) {
|
||
|
ThreadLoop();
|
||
|
}
|
||
|
}
|
||
|
#pragma clang diagnostic pop
|
||
|
|
||
|
void FenceMonitor::ThreadLoop()
|
||
|
{
|
||
|
sp<HwcLayerFence> fence;
|
||
|
const int maxMsgLen = 100;
|
||
|
uint64_t fenceNum;
|
||
|
{
|
||
|
std::unique_lock<std::mutex> lock(mMutex);
|
||
|
while (mQueue.empty()) {
|
||
|
mCondition.wait(lock);
|
||
|
}
|
||
|
fence = mQueue[0];
|
||
|
fenceNum = mFencesSignaled;
|
||
|
}
|
||
|
{
|
||
|
char message[maxMsgLen] = {0};
|
||
|
if (fence->GetSignalTime() != Fence::SIGNAL_TIME_PENDING) {
|
||
|
int ret = snprintf_s(message, sizeof(message), sizeof(message) - 1,
|
||
|
"%s fence:%llu %llu - %llu has signaled", mName.c_str(), fence->GetSeq(),
|
||
|
fence->GetLayerId(), fenceNum);
|
||
|
HWC_CHK_RETURN_NOT_VALUE((ret < 0), ALOGE("snprintf_s message failed(0x%x)", ret));
|
||
|
ATRACE_NAME(message);
|
||
|
} else {
|
||
|
int ret = snprintf_s(message, sizeof(message), sizeof(message) - 1, "waiting for %s:%llu %llu - %llu",
|
||
|
mName.c_str(), fence->GetSeq(), fence->GetLayerId(), fenceNum);
|
||
|
HWC_CHK_RETURN_NOT_VALUE((ret < 0), ALOGE("snprintf_s message failed(0x%x)", ret));
|
||
|
ATRACE_NAME(message);
|
||
|
std::string msg = message;
|
||
|
status_t result = fence->WaitForever(msg);
|
||
|
if (result != OK) {
|
||
|
ALOGE("Error waiting for fence: %d", result);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
{
|
||
|
std::lock_guard<std::mutex> lock(mMutex);
|
||
|
mQueue.pop_front();
|
||
|
mFencesSignaled++;
|
||
|
ATRACE_INT(mName.c_str(), int32_t(mQueue.size()));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
FenceMonitorMng::FenceMonitorMng() {}
|
||
|
|
||
|
FenceMonitorMng::~FenceMonitorMng() {}
|
||
|
|
||
|
void FenceMonitorMng::AddFence(int fd, FENCE_TYPE type, hwc2_layer_t layerid, uint64_t seq)
|
||
|
{
|
||
|
if (type >= FENCE_TYPE_ENUM::FENCE_TYPE_NUM) {
|
||
|
return;
|
||
|
}
|
||
|
if (m_fenceMonior[(int)type] == nullptr) {
|
||
|
m_fenceMonior[(int)type] = std::make_unique<FenceMonitor>(G_FENCE_TYPE_NMAE[(int)type]);
|
||
|
}
|
||
|
m_fenceMonior[(int)type]->QueueFence(new HwcLayerFence(new Fence(dup(fd)), layerid, seq));
|
||
|
}
|
||
|
|
||
|
std::string FenceMonitorMng::Dump() const
|
||
|
{
|
||
|
std::stringstream os;
|
||
|
os << "HWC fence monitor:" << std::endl;
|
||
|
for (int i = 0; i < static_cast<int>(FENCE_TYPE_ENUM::FENCE_TYPE_NUM); i++) {
|
||
|
if (m_fenceMonior[i] != nullptr) {
|
||
|
os << " " << m_fenceMonior[i]->Dump() << std::endl;
|
||
|
}
|
||
|
}
|
||
|
return os.str();
|
||
|
}
|
||
|
} // end namespace
|