User forums > General (but related to Code::Blocks)
C::B with DirectWrite enabled will crash when in Windows remote desktop
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