Files
BPI-CM9-Linux/aml-comp/vendor/amlogic/meson_videoserver/display/DisplayThread.cpp
T
2026-08-24 10:03:24 +08:00

112 lines
3.0 KiB
C++

/*
* Copyright (C) 2024 Amlogic Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <sys/prctl.h>
#include "DisplayThread.h"
#include "DispAdptLog.h"
DisplayThread::DisplayThread(MesonDisplay *display)
{
int32_t ret;
mDisplay = display;
mExit = false;
needRefresh = false;
snprintf(mName, 64, "DisplayThread-%d", mDisplay->getDisplayId());
ret = pthread_create(&mThread, NULL, DisplayThreadMain, (void *)this);
if (ret) {
DISPLAY_LOGE("%s %s, failed to create VideoTunnel CmdThread: %s",
mName, __func__, strerror(ret));
}
}
DisplayThread::~DisplayThread()
{
mExit = true;
pthread_join(mThread, NULL);
}
void DisplayThread::onVsync(int64_t timestamp, uint32_t vsyncPeriodNanos)
{
std::unique_lock<std::mutex> stateLock(mMutex);
needRefresh = true;
stateLock.unlock();
mCondition.notify_all();
}
void DisplayThread::onFrameAvailableForGameMode()
{
std::unique_lock<std::mutex> stateLock(mMutex);
needRefresh = true;
stateLock.unlock();
mCondition.notify_all();
}
void* DisplayThread::DisplayThreadMain(void *data) {
DisplayThread* pThis = (DisplayThread*)data;
prctl(PR_SET_NAME, "displayThread");
// set videotunnel thread to SCHED_FIFO to minimize jitter
struct sched_param param = {0};
param.sched_priority = sched_get_priority_max(SCHED_FIFO);
if (sched_setscheduler(0, SCHED_FIFO, &param) != 0) {
DISPLAY_LOGE("%s %s, Couldn't set SCHED_FIFO for videotunnelthread",
pThis->mName, __func__);
}
while (true) {
if (pThis->mExit) {
DISPLAY_LOGD("%s %s, VtDisplayThread exit video tunnel loop",
pThis->mName, __func__);
pthread_exit(0);
return NULL;
}
pThis->handleDisplay();
}
}
void DisplayThread::handleDisplay()
{
int32_t outPresentFence = -1;
long long time;
std::unique_lock<std::mutex> stateLock(mMutex);
while (!needRefresh) {
mCondition.wait(stateLock);
}
needRefresh = false;
stateLock.unlock();
// run display
do {
mDisplay->setLayersPresentTime();
if (mDisplay->handleDisplayConnection()) {
time = DispAdptGetCurrentTime();
mDisplay->validateDisplay(NULL, NULL);
mDisplay->presentDisplay(&outPresentFence);
mDisplay->setVsyncDelayLatency(DispAdptGetCurrentTime() - time);
if (outPresentFence >= 0)
close(outPresentFence);
}
mDisplay->releaseLayers();
} while (mDisplay->newGameBuffer());
}