Skip to content

Fix browser source tearing with hardware acceleration - #531

Open
hubert-blasttv wants to merge 1 commit into
obsproject:masterfrom
blastorg:fix/source_tearing
Open

hubert-blasttv wants to merge 1 commit into
obsproject:masterfrom
blastorg:fix/source_tearing

Conversation

@hubert-blasttv

@hubert-blasttv hubert-blasttv commented Aug 4, 2026 •

Copy link
Copy Markdown

Description

Since the CEF M124 OSR rework, OnAcceleratedPaint hands out a texture from a small internal pool, with no keyed mutex. The handle "cannot be cached and cannot be accessed outside of this callback" and the contents "should be copied to a texture owned by the client application". "Resources will be released to the underlying pool for reuse when the callback returns" and that the texture "is instantiated without a keyed mutex".

The current implementation does the opposite: open the handle, keep the resource as bs->texture, and let the render thread sample it during composition at some later point. When the compositor falls behind under CPU load, CEF is already writing a later frame into that same pooled texture while we sample it, which shows up as the one-frame swaps and tears from the issue.

Fix

CopyAcceleratedTexture() now copies the frame into a texture we own, inside the callback, while the handle is guaranteed valid. The copy target is reused across frames and only reallocated when the size or format changes. gs_flush() submits the copy before the callback returns, since the pooled texture can be reused after that. The render thread then samples our private, stable copy.

The gs_texture_acquire_sync(shared, 1, 50) is a no-op right now but it cooperates, with a bounded wait, if a future producer exposes a keyed mutex.

One note: the flush submits the copy but cannot fence it, because CEF exposes no fence through this API. This is as close to the documented contract as a consumer can get. The exposure window shrinks from a full compositor frame of sampling to command submission granularity, and the pool depth gives the copy several frame intervals of slack in practice.

Motivation and Context

Recurrence of #488

How Has This Been Tested?

Retested multiple times against example from #488, and with python script to detect tear artifacts.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)

Checklist:

  • I have read the contributing document.
  • My code has been run through clang-format.
  • My code follows the project's style guidelines
  • My code is not on the master branch.
  • My code has been tested.
  • All commit messages are properly formatted and commits squashed where appropriate.
  • I have included updates to all appropriate documentation.

@Dan-Shields

Copy link
Copy Markdown

I have independently tested the patch and this solves our issue!

@Warchamp7
Warchamp7 requested review from WizardCM and notr1ch August 4, 2026 14:00
TheB1gG pushed a commit to TheB1gG/obs-studio that referenced this pull request Aug 29, 2026
…ation

Cherry-pick of obsproject/obs-browser#531 (839d3e9) by Hubert Walczak. CopyAcceleratedTexture() now copies CEF's pooled texture into an OBS-owned texture inside OnAcceleratedPaint instead of sampling the pooled handle later (obsproject#488).
TheB1gG pushed a commit to TheB1gG/obs-browser that referenced this pull request Sep 1, 2026
Fix browser source tearing with hardware acceleration (obsproject#531)
@github-project-automation github-project-automation Bot moved this to Ready For Review in 33.1 Release Tracker Sep 20, 2026
@Dan-Shields

Dan-Shields commented Sep 24, 2026 •

Copy link
Copy Markdown

I've confirmed that this patch builds and works as intended with the CEF 150 update (obs-studio/#13900)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Ready For Review

Development

Successfully merging this pull request may close these issues.

3 participants