尝试修复粉紫屏未果
This commit is contained in:
@@ -187,6 +187,9 @@ QVariant OpenGLRenderer::CreateNativeTexture(int width, int height, int depth,
|
||||
const void *data, int linesize)
|
||||
{
|
||||
GL_PREAMBLE;
|
||||
if (!EnsureContextCurrent(__FUNCTION__)) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool is_3d = depth > 1;
|
||||
|
||||
@@ -237,7 +240,10 @@ void OpenGLRenderer::AttachTextureAsDestination(const QVariant &texture)
|
||||
|
||||
void OpenGLRenderer::DetachTextureAsDestination()
|
||||
{
|
||||
functions_->glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
// QOpenGLWidget renders to a non-zero default FBO.
|
||||
const GLuint default_fbo =
|
||||
context_ ? context_->defaultFramebufferObject() : 0;
|
||||
functions_->glBindFramebuffer(GL_FRAMEBUFFER, default_fbo);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::DestroyNativeTexture(QVariant texture)
|
||||
@@ -423,6 +429,12 @@ void OpenGLRenderer::Blit(QVariant s, AcceleratedJob& a_job, Texture *destinatio
|
||||
{
|
||||
GL_PREAMBLE;
|
||||
try {
|
||||
if (!destination) {
|
||||
// Ensure we're drawing to the default framebuffer for this context.
|
||||
GLuint fbo = context_ ? context_->defaultFramebufferObject() : 0;
|
||||
functions_->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
}
|
||||
|
||||
ShaderJob &s_job=dynamic_cast<ShaderJob &>(a_job);
|
||||
ShaderJob job(s_job);
|
||||
// If this node is iterative, we'll pick up which input here
|
||||
@@ -694,6 +706,7 @@ void OpenGLRenderer::Blit(QVariant s, AcceleratedJob& a_job, Texture *destinatio
|
||||
PRINT_GL_ERRORS;
|
||||
functions_->glDrawArrays(GL_TRIANGLES, 0, blit_vertices.size() / 3);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (destination) {
|
||||
|
||||
@@ -73,6 +73,8 @@ public:
|
||||
return context_;
|
||||
}
|
||||
|
||||
bool EnsureContextCurrent(const char *caller);
|
||||
|
||||
protected:
|
||||
virtual void Blit(QVariant shader, olive::AcceleratedJob& job,
|
||||
olive::Texture *destination,
|
||||
@@ -99,8 +101,6 @@ private:
|
||||
|
||||
static GLenum GetPixelFormat(int channel_count);
|
||||
|
||||
bool EnsureContextCurrent(const char *caller);
|
||||
|
||||
void PrepareInputTexture(GLenum target, Texture::Interpolation interp);
|
||||
|
||||
void ClearDestinationInternal(double r = 0.0, double g = 0.0,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -38,15 +38,25 @@ namespace olive
|
||||
{
|
||||
namespace plugin{
|
||||
namespace detail {
|
||||
// 作用:将字节行跨度转换为像素跨度,便于纹理读写。
|
||||
// Purpose: Convert byte stride to pixel stride for texture I/O.
|
||||
int BytesToPixels(int byte_linesize, const olive::VideoParams ¶ms);
|
||||
}
|
||||
// 作用:OFX 插件渲染器,负责 CPU/GL 路径下的插件调用和纹理桥接。
|
||||
// Purpose: OFX plugin renderer that drives CPU/GL render paths and texture bridging.
|
||||
class PluginRenderer : public olive::OpenGLRenderer{
|
||||
Q_OBJECT
|
||||
public:
|
||||
PluginRenderer(QObject *parent=nullptr):OpenGLRenderer(parent){};
|
||||
virtual ~PluginRenderer() override{};
|
||||
// 作用:将目标纹理绑定为插件输出。
|
||||
// Purpose: Attach destination texture as OFX output.
|
||||
void AttachOutputTexture(olive::TexturePtr texture);
|
||||
// 作用:解除目标纹理绑定。
|
||||
// Purpose: Detach destination texture binding.
|
||||
void DetachOutputTexture();
|
||||
// 作用:执行插件渲染流程(参数配置、输入/输出、调用渲染动作)。
|
||||
// Purpose: Execute plugin render flow (params, inputs/outputs, render actions).
|
||||
void RenderPlugin(TexturePtr src, olive::plugin::PluginJob& job,
|
||||
olive::TexturePtr destination,
|
||||
olive::VideoParams destination_params,
|
||||
|
||||
@@ -530,8 +530,11 @@ void PreviewAutoCacher::TryRender()
|
||||
t->property("dry").toBool());
|
||||
video_immediate_passthroughs_[watcher].append(t);
|
||||
} else {
|
||||
qWarning() << "Failed to find copied node for SFR ticket";
|
||||
t->Finish();
|
||||
qWarning() << "Failed to find copied node for SFR ticket, requeueing";
|
||||
single_frame_render_ = t;
|
||||
if (!delayed_requeue_timer_.isActive()) {
|
||||
delayed_requeue_timer_.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -560,7 +563,11 @@ void PreviewAutoCacher::TryRender()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
qCritical() << "Failed to find node copy for video job";
|
||||
qWarning() << "Failed to find node copy for video job, retrying";
|
||||
if (!delayed_requeue_timer_.isActive()) {
|
||||
delayed_requeue_timer_.start();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (d.iterator.HasNext()) {
|
||||
@@ -598,7 +605,12 @@ void PreviewAutoCacher::TryRender()
|
||||
|
||||
RenderAudio(copy, d.context, use_range, d.cache);
|
||||
} else {
|
||||
qCritical() << "Failed to find node copy for audio job";
|
||||
qWarning() << "Failed to find node copy for audio job, retrying";
|
||||
pop = false;
|
||||
if (!delayed_requeue_timer_.isActive()) {
|
||||
delayed_requeue_timer_.start();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (pop) {
|
||||
|
||||
+31
-1
@@ -28,9 +28,18 @@ namespace olive
|
||||
|
||||
Renderer::Renderer(QObject *parent)
|
||||
: QObject(parent)
|
||||
, lifetime_(std::make_shared<RendererLifetime>())
|
||||
{
|
||||
}
|
||||
|
||||
Renderer::~Renderer()
|
||||
{
|
||||
destroyed_ = true;
|
||||
if (lifetime_) {
|
||||
lifetime_->alive = false;
|
||||
}
|
||||
}
|
||||
|
||||
TexturePtr Renderer::CreateTexture(const VideoParams ¶ms, const void *data,
|
||||
int linesize)
|
||||
{
|
||||
@@ -68,6 +77,9 @@ TexturePtr Renderer::CreateTexture(const VideoParams ¶ms, const void *data,
|
||||
|
||||
void Renderer::DestroyTexture(Texture *texture)
|
||||
{
|
||||
if (destroyed_) {
|
||||
return;
|
||||
}
|
||||
if (USE_TEXTURE_CACHE) {
|
||||
// HACK: Dirty, dirty hack. OpenGL uses "contexts" to store all of its data, and each context
|
||||
// can only be used by the thread that created it. However there are also "shared contexts"
|
||||
@@ -142,6 +154,10 @@ QVariant Renderer::GetDefaultShader()
|
||||
|
||||
void Renderer::Destroy()
|
||||
{
|
||||
destroyed_ = true;
|
||||
if (lifetime_) {
|
||||
lifetime_->alive = false;
|
||||
}
|
||||
if (!default_shader_.isNull()) {
|
||||
DestroyNativeShader(default_shader_);
|
||||
default_shader_.clear();
|
||||
@@ -169,7 +185,7 @@ TexturePtr Renderer::CreateTextureFromNativeHandle(const QVariant &v,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::make_shared<Texture>(this, v, params);
|
||||
return std::make_shared<Texture>(this, v, params, lifetime_);
|
||||
}
|
||||
|
||||
bool Renderer::GetColorContext(const ColorTransformJob &color_job,
|
||||
@@ -323,6 +339,20 @@ void Renderer::BlitColorManaged(const ColorTransformJob &color_job,
|
||||
{
|
||||
ColorContext color_ctx;
|
||||
if (!GetColorContext(color_job, &color_ctx)) {
|
||||
ShaderJob fallback_job;
|
||||
fallback_job.Insert(QStringLiteral("ove_maintex"),
|
||||
color_job.GetInputTexture());
|
||||
fallback_job.Insert(
|
||||
QStringLiteral("ove_mvpmat"),
|
||||
NodeValue(NodeValue::kMatrix, color_job.GetTransformMatrix()));
|
||||
|
||||
if (destination) {
|
||||
BlitToTexture(GetDefaultShader(), fallback_job, destination,
|
||||
color_job.IsClearDestinationEnabled());
|
||||
} else {
|
||||
Blit(GetDefaultShader(), fallback_job, params,
|
||||
color_job.IsClearDestinationEnabled());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include <QMutex>
|
||||
#include <QObject>
|
||||
#include <QVariant>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
|
||||
#include "common/define.h"
|
||||
#include "node/node.h"
|
||||
@@ -40,6 +42,7 @@ class Renderer : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
Renderer(QObject *parent = nullptr);
|
||||
virtual ~Renderer() override;
|
||||
|
||||
virtual bool Init() = 0;
|
||||
|
||||
@@ -106,6 +109,10 @@ public:
|
||||
|
||||
virtual Color GetPixelFromTexture(olive::Texture *texture,
|
||||
const QPointF &pt) = 0;
|
||||
std::shared_ptr<RendererLifetime> GetLifetime() const
|
||||
{
|
||||
return lifetime_;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void Blit(QVariant shader, olive::AcceleratedJob& job,
|
||||
@@ -122,6 +129,8 @@ protected:
|
||||
virtual void DestroyInternal() = 0;
|
||||
|
||||
private:
|
||||
std::atomic<bool> destroyed_{false};
|
||||
std::shared_ptr<RendererLifetime> lifetime_;
|
||||
struct ColorContext {
|
||||
struct LUT {
|
||||
TexturePtr texture;
|
||||
|
||||
@@ -90,7 +90,7 @@ RenderThread *RenderManager::CreateThread(Renderer *renderer)
|
||||
{
|
||||
auto t = new RenderThread(renderer, decoder_cache_, shader_cache_, this);
|
||||
render_threads_.push_back(t);
|
||||
t->start(QThread::IdlePriority);
|
||||
t->start(QThread::NormalPriority);
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
@@ -635,8 +635,56 @@ TexturePtr RenderProcessor::ProcessPluginJob(TexturePtr texture,
|
||||
plugin_renderer_->PostInit();
|
||||
}
|
||||
|
||||
NodeValueRow &values = plugin_job->GetValues();
|
||||
|
||||
auto is_usable_texture = [](const TexturePtr &tex) {
|
||||
if (!tex) {
|
||||
return false;
|
||||
}
|
||||
if (!tex->IsDummy() && tex->renderer()) {
|
||||
return true;
|
||||
}
|
||||
AVFramePtr frame = tex->frame();
|
||||
return frame && frame->data[0];
|
||||
};
|
||||
|
||||
TexturePtr src = nullptr;
|
||||
QString effect_input_id;
|
||||
if (plugin_job->node()) {
|
||||
effect_input_id = plugin_job->node()->GetEffectInputID();
|
||||
}
|
||||
if (!effect_input_id.isEmpty()) {
|
||||
if (TexturePtr effect_tex = values.value(effect_input_id).toTexture();
|
||||
is_usable_texture(effect_tex)) {
|
||||
src = effect_tex;
|
||||
}
|
||||
}
|
||||
if (!src) {
|
||||
const QString source_key =
|
||||
QString::fromUtf8(kOfxImageEffectSimpleSourceClipName);
|
||||
if (TexturePtr source_tex = values.value(source_key).toTexture();
|
||||
is_usable_texture(source_tex)) {
|
||||
src = source_tex;
|
||||
} else if (TexturePtr effect_tex =
|
||||
values.value(plugin::kTextureInput).toTexture();
|
||||
is_usable_texture(effect_tex)) {
|
||||
src = effect_tex;
|
||||
}
|
||||
}
|
||||
if (!src) {
|
||||
for (auto it = values.cbegin(); it != values.cend(); ++it) {
|
||||
if (it.value().type() == NodeValue::kTexture) {
|
||||
if (TexturePtr any_tex = it.value().toTexture();
|
||||
is_usable_texture(any_tex)) {
|
||||
src = any_tex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
plugin_renderer_->RenderPlugin(
|
||||
texture,
|
||||
src,
|
||||
*plugin_job,
|
||||
destination,
|
||||
destination->params(),
|
||||
|
||||
@@ -28,7 +28,7 @@ const Texture::Interpolation Texture::kDefaultInterpolation =
|
||||
|
||||
Texture::~Texture()
|
||||
{
|
||||
if (renderer_) {
|
||||
if (IsRendererAlive()) {
|
||||
renderer_->DestroyTexture(this);
|
||||
}
|
||||
|
||||
@@ -39,14 +39,14 @@ Texture::~Texture()
|
||||
|
||||
void Texture::Upload(void *data, int linesize)
|
||||
{
|
||||
if (renderer_) {
|
||||
if (IsRendererAlive()) {
|
||||
renderer_->UploadToTexture(this->id(), this->params(), data, linesize);
|
||||
}
|
||||
}
|
||||
|
||||
void Texture::Download(void *data, int linesize)
|
||||
{
|
||||
if (renderer_) {
|
||||
if (IsRendererAlive()) {
|
||||
renderer_->DownloadFromTexture(this->id(), this->params(), data,
|
||||
linesize);
|
||||
}
|
||||
|
||||
+15
-1
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "common/ffmpegutils.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <QVariant>
|
||||
|
||||
@@ -31,6 +32,9 @@ namespace olive
|
||||
|
||||
class AcceleratedJob;
|
||||
class Renderer;
|
||||
struct RendererLifetime {
|
||||
std::atomic<bool> alive{true};
|
||||
};
|
||||
|
||||
class Texture;
|
||||
using TexturePtr = std::shared_ptr<Texture>;
|
||||
@@ -46,6 +50,7 @@ public:
|
||||
*/
|
||||
Texture(const VideoParams ¶m)
|
||||
: renderer_(nullptr)
|
||||
, renderer_lifetime_(nullptr)
|
||||
, params_(param)
|
||||
, job_(nullptr)
|
||||
{
|
||||
@@ -62,8 +67,10 @@ public:
|
||||
* @brief Construct a real texture linked to a renderer backend
|
||||
*/
|
||||
Texture(Renderer *renderer, const QVariant &native,
|
||||
const VideoParams ¶m)
|
||||
const VideoParams ¶m,
|
||||
std::shared_ptr<RendererLifetime> lifetime = nullptr)
|
||||
: renderer_(renderer)
|
||||
, renderer_lifetime_(lifetime)
|
||||
, params_(param)
|
||||
, id_(native)
|
||||
, job_(nullptr)
|
||||
@@ -158,7 +165,14 @@ public:
|
||||
return frame_;
|
||||
}
|
||||
private:
|
||||
bool IsRendererAlive() const
|
||||
{
|
||||
return renderer_ &&
|
||||
(!renderer_lifetime_ || renderer_lifetime_->alive.load());
|
||||
}
|
||||
|
||||
Renderer *renderer_;
|
||||
std::shared_ptr<RendererLifetime> renderer_lifetime_;
|
||||
|
||||
VideoParams params_;
|
||||
|
||||
|
||||
@@ -19,10 +19,12 @@
|
||||
#ifndef VIDEOPARAMS_H
|
||||
#define VIDEOPARAMS_H
|
||||
|
||||
#include "ofxImageEffect.h"
|
||||
#include <olive/core/core.h>
|
||||
#include <QVector2D>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
#include <string>
|
||||
|
||||
namespace olive
|
||||
{
|
||||
@@ -173,7 +175,18 @@ public:
|
||||
{
|
||||
channel_count_ = c;
|
||||
}
|
||||
|
||||
void set_channel_count(std::string ofxComponent)
|
||||
{
|
||||
if (ofxComponent == kOfxImageComponentAlpha){
|
||||
channel_count_ = 1;
|
||||
}
|
||||
else if (ofxComponent == kOfxImageComponentRGB){
|
||||
channel_count_ = kRGBChannelCount;
|
||||
}
|
||||
else if(ofxComponent == kOfxImageComponentRGBA){
|
||||
channel_count_ = kRGBAChannelCount;
|
||||
}
|
||||
}
|
||||
const rational &pixel_aspect_ratio() const
|
||||
{
|
||||
return pixel_aspect_ratio_;
|
||||
|
||||
Reference in New Issue
Block a user