You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Canvas绑定Framebuffer的TextureSurface无渲染输出问题

Android后台线程Skia离屏绘制全黑问题解决思路

问题核心

你已经完成后台线程的EGL初始化、PBuffer创建、FBO与纹理绑定,GLES指令可正常更新纹理,但通过SurfaceTexture创建的RecordingCanvas绘制后输出全黑——本质是Skia绘制指令未正确提交到后台GPU上下文,且原生RecordingCanvas未关联到你初始化的独立EGL环境。


具体解决步骤

1. 绑定Skia GrContext到后台EGL上下文

初始化EGL并激活后台上下文后,必须显式创建与当前EGL环境绑定的GrContext,不能使用默认上下文:

// 已完成EGL初始化、PBuffer surface创建与上下文激活
val grContext = GrContext.makeGL().apply {
    resetContext() // 强制关联当前活跃的EGL上下文
}

2. 用Skia Surface替代原生RecordingCanvas

原生RecordingCanvas会默认关联主线程GPU上下文,必须改用Skia自身的Surface创建Canvas,确保绘制指令提交到后台EGL环境:

// 假设已获取绑定到FBO的textureId、目标宽高
val backendTexture = BackendTexture.makeGL(
    textureId,
    width,
    height,
    GrMipmapped.kNo
)
val skSurface = Surface.makeFromBackendTexture(
    grContext,
    backendTexture,
    SurfaceOrigin.kTopLeft_GrSurfaceOrigin,
    1,
    ColorType.kRGBA_8888_GrColorType,
    ColorSpace.getSRGB(),
    SurfaceProps()
)

// 获取Skia Canvas执行绘制
val canvas = skSurface.canvas
canvas.drawColor(Color.WHITE) // 示例绘制

// 强制提交绘制指令到GPU
skSurface.flushAndSubmit()

3. 同步EGL上下文确保绘制完成

Skia flush后,需触发EGL层面的同步,保证GPU完成绘制:

// 针对PBuffer surface,调用eglSwapBuffers或glFinish
EGL14.eglSwapBuffers(eglDisplay, eglSurface)
GLES20.glFinish()

4. 正确更新SurfaceTexture

完成绘制同步后,在后台线程内调用SurfaceTexture.updateTexImage(),确保纹理数据被正确读取:

surfaceTexture.updateTexImage()

避坑提示

  • 后台EGL上下文必须完全独立,禁止与主线程EGL上下文共享,否则会导致上下文冲突。
  • 禁止混用Android原生Canvas与Skia Canvas,前者会自动切换到主线程GPU上下文,导致绘制指令丢失。
  • 绘制完成后需及时释放GrContext与SkSurface,避免GPU资源泄漏。

内容的提问来源于stack exchange,提问作者Thomas Cuthill

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 19:03:13