diff --git a/app/node/processor/renderer/renderer.cpp b/app/node/processor/renderer/renderer.cpp index e5b8f3cb4..2ad69c726 100644 --- a/app/node/processor/renderer/renderer.cpp +++ b/app/node/processor/renderer/renderer.cpp @@ -26,7 +26,6 @@ #include #include #include -#include #include #include "common/filefunctions.h" @@ -76,7 +75,6 @@ void RendererProcessor::SetCacheName(const QString &s) GenerateCacheIDInternal(); } -#include QVariant RendererProcessor::Value(NodeOutput* output, const rational& time) { if (output == texture_output_) { @@ -199,7 +197,7 @@ void RendererProcessor::Start() QOpenGLContext* ctx = QOpenGLContext::currentContext(); - int background_thread_count = qMax(1, QThread::idealThreadCount() - 1); + int background_thread_count = QThread::idealThreadCount(); threads_.resize(background_thread_count); @@ -240,16 +238,16 @@ void RendererProcessor::Stop() started_ = false; - foreach (RendererProcessThreadPtr process_thread, threads_) { - process_thread->Cancel(); - } - threads_.clear(); - foreach (RendererDownloadThreadPtr download_thread_, download_threads_) { download_thread_->Cancel(); } download_threads_.clear(); + foreach (RendererProcessThreadPtr process_thread, threads_) { + process_thread->Cancel(); + } + threads_.clear(); + master_texture_ = nullptr; cache_frame_load_buffer_.clear(); @@ -265,9 +263,10 @@ void RendererProcessor::GenerateCacheIDInternal() QCryptographicHash hash(QCryptographicHash::Sha1); hash.addData(cache_name_.toUtf8()); hash.addData(QString::number(cache_time_).toUtf8()); - hash.addData(QString::number(effective_width_).toUtf8()); - hash.addData(QString::number(effective_height_).toUtf8()); + hash.addData(QString::number(width_).toUtf8()); + hash.addData(QString::number(height_).toUtf8()); hash.addData(QString::number(format_).toUtf8()); + hash.addData(QString::number(divider_).toUtf8()); QByteArray bytes = hash.result(); cache_id_ = bytes.toHex(); @@ -286,7 +285,6 @@ void RendererProcessor::CacheNext() qDebug() << "[RendererProcessor] Caching" << cache_frame_.toDouble(); - // Run this probe in another thread master_thread_ = threads_.at(0).get(); master_thread_->Queue(NodeDependency(texture_input_->get_connected_output(), cache_frame_), true); @@ -315,15 +313,14 @@ void RendererProcessor::ThreadCallback() // Threads are all done now, time to proceed caching_ = false; - // FIXME: Save the texture results here RenderTexturePtr texture = texture_input_->get_value(cache_frame_).value(); - QString fn = CachePathName(cache_frame_); - if (texture == nullptr && QFileInfo::exists(fn)) { - QFile(fn).remove(); + if (texture == nullptr) { + if (QFileInfo::exists(fn)) { + QFile(fn).remove(); + } } else { - // Choose download thread with the smallest queue download_threads_[last_download_thread_%download_threads_.size()]->Queue(texture, fn); last_download_thread_++; } diff --git a/app/node/processor/renderer/rendererdownloadthread.cpp b/app/node/processor/renderer/rendererdownloadthread.cpp index c0250f184..374eb709b 100644 --- a/app/node/processor/renderer/rendererdownloadthread.cpp +++ b/app/node/processor/renderer/rendererdownloadthread.cpp @@ -1,6 +1,7 @@ #include "rendererdownloadthread.h" #include +#include #include #include "common/define.h" @@ -13,7 +14,6 @@ RendererDownloadThread::RendererDownloadThread(QOpenGLContext *share_ctx, const olive::RenderMode &mode) : RendererThreadBase(share_ctx, width, height, format, mode) { - } void RendererDownloadThread::Queue(RenderTexturePtr texture, const QString& fn) @@ -42,68 +42,62 @@ void RendererDownloadThread::ProcessLoop() render_instance()->width(), render_instance()->height()); - uchar* data_buffer = new uchar[buffer_size]; + QVector data_buffer; + data_buffer.resize(buffer_size); + + PixelFormatInfo format_info = PixelService::GetPixelFormatInfo(render_instance()->format()); + + // Set up OIIO::ImageSpec for compressing cached images on disk + OIIO::ImageSpec spec(render_instance()->width(), render_instance()->height(), kRGBAChannels, format_info.oiio_desc); + spec.attribute("compression", "dwaa:200"); while (!Cancelled()) { // Check queue for textures to download (use mutex to prevent collisions) texture_queue_lock_.lock(); - do { - if (texture_queue_.isEmpty()) { - working_texture = nullptr; - } else { - working_texture = texture_queue_.takeFirst(); - working_filename = download_filenames_.takeFirst(); - } + while (texture_queue_.isEmpty()) { + // Main waiting condition + wait_cond_.wait(&texture_queue_lock_); + } - if (working_texture == nullptr) { - // Main waiting condition - wait_cond_.wait(&texture_queue_lock_); - } - } while (working_texture == nullptr); + working_texture = texture_queue_.takeFirst(); + working_filename = download_filenames_.takeFirst(); texture_queue_lock_.unlock(); // Download the texture - f->glBindFramebuffer(GL_READ_FRAMEBUFFER, read_buffer_); - xf->glFramebufferTexture2D(GL_READ_FRAMEBUFFER, + f->glBindFramebuffer(GL_FRAMEBUFFER, read_buffer_); + + xf->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, working_texture->texture(), 0); - PixelFormatInfo format_info = PixelService::GetPixelFormatInfo(working_texture->format()); - f->glReadPixels(0, 0, working_texture->width(), working_texture->height(), format_info.pixel_format, format_info.pixel_type, - data_buffer); + data_buffer.data()); - xf->glFramebufferTexture2D(GL_READ_FRAMEBUFFER, + xf->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); - f->glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + f->glBindFramebuffer(GL_FRAMEBUFFER, 0); std::string working_fn_std = working_filename.toStdString(); std::unique_ptr out = OIIO::ImageOutput::create(working_fn_std); if (out) { - OIIO::ImageSpec spec(working_texture->width(), working_texture->height(), kRGBAChannels, format_info.oiio_desc); - - spec.attribute("compression", "dwaa:200"); - out->open(working_fn_std, spec); - - out->write_image(format_info.oiio_desc, data_buffer); - + out->write_image(format_info.oiio_desc, data_buffer.data()); out->close(); } @@ -111,7 +105,5 @@ void RendererDownloadThread::ProcessLoop() } - delete [] data_buffer; - f->glDeleteFramebuffers(1, &read_buffer_); } diff --git a/app/render/renderinstance.cpp b/app/render/renderinstance.cpp index 1b592c490..3941e6de1 100644 --- a/app/render/renderinstance.cpp +++ b/app/render/renderinstance.cpp @@ -43,6 +43,10 @@ void RenderInstance::SetShareContext(QOpenGLContext *share) bool RenderInstance::Start() { + if (IsStarted()) { + return true; + } + // If we're sharing resources, set this up now if (share_ctx_ != nullptr) { ctx_.setShareContext(share_ctx_); diff --git a/app/render/rendertexture.cpp b/app/render/rendertexture.cpp index 184532c89..16ac9680d 100644 --- a/app/render/rendertexture.cpp +++ b/app/render/rendertexture.cpp @@ -25,11 +25,14 @@ #include "render/pixelservice.h" +// FIXME: Test code +QMutex m; +// End test code + RenderTexture::RenderTexture() : context_(nullptr), texture_(0) { - } RenderTexture::~RenderTexture() @@ -62,11 +65,11 @@ void RenderTexture::Create(QOpenGLContext *ctx, int width, int height, const oli format_ = format; // Create main texture - CreateInternal(data); + CreateInternal(&texture_, data); if (type == kDoubleBuffer) { // Create back texture - CreateInternal(nullptr); + CreateInternal(&back_texture_, nullptr); } } @@ -196,12 +199,12 @@ uchar *RenderTexture::Download() const return data; } -void RenderTexture::CreateInternal(void *data) +void RenderTexture::CreateInternal(GLuint* tex, void *data) { QOpenGLFunctions* f = context_->functions(); // Create texture - f->glGenTextures(1, &texture_); + f->glGenTextures(1, tex); // Verify texture if (texture_ == 0) { @@ -210,7 +213,7 @@ void RenderTexture::CreateInternal(void *data) } // Bind texture - f->glBindTexture(GL_TEXTURE_2D, texture_); + f->glBindTexture(GL_TEXTURE_2D, *tex); // Allocate storage for texture const PixelFormatInfo& bit_depth = PixelService::GetPixelFormatInfo(format_); diff --git a/app/render/rendertexture.h b/app/render/rendertexture.h index 6225adb89..360f451d0 100644 --- a/app/render/rendertexture.h +++ b/app/render/rendertexture.h @@ -26,6 +26,11 @@ #include "pixelformat.h" +// FIXME: Test code +#include +extern QMutex m; +// End test code + class RenderTexture : public QObject { public: @@ -69,7 +74,7 @@ public: uchar *Download() const; private: - void CreateInternal(void *data = nullptr); + void CreateInternal(GLuint *tex, void *data = nullptr); QOpenGLContext* context_; diff --git a/app/task/import/import.cpp b/app/task/import/import.cpp index ddf8bfc62..b2491e5b5 100644 --- a/app/task/import/import.cpp +++ b/app/task/import/import.cpp @@ -39,7 +39,8 @@ ImportTask::ImportTask(ProjectViewModel *model, Folder *parent, const QStringList &urls) : model_(model), urls_(urls), - parent_(parent) + parent_(parent), + command_(nullptr) { set_text(tr("Importing %1 files").arg(urls.size())); } @@ -48,16 +49,25 @@ bool ImportTask::Action() { parent_->LockDeletes(); - QUndoCommand* command = new QUndoCommand(); + command_ = new QUndoCommand(); - Import(urls_, parent_, command); + Import(urls_, parent_, command_); // If this task was cancelled, we won't bother pushing an undo command (we don't end up with anything undoable since // the undo command executes the final import anyway) if (cancelled()) { - delete command; - } else { - olive::undo_stack.push(command); + delete command_; + command_ = nullptr; + parent_->UnlockDeletes(); + } + + return true; +} + +bool ImportTask::Epilogue() +{ + if (command_ != nullptr) { + olive::undo_stack.push(command_); } parent_->UnlockDeletes(); diff --git a/app/task/import/import.h b/app/task/import/import.h index ce33daf1e..268744b5d 100644 --- a/app/task/import/import.h +++ b/app/task/import/import.h @@ -41,12 +41,16 @@ public: virtual bool Action() override; + virtual bool Epilogue() override; + private: void Import(const QStringList& files, Folder* folder, QUndoCommand* parent_command); ProjectViewModel* model_; QStringList urls_; Folder* parent_; + + QUndoCommand* command_; }; #endif // IMPORT_H