JDK-8095424 : WebView fails to unlock some texture resources
  • Type: Bug
  • Component: javafx
  • Sub-Component: web
  • Affected Version: 8
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2013-10-17
  • Updated: 2015-06-12
  • Resolved: 2013-10-25
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
Relates :  
Relates :  
Relates :  
Description
Running the "FullTutorial" CanvasTest toy from rt-closed, we get texture statistics being printed out starting from the "Operations" tab showing that some textures are left locked.

One or two of these locked textures are due to a bug in NGCanvas that leaves a temporary texture locked after applying a non-SrcOver blending mode, but the rest (about 26) of the locked textures come from the WCGraphics code with the following stack trace showing where they were locked:

     [java] java.lang.Throwable: 1
     [java] 	at com.sun.prism.impl.ManagedResource.lock(ManagedResource.java:286)
     [java] 	at com.sun.prism.impl.ManagedResource.<init>(ManagedResource.java:197)
     [java] 	at com.sun.prism.impl.DisposerManagedResource.<init>(DisposerManagedResource.java:34)
     [java] 	at com.sun.prism.es2.ES2TextureResource.<init>(ES2TextureResource.java:34)
     [java] 	at com.sun.prism.es2.ES2RTTexture.create(ES2RTTexture.java:285)
     [java] 	at com.sun.prism.es2.ES2ResourceFactory.createRTTexture(ES2ResourceFactory.java:101)
     [java] 	at com.sun.prism.es2.ES2ResourceFactory.createRTTexture(ES2ResourceFactory.java:97)
     [java] 	at com.sun.scenario.effect.impl.prism.ps.PPSDrawable.create(PPSDrawable.java:67)
     [java] 	at com.sun.scenario.effect.impl.prism.ps.PPSRenderer.createCompatibleImage(PPSRenderer.java:164)
     [java] 	at com.sun.scenario.effect.impl.prism.ps.PPSRenderer.createCompatibleImage(PPSRenderer.java:65)
     [java] 	at com.sun.scenario.effect.Effect.createCompatibleImage(Effect.java:466)
     [java] 	at com.sun.javafx.webkit.prism.WCGraphicsPrismContext$Composite.blend(WCGraphicsPrismContext.java:1324)
     [java] 	at com.sun.javafx.webkit.prism.WCGraphicsPrismContext$Composite.paint(WCGraphicsPrismContext.java:1307)
     [java] 	at com.sun.javafx.webkit.prism.WCGraphicsPrismContext$Composite.paint(WCGraphicsPrismContext.java:1287)
     [java] 	at com.sun.javafx.webkit.prism.WCGraphicsPrismContext.drawImage(WCGraphicsPrismContext.java:700)
     [java] 	at com.sun.webkit.graphics.GraphicsDecoder.drawImage(GraphicsDecoder.java:408)
     [java] 	at com.sun.webkit.graphics.GraphicsDecoder.decode(GraphicsDecoder.java:166)
     [java] 	at com.sun.webkit.graphics.WCRenderQueue.decode(WCRenderQueue.java:69)
     [java] 	at com.sun.webkit.graphics.WCRenderQueue.decode(WCRenderQueue.java:80)
     [java] 	at com.sun.webkit.graphics.WCRenderQueue.decode(WCRenderQueue.java:86)
     [java] 	at com.sun.webkit.graphics.GraphicsDecoder.decode(GraphicsDecoder.java:322)
     [java] 	at com.sun.webkit.graphics.WCRenderQueue.decode(WCRenderQueue.java:69)
     [java] 	at com.sun.webkit.WebPage.paint2GC(WebPage.java:669)
     [java] 	at com.sun.webkit.WebPage.paint(WebPage.java:637)
     [java] 	at com.sun.javafx.sg.prism.NGWebView.renderContent(NGWebView.java:73)

(To get the stack traces of where unmatched locks occur, set the ManagedResource.trackLockSources flag to true...)
Comments
Ok. Close the issue as verified on 8.0b125
24-01-2014

