#include <QGraphicsItemGroup>
#include <QtConcurrentRun>
+#include <QGLWidget>
#include <KFileMetaInfo>
-ClipManager::ClipManager(KdenliveDoc *doc) :
+ClipManager::ClipManager(KdenliveDoc *doc, QGLWidget *glContext) :
QObject(),
+ m_mainGLContext(glContext),
m_audioThumbsQueue(),
m_doc(doc),
m_abortThumb(false),
void ClipManager::slotGetThumbs()
{
+ // We are in a new thread, so we need a new OpenGL context for the remainder of the function.
+ QGLWidget ctx(0, m_mainGLContext);
+ ctx.makeCurrent();
+
QMap<QString, int>::const_iterator i;
int max;
int done = 0;
void ClipManager::slotGetAudioThumbs()
{
+ // We are in a new thread, so we need a new OpenGL context for the remainder of the function.
+ QGLWidget ctx(0, m_mainGLContext);
+ ctx.makeCurrent();
+
Mlt::Profile prof((char*) KdenliveSettings::current_profile().toUtf8().constData());
mlt_audio_format audioFormat = mlt_audio_s16;
while (!m_abortAudioThumb && !m_audioThumbsQueue.isEmpty()) {
class KdenliveDoc;
class DocClipBase;
class AbstractGroupItem;
+class QGLWidget;
class SolidVolumeInfo
{
Q_OBJECT public:
- ClipManager(KdenliveDoc *doc);
+ ClipManager(KdenliveDoc *doc, QGLWidget *glContext);
virtual ~ ClipManager();
void addClip(DocClipBase *clip);
DocClipBase *getClipAt(int pos);
void slotAddClip(KIO::Job *job, const KUrl &, const KUrl &dst);
private: // Private attributes
+ QGLWidget *m_mainGLContext;
/** the list of clips in the document */
QList <DocClipBase*> m_clipList;
/** the list of groups in the document */
{
QString profile = DvdWizardVob::getDvdProfile(format);
if (m_monitor == NULL) {
- m_monitor = new Monitor(Kdenlive::DvdMonitor, m_manager, profile, this);
+ m_monitor = new Monitor(Kdenlive::DvdMonitor, m_manager, NULL, profile, this);
//m_monitor->start();
QVBoxLayout *vbox = new QVBoxLayout;
vbox->addWidget(m_monitor);
const double DOCUMENTVERSION = 0.88;
-KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup *undoGroup, const QString &profileName, const QMap <QString, QString>& properties, const QMap <QString, QString>& metadata, const QPoint &tracks, Render *render, KTextEdit *notes, bool *openBackup, MainWindow *parent, KProgressDialog *progressDialog) :
+KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup *undoGroup, const QString &profileName, const QMap <QString, QString>& properties, const QMap <QString, QString>& metadata, const QPoint &tracks, Render *render, KTextEdit *notes, bool *openBackup, QGLWidget *glContext, MainWindow *parent, KProgressDialog *progressDialog) :
QObject(parent),
m_autosave(NULL),
m_url(url),
m_profile.display_aspect_den = 0;
m_profile.colorspace = 0;
- m_clipManager = new ClipManager(this);
+ m_clipManager = new ClipManager(this, glContext);
m_autoSaveTimer = new QTimer(this);
m_autoSaveTimer->setSingleShot(true);
connect(m_clipManager, SIGNAL(displayMessage(QString,int)), parent, SLOT(slotGotProgressInfo(QString,int)));
class KTextEdit;
class KProgressDialog;
+class QGLWidget;
class QUndoGroup;
class QTimer;
class QUndoStack;
Q_OBJECT
public:
- KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup *undoGroup, const QString &profileName, const QMap <QString, QString>& properties, const QMap <QString, QString>& metadata, const QPoint &tracks, Render *render, KTextEdit *notes, bool *openBackup, MainWindow *parent = 0, KProgressDialog *progressDialog = 0);
+ KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup *undoGroup, const QString &profileName, const QMap <QString, QString>& properties, const QMap <QString, QString>& metadata, const QPoint &tracks, Render *render, KTextEdit *notes, bool *openBackup, QGLWidget *glContext, MainWindow *parent = 0, KProgressDialog *progressDialog = 0);
~KdenliveDoc();
QDomNodeList producersList();
double fps() const;
#include <QtConcurrentRun>
#include <QVarLengthArray>
#include <QPainter>
+#include <QGLWidget>
KThumb::KThumb(ClipManager *clipManager, const KUrl &url, const QString &id, const QString &hash, QObject * parent) :
QObject(parent),
void KThumb::slotGetIntraThumbs()
{
+ // We are in a new thread, so we need a new OpenGL context for the remainder of the function.
+ QGLWidget ctx(0, m_clipManager->getMainContext());
+ ctx.makeCurrent();
+
const int theight = KdenliveSettings::trackheight();
const int frameWidth = (int)(theight * m_ratio + 0.5);
const int displayWidth = (int)(theight * m_dar + 0.5);
#include <QDesktopWidget>
#include <QBitmap>
#include <QUndoGroup>
+#include <QGLWidget>
#include <stdlib.h>
#include <locale.h>
MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & clipsToLoad, QWidget *parent) :
KXmlGuiWindow(parent),
+ m_glContext(NULL),
m_activeDocument(NULL),
m_activeTimeline(NULL),
m_projectList(NULL),
setFont(KGlobalSettings::toolBarFont());
parseProfiles(MltPath);
KdenliveSettings::setCurrent_profile(KdenliveSettings::default_profile());
+
+ // Create OpenGL context, to have a common context all the other contexts
+ // can share with.
+ m_glContext = new QGLWidget(this);
+ m_glContext->resize(0, 0);
+
m_commandStack = new QUndoGroup;
setDockNestingEnabled(true);
m_timelineArea = new KTabWidget(this);
m_projectListDock = new QDockWidget(i18n("Project Tree"), this);
m_projectListDock->setObjectName("project_tree");
- m_projectList = new ProjectList();
+ m_projectList = new ProjectList(m_glContext);
m_projectListDock->setWidget(m_projectList);
addDockWidget(Qt::TopDockWidgetArea, m_projectListDock);
m_clipMonitorDock = new QDockWidget(i18n("Clip Monitor"), this);
m_clipMonitorDock->setObjectName("clip_monitor");
- m_clipMonitor = new Monitor(Kdenlive::ClipMonitor, m_monitorManager, QString(), m_timelineArea);
+ m_clipMonitor = new Monitor(Kdenlive::ClipMonitor, m_monitorManager, m_glContext, QString(), m_timelineArea);
m_clipMonitorDock->setWidget(m_clipMonitor);
// Connect the project list
m_projectMonitorDock = new QDockWidget(i18n("Project Monitor"), this);
m_projectMonitorDock->setObjectName("project_monitor");
- m_projectMonitor = new Monitor(Kdenlive::ProjectMonitor, m_monitorManager, QString());
+ m_projectMonitor = new Monitor(Kdenlive::ProjectMonitor, m_monitorManager, m_glContext, QString());
m_projectMonitorDock->setWidget(m_projectMonitor);
#ifndef Q_WS_MAC
delete m_monitorManager;
delete m_scopeManager;
Mlt::Factory::close();
+ delete m_glContext;
}
//virtual
m_timelineArea->setEnabled(true);
m_projectList->setEnabled(true);
bool openBackup;
- KdenliveDoc *doc = new KdenliveDoc(KUrl(), projectFolder, m_commandStack, profileName, documentProperties, documentMetadata, projectTracks, m_projectMonitor->render, m_notesWidget, &openBackup, this);
+ KdenliveDoc *doc = new KdenliveDoc(KUrl(), projectFolder, m_commandStack, profileName, documentProperties, documentMetadata, projectTracks, m_projectMonitor->render, m_notesWidget, &openBackup, m_glContext, this);
doc->m_autosave = new KAutoSaveFile(KUrl(), doc);
bool ok;
TrackView *trackView = new TrackView(doc, m_tracksActionCollection->actions(), &ok, this);
progressDialog.progressBar()->setValue(0);
bool openBackup;
- KdenliveDoc *doc = new KdenliveDoc(stale ? KUrl(stale->fileName()) : url, KdenliveSettings::defaultprojectfolder(), m_commandStack, KdenliveSettings::default_profile(), QMap <QString, QString> (), QMap <QString, QString> (), QPoint(KdenliveSettings::videotracks(), KdenliveSettings::audiotracks()), m_projectMonitor->render, m_notesWidget, &openBackup, this, &progressDialog);
+ KdenliveDoc *doc = new KdenliveDoc(stale ? KUrl(stale->fileName()) : url, KdenliveSettings::defaultprojectfolder(), m_commandStack, KdenliveSettings::default_profile(), QMap <QString, QString> (), QMap <QString, QString> (), QPoint(KdenliveSettings::videotracks(), KdenliveSettings::audiotracks()), m_projectMonitor->render, m_notesWidget, &openBackup, m_glContext, this, &progressDialog);
progressDialog.progressBar()->setValue(1);
progressDialog.progressBar()->setMaximum(4);
class AudioSignal;
class AudioSpectrum;
class Spectrogram;
+class QGLWidget;
class MainWindow : public KXmlGuiWindow
{
virtual void readProperties(const KConfigGroup &config);
private:
+ QGLWidget* m_glContext;
+
KTabWidget* m_timelineArea;
QProgressBar *m_statusProgressBar;
#include "abstractclipitem.h"
#include "monitorscene.h"
#include "widgets/monitoreditwidget.h"
+#include "widgets/videosurface.h"
+#include "widgets/videoglwidget.h"
#include "kdenlivesettings.h"
#include <KDebug>
#define SEEK_INACTIVE (-1)
-Monitor::Monitor(Kdenlive::MonitorId id, MonitorManager *manager, QString profile, QWidget *parent) :
+Monitor::Monitor(Kdenlive::MonitorId id, MonitorManager *manager, QGLWidget *glContext, QString profile, QWidget *parent) :
AbstractMonitor(id, manager, parent)
, render(NULL)
, m_currentClip(NULL)
, m_effectWidget(NULL)
, m_selectedClip(NULL)
, m_loopClipTransition(true)
+ , m_parentGLContext(glContext)
, m_glWidget(NULL)
, m_editMarker(NULL)
{
void Monitor::createOpenGlWidget(QWidget *parent, const QString &profile)
{
- render = new Render(id(), 0, profile, this);
- m_glWidget = new VideoGLWidget(parent);
+ m_glWidget = new VideoGLWidget(parent, m_parentGLContext);
+ render = new Render(id(), 0, profile, this, m_glWidget);
if (m_glWidget == NULL) {
// Creation failed, we are in trouble...
QMessageBox::critical(this, i18n("Missing OpenGL support"),
m_glWidget->setImageAspectRatio(render->dar());
m_glWidget->setBackgroundColor(KdenliveSettings::window_background());
connect(render, SIGNAL(showImageSignal(QImage)), m_glWidget, SLOT(showImage(QImage)));
+ connect(render, SIGNAL(showImageSignal(GLuint)), m_glWidget, SLOT(showImage(GLuint)));
}
void Monitor::setupMenu(QMenu *goMenu, QAction *playZone, QAction *loopZone, QMenu *markerMenu, QAction *loopClip)
Q_OBJECT
public:
- Monitor(Kdenlive::MonitorId id, MonitorManager *manager, QString profile = QString(), QWidget *parent = 0);
+ Monitor(Kdenlive::MonitorId id, MonitorManager *manager, QGLWidget *glContext, QString profile = QString(), QWidget *parent = 0);
~Monitor();
Render *render;
AbstractRender *abstractRender();
/** true if selected clip is transition, false = selected clip is clip.
* Necessary because sometimes we get two signals, e.g. we get a clip and we get selected transition = NULL. */
bool m_loopClipTransition;
+
+ QGLWidget *m_parentGLContext;
VideoGLWidget *m_glWidget;
void createOpenGlWidget(QWidget *parent, const QString &profile);
#include <QtConcurrentRun>
#include <QVBoxLayout>
#include <KPassivePopup>
+#include <QGLWidget>
MyMessageWidget::MyMessageWidget(QWidget *parent) : KMessageWidget(parent) {}
}
-ProjectList::ProjectList(QWidget *parent) :
+ProjectList::ProjectList(QGLWidget *glContext, QWidget *parent) :
QWidget(parent)
, m_render(NULL)
, m_fps(-1)
, m_abortAllJobs(false)
, m_closing(false)
, m_invalidClipDialog(NULL)
+ , m_mainGLContext(glContext)
{
qRegisterMetaType<stringMap> ("stringMap");
QVBoxLayout *layout = new QVBoxLayout;
void ProjectList::updateAllClips(bool displayRatioChanged, bool fpsChanged, const QStringList &brokenClips)
{
+ // We are in a new thread, so we need a new OpenGL context for the remainder of the function.
+ QGLWidget ctx(0, m_mainGLContext);
+ ctx.makeCurrent();
+
if (!m_allClipsProcessed) m_listView->setEnabled(false);
m_listView->setSortingEnabled(false);
QTreeWidgetItemIterator it(m_listView);
class DocClipBase;
class AbstractClipJob;
class ItemDelegate;
+class QGLWidget;
class SmallInfoLabel: public QPushButton
{
Q_OBJECT
public:
- ProjectList(QWidget *parent = 0);
+ ProjectList(QGLWidget *glContext, QWidget *parent = 0);
virtual ~ProjectList();
QDomElement producersList();
/** @brief The action that will trigger the log dialog. */
QAction *m_logAction;
#endif
+ QGLWidget *m_mainGLContext;
void requestClipThumbnail(const QString &id);
emit self->mltFrameReceived(new Mlt::Frame(frame_ptr));
}
-Render::Render(Kdenlive::MonitorId rendererName, int winid, QString profile, QWidget *parent) :
+Render::Render(Kdenlive::MonitorId rendererName, int winid, QString profile, QWidget *parent, QGLWidget *mainGLContext) :
AbstractRender(rendererName, parent),
requestedSeekPosition(SEEK_INACTIVE),
showFrameSemaphore(1),
m_blackClip(NULL),
m_winid(winid),
m_paused(true),
- m_isActive(false)
+ m_isActive(false),
+ m_mainGLContext(mainGLContext),
+ m_GLContext(NULL)
{
qRegisterMetaType<stringMap> ("stringMap");
analyseAudio = KdenliveSettings::monitor_audio();
m_mltProducer->set_speed(0.0);
m_refreshTimer.setSingleShot(true);
m_refreshTimer.setInterval(100);
+ m_glslManager = new Mlt::Filter(*m_mltProfile, "glsl.manager");
connect(&m_refreshTimer, SIGNAL(timeout()), this, SLOT(refresh()));
connect(this, SIGNAL(multiStreamFound(QString,QList<int>,QList<int>,stringMap)), this, SLOT(slotMultiStreamProducerFound(QString,QList<int>,QList<int>,stringMap)));
connect(this, SIGNAL(checkSeeking()), this, SLOT(slotCheckSeeking()));
connect(this, SIGNAL(mltFrameReceived(Mlt::Frame*)), this, SLOT(showFrame(Mlt::Frame*)), Qt::UniqueConnection);
+
+ m_GLContext = new QGLWidget(0, m_mainGLContext);
+ m_GLContext->resize(0, 0);
}
Render::~Render()
{
closeMlt();
delete m_mltProfile;
+ delete m_GLContext;
}
void Render::processFileProperties()
{
+ // We are in a new thread, so we need a new OpenGL context for the remainder of the function.
+ QGLWidget ctx(0, m_mainGLContext);
+ ctx.makeCurrent();
+
requestClipInfo info;
QLocale locale;
while (!m_requestList.isEmpty()) {
#include <QSemaphore>
#include <QTimer>
+class QGLWidget;
class QPixmap;
class KComboBox;
* @param rendererName A unique identifier for this renderer
* @param winid The parent widget identifier (required for SDL display). Set to 0 for OpenGL rendering
* @param profile The MLT profile used for the renderer (default one will be used if empty). */
- Render(Kdenlive::MonitorId rendererName, int winid, QString profile = QString(), QWidget *parent = 0);
+ Render(Kdenlive::MonitorId rendererName, int winid, QString profile = QString(), QWidget *parent = 0, QGLWidget *mainGLContext = 0);
/** @brief Destroy the MLT Renderer. */
virtual ~Render();
bool m_paused;
/** @brief True if this monitor is active. */
bool m_isActive;
+ QGLWidget *m_mainGLContext;
+ QGLWidget *m_GLContext;
+ Mlt::Filter* m_glslManager;
void closeMlt();
void mltCheckLength(Mlt::Tractor *tractor);
*
* Used in Mac OS X. */
void showImageSignal(QImage);
+ void showImageSignal(GLuint);
void showAudioSignal(const QVector<double> &);
void addClip(const KUrl &, stringMap);
void checkSeeking();
#define GL_TEXTURE_RECTANGLE_EXT GL_TEXTURE_RECTANGLE_NV
#endif
-VideoGLWidget::VideoGLWidget(QWidget *parent)
- : QGLWidget(parent)
+VideoGLWidget::VideoGLWidget(QWidget *parent, QGLWidget *share)
+ : QGLWidget(parent, share)
, x(0)
, y(0)
, w(width())
, m_image_width(0)
, m_image_height(0)
, m_texture(0)
+ , m_other_texture(0)
, m_display_ratio(4.0 / 3.0)
, m_backgroundColor(Qt::gray)
{
glEnd();
glDisable(GL_TEXTURE_RECTANGLE_EXT);
}
+ if (m_other_texture) {
+#ifdef Q_WS_MAC
+ glClear(GL_COLOR_BUFFER_BIT);
+#endif
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, m_other_texture);
+ glBegin(GL_QUADS);
+ glTexCoord2i(0, 0);
+ glVertex2i(x, y);
+ glTexCoord2i(1, 0);
+ glVertex2i(x + w, y);
+ glTexCoord2i(1, 1);
+ glVertex2i(x + w, y + h);
+ glTexCoord2i(0, 1);
+ glVertex2i(x, y + h);
+ glEnd();
+ glDisable(GL_TEXTURE_2D);
+ }
}
void VideoGLWidget::showImage(const QImage &image)
makeCurrent();
if (m_texture)
glDeleteTextures(1, &m_texture);
+ m_other_texture = 0;
glPixelStorei(GL_UNPACK_ROW_LENGTH, m_image_width);
glGenTextures(1, &m_texture);
updateGL();
}
+void VideoGLWidget::showImage(GLuint texnum)
+{
+ makeCurrent();
+ if (m_texture) {
+ glDeleteTextures(1, &m_texture);
+ m_texture = 0;
+ }
+ m_other_texture = texnum;
+
+ updateGL();
+}
+
void VideoGLWidget::mouseDoubleClickEvent(QMouseEvent * event)
{
// TODO: disable screensaver?
Q_OBJECT
public:
- explicit VideoGLWidget(QWidget *parent = 0);
+ explicit VideoGLWidget(QWidget *parent = 0, QGLWidget *share = 0);
~VideoGLWidget();
void activateMonitor();
QSize minimumSizeHint() const;
public slots:
void showImage(const QImage &image);
+ void showImage(GLuint);
protected:
void initializeGL();
private:
int x, y, w, h;
int m_image_width, m_image_height;
- GLuint m_texture;
+ GLuint m_texture, m_other_texture;
double m_display_ratio;
QColor m_backgroundColor;
Qt::WindowFlags m_baseFlags;