Skip to content

Linux/GTK: SKIA forgets to unbind temporary framebuffer, resulting in unusable OpenGL state #120815

@surban

Description

@surban

Consider a call to GrGLGpu::readOrTransferPixelsFrom with renderTarget == null.

This leads to bindSurfaceFBOForPixelOps being called, which binds a temporary framebuffer to the current OpenGL context and then binds a texture to that framebuffer. After GrGLGpu::readOrTransferPixelsFrom has read the pixels the function unbindSurfaceFBOForPixelOps is called, which unbinds the texture but does not revert the framebuffer change.

Thus, the next OpenGL rendering call tries to access the temporary (and incomplete) framebuffer. Hence rendering fails and the application seems to be hung.

Adding this->bindFramebuffer(fboTarget, 0); to the end of unbindSurfaceFBOForPixelOps fixes the problem. However, I am not sure if this is the right fix for this issue or the problem is how this gets called from Rasterizer::MakeSkiaGpuImage.

Here is a stack trace showing how GrGLGpu::bindSurfaceFBOForPixelOps gets called in my case:

  * frame #0: 0x00007ffff6ac4d58 libflutter_linux_gtk.so`GrGLGpu::bindSurfaceFBOForPixelOps(this=0x00000000015e7bb0, surface=0x0000000002556160, mipLevel=0, fboTarget=36160, tempFBOTarget=kSrc_TempFBOTarget) at GrGLGpu.cpp:3085:31
    frame #1: 0x00007ffff6ac0af9 libflutter_linux_gtk.so`GrGLGpu::readOrTransferPixelsFrom(this=0x00000000015e7bb0, surface=0x0000000002556160, rect=(fLeft = 0, fTop = 0, fRight = 1200, fBottom = 720), surfaceColorType=kRGBA_8888, dstColorType=kRGBA_8888, offsetOrPtr=0x00000000031582c0, rowWidthInPixels=1200) at GrGLGpu.cpp:2304:15
    frame #2: 0x00007ffff6acabf1 libflutter_linux_gtk.so`GrGLGpu::onReadPixels(this=0x00000000015e7bb0, surface=0x0000000002556160, rect=(fLeft = 0, fTop = 0, fRight = 1200, fBottom = 720), surfaceColorType=kRGBA_8888, dstColorType=kRGBA_8888, buffer=0x00000000031582c0, rowBytes=4800) at GrGLGpu.cpp:2354:18
    frame #3: 0x00007ffff6888a1d libflutter_linux_gtk.so`GrGpu::readPixels(this=0x00000000015e7bb0, surface=0x0000000002556160, rect=(fLeft = 0, fTop = 0, fRight = 1200, fBottom = 720), surfaceColorType=kRGBA_8888, dstColorType=kRGBA_8888, buffer=0x00000000031582c0, rowBytes=4800) at GrGpu.cpp:456:18
    frame #4: 0x00007ffff6906d79 libflutter_linux_gtk.so`skgpu::v1::SurfaceContext::readPixels(this=0x00000000012a7160, dContext=0x000000000136c5f0, dst=GrPixmap @ 0x00007fffffffc870, pt=(fX = 0, fY = 0)) at SurfaceContext.cpp:255:37
    frame #5: 0x00007ffff6a881d3 libflutter_linux_gtk.so`SkImage_GpuBase::getROPixels(this=0x0000000002550df0, dContext=0x000000000136c5f0, dst=0x00007fffffffcaf0, chint=kAllow_CachingHint) const at SkImage_GpuBase.cpp:147:20
    frame #6: 0x00007ffff61ffc08 libflutter_linux_gtk.so`SkBitmapDevice::drawImageRect(this=0x00000000025b2200, image=0x0000000002550df0, src=0x0000000000000000, dst=0x00007fffffffcd78, sampling=0x00007fffffffcf68, paint=0x00007fffffffcdb0, constraint=kFast_SrcRectConstraint) at SkBitmapDevice.cpp:414:24
    frame #7: 0x00007ffff623e7d0 libflutter_linux_gtk.so`SkCanvas::onDrawImage2(this=0x00000000012b0600, image=0x0000000002550df0, x=0, y=0, sampling=0x00007fffffffcf68, paint=0x0000000000000000) at SkCanvas.cpp:2336:28
    frame #8: 0x00007ffff623ef5a libflutter_linux_gtk.so`SkCanvas::drawImage(this=0x00000000012b0600, image=0x0000000002550df0, x=0, y=0, sampling=0x00007fffffffcf68, paint=0x0000000000000000) at SkCanvas.cpp:2391:11
    frame #9: 0x00007ffff6090321 libflutter_linux_gtk.so`SkCanvas::drawImage(this=0x00000000012b0600, image=0x00007fffffffcf80, x=0, y=0, sampling=0x00007fffffffcf68, paint=0x0000000000000000) at SkCanvas.h:1488:15
    frame #10: 0x00007ffff610f9d2 libflutter_linux_gtk.so`flutter::DisplayListCanvasDispatcher::drawImage(this=0x00007fffffffd340, image=const sk_sp<flutter::DlImage> @ 0x00007fffffffcfc8, point=(fX = 0, fY = 0), sampling=kLinear, render_with_attributes=false) at display_list_canvas_dispatcher.cc:196:12
    frame #11: 0x00007ffff60d6de4 libflutter_linux_gtk.so`flutter::DrawImageOp::dispatch(this=0x00000000025a6100, ctx=0x00007fffffffd020) const at display_list_ops.h:881:1
    frame #12: 0x00007ffff60d3767 libflutter_linux_gtk.so`flutter::DisplayList::Dispatch(this=0x00007fffa0750970, dispatcher=0x00007fffffffd340, ptr="J\U00000010", end="", culler=0x00007ffff7f36220) const at display_list.cc:186:7
    frame #13: 0x00007ffff60d2fa5 libflutter_linux_gtk.so`flutter::DisplayList::Dispatch(this=0x00007fffa0750970, ctx=0x00007fffffffd340) const at display_list.cc:139:3
    frame #14: 0x00007ffff60d3dc9 libflutter_linux_gtk.so`flutter::DisplayList::RenderTo(this=0x00007fffa0750970, canvas=0x00000000012b0600, opacity=1) const at display_list.cc:315:5
    frame #15: 0x00007ffff6f9ef03 libflutter_linux_gtk.so`flutter::(anonymous namespace)::MakeBitmapImage(display_list=0x00007fffffffdab8, image_info=0x00007fffa0629a68) at rasterizer.cc:276:17
    frame #16: 0x00007ffff6f9ed0e libflutter_linux_gtk.so`flutter::Rasterizer::MakeSkiaGpuImage(this=0x00000000015d6180, display_list=sk_sp<flutter::DisplayList> @ 0x00007fffffffdab8, image_info=0x00007fffa0629a68) at rasterizer.cc:295:10
    frame #17: 0x00007ffff73ac846 libflutter_linux_gtk.so`flutter::DlDeferredImageGPUSkia::ImageWrapper::SnapshotDisplayList(this=({...}, {...}))::$_0::operator()() const at display_list_deferred_image_gpu_skia.cc:181:42
    frame #18: 0x00007ffff73ac675 libflutter_linux_gtk.so`decltype(__f=({...}, {...}))::$_0&>()()) std::_LIBCPP_ABI_NAMESPACE::__invoke[abi:v15000]<flutter::DlDeferredImageGPUSkia::ImageWrapper::SnapshotDisplayList(std::_LIBCPP_ABI_NAMESPACE::shared_ptr<flutter::LayerTree>)::$_0&>(flutter::DlDeferredImageGPUSkia::ImageWrapper::SnapshotDisplayList(std::_LIBCPP_ABI_NAMESPACE::shared_ptr<flutter::LayerTree>)::$_0&) at invoke.h:403:23
    frame #19: 0x00007ffff73ac635 libflutter_linux_gtk.so`void std::_LIBCPP_ABI_NAMESPACE::__invoke_void_return_wrapper<void, true>::__call<flutter::DlDeferredImageGPUSkia::ImageWrapper::SnapshotDisplayList(__args=({...}, {...}))::$_0&>(flutter::DlDeferredImageGPUSkia::ImageWrapper::SnapshotDisplayList(std::_LIBCPP_ABI_NAMESPACE::shared_ptr<flutter::LayerTree>)::$_0&) at invoke.h:488:9
    frame #20: 0x00007ffff73ac60d libflutter_linux_gtk.so`std::_LIBCPP_ABI_NAMESPACE::__function::__alloc_func<flutter::DlDeferredImageGPUSkia::ImageWrapper::SnapshotDisplayList(std::_LIBCPP_ABI_NAMESPACE::shared_ptr<flutter::LayerTree>)::$_0, std::_LIBCPP_ABI_NAMESPACE::allocator<flutter::DlDeferredImageGPUSkia::ImageWrapper::SnapshotDisplayList(std::_LIBCPP_ABI_NAMESPACE::shared_ptr<flutter::LayerTree>)::$_0>, void ()>::operator(this=0x00000000021478f8)[abi:v15000]() at function.h:185:16
    frame #21: 0x00007ffff73abb69 libflutter_linux_gtk.so`std::_LIBCPP_ABI_NAMESPACE::__function::__func<flutter::DlDeferredImageGPUSkia::ImageWrapper::SnapshotDisplayList(std::_LIBCPP_ABI_NAMESPACE::shared_ptr<flutter::LayerTree>)::$_0, std::_LIBCPP_ABI_NAMESPACE::allocator<flutter::DlDeferredImageGPUSkia::ImageWrapper::SnapshotDisplayList(std::_LIBCPP_ABI_NAMESPACE::shared_ptr<flutter::LayerTree>)::$_0>, void ()>::operator(this=0x00000000021478f0)() at function.h:359:12
    frame #22: 0x00007ffff5c3e022 libflutter_linux_gtk.so`std::_LIBCPP_ABI_NAMESPACE::__function::__value_func<void ()>::operator(this=0x00007fffffffdec0)[abi:v15000]() const at function.h:512:16
    frame #23: 0x00007ffff5c3dfa5 libflutter_linux_gtk.so`std::_LIBCPP_ABI_NAMESPACE::function<void ()>::operator(this=0x00007fffffffdec0)() const at function.h:1187:12
    frame #24: 0x00007ffff607f13a libflutter_linux_gtk.so`flutter::EmbedderTaskRunner::PostTask(this=0x000000000130db00, baton=877) at embedder_task_runner.cc:77:3
    frame #25: 0x00007ffff6082c72 libflutter_linux_gtk.so`flutter::EmbedderThreadHost::PostTask(this=0x0000000001417590, runner=19979008, task=877) const at embedder_thread_host.cc:295:25
    frame #26: 0x00007ffff6059e5c libflutter_linux_gtk.so`flutter::EmbedderEngine::RunTask(this=0x00000000015bf300, task=0x00007fffa06331a8) at embedder_engine.cc:245:24
    frame #27: 0x00007ffff601468c libflutter_linux_gtk.so`::FlutterEngineRunTask(engine=0x00000000015bf300, task=0x00007fffa06331a8) at embedder.cc:2562:62
    frame #28: 0x00007ffff5c0a041 libflutter_linux_gtk.so`::fl_engine_execute_task(self=0x00000000012dc010, task=0x00007fffa06331a8) at fl_engine.cc:869:3
    frame #29: 0x00007ffff5c3394b libflutter_linux_gtk.so`fl_task_runner_process_expired_tasks_locked(self=0x00000000013318a0) at fl_task_runner.cc:57:5
    frame #30: 0x00007ffff5c33b57 libflutter_linux_gtk.so`fl_task_runner_on_expired_timeout(data=0x00000000013318a0) at fl_task_runner.cc:79:3
    frame #31: 0x00007ffff26c84c8 libglib-2.0.so.0`___lldb_unnamed_symbol2503 + 40
    frame #32: 0x00007ffff26c7cbf libglib-2.0.so.0`g_main_context_dispatch + 415
    frame #33: 0x00007ffff271d598 libglib-2.0.so.0`___lldb_unnamed_symbol2790 + 776
    frame #34: 0x00007ffff26c4f40 libglib-2.0.so.0`g_main_context_iteration + 48
    frame #35: 0x00007ffff28f394d libgio-2.0.so.0`g_application_run + 477
    frame #36: 0x0000000000402561 xxx_app`main(argc=1, argv=0x00007fffffffe398) at main.cc:5:10
    frame #37: 0x00007ffff216a510 libc.so.6`__libc_start_call_main + 128
    frame #38: 0x00007ffff216a5c9 libc.so.6`__libc_start_main@@GLIBC_2.34 + 137
    frame #39: 0x0000000000402445 xxx_app`_start + 37

Tested on master branch of Flutter engine and tool. I am using a custom texture widget via fl_texture_registrar_register_texture, thus I am probably triggering a code path that has not been used otherwise.

@dnfield This seems related to #108835.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work listdependency: skiaSkia team may need to help usengineflutter/engine related. See also e: labels.platform-linuxBuilding on or for Linux specifically

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions