Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/rendering/PAGDecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@

namespace pag {

static std::mutex renderLocker = {};

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

建议从根本上解决而非打补丁规避。真正的根因在于渲染引擎(tgfx)层:多个 PAGDecoder 各自 GLDevice::Make(sharedContext) 创建的 EGLContext 共享同一命名空间,缺乏对并发 GL 访问的保护,低端驱动才会错乱。

在 PAGDecoder 层加一把全局锁只是把并发压平为串行来规避问题,存在两个固有缺陷:

  1. 进程内所有 decoder 的首帧渲染被完全串行化,即使分属不相干的 context/业务,多视图首屏耗时线性叠加;
  2. 无法覆盖其他同样使用 GLDevice::Make(currentContext) 的并发 GL 路径(如 StillImage 等),本 PR 也未保护 reader 销毁(reader = nullptr)时的 GL 对象释放——它在锁作用域之外,仍与其他 decoder 的 renderFrame 并发。

根治方向:在 tgfx GLDevice 层对共享命名空间的并发访问做 per-context 锁 + makeCurrent 纪律,从渲染引擎层根除,让所有上层调用方自动受益,而非在每个调用点各自打补丁。


static std::string DefaultCacheKeyGeneratorFunc(PAGDecoder* decoder,
std::shared_ptr<PAGComposition> composition) {
if (!composition->isPAGFile() || pag::ContentVersion::Get(composition) > 0) {
Expand Down Expand Up @@ -196,6 +198,7 @@ bool PAGDecoder::readFrameInternal(int index, std::shared_ptr<BitmapBuffer> bitm
}
auto success = sequenceFile->readFrame(index, bitmap);
if (!success) {
std::lock_guard<std::mutex> autoLock(renderLocker);
success = renderFrame(composition, index, bitmap);
if (success) {
success = sequenceFile->writeFrame(index, bitmap);
Expand Down
Loading