Fixes a number of playback stuttering and general UI lag issues by setting all background tasks to IdlePriority rather than LowPriority. While it was assumed LowPriority tasks would always get scheduled below NormalPriority (e.g. main thread) tasks, it turns out this is not always the case. If the background tasks start consuming a lot of CPU cycles, the scheduler may use "dynamic scheduling" to schedule them above the main thread regardless leading to UI lag. This is apparently the case for all thread priorities apart from IdlePriority, which is allegedly a special case where threads are *only* scheduled when other threads aren't busy ensuring the main thread stays responsive.
80 lines
1.8 KiB
C++
80 lines
1.8 KiB
C++
#include "openglbackend.h"
|
|
|
|
#include <QEventLoop>
|
|
#include <QThread>
|
|
|
|
#include "openglrenderfunctions.h"
|
|
|
|
OpenGLBackend::OpenGLBackend(QObject *parent) :
|
|
VideoRenderBackend(parent),
|
|
proxy_(nullptr)
|
|
{
|
|
}
|
|
|
|
OpenGLBackend::~OpenGLBackend()
|
|
{
|
|
Close();
|
|
}
|
|
|
|
bool OpenGLBackend::InitInternal()
|
|
{
|
|
if (!VideoRenderBackend::InitInternal()) {
|
|
return false;
|
|
}
|
|
|
|
proxy_ = new OpenGLProxy();
|
|
proxy_->SetParameters(params());
|
|
QThread* proxy_thread = new QThread();
|
|
proxy_thread->start(QThread::IdlePriority);
|
|
proxy_->moveToThread(proxy_thread);
|
|
|
|
if (!proxy_->Init()) {
|
|
proxy_thread->quit();
|
|
proxy_thread->wait();
|
|
delete proxy_thread;
|
|
delete proxy_;
|
|
return false;
|
|
}
|
|
|
|
// Initiate one thread per CPU core
|
|
for (int i=0;i<threads().size();i++) {
|
|
// Create one processor object for each thread
|
|
OpenGLWorker* processor = new OpenGLWorker(frame_cache(), decoder_cache());
|
|
processor->SetParameters(params());
|
|
processors_.append(processor);
|
|
|
|
connect(processor, &OpenGLWorker::RequestFrameToValue, proxy_, &OpenGLProxy::FrameToValue, Qt::BlockingQueuedConnection);
|
|
connect(processor, &OpenGLWorker::RequestTextureToBuffer, proxy_, &OpenGLProxy::TextureToBuffer, Qt::BlockingQueuedConnection);
|
|
connect(processor, &OpenGLWorker::RequestRunNodeAccelerated, proxy_, &OpenGLProxy::RunNodeAccelerated, Qt::BlockingQueuedConnection);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void OpenGLBackend::CloseInternal()
|
|
{
|
|
if (proxy_) {
|
|
delete proxy_;
|
|
proxy_ = nullptr;
|
|
}
|
|
|
|
VideoRenderBackend::CloseInternal();
|
|
}
|
|
|
|
bool OpenGLBackend::CompileInternal()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
void OpenGLBackend::DecompileInternal()
|
|
{
|
|
}
|
|
|
|
void OpenGLBackend::ParamsChangedEvent()
|
|
{
|
|
// If we're initiated, we need to recreate the texture. Otherwise this backend isn't active so it doesn't matter.
|
|
if (IsInitiated()) {
|
|
proxy_->SetParameters(params());
|
|
}
|
|
}
|