Skip to content

fix(camera): fix OpenGL preview rendering and frame ownership - #511

Merged
deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
add-uos:fix-372435-update-opengl-paint
Aug 3, 2026
Merged

fix(camera): fix OpenGL preview rendering and frame ownership#511
deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
add-uos:fix-372435-update-opengl-paint

Conversation

@add-uos

@add-uos add-uos commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Manage YUV frame lifetime with shared_ptr for thread-safe rendering, add core-profile shaders with legacy fallback and one-time texture setup.

使用 shared_ptr 管理 YUV 帧生命周期实现跨线程安全渲染,新增
core-profile 着色器并保留 legacy 回退,纹理参数改为初始化时一次性设置。

Log: 修复相机预览OpenGL渲染异常与YUV帧生命周期管理问题
PMS: BUG-372435
Influence: 修复预览画面渲染异常及潜在崩溃,提升OpenGL渲染稳定性与兼容性。

Summary by Sourcery

Stabilize OpenGL-based camera preview rendering by introducing safer YUV frame ownership and modern/legacy shader handling.

New Features:

  • Add modern core-profile vertex and fragment shaders with automatic fallback to legacy GLSL for broader OpenGL compatibility.

Bug Fixes:

  • Ensure YUV frame data remains valid during rendering by managing frame lifetime with shared_ptr across threads.
  • Fix camera preview rendering glitches and potential crashes caused by unsafe texture and shader usage.

Enhancements:

  • Initialize texture filtering and wrapping parameters once during OpenGL setup to avoid per-frame stalls and improve performance.
  • Introduce a vertex array object for the preview widget and clean up OpenGL resources more robustly in the destructor.
  • Simplify resize handling and remove redundant state changes and debug logging in the preview rendering path.

Chores:

  • Update SPDX copyright headers to reflect the 2023–2026 time range.

…2435)

Manage YUV frame lifetime with shared_ptr for thread-safe rendering,
add core-profile shaders with legacy fallback and one-time texture setup.

使用 shared_ptr 管理 YUV 帧生命周期实现跨线程安全渲染,新增
core-profile 着色器并保留 legacy 回退,纹理参数改为初始化时一次性设置。

Log: 修复相机预览OpenGL渲染异常与YUV帧生命周期管理问题
PMS: BUG-372435
Influence: 修复预览画面渲染异常及潜在崩溃,提升OpenGL渲染稳定性与兼容性。

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @add-uos, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@sourcery-ai

sourcery-ai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Reviewer's Guide

Refactors camera preview OpenGL rendering to use shared_ptr-managed YUV frames for safe cross-thread ownership, introduces core-profile compatible shaders with legacy fallbacks, adds VAO usage, and moves texture parameter setup to initialization for performance and stability.

Sequence diagram for shared_ptr-based YUV frame rendering pipeline

sequenceDiagram
    participant MajorImageProcessingThread
    participant PreviewOpenglWidget
    participant QtEventLoop

    MajorImageProcessingThread->>PreviewOpenglWidget: sigYUVFrame(shared_ptr<uchar[]> yuv, uint width, uint height)
    PreviewOpenglWidget->>PreviewOpenglWidget: slotShowYuv(shared_ptr<uchar[]> frame, uint width, uint height)
    PreviewOpenglWidget->>PreviewOpenglWidget: update()

    QtEventLoop->>PreviewOpenglWidget: paintGL()
    PreviewOpenglWidget->>PreviewOpenglWidget: lock(m_Rendermutex)
    PreviewOpenglWidget->>PreviewOpenglWidget: localFrame = m_yuvFrame
    PreviewOpenglWidget->>PreviewOpenglWidget: glTexSubImage2D(..., localFrame.get())
    PreviewOpenglWidget->>PreviewOpenglWidget: glDrawArrays(GL_TRIANGLE_FAN, 0, 4)
Loading

File-Level Changes

