尝试修复粉紫屏未果

This commit is contained in:
2026-01-16 21:11:24 +08:00
parent 3f774dfa53
commit e851653fa3
30 changed files with 1377 additions and 238 deletions
+14 -1
View File
@@ -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) {
+2 -2
View File
@@ -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
+10
View File
@@ -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 &params);
}
// 作用: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,
+16 -4
View File
@@ -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
View File
@@ -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 &params, const void *data,
int linesize)
{
@@ -68,6 +77,9 @@ TexturePtr Renderer::CreateTexture(const VideoParams &params, 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;
}
+9
View File
@@ -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;
+1 -1
View File
@@ -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;
}
+49 -1
View File
@@ -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(),
+3 -3
View File
@@ -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
View File
@@ -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 &param)
: 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 &param)
const VideoParams &param,
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_;
+14 -1
View File
@@ -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_;