opengl: use shared contexts and downgrade to ES 2.0 (BIG CHANGE)
If you run into new OpenGL issues, this is likely the commit that caused it. I've tested this on as many systems as I have access to (including AMD, Apple, Intel, and NVIDIA GPUs with a mixture of Windows, Linux, and macOS) and it appears to work fine, however we all know how unpredictable GPUs can be. This should help increase GPU performance and compatibility. Squashed commit of the following: commit fa3c0ac7c469aebe2941a803736bdc06cdd5a2d8 Author: itsmattkc <itsmattkc@gmail.com> Date: Thu May 27 13:17:44 2021 +1000 viewer: updated pixel sampling for shared contexts commit 9334261da235f09cb67b193c5bb6169abd7a95f7 Author: itsmattkc <itsmattkc@gmail.com> Date: Thu May 27 13:12:39 2021 +1000 pixelsampler: show color preview box commit dacd9be6971c5c0312ae45c8db349d47910a80dd Author: itsmattkc <itsmattkc@gmail.com> Date: Thu May 27 12:43:32 2021 +1000 renderer: interlace on GPU commit 074cea06cb87e9fdc4e8ea6b09587be6df296057 Author: itsmattkc <itsmattkc@gmail.com> Date: Thu May 27 12:43:14 2021 +1000 renderer: added texture clear option commit 5d4f86b4cf1b1dcd3fb8e8c854ffa7f6fb8ca346 Author: itsmattkc <itsmattkc@gmail.com> Date: Thu May 27 12:42:12 2021 +1000 renderer: updated scopes for shared textures commit 6fad96358d189874cf45f7887b7e13cc2b1603c4 Author: itsmattkc <itsmattkc@gmail.com> Date: Thu May 27 11:42:05 2021 +1000 opengl: fixed edge case commit 1a19ffb53703ac6f30ed210f6d8eb5fc4b7b0f2d Author: itsmattkc <itsmattkc@gmail.com> Date: Thu May 27 10:56:13 2021 +1000 opengl: fix deinterlace shader commit 085961aa39cca90ebf51b919a78ef07a4882f0e1 Author: itsmattkc <itsmattkc@gmail.com> Date: Thu May 27 10:08:40 2021 +1000 opengl: downgrade to ES 2.0 With half-float/float/3D extensions, this should be doable commit ea1ab45cbcf5e017dfd0d8f28b231ff3255dfe92 Author: itsmattkc <itsmattkc@gmail.com> Date: Thu May 27 10:06:59 2021 +1000 renderer: fixed mutex deadlock commit ecc2f08b16f03421870c5b61625ecd26f2f96582 Author: itsmattkc <itsmattkc@gmail.com> Date: Wed May 26 21:28:13 2021 +1000 opengl: fixed shared contexts commit 261c689ea8089463155cf11b9ab15aa3f879f439 Merge: bfd4338a91c88b1cAuthor: itsmattkc <itsmattkc@gmail.com> Date: Wed May 26 19:52:00 2021 +1000 Merge branch 'master' into shared-contexts commit bfd4338aaa3b09b6fbb7717c637face8d5490721 Author: itsmattkc <itsmattkc@gmail.com> Date: Wed May 26 18:52:38 2021 +1000 viewer: remove debug line commit 45868d8a396181bf81c24b92a1ac5ce9ffed3426 Merge: 642f8e9dd0bd5e21Author: itsmattkc <itsmattkc@gmail.com> Date: Wed May 26 17:21:48 2021 +1000 Merge branch 'master' into shared-contexts commit 642f8e9df7d7d1a9ed4202d428f4d968ff668552 Merge: 861e5b894de0a727Author: itsmattkc <itsmattkc@gmail.com> Date: Wed May 26 17:01:38 2021 +1000 Merge branch 'master' of https://github.com/olive-editor/olive into shared-contexts commit 861e5b89a38c281897dc44b20e3587d39c4f808c Merge: 472598a7ef31c3fbAuthor: itsmattkc <itsmattkc@gmail.com> Date: Wed May 26 14:28:21 2021 +1000 Merge branch 'master' into shared-contexts commit 472598a740a095aa43a4aad5680dd5abcf453a4c Author: itsmattkc <itsmattkc@gmail.com> Date: Fri May 14 16:29:35 2021 +1000 attempt at sharing contexts
This commit is contained in:
@@ -60,10 +60,19 @@ void ColorPreviewBox::paintEvent(QPaintEvent *e)
|
||||
|
||||
QPainter p(this);
|
||||
|
||||
QRect draw_rect = rect().adjusted(0, 0, -1, -1);
|
||||
|
||||
p.setPen(Qt::black);
|
||||
|
||||
if (color_.alpha() < 1.0) {
|
||||
// Draw black background so the background isn't the window color
|
||||
p.setBrush(Qt::black);
|
||||
p.drawRect(draw_rect);
|
||||
}
|
||||
|
||||
// Draw with color over the top
|
||||
p.setBrush(c);
|
||||
|
||||
p.drawRect(rect().adjusted(0, 0, -1, -1));
|
||||
p.drawRect(draw_rect);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,7 +27,13 @@ namespace olive {
|
||||
PixelSamplerWidget::PixelSamplerWidget(QWidget *parent) :
|
||||
QGroupBox(parent)
|
||||
{
|
||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||
QHBoxLayout* layout = new QHBoxLayout(this);
|
||||
|
||||
box_ = new ColorPreviewBox();
|
||||
QFontMetrics fm = fontMetrics();
|
||||
int box_sz = fm.height() * 2;
|
||||
box_->setFixedSize(box_sz, box_sz);
|
||||
layout->addWidget(box_);
|
||||
|
||||
label_ = new QLabel();
|
||||
layout->addWidget(label_);
|
||||
@@ -45,6 +51,8 @@ void PixelSamplerWidget::SetValues(const Color &color)
|
||||
|
||||
void PixelSamplerWidget::UpdateLabelInternal()
|
||||
{
|
||||
box_->SetColor(color_);
|
||||
|
||||
label_->setText(tr("<html>"
|
||||
"<font color='#FF8080'>R: %1</font><br>"
|
||||
"<font color='#80FF80'>G: %2</font><br>"
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <QWidget>
|
||||
|
||||
#include "render/color.h"
|
||||
#include "widget/colorwheel/colorpreviewbox.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
@@ -43,6 +44,8 @@ private:
|
||||
|
||||
Color color_;
|
||||
|
||||
ColorPreviewBox *box_;
|
||||
|
||||
QLabel* label_;
|
||||
|
||||
};
|
||||
|
||||
@@ -28,23 +28,22 @@ namespace olive {
|
||||
|
||||
ScopeBase::ScopeBase(QWidget* parent) :
|
||||
super(parent),
|
||||
buffer_(nullptr)
|
||||
texture_(nullptr),
|
||||
managed_tex_up_to_date_(false)
|
||||
{
|
||||
EnableDefaultContextMenu();
|
||||
}
|
||||
|
||||
void ScopeBase::SetBuffer(Frame *frame)
|
||||
void ScopeBase::SetBuffer(TexturePtr frame)
|
||||
{
|
||||
buffer_ = frame;
|
||||
|
||||
UploadTextureFromBuffer();
|
||||
texture_ = frame;
|
||||
managed_tex_up_to_date_ = false;
|
||||
update();
|
||||
}
|
||||
|
||||
void ScopeBase::showEvent(QShowEvent* e)
|
||||
{
|
||||
super::showEvent(e);
|
||||
|
||||
UploadTextureFromBuffer();
|
||||
}
|
||||
|
||||
void ScopeBase::DrawScope(TexturePtr managed_tex, QVariant pipeline)
|
||||
@@ -58,32 +57,6 @@ void ScopeBase::DrawScope(TexturePtr managed_tex, QVariant pipeline)
|
||||
VideoParams::kInternalChannelCount));
|
||||
}
|
||||
|
||||
void ScopeBase::UploadTextureFromBuffer()
|
||||
{
|
||||
if (!isVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (buffer_) {
|
||||
makeCurrent();
|
||||
|
||||
if (!texture_ || texture_->params() != buffer_->video_params()) {
|
||||
texture_ = nullptr;
|
||||
managed_tex_ = nullptr;
|
||||
|
||||
texture_ = renderer()->CreateTexture(buffer_->video_params(),
|
||||
buffer_->data(), buffer_->linesize_pixels());
|
||||
managed_tex_ = renderer()->CreateTexture(buffer_->video_params());
|
||||
} else {
|
||||
texture_->Upload(buffer_->data(), buffer_->linesize_pixels());
|
||||
}
|
||||
|
||||
doneCurrent();
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void ScopeBase::OnInit()
|
||||
{
|
||||
super::OnInit();
|
||||
@@ -96,13 +69,13 @@ void ScopeBase::OnPaint()
|
||||
// Clear display surface
|
||||
renderer()->ClearDestination();
|
||||
|
||||
if (buffer_) {
|
||||
if (texture_) {
|
||||
// Convert reference frame to display space
|
||||
if (!texture_ || !managed_tex_) {
|
||||
UploadTextureFromBuffer();
|
||||
makeCurrent(); // UploadTextureFromBuffer calls "doneCurrent", so we re-call "makeCurrent"
|
||||
if (!managed_tex_ || !managed_tex_up_to_date_
|
||||
|| managed_tex_->params() != texture_->params()) {
|
||||
managed_tex_ = renderer()->CreateTexture(texture_->params());
|
||||
renderer()->BlitColorManaged(color_service(), texture_, true, managed_tex_.get());
|
||||
}
|
||||
renderer()->BlitColorManaged(color_service(), texture_, true, managed_tex_.get());
|
||||
|
||||
DrawScope(managed_tex_, pipeline_);
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
MANAGEDDISPLAYWIDGET_DEFAULT_DESTRUCTOR(ScopeBase)
|
||||
|
||||
public slots:
|
||||
void SetBuffer(Frame* frame);
|
||||
void SetBuffer(TexturePtr frame);
|
||||
|
||||
protected slots:
|
||||
virtual void OnInit() override;
|
||||
@@ -57,15 +57,13 @@ protected:
|
||||
virtual void DrawScope(TexturePtr managed_tex, QVariant pipeline);
|
||||
|
||||
private:
|
||||
void UploadTextureFromBuffer();
|
||||
|
||||
QVariant pipeline_;
|
||||
|
||||
TexturePtr texture_;
|
||||
|
||||
TexturePtr managed_tex_;
|
||||
|
||||
Frame* buffer_;
|
||||
bool managed_tex_up_to_date_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -56,8 +56,6 @@ ViewerWidget::ViewerWidget(QWidget *parent) :
|
||||
color_menu_enabled_(true),
|
||||
time_changed_from_timer_(false),
|
||||
prequeuing_(false),
|
||||
last_loaded_buffer_(nullptr),
|
||||
last_loaded_buffer_is_empty_(false),
|
||||
active_queue_jobs_(0),
|
||||
cache_time_(rational::NaN)
|
||||
{
|
||||
@@ -83,6 +81,7 @@ ViewerWidget::ViewerWidget(QWidget *parent) :
|
||||
connect(display_widget_, &ViewerDisplayWidget::DragEntered, this, &ViewerWidget::DragEntered);
|
||||
connect(display_widget_, &ViewerDisplayWidget::Dropped, this, &ViewerWidget::Dropped);
|
||||
connect(display_widget_, &ViewerDisplayWidget::VisibilityChanged, this, &ViewerWidget::Pause);
|
||||
connect(display_widget_, &ViewerDisplayWidget::TextureChanged, this, &ViewerWidget::TextureChanged);
|
||||
connect(sizer_, &ViewerSizer::RequestScale, display_widget_, &ViewerDisplayWidget::SetMatrixZoom);
|
||||
connect(sizer_, &ViewerSizer::RequestTranslate, display_widget_, &ViewerDisplayWidget::SetMatrixTranslate);
|
||||
connect(display_widget_, &ViewerDisplayWidget::HandDragMoved, sizer_, &ViewerSizer::HandDragMove);
|
||||
@@ -249,7 +248,7 @@ void ViewerWidget::DisconnectNodeEvent(ViewerOutput *n)
|
||||
disconnect(n->audio_playback_cache(), &AudioPlaybackCache::Validated, this, &ViewerWidget::AudioCacheValidated);
|
||||
disconnect(n, &ViewerOutput::TextureInputChanged, this, &ViewerWidget::UpdateStack);
|
||||
|
||||
SetDisplayImage(nullptr);
|
||||
SetDisplayImage(QVariant());
|
||||
|
||||
ruler()->SetPlaybackCache(nullptr);
|
||||
|
||||
@@ -351,7 +350,7 @@ void ViewerWidget::SetFullScreen(QScreen *screen)
|
||||
vw->display_widget()->SetDeinterlacing(vw->display_widget()->IsDeinterlacing());
|
||||
}
|
||||
|
||||
vw->display_widget()->SetImage(last_loaded_buffer_);
|
||||
vw->display_widget()->SetImage(QVariant::fromValue(display_widget()->GetCurrentTexture()));
|
||||
|
||||
windows_.insert(screen, vw);
|
||||
}
|
||||
@@ -420,33 +419,10 @@ bool ViewerWidget::ShouldForceWaveform() const
|
||||
|
||||
void ViewerWidget::SetEmptyImage()
|
||||
{
|
||||
FramePtr frame = nullptr;
|
||||
display_widget()->SetBlank();
|
||||
|
||||
if (GetConnectedNode()) {
|
||||
frame = last_loaded_buffer_;
|
||||
|
||||
if (!frame) {
|
||||
frame = Frame::Create();
|
||||
}
|
||||
|
||||
if (frame->video_params() != GetConnectedNode()->GetVideoParams()) {
|
||||
frame->destroy();
|
||||
frame->set_video_params(GetConnectedNode()->GetVideoParams());
|
||||
}
|
||||
|
||||
if (!frame->is_allocated()) {
|
||||
frame->allocate();
|
||||
}
|
||||
|
||||
if (!last_loaded_buffer_is_empty_) {
|
||||
memset(frame->data(), 0, frame->allocated_size());
|
||||
}
|
||||
}
|
||||
|
||||
SetDisplayImage(frame);
|
||||
|
||||
if (frame) {
|
||||
last_loaded_buffer_is_empty_ = true;
|
||||
foreach (ViewerWindow *vw, windows_) {
|
||||
vw->display_widget()->SetBlank();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -554,6 +530,7 @@ void ViewerWidget::UpdateTextureFromNode()
|
||||
} else {
|
||||
// Not playing, run a task to get the frame either from the cache or the renderer
|
||||
RenderTicketWatcher* watcher = new RenderTicketWatcher();
|
||||
watcher->setProperty("time", QVariant::fromValue(time));
|
||||
connect(watcher, &RenderTicketWatcher::Finished, this, &ViewerWidget::RendererGeneratedFrame);
|
||||
nonqueue_watchers_.append(watcher);
|
||||
watcher->SetTicket(GetFrame(time, true));
|
||||
@@ -723,7 +700,7 @@ bool ViewerWidget::ViewerMightBeAStill()
|
||||
return GetConnectedNode() && GetConnectedNode()->GetConnectedTextureOutput().IsValid() && GetConnectedNode()->GetVideoLength().isNull();
|
||||
}
|
||||
|
||||
void ViewerWidget::SetDisplayImage(FramePtr frame, bool main_only)
|
||||
void ViewerWidget::SetDisplayImage(QVariant frame, bool main_only)
|
||||
{
|
||||
display_widget_->SetImage(frame);
|
||||
|
||||
@@ -732,10 +709,6 @@ void ViewerWidget::SetDisplayImage(FramePtr frame, bool main_only)
|
||||
vw->display_widget()->SetImage(frame);
|
||||
}
|
||||
}
|
||||
|
||||
last_loaded_buffer_ = frame;
|
||||
last_loaded_buffer_is_empty_ = false;
|
||||
emit LoadedBuffer(frame.get());
|
||||
}
|
||||
|
||||
void ViewerWidget::RequestNextFrameForQueue(bool prioritize, bool increment)
|
||||
@@ -749,6 +722,7 @@ void ViewerWidget::RequestNextFrameForQueue(bool prioritize, bool increment)
|
||||
}
|
||||
|
||||
RenderTicketWatcher* watcher = new RenderTicketWatcher();
|
||||
watcher->setProperty("time", QVariant::fromValue(next_time));
|
||||
connect(watcher, &RenderTicketWatcher::Finished, this, &ViewerWidget::RendererGeneratedFrameForQueue);
|
||||
watcher->SetTicket(GetFrame(next_time, prioritize));
|
||||
active_queue_jobs_++;
|
||||
@@ -886,8 +860,6 @@ void ViewerWidget::RendererGeneratedFrame()
|
||||
RenderTicketWatcher* ticket = static_cast<RenderTicketWatcher*>(sender());
|
||||
|
||||
if (ticket->HasResult()) {
|
||||
FramePtr frame = ticket->Get().value<FramePtr>();
|
||||
|
||||
if (nonqueue_watchers_.contains(ticket)) {
|
||||
while (!nonqueue_watchers_.isEmpty()) {
|
||||
if (nonqueue_watchers_.takeFirst() == ticket) {
|
||||
@@ -895,7 +867,7 @@ void ViewerWidget::RendererGeneratedFrame()
|
||||
}
|
||||
}
|
||||
|
||||
SetDisplayImage(frame);
|
||||
SetDisplayImage(ticket->Get());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -907,14 +879,16 @@ void ViewerWidget::RendererGeneratedFrameForQueue()
|
||||
RenderTicketWatcher* watcher = static_cast<RenderTicketWatcher*>(sender());
|
||||
|
||||
if (watcher->HasResult()) {
|
||||
FramePtr frame = watcher->Get().value<FramePtr>();
|
||||
QVariant frame = watcher->Get();
|
||||
|
||||
// Ignore this signal if we've paused now
|
||||
if (IsPlaying() || prequeuing_) {
|
||||
playback_queue_.AppendTimewise({frame->timestamp(), frame}, playback_speed_);
|
||||
rational ts = watcher->property("time").value<rational>();
|
||||
|
||||
playback_queue_.AppendTimewise({ts, frame}, playback_speed_);
|
||||
|
||||
foreach (ViewerWindow* window, windows_) {
|
||||
window->queue()->AppendTimewise({frame->timestamp(), frame}, playback_speed_);
|
||||
window->queue()->AppendTimewise({ts, frame}, playback_speed_);
|
||||
}
|
||||
|
||||
if (prequeuing_ && int(playback_queue_.size()) == prequeue_length_) {
|
||||
|
||||
@@ -128,7 +128,7 @@ signals:
|
||||
/**
|
||||
* @brief Signal emitted when a new frame is loaded
|
||||
*/
|
||||
void LoadedBuffer(Frame* load_buffer);
|
||||
void TextureChanged(TexturePtr t);
|
||||
|
||||
/**
|
||||
* @brief Request a scope panel
|
||||
@@ -185,7 +185,7 @@ private:
|
||||
|
||||
bool ViewerMightBeAStill();
|
||||
|
||||
void SetDisplayImage(FramePtr frame, bool main_only = false);
|
||||
void SetDisplayImage(QVariant frame, bool main_only = false);
|
||||
|
||||
void RequestNextFrameForQueue(bool prioritize = false, bool increment = true);
|
||||
|
||||
@@ -251,9 +251,6 @@ private:
|
||||
|
||||
QTimer audio_restart_timer_;
|
||||
|
||||
FramePtr last_loaded_buffer_;
|
||||
bool last_loaded_buffer_is_empty_;
|
||||
|
||||
int active_queue_jobs_;
|
||||
|
||||
rational cache_time_;
|
||||
|
||||
@@ -45,13 +45,12 @@ ViewerDisplayWidget::ViewerDisplayWidget(QWidget *parent) :
|
||||
signal_cursor_color_(false),
|
||||
gizmos_(nullptr),
|
||||
gizmo_click_(false),
|
||||
last_loaded_buffer_(nullptr),
|
||||
hand_dragging_(false),
|
||||
deinterlace_(false),
|
||||
show_fps_(false),
|
||||
frames_skipped_(0),
|
||||
show_widget_background_(false),
|
||||
texture_equal_to_frame_(false)
|
||||
push_mode_(kPushNull)
|
||||
{
|
||||
connect(Core::instance(), &Core::ToolChanged, this, &ViewerDisplayWidget::UpdateCursor);
|
||||
|
||||
@@ -100,17 +99,26 @@ void ViewerDisplayWidget::SetSignalCursorColorEnabled(bool e)
|
||||
inner_widget()->setMouseTracking(e);
|
||||
}
|
||||
|
||||
void ViewerDisplayWidget::SetImage(FramePtr in_buffer)
|
||||
void ViewerDisplayWidget::SetImage(const QVariant &buffer)
|
||||
{
|
||||
if (last_loaded_buffer_ != in_buffer) {
|
||||
last_loaded_buffer_ = in_buffer;
|
||||
load_frame_ = buffer;
|
||||
|
||||
texture_equal_to_frame_ = false;
|
||||
if (load_frame_.isNull()) {
|
||||
push_mode_ = kPushNull;
|
||||
} else {
|
||||
push_mode_ = kPushFrame;
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void ViewerDisplayWidget::SetBlank()
|
||||
{
|
||||
push_mode_ = kPushBlank;
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void ViewerDisplayWidget::SetDeinterlacing(bool e)
|
||||
{
|
||||
deinterlace_ = e;
|
||||
@@ -318,51 +326,73 @@ void ViewerDisplayWidget::OnPaint()
|
||||
{
|
||||
// Clear background to empty
|
||||
QColor bg_color = show_widget_background_ ? palette().window().color() : Qt::black;
|
||||
renderer()->ClearDestination(bg_color.redF(), bg_color.greenF(), bg_color.blueF());
|
||||
renderer()->ClearDestination(nullptr, bg_color.redF(), bg_color.greenF(), bg_color.blueF());
|
||||
|
||||
// We only draw if we have a pipeline
|
||||
if (last_loaded_buffer_ && color_service()) {
|
||||
if (!texture_
|
||||
|| texture_->width() != last_loaded_buffer_->width()
|
||||
|| texture_->height() != last_loaded_buffer_->height()
|
||||
|| texture_->format() != last_loaded_buffer_->format()
|
||||
|| texture_->channel_count() != last_loaded_buffer_->channel_count()) {
|
||||
texture_ = renderer()->CreateTexture(last_loaded_buffer_->video_params(), last_loaded_buffer_->data(), last_loaded_buffer_->linesize_pixels());
|
||||
} else if (!texture_equal_to_frame_) {
|
||||
texture_->Upload(last_loaded_buffer_->data(), last_loaded_buffer_->linesize_pixels());
|
||||
}
|
||||
texture_equal_to_frame_ = true;
|
||||
|
||||
TexturePtr texture_to_draw = texture_;
|
||||
|
||||
if (deinterlace_) {
|
||||
if (deinterlace_shader_.isNull()) {
|
||||
deinterlace_shader_ = renderer()->CreateNativeShader(ShaderCode(FileFunctions::ReadFileAsString(QStringLiteral(":/shaders/deinterlace.frag"))));
|
||||
}
|
||||
|
||||
if (!deinterlace_texture_
|
||||
|| deinterlace_texture_->params() != texture_to_draw->params()) {
|
||||
// (Re)create texture
|
||||
deinterlace_texture_ = renderer()->CreateTexture(texture_to_draw->params());
|
||||
}
|
||||
|
||||
ShaderJob job;
|
||||
job.InsertValue(QStringLiteral("resolution_in"), NodeValue(NodeValue::kVec2, QVector2D(texture_to_draw->width(), texture_to_draw->height())));
|
||||
job.InsertValue(QStringLiteral("ove_maintex"), NodeValue(NodeValue::kTexture, QVariant::fromValue(texture_to_draw)));
|
||||
|
||||
renderer()->BlitToTexture(deinterlace_shader_, job, deinterlace_texture_.get());
|
||||
|
||||
texture_to_draw = deinterlace_texture_;
|
||||
}
|
||||
|
||||
if (push_mode_ != kPushNull) {
|
||||
// Draw texture through color transform
|
||||
int device_width = width() * devicePixelRatioF();
|
||||
int device_height = height() * devicePixelRatioF();
|
||||
VideoParams::Format device_format = static_cast<VideoParams::Format>(Config::Current()["OfflinePixelFormat"].toInt());
|
||||
VideoParams device_params(device_width, device_height, device_format, VideoParams::kInternalChannelCount);
|
||||
|
||||
renderer()->BlitColorManaged(color_service(), texture_to_draw, true, device_params, false,
|
||||
combined_matrix_flipped_, crop_matrix_);
|
||||
if (push_mode_ == kPushBlank) {
|
||||
if (blank_shader_.isNull()) {
|
||||
blank_shader_ = renderer()->CreateNativeShader(ShaderCode());
|
||||
}
|
||||
|
||||
ShaderJob job;
|
||||
job.InsertValue(QStringLiteral("ove_mvpmat"), NodeValue(NodeValue::kMatrix, combined_matrix_flipped_));
|
||||
job.InsertValue(QStringLiteral("ove_cropmatrix"), NodeValue(NodeValue::kMatrix, crop_matrix_));
|
||||
|
||||
renderer()->Blit(blank_shader_, job, device_params, false);
|
||||
} else if (color_service()) {
|
||||
if (FramePtr frame = load_frame_.value<FramePtr>()) {
|
||||
// This is a CPU frame, upload it now
|
||||
if (!texture_
|
||||
|| texture_->renderer() != renderer() // Some implementations don't like it if we upload to a texture created in another (albeit shared) context
|
||||
|| texture_->width() != frame->width()
|
||||
|| texture_->height() != frame->height()
|
||||
|| texture_->format() != frame->format()
|
||||
|| texture_->channel_count() != frame->channel_count()) {
|
||||
texture_ = renderer()->CreateTexture(frame->video_params(), frame->data(), frame->linesize_pixels());
|
||||
} else {
|
||||
texture_->Upload(frame->data(), frame->linesize_pixels());
|
||||
}
|
||||
} else if (TexturePtr texture = load_frame_.value<TexturePtr>()) {
|
||||
// This is a GPU texture, switch to it directly
|
||||
texture_ = texture;
|
||||
}
|
||||
|
||||
emit TextureChanged(texture_);
|
||||
|
||||
push_mode_ = kPushUnnecessary;
|
||||
|
||||
TexturePtr texture_to_draw = texture_;
|
||||
|
||||
if (deinterlace_) {
|
||||
if (deinterlace_shader_.isNull()) {
|
||||
deinterlace_shader_ = renderer()->CreateNativeShader(ShaderCode(FileFunctions::ReadFileAsString(QStringLiteral(":/shaders/deinterlace.frag"))));
|
||||
}
|
||||
|
||||
if (!deinterlace_texture_
|
||||
|| deinterlace_texture_->params() != texture_to_draw->params()) {
|
||||
// (Re)create texture
|
||||
deinterlace_texture_ = renderer()->CreateTexture(texture_to_draw->params());
|
||||
}
|
||||
|
||||
ShaderJob job;
|
||||
job.InsertValue(QStringLiteral("resolution_in"), NodeValue(NodeValue::kVec2, QVector2D(texture_to_draw->width(), texture_to_draw->height())));
|
||||
job.InsertValue(QStringLiteral("ove_maintex"), NodeValue(NodeValue::kTexture, QVariant::fromValue(texture_to_draw)));
|
||||
|
||||
renderer()->BlitToTexture(deinterlace_shader_, job, deinterlace_texture_.get());
|
||||
|
||||
texture_to_draw = deinterlace_texture_;
|
||||
}
|
||||
|
||||
renderer()->BlitColorManaged(color_service(), texture_to_draw, true, device_params, false,
|
||||
combined_matrix_flipped_, crop_matrix_);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw gizmos if we have any
|
||||
@@ -452,12 +482,20 @@ void ViewerDisplayWidget::OnPaint()
|
||||
|
||||
void ViewerDisplayWidget::OnDestroy()
|
||||
{
|
||||
renderer()->DestroyNativeShader(deinterlace_shader_);
|
||||
deinterlace_shader_.clear();
|
||||
renderer()->DestroyNativeShader(blank_shader_);
|
||||
blank_shader_.clear();
|
||||
|
||||
super::OnDestroy();
|
||||
|
||||
texture_ = nullptr;
|
||||
deinterlace_texture_ = nullptr;
|
||||
if (load_frame_.isNull()) {
|
||||
push_mode_ = kPushNull;
|
||||
} else {
|
||||
push_mode_ = kPushFrame;
|
||||
}
|
||||
}
|
||||
|
||||
QPointF ViewerDisplayWidget::GetTexturePosition(const QPoint &screen_pos)
|
||||
@@ -542,12 +580,11 @@ void ViewerDisplayWidget::EmitColorAtCursor(QMouseEvent *e)
|
||||
if (signal_cursor_color_) {
|
||||
Color reference, display;
|
||||
|
||||
if (last_loaded_buffer_) {
|
||||
if (texture_) {
|
||||
QPointF pixel_pos = GenerateGizmoTransform().inverted().map(e->pos());
|
||||
pixel_pos /= texture_->params().divider();
|
||||
|
||||
pixel_pos /= last_loaded_buffer_->video_params().divider();
|
||||
|
||||
reference = last_loaded_buffer_->get_pixel(qRound(pixel_pos.x()), qRound(pixel_pos.y()));
|
||||
reference = renderer()->GetPixelFromTexture(texture_.get(), pixel_pos);
|
||||
display = color_service()->ConvertColor(reference);
|
||||
}
|
||||
|
||||
|
||||
@@ -102,6 +102,11 @@ public:
|
||||
fps_timer_update_count_++;
|
||||
}
|
||||
|
||||
TexturePtr GetCurrentTexture() const
|
||||
{
|
||||
return texture_;
|
||||
}
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief Set the transformation matrix to draw with
|
||||
@@ -126,13 +131,9 @@ public slots:
|
||||
*/
|
||||
void SetSignalCursorColorEnabled(bool e);
|
||||
|
||||
/**
|
||||
* @brief Overrides the image with the load buffer of another ViewerGLWidget
|
||||
*
|
||||
* If there are multiple ViewerGLWidgets showing the same thing, this is faster than decoding the image from file
|
||||
* each time.
|
||||
*/
|
||||
void SetImage(FramePtr in_buffer);
|
||||
void SetImage(const QVariant &buffer);
|
||||
|
||||
void SetBlank();
|
||||
|
||||
/**
|
||||
* @brief Changes the pointer type if the tool is changed to the hand tool. Otherwise resets the pointer to it's
|
||||
@@ -181,6 +182,8 @@ signals:
|
||||
|
||||
void VisibilityChanged(bool visible);
|
||||
|
||||
void TextureChanged(TexturePtr texture);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Override the mouse press event for the DragStarted() signal and gizmos
|
||||
@@ -249,6 +252,11 @@ private:
|
||||
*/
|
||||
QVariant deinterlace_shader_;
|
||||
|
||||
/**
|
||||
* @brief Blank shader
|
||||
*/
|
||||
QVariant blank_shader_;
|
||||
|
||||
/**
|
||||
* @brief Translation only matrix (defaults to identity).
|
||||
*/
|
||||
@@ -283,8 +291,6 @@ private:
|
||||
|
||||
rational time_;
|
||||
|
||||
FramePtr last_loaded_buffer_;
|
||||
|
||||
/**
|
||||
* @brief Position of mouse to calculate delta from.
|
||||
*/
|
||||
@@ -304,7 +310,23 @@ private:
|
||||
|
||||
bool show_widget_background_;
|
||||
|
||||
bool texture_equal_to_frame_;
|
||||
QVariant load_frame_;
|
||||
|
||||
enum PushMode {
|
||||
/// New frame to push to internal texture
|
||||
kPushFrame,
|
||||
|
||||
/// Internal texture reference is up to date, keep showing it
|
||||
kPushUnnecessary,
|
||||
|
||||
/// Draw blank/black screen
|
||||
kPushBlank,
|
||||
|
||||
/// Draw nothing (not even a black frame)
|
||||
kPushNull,
|
||||
};
|
||||
|
||||
PushMode push_mode_;
|
||||
|
||||
private slots:
|
||||
void EmitColorAtCursor(QMouseEvent* e);
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace olive {
|
||||
|
||||
struct ViewerPlaybackFrame {
|
||||
rational timestamp;
|
||||
FramePtr frame;
|
||||
QVariant frame;
|
||||
};
|
||||
|
||||
class ViewerQueue : public std::list<ViewerPlaybackFrame> {
|
||||
|
||||
Reference in New Issue
Block a user