Change Details Files
Make YUV frame ownership cross-thread safe by using std::shared_ptr and adjusting signal/slot interfaces and usage.
  • Change PreviewOpenglWidget::slotShowYuv to accept std::shared_ptr<uchar[]> instead of raw uchar* and store it as m_yuvFrame under mutex protection.
  • Update paintGL to copy shared_ptr to a local variable under lock, derive raw pointer via get(), and use local width/height to drive texture uploads.
  • Change MajorImageProcessingThread::m_yuvPtr from raw buffer to std::shared_ptr<uchar[]> and allocate/reset via shared_ptr instead of new/delete.
  • Update YUV copying and ImageHorizontalMirror calls to use m_yuvPtr.get() and ensure m_frame->yuv_frame points to the shared buffer.
  • Change sigYUVFrame signal and slotShowYuv slot signatures to use std::shared_ptr<uchar[]> and update videowidget connections to use the typed signal/slot with Qt::DirectConnection.
src/src/previewopenglwidget.cpp
src/src/previewopenglwidget.h
src/src/majorimageprocessingthread.cpp
src/src/majorimageprocessingthread.h
src/src/videowidget.cpp
Introduce modern/core-profile-capable GLSL shaders with compatibility macros and legacy fallbacks, and attach them conditionally based on environment.
  • Add namespace-scope GLSL source strings for legacy and modern vertex shaders and a shared fragment shader body with compatibility macros for in/out, fragColor, and texture functions.
  • Implement makeLegacyFragmentShader and makeModernFragmentShader helpers to build fragment shader source for GLES and desktop core profiles.
  • Refactor initializeGL to create QOpenGLShaderProgram, bind attribute locations, and attempt core-profile or GLES shaders first, falling back to legacy GLSL if linking fails, logging warnings on failure.
  • Adjust fragment shader to use TEXTURE macro and FRAG_COLOR alias and to declare textureOut appropriately for both legacy and modern paths.
