[Rev 02] RFR: 8088198: Exception thrown from snapshot if dimensions are larger than max texture size
Nir Lisker
nlisker at openjdk.java.net
Thu Jan 16 17:00:50 UTC 2020
On Thu, 16 Jan 2020 17:00:47 GMT, Frederic Thevenet <github.com+7450507+fthevenet at openjdk.org> wrote:
>> This PR aims to address the following issue: JDK-8088198 Exception thrown from snapshot if dimensions are larger than max texture size
>>
>> In order to do that, it simply captures snapshots in multiple tiles of maxTextureSize^2 dimensions (or less, as needed), and then recomposes all the tiles into a a single image.
>> Other than that, the logic used to do the actual snapshot is unchanged.
>>
>> Tests using the existing SnapshotCommon class have been added in a new file named Snapshot3Test under SystemTest/test/javafx/scene.
>> These tests pass with the proposed fix, and fail without, throwing " java.lang.IllegalArgumentException: Unrecognized image loader: null"
>
> The pull request has been updated with 2 additional commits.
I tested this fix against the repro code in https://github.com/javafxports/openjdk-jfx/issues/433 (which is [JDK-8222238](https://bugs.openjdk.java.net/browse/JDK-8222238)), but there is still an NPE. I'm not certain that this fix is supposed to solve that bug, but according to the comments, the root cause is the same as [JDK-8189082](https://bugs.openjdk.java.net/browse/JDK-8189082), which is related to this one. It's worth to take a look to see if something was missed.
modules/javafx.graphics/src/main/java/javafx/scene/Scene.java line 1290:
> 1289: int yMin = (int)Math.floor(y);
> 1290: int xMax = (int)Math.ceil(x + w);
> 1291: int yMax = (int)Math.ceil(y + h);
While you're working in the area, this code can be written as
int width, height;
if (wimg == null) {
int xMax = (int)Math.ceil(x + w);
int yMax = (int)Math.ceil(y + h);
width = Math.max(xMax - xMin, 1);
height = Math.max(yMax - yMin, 1);
wimg = new WritableImage(width, height);
} else {
to avoid unnecessary computations.
modules/javafx.graphics/src/main/java/javafx/scene/Scene.java line 1313:
> 1312: int tileHeight = Math.min(maxTextureSize, height - yOffset);
> 1313: WritableImage tile = doSnapshotTile(scene, xMin + xOffset, yMin + yOffset, tileWidth, tileHeight, root, transform, depthBuffer, fill, camera, null);
> 1314: wimg.getPixelWriter().setPixels(xOffset, yOffset, tileWidth, tileHeight, tile.getPixelReader(), 0, 0);
This line is too long and needs to break into 2. I think that the limit is 135 characters.
modules/javafx.graphics/src/main/java/javafx/scene/Scene.java line 1316:
> 1315: }
> 1316: }
> 1317: } else {
I would extract this code into its own method similar to `doSnapshotTile`:
`assemble(scene, xMin, yMin, width, height, root, transform, depthBuffer, fill, camera, wimg, maxTextureSize);`
(`assemble` is a bad name, I didn't think about a better one).
The method can return he resulting `WritableImage`, but it is not needed since it is manipulated via "side-effects". I would, however, bring it line with the `else` clause - either both use `wimg = methodName(..., wimg, ...);` or just `methodName(..., wimg, ...);`. This is fine since the input `WritableImage` is never `null`. From a readability point of view, using return values seems better.
-------------
PR: https://git.openjdk.java.net/jfx/pull/68
More information about the openjfx-dev
mailing list