Discussion:
Direct2D Black Screen
Florian Balmer
2013-04-23 18:11:44 UTC
Permalink
Dear Scintilla Community

The issue described below has been reproduced with Scintilla 3.2.3 through
3.3.1.

There have been reports about the latest beta versions of Notepad2 showing
a black rectangle instead of the normal text, in certain siutations. The
problem only appears on Windows Vista and above with Direct2D enabled (can
be disabled in the Notepad2.ini file). The most reliable way to reproduce
the issue is to lock Windows (Windows Key+L) while Notepad2 is in the
foreground, then the black rectangle appears right after logging on. It can
also be triggered through an UAC prompt, sometimes.

I've tracked down the issue to ScintillaWin::WndPaint(), where Scintilla
discards the allocated Direct2D objects in response to the
D2DERR_RECREATE_TARGET error. If FullPaint() is called after this error,
the black rectangle won't appear.

I'm not familiar with Direct2D at all, but somehow this makes sense to me.
The MSDN tutorial [1] does not explicitly mention that (see section "The
Direct2D Render Loop"), but maybe implicitly in step 3 by saying "Repeat
step 2 whenever you need to update or redraw the scene". The question is:
is there a need to redraw if the render target has been lost, or not?

[1]
http://msdn.microsoft.com/en-us/library/windows/desktop/ff684174(v=vs.85).aspx

The problem does not appear with SciTE, but I suspect this is due to some
housekeeping (such as showing/hiding the selection upon a focus change)
causing a full repaint if the SciTE window is reactivated after logon.

Also, with Direct2D, the caret does not appear when setting the focus to
Scintilla, if there's no text (empty document), unless some keyboard or
mouse input has arrived to Scintilla. Forcing the full repaint as outlined
above partially fixes this issue (but not for the initial display of the
caret in a newly opened Notepad2 window with an empty document), that's why
I think this may be a somehow related issue. Again, no problem here in
SciTE, but maybe some action being taken on WM_ACTIVATE or WM_ACTIVATEAPP
causes a full repaint, and reinitialization of the caret.

Has anybody experienced similar problems with Direct2D turning Scintilla
into a black rectangle? Is my suggested fix reasonable, or did I miss the
point about Direct2D completely? Has anybody else noted the behaviour with
the caret, and found out if it's also linked to Direct2D?

--Florian
--
You received this message because you are subscribed to the Google Groups "scintilla-interest" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scintilla-interest+***@googlegroups.com.
To post to this group, send email to scintilla-***@googlegroups.com.
Visit this group at http://groups.google.com/group/scintilla-interest?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
Sven Strickroth
2013-04-23 19:18:43 UTC
Permalink
Hi,
Post by Florian Balmer
Has anybody experienced similar problems with Direct2D turning Scintilla
into a black rectangle? Is my suggested fix reasonable, or did I miss
the point about Direct2D completely? Has anybody else noted the
behaviour with the caret, and found out if it's also linked to Direct2D?
we use Scintilla in TortoiseGit. In some previous versions we had
enabled Direct2D and experienced several issues:

* Background blinks/flashes black/white
* Redraw issues in mstsc Remote Desktop session
* Text cursor is often invisible
* Random crashes

See: http://sourceforge.net/p/scintilla/bugs/1398/
--
Best regards,
Sven Strickroth
PGP key id F5A9D4C4 @ any key-server
--
You received this message because you are subscribed to the Google Groups "scintilla-interest" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scintilla-interest+***@googlegroups.com.
To post to this group, send email to scintilla-***@googlegroups.com.
Visit this group at http://groups.google.com/group/scintilla-interest?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
Neil Hodgson
2013-04-24 00:02:10 UTC
Permalink
I've tracked down the issue to ScintillaWin::WndPaint(), where Scintilla discards the allocated Direct2D objects in response to the D2DERR_RECREATE_TARGET error. If FullPaint() is called after this error, the black rectangle won't appear.
I'm not familiar with Direct2D at all, but somehow this makes sense to me. The MSDN tutorial [1] does not explicitly mention that (see section "The Direct2D Render Loop"), but maybe implicitly in step 3 by saying "Repeat step 2 whenever you need to update or redraw the scene". The question is: is there a need to redraw if the render target has been lost, or not?
I'd prefer a loop around the drawing code for a second attempt when receiving D2DERR_RECREATE_TARGET. FullPaint is for other situations and lumping this one in may make it harder to maintain.
Also, with Direct2D, the caret does not appear when setting the focus to Scintilla, if there's no text (empty document), unless some keyboard or mouse input has arrived to Scintilla.
Are you sure Scintilla is receiving focus? Its in the handling of WM_SETFOCUS that ShowCaretAtCurrentPosition is called and caret ticking is turned on. Can't see any reason for a blank document to be treated differently to one with text here.

To see if it has focus try typing and try using the tab key to see if the focus highlight is anywhere on screen.

Neil
--
You received this message because you are subscribed to the Google Groups "scintilla-interest" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scintilla-interest+***@googlegroups.com.
To post to this group, send email to scintilla-***@googlegroups.com.
Visit this group at http://groups.google.com/group/scintilla-interest?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
Neil Hodgson
2013-04-25 00:34:07 UTC
Permalink
A modification has been pushed that tries to paint another time after receiving D2DERR_RECREATE_TARGET.
http://sourceforge.net/p/scintilla/code/ci/fabcea1716dcbcc935eea86c93a472c27d8039d2/
a previous clean up change should be applied first
http://sourceforge.net/p/scintilla/code/ci/a6b4a7c067473ed837176ac57338e320e0b311ed/

Neil
--
You received this message because you are subscribed to the Google Groups "scintilla-interest" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scintilla-interest+***@googlegroups.com.
To post to this group, send email to scintilla-***@googlegroups.com.
Visit this group at http://groups.google.com/group/scintilla-interest?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
Florian Balmer
2013-04-25 19:40:31 UTC
Permalink
This post might be inappropriate. Click to display it.
Florian Balmer
2013-04-28 10:13:22 UTC
Permalink
This post might be inappropriate. Click to display it.
Neil Hodgson
2013-04-28 10:23:14 UTC
Permalink
Post by Florian Balmer
Another work around besides posting SCI_CHARLEFT to fix this problem is
to set the Scintilla control text to a space, and remove it again, when
the control is created. It seems like Scintilla is using different
approaches to draw the caret, whether or not there's some text, and the
no-text variant will only initialize properly after the text variant has
already been used.
About the only interesting difference I know of between having text and not having text is that there are no calls to lexers/folders for an empty document. Its possible that something is tripped downstream by a notification caused by lexing/folding.

You could try checking that drawing is occurring by changing something such as turning on the caret line. Also try tracing the invalidation calls to see what areas are being invalidated.
Post by Florian Balmer
Another observation: defining SCI_DISABLE_PROVISIONAL raises a bunch of
build errors, so it's not possible to exclude the provisional features,
at the moment.
Scintilla is not meant to be built with SCI_DISABLE_PROVISIONAL - it should only be defined by client code that wants to avoid using provisional features.

Neil
--
You received this message because you are subscribed to the Google Groups "scintilla-interest" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scintilla-interest+***@googlegroups.com.
To post to this group, send email to scintilla-***@googlegroups.com.
Visit this group at http://groups.google.com/group/scintilla-interest?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
Florian Balmer
2013-04-29 17:54:45 UTC
Permalink
Post by Neil Hodgson
You could try checking that drawing is occurring by changing something
such as turning on the caret line. Also try tracing the invalidation
calls to see what areas are being invalidated.
Thanks for the hint, tracking the areas being invalidated helped! I'm
using the following sequence to initialize Scintilla:

SCI_CLEARALL
SCI_SETSCROLLWIDTH(2048)
SCI_SETXOFFSET(0)
if (length)
SCI_ADDTEXT(length,text)
SCI_GOTOPOS(0)
SCI_CHOOSECARETX

This results in xOffset being set to 30 for length==0, but to 0 for
length>0, which I didn't foresee! Moving the SCI_SETXOFFSET call to the
end of the sequence solves my problem, the caret is displayed correctly!
I'm sorry for the false alarm, and thanks again for the help!
Post by Neil Hodgson
Scintilla is not meant to be built with SCI_DISABLE_PROVISIONAL - it
should only be defined by client code that wants to avoid using
provisional features.
Ok, I see, thanks for the clarification.

--Florian
--
You received this message because you are subscribed to the Google Groups "scintilla-interest" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scintilla-interest+***@googlegroups.com.
To post to this group, send email to scintilla-***@googlegroups.com.
Visit this group at http://groups.google.com/group/scintilla-interest?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
Florian Balmer
2013-07-13 16:49:52 UTC
Permalink
A follow up to the issue:

With the fix that evolved from the above discussion, most people who
reported the error to me in the first place, and who gave me a follow up,
were not experiencing the problem any more. There's one system left I know
of, which still suffers from the problem, a "Windows 7 64-bit SP1 Macbook
Air/Thunderbolt Display" machine.

On my 32-bit systems, the problem disappeared with this weeks Windows
Updates and Graphics Driver software updates, even for unpatched versions
of Notepad2! On my 64-bit systems, the problem persisted for unpatched
versions (both 32-bit and 64-bit builds), but the fixed version worked fine.

Moreover, a problem in Windows that caused the first UAC prompt in a
session to cause a looooong time to appear (up to 10-20 seconds) has also
been fixed with the latest Graphics Driver software (when doing some
research about this issue, I've come across a statement from Microsoft that
the origin of this is the Graphics Driver software). I consider this a
somehow related problem (but I may be wrong), as switching to and away from
the secure UAC desktop causes some troubles, either with initialization, or
cleanup.

So the issue in general may always have been related to Graphics Driver
software, and not to Scintilla. Anyway, the fix is a good solution one some
systems, and does not seem to be harmful.

--Florian
--
You received this message because you are subscribed to the Google Groups "scintilla-interest" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scintilla-interest+***@googlegroups.com.
To post to this group, send email to scintilla-***@googlegroups.com.
Visit this group at http://groups.google.com/group/scintilla-interest.
For more options, visit https://groups.google.com/groups/opt_out.
Florian Balmer
2013-11-09 16:27:48 UTC
Permalink
There has been one more report about this issue, this time on Windows 8, so
I started a new round of investigation, and I believe I have found a
definitive fix, now!

More systematic testing revealed that each time the Windows desktop is
switched (i.e. if a lock screen, or an UAC prompt appears), the NORMAL
behavior of ID2D1RenderTarget::EndDraw() is to return
D2DERR_RECREATE_TARGET, which is what happens here [1].

[1]
http://sourceforge.net/p/scintilla/code/ci/45d12cc53b5ae3f2fab2ba79c6eddb093b46d774/tree/win32/ScintillaWin.cxx#l610

The HALLELUJAH for me was to notice that just a few yoctoseconds later,
there's a rescue mechanism [2].

[2]
http://sourceforge.net/p/scintilla/code/ci/45d12cc53b5ae3f2fab2ba79c6eddb093b46d774/tree/win32/ScintillaWin.cxx#l627

So, as I have already suspected earlier, Scintilla-based editors not
exhibiting the "black screen bug" always seem to run into the "paintState
== paintAbandoned" situation, probably due to some internal housekeeping
upon focus/activation changes or similar, and thus always get a nice,
fresh, full redraw!

My proposed solution to fix this problem (once and for all, hopefully) is
to drop the "for (int attempt=0; ...)" loop and it's corresponding break
statement, and just set "paintState = paintAbandoned", right after calling
DropRenderTarget(), in case ID2D1RenderTarget::EndDraw() delivers
D2DERR_RECREATE_TARGET.

According to the MSDN samples, I'd also suggest to change the error
checking to "if (FAILED(hr) || hr == D2DERR_RECREATE_TARGET)".

This solution fixes the issue for anybody who has reported it to me, so I'd
be happy if this could slip into Scintilla.

--Florian
--
You received this message because you are subscribed to the Google Groups "scintilla-interest" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scintilla-interest+***@googlegroups.com.
To post to this group, send email to scintilla-***@googlegroups.com.
Visit this group at http://groups.google.com/group/scintilla-interest.
For more options, visit https://groups.google.com/groups/opt_out.
Florian Balmer
2013-11-10 07:36:42 UTC
Permalink
I forgot to mention that the D2DERR_RECREATE_TARGET error always requires a
full repaint, that's why the "for (int attempt=0; ...)" loop is not
sufficient to fix the problem. The loop works fine for the region that
needs to be updated, and i.e. repaints the current line, but the rest of
the window remains black. The Scintilla-based editors not showing the bug
satisfy the need for a full repaint after hitting D2DERR_RECREATE_TARGET,
because they have the "paintState == paintAbandoned" situation, which
triggers a full paint.
--
You received this message because you are subscribed to the Google Groups "scintilla-interest" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scintilla-interest+***@googlegroups.com.
To post to this group, send email to scintilla-***@googlegroups.com.
Visit this group at http://groups.google.com/group/scintilla-interest.
For more options, visit https://groups.google.com/groups/opt_out.
Neil Hodgson
2013-11-10 08:44:03 UTC
Permalink
More systematic testing revealed that each time the Windows desktop is switched (i.e. if a lock screen, or an UAC prompt appears), the NORMAL behavior of ID2D1RenderTarget::EndDraw() is to return D2DERR_RECREATE_TARGET, which is what happens here [1].
[1] http://sourceforge.net/p/scintilla/code/ci/45d12cc53b5ae3f2fab2ba79c6eddb093b46d774/tree/win32/ScintillaWin.cxx#l610
The HALLELUJAH for me was to notice that just a few yoctoseconds later, there's a rescue mechanism [2].
Its an expensive rescue which you don't want to perform unless necessary.
My proposed solution to fix this problem (once and for all, hopefully) is to drop the "for (int attempt=0; ...)" loop and it's corresponding break statement, and just set "paintState = paintAbandoned", right after calling DropRenderTarget(), in case ID2D1RenderTarget::EndDraw() delivers D2DERR_RECREATE_TARGET.
OK.
According to the MSDN samples, I'd also suggest to change the error checking to "if (FAILED(hr) || hr == D2DERR_RECREATE_TARGET)".
That looks repetitive as D2DERR_RECREATE_TARGET should also trigger FAILED(). Unless there are other reported failure codes here, I'd prefer to leave it handling just D2DERR_RECREATE_TARGET.

Neil
--
You received this message because you are subscribed to the Google Groups "scintilla-interest" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scintilla-interest+***@googlegroups.com.
To post to this group, send email to scintilla-***@googlegroups.com.
Visit this group at http://groups.google.com/group/scintilla-interest.
For more options, visit https://groups.google.com/groups/opt_out.
Florian Balmer
2013-11-10 20:54:01 UTC
Permalink
Post by Neil Hodgson
Its an expensive rescue which you don't want to perform unless necessary.
I agree, but I would vote for this to be affordable for an uncommon corner
case like desktop switching, when anything is likely to be flickering
anyway, on Windows. By the way, the bug can also be triggered using the
Sysinternals Desktops tool, which allows more comfortable testing (by
setting hotkeys) than with the Windows secure desktops.
Post by Neil Hodgson
That looks repetitive as D2DERR_RECREATE_TARGET should also trigger
FAILED(). Unless there are other reported failure codes here, I'd prefer to
leave it handling just D2DERR_RECREATE_TARGET.

I haven't seen or heard about other error codes in conjunction with the
black screen problem, so sticking with D2DERR_RECREATE_TARGET seems fine.

--Florian
--
You received this message because you are subscribed to the Google Groups "scintilla-interest" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scintilla-interest+***@googlegroups.com.
To post to this group, send email to scintilla-***@googlegroups.com.
Visit this group at http://groups.google.com/group/scintilla-interest.
For more options, visit https://groups.google.com/groups/opt_out.
Neil Hodgson
2013-11-10 23:38:16 UTC
Permalink
I haven't seen or heard about other error codes in conjunction with the black screen problem, so sticking with D2DERR_RECREATE_TARGET seems fine.
Committed a change:
https://sourceforge.net/p/scintilla/code/ci/6888f930b5e1935d68f1a9beb9b5b26a384bf068/

There is also the case of call tip drawing which doesn’t do anything when EndDraw fails. Haven’t managed to show any problems with this as the call tip is cancelled when Scintilla loses focus. If anyone can provoke a black call tip then that code needs to look at the return from EndDraw and perform a redraw.

Neil
--
You received this message because you are subscribed to the Google Groups "scintilla-interest" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scintilla-interest+***@googlegroups.com.
To post to this group, send email to scintilla-***@googlegroups.com.
Visit this group at http://groups.google.com/group/scintilla-interest.
For more options, visit https://groups.google.com/groups/opt_out.
Continue reading on narkive:
Loading...