src/src/previewopenglwidget.cpp
Optimize OpenGL state and resource management with VAO usage, one-time texture parameter setup, cleaner clear behavior, and robust destruction.
  • Create and bind a QOpenGLVertexArrayObject (m_vao) in initializeGL around VBO setup and attribute configuration, and store it as a member.
  • Move glTexParameteri calls for filter and wrap modes to initializeGL, applying them once to Y/U/V texture IDs instead of every frame.
  • Add glClear(GL_COLOR_BUFFER_BIT
GL_DEPTH_BUFFER_BIT) at the start of paintGL and simplify resizeGL by removing redundant clear/update.
  • Bind m_vao and m_program in paintGL before drawing and use constexpr offsets for attribute buffers for clarity.
  • Ensure destructor calls makeCurrent(), destroys VAO/VBO and all textures, deletes m_program if non-null, and then calls doneCurrent().
  • Minor behavioral and maintenance updates to improve compatibility and clarity.
    • Remove DSysInfo major version check that forced RGB rendering for version >= 23, leaving only LoongArch/MIPS and Wayland conditions.
    • Update glClearColor alpha from 0.0 to 1.0 in initializeGL for consistent background opacity.
    • Extend SPDX-FileCopyrightText years to 2023 - 2026 in touched headers and source files.
    • Remove some verbose debug logging around OpenGL widget lifecycle and YUV handling to reduce log noise.
    src/src/previewopenglwidget.cpp
    src/src/majorimageprocessingthread.cpp
    src/src/previewopenglwidget.h
    src/src/majorimageprocessingthread.h

    Tips and commands

    Interacting with Sourcery

    • Trigger a new review: Comment @sourcery-ai review on the pull request.
    • Continue discussions: Reply directly to Sourcery's review comments.
    • Generate a GitHub issue from a review comment: Ask Sourcery to create an
      issue from a review comment by replying to it. You can also reply to a
      review comment with @sourcery-ai issue to create an issue from it.
    • Generate a pull request title: Write @sourcery-ai anywhere in the pull
      request title to generate a title at any time. You can also comment
      @sourcery-ai title on the pull request to (re-)generate the title at any time.
    • Generate a pull request summary: Write @sourcery-ai summary anywhere in
      the pull request body to generate a PR summary at any time exactly where you
      want it. You can also comment @sourcery-ai summary on the pull request to
      (re-)generate the summary at any time.
    • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
      request to (re-)generate the reviewer's guide at any time.
    • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
      pull request to resolve all Sourcery comments. Useful if you've already
      addressed all the comments and don't want to see them anymore.
    • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
      request to dismiss all existing Sourcery reviews. Especially useful if you
      want to start fresh with a new review - don't forget to comment
      @sourcery-ai review to trigger a new review!

    Customizing Your Experience

    Access your dashboard to:

    • Enable or disable review features such as the Sourcery-generated pull request
      summary, the reviewer's guide, and others.
    • Change the review language.
    • Add, remove or edit custom review instructions.
    • Adjust other review settings.

    Getting Help

    @deepin-ci-robot

    Copy link
    Copy Markdown

    deepin pr auto review

    ★ 总体评分:100分

    ■ 【总体评价】

    代码通过引入智能指针和优化OpenGL渲染逻辑,彻底修复了跨线程内存生命周期管理问题并提升了渲染性能。
    逻辑正确,消除了原有的悬空指针风险,且无安全漏洞,代码质量与性能均达到优秀标准。

    ■ 【详细分析】

    • 1.语法逻辑 完全正确 ✓

    majorimageprocessingthread.cpp 中将 m_yuvPtr 替换为 std::shared_ptr<uchar[]>,并使用 .reset().get() 进行管理,操作正确。previewopenglwidget.cppslotShowYuv 接收 std::shared_ptr<uchar[]> 并通过 std::move 转移所有权,配合 QMutexLocker 保证线程安全。paintGL 函数中使用局部变量拷贝 shared_ptr 和尺寸数据,确保渲染期间数据有效。OpenGL 着色器初始化逻辑增加了版本兼容处理和回退机制,语法无误。
    潜在问题:无
    建议:无

    • 2.代码质量 优秀 ✓

    代码清理了大量冗余的 qDebug 调试输出。着色器源码被重构为常量和辅助函数,消除了重复代码,提升了可维护性。纹理参数设置从 paintGL 移至 initializeGL,逻辑更加合理。信号槽连接改为类型安全的函数指针形式。
    潜在问题:无
    建议:无

    • 3.代码性能 高效 ✓

    将纹理过滤与环绕参数设置移至 initializeGL 中一次性完成,避免了 paintGL 每帧重复下发 GL 指令造成的性能损耗。paintGL 中缩小了互斥锁的持有范围,仅保护数据帧的拷贝,不阻塞整个渲染流程,有效降低了线程竞争。使用 Qt::DirectConnection 避免了信号队列开销。
    潜在问题:无
    建议:无

    • 4.代码安全 存在0个安全漏洞 ✓

    漏洞对比统计:新增漏洞 0 个,减少漏洞 0 个,持平 0 个
    本次修改通过 std::shared_ptr 彻底解决了跨线程传递原始 uchar* 指针导致的 Use-After-Free 悬空指针问题,消除了内存访问越界风险。未引入任何新的安全漏洞。

    • 建议:无

    ■ 【改进建议代码示例】

    // 代码已达到优秀标准,无需额外修复,以下为当前优秀的实现片段展示:
    void PreviewOpenglWidget::slotShowYuv(std::shared_ptr<uchar[]> frame, uint width, uint height)
    {
        if (!frame) {
            return;
        }
        {
            QMutexLocker locker(&m_Rendermutex);
            m_videoWidth = width;
            m_videoHeight = height;
            m_yuvFrame = std::move(frame);
        }
        update();
    }

    @deepin-ci-robot

    Copy link
    Copy Markdown

    [APPROVALNOTIFIER] This PR is NOT APPROVED

    This pull-request has been approved by: add-uos, lzwind

    The full list of commands accepted by this bot can be found here.

    Details Needs approval from an approver in each of these files:

    Approvers can indicate their approval by writing /approve in a comment
    Approvers can cancel approval by writing /approve cancel in a comment

    @add-uos

    add-uos commented Aug 3, 2026

    Copy link
    Copy Markdown
    Contributor Author

    /merge

    @deepin-bot
    deepin-bot Bot merged commit d1bfd20 into linuxdeepin:master Aug 3, 2026
    20 checks passed
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Labels

    None yet

    Projects

    None yet

    Development

    Successfully merging this pull request may close these issues.

    3 participants