Menu

#2138 Win32: Crash with D2D surface and (Intel) Graphic Driver installation

Bug
closed-fixed
nobody
5
2020-03-03
2019-11-17
mberchtold
No

When the Intel Graphics Driver (tested with 26.20.100.7463 but also happened with previous versions) is installed (not upgraded), Scintilla crashes.

Stack trace:

[Inline Frame] Scintilla.dll!Scintilla::SurfaceD2D::FlushDrawing() Line 1151 C++
Scintilla.dll!Scintilla::SurfaceD2D::FillRectangle(Scintilla::PRectangle rc, Scintilla::Surface & surfacePattern) Line 1338 C++
Scintilla.dll!Scintilla::MarginView::PaintMargin(Scintilla::Surface * surface, int64 topLine, Scintilla::PRectangle rc, Scintilla::PRectangle rcMargin, const Scintilla::EditModel & model, const Scintilla::ViewStyle & vs) Line 205 C++
Scintilla.dll!Scintilla::Editor::PaintSelMargin(Scintilla::Surface * surfaceWindow, const Scintilla::PRectangle & rc) Line 1699 C++

Scintilla.dll!Scintilla::Editor::Paint(Scintilla::Surface * surfaceWindow, Scintilla::PRectangle rcArea) Line 1760 C++
Scintilla.dll!ScintillaWin::FullPaintDC(HDC hdc) Line 3210 C++
Scintilla.dll!ScintillaWin::WndProc(unsigned int iMessage, unsigned int64 wParam, int64 lParam) Line 1487 C++
Scintilla.dll!ScintillaWin::SWndProc(HWND hWnd, unsigned int iMessage, unsigned int64 wParam, int64 lParam) Line 3689 C++

The first assert happens here:
Editor::Paint
...
PLATFORM_ASSERT(marginView.pixmapSelPattern->Initialised());

then the actual crash happens in
SurfaceD2D::FlushDrawing because pRenderTarget is nullptr

Steps to reproduce it:
- First install the Intel Graphics Driver (in Program and Features)
- Restart the system
- Start the application which uses Scintilla (with D2D)
- Install the latest Intel Graphics Driver
- Application crashes

OS: Windows 10 x64
Scintilla: 4.2.1

Discussion

  • Neil Hodgson

    Neil Hodgson - 2019-11-17

    I do not have a system with Intel Graphics to check this on. It seems that a render target for the window was created and used OK, but it failed to create a bitmap render target for the margin texture. If possible, attach a debugger or add some logging to SurfaceD2D::InitPixMap to find just what happened there - the HRESULT may indicate the problem.

    The compiler / library used to build Scintilla may be significant with a MinGW-w64 workaround in this code. Trying some of the variant D2D modes (SC_TECHNOLOGY_DIRECTWRITEDC or SC_TECHNOLOGY_DIRECTWRITERETAIN) may produce different results.

    The crash could be avoided by testing for validity but that would mean incorrect drawing. Alternatively, an earlier assertion could help uncover problems.

     
  • mberchtold

    mberchtold - 2019-11-18

    It is not Intel graphics driver specific, it happens whenever the rendertargets are destroyed/invalidated. E.g. this is also the case when you install a graphic driver from another vendor.

    Is it possible that psurfOther->pRenderTarget in SurfaceD2D::InitPixMap is the destroyed/invalid rendertarget? In this case the CreateCompatibleRenderTarget calls probably returns D2DERR_RECREATE_TARGET.

    const HRESULT hr = psurfOther->pRenderTarget->CreateCompatibleRenderTarget(
    &desiredSize, nullptr, &desiredFormat, D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &pCompatibleRenderTarget);
    if (SUCCEEDED(hr)) {

    In this case SurfaceD2D::InitPixMap may need to recreate the window render target:
    psurfOther->Init(wid);

    I also believe the application should early abort if the result of CreateCompatibleRenderTarget is not successful. Right now, errors are just ignored.

    Unfortunately debugging is not straight forward, as it also crashed the attached debugger (Visual Studio).

     
  • mberchtold

    mberchtold - 2019-11-18

    I was further debugging it and the hr returned from psurfOther->pRenderTarget->CreateCompatibleRenderTarget is D2DERR_RECREATE_TARGET (0x8899000C).
    desiredFormat.format is 87 (DXGI_FORMAT_B8G8R8A8_UNORM)

    The SurfaceD2D::InitPixMap has to somehow tell the ScintillaWin to recreate/invalidate the render target (DropRenderTarget) in ScintillaWin.
    But since this is not possible right now, my workaround is to abandon the paint when the margin render target is valid. See attached patch.
    + //PLATFORM_ASSERT(marginView.pixmapSelPattern->Initialised());
    + // happens when the SurfaceD2D is used and marginView.RefreshPixMaps fails with D2DERR_RECREATE_TARGET
    + if (!marginView.pixmapSelPattern->Initialised()) {
    + // abandon paint
    + return;
    + }
    +

     
  • Neil Hodgson

    Neil Hodgson - 2019-11-18

    The lifetime of ScintillaWin::pRenderTarget should not allow calling into painting if it is destroyed or invalid. It seems to be working sufficiently to return DXGI_FORMAT_B8G8R8A8_UNORM from GetPixelFormat.

    To trace this to its source, it may be worthwhile adding a check for pRenderTarget validity just before calling Paint from FullPaintDC. Since we know that CreateCompatibleRenderTarget can fail, try adding a CreateCompatibleRenderTarget call.

    Turning on Direct2D debugging shows some interesting information. Replace the current D2D creation call with:

    if (fnD2DCF) {
        D2D1_FACTORY_OPTIONS opts;
        opts.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
        // A single threaded factory as Scintilla always draw on the GUI thread
        fnD2DCF(D2D1_FACTORY_TYPE_SINGLE_THREADED,
            __uuidof(ID2D1Factory),
            &opts,
            reinterpret_cast<IUnknown**>(&pD2DFactory));
    }
    

    With debugging, resize the window and a break occurs in SurfaceD2D::Clear saying that it calls Release when EndDraw hasn't been called. Changing the ownRenderTarget branch fixes that. EndDraw should probably be called at the end of RefreshPixMaps but there isn't a Surface API for that although something could be done with FlushCachedState.

            if (ownRenderTarget) {
                HRESULT hr = pRenderTarget->EndDraw();
                PLATFORM_ASSERT(hr == S_OK);
                pRenderTarget->Release();
                ownRenderTarget = false;
            }
    
     
  • Neil Hodgson

    Neil Hodgson - 2020-02-14
    • labels: --> scintilla, win32, direct2d
    • status: open --> open-fixed
     
  • Neil Hodgson

    Neil Hodgson - 2020-02-14

    Committed return from Paint when pixmapSelPattern null with [0ffb5a].

     

    Related

    Commit: [0ffb5a]

  • Neil Hodgson

    Neil Hodgson - 2020-03-03
    • status: open-fixed --> closed-fixed
     
  • Neil Hodgson

    Neil Hodgson - 2020-03-03

    Committed return from Paint when pixmapSelPattern null with [0ffb5a].

     

    Related

    Commit: [0ffb5a]


Log in to post a comment.