JDK-8123247 : NPE when rendering NGRegion when returning from screen lock
  • Type: Bug
  • Component: javafx
  • Sub-Component: graphics
  • Affected Version: 8
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2013-09-18
  • Updated: 2015-06-17
  • Resolved: 2013-09-19
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8
8Fixed
Related Reports
Blocks :  
Blocks :  
Description
Note that you need the fix for RT-32636, which is under review, in order to see this bug, since that bug causes all rendering to cease.

To reproduce:

* Run any program with controls, e.g., "HelloButton"
* Go into screen lock using CTRL-ALT-DEL (or Windows-L)
* Return from screen lock by pressing ESC (or logging back in)

You will get the following NPE in the renderer which kills rendering:

java.lang.NullPointerException
        at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:627)
        at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2028)
        at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1937)
        at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:225)
        at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2028)
        at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1937)
        at com.sun.javafx.tk.quantum.ViewPainter.doPaint(ViewPainter.java:472)
        at com.sun.javafx.tk.quantum.ViewPainter.paintImpl(ViewPainter.java:324)
        at com.sun.javafx.tk.quantum.PresentingPainter.run(PresentingPainter.java:88)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
        at com.sun.javafx.tk.RenderJob.run(RenderJob.java:58)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:129)
        at java.lang.Thread.run(Thread.java:724)

Comments
Verified on 8.0b120
31-12-2013

I created RT-34516
26-11-2013

This sounds like a new bug, then. Can you please file a new JIRA?
26-11-2013

In my case I trigger the "black window" by logging in via Remote Desktop, then when I'm back on the local machine the UI is toast. Even a "Do you want to save first?" dialog that popped up when I tried to close my app was completely blank (though not black, seemed to be using the default background colour of the window). Windows 7 64-bit.
26-11-2013

Using the very same steps described in the initial problem description ? What version of Windows ? For me that works for fine on Windows 8.
26-11-2013

This happens in JavaFX 8.0b117 But no stack trace is printed, just "Exception in thread "JavaFX Application Thread" java.lang.NullPointerException" over and over.
26-11-2013

I have no specific knowledge about how screen locks, et al, affect the various kinds of textures. It seems odd to me that they would distinguish the textures that are lost, but I'm not an expert there...
19-09-2013

About the GlyphCache, it is contentsUseful=true and permanent=true and it never checks for isSurfaceLost(). and as far as I can tell it is fine. I did all the same for Region cache and here it failed. The difference is that GlyphCache is not a RTTexture. It is created using factory.createMaskTexture(widht, height, wrapMode). While region cache is created using factory.createRTTexture(widht, height, wrapMode). My current empirical understanding is that regular textures (at least masks) are not hit by problem solved by isSurfaceLost(), only RTTextures are... is that right ?
18-09-2013

I think the root cause here is that we assume that permanent resources are "forever", but they can die during a screen lock despite our best intentions. Hopefully all of our other uses of permanent resources also check for isSurfaceLost(). I know that the NGCanvas permanent resources are saved and restored even though they are permanent. What about the glyph cache and the rectangle/ellipse texture farm objects? Some food for thought... I'll note that the region cache doesn't really need to be permanent. It could be marked "contentsUseful" and it could use the lock/isLost/unlock paradigm instead...
18-09-2013

Btw, the patch with "if (tex.isSurfaceLost() || tex.createGraphics() == null)" also fixes RT-30362
18-09-2013

Hi Jim Could you please comment on the above ? I would prefer to use: if (tex.isSurfaceLost()) instead of if (tex.isSurfaceLost() || tex.createGraphics() == null) If you agree with me that tex.isSurfaceLost() should be sufficient I will include the necessary changes as part of my fix for this issue. Thank you.
18-09-2013

That fix didn't work, replacing if (tex.isSurfaceLost()) by if (tex.isSurfaceLost() || tex.createGraphics() == null) That said, I would expect tex.isSurfaceLost() to return true when tex.createGraphics() == null. Looking at the implementation BaseTexture @Override public final boolean isSurfaceLost() { return !resource.isValid(); } and ManagedResource: public final boolean isValid() { return resource != null; } ----------------------- That is happening is that resource != null, but resource.getResource() == 0L; Shouldn't D3D override one of the these methods and fix isSurfaceLost() ? Or is it "if (tex.isSurfaceLost() || tex.createGraphics() == null)" the way to go ?
18-09-2013

I see. Yes, this might be a better fix.
18-09-2013

The fix should be something like this: diff -r bd45200f433e modules/graphics/src/main/java/com/sun/javafx/sg/prism/NGRegion.java --- a/modules/graphics/src/main/java/com/sun/javafx/sg/prism/NGRegion.java Tue Sep 17 14:33:27 2013 -0700 +++ b/modules/graphics/src/main/java/com/sun/javafx/sg/prism/NGRegion.java Wed Sep 18 08:36:29 2013 -0700 @@ -371,6 +371,13 @@ private RegionImageCache getImageCache(final Graphics g) { final Screen screen = g.getAssociatedScreen(); RegionImageCache cache = imageCacheMap.get(screen); + if (cache != null) { + Texture tex = cache.getBackingStore(); + if (tex.isSurfaceLost()) { + imageCacheMap.remove(screen); + cache = null; + } + } if (cache == null) { cache = new RegionImageCache(g.getResourceFactory()); imageCacheMap.put(screen, cache);
18-09-2013

That means JFX would never cache regions after a ctrl+alt+del.
18-09-2013

The problem is that the following code, which appears in two places, is not prepared to handle a null graphics returned from createGraphics() which will happen if the surface is lost: if (cached != null && render) { Graphics cachedGraphics = cached.createGraphics(); // Have to move the origin such that when rendering to x=0, we actually end up rendering // at x=bounds.getMinX(). Otherwise anything rendered to the left of the origin would be lost cachedGraphics.translate(rect.x - outsetShapeBounds.getMinX(), rect.y - outsetShapeBounds.getMinY()); renderBackgroundShape(cachedGraphics); ------ The solution will be something like: if (cachedGraphics != null) { cachedGraphics.translate(rect.x - outsetShapeBounds.getMinX(), rect.y - outsetShapeBounds.getMinY()); renderBackgroundShape(cachedGraphics); } else { cached = null; } By inspecction, I see a similar problem in RegionImageCache.java (and possibly other places).
18-09-2013