If textures are left locked while rendering a frame, then code in the Prism pipeline will print out warnings (including a summary of texture statistics). If there are no printouts while running through all of the tabs in the tutorial then the problem has been solved.
23-01-2014

How do you get "we get texture statistics being printed out starting from the "Operations" tab showing that some textures are left locked"?
23-01-2014

Fixed in changeset http://hg.openjdk.java.net/openjfx/8/graphics/rt/rev/41c08cf957cf
25-10-2013

Comment from Jim on the fix: Note that the get() methods already return a locked image so locking it is adding a second lock and then unlocking it returns it to 1 outstanding lock. I tried a quick test to switch to getCompatible with no added locks, but it then ran into a problem where the PassThrough used by the createEffect() method will install the texture into an ImageData and return it. ImageData is designed to be used with an image that comes from getCompatibleImage, but it then owns that image and will return it to the pool when all locking is done. Thus, release() would be called twice for most of these images, and it would be called for images that were obtained via the "readbackGraphics" section of code - attempting to return those textures to the pool. Possible ways around this: 1) create a single ImageData for a given texture you get from getCompatibleImage() and use that everywhere, calling addref and unref as necessary to manage its lifetime. PassThrough would then addref the existing ImageData before returning it in the filter() method (the caller would be responsible for unref()ing the ImageData reference when it was done). This technique might cause problems with the textures that come from the readbackGraphics, though. 2) Use "reusable" ImageDatas in PassThrough. A flag was added to ImageData as part of the ManagedResource work for cases where code creates an ImageData and keeps it around for multiple rendered frames. Internally the ImageData object does not hand those textures back to the pool when the ref count goes to zero - it simply unlocks the texture. Essentially the "reusable" flag means "non-pool texture". To use this, you would lock the texture in the filter() method and then make an ImageData from it, and then mark the ImageData as reusable using the setReusable() method. This technique would be compatible with the readbackGraphics texture too.
22-10-2013

That looks like the bug right there. release is only valid on images that you get from getCompatibleImage. If you look at the implementation, it changes the state in the ImagePool of that image from "checked out" to "checked in", but if it doesn't find the image in the pool (which it won't if you get it from createCompatibleImage) then it does nothing and you drop it on the floor locked. This issue of API confusion is actually documented in its own Jira issue - RT-15960 - but until the managed resource mechanism, it didn't have any side effects and so was on the back burner. The solutions within the WebView code are: - Change to using "getCompatibleImage" in WCGPC. This would mean that those textures would come from a cache rather than being created on the fly. - Change to unlocking and/or disposing the image rather than releasing it in WCGPC. It would fix the MR issues, and would acknowledge the fact that those textures are not currently cached anyway. - Change WCGPC to just create and dispose its own textures directly if it gets no benefit from the wrapped images that are returned from the Effects framework (caching being one of the few advantages that you get outside of the Effect framework). If the textures are later used in effect code, then that may be a benefit as well. Some issues in RT-15960 that could be fixed in the meantime: - Modify releaseCI() to always unlock the texture whether or not it finds an entry in the ImagePool. - Modify releaseCI() to print or throw errors or warnings when it is used on a non-pool image. - Get rid of create/get/release and use something better that ties in to ManagedResources better.
17-10-2013

I just searched the workspace for other calls to createCompatibleImage() and WCGPC is the only current code that calls that method outside of the Effects package (which mainly uses it to populate the ImagePool from the ImagePool code itself). So, it looks like the confusion documented in RT-15960 is currently isolated to just those 2 calls from the WCPGC code. I seem to recall having removed a bunch of calls to createCI() from other code over time so these are probably the last 2 remaining calls...
17-10-2013

I've stepped through the test case and verified that every single image created with Effect.createCompatibleImage() (WCGraphicsPrismContext.java lines 1324 and 1336) is then released with Effect.releaseCompatibleImage() (lines 1346 and 1352). There were 26 such images. Still the textures are listed as locked. Is releaseCompatibleImage() not enough?
17-10-2013

Upgrading to critical because unmatched lock/unlock pairs unnecessarily leaks texture resources that can not be reclaimed.
17-10-2013