Skip to content

WIP: 录屏重构 - #1234

Draft
glyvut wants to merge 1 commit into
linuxdeepin:masterfrom
glyvut:refactor/rec
Draft

WIP: 录屏重构#1234
glyvut wants to merge 1 commit into
linuxdeepin:masterfrom
glyvut:refactor/rec

Conversation

@glyvut

@glyvut glyvut commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Summary by Sourcery

Refactor the foreign toplevel image capture pipeline to capture from the QQuick window wrapper via an offscreen buffer renderer, improving robustness, size/format constraints handling, and integration with the output render window.

New Features:

  • Support capturing the full window content (including decorations) using the QQuickItem surface wrapper as the capture source.
  • Add an offscreen rendering path that renders the window content into a dedicated buffer via WBufferRenderer for image capture.

Bug Fixes:

  • Fix device-pixel-ratio handling in image capture to avoid double-scaling content, especially at fractional scales.
  • Prevent buffer lifecycle issues by explicitly locking/unlocking rendered buffers and avoiding use-after-free during capture and copy operations.
  • Ensure frame events and damage are emitted based on the actual rendered buffer size, avoiding invalid or zero-sized damage regions.
  • Handle buffer size mismatches more safely by updating capture constraints and failing copy requests when client buffers do not match the rendered size.

Enhancements:

  • Replace the WSurfaceItemContent-based capture path with a wrapper-based approach that better matches the window model and avoids traversing the full scene graph.
  • Introduce a two-phase capture flow (afterRendering offscreen render, renderEnd frame emission) for clearer separation of rendering and protocol events.
  • Add helper API on WOutputRenderWindow (renderItemToBuffer) to render items into an offscreen buffer while keeping renderer management consistent.
  • Improve logging and validation around capture start/stop, buffer availability, and constraint updates for easier debugging.

@deepin-ci-robot

Copy link
Copy Markdown

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: glyvut

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

@sourcery-ai

sourcery-ai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Reviewer's Guide

Refactors the foreign toplevel screen capture path to capture from the QQuickItem-based window wrapper using an offscreen WBufferRenderer pipeline, introduces coordinated afterRendering/renderEnd handling, and adds a helper on WOutputRenderWindow to render items into a wlroots-compatible buffer while tightening buffer/constraint management.

Sequence diagram for the offscreen capture pipeline using WBufferRenderer

sequenceDiagram
    actor Client
    participant Helper
    participant SurfaceWrapper as QQuickItem_SurfaceWrapper
    participant Capture as WExtImageCaptureSourceV1Impl
    participant Window as WOutputRenderWindow
    participant Renderer as WBufferRenderer
    participant Proxy as WQuickTextureProxy
    participant Buffer as qw_buffer

    Client->>Helper: handleNewForeignToplevelCaptureRequest(request)
    Helper->>SurfaceWrapper: ownsOutput()
    Helper->>Capture: new WExtImageCaptureSourceV1Impl(surfaceWrapper, output)

    Client->>Capture: start(with_cursors)
    Capture->>Window: renderWindow()
    Capture->>Renderer: new WBufferRenderer(Window->contentItem())
    Capture->>Proxy: new WQuickTextureProxy(Renderer)
    Capture->>Proxy: setSourceItem(surfaceWrapper)
    Capture->>Renderer: setSourceList({Proxy}, false)
    Capture->>Window: connect(afterRendering, doOffscreenRender)
    Capture->>Window: connect(renderEnd, handleRenderEnd)
    Capture->>Window: wlr_output_update_needs_frame(nativeHandle)

    Window-->>Capture: afterRendering
    Capture->>Capture: computePixelSize()
    Capture->>Proxy: setWidth/Height(boundingRect)
    Capture->>Window: renderItemToBuffer(Renderer, renderMatrices, pixelSize, dpr, DRM_FORMAT_ARGB8888)
    Window->>Renderer: beginRender(pixelSize, dpr, format, flags)
    Window->>Renderer: render(i, renderMatrix, {}, {}, incremental)
    Window->>Renderer: endRender()
    Window-->>Capture: lastBuffer()
    Capture->>Buffer: lock()

    Window-->>Capture: renderEnd
    Capture->>Capture: handleRenderEnd()
    Capture->>Buffer: handle() // wlr_buffer
    Capture->>Capture: WPixmanRegion fullDamage
    Capture->>Capture: wl_signal_emit_mutable(&handle()->events.frame, &event)

    Client->>Capture: copy_frame(dst_frame, frame_event)
    Capture->>Renderer: m_output->renderer()
    Capture->>Buffer: handle() // src
    alt size mismatch
        Capture->>Capture: updateConstraints(QSize(src->width, src->height))
        Capture->>dst_frame: fail(BUFFER_CONSTRAINTS)
    else size ok
        Capture->>dst_frame: qw_ext_image_copy_capture_frame_v1::copy_buffer(dst_frame, src, renderer->handle())
        Capture->>dst_frame: ready(WL_OUTPUT_TRANSFORM_NORMAL, &now)
    end
    Capture->>Buffer: unlock()

    Client->>Capture: stop()
    Capture->>Window: disconnect(afterRendering)
    Capture->>Window: disconnect(renderEnd)
    Capture->>Buffer: unlock()
Loading

File-Level Changes

Change Details Files
Refactor WExtImageCaptureSourceV1Impl to capture via QQuickItem-based SurfaceWrapper using offscreen WBufferRenderer instead of WSurfaceItemContent/qwBuffer path.
  • Constructor now takes QQuickItem *surfaceWrapper and derives initial constraints from its boundingRect scaled by device pixel ratio.
  • Replaces m_surfaceContent with m_surfaceWrapper and introduces helper methods renderWindow(), computeDpr(), computePixelSize(), and updateConstraints().
  • Adds WBufferRenderer-based offscreen rendering in doOffscreenRender, including WQuickTextureProxy wiring, buffer locking/unlocking, and size/damage handling.
  • Changes start/stop/schedule_frame to use QQuickWindow::afterRendering and WOutputRenderWindow::renderEnd, requesting frames via wlr_output_update_needs_frame.
  • Updates copy_frame to copy from the offscreen-rendered buffer, with improved size mismatch handling via updateConstraints and simplified error paths.
  • Cleans up resources correctly in destructor, including stopping capture, deleting WBufferRenderer and proxy, and managing QPointers/QMetaObject::Connections.
waylib/src/server/utils/wextimagecapturesourcev1impl.cpp
waylib/src/server/utils/wextimagecapturesourcev1impl.h
Add WOutputRenderWindow::renderItemToBuffer helper to render items into an offscreen buffer via WBufferRenderer.
  • Implements renderItemToBuffer to beginRender with specific pixelSize, dpr, and format while using DontConfigureSwapchain and RedirectOpenGLContextDefaultFrameBufferObject flags.
  • Pushes the renderer onto rendererList for each renderMatrix, calls renderer->render, then endRender and pops all pushed entries to keep rendererList consistent.
  • Returns renderer->lastBuffer() (qw_buffer*) as the rendered result or nullptr on failure.
waylib/src/server/qtquick/woutputrenderwindow.cpp
waylib/src/server/qtquick/woutputrenderwindow.h
Update foreign toplevel capture helper to construct capture source from SurfaceWrapper directly instead of internal WSurfaceItemContent.
  • Removes lookup of WSurfaceItem, WSurfaceItemContent, and related logging from handleNewForeignToplevelCaptureRequest.
  • Instantiates WExtImageCaptureSourceV1Impl with the SurfaceWrapper QQuickItem and its WOutput, aligning with the new capture implementation.
src/seat/helper.cpp

Possibly linked issues

  • #(unknown): PR rewrites WExtImageCaptureSourceV1Impl start/copy_frame logic that appears in the crash backtrace, addressing stability.
  • #: PR rewrites capture to use offscreen WBufferRenderer and texture proxy, directly addressing crashes during recording window moves.

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-bot

deepin-bot Bot commented Aug 14, 2026

Copy link
Copy Markdown

TAG Bot

New tag: 0.8.18
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1286

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.

2 participants