Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8139210

JavaFX rendering glitch when rendering many Paths using HW pipeline

XMLWordPrintable

    • b12
    • x86
    • generic

        FULL PRODUCT VERSION :
        java version "1.8.0_60"
        Java(TM) SE Runtime Environment (build 1.8.0_60-b27)
        Java HotSpot(TM) Client VM (build 25.60-b23, mixed mode)

        ADDITIONAL OS VERSION INFORMATION :
        Microsoft Windows [Version 6.3.9600]

        A DESCRIPTION OF THE PROBLEM :
        I have a javaFX 8 application that works perfectly well in jre 1.8.0_45 but today a user came to me with a problem. After some investigation i realized that it was related to him having a more recent release of the jre, specifically 1.8.0_60.
        Im reading a GIS shapefile and drawing several Paths to a Group (like 30.000 or more) in my version it was a bit slow but it worked fine. In the latest version the image appeared distorted. The paths where drawn out of place and out of scale in chunks.

        So i decided to make a little test application to separate the problem from anything else i might be doing. In doing so i found out that the problem wasn't only when drawing Paths on a Group but also in drawing to a canvas. Also if somehow i managed to redraw the screen the image would appear fine. For example i have a checkbox binded with the visible property of the Group containing the paths so if i set it to false and then true it takes some time drawing the scene but then it appears fine. The test app is very simple if you press a button you generate a canvas with some squares 10px10p if you press the other you generate more squares and thus the rendering glitch appears.

        This error has been reproduced by que StackOverflow comunity here :
        http://stackoverflow.com/questions/32492330/javafx-rendering-glitch-in-jre-1-8-0-60?noredirect=1#comment52868774_32492330

        REGRESSION. Last worked in version 8u51

        ADDITIONAL REGRESSION INFORMATION:
        java version "1.8.0_51"
        Java(TM) SE Runtime Environment (build 1.8.0_51-b16)
        Java HotSpot(TM) 64-Bit Server VM (build 25.51-b03, mixed mode)

        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        Test 1: press button "Canvas 100 x 30", 3000 squares are drawn correctly and fast

        Test 2: press button "Canvas 100 x 400", 40000 squares are drawn showing the glitch.

        Test 3: press button "Canvas 100 x 400" again, 40000 squares are drawn correctly and fast.

        Test 4: press button "Paths 100 x 30", 3000 squares are drawn showing the glitch.

        Test 5: press button "Paths 100 x 30" again, 3000 squares are drawn correctly.

        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        https://dl.dropboxusercontent.com/u/1702867/Test2Expected.png
        https://dl.dropboxusercontent.com/u/1702867/test3Expected.png
        ACTUAL -
        https://dl.dropboxusercontent.com/u/1702867/test2ErrorCase.png
        https://dl.dropboxusercontent.com/u/1702867/test3ErrorCase.png

        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------
        package gisUI;

        import javafx.application.Application;
        import javafx.application.Platform;
        import javafx.scene.Group;
        import javafx.scene.Node;
        import javafx.scene.Scene;
        import javafx.scene.canvas.Canvas;
        import javafx.scene.canvas.GraphicsContext;
        import javafx.scene.control.Button;
        import javafx.scene.layout.HBox;
        import javafx.scene.layout.Pane;
        import javafx.scene.layout.VBox;
        import javafx.scene.paint.Color;
        import javafx.scene.paint.Paint;
        import javafx.scene.shape.LineTo;
        import javafx.scene.shape.MoveTo;
        import javafx.scene.shape.Path;
        import javafx.stage.Stage;

        public class Path2DTestApplication extends Application {
            private static final int WIDTH = 10;

            Group content = new Group();

            @Override
            public void start(Stage stage) throws Exception {
                stage.setTitle("JavaFX 1.8.0_60 rendering test");

                Button button = new Button("Canvas 100 x 30");
                button.setOnAction(a->doGenerateCanvas(100,30));

                Button button2 = new Button("Canvas 100 x 400");
                button2.setOnAction(a->doGenerateCanvas(100,400));

                Button button3 = new Button("Paths 100 x 30");
                button3.setOnAction(a->doGeneratePaths(100,30));
                VBox vBox = new VBox();
                vBox.getChildren().addAll(new HBox(button,button2,button3),content);

                Group root = new Group();
                root.getChildren().add(vBox);

                Scene scene = new Scene(root,80*WIDTH,60*WIDTH);//, 1500, 800);//, Color.White);
                stage.setScene(scene);
                stage.show();
            }

            private void doGeneratePaths(int maxX,int maxY) {
                Pane paths = new Pane();
                content.getChildren().clear();
                Platform.runLater(()->{
                for(int i = 0;i<maxX;i++){
                    for(int j=0;j<maxY;j++){
                        paths.getChildren().add(getPath(i,j));
                    }
                }

                content.getChildren().add(paths);
                });
            }

            private void doGenerateCanvas(int maxX,int maxY) {
                content.getChildren().clear();
                Platform.runLater(()->{
                Canvas canvas = new Canvas(maxX*WIDTH, maxY*WIDTH);
                GraphicsContext gc = canvas.getGraphicsContext2D();
                int counter =0;
                for(int i = 0;i<maxX;i++){
                    for(int j=0;j<maxY;j++){
                        gc.setFill(Color. rgb(255,(int) (Math.random()*255),191));
                        double[] xCoords = new double[]{i*WIDTH, (i+1)*WIDTH, (i+1)*WIDTH, i*WIDTH};
                        double[] yCoords = new double[]{j*WIDTH,(j)*WIDTH,(j+1)*WIDTH,(j+1)*WIDTH};
                        gc.fillPolygon(xCoords,yCoords,xCoords.length);
                        counter++;
                    }
                }
                System.out.println(counter +" polygons added");
                content.getChildren().add(canvas);
                });
            }

            protected Node getPath(int i,int j) {
                Path path = new Path();
                path.getElements().add(new MoveTo(i*WIDTH, j*WIDTH));
                path.getElements().add(new LineTo((i+1)*WIDTH, j*WIDTH));
                path.getElements().add(new LineTo((i+1)*WIDTH, (j+1)*WIDTH));
                path.getElements().add(new LineTo(i*WIDTH, (j+1)*WIDTH));
                path.getElements().add(new LineTo(i*WIDTH, j*WIDTH));

                Paint currentColor =Color. rgb(255,(int) (Math.random()*255),191);

                path.setFill(currentColor);
                path.setStrokeWidth(0.1);
                return path;
            }
            public static void main(String[] args) {
                Application.launch(Path2DTestApplication.class, args);
            }
        }
        ---------- END SOURCE ----------

        CUSTOMER SUBMITTED WORKAROUND :
        This workarround was sugested by http://stackoverflow.com/users/2189127/james-d

        I played around with this on my MacBook Pro (OS X 10.9.5). This has a native Retina LCD display at 2880x1800, with an attached Thunderbolt LCD display at 2560x1440. Note that the native pixel resolution is different between these two displays.

        When I run the code posted, I had no issues with any of the canvas rendering. When rendering the "Paths" option for the first time, or switching from "canvas" to "paths", I saw rendering issues similar to those you describe but only if the application was displayed on the thunderbolt display. When moving to the Retina display, everything worked fine.

        So the problem appears to be hardware related. This is clearly a bug, and you should report it as mentioned in a comment, but as a workaround you can switch to software rendering using the system property -Dprism.order=sw from the command line:

        java -Dprism.order=sw gisUI.Path2DTestApplication
        This removed all rendering errors on my system. You should be aware that this may impact performance.


              flar Jim Graham
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

                Created:
                Updated:
                Resolved: