diff --git a/app/widget/scope/CMakeLists.txt b/app/widget/scope/CMakeLists.txt
index a14b351dd..91c4f0b44 100644
--- a/app/widget/scope/CMakeLists.txt
+++ b/app/widget/scope/CMakeLists.txt
@@ -15,6 +15,7 @@
# along with this program. If not, see .
add_subdirectory(histogram)
+add_subdirectory(scopebase)
add_subdirectory(waveform)
set(OLIVE_SOURCES
diff --git a/app/widget/scope/histogram/histogram.cpp b/app/widget/scope/histogram/histogram.cpp
index b9028f85a..9665e32de 100644
--- a/app/widget/scope/histogram/histogram.cpp
+++ b/app/widget/scope/histogram/histogram.cpp
@@ -29,189 +29,8 @@
OLIVE_NAMESPACE_ENTER
HistogramScope::HistogramScope(QWidget* parent) :
- ManagedDisplayWidget(parent),
- buffer_(nullptr)
+ ScopeBase(parent)
{
- EnableDefaultContextMenu();
-
- connect(&worker_, &HistogramScopeWorker::Finished, this, &HistogramScope::FinishedProcessing, Qt::QueuedConnection);
- worker_.start(QThread::IdlePriority);
-}
-
-HistogramScope::~HistogramScope()
-{
- worker_.Cancel();
- worker_.quit();
- worker_.wait();
-}
-
-void HistogramScope::SetBuffer(Frame* frame)
-{
- buffer_ = frame;
-
- if (isVisible()) {
- StartUpdate();
- }
-}
-
-void HistogramScope::FinishedProcessing(QVector red, QVector green, QVector blue)
-{
- red_val_ = red;
- green_val_ = green;
- blue_val_ = blue;
-
- update();
-}
-
-void HistogramScope::paintGL()
-{
- QVector red_lines(red_val_.size());
- QVector green_lines(green_val_.size());
- QVector blue_lines(blue_val_.size());
-
- for (int i=0;i data(w * kRGBChannels, 0);
-
- int max_w = w-1;
-
- for (int x=0;xConvertColor(c);
- }
-
- data[qFloor(clamp(c.red(), 0.0f, 1.0f) * max_w)]++;
- data[qFloor(clamp(c.green(), 0.0f, 1.0f) * max_w) + w]++;
- data[qFloor(clamp(c.blue(), 0.0f, 1.0f) * max_w) + w * 2]++;
- }
- }
-
- int max_val = 0;
-
- foreach (const int& i, data) {
- if (i > max_val) {
- max_val = i;
- }
- }
-
- if (!max_val) {
- // Prevent divide by zero
- return;
- }
-
- QVector red_lines(w);
- QVector green_lines(w);
- QVector blue_lines(w);
-
- for (int i=0;i(data.at(i)) / static_cast(max_val));
- green_lines.replace(i, static_cast(data.at(i + w)) / static_cast(max_val));
- blue_lines.replace(i, static_cast(data.at(i + w * 2)) / static_cast(max_val));
- }
-
- emit Finished(red_lines, green_lines, blue_lines);
- }
-}
-
-void HistogramScopeWorker::QueueNext(const Frame &f, ColorProcessorPtr processor, int width)
-{
- next_lock_.lock();
-
- next_ = f;
- next_width_ = width;
- next_processor_ = processor;
-
- next_wait_.wakeOne();
-
- next_lock_.unlock();
-}
-
-void HistogramScopeWorker::Cancel()
-{
- cancelled_ = true;
- next_lock_.lock();
- next_wait_.wakeOne();
- next_lock_.unlock();
}
OLIVE_NAMESPACE_EXIT
diff --git a/app/widget/scope/histogram/histogram.h b/app/widget/scope/histogram/histogram.h
index 3efad3919..625074a89 100644
--- a/app/widget/scope/histogram/histogram.h
+++ b/app/widget/scope/histogram/histogram.h
@@ -21,80 +21,20 @@
#ifndef HISTOGRAMSCOPE_H
#define HISTOGRAMSCOPE_H
-#include
-#include
-#include
-
-#include "codec/frame.h"
-#include "render/colorprocessor.h"
-#include "widget/manageddisplay/manageddisplay.h"
+#include "widget/scope/scopebase/scopebase.h"
OLIVE_NAMESPACE_ENTER
-class HistogramScopeWorker : public QThread
-{
- Q_OBJECT
-public:
- HistogramScopeWorker();
-
- // Thread-safe
- void QueueNext(const Frame& f, ColorProcessorPtr processor, int width);
-
- // Thread-safe
- void Cancel();
-
-protected:
- virtual void run() override;
-
-signals:
- void Finished(QVector red, QVector green, QVector blue);
-
-private:
- QAtomicInt cancelled_;
-
- QMutex next_lock_;
- QWaitCondition next_wait_;
- Frame next_;
- int next_width_;
- ColorProcessorPtr next_processor_;
-
-};
-
-class HistogramScope : public ManagedDisplayWidget
+class HistogramScope : public ScopeBase
{
Q_OBJECT
public:
HistogramScope(QWidget* parent = nullptr);
- virtual ~HistogramScope() override;
-
-public slots:
- void SetBuffer(Frame* frame);
-
protected:
- virtual void paintGL() override;
+ //virtual OpenGLShaderPtr CreateShader() override;
- virtual void resizeEvent(QResizeEvent* e) override;
-
- virtual void ColorProcessorChangedEvent() override;
-
- virtual void showEvent(QShowEvent* e) override;
-
-private:
- void StartUpdate();
-
- Frame* buffer_;
-
- QVector red_val_;
-
- QVector green_val_;
-
- QVector blue_val_;
-
- HistogramScopeWorker worker_;
-
-private slots:
- void FinishedProcessing(QVector red, QVector green, QVector blue);
+ //virtual void DrawScope() override;
};
diff --git a/app/widget/scope/scopebase/CMakeLists.txt b/app/widget/scope/scopebase/CMakeLists.txt
new file mode 100644
index 000000000..ca6d924c3
--- /dev/null
+++ b/app/widget/scope/scopebase/CMakeLists.txt
@@ -0,0 +1,22 @@
+# Olive - Non-Linear Video Editor
+# Copyright (C) 2019 Olive Team
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+set(OLIVE_SOURCES
+ ${OLIVE_SOURCES}
+ widget/scope/scopebase/scopebase.h
+ widget/scope/scopebase/scopebase.cpp
+ PARENT_SCOPE
+)
diff --git a/app/widget/scope/scopebase/scopebase.cpp b/app/widget/scope/scopebase/scopebase.cpp
new file mode 100644
index 000000000..c58b9e8bd
--- /dev/null
+++ b/app/widget/scope/scopebase/scopebase.cpp
@@ -0,0 +1,163 @@
+/***
+
+ Olive - Non-Linear Video Editor
+ Copyright (C) 2019 Olive Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+***/
+
+#include "scopebase.h"
+
+#include "render/backend/opengl/openglrenderfunctions.h"
+
+OLIVE_NAMESPACE_ENTER
+
+ScopeBase::ScopeBase(QWidget* parent) :
+ ManagedDisplayWidget(parent),
+ buffer_(nullptr)
+{
+ EnableDefaultContextMenu();
+}
+
+ScopeBase::~ScopeBase()
+{
+ CleanUp();
+
+ if (context()) {
+ disconnect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &ScopeBase::CleanUp);
+ }
+}
+
+void ScopeBase::SetBuffer(Frame *frame)
+{
+ buffer_ = frame;
+
+ UploadTextureFromBuffer();
+}
+
+void ScopeBase::showEvent(QShowEvent* e)
+{
+ ManagedDisplayWidget::showEvent(e);
+
+ UploadTextureFromBuffer();
+}
+
+OpenGLShaderPtr ScopeBase::CreateShader()
+{
+ return OpenGLShader::CreateDefault();
+}
+
+void ScopeBase::DrawScope()
+{
+ managed_tex().Bind();
+
+ OpenGLRenderFunctions::Blit(pipeline());
+
+ managed_tex().Release();
+}
+
+OpenGLShaderPtr ScopeBase::pipeline()
+{
+ return pipeline_;
+}
+
+OpenGLTexture &ScopeBase::managed_tex()
+{
+ return managed_tex_;
+}
+
+void ScopeBase::UploadTextureFromBuffer()
+{
+ if (!isVisible()) {
+ return;
+ }
+
+ if (buffer_) {
+ makeCurrent();
+
+ if (!texture_.IsCreated()
+ || texture_.width() != buffer_->width()
+ || texture_.height() != buffer_->height()
+ || texture_.format() != buffer_->format()) {
+ texture_.Destroy();
+ managed_tex_.Destroy();
+
+ texture_.Create(context(), buffer_);
+ managed_tex_.Create(context(), buffer_->video_params());
+ } else {
+ texture_.Upload(buffer_);
+ }
+
+ doneCurrent();
+ }
+
+ update();
+}
+
+void ScopeBase::CleanUp()
+{
+ makeCurrent();
+
+ pipeline_ = nullptr;
+ texture_.Destroy();
+ managed_tex_.Destroy();
+ framebuffer_.Destroy();
+
+ doneCurrent();
+}
+
+void ScopeBase::initializeGL()
+{
+ ManagedDisplayWidget::initializeGL();
+
+ pipeline_ = CreateShader();
+
+ framebuffer_.Create(context());
+
+ connect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &ScopeBase::CleanUp, Qt::DirectConnection);
+
+ UploadTextureFromBuffer();
+}
+
+void ScopeBase::paintGL()
+{
+ QOpenGLFunctions* f = context()->functions();
+
+ f->glClearColor(0, 0, 0, 0);
+ f->glClear(GL_COLOR_BUFFER_BIT);
+
+ if (buffer_ && pipeline() && texture_.IsCreated()) {
+ // Convert reference frame to display space
+ framebuffer_.Attach(&managed_tex_);
+ framebuffer_.Bind();
+
+ texture_.Bind();
+
+ f->glViewport(0, 0, texture_.width(), texture_.height());
+
+ color_service()->ProcessOpenGL();
+
+ texture_.Release();
+
+ framebuffer_.Release();
+ framebuffer_.Detach();
+
+ f->glViewport(0, 0, width(), height());
+
+ DrawScope();
+ }
+}
+
+OLIVE_NAMESPACE_EXIT
diff --git a/app/widget/scope/scopebase/scopebase.h b/app/widget/scope/scopebase/scopebase.h
new file mode 100644
index 000000000..3098af212
--- /dev/null
+++ b/app/widget/scope/scopebase/scopebase.h
@@ -0,0 +1,78 @@
+/***
+
+ Olive - Non-Linear Video Editor
+ Copyright (C) 2019 Olive Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+***/
+
+#ifndef SCOPEBASE_H
+#define SCOPEBASE_H
+
+#include "codec/frame.h"
+#include "render/backend/opengl/openglcolorprocessor.h"
+#include "render/backend/opengl/openglframebuffer.h"
+#include "render/backend/opengl/openglshader.h"
+#include "render/backend/opengl/opengltexture.h"
+#include "widget/manageddisplay/manageddisplay.h"
+
+OLIVE_NAMESPACE_ENTER
+
+class ScopeBase : public ManagedDisplayWidget
+{
+public:
+ ScopeBase(QWidget* parent = nullptr);
+
+ virtual ~ScopeBase() override;
+
+public slots:
+ void SetBuffer(Frame* frame);
+
+protected:
+ virtual void initializeGL() override;
+
+ virtual void paintGL() override;
+
+ virtual void showEvent(QShowEvent* e) override;
+
+ virtual OpenGLShaderPtr CreateShader();
+
+ virtual void DrawScope();
+
+ OpenGLShaderPtr pipeline();
+
+ OpenGLTexture& managed_tex();
+
+private:
+ void UploadTextureFromBuffer();
+
+ OpenGLShaderPtr pipeline_;
+
+ OpenGLTexture texture_;
+
+ OpenGLTexture managed_tex_;
+
+ OpenGLFramebuffer framebuffer_;
+
+ Frame* buffer_;
+
+private slots:
+ void CleanUp();
+
+};
+
+OLIVE_NAMESPACE_EXIT
+
+#endif // SCOPEBASE_H
diff --git a/app/widget/scope/waveform/waveform.cpp b/app/widget/scope/waveform/waveform.cpp
index 5f9225b3f..6c3c43fc7 100644
--- a/app/widget/scope/waveform/waveform.cpp
+++ b/app/widget/scope/waveform/waveform.cpp
@@ -32,59 +32,24 @@
OLIVE_NAMESPACE_ENTER
WaveformScope::WaveformScope(QWidget* parent) :
- ManagedDisplayWidget(parent),
- buffer_(nullptr)
+ ScopeBase(parent)
{
- EnableDefaultContextMenu();
}
-WaveformScope::~WaveformScope()
+OpenGLShaderPtr WaveformScope::CreateShader()
{
- CleanUp();
+ OpenGLShaderPtr pipeline = OpenGLShader::Create();
- if (context()) {
- disconnect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &WaveformScope::CleanUp);
- }
+ pipeline->create();
+ pipeline->addShaderFromSourceCode(QOpenGLShader::Vertex, OpenGLShader::CodeDefaultVertex());
+ pipeline->addShaderFromSourceCode(QOpenGLShader::Fragment, Node::ReadFileAsString(":/shaders/rgbwaveform.frag"));
+ pipeline->link();
+
+ return pipeline;
}
-void WaveformScope::SetBuffer(Frame *frame)
+void WaveformScope::DrawScope()
{
- buffer_ = frame;
-
- UploadTextureFromBuffer();
-}
-
-void WaveformScope::showEvent(QShowEvent* e)
-{
- ManagedDisplayWidget::showEvent(e);
-
- UploadTextureFromBuffer();
-}
-
-void WaveformScope::initializeGL()
-{
- ManagedDisplayWidget::initializeGL();
-
- pipeline_ = OpenGLShader::Create();
- pipeline_->create();
- pipeline_->addShaderFromSourceCode(QOpenGLShader::Vertex, OpenGLShader::CodeDefaultVertex());
- pipeline_->addShaderFromSourceCode(QOpenGLShader::Fragment, Node::ReadFileAsString(":/shaders/rgbwaveform.frag"));
- pipeline_->link();
-
- framebuffer_.Create(context());
-
- connect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &WaveformScope::CleanUp, Qt::DirectConnection);
-
- UploadTextureFromBuffer();
-}
-
-void WaveformScope::paintGL()
-{
- QOpenGLFunctions* f = context()->functions();
-
- f->glClearColor(0, 0, 0, 0);
- f->glClear(GL_COLOR_BUFFER_BIT);
-
float waveform_scale = 0.80f;
float waveform_dim_x = width() * waveform_scale;
float waveform_dim_y = height() * waveform_scale;
@@ -93,59 +58,40 @@ void WaveformScope::paintGL()
float waveform_end_dim_x = width() - waveform_start_dim_x;
float waveform_end_dim_y = height() - waveform_start_dim_y;
- if (buffer_ && pipeline_ && texture_.IsCreated()) {
- // Convert reference frame to display space
- framebuffer_.Attach(&managed_tex_);
- framebuffer_.Bind();
+ // Draw waveform through shader
+ pipeline()->bind();
+ pipeline()->setUniformValue("ove_resolution", managed_tex().width(), managed_tex().height());
+ pipeline()->setUniformValue("ove_viewport", width(), height());
+ GLfloat luma[3] = {0.0, 0.0, 0.0};
+ color_manager()->GetDefaultLumaCoefs(luma);
+ pipeline()->setUniformValue("luma_coeffs", luma[0], luma[1], luma[2]);
- texture_.Bind();
+ // Scale of the waveform relative to the viewport surface.
+ pipeline()->setUniformValue("waveform_scale", waveform_scale);
+ pipeline()->setUniformValue(
+ "waveform_dims", waveform_dim_x, waveform_dim_y);
- f->glViewport(0, 0, texture_.width(), texture_.height());
+ pipeline()->setUniformValue(
+ "waveform_region",
+ waveform_start_dim_x, waveform_start_dim_y,
+ waveform_end_dim_x, waveform_end_dim_y);
- color_service()->ProcessOpenGL();
+ float waveform_start_uv_x = waveform_start_dim_x / width();
+ float waveform_start_uv_y = waveform_start_dim_y / height();
+ float waveform_end_uv_x = waveform_end_dim_x / width();
+ float waveform_end_uv_y = waveform_end_dim_y / height();
+ pipeline()->setUniformValue(
+ "waveform_uv",
+ waveform_start_uv_x, waveform_start_uv_y,
+ waveform_end_uv_x, waveform_end_uv_y);
- texture_.Release();
+ pipeline()->release();
- framebuffer_.Release();
- framebuffer_.Detach();
+ managed_tex().Bind();
- // Draw waveform through shader
- pipeline_->bind();
- pipeline_->setUniformValue("ove_resolution", texture_.width(), texture_.height());
- pipeline_->setUniformValue("ove_viewport", width(), height());
- GLfloat luma[3] = {0.0, 0.0, 0.0};
- color_manager()->GetDefaultLumaCoefs(luma);
- pipeline_->setUniformValue("luma_coeffs", luma[0], luma[1], luma[2]);
+ OpenGLRenderFunctions::Blit(pipeline());
- // Scale of the waveform relative to the viewport surface.
- pipeline_->setUniformValue("waveform_scale", waveform_scale);
- pipeline_->setUniformValue(
- "waveform_dims", waveform_dim_x, waveform_dim_y);
-
- pipeline_->setUniformValue(
- "waveform_region",
- waveform_start_dim_x, waveform_start_dim_y,
- waveform_end_dim_x, waveform_end_dim_y);
-
- float waveform_start_uv_x = waveform_start_dim_x / width();
- float waveform_start_uv_y = waveform_start_dim_y / height();
- float waveform_end_uv_x = waveform_end_dim_x / width();
- float waveform_end_uv_y = waveform_end_dim_y / height();
- pipeline_->setUniformValue(
- "waveform_uv",
- waveform_start_uv_x, waveform_start_uv_y,
- waveform_end_uv_x, waveform_end_uv_y);
-
- pipeline_->release();
-
- f->glViewport(0, 0, width(), height());
-
- managed_tex_.Bind();
-
- OpenGLRenderFunctions::Blit(pipeline_);
-
- managed_tex_.Release();
- }
+ managed_tex().Release();
// Draw line overlays
QPainter p(this);
@@ -179,44 +125,4 @@ void WaveformScope::paintGL()
p.drawLines(ire_lines);
}
-void WaveformScope::UploadTextureFromBuffer()
-{
- if (!isVisible()) {
- return;
- }
-
- if (buffer_) {
- makeCurrent();
-
- if (!texture_.IsCreated()
- || texture_.width() != buffer_->width()
- || texture_.height() != buffer_->height()
- || texture_.format() != buffer_->format()) {
- texture_.Destroy();
- managed_tex_.Destroy();
-
- texture_.Create(context(), buffer_);
- managed_tex_.Create(context(), buffer_->video_params());
- } else {
- texture_.Upload(buffer_);
- }
-
- doneCurrent();
- }
-
- update();
-}
-
-void WaveformScope::CleanUp()
-{
- makeCurrent();
-
- pipeline_ = nullptr;
- texture_.Destroy();
- managed_tex_.Destroy();
- framebuffer_.Destroy();
-
- doneCurrent();
-}
-
OLIVE_NAMESPACE_EXIT
diff --git a/app/widget/scope/waveform/waveform.h b/app/widget/scope/waveform/waveform.h
index 4243a9d3a..04a464e52 100644
--- a/app/widget/scope/waveform/waveform.h
+++ b/app/widget/scope/waveform/waveform.h
@@ -21,48 +21,20 @@
#ifndef WAVEFORMSCOPE_H
#define WAVEFORMSCOPE_H
-#include "codec/frame.h"
-#include "render/backend/opengl/openglcolorprocessor.h"
-#include "render/backend/opengl/openglframebuffer.h"
-#include "render/backend/opengl/openglshader.h"
-#include "render/backend/opengl/opengltexture.h"
-#include "widget/manageddisplay/manageddisplay.h"
+#include "widget/scope/scopebase/scopebase.h"
OLIVE_NAMESPACE_ENTER
-class WaveformScope : public ManagedDisplayWidget
+class WaveformScope : public ScopeBase
{
Q_OBJECT
public:
WaveformScope(QWidget* parent = nullptr);
- virtual ~WaveformScope() override;
-
-public slots:
- void SetBuffer(Frame* frame);
-
protected:
- virtual void initializeGL() override;
+ virtual OpenGLShaderPtr CreateShader() override;
- virtual void paintGL() override;
-
- virtual void showEvent(QShowEvent* e) override;
-
-private:
- void UploadTextureFromBuffer();
-
- OpenGLShaderPtr pipeline_;
-
- OpenGLTexture texture_;
-
- OpenGLTexture managed_tex_;
-
- OpenGLFramebuffer framebuffer_;
-
- Frame* buffer_;
-
-private slots:
- void CleanUp();
+ virtual void DrawScope() override;
};