fixed opengl context corruption when docking/undocking viewer

This commit is contained in:
itsmattkc
2018-08-31 15:11:32 +10:00
parent f12678aac4
commit 24c3ff647c
13 changed files with 104 additions and 90 deletions
+1
View File
@@ -6,6 +6,7 @@
#include <QThread>
#include <QDebug>
#include <QMessageBox>
#include <QOpenGLContext>
#include "panels/panels.h"
#include "panels/viewer.h"
+5
View File
@@ -8,6 +8,11 @@
#include <QMutex>
#include <QPixmap>
#define MEDIA_TYPE_FOOTAGE 0
#define MEDIA_TYPE_SEQUENCE 1
#define MEDIA_TYPE_FOLDER 2
#define MEDIA_TYPE_SOLID 3
struct Sequence;
struct Clip;
+5 -2
View File
@@ -21,6 +21,7 @@
#include "dialogs/preferencesdialog.h"
#include "playback/audio.h"
#include "playback/playback.h"
#include "ui_timeline.h"
@@ -142,6 +143,8 @@ MainWindow::MainWindow(QWidget *parent) :
}
MainWindow::~MainWindow() {
set_sequence(NULL);
QString data_dir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
if (!data_dir.isEmpty() && !autorecovery_filename.isEmpty()) {
if (QFile::exists(autorecovery_filename)) {
@@ -375,7 +378,7 @@ void MainWindow::on_action_Save_Project_triggered()
void MainWindow::on_action_Open_Project_triggered()
{
QString fn = QFileDialog::getOpenFileName(this, "Open Project...", "", OLIVE_FILE_FILTER);
if (!fn.isEmpty() && can_close_project()) {
if (!fn.isEmpty() && can_close_project()) {
updateTitle(fn);
panel_project->load_project();
undo_stack.clear();
@@ -385,7 +388,7 @@ void MainWindow::on_action_Open_Project_triggered()
void MainWindow::on_actionProject_triggered()
{
if (can_close_project()) {
panel_effect_controls->clear_effects(true);
panel_effect_controls->clear_effects(true);
undo_stack.clear();
project_url.clear();
panel_project->new_project();
-8
View File
@@ -197,14 +197,6 @@ void EffectControls::load_effects() {
}
}
if (selected_clips.size() > 0) {
// ui->scrollArea->setMinimumWidth(ui->effects_area->width());
/*ui->effects_area->layout()->update();
ui->effects_area->layout()->activate();
qDebug() << ui->effects_area->height();
ui->keyframeView->resize(ui->keyframeView->width(), ui->effects_area->height());*/
ui->keyframeView->setMinimumHeight(ui->effects_area->height());
ui->keyframeView->setEnabled(true);
ui->keyframeView->visible_in = effects_in;
+5 -1
View File
@@ -17,6 +17,7 @@
#include "io/config.h"
#include "playback/cacher.h"
#include "dialogs/replaceclipmediadialog.h"
#include "panels/effectcontrols.h"
#include <QFileDialog>
#include <QString>
@@ -559,6 +560,9 @@ void Project::delete_clips_using_selected_media() {
}
void Project::clear() {
// clear effects cache
panel_effect_controls->clear_effects(true);
// delete sequences first because it's important to close all the clips before deleting the media
QVector<Sequence*> sequences = list_all_project_sequences();
for (int i=0;i<sequences.size();i++) {
@@ -574,7 +578,7 @@ void Project::clear() {
}
void Project::new_project() {
// clear existing project
// clear existing project
set_sequence(NULL);
clear();
project_changed = false;
-5
View File
@@ -16,11 +16,6 @@ class QXmlStreamWriter;
class QXmlStreamReader;
class QFile;
#define MEDIA_TYPE_FOOTAGE 0
#define MEDIA_TYPE_SEQUENCE 1
#define MEDIA_TYPE_FOLDER 2
#define MEDIA_TYPE_SOLID 3
#define LOAD_TYPE_VERSION 69
class TimelineAction;
+1 -2
View File
@@ -140,8 +140,7 @@ void Viewer::update_sequence() {
update_end_timecode();
}
viewer_widget->initializeGL();
viewer_widget->repaint();
viewer_widget->update();
update();
}
+2 -4
View File
@@ -416,13 +416,11 @@ void cache_clip_worker(Clip* clip, long playhead, bool write_A, bool write_B, bo
void close_clip_worker(Clip* clip) {
// closes ffmpeg file handle and frees any memory used for caching
MediaStream* ms = static_cast<Media*>(clip->media)->get_stream_from_file_index(clip->track < 0, clip->media_stream);
if (clip->stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
if (clip->track < 0) {
sws_freeContext(clip->sws_ctx);
delete [] clip->comp_frame;
delete clip->fbo;
clip->fbo = NULL;
} else if (clip->stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
} else {
swr_free(&clip->swr_ctx);
}
+52 -28
View File
@@ -22,27 +22,32 @@ extern "C" {
#include <QOpenGLTexture>
#include <QDebug>
#include <QOpenGLPixelTransferOptions>
#include <QOpenGLFramebufferObject>
bool texture_failed = false;
void open_clip(Clip* clip, bool multithreaded) {
if (multithreaded) {
if (clip->open_lock.tryLock()) {
clip->multithreaded = true;
if (clip->media_type == MEDIA_TYPE_FOOTAGE) {
if (multithreaded) {
if (clip->open_lock.tryLock()) {
clip->multithreaded = true;
// maybe keep cacher instance in memory while clip exists for performance?
clip->cacher = new Cacher(clip);
QObject::connect(clip->cacher, SIGNAL(finished()), clip->cacher, SLOT(deleteLater()));
// maybe keep cacher instance in memory while clip exists for performance?
clip->cacher = new Cacher(clip);
QObject::connect(clip->cacher, SIGNAL(finished()), clip->cacher, SLOT(deleteLater()));
clip->cacher->start(QThread::LowPriority);
}
} else {
clip->multithreaded = false;
clip->finished_opening = false;
clip->open = true;
clip->cacher->start(QThread::LowPriority);
}
} else {
clip->multithreaded = false;
clip->finished_opening = false;
clip->open = true;
open_clip_worker(clip);
}
open_clip_worker(clip);
}
} else if (clip->media_type == MEDIA_TYPE_SEQUENCE) {
clip->open = true;
}
}
void close_clip(Clip* clip) {
@@ -52,11 +57,21 @@ void close_clip(Clip* clip) {
clip->texture = NULL;
}
if (clip->multithreaded) {
clip->cacher->caching = false;
clip->can_cache.wakeAll();
} else {
close_clip_worker(clip);
if (clip->fbo != NULL) {
delete clip->fbo;
clip->fbo = NULL;
}
if (clip->media_type == MEDIA_TYPE_FOOTAGE) {
if (clip->multithreaded) {
clip->cacher->caching = false;
clip->can_cache.wakeAll();
} else {
close_clip_worker(clip);
}
} else if (clip->media_type == MEDIA_TYPE_SEQUENCE) {
closeActiveClips(static_cast<Sequence*>(clip->media), false);
clip->open = false;
}
}
@@ -270,17 +285,26 @@ bool is_clip_active(Clip* c, long playhead) {
}
void set_sequence(Sequence* s) {
if (sequence != NULL) {
// clean up - close all open clips
for (int i=0;i<sequence->clip_count();i++) {
Clip* c = sequence->get_clip(i);
if (c != NULL && c->open) {
close_clip(c);
}
}
}
closeActiveClips(sequence, true);
sequence = s;
panel_timeline->update_sequence();
panel_viewer->update_sequence();
panel_timeline->setFocus();
}
void closeActiveClips(Sequence *s, bool wait) {
if (s != NULL) {
for (int i=0;i<s->clip_count();i++) {
Clip* c = s->get_clip(i);
if (c != NULL) {
if (c->media_type == MEDIA_TYPE_SEQUENCE) {
closeActiveClips(static_cast<Sequence*>(c->media), wait);
close_clip(c);
} else if (c->media_type == MEDIA_TYPE_FOOTAGE && c->open) {
close_clip(c);
if (c->multithreaded && wait) c->cacher->wait();
}
}
}
}
}
+1
View File
@@ -27,6 +27,7 @@ void retrieve_next_frame_raw_data(Clip* c, AVFrame* output);
bool is_clip_active(Clip* c, long playhead);
void get_next_audio(Clip* c, bool mix);
void set_sequence(Sequence* s);
void closeActiveClips(Sequence* s, bool wait);
struct ClipCacheData {
Clip& clip;
+1 -2
View File
@@ -4,8 +4,7 @@
#include <QResizeEvent>
// enforces aspect ratio
ViewerContainer::ViewerContainer(QWidget *parent) : QWidget(parent)
{
ViewerContainer::ViewerContainer(QWidget *parent) : QWidget(parent) {
child = NULL;
aspect_ratio = 1;
}
+30 -36
View File
@@ -11,6 +11,7 @@
#include "playback/audio.h"
#include "io/media.h"
#include "ui_timeline.h"
#include "playback/cacher.h"
#include <QDebug>
#include <QPainter>
@@ -18,6 +19,7 @@
#include <QOpenGLShaderProgram>
#include <QtMath>
#include <QOpenGLFramebufferObject>
#include <QOpenGLFunctions>
extern "C" {
#include <libavformat/avformat.h>
@@ -41,36 +43,20 @@ ViewerWidget::ViewerWidget(QWidget *parent) :
void ViewerWidget::deleteFunction() {
// destroy all textures as well
for (int i=0;i<sequence->clip_count();i++) {
Clip* c = sequence->get_clip(i);
if (c->texture != NULL) {
/* TODO NOTE: apparently "destroy()" is non-functional here because
* it requires a valid current context, and I guess it's no longer
* valid or current by the time this function is called. Not sure
* how to handle that just yet...
*/
c->texture->destroy();
c->texture = NULL;
}
}
makeCurrent();
closeActiveClips(sequence, true);
doneCurrent();
}
void ViewerWidget::retry() {
update();
}
void ViewerWidget::initializeGL() {
/*if (fbo != NULL) {
delete fbo;
fbo = NULL;
}*/
void ViewerWidget::initializeGL() {
connect(context(), SIGNAL(aboutToBeDestroyed()), this, SLOT(deleteFunction()), Qt::DirectConnection);
glClearColor(0, 0, 0, 1);
connect(context(), SIGNAL(aboutToBeDestroyed()), this, SLOT(deleteFunction()));
initializeOpenGLFunctions();
update();
retry_timer.start();
}
//void ViewerWidget::resizeGL(int w, int h)
@@ -78,7 +64,10 @@ void ViewerWidget::initializeGL() {
//}
void ViewerWidget::paintEvent(QPaintEvent *e) {
if (enable_paint) QOpenGLWidget::paintEvent(e);
if (enable_paint) {
makeCurrent();
QOpenGLWidget::paintEvent(e);
}
}
GLuint ViewerWidget::draw_clip(Clip* clip, GLuint texture) {
@@ -122,12 +111,12 @@ GLuint ViewerWidget::compose_sequence(Clip* nest, bool render_audio) {
if (c != NULL && !(nest != NULL && !same_sign(c->track, nest->track))) {
bool clip_is_active = false;
switch (c->media_type) {
case MEDIA_TYPE_FOOTAGE:
{
Media* m = static_cast<Media*>(c->media);
switch (c->media_type) {
case MEDIA_TYPE_FOOTAGE:
{
Media* m = static_cast<Media*>(c->media);
if (m->ready) {
if (m->get_stream_from_file_index(c->track < 0, c->media_stream) != NULL
if (m->get_stream_from_file_index(c->track < 0, c->media_stream) != NULL
&& is_clip_active(c, playhead)) {
// if thread is already working, we don't want to touch this,
// but we also don't want to hang the UI thread
@@ -142,12 +131,17 @@ GLuint ViewerWidget::compose_sequence(Clip* nest, bool render_audio) {
} else {
texture_failed = true;
}
}
break;
case MEDIA_TYPE_SEQUENCE:
clip_is_active = true;
break;
}
}
break;
case MEDIA_TYPE_SEQUENCE:
if (is_clip_active(c, playhead)) {
if (!c->open) open_clip(c, multithreaded);
clip_is_active = true;
} else if (c->open) {
close_clip(c);
}
break;
}
if (clip_is_active) {
bool added = false;
@@ -294,12 +288,12 @@ GLuint ViewerWidget::compose_sequence(Clip* nest, bool render_audio) {
}
void ViewerWidget::paintGL() {
glClearColor(0, 0, 0, 1);
glMatrixMode(GL_PROJECTION);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
bool loop = true;
while (loop) {
loop = false;
texture_failed = false;
+1 -2
View File
@@ -2,7 +2,6 @@
#define VIEWERWIDGET_H
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QMatrix4x4>
#include <QOpenGLTexture>
#include <QTimer>
@@ -13,7 +12,7 @@
struct Clip;
struct Sequence;
class ViewerWidget : public QOpenGLWidget, public QOpenGLFunctions
class ViewerWidget : public QOpenGLWidget
{
Q_OBJECT
public: