build/ci: green builds and tests on all three platforms

Compiler hygiene (all platforms):
- Silence warnings across the tree: missing override, -Wreorder ctor
  init, -Wshadow, -Wsign-compare, missing switch cases, unused
  functions/captures, Qt 6.11 deprecations (QMouseEvent/QDropEvent
  accessors, qAsConst, Q_FOREACH over non-shared containers,
  AA_UseHighDpiPixmaps) and the .bak/ backup tree removal.
- Fix regressions from the cleanup: missing clip decls in
  capi/timeline.cpp, plugin.cpp rename fallout, panel setFocus
  ambiguity, QGraphicsItem::pos vs event->position(), duplicate
  k_push_button case, boolean test variable.

Windows:
- Qt portability: CommandLineParser is_set/add_option, QTimeZone
  systemTimeZone (QTimeZone::LocalTime is 6.11-only), k_progress_* enum.
- Linking: stop adding oakengine to OLIVE_LIBRARIES (import lib plus
  oakengine-obj caused multiple definitions); add OAKENGINE_STATIC so
  internal consumers no longer reference __imp_* stubs.
- oakengine.ver: export olive::Renderer typeinfo so liboakgl.so can be
  dlopened (Linux), DynamicRenderer no longer dlcloses backend libraries
  (crash in RenderManager's dtor calling into unmapped memory).
- OTIO runtime: copy DLLs next to every binary on Windows instead of
  relying on PATH (0xc0000135 in gtest discovery).
- Headless GL: the runner only has GDI OpenGL 1.1, killing every render
  worker. Deploy Mesa llvmpipe as opengl32sw.dll (Qt's software-GL
  channel) with QT_OPENGL=software, and let QT_OPENGL override the
  AA_UseDesktopOpenGL default. ExportTask fails fast after 8 consecutive
  undelivered frames instead of segfaulting or grinding forever;
  FFmpegEncoder::write_frame tolerates null frames.
- Tests: GetTempPathA+PID temp dirs, GetLongPathNameA for 8.3 names,
  forward-slash normalization when comparing project filenames.

Linux:
- Install libshaderc-dev so oakvulkan compiles GLSL (Vulkan tests).
- Accept UNORM floor-or-round (63/64) in the blit ping-pong test.
- Skip MainWindow construction test on the offscreen QPA (cannot paint
  QOpenGLWidget).

Also: oak_cli_transcode gets a 300s ctest timeout, worker logs GL
context version and LoadGraph/render_frame stages, and
docs/plans/eliminate-event-bridge-issues.md (English translation).
This commit is contained in:
2026-08-04 21:34:31 +08:00
parent 5006382790
commit 712badbaa7
127 changed files with 826 additions and 8498 deletions
+1 -1
View File
@@ -37,7 +37,7 @@ void AudioWaveformCache::write_waveform(const TimeRange &range,
const AudioVisualWaveform *waveform)
{
// Write each valid range to the segments
foreach (const TimeRange &r, valid_ranges) {
for (const TimeRange &r : valid_ranges) {
if (waveform) {
waveforms_->overwrite_sums(*waveform, r.in(), r.in() - range.in(),
r.length());
+5 -4
View File
@@ -18,7 +18,11 @@ DynamicRenderer::DynamicRenderer(const QString &backend, QObject *parent)
}
// Tears down the backend in the reverse order used by Load(): release renderer
// resources, destroy the opaque backend object, then unload the shared library.
// resources, then destroy the opaque backend object. The shared library itself
// is deliberately NOT unloaded: multiple DynamicRenderer instances can wrap the
// same backend library, and one instance's dlclose can unmap code that other
// instances (or Qt) still reference, producing calls into unmapped memory.
// Backend libraries stay mapped until process exit.
DynamicRenderer::~DynamicRenderer()
{
destroy();
@@ -27,9 +31,6 @@ DynamicRenderer::~DynamicRenderer()
destroy_(handle_);
handle_ = nullptr;
}
if (library_.isLoaded()) {
library_.unload();
}
}
// Builds the private backend library path for the current platform.
+1 -1
View File
@@ -373,7 +373,7 @@ bool DiskCacheFolder::delete_least_recent()
auto hash_to_delete = disk_data_.begin();
if (disk_data_.begin() != disk_data_.end()) {
for (auto it = disk_data_.begin() + 1; it != disk_data_.end(); it++) {
for (auto it = std::next(disk_data_.begin()); it != disk_data_.end(); it++) {
if (it->access_time < hash_to_delete->access_time) {
hash_to_delete = it;
}
+3 -2
View File
@@ -558,6 +558,8 @@ void OpenGLRenderer::blit(QVariant s, AcceleratedJob &a_job,
// over/underflows if the number is large enough, but the likelihood of that is quite low.
functions_->glUniform1i(variable_location, value.to_int());
break;
default:
break;
case NodeValue::k_float:
// kFloat technically specifies a double but as above, OpenGL doesn't support those.
functions_->glUniform1f(variable_location, value.to_double());
@@ -828,7 +830,7 @@ void OpenGLRenderer::blit(QVariant s, AcceleratedJob &a_job,
vert_vbo.destroy();
vao.release();
vao.destroy();
} catch (std::bad_cast e) {
} catch (const std::bad_cast &e) {
}
}
@@ -975,7 +977,6 @@ GLuint OpenGLRenderer::compile_shader(GLenum type, const QString &code)
{
const bool is_gles = context_ && context_->isOpenGLES();
const int major = context_ ? context_->format().majorVersion() : 0;
const int minor = context_ ? context_->format().minorVersion() : 0;
const bool is_gles2 = is_gles && (major < 3);
const QString gles_preamble =
is_gles2 ? QStringLiteral("#version 100\n\n"
+3 -3
View File
@@ -191,7 +191,7 @@ void PlaybackCache::draw(QPainter *p, const Rational &start, double scale,
{
p->fillRect(rect, Qt::red);
foreach (const TimeRange &range, get_validated_ranges()) {
for (const TimeRange &range : get_validated_ranges()) {
int range_left = rect.left() + (range.in() - start).to_double() * scale;
if (range_left >= rect.right()) {
continue;
@@ -288,11 +288,11 @@ TimeRangeList PlaybackCache::get_invalidated_ranges(TimeRange intersecting) cons
invalidated.insert(intersecting);
foreach (const TimeRange &range, validated_) {
for (const TimeRange &range : validated_) {
invalidated.remove(range);
}
foreach (const TimeRange &range, passthroughs_) {
for (const TimeRange &range : passthroughs_) {
invalidated.remove(range);
}
+16 -17
View File
@@ -69,9 +69,9 @@ static int
get_ofx_av_pixel_format(const OFX::Host::ImageEffect::Image &image,
int *bytes_per_pixel)
{
const std::string &depth =
[[maybe_unused]] const std::string &depth =
image.getStringProperty(kOfxImageEffectPropPixelDepth);
const std::string &components =
[[maybe_unused]] const std::string &components =
image.getStringProperty(kOfxImageEffectPropComponents);
olive::core::PixelFormat pixel_format = olive::core::PixelFormat::invalid;
@@ -289,7 +289,7 @@ get_destination_av_pixel_format(const olive::VideoParams &params);
// 作用:读取 clip 偏好(像素深度与分量)并更新 VideoParams。
// Purpose: Apply clip preferences (depth/components) into VideoParams.
static bool
[[maybe_unused]] static bool
apply_clip_preferences_to_params(const OFX::Host::ImageEffect::ClipInstance &clip,
olive::VideoParams *params)
{
@@ -298,7 +298,7 @@ apply_clip_preferences_to_params(const OFX::Host::ImageEffect::ClipInstance &cli
}
olive::core::PixelFormat format = olive::core::PixelFormat::invalid;
const std::string &depth = clip.getPixelDepth();
[[maybe_unused]] const std::string &depth = clip.getPixelDepth();
if (depth == kOfxBitDepthByte) {
format = olive::core::PixelFormat::u8;
} else if (depth == kOfxBitDepthShort) {
@@ -310,7 +310,7 @@ apply_clip_preferences_to_params(const OFX::Host::ImageEffect::ClipInstance &cli
}
int channels = 0;
const std::string &components = clip.getComponents();
[[maybe_unused]] const std::string &components = clip.getComponents();
if (components == kOfxImageComponentRGBA) {
channels = 4;
} else if (components == kOfxImageComponentRGB) {
@@ -359,6 +359,8 @@ static const char *ofx_depth_from_pixel_format(olive::core::PixelFormat format)
return kOfxBitDepthShort;
case olive::core::PixelFormat::f16:
return kOfxBitDepthHalf;
default:
break;
case olive::core::PixelFormat::f32:
return kOfxBitDepthFloat;
case olive::core::PixelFormat::invalid:
@@ -460,7 +462,7 @@ static bool params_convertible(const olive::VideoParams &params)
// 作用:在 clip 偏好无效时,选择一个插件支持的输出格式。
// Purpose: Pick a supported output format when clip preferences are invalid.
static void
[[maybe_unused]] static void
choose_supported_output_params(const OFX::Host::ImageEffect::Instance &instance,
const OFX::Host::ImageEffect::ClipInstance &clip,
const olive::VideoParams &preferred,
@@ -522,7 +524,7 @@ convert_texture_for_params(olive::TexturePtr src,
// 作用:根据插件能力与偏好选择输入格式并执行转换。
// Purpose: Select a supported input format and convert texture for the clip.
static olive::TexturePtr
[[maybe_unused]] static olive::TexturePtr
convert_texture_for_clip(const OFX::Host::ImageEffect::Instance &instance,
const OFX::Host::ImageEffect::ClipInstance &clip,
olive::TexturePtr src,
@@ -670,7 +672,7 @@ convert_texture_for_clip(const OFX::Host::ImageEffect::Instance &instance,
// 作用:从 OFX Image 复制数据到 AVFrame(按图像属性推导格式)。
// Purpose: Copy OFX Image data into an AVFrame with inferred format.
static olive::AVFramePtr
[[maybe_unused]] static olive::AVFramePtr
create_avframe_from_ofx_image(OFX::Host::ImageEffect::Image &image)
{
void *data_ptr = image.getPointerProperty(kOfxImagePropData);
@@ -1323,10 +1325,9 @@ static void log_image_props(const char *label,
int rod[4] = { 0, 0, 0, 0 };
image->getIntPropertyN(kOfxImagePropBounds, bounds, 4);
image->getIntPropertyN(kOfxImagePropRegionOfDefinition, rod, 4);
const int row_bytes = image->getIntProperty(kOfxImagePropRowBytes);
const std::string &depth =
[[maybe_unused]] const std::string &depth =
image->getStringProperty(kOfxImageEffectPropPixelDepth);
const std::string &components =
[[maybe_unused]] const std::string &components =
image->getStringProperty(kOfxImageEffectPropComponents);
/*qWarning().noquote()
<< "OFX image props" << label
@@ -1370,7 +1371,7 @@ static void schedule_error_dialog_and_undo(const QString &message)
}
}
static olive::AVFramePtr download_texture_to_frame(const olive::TexturePtr &tex)
[[maybe_unused]] static olive::AVFramePtr download_texture_to_frame(const olive::TexturePtr &tex)
{
if (!tex || tex->is_dummy() || !tex->renderer()) {
return nullptr;
@@ -1425,7 +1426,7 @@ select_best_plugin_input_format(const OFX::Host::ImageEffect::Descriptor &desc)
bool supports_f16 = false;
for (int i = 0; i < dim; ++i) {
const std::string &depth =
[[maybe_unused]] const std::string &depth =
props.getStringProperty(kOfxImageEffectPropSupportedPixelDepths, i);
if (depth == kOfxBitDepthFloat) {
supports_f32 = true;
@@ -1541,8 +1542,8 @@ void olive::plugin::PluginRenderer::render_plugin(
if (!tex->is_dummy() && tex->renderer()) {
return true;
}
AVFramePtr frame = tex->frame();
return frame && frame->data(0);
AVFramePtr av_frame = tex->frame();
return av_frame && av_frame->data(0);
};
std::map<std::string, TexturePtr> input_textures;
std::map<std::string, OliveClipInstance *> input_clips;
@@ -1817,12 +1818,10 @@ void olive::plugin::PluginRenderer::render_plugin(
}
// Diagnostic: peek at first few pixels
void *img_data = output_image->getPointerProperty(kOfxImagePropData);
bool img_black = true;
if (img_data) {
float *f = static_cast<float *>(img_data);
for (int i = 0; i < 16; ++i) {
if (f[i] != 0.0f) {
img_black = false;
break;
}
}
+1 -1
View File
@@ -36,7 +36,7 @@ void RenderJobTracker::insert(const TimeRange &range, JobTime job_time)
void RenderJobTracker::insert(const TimeRangeList &ranges, JobTime job_time)
{
foreach (const TimeRange &r, ranges) {
for (const TimeRange &r : ranges) {
insert(r, job_time);
}
}