fixed various issues with threading

This commit is contained in:
itsmattkc
2019-01-15 22:01:51 +11:00
parent 13d30ab06a
commit e1ec2f6fbe
16 changed files with 339 additions and 115 deletions
+1 -1
View File
@@ -425,7 +425,7 @@ GLuint compose_sequence(Viewer* viewer,
glBindTexture(GL_TEXTURE_2D, 0); // unbind texture
// TODO restore this function
/*if (gizmos != nullptr && !drawn_gizmos && nests.isEmpty()) {
/*if ((*gizmos) != nullptr && !drawn_gizmos && nests.isEmpty()) {
(*gizmos)->gizmo_draw(timecode, coords); // set correct gizmo coords
(*gizmos)->gizmo_world_to_screen();
+24 -5
View File
@@ -7,12 +7,16 @@
#include "ui/renderfunctions.h"
#include "playback/playback.h"
#include "project/sequence.h"
RenderThread::RenderThread() :
share_ctx(nullptr),
ctx(nullptr),
frameBuffer(0),
texColorBuffer(0)
texColorBuffer(0),
tex_width(-1),
tex_height(-1),
queued(false)
{
surface.create();
}
@@ -27,7 +31,10 @@ void RenderThread::run() {
bool running = true;
while (running) {
waitCond.wait(&mutex);
if (!queued) {
waitCond.wait(&mutex);
}
queued = false;
if (share_ctx != nullptr) {
if (ctx == nullptr) {
@@ -48,12 +55,20 @@ void RenderThread::run() {
ctx->functions()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBuffer);
// gen texture
if (texColorBuffer == 0) {
if (texColorBuffer == 0 || tex_width != seq->width || tex_height != seq->height) {\
if (texColorBuffer > 0) {
ctx->functions()->glFramebufferTexture2D(
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0
);
glDeleteTextures(1, &texColorBuffer);
}
glGenTextures(1, &texColorBuffer);
glBindTexture(GL_TEXTURE_2D, texColorBuffer);
glTexImage2D(
GL_TEXTURE_2D, 0, GL_RGB, 1920, 1080, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr
GL_TEXTURE_2D, 0, GL_RGB, seq->width, seq->height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr
);
tex_width = seq->width;
tex_height = seq->height;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
ctx->functions()->glFramebufferTexture2D(
@@ -70,12 +85,15 @@ void RenderThread::run() {
// release
ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER, 0);
emit ready();
}
}
}
if (ctx != nullptr) {
if (frameBuffer != 0) ctx->functions()->glDeleteFramebuffers(1, &frameBuffer);
if (texColorBuffer > 0) glDeleteTextures(1, &texColorBuffer);
if (frameBuffer > 0) ctx->functions()->glDeleteFramebuffers(1, &frameBuffer);
ctx->doneCurrent();
delete ctx;
}
@@ -110,5 +128,6 @@ void RenderThread::paint() {
void RenderThread::start_render(QOpenGLContext *share, Sequence *s, int idivider) {
share_ctx = share;
seq = s;
queued = true;
waitCond.wakeAll();
}
+6
View File
@@ -11,6 +11,7 @@
struct Sequence;
class RenderThread : public QThread {
Q_OBJECT
public:
RenderThread();
~RenderThread();
@@ -20,6 +21,8 @@ public:
GLuint texColorBuffer;
void paint();
void start_render(QOpenGLContext* share, Sequence* s, int idivider = 0);
signals:
void ready();
private:
QWaitCondition waitCond;
QOffscreenSurface surface;
@@ -27,6 +30,9 @@ private:
QOpenGLContext* ctx;
Sequence* seq;
int divider;
int tex_width;
int tex_height;
bool queued;
};
#endif // RENDERTHREAD_H
+160 -60
View File
@@ -23,6 +23,8 @@
#include "ui/timelinewidget.h"
#include "ui/renderfunctions.h"
#include "ui/renderthread.h"
#include "Ui/viewerwindow.h"
#include "mainwindow.h"
#include <QPainter>
#include <QAudioOutput>
@@ -39,6 +41,8 @@
#include <QDesktopWidget>
#include <QInputDialog>
#include <QApplication>
#include <QScreen>
#include <QMessageBox>
extern "C" {
#include <libavformat/avformat.h>
@@ -53,7 +57,8 @@ ViewerWidget::ViewerWidget(QWidget *parent) :
dragging(false),
gizmos(nullptr),
selected_gizmo(nullptr),
just_repaint(false)
just_repaint(false),
window(nullptr)
{
setMouseTracking(true);
setFocusPolicy(Qt::ClickFocus);
@@ -62,15 +67,19 @@ ViewerWidget::ViewerWidget(QWidget *parent) :
format.setDepthBufferSize(24);
setFormat(format);
// error handler - retries after 50ms if we couldn't get the entire image
retry_timer.setInterval(50);
connect(&retry_timer, SIGNAL(timeout()), this, SLOT(retry()));
setContextMenuPolicy(Qt::CustomContextMenu);
connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(show_context_menu()));
renderer = new RenderThread();
renderer->start(QThread::HighPriority);
connect(renderer, SIGNAL(ready()), this, SLOT(queue_repaint()));
}
ViewerWidget::~ViewerWidget() {
if (window != nullptr) {
window->close();
delete window;
}
}
void ViewerWidget::delete_function() {
@@ -95,8 +104,18 @@ void ViewerWidget::show_context_menu() {
QAction* save_frame_as_image = menu.addAction(tr("Save Frame as Image..."));
connect(save_frame_as_image, SIGNAL(triggered(bool)), this, SLOT(save_frame()));
QAction* show_fullscreen_action = menu.addAction(tr("Show Fullscreen"));
connect(show_fullscreen_action, SIGNAL(triggered()), this, SLOT(show_fullscreen()));
/*QAction* show_fullscreen_action = menu.addAction(tr("Show Fullscreen"));
connect(show_fullscreen_action, SIGNAL(triggered()), this, SLOT(show_fullscreen()));*/
QMenu* fullscreen_menu = menu.addMenu(tr("Show Fullscreen"));
QList<QScreen*> screens = QGuiApplication::screens();
for (int i=0;i<screens.size();i++) {
QAction* screen_action = fullscreen_menu->addAction(tr("Screen %1: %2x%3").arg(
QString::number(i),
QString::number(screens.at(i)->size().width()),
QString::number(screens.at(i)->size().height())));
screen_action->setData(i);
}
connect(fullscreen_menu, SIGNAL(triggered(QAction*)), this, SLOT(fullscreen_menu_action(QAction*)));
QMenu zoom_menu(tr("Zoom"));
QAction* fit_zoom = zoom_menu.addAction(tr("Fit"));
@@ -153,8 +172,20 @@ void ViewerWidget::save_frame() {
}
}
void ViewerWidget::show_fullscreen() {
showFullScreen();
void ViewerWidget::queue_repaint() {
just_repaint = true;
update();
}
void ViewerWidget::fullscreen_menu_action(QAction *action) {
if (window == nullptr) {
QMessageBox::critical(this, "Error", "Failed to create viewer window");
} else {
QScreen* selected_screen = QGuiApplication::screens().at(action->data().toInt());
window->showFullScreen();
window->setGeometry(selected_screen->geometry());
// window->show();
}
}
void ViewerWidget::set_fit_zoom() {
@@ -193,19 +224,41 @@ void ViewerWidget::initializeGL() {
connect(context(), SIGNAL(aboutToBeDestroyed()), this, SLOT(delete_function()), Qt::DirectConnection);
retry_timer.start();
if (window != nullptr) {
delete window;
}
window = new ViewerWindow(context());
// retry_timer.start();
}
void ViewerWidget::frame_update() {
if (viewer->seq != nullptr) {
gizmos = nullptr;
drawn_gizmos = false;
force_quit = false;
bool render_audio = (viewer->playing || rendering);
// send context to other thread for drawing
doneCurrent();
renderer->start_render(context(), viewer->seq);
// render the audio
QVector<Clip*> nests;
compose_sequence(viewer, context(), viewer->seq, nests, false, render_audio, &gizmos);
}
}
//void ViewerWidget::resizeGL(int w, int h)
//{
//}
void ViewerWidget::paintEvent(QPaintEvent *e) {
if (!rendering && context()->thread() == this->thread()) {
makeCurrent();
/*void ViewerWidget::paintEvent(QPaintEvent *e) {
if (!rendering) {
QOpenGLWidget::paintEvent(e);
}
}
}*/
void ViewerWidget::seek_from_click(int x) {
viewer->seek(getFrameFromScreenPoint(waveform_zoom, x+waveform_scroll));
@@ -393,8 +446,51 @@ void ViewerWidget::drawTitleSafeArea() {
}
void ViewerWidget::paintGL() {
retry_timer.stop();
if (renderer->mutex.tryLock(10)) {
makeCurrent();
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, renderer->texColorBuffer);
glLoadIdentity();
glOrtho(0, 1, 1, 0, -1, 1);
glBegin(GL_QUADS);
glVertex2f(0, 0);
glTexCoord2f(0, 0);
glVertex2f(0, 1);
glTexCoord2f(1, 0);
glVertex2f(1, 1);
glTexCoord2f(1, 1);
glVertex2f(1, 0);
glTexCoord2f(0, 1);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
if (window != nullptr && window->isVisible()) {
window->set_texture(renderer->texColorBuffer, double(viewer->seq->width)/double(viewer->seq->height));
}
renderer->mutex.unlock();
if (texture_failed) {
doneCurrent();
renderer->start_render(context(), viewer->seq);
}
}
// retry_timer.stop();
/*
if (viewer->seq != nullptr) {
gizmos = nullptr;
drawn_gizmos = false;
@@ -410,53 +506,57 @@ void ViewerWidget::paintGL() {
// render the audio
QVector<Clip*> nests;
compose_sequence(viewer, context(), viewer->seq, nests, false, render_audio, &gizmos);
}
// try to draw the texture from the other thread if we got it
if (renderer->mutex.tryLock(10)) {
makeCurrent();
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, renderer->texColorBuffer);
glLoadIdentity();
glOrtho(0, 1, 1, 0, -1, 1);
glBegin(GL_QUADS);
glVertex2f(0, 0);
glTexCoord2f(0, 0);
glVertex2f(0, 1);
glTexCoord2f(1, 0);
glVertex2f(1, 1);
glTexCoord2f(1, 1);
glVertex2f(1, 0);
glTexCoord2f(0, 1);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
renderer->mutex.unlock();
if (texture_failed) {
qDebug() << "texture failed, retry called";
retry_timer.start();
}
} else {
qDebug() << "renderer failed, retry called";
retry_timer.start();
just_repaint = true;
}
}
// try to draw the texture from the other thread if we got it
// if (renderer->mutex.tryLock(10)) {
makeCurrent();
just_repaint = false;
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, renderer->texColorBuffer);
glLoadIdentity();
glOrtho(0, 1, 1, 0, -1, 1);
glBegin(GL_QUADS);
glVertex2f(0, 0);
glTexCoord2f(0, 0);
glVertex2f(0, 1);
glTexCoord2f(1, 0);
glVertex2f(1, 1);
glTexCoord2f(1, 1);
glVertex2f(1, 0);
glTexCoord2f(0, 1);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
if (window != nullptr && window->isVisible()) {
window->set_texture(renderer->texColorBuffer, double(viewer->seq->width)/double(viewer->seq->height));
}
// renderer->mutex.unlock();
// if (texture_failed) {
// qDebug() << "texture failed, retry called";
// retry_timer.start();
// }
// } else {
// qDebug() << "renderer failed, retry called";
// retry_timer.start();
// just_repaint = true;
// }
}
just_repaint = false;
}*/
/*drawn_gizmos = false;
+8 -7
View File
@@ -19,12 +19,14 @@ class EffectGizmo;
class ViewerContainer;
struct GLTextureCoords;
class RenderThread;
class ViewerWindow;
class ViewerWidget : public QOpenGLWidget, QOpenGLFunctions
{
Q_OBJECT
public:
ViewerWidget(QWidget *parent = 0);
~ViewerWidget();
void paintGL();
void initializeGL();
@@ -40,23 +42,21 @@ public:
int waveform_scroll;
bool force_quit;
void frame_update();
public slots:
void delete_function();
void set_waveform_scroll(int s);
protected:
void paintEvent(QPaintEvent *e);
// void paintEvent(QPaintEvent *e);
// void resizeGL(int w, int h);
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
private:
QTimer retry_timer;
void drawTitleSafeArea();
bool dragging;
void seek_from_click(int x);
// GLuint compose_sequence(QVector<Clip *> &nests, bool video, bool render_audio);
// GLuint draw_clip(QOpenGLFramebufferObject *clip, GLuint texture, bool clear);
// void process_effect(Clip* c, Effect* e, double timecode, GLTextureCoords& coords, GLuint& composite_texture, bool& fbo_switcher, int data);
Effect* gizmos;
int drag_start_x;
int drag_start_y;
@@ -67,13 +67,14 @@ private:
bool drawn_gizmos;
void move_gizmos(QMouseEvent *event, bool done);
RenderThread* renderer;
ViewerWindow* window;
bool just_repaint;
private slots:
void retry();
void show_context_menu();
void save_frame();
void show_fullscreen();
void queue_repaint();
void fullscreen_menu_action(QAction* action);
void set_fit_zoom();
void set_custom_zoom();
void set_menu_zoom(QAction *action);
+62
View File
@@ -0,0 +1,62 @@
#include "viewerwindow.h"
ViewerWindow::ViewerWindow(QOpenGLContext *share) :
QOpenGLWindow(share),
texture(0)
{}
void ViewerWindow::set_texture(GLuint t, double iar) {
texture = t;
ar = iar;
update();
}
void ViewerWindow::paintGL() {
if (texture > 0) {
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);
glLoadIdentity();
glOrtho(0, 1, 1, 0, -1, 1);
glBegin(GL_QUADS);
double top = 0;
double left = 0;
double right = 1;
double bottom = 1;
double widget_ar = double(width()) / double(height());
if (widget_ar > ar) {
/*widget_width = widget_height * aspect_ratio;
widget_x = (width() / 2) - (widget_width / 2);*/
double width = 1.0 * ar / widget_ar;
left = (1.0 - width)*0.5;
right = left + width;
} else {
double height = 1.0 / ar * widget_ar;
top = (1.0 - height)*0.5;
bottom = top + height;
}
glVertex2d(left, top);
glTexCoord2d(0, 0);
glVertex2d(left, bottom);
glTexCoord2d(1, 0);
glVertex2d(right, bottom);
glTexCoord2d(1, 1);
glVertex2d(right, top);
glTexCoord2d(0, 1);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
}
}
+17
View File
@@ -0,0 +1,17 @@
#ifndef VIEWERWINDOW_H
#define VIEWERWINDOW_H
#include <QOpenGLWindow>
class ViewerWindow : public QOpenGLWindow {
Q_OBJECT
public:
ViewerWindow(QOpenGLContext* share);
void set_texture(GLuint t, double iar);
private:
void paintGL();
GLuint texture;
double ar;
};
#endif // VIEWERWINDOW_H