fixed opengl context corruption when docking/undocking viewer
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
#include <QThread>
|
||||
#include <QDebug>
|
||||
#include <QMessageBox>
|
||||
#include <QOpenGLContext>
|
||||
|
||||
#include "panels/panels.h"
|
||||
#include "panels/viewer.h"
|
||||
|
||||
@@ -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
@@ -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();
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -140,8 +140,7 @@ void Viewer::update_sequence() {
|
||||
update_end_timecode();
|
||||
}
|
||||
|
||||
viewer_widget->initializeGL();
|
||||
viewer_widget->repaint();
|
||||
viewer_widget->update();
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
+2
-4
@@ -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
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user