JDK-8128944 : NPE when loading webpages that use large textures when rendering
  • Type: Bug
  • Component: javafx
  • Sub-Component: web
  • Affected Version: fx2.0
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2011-08-31
  • Updated: 2015-06-17
  • Resolved: 2011-10-14
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.
Other
fx2.0.2Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Description
I instrumented the runtime and found that WebView requests a very large texture without clipping it to the drawing area. All graphics cards have some limit (usually either 4K or 8K), and will fail to allocate a texture with either a width or height that exceeds that. Note that this is an addressing limitation not a memory limitation, since the texture in question does not take up all that much memory.

Note that on my graphics card, I also get an NPE on www.yahoo.com (which uses a texture of > 4K but < 8K).

To reproduce this:

java WebLauncher http://autos.yahoo.com/

java.lang.RuntimeException: ERROR: unable to create texture  11580x50
	at com.sun.prism.d3d.D3DResourceFactory.fatalError(D3DResourceFactory.java:377)
	at com.sun.prism.d3d.D3DResourceFactory.createTexture(D3DResourceFactory.java:77)
	at com.sun.prism.d3d.D3DResourceFactory.createTexture(D3DResourceFactory.java:39)
	at com.sun.prism.impl.BaseResourceFactory.createTexture(BaseResourceFactory.java:109)
	at com.sun.prism.impl.BaseResourceFactory.createTexture(BaseResourceFactory.java:100)
	at com.sun.webpane.sg.prism.WCImageImpl.getTexture(WCImageImpl.java:117)
	at com.sun.webpane.sg.prism.WCGraphicsPrismContext.drawImage(WCGraphicsPrismContext.java:618)
	at com.sun.webpane.platform.graphics.GraphicsDecoder.drawImage(GraphicsDecoder.java:423)
	at com.sun.webpane.platform.graphics.GraphicsDecoder.decode(GraphicsDecoder.java:166)
	at com.sun.webpane.platform.graphics.WCRenderQueue.decode(WCRenderQueue.java:35)
	at com.sun.webpane.platform.WebPage.paint2GC(WebPage.java:631)
	at com.sun.webpane.platform.WebPage.paint(WebPage.java:610)
	at com.sun.javafx.sg.prism.NGWebView.renderContent(NGWebView.java:68)
	at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:185)
	at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:39)
	at com.sun.javafx.sg.BaseNode.render(BaseNode.java:1128)
	at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:202)
	at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:397)
	at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:185)
	at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:39)
	at com.sun.javafx.sg.BaseNode.render(BaseNode.java:1128)
	at com.sun.javafx.tk.quantum.PaintRunnable.doPaint(PaintRunnable.java:217)
	at com.sun.javafx.tk.quantum.PaintRunnable.paintImpl(PaintRunnable.java:148)
	at com.sun.javafx.tk.quantum.PaintRunnable.run(PaintRunnable.java:329)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
	at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:317)
	at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:150)
	at com.sun.prism.render.RenderJob.run(RenderJob.java:29)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at com.sun.javafx.tk.quantum.QuantumRenderer$ObservedRunnable.run(QuantumRenderer.java:67)
	at java.lang.Thread.run(Thread.java:662)


Comments
Vasiliy, thank you very much for your help! Verfied with 2.0.2 b07 (JDK6 32bit and JDK7 32bit).
08-11-2011

Actually, my question was the following :) is this behaviour right for the current state of the product? Or should the images be finally rendered? Also, should I verify this CR by verifying that no NPE is thrown, or proper image rendering should also be verified?
08-11-2011

