From 6294466a0d6a4e4bfb765100aedb15e9016be70e Mon Sep 17 00:00:00 2001 From: ray cutler Date: Wed, 26 Jun 2019 09:33:22 -0400 Subject: [PATCH] work on isf editor partially worked around the mac qt bug that was causing GL widgets to break event handling/pop-up buttons :: cleaned up some logs :: fixed a bug that would unload the tmp isf doc if you started saving it, but cancelled --- .../Qt/ISFEditor/ISFEditor_app/DocWindow.cpp | 107 ++++++++------ .../ISFEditor/ISFEditor_app/ISFController.cpp | 11 +- .../ISFEditor/ISFEditor_app/ISFEditor_app.pro | 4 +- .../ISFEditor/ISFEditor_app/LoadingWindow.cpp | 12 +- .../Qt/ISFEditor/ISFEditor_app/MainWindow.cpp | 15 +- .../ISFEditor/ISFEditor_app/OutputWindow.cpp | 2 +- .../VideoSource/DynamicVideoSource.cpp | 2 +- .../VideoSource/ISFVideoSource.cpp | 2 +- examples/Qt/ISFEditor/ISFEditor_app/main.cpp | 1 - .../LoadingWindowFileListModel.cpp | 6 +- .../TexDownloadBenchmark.pro | 9 +- .../TexUploadBenchmark/TexUploadBenchmark.pro | 5 + .../TexUploadBenchmarkMainWindow.cpp | 2 +- examples/Qt/common/DisplayLinkDriver.h | 38 +++++ examples/Qt/common/DisplayLinkDriver.mm | 139 ++++++++++++++++++ examples/Qt/common/GLBufferQWidget.cpp | 20 +++ examples/Qt/common/GLBufferQWidget.h | 7 + examples/Qt/common/ISFGLBufferQWidget.cpp | 24 ++- examples/Qt/common/ISFGLBufferQWidget.h | 7 + examples/Qt/common/VVGLRenderQThread.cpp | 4 +- 20 files changed, 336 insertions(+), 81 deletions(-) create mode 100644 examples/Qt/common/DisplayLinkDriver.h create mode 100644 examples/Qt/common/DisplayLinkDriver.mm diff --git a/examples/Qt/ISFEditor/ISFEditor_app/DocWindow.cpp b/examples/Qt/ISFEditor/ISFEditor_app/DocWindow.cpp index 2288485..64b0c0a 100644 --- a/examples/Qt/ISFEditor/ISFEditor_app/DocWindow.cpp +++ b/examples/Qt/ISFEditor/ISFEditor_app/DocWindow.cpp @@ -112,7 +112,7 @@ DocWindow::~DocWindow() { void DocWindow::updateContentsFromISFController() { - qDebug() << __PRETTY_FUNCTION__; + //qDebug() << __PRETTY_FUNCTION__; //ISFSceneRef scene = GetISFController()->getScene(); //ISFDocRef doc = (scene==nullptr) ? nullptr : scene->doc(); @@ -413,48 +413,57 @@ void DocWindow::saveOpenFile() { lw->getBaseDirectory(), tr("Text (*.fs)")); } - //qDebug() << "\tdestPath is " << pathToSave; - QFileInfo saveFileInfo(pathToSave); - QString noExtPathToSave = QString("%1/%2").arg(saveFileInfo.dir().absolutePath()).arg(saveFileInfo.completeBaseName()); - //qDebug() << "\tnoExtPathToSave is " << noExtPathToSave; - - - if (fragContentsChanged) { - QString localWritePath = QString("%1.fs").arg(noExtPathToSave); - qDebug() << "\tsaving frag to file " << localWritePath; - VVDELETE(_fragFilePath); - _fragFilePath = new QString(localWritePath); - VVDELETE(_fragFilePathContentsOnOpen) - _fragFilePathContentsOnOpen = new QString(currentFragString); + qDebug() << "\tpathToSave is " << pathToSave; + if (pathToSave.length() < 1) { + //qDebug() << "\tinvalid path, don't save!"; + } + else { + QFileInfo saveFileInfo(pathToSave); + QString noExtPathToSave = QString("%1/%2").arg(saveFileInfo.dir().absolutePath()).arg(saveFileInfo.completeBaseName()); + qDebug() << "\tnoExtPathToSave is " << noExtPathToSave; - QFile wFile(localWritePath); - if (wFile.open(QIODevice::WriteOnly)) { - QTextStream wStream(&wFile); - wStream << currentFragString; - wFile.close(); + if (fragContentsChanged) { + QString localWritePath = QString("%1.fs").arg(noExtPathToSave); + qDebug() << "\tsaving frag to file " << localWritePath; + VVDELETE(_fragFilePath); + _fragFilePath = new QString(localWritePath); + VVDELETE(_fragFilePathContentsOnOpen) + _fragFilePathContentsOnOpen = new QString(currentFragString); + + QFile wFile(localWritePath); + if (wFile.open(QIODevice::WriteOnly)) { + QTextStream wStream(&wFile); + wStream << currentFragString; + wFile.close(); + _fragEditsPerformed = false; + } } - } - if (vertContentsChanged) { - QString localWritePath = QString("%1.vs").arg(noExtPathToSave); - qDebug() << "\tsaving vert to file " << localWritePath; - VVDELETE(_vertFilePath); - _vertFilePath = new QString(localWritePath); - VVDELETE(_vertFilePathContentsOnOpen) - _vertFilePathContentsOnOpen = new QString(currentVertString); + if (vertContentsChanged) { + QString localWritePath = QString("%1.vs").arg(noExtPathToSave); + qDebug() << "\tsaving vert to file " << localWritePath; + VVDELETE(_vertFilePath); + _vertFilePath = new QString(localWritePath); + VVDELETE(_vertFilePathContentsOnOpen) + _vertFilePathContentsOnOpen = new QString(currentVertString); - QFile wFile(localWritePath); - if (wFile.open(QIODevice::WriteOnly)) { - QTextStream wStream(&wFile); - wStream << currentVertString; - wFile.close(); + QFile wFile(localWritePath); + if (wFile.open(QIODevice::WriteOnly)) { + QTextStream wStream(&wFile); + wStream << currentVertString; + wFile.close(); + _vertEditsPerformed = false; + } } - } - if (fragContentsChanged || vertContentsChanged) { - if (lw != nullptr) - lw->on_loadFile(pathToSave); + if (fragContentsChanged || vertContentsChanged) { + if (lw != nullptr) + lw->on_loadFile(pathToSave); + } } + + + } // else the file path is non-nil and not in tmp, so just save it to disk else { @@ -655,7 +664,7 @@ void DocWindow::reloadColorsAndSyntaxFormats() { void DocWindow::on_actionNew_triggered() { - qDebug() << __PRETTY_FUNCTION__; + //qDebug() << __PRETTY_FUNCTION__; LoadingWindow *lw = GetLoadingWindow(); if (lw != nullptr) lw->on_createNewFile(); @@ -665,11 +674,11 @@ void DocWindow::on_actionSave_triggered() { saveOpenFile(); } void DocWindow::on_actionImport_from_GLSLSandbox_triggered() { - qDebug() << __PRETTY_FUNCTION__; + //qDebug() << __PRETTY_FUNCTION__; GLSLSandboxConverter *conv = new GLSLSandboxConverter(GetLoadingWindow()); int returnCode = conv->exec(); - qDebug() << "returnCode is " << returnCode; + //qDebug() << "returnCode is " << returnCode; if (!returnCode) { LoadingWindow *lw = GetLoadingWindow(); if (lw != nullptr) { @@ -679,11 +688,11 @@ void DocWindow::on_actionImport_from_GLSLSandbox_triggered() { delete conv; } void DocWindow::on_actionImport_from_Shadertoy_triggered() { - qDebug() << __PRETTY_FUNCTION__; + //qDebug() << __PRETTY_FUNCTION__; ShadertoyConverter *conv = new ShadertoyConverter(GetLoadingWindow()); int returnCode = conv->exec(); - qDebug() << "returnCode is " << returnCode; + //qDebug() << "returnCode is " << returnCode; if (!returnCode) { LoadingWindow *lw = GetLoadingWindow(); if (lw != nullptr) { @@ -693,14 +702,14 @@ void DocWindow::on_actionImport_from_Shadertoy_triggered() { delete conv; } void DocWindow::on_actionPreferences_triggered() { - qDebug() << __PRETTY_FUNCTION__; + //qDebug() << __PRETTY_FUNCTION__; Preferences *p = GetPreferences(); if (p != nullptr) { p->show(); } } void DocWindow::on_actionQuit_triggered() { - qDebug() << __PRETTY_FUNCTION__; + //qDebug() << __PRETTY_FUNCTION__; QCoreApplication::quit(); } @@ -744,7 +753,7 @@ void DocWindow::on_actionUse_selection_for_next_Find_triggered() { void DocWindow::on_actionCheck_for_Updates_triggered() { - qDebug() << __PRETTY_FUNCTION__; + //qDebug() << __PRETTY_FUNCTION__; AutoUpdater *aa = GetGlobalAutoUpdater(); if (aa != nullptr) { aa->checkForUpdates(); @@ -754,14 +763,14 @@ void DocWindow::on_actionCheck_for_Updates_triggered() { } } void DocWindow::on_actionAbout_triggered() { - qDebug() << __PRETTY_FUNCTION__; + //qDebug() << __PRETTY_FUNCTION__; AboutWindow *aw = GetAboutWindow(); if (aw != nullptr) { aw->show(); } } void DocWindow::on_actionGet_Help_triggered() { - qDebug() << __PRETTY_FUNCTION__; + //qDebug() << __PRETTY_FUNCTION__; ReportProblemDialog *rpd = GetReportProblemDialog(); if (rpd != nullptr) { rpd->show(); @@ -785,7 +794,7 @@ void DocWindow::closeEvent(QCloseEvent * event) { QCoreApplication::quit(); } void DocWindow::showEvent(QShowEvent * event) { - qDebug() << __PRETTY_FUNCTION__; + //qDebug() << __PRETTY_FUNCTION__; //Q_UNUSED(event); QWidget::showEvent(event); @@ -855,7 +864,7 @@ void DocWindow::showEvent(QShowEvent * event) { } void DocWindow::appQuitEvent() { - qDebug() << __PRETTY_FUNCTION__; + //qDebug() << __PRETTY_FUNCTION__; QSettings settings; settings.setValue("DocWindowGeometry", saveGeometry()); @@ -884,7 +893,7 @@ SimpleSourceCodeEditor * DocWindow::focusedSourceCodeEditor() { return focusedEd; } void DocWindow::tmpSaveTimerSlot() { - qDebug() << __PRETTY_FUNCTION__; + //qDebug() << __PRETTY_FUNCTION__; QString currentFragString = ui->fragShaderEditor->toPlainText(); QString currentVertString = ui->vertShaderEditor->toPlainText(); diff --git a/examples/Qt/ISFEditor/ISFEditor_app/ISFController.cpp b/examples/Qt/ISFEditor/ISFEditor_app/ISFController.cpp index 5c0a843..3d30e86 100644 --- a/examples/Qt/ISFEditor/ISFEditor_app/ISFController.cpp +++ b/examples/Qt/ISFEditor/ISFEditor_app/ISFController.cpp @@ -87,7 +87,7 @@ void ISFController::aboutToQuit() { std::lock_guard tmpLock(sceneLock); } void ISFController::loadFile(const QString & inPathToLoad) { - qDebug() << __PRETTY_FUNCTION__ << "... " << inPathToLoad; + //qDebug() << __PRETTY_FUNCTION__ << "... " << inPathToLoad; if (GetGlobalBufferPool() == nullptr) { qDebug() << "\terr: no global buffer pool, " << __PRETTY_FUNCTION__; @@ -474,7 +474,7 @@ void ISFController::threadedRenderCallback() { sceneCtx = scene->context(); if (needToLoadFiles) { - qDebug() << "need to load, moving ctx to main thread..."; + //qDebug() << "need to load, moving ctx to main thread..."; //renderThreadCtx->moveToThread(qApp->thread()); sceneCtx->moveToThread(qApp->thread()); needToLoadFiles = false; @@ -482,7 +482,7 @@ void ISFController::threadedRenderCallback() { return; } if (loadingFiles) { - qDebug() << "loading files- killing time, waiting for main thread..."; + //qDebug() << "loading files- killing time, waiting for main thread..."; return; } @@ -490,7 +490,7 @@ void ISFController::threadedRenderCallback() { //if (renderThreadCtx==nullptr || renderThreadCtx->contextThread()!=QThread::currentThread()) if (sceneCtx==nullptr || sceneCtx->contextThread()!=QThread::currentThread()) { - cout << "no render ctx or ctx isnt attached to current thread, bailing, " << __PRETTY_FUNCTION__ << endl; + //cout << "no render ctx or ctx isnt attached to current thread, bailing, " << __PRETTY_FUNCTION__ << endl; return; } @@ -598,7 +598,7 @@ void ISFController::threadedRenderCallback() { } void ISFController::populateLoadingWindowUI() { - //qDebug() << __PRETTY_FUNCTION__; + qDebug() << __PRETTY_FUNCTION__; if (qApp->thread() != QThread::currentThread()) qDebug() << "ERR: thread is not main! " << __PRETTY_FUNCTION__; @@ -645,6 +645,7 @@ void ISFController::populateLoadingWindowUI() { return; // run through the scene's inputs- we want to make a UI item for each... + qDebug() << "loading UI for scene at " << scene->doc()->path().c_str(); vector sceneInputs = scene->inputs(); for (auto it=sceneInputs.begin(); it!=sceneInputs.end(); ++it) { ISFAttrRef attrib = *it; diff --git a/examples/Qt/ISFEditor/ISFEditor_app/ISFEditor_app.pro b/examples/Qt/ISFEditor/ISFEditor_app/ISFEditor_app.pro index ae2fbef..2634618 100644 --- a/examples/Qt/ISFEditor/ISFEditor_app/ISFEditor_app.pro +++ b/examples/Qt/ISFEditor/ISFEditor_app/ISFEditor_app.pro @@ -60,6 +60,7 @@ SOURCES += \ ../../common/GLBufferQVideoSurface.cpp \ ../../common/GLBufferQWidget.cpp \ ../../common/ISFGLBufferQWidget.cpp \ + ../../common/DisplayLinkDriver.mm \ DocWindow.cpp \ misc_classes/FileLoadEventFilter.cpp \ ISFController.cpp \ @@ -125,6 +126,7 @@ HEADERS += \ ../../common/GLBufferQVideoSurface.h \ ../../common/GLBufferQWidget.h \ ../../common/ISFGLBufferQWidget.h \ + ../../common/DisplayLinkDriver.h \ DocWindow.h \ misc_classes/FileLoadEventFilter.h \ ISFController.h \ @@ -285,7 +287,7 @@ win32 { QT += winextras LIBS += -lAdvapi32 -lOle32 -lShell32 } else:mac { - LIBS += -framework Security + LIBS += -framework Security -framework CoreVideo } else:unix { LIBS += -lutil } diff --git a/examples/Qt/ISFEditor/ISFEditor_app/LoadingWindow.cpp b/examples/Qt/ISFEditor/ISFEditor_app/LoadingWindow.cpp index c424b7a..9fa3832 100644 --- a/examples/Qt/ISFEditor/ISFEditor_app/LoadingWindow.cpp +++ b/examples/Qt/ISFEditor/ISFEditor_app/LoadingWindow.cpp @@ -85,7 +85,7 @@ QScrollArea * LoadingWindow::getScrollArea() { QSpinBox * LoadingWindow::getWidthSB() { return ui->renderResWidthWidget; } QSpinBox * LoadingWindow::getHeightSB() { return ui->renderResHeightWidget; } void LoadingWindow::on_createNewFile() { - qDebug() << __PRETTY_FUNCTION__; + //qDebug() << __PRETTY_FUNCTION__; //QThread *mainThread = QApplication::instance()->thread(); //qDebug() << "main thread is currently " << mainThread; @@ -95,7 +95,7 @@ void LoadingWindow::on_createNewFile() { QFile tmpFragShaderFile( QString("%1/ISFTesterTmpFile.fs").arg(QDir::tempPath()) ); if (tmpFragShaderFile.open(QIODevice::WriteOnly)) { tmpFilePath = tmpFragShaderFile.fileName(); - qDebug() << "\ttmpFragShaderFile's path is " << tmpFilePath; + //qDebug() << "\ttmpFragShaderFile's path is " << tmpFilePath; QFile newFileTemplate(":/resources/NewFileTemplate.txt"); if (newFileTemplate.open(QFile::ReadOnly)) { @@ -161,7 +161,7 @@ void LoadingWindow::closeEvent(QCloseEvent * event) { QWidget::closeEvent(event); } void LoadingWindow::showEvent(QShowEvent * event) { - qDebug() << __PRETTY_FUNCTION__; + //qDebug() << __PRETTY_FUNCTION__; //Q_UNUSED(event); QWidget::showEvent(event); @@ -238,7 +238,7 @@ void LoadingWindow::showEvent(QShowEvent * event) { } } void LoadingWindow::appQuitEvent() { - qDebug() << __PRETTY_FUNCTION__; + //qDebug() << __PRETTY_FUNCTION__; QSettings settings; settings.setValue("LoadingWindowGeometry", saveGeometry()); @@ -367,7 +367,7 @@ void LoadingWindow::newFileSelected(const QItemSelection &selected, const QItemS } */ void LoadingWindow::listOfVideoSourcesUpdated(DynamicVideoSource * inSrc) { - qDebug() << __PRETTY_FUNCTION__; + //qDebug() << __PRETTY_FUNCTION__; if (inSrc == nullptr) { qDebug() << "ERR: bailing, inSrc null, " << __PRETTY_FUNCTION__; @@ -484,7 +484,7 @@ void LoadingWindow::videoSourceChanged(int arg1) { void LoadingWindow::setBaseDirectory(const QString & inBaseDir) { - qDebug() << __PRETTY_FUNCTION__ << ", " << inBaseDir; + //qDebug() << __PRETTY_FUNCTION__ << ", " << inBaseDir; if (qApp->thread() != QThread::currentThread()) qDebug() << "ERR: thread is not main! " << __PRETTY_FUNCTION__; /* diff --git a/examples/Qt/ISFEditor/ISFEditor_app/MainWindow.cpp b/examples/Qt/ISFEditor/ISFEditor_app/MainWindow.cpp index 986d1b9..5e3f11d 100644 --- a/examples/Qt/ISFEditor/ISFEditor_app/MainWindow.cpp +++ b/examples/Qt/ISFEditor/ISFEditor_app/MainWindow.cpp @@ -61,7 +61,6 @@ void MainWindow::widgetDrewItsFirstFrame() { // make the global buffer pool, using a newly-created context that shares the base global context CreateGlobalBufferPool(widgetCtx->newContextSharingMe()); - cout << "global buffer pool is " << GetGlobalBufferPool() << endl; // don't tell the widget to start rendering- doing so will cause it to start rendering at 60fps //ui->bufferView->startRendering(); @@ -108,22 +107,24 @@ void FinishLaunching() { // connect the output window's buffer view's signal to the ISFController's redraw slot ISFGLBufferQWidget *bufferView = (ow==nullptr) ? nullptr : ow->bufferView(); - if (bufferView == nullptr) - qDebug() << "ERR: bufferView nil in " << __PRETTY_FUNCTION__; + if (bufferView == nullptr) { + //qDebug() << "ERR: bufferView nil in " << __PRETTY_FUNCTION__; + } else { QObject::connect(bufferView, &QOpenGLWidget::frameSwapped, GetISFController(), &ISFController::widgetRedrawSlot); } - qDebug() << "about to show the output window..."; + //qDebug() << "about to show the output window..."; ow->show(); - qDebug() << "finished showing the output window..."; + //qDebug() << "finished showing the output window..."; // the doc window already created the auto updater- check for an update after a small delay QTimer::singleShot(500, [&]() { //qDebug() << "checking for update!"; AutoUpdater *aa = GetGlobalAutoUpdater(); - if (aa == nullptr) - cout << "ERR: auto updater nil in main()\n"; + if (aa == nullptr) { + //cout << "ERR: auto updater nil in main()\n"; + } else { //aa->checkForUpdates(); } diff --git a/examples/Qt/ISFEditor/ISFEditor_app/OutputWindow.cpp b/examples/Qt/ISFEditor/ISFEditor_app/OutputWindow.cpp index 47d995c..41a4f51 100644 --- a/examples/Qt/ISFEditor/ISFEditor_app/OutputWindow.cpp +++ b/examples/Qt/ISFEditor/ISFEditor_app/OutputWindow.cpp @@ -238,7 +238,7 @@ void OutputWindow::widgetDrewItsFirstFrame() { } */ void OutputWindow::aboutToQuit() { - qDebug() << __PRETTY_FUNCTION__; + //qDebug() << __PRETTY_FUNCTION__; QSettings settings; settings.setValue("OutputWindowGeometry", saveGeometry()); diff --git a/examples/Qt/ISFEditor/ISFEditor_app/VideoSource/DynamicVideoSource.cpp b/examples/Qt/ISFEditor/ISFEditor_app/VideoSource/DynamicVideoSource.cpp index 559e4b2..1284476 100644 --- a/examples/Qt/ISFEditor/ISFEditor_app/VideoSource/DynamicVideoSource.cpp +++ b/examples/Qt/ISFEditor/ISFEditor_app/VideoSource/DynamicVideoSource.cpp @@ -151,7 +151,7 @@ MediaFile::Type DynamicVideoSource::srcType() { void DynamicVideoSource::loadFile(const MediaFile & n) { - qDebug() << __PRETTY_FUNCTION__ << "... " << n.name(); + //qDebug() << __PRETTY_FUNCTION__ << "... " << n.name(); lock_guard tmpLock(srcLock); diff --git a/examples/Qt/ISFEditor/ISFEditor_app/VideoSource/ISFVideoSource.cpp b/examples/Qt/ISFEditor/ISFEditor_app/VideoSource/ISFVideoSource.cpp index b3febff..8fedb08 100644 --- a/examples/Qt/ISFEditor/ISFEditor_app/VideoSource/ISFVideoSource.cpp +++ b/examples/Qt/ISFEditor/ISFEditor_app/VideoSource/ISFVideoSource.cpp @@ -155,7 +155,7 @@ bool ISFVideoSource::playingBackItem(const MediaFile & n) { return false; } void ISFVideoSource::loadFile(const MediaFile & n) { - qDebug() << __PRETTY_FUNCTION__ << ", " << n; + //qDebug() << __PRETTY_FUNCTION__ << ", " << n; if (n.type() != MediaFile::Type_ISF) return; diff --git a/examples/Qt/ISFEditor/ISFEditor_app/main.cpp b/examples/Qt/ISFEditor/ISFEditor_app/main.cpp index e8d38f4..a5f1a8a 100644 --- a/examples/Qt/ISFEditor/ISFEditor_app/main.cpp +++ b/examples/Qt/ISFEditor/ISFEditor_app/main.cpp @@ -74,7 +74,6 @@ int main(int argc, char *argv[]) if (qApp == nullptr) qDebug() << "ERR: qApp NULL"; else { - qDebug() << "installing event filter!"; FileLoadEventFilter *tmpThing = new FileLoadEventFilter(qApp); qApp->installEventFilter(tmpThing); } diff --git a/examples/Qt/ISFEditor/ISFEditor_app/misc_classes/LoadingWindowFileListModel.cpp b/examples/Qt/ISFEditor/ISFEditor_app/misc_classes/LoadingWindowFileListModel.cpp index f09fe64..3887081 100644 --- a/examples/Qt/ISFEditor/ISFEditor_app/misc_classes/LoadingWindowFileListModel.cpp +++ b/examples/Qt/ISFEditor/ISFEditor_app/misc_classes/LoadingWindowFileListModel.cpp @@ -17,7 +17,7 @@ LoadingWindowFileListModel::LoadingWindowFileListModel(QObject * parent) : QFileSystemModel(parent) { - qDebug() << __PRETTY_FUNCTION__; + //qDebug() << __PRETTY_FUNCTION__; setReadOnly(true); //setReadOnly(false); setFilter(QDir::Files); @@ -69,7 +69,7 @@ bool LoadingWindowFileListModel::canDropMimeData(const QMimeData *data, Qt::Drop } bool LoadingWindowFileListModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) { - qDebug() << __PRETTY_FUNCTION__; + //qDebug() << __PRETTY_FUNCTION__; if (!canDropMimeData(data, action, row, column, parent)) return false; @@ -79,7 +79,7 @@ bool LoadingWindowFileListModel::dropMimeData(const QMimeData *data, Qt::DropAct QList urls = data->urls(); for (const QUrl & url : urls) { QString localPath = url.toLocalFile(); - qDebug() << "\turl is " << url << ", path is " << localPath; + //qDebug() << "\turl is " << url << ", path is " << localPath; QFileInfo fi(localPath); if (fi.isDir()) { lw->setBaseDirectory(localPath); diff --git a/examples/Qt/TexDownloadBenchmark/TexDownloadBenchmark.pro b/examples/Qt/TexDownloadBenchmark/TexDownloadBenchmark.pro index 38cc8a7..b219772 100644 --- a/examples/Qt/TexDownloadBenchmark/TexDownloadBenchmark.pro +++ b/examples/Qt/TexDownloadBenchmark/TexDownloadBenchmark.pro @@ -34,16 +34,21 @@ DEFINES += VVGL_SDK_QT SOURCES += \ main.cpp \ TexDownloadBenchmarkMainWindow.cpp \ - ../common/GLBufferQWidget.cpp + ../common/GLBufferQWidget.cpp \ + ../common/DisplayLinkDriver.mm HEADERS += \ TexDownloadBenchmarkMainWindow.h \ - ../common/GLBufferQWidget.h + ../common/GLBufferQWidget.h \ + ../common/DisplayLinkDriver.h FORMS += \ TexDownloadBenchmarkMainWindow.ui +mac { + LIBS += -framework CoreVideo -framework AppKit +} # additions for VVGL lib diff --git a/examples/Qt/TexUploadBenchmark/TexUploadBenchmark.pro b/examples/Qt/TexUploadBenchmark/TexUploadBenchmark.pro index 1472c34..1a2f52c 100644 --- a/examples/Qt/TexUploadBenchmark/TexUploadBenchmark.pro +++ b/examples/Qt/TexUploadBenchmark/TexUploadBenchmark.pro @@ -35,15 +35,20 @@ SOURCES += \ main.cpp \ TexUploadBenchmarkMainWindow.cpp \ ../common/GLBufferQWidget.cpp \ + ../common/DisplayLinkDriver.mm HEADERS += \ TexUploadBenchmarkMainWindow.h \ ../common/GLBufferQWidget.h \ + ../common/DisplayLinkDriver.h FORMS += \ TexUploadBenchmarkMainWindow.ui +mac { + LIBS += -framework CoreVideo -framework AppKit +} # additions for VVGL lib diff --git a/examples/Qt/TexUploadBenchmark/TexUploadBenchmarkMainWindow.cpp b/examples/Qt/TexUploadBenchmark/TexUploadBenchmarkMainWindow.cpp index 84fe139..389a813 100644 --- a/examples/Qt/TexUploadBenchmark/TexUploadBenchmarkMainWindow.cpp +++ b/examples/Qt/TexUploadBenchmark/TexUploadBenchmarkMainWindow.cpp @@ -164,7 +164,7 @@ GLBufferRef TexUploadBenchmarkMainWindow::createTexForWork() desc.msAmount = 0; desc.localSurfaceID = 0; - GLBufferRef returnMe = GetGlobalBufferPool()->createBufferRef(desc, cpuBuffer->srcRect.size, nullptr, Size(), true); + GLBufferRef returnMe = GetGlobalBufferPool()->createBufferRef(desc, cpuBuffer->srcRect.size, nullptr, VVGL::Size(), true); returnMe->parentBufferPool = GetGlobalBufferPool(); return returnMe; diff --git a/examples/Qt/common/DisplayLinkDriver.h b/examples/Qt/common/DisplayLinkDriver.h new file mode 100644 index 0000000..44b1989 --- /dev/null +++ b/examples/Qt/common/DisplayLinkDriver.h @@ -0,0 +1,38 @@ +#ifndef DISPLAYLINKDRIVER_H +#define DISPLAYLINKDRIVER_H + +#include +#include + + + + +class DisplayLinkDriver : public QObject +{ + Q_OBJECT + + using DisplayLinkCallback = std::function; + +public: + // moves the passed context to the thread (to self), creates a buffer pool & thread copier using the ctx, will use the ctx to perform all rendering + explicit DisplayLinkDriver(QObject * parent = nullptr); + ~DisplayLinkDriver(); + + void performCallback(); + + void setDisplayLinkCallback(const DisplayLinkCallback & n=nullptr); + +public slots: + Q_SLOT void start(); + Q_SLOT void stop(); + +private: + void *_displayLink = NULL; // really a CVDisplayLinkRef + + DisplayLinkCallback _displayLinkCallback = nullptr; +}; + + + + +#endif // DISPLAYLINKDRIVER_H diff --git a/examples/Qt/common/DisplayLinkDriver.mm b/examples/Qt/common/DisplayLinkDriver.mm new file mode 100644 index 0000000..5d4c79c --- /dev/null +++ b/examples/Qt/common/DisplayLinkDriver.mm @@ -0,0 +1,139 @@ +#include "DisplayLinkDriver.h" + +#include + +#include +//#include "VVGL.hpp" +#import +#import + + + + +CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp *inNow, const CVTimeStamp *inOutputTime, CVOptionFlags flagsIn, CVOptionFlags *flagsOut, void *displayLinkContext); + + + + +DisplayLinkDriver::DisplayLinkDriver(QObject * inParent) : QObject(inParent) { + //qDebug() << __PRETTY_FUNCTION__; +} +DisplayLinkDriver::~DisplayLinkDriver() { + stop(); +} + + +void DisplayLinkDriver::performCallback() { + //qDebug() << __PRETTY_FUNCTION__; + if (_displayLinkCallback != nullptr) + _displayLinkCallback(); +} + + +void DisplayLinkDriver::setDisplayLinkCallback(const DisplayLinkCallback & n) { + _displayLinkCallback = n; +} + + +void DisplayLinkDriver::start() { + //qDebug() << __PRETTY_FUNCTION__; + + if (_displayLink != NULL) + return; + + @autoreleasepool { + // make the displaylink, which will drive rendering + CVReturn err = kCVReturnSuccess; + CGOpenGLDisplayMask totalDisplayMask = 0; + GLint virtualScreen = 0; + GLint displayMask = 0; + + + + + CGError cgErr = kCGErrorSuccess; + CGDirectDisplayID dspys[10]; + CGDisplayCount count = 0; + uint32_t glDisplayMask = 0; + cgErr = CGGetActiveDisplayList(10,dspys,&count); + if (cgErr == kCGErrorSuccess) { + int i; + for (i=0;i(tmpDisplayLink); + } +} +void DisplayLinkDriver::stop() { + //qDebug() << __PRETTY_FUNCTION__; + + if (_displayLink == NULL) + return; + + @autoreleasepool { + CVDisplayLinkRef tmpDisplayLink = static_cast(_displayLink); + CVDisplayLinkStop(tmpDisplayLink); + CVDisplayLinkRelease(tmpDisplayLink); + _displayLink = NULL; + } +} + + + + + + + + +CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, + const CVTimeStamp *inNow, + const CVTimeStamp *inOutputTime, + CVOptionFlags flagsIn, + CVOptionFlags *flagsOut, + void *displayLinkContext) +{ + NSAutoreleasePool *pool =[[NSAutoreleasePool alloc] init]; + static_cast(displayLinkContext)->performCallback(); + [pool release]; + return kCVReturnSuccess; +} diff --git a/examples/Qt/common/GLBufferQWidget.cpp b/examples/Qt/common/GLBufferQWidget.cpp index 465596a..8fc06ce 100644 --- a/examples/Qt/common/GLBufferQWidget.cpp +++ b/examples/Qt/common/GLBufferQWidget.cpp @@ -18,9 +18,18 @@ using namespace VVGL; GLBufferQWidget::GLBufferQWidget(QWidget * inParent) : QOpenGLWidget(inParent) +#ifdef Q_OS_MACOS + , displayLinkDriver(inParent) +#endif { //cout << __PRETTY_FUNCTION__ << endl; connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(aboutToQuit())); + +#ifdef Q_OS_MACOS + displayLinkDriver.setDisplayLinkCallback([&]() { + QMetaObject::invokeMethod(this, "update", Qt::AutoConnection); + }); +#endif } GLBufferQWidget::~GLBufferQWidget() { @@ -34,7 +43,9 @@ void GLBufferQWidget::drawBuffer(const GLBufferRef & inBuffer) { lock_guard lock(ctxLock); buffer = inBuffer; +#ifndef Q_OS_MACOS update(); +#endif } GLBufferRef GLBufferQWidget::getBuffer() { @@ -73,7 +84,9 @@ void GLBufferQWidget::_renderNow() { } if (renderAnotherFrame) { +#ifndef Q_OS_MACOS update(); +#endif } bp->housekeeping(); @@ -185,7 +198,11 @@ void GLBufferQWidget::startRenderingSlot() //connect(ctxThread, SIGNAL(started()), this, SLOT(requestUpdate())); //connect(ctxThread, &QThread::started, this, &GLBufferQWidget::requestUpdate); //ctxThread->start(); +#ifdef Q_OS_MACOS + displayLinkDriver.start(); +#else update(); +#endif //cout << "\tFINISHED- " << __PRETTY_FUNCTION__ << endl; } void GLBufferQWidget::stopRenderingSlot() @@ -212,6 +229,9 @@ void GLBufferQWidget::stopRenderingSlot() //ctxThread->quit(); //ctxThread->deleteLater(); ctxThread = nullptr; +#ifdef Q_OS_MACOS + displayLinkDriver.stop(); +#endif //qDebug()<<"\tctxThread is now "< #include +#ifdef Q_OS_MACOS +#include "DisplayLinkDriver.h" +#endif + @@ -42,6 +46,9 @@ public slots: void _renderNow(); private: +#ifdef Q_OS_MACOS + DisplayLinkDriver displayLinkDriver; // calling 'QOpenGLWidget::update' on macs breaks Qt: https://bugreports.qt.io/browse/QTBUG-73209 +#endif std::recursive_mutex ctxLock; VVGL::GLContextRef ctx = nullptr; VVGL::GLSceneRef scene = nullptr; diff --git a/examples/Qt/common/ISFGLBufferQWidget.cpp b/examples/Qt/common/ISFGLBufferQWidget.cpp index 81e9390..629a829 100644 --- a/examples/Qt/common/ISFGLBufferQWidget.cpp +++ b/examples/Qt/common/ISFGLBufferQWidget.cpp @@ -20,9 +20,18 @@ using namespace VVISF; ISFGLBufferQWidget::ISFGLBufferQWidget(QWidget * inParent) : QOpenGLWidget(inParent) +#ifdef Q_OS_MACOS + , displayLinkDriver(inParent) +#endif { //cout << __PRETTY_FUNCTION__ << endl; connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(aboutToQuit())); + +#ifdef Q_OS_MACOS + displayLinkDriver.setDisplayLinkCallback([&]() { + QMetaObject::invokeMethod(this, "update", Qt::AutoConnection); + }); +#endif } ISFGLBufferQWidget::~ISFGLBufferQWidget() { @@ -36,7 +45,9 @@ void ISFGLBufferQWidget::drawBuffer(const GLBufferRef & inBuffer) { lock_guard lock(ctxLock); buffer = inBuffer; +#ifndef Q_OS_MACOS update(); +#endif } GLBufferRef ISFGLBufferQWidget::getBuffer() { @@ -78,7 +89,9 @@ void ISFGLBufferQWidget::_renderNow() { } if (renderAnotherFrame) { +#ifndef Q_OS_MACOS update(); +#endif } } @@ -188,7 +201,11 @@ void ISFGLBufferQWidget::startRenderingSlot() //connect(ctxThread, SIGNAL(started()), this, SLOT(requestUpdate())); //connect(ctxThread, &QThread::started, this, &ISFGLBufferQWidget::requestUpdate); //ctxThread->start(); +#ifdef Q_OS_MACOS + displayLinkDriver.start(); +#else update(); +#endif //cout << "\tFINISHED- " << __PRETTY_FUNCTION__ << endl; } void ISFGLBufferQWidget::stopRenderingSlot() @@ -215,6 +232,9 @@ void ISFGLBufferQWidget::stopRenderingSlot() //ctxThread->quit(); //ctxThread->deleteLater(); ctxThread = nullptr; +#ifdef Q_OS_MACOS + displayLinkDriver.stop(); +#endif //qDebug()<<"\tctxThread is now "<setPerformClear(true); //scene->setClearColor(0., 0., 0., 0.); - + + /* if (scene->context()->sameShareGroupAs(GetGlobalBufferPool()->context())) cout << "\tISFGLBufferQWidget is in same sharegroup as buffer pool...\n"; else cout << "\tERR: ISFGLBufferQWidget is NOT in same sharegroup as buffer pool!\n"; + */ } diff --git a/examples/Qt/common/ISFGLBufferQWidget.h b/examples/Qt/common/ISFGLBufferQWidget.h index 2edeab0..3b9df7a 100644 --- a/examples/Qt/common/ISFGLBufferQWidget.h +++ b/examples/Qt/common/ISFGLBufferQWidget.h @@ -6,6 +6,10 @@ #include #include +#ifdef Q_OS_MACOS +#include "DisplayLinkDriver.h" +#endif + @@ -44,6 +48,9 @@ public slots: void _renderNow(); protected: +#ifdef Q_OS_MACOS + DisplayLinkDriver displayLinkDriver; // calling 'QOpenGLWidget::update' on macs breaks Qt: https://bugreports.qt.io/browse/QTBUG-73209 +#endif std::recursive_mutex ctxLock; VVGL::GLContextRef ctx = nullptr; VVISF::ISFSceneRef scene = nullptr; diff --git a/examples/Qt/common/VVGLRenderQThread.cpp b/examples/Qt/common/VVGLRenderQThread.cpp index 648eda8..4f682d2 100644 --- a/examples/Qt/common/VVGLRenderQThread.cpp +++ b/examples/Qt/common/VVGLRenderQThread.cpp @@ -58,7 +58,7 @@ VVGL::GLTexToTexCopierRef VVGLRenderQThread::texCopier() { void VVGLRenderQThread::start(QThread::Priority inPriority) { - qDebug() << __PRETTY_FUNCTION__; + //qDebug() << __PRETTY_FUNCTION__; if (_ctx != nullptr) _ctx->moveToThread(this); @@ -72,7 +72,7 @@ void VVGLRenderQThread::start(QThread::Priority inPriority) { void VVGLRenderQThread::run() { - qDebug() << __PRETTY_FUNCTION__; + //qDebug() << __PRETTY_FUNCTION__; while (1) { //qDebug() << "\tentering wait loop...";