User forums > General (but related to Code::Blocks)

C::B with DirectWrite enabled will crash when in Windows remote desktop

<< < (3/3)

ollydbg:
I'm just testing the stc sample from official wx 3.2.1. (by this project: codeblocks cbp projects for wx samples)

In it's menu, there is an option named "Technology", and I change the value to DirectWrite.

Now, I just close the remote desktop client, and logged again, I see the same crash happens in the stc sample application. So, the crash issue also exists in the wxStyledTextCtrl.  :(

ollydbg:
I wrote an issue in wx's github, see here:

wxStyledTextCtrl with DirectWrite enabled will crash when user logs in by Windows remote desktop  Issue #22872 wxWidgets/wxWidgets

ollydbg:
I just download the scintilla 3.21.1(I think it is the long term branch, see here: https://sourceforge.net/projects/scintilla/files/scintilla/3.21.1/ ) source code, and search the keyword: D2DERR_RECREATE_TARGET.

I got this:


--- Code: ---bool ScintillaWin::PaintDC(HDC hdc) {
if (technology == SC_TECHNOLOGY_DEFAULT) {
AutoSurface surfaceWindow(hdc, this);
if (surfaceWindow) {
Paint(surfaceWindow, rcPaint);
surfaceWindow->Release();
}
} else {
#if defined(USE_D2D)
EnsureRenderTarget(hdc);
if (pRenderTarget) {
AutoSurface surfaceWindow(pRenderTarget, this);
if (surfaceWindow) {
pRenderTarget->BeginDraw();
Paint(surfaceWindow, rcPaint);
surfaceWindow->Release();
const HRESULT hr = pRenderTarget->EndDraw();
if (hr == static_cast<HRESULT>(D2DERR_RECREATE_TARGET)) {
DropRenderTarget();
return false;
}
}
}
#endif
}

return true;
}

--- End code ---

And this is our C::B's implementation of the Technology in sdk\wxscintilla\src\ScintillaWX.cpp:


--- Code: ---#if defined(__WXMSW__) && wxUSE_GRAPHICS_DIRECT2D
        case SCI_SETTECHNOLOGY:
            if ((wParam == SC_TECHNOLOGY_DEFAULT) || (wParam == SC_TECHNOLOGY_DIRECTWRITE)) {
                if (technology != static_cast<int>(wParam)) {
                    SurfaceDataD2D* newSurfaceData(NULL);

                    if (static_cast<int>(wParam) > SC_TECHNOLOGY_DEFAULT) {
                        newSurfaceData =  new SurfaceDataD2D(this);

                        if (!newSurfaceData->Initialised()) {
                            // Failed to load Direct2D or DirectWrite so no effect
                            delete newSurfaceData;
                            return 0;
                        }
                    }

                    technology = static_cast<int>(wParam);
                    if ( m_surfaceData ) {
                        delete m_surfaceData;
                    }
                    m_surfaceData = newSurfaceData;

                    // Invalidate all cached information including layout.
                    DropGraphics(true);
                    InvalidateStyleRedraw();
                }
            }
            break;
#endif

--- End code ---

And this is the scintilla 3.21.1's SCI_SETTECHNOLOGY handling in ScintillaWin.cxx:


--- Code: --- case SCI_SETTECHNOLOGY:
if ((wParam == SC_TECHNOLOGY_DEFAULT) ||
(wParam == SC_TECHNOLOGY_DIRECTWRITERETAIN) ||
(wParam == SC_TECHNOLOGY_DIRECTWRITEDC) ||
(wParam == SC_TECHNOLOGY_DIRECTWRITE)) {
const int technologyNew = static_cast<int>(wParam);
if (technology != technologyNew) {
if (technologyNew > SC_TECHNOLOGY_DEFAULT) {
#if defined(USE_D2D)
if (!LoadD2D())
// Failed to load Direct2D or DirectWrite so no effect
return 0;
#else
return 0;
#endif
}
#if defined(USE_D2D)
DropRenderTarget();
#endif
technology = technologyNew;
// Invalidate all cached information including layout.
DropGraphics(true);
InvalidateStyleRedraw();
}
}
break;

--- End code ---

It looks like we need a function call like DropRenderTarget() in some places. But it is a bit complex for me to understand the logic.  :(

Miguel Gimenez:
As I see this problem, the Direct2D driver can nullify m_pRenderTarget (because it knows the address) whenever the target is not valid (looks like Remote Desktop tends to do this). The driver reports this situation returning D2DERR_RECREATE_TARGET when calling the driver functions, and the expected actions are:
  1- Recreate the target, probably using SurfaceDataD2D::CreateGraphicsResources()
  2- Calli the function again.

Sadly, this must be done on every call to the driver, so a lot of editing is expected.

ollydbg:

--- Quote from: Miguel Gimenez on October 16, 2022, 12:13:03 pm ---As I see this problem, the Direct2D driver can nullify m_pRenderTarget (because it knows the address) whenever the target is not valid (looks like Remote Desktop tends to do this). The driver reports this situation returning D2DERR_RECREATE_TARGET when calling the driver functions, and the expected actions are:
  1- Recreate the target, probably using SurfaceDataD2D::CreateGraphicsResources()
  2- Calli the function again.

Sadly, this must be done on every call to the driver, so a lot of editing is expected.

--- End quote ---

Hi, Miguel Gimenez, I think you are correct. To reproduce the crash, we don't need to use the remote desktop, we just need to click the "switch user", and re-log in again.

I see in the Windows native implementation of scintilla, there is a function named EnsureRenderTarget(), this function has the ability to create a Direct2D target.


--- Code: ---void ScintillaWin::EnsureRenderTarget(HDC hdc) {
if (!renderTargetValid) {
DropRenderTarget();
renderTargetValid = true;
}
if (pD2DFactory && !pRenderTarget) {
HWND hw = MainHWND();

--- End code ---

I see that this function has been called in the OnPaint event handler:


--- Code: ---bool ScintillaWin::PaintDC(HDC hdc) {
if (technology == SC_TECHNOLOGY_DEFAULT) {
AutoSurface surfaceWindow(hdc, this);
if (surfaceWindow) {
Paint(surfaceWindow, rcPaint);
surfaceWindow->Release();
}
} else {
#if defined(USE_D2D)
EnsureRenderTarget(hdc);
if (pRenderTarget) {
AutoSurface surfaceWindow(pRenderTarget, this);
if (surfaceWindow) {
pRenderTarget->BeginDraw();
Paint(surfaceWindow, rcPaint);
surfaceWindow->Release();
const HRESULT hr = pRenderTarget->EndDraw();
if (hr == static_cast<HRESULT>(D2DERR_RECREATE_TARGET)) {
DropRenderTarget();
return false;
}
}
}
#endif
}

return true;
}

--- End code ---

Navigation

[0] Message Index

[*] Previous page

Go to full version