I don't get it. With 2.0.2 b07 I have no exceptions, but none of enormous images provided are rendered (neither a red line nor a piece from yahoo.com). The exact code of my test app (other web pages/local pages do load if URL pasted instead of current one): import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.web.WebEngine; import javafx.scene.web.WebView; import javafx.stage.Stage; public class Main extends Application { /** * @param args the command line arguments */ public static void main(String[] args) { System.setProperty("proxyHost", "emeacache.uk.oracle.com"); System.setProperty("proxyPort", "80"); Application.launch(Main.class, new String[0]); } @Override public void start(Stage stage) throws Exception { WebView wv = new WebView(); WebEngine e = wv.getEngine(); stage.setScene(new Scene(wv)); e.load("http://l.yimg.com/a/i/us/aut/gr/ui07/common_bgs_20080305a.png"); stage.show(); } } Prism verbose output: run: Prism pipeline init order: d3d j2d Using t2k for text rasterization Using dirty region optimizations Prism pipeline name = com.sun.prism.d3d.D3DPipeline Loading D3D native library ... succeeded. OS Information: Windows 7 build 7601 D3D Driver Information: NVIDIA GeForce GT 240 \\.\DISPLAY1 Driver nvd3dum.dll, version 8.17.12.6724 Pixel Shader version 3.0 Device : ven_10DE, dev_0CA3, subsys_83261043 Direct3D initialization succeeded (X) Got class = class com.sun.prism.d3d.D3DPipeline D3DPipeline:getInstance(), d3dEnabled=true Initialized prism pipeline: com.sun.prism.d3d.D3DPipeline RESIZE: 1302072356863104 w: 800 h: 600 Even if the window is left alone for a long time, nothing is rendered.
08-11-2011

This particular issue and fix are meant to eliminate the NPE with auto.yahoo.com and www.yahoo.com. Before this fix, WebView would always throw an NPE on auto.yahoo.com and, in certain cases, on www.yahoo.com, all in d3d mode. After this fix, the NPE should no longer appear. To verify this issue, check that auto.yahoo.com and www.yahoo.com render correctly and do not throw any exceptions in d3d mode. Additionally, before this fix, if you opened 10000x20.png, http://l.yimg.com/a/i/us/aut/gr/ui07/common_bgs_20080305a.png, or any other sufficiently large image in WebView in d3d mode, WebView would throw the same NPE. After this fix, the NPE should no longer appear. The image, however, is expected to not be rendered. This is a known problem tracked as RT-17425. That said, the behavior you are observing is expected, for the current state of the project.
08-11-2011

Fixed with http://jfxsrc.us.oracle.com/javafx/2.0.2/scrum/graphics/runtime/rev/9950295125de Follow-up issue: RT-17425
14-10-2011

Webrev: http://javaweb.us.oracle.com/jcg/fx-webrevs/RT-16536/2 Summary of changes: - Account for the fact that when the texture width and/or height is too large, ResourceFactory.createTexture() will return null rather than throw NPE To trigger the failure case, open the attached 10000x20.png image in Browser or WebLauncher.
13-10-2011

Kirill Prazdnikov pointed out in an off-line conversation that WCImageImpl's call to ResourceFactory.createTexture() cannot throw NullPointerException, and therefore it is incorrect to have a catch statement for NPE in WCImageImpl.updateTexture(). Instead, WCImageImpl.updateTexture() should be prepared for ResourceFactory.createTexture() to return null.
11-10-2011

Fixed with http://jfxsrc.us.oracle.com/javafx/2.0.2/scrum/graphics/runtime/rev/81422c23f50a
27-09-2011

The fix looks fine for me.
23-09-2011

Well, I am probably missing something but my understanding is PrismImage.draw() has to support scaling. This follows from the declaration of the drawImage() method in com.sun.webpane.platform.graphics.WCGraphicsContext and com.sun.webpane.sg.prism.WCGraphicsPrismContext: WCGraphicsContext: public abstract void drawImage(WCImage img, float dstx, float dsty, float dstw, float dsth, float srcx, float srcy, float srcw, float srch); WCGraphicsPrismContext: public void drawImage(WCImage img, float dstx, float dsty, float dstw, float dsth, float srcx, float srcy, float srcw, float srch)
23-09-2011

PrismImage.draw() accepts 8 parameters, which allows for scaling the image. It would probably be more defensive if it accepted just srcX/Y, dstX/Y, and width/height. This way, it would be impossible to invoke scaling by error. The code would also be slightly more concise =) This is purely stylistic issue and I won't insist on it -- just a thing to consider.
23-09-2011

Follow-up issue: RT-17074
22-09-2011

Webrev: http://javaweb.us.oracle.com/jcg/fx-webrevs/RT-16536/1 Summary of changes: - When requested to draw a fragment of a com.sun.webpane.sg.prismWCImageImpl for the first time, do not attempt to create the texture for the entire image. Instead, create a texture of the minimum required size, use it, and cache it. On all subsequent draw requests, re-use the cached texture if its size is sufficient to satisfy the request, or otherwise replace it with a larger texture. - Since the com.sun.webpane.sg.prism.PrismImage's texture can now contain virtually any fragment of the image, the texture is no longer exposed via the PrismImage interface. Instead of exposing the texture, PrismImage's implementations are now given responsibility to draw and dispose themselves. Testing: - http://autos.yahoo.com and http://www.yahoo.com now render correctly without exceptions in d3d and j2d modes - No regressions in Ensemble, Browser, WebMap, and WebLauncher - No regressions in unit tests - No regressions in the WebView's Guimark2.Bitmap benchmark - No regressions on http://theimage.com and animated GIF images reachable from http://theimage.com/animation/intro/animationintro.html
22-09-2011

Here is the description of the problem intended to help add it to the release notes. If the web page loaded into a WebView makes use of an image or HTML5 canvas whose width or height exceeds a certain limit, WebView will display the following exception in stderr when trying to render the page content: java.lang.NullPointerException at com.sun.prism.impl.BaseResourceFactory.createTexture(BaseResourceFactory.java:113) at com.sun.prism.impl.BaseResourceFactory.createTexture(BaseResourceFactory.java:100) at com.sun.webpane.sg.prism.WCImageImpl.getTexture(WCImageImpl.java:125) at com.sun.webpane.sg.prism.WCGraphicsPrismContext.drawImage(WCGraphicsPrismContext.java:618) at com.sun.webpane.platform.graphics.GraphicsDecoder.drawImage(GraphicsDecoder.java:423) at com.sun.webpane.platform.graphics.GraphicsDecoder.decode(GraphicsDecoder.java:166) at com.sun.webpane.platform.graphics.WCRenderQueue.decode(WCRenderQueue.java:35) at com.sun.webpane.platform.WebPage.paint2GC(WebPage.java:631) at com.sun.webpane.platform.WebPage.paint(WebPage.java:610) at com.sun.javafx.sg.prism.NGWebView.renderContent(NGWebView.java:68) at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:185) at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:39) at com.sun.javafx.sg.BaseNode.render(BaseNode.java:1128) at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:202) at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:397) at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:185) at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:39) at com.sun.javafx.sg.BaseNode.render(BaseNode.java:1128) at com.sun.javafx.tk.quantum.PaintRunnable.doPaint(PaintRunnable.java:217) at com.sun.javafx.tk.quantum.PaintRunnable.paintImpl(PaintRunnable.java:148) at com.sun.javafx.tk.quantum.PaintRunnable.run(PaintRunnable.java:329) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441) at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:317) at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:150) at com.sun.prism.render.RenderJob.run(RenderJob.java:29) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) at com.sun.javafx.tk.quantum.QuantumRenderer$ObservedRunnable.run(QuantumRenderer.java:67) at java.lang.Thread.run(Thread.java:662) The limit is graphics card-specific and is usually either 4096 or 8192 pixels. The problem only appears when running the HW pipeline and is not reproducible with the SW pipeline.
09-09-2011

What happens in the http://autos.yahoo.com case is, that web page appears to use the following 11580 x 50 png image as a collection of drawing primitives: http://l.yimg.com/a/i/us/aut/gr/ui07/common_bgs_20080305a.png (The size of the image file is only 6 Kbytes.) At some point WebKit asks WebView to paint one of the primitives on the screen. The size of the primitive is rather small: 54 x 22. The problem is, instead of creating a small 54 x 22 texture, WebView creates a texture for the entire image, thus causing the NPE. WebView creates and caches such a big texture with the intent to re-use it for all painting operations associated with the image, but that appears to be an incorrect way to use Prism textures, as this bug indicates. Kevin, I have one more question. Suppose I have a com.sun.prism.Image and I want to draw a certain fragment of it into a com.sun.prism.Graphics. Would it be correct to do so as follows: PixelFormat format = image.getPixelFormat(); Texture tex = GraphicsPipeline.getDefaultResourceFactory().createTexture(format, Usage.DEFAULT, fragmentWidth, fragmentHeight); tex.update(image, fragmentX, fragmentY, fragmentWidth, fragmentHeight); // ... and then graphics.drawTexture(tex, ...); Any performance implications? What if I need to do this many-many times per a rendering cycle? Am I expected to maintain a pool of Textures (or a single Texture of a maximum required size) to bypass texture creation for each and every painting operation? Thank you.
09-09-2011

Yes, I am running the SW pipeline. [java] Prism pipeline init order: d3d j2d [java] Using t2k for text rasterization [java] Using dirty region optimizations [java] Prism pipeline name = com.sun.prism.d3d.D3DPipeline [java] Loading D3D native library ... [java] succeeded. [java] OS Information: [java] Windows 7 build 7601 [java] D3D Driver Information: [java] Intel(R) HD Graphics [java] \\.\DISPLAY1 [java] Driver igdumdx32.dll, version 8.15.10.2202 [java] Pixel Shader version 3.0 [java] Device : ven_8086, dev_0046, subsys_21D617AA [java] *** WARNING: bad driver version detected, device disabled! Please update your driver to at least version 8.15.10.2302 [java] [java] Direct3D initialization failed [java] (X) Got class = class com.sun.prism.d3d.D3DPipeline [java] D3DPipeline:getInstance(), d3dEnabled=false [java] GraphicsPipeline.createPipeline: error initializing pipeline com.sun.prism.d3d.D3DPipeline [java] Prism pipeline name = com.sun.prism.j2d.J2DPipeline [java] *** Fallback to Prism SW pipeline [java] (X) Got class = class com.sun.prism.j2d.J2DPipeline [java] Initialized prism pipeline: com.sun.prism.j2d.J2DPipeline [java] RESIZE: 24163330702687 w: 784 h: 562 [java] Glass native format: 1 What I am going to do is try installing a newer driver and also try the whole thing on another machine.
05-09-2011

Can you run with -Dprism.verbose=true and see whether you are running the HW or SW pipeline? If you have an older driver you may be falling back to SW (the J2D pipeline) which doesn't have this issue.
05-09-2011

BTW, I cannot reproduce the problem with autos.yahoo.com on my laptop (Lenovo T410, Intel HD Graphics). Also, the first reasonably large image I found, 12724 x 1261, http://www.flickr.com/photos/transmogrifiedmedia/5353877982/sizes/o/in/photostream loads and displays OK. To be continued.
05-09-2011

Thank you!
02-09-2011

The exception is not fatal and just prevents rendering of the problematic image, so deferring it makes sense to me (I think this should be targeted to Lombard). To answer your earlier question: there isn't a method currently (I will file an RFE for Lombard), but hard-coding 4K is likely to be OK based on the graphics cards we have run across.
02-09-2011

Anyway, unless I am missing something, this is only an exception message and not a failure to render the entire page. Given that we cannot come up with a quick and safe fix right now, I am requesting a deferral.
01-09-2011

Kevin, I have a question in relation to RT-16536, if I may. Do you know if there is a mechanism in Prism (or anywhere else) that would allow WebView to find out up-front if a texture creation will fail or not, based on the image attributes? We are specifically interested in a mechanism that could be used by the code running on the JavaFX Application Thread. If WebView could determine that a texture cannot be created by only looking at the image size and other attributes, that would make things a lot more consistent with WebKit and hence simpler. If there is no programmatic mechanism for that in Prism, would it be correct for WebView to have the 4K limit hard coded and refrain from creating textures larger (higher or wider) than that? Clipping to the drawing area is not always feasible because a web page can and should be able to create an HTML5 canvas slightly larger than the page or screen size and start drawing on the canvas, and WebView has to retain the results of all such drawing including the pixels that are outside of the currently visible area. What WebView can and should do is fail fast when the page attempts to create an image or canvas of an excessive size. Therefore my question.
01-09-2011

Go through the deferral process. Add presidio-defer-request label
01-09-2011