Discussion:
Bad DropShadow performance
Tom Schindl
2018-10-04 11:10:30 UTC
Permalink
Hi,

Why does applying a DropShadow on a large region cause problem when
animating nodes contained in that region?
package fxbugs;
import javafx.animation.ScaleTransition;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.effect.BlurType;
import javafx.scene.effect.DropShadow;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Duration;
public class DropShadowPerformance extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
BorderPane p = new BorderPane();
p.setPadding(new Insets(30));
GridPane container = new GridPane();
container.setHgap(10);
container.setVgap(10);
container.setStyle("-fx-background-color: green; -fx-padding: 10;");
container.setEffect(new DropShadow(BlurType.GAUSSIAN, Color.rgb(0, 0, 0, 0.3), 10, 0.5, 0, 0));
for( int i = 0; i < 8; i++ ) {
for( int j = 0; j < 14; j++ ) {
container.add(createButton(), i, j);
}
}
p.setCenter(container);
Scene s = new Scene(p, 800, 600);
primaryStage.setScene(s);
primaryStage.show();
}
private Node createButton() {
Button button = new Button("hello world");
button.hoverProperty().addListener((ob,ol,ne) -> {
ScaleTransition t = new ScaleTransition(Duration.millis(500), button);
if( ne ) {
t.setFromX(1);
t.setFromY(1);
t.setToX(1.2);
t.setToY(1.2);
} else {
t.setFromX(1.2);
t.setFromY(1.2);
t.setToX(1);
t.setToY(1);
}
t.play();
});
return button;
}
public static void main(String[] args) {
launch(args);
}
}
If you run the following application:
* Maximize the window
* Hover over a button (eg the one in the right lower corner)

You'll notice that the animation is not smooth, setting cache flags on
the container does not improve the situation, nor does using a ONE_PASS_BOX.

Removing the effect on the container node "fixes" the problem.

This is on a MacBook Pro and Windows Surface both having a Intel Iris
Plus 650 graphics card.

Tom
--
Tom Schindl, CTO
BestSolution.at EDV Systemhaus GmbH
Eduard-Bodem-Gasse 5-7. A-6020 Innsbruck
Reg. Nr. FN 222302s am Firmenbuchgericht Innsbruck
Dirk Lemmermann
2018-10-04 18:32:31 UTC
Permalink
Yes, I also noticed that DropShadow causes severe performance degradation.

Dirk
Post by Tom Schindl
Hi,
Why does applying a DropShadow on a large region cause problem when
animating nodes contained in that region?
package fxbugs;
import javafx.animation.ScaleTransition;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.effect.BlurType;
import javafx.scene.effect.DropShadow;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Duration;
public class DropShadowPerformance extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
BorderPane p = new BorderPane();
p.setPadding(new Insets(30));
GridPane container = new GridPane();
container.setHgap(10);
container.setVgap(10);
container.setStyle("-fx-background-color: green; -fx-padding: 10;");
container.setEffect(new DropShadow(BlurType.GAUSSIAN, Color.rgb(0, 0, 0, 0.3), 10, 0.5, 0, 0));
for( int i = 0; i < 8; i++ ) {
for( int j = 0; j < 14; j++ ) {
container.add(createButton(), i, j);
}
}
p.setCenter(container);
Scene s = new Scene(p, 800, 600);
primaryStage.setScene(s);
primaryStage.show();
}
private Node createButton() {
Button button = new Button("hello world");
button.hoverProperty().addListener((ob,ol,ne) -> {
ScaleTransition t = new ScaleTransition(Duration.millis(500), button);
if( ne ) {
t.setFromX(1);
t.setFromY(1);
t.setToX(1.2);
t.setToY(1.2);
} else {
t.setFromX(1.2);
t.setFromY(1.2);
t.setToX(1);
t.setToY(1);
}
t.play();
});
return button;
}
public static void main(String[] args) {
launch(args);
}
}
* Maximize the window
* Hover over a button (eg the one in the right lower corner)
You'll notice that the animation is not smooth, setting cache flags on
the container does not improve the situation, nor does using a ONE_PASS_BOX.
Removing the effect on the container node "fixes" the problem.
This is on a MacBook Pro and Windows Surface both having a Intel Iris
Plus 650 graphics card.
Tom
--
Tom Schindl, CTO
BestSolution.at EDV Systemhaus GmbH
Eduard-Bodem-Gasse 5-7. A-6020 Innsbruck
Reg. Nr. FN 222302s am Firmenbuchgericht Innsbruck
Kevin Rushforth
2018-10-04 20:08:52 UTC
Permalink
Any effect has the potential for slowing down depending on the size if
the node being rendered, since it is done as an image operation on the
entire area (bounding box) covered by the Parent. Have you noticed
whether DropShadow is worse than other effects, say, GaussianBlur? One
other thing to note is that caching a Parent will have no effect if the
children are animating, since it will need to be recreated each time.

-- Kevin
Post by Dirk Lemmermann
Yes, I also noticed that DropShadow causes severe performance degradation.
Dirk
Post by Tom Schindl
Hi,
Why does applying a DropShadow on a large region cause problem when
animating nodes contained in that region?
package fxbugs;
import javafx.animation.ScaleTransition;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.effect.BlurType;
import javafx.scene.effect.DropShadow;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Duration;
public class DropShadowPerformance extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
BorderPane p = new BorderPane();
p.setPadding(new Insets(30));
GridPane container = new GridPane();
container.setHgap(10);
container.setVgap(10);
container.setStyle("-fx-background-color: green; -fx-padding: 10;");
container.setEffect(new DropShadow(BlurType.GAUSSIAN, Color.rgb(0, 0, 0, 0.3), 10, 0.5, 0, 0));
for( int i = 0; i < 8; i++ ) {
for( int j = 0; j < 14; j++ ) {
container.add(createButton(), i, j);
}
}
p.setCenter(container);
Scene s = new Scene(p, 800, 600);
primaryStage.setScene(s);
primaryStage.show();
}
private Node createButton() {
Button button = new Button("hello world");
button.hoverProperty().addListener((ob,ol,ne) -> {
ScaleTransition t = new ScaleTransition(Duration.millis(500), button);
if( ne ) {
t.setFromX(1);
t.setFromY(1);
t.setToX(1.2);
t.setToY(1.2);
} else {
t.setFromX(1.2);
t.setFromY(1.2);
t.setToX(1);
t.setToY(1);
}
t.play();
});
return button;
}
public static void main(String[] args) {
launch(args);
}
}
* Maximize the window
* Hover over a button (eg the one in the right lower corner)
You'll notice that the animation is not smooth, setting cache flags on
the container does not improve the situation, nor does using a ONE_PASS_BOX.
Removing the effect on the container node "fixes" the problem.
This is on a MacBook Pro and Windows Surface both having a Intel Iris
Plus 650 graphics card.
Tom
--
Tom Schindl, CTO
BestSolution.at EDV Systemhaus GmbH
Eduard-Bodem-Gasse 5-7. A-6020 Innsbruck
Reg. Nr. FN 222302s am Firmenbuchgericht Innsbruck
Tom Schindl
2018-10-04 20:44:07 UTC
Permalink
Hi Kevin,

Thank you for the comment so the trick to fix my problems is that I
don't apply the effect on the container but create a 2nd node who has
the same size and is a sibling of my area and apply the effect there?

This looks like it is working ;-)

package fxbugs;

import javafx.animation.ScaleTransition;
import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.effect.BlurType;
import javafx.scene.effect.DropShadow;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Region;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Duration;

public class DropShadowPerformance extends Application {

@Override
public void start(Stage primaryStage) throws Exception {
AnchorPane p = new AnchorPane();

//
// Use a shadow
Region shadow = new Region();
shadow.setStyle("-fx-background-color: black;");
shadow.setEffect(new DropShadow(BlurType.GAUSSIAN, Color.rgb(0,
0, 0, 0.3), 10, 0.5, 0, 0));
shadow.setCache(true);
AnchorPane.setBottomAnchor(shadow, 30.0);
AnchorPane.setTopAnchor(shadow, 30.0);
AnchorPane.setLeftAnchor(shadow, 30.0);
AnchorPane.setRightAnchor(shadow, 30.0);

p.getChildren().add(shadow);

GridPane container = new GridPane();
container.setHgap(10);
container.setVgap(10);
container.setStyle("-fx-background-color: green; -fx-padding: 10;");
// container.setEffect(new DropShadow(BlurType.GAUSSIAN,
Color.rgb(0, 0, 0, 0.3), 10, 0.5, 0, 0));
for( int i = 0; i < 8; i++ ) {
for( int j = 0; j < 14; j++ ) {
container.add(createButton(), i, j);
}
}
AnchorPane.setBottomAnchor(container, 30.0);
AnchorPane.setTopAnchor(container, 30.0);
AnchorPane.setLeftAnchor(container, 30.0);
AnchorPane.setRightAnchor(container, 30.0);
p.getChildren().add(container);

Scene s = new Scene(p, 800, 600);
primaryStage.setScene(s);
primaryStage.show();
}

private Node createButton() {
Button button = new Button("hello world");
button.hoverProperty().addListener((ob,ol,ne) -> {
ScaleTransition t = new
ScaleTransition(Duration.millis(500), button);

if( ne ) {
t.setFromX(1);
t.setFromY(1);
t.setToX(1.2);
t.setToY(1.2);
} else {
t.setFromX(1.2);
t.setFromY(1.2);
t.setToX(1);
t.setToY(1);
}

t.play();
});
return button;
}

public static void main(String[] args) {
launch(args);
}
}


Tom
Post by Kevin Rushforth
Any effect has the potential for slowing down depending on the size if
the node being rendered, since it is done as an image operation on the
entire area (bounding box) covered by the Parent. Have you noticed
whether DropShadow is worse than other effects, say, GaussianBlur? One
other thing to note is that caching a Parent will have no effect if the
children are animating, since it will need to be recreated each time.
-- Kevin
Post by Dirk Lemmermann
Yes, I also noticed that DropShadow causes severe performance
degradation.
Dirk
Post by Tom Schindl
Hi,
Why does applying a DropShadow on a large region cause problem when
animating nodes contained in that region?
package fxbugs;
import javafx.animation.ScaleTransition;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.effect.BlurType;
import javafx.scene.effect.DropShadow;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Duration;
public class DropShadowPerformance extends Application {
    public void start(Stage primaryStage) throws Exception {
        BorderPane p = new BorderPane();
        p.setPadding(new Insets(30));
        GridPane container = new GridPane();
        container.setHgap(10);
        container.setVgap(10);
        container.setStyle("-fx-background-color: green;
-fx-padding: 10;");
        container.setEffect(new DropShadow(BlurType.GAUSSIAN,
Color.rgb(0, 0, 0, 0.3), 10, 0.5, 0, 0));
        for( int i = 0; i < 8; i++ ) {
            for( int j = 0; j < 14; j++ ) {
                container.add(createButton(), i, j);
            }
        }
        p.setCenter(container);
        Scene s = new Scene(p, 800, 600);
        primaryStage.setScene(s);
        primaryStage.show();
    }
    private Node createButton() {
        Button button = new Button("hello world");
        button.hoverProperty().addListener((ob,ol,ne) -> {
            ScaleTransition t = new
ScaleTransition(Duration.millis(500), button);
            if( ne ) {
                t.setFromX(1);
                t.setFromY(1);
                t.setToX(1.2);
                t.setToY(1.2);
            } else {
                t.setFromX(1.2);
                t.setFromY(1.2);
                t.setToX(1);
                t.setToY(1);
            }
            t.play();
        });
        return button;
    }
    public static void main(String[] args) {
        launch(args);
    }
}
* Maximize the window
* Hover over a button (eg the one in the right lower corner)
You'll notice that the animation is not smooth, setting cache flags on
the container does not improve the situation, nor does using a ONE_PASS_BOX.
Removing the effect on the container node "fixes" the problem.
This is on a MacBook Pro and Windows Surface both having a Intel Iris
Plus 650 graphics card.
Tom
-- 
Tom Schindl, CTO
BestSolution.at EDV Systemhaus GmbH
Eduard-Bodem-Gasse 5-7. A-6020 Innsbruck
Reg. Nr. FN 222302s am Firmenbuchgericht Innsbruck
--
Tom Schindl, CTO
BestSolution.at EDV Systemhaus GmbH
Eduard-Bodem-Gasse 5-7. A-6020 Innsbruck
Reg. Nr. FN 222302s am Firmenbuchgericht Innsbruck
Kevin Rushforth
2018-10-04 23:58:31 UTC
Permalink
Glad you were able to fix your issue. If you don't need to apply the
effect to the group with the animating content, then it will be able to
be cached, which is where I guess the speedup is coming from.

-- Kevin
Post by Tom Schindl
Hi Kevin,
Thank you for the comment so the trick to fix my problems is that I
don't apply the effect on the container but create a 2nd node who has
the same size and is a sibling of my area and apply the effect there?
This looks like it is working ;-)
package fxbugs;
import javafx.animation.ScaleTransition;
import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.effect.BlurType;
import javafx.scene.effect.DropShadow;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Region;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Duration;
public class DropShadowPerformance extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
AnchorPane p = new AnchorPane();
//
// Use a shadow
Region shadow = new Region();
shadow.setStyle("-fx-background-color: black;");
shadow.setEffect(new DropShadow(BlurType.GAUSSIAN, Color.rgb(0,
0, 0, 0.3), 10, 0.5, 0, 0));
shadow.setCache(true);
AnchorPane.setBottomAnchor(shadow, 30.0);
AnchorPane.setTopAnchor(shadow, 30.0);
AnchorPane.setLeftAnchor(shadow, 30.0);
AnchorPane.setRightAnchor(shadow, 30.0);
p.getChildren().add(shadow);
GridPane container = new GridPane();
container.setHgap(10);
container.setVgap(10);
container.setStyle("-fx-background-color: green; -fx-padding: 10;");
// container.setEffect(new DropShadow(BlurType.GAUSSIAN,
Color.rgb(0, 0, 0, 0.3), 10, 0.5, 0, 0));
for( int i = 0; i < 8; i++ ) {
for( int j = 0; j < 14; j++ ) {
container.add(createButton(), i, j);
}
}
AnchorPane.setBottomAnchor(container, 30.0);
AnchorPane.setTopAnchor(container, 30.0);
AnchorPane.setLeftAnchor(container, 30.0);
AnchorPane.setRightAnchor(container, 30.0);
p.getChildren().add(container);
Scene s = new Scene(p, 800, 600);
primaryStage.setScene(s);
primaryStage.show();
}
private Node createButton() {
Button button = new Button("hello world");
button.hoverProperty().addListener((ob,ol,ne) -> {
ScaleTransition t = new
ScaleTransition(Duration.millis(500), button);
if( ne ) {
t.setFromX(1);
t.setFromY(1);
t.setToX(1.2);
t.setToY(1.2);
} else {
t.setFromX(1.2);
t.setFromY(1.2);
t.setToX(1);
t.setToY(1);
}
t.play();
});
return button;
}
public static void main(String[] args) {
launch(args);
}
}
Tom
Post by Kevin Rushforth
Any effect has the potential for slowing down depending on the size if
the node being rendered, since it is done as an image operation on the
entire area (bounding box) covered by the Parent. Have you noticed
whether DropShadow is worse than other effects, say, GaussianBlur? One
other thing to note is that caching a Parent will have no effect if the
children are animating, since it will need to be recreated each time.
-- Kevin
Post by Dirk Lemmermann
Yes, I also noticed that DropShadow causes severe performance degradation.
Dirk
Post by Tom Schindl
Hi,
Why does applying a DropShadow on a large region cause problem when
animating nodes contained in that region?
package fxbugs;
import javafx.animation.ScaleTransition;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.effect.BlurType;
import javafx.scene.effect.DropShadow;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Duration;
public class DropShadowPerformance extends Application {
    public void start(Stage primaryStage) throws Exception {
        BorderPane p = new BorderPane();
        p.setPadding(new Insets(30));
        GridPane container = new GridPane();
        container.setHgap(10);
        container.setVgap(10);
        container.setStyle("-fx-background-color: green;
-fx-padding: 10;");
        container.setEffect(new DropShadow(BlurType.GAUSSIAN,
Color.rgb(0, 0, 0, 0.3), 10, 0.5, 0, 0));
        for( int i = 0; i < 8; i++ ) {
            for( int j = 0; j < 14; j++ ) {
                container.add(createButton(), i, j);
            }
        }
        p.setCenter(container);
        Scene s = new Scene(p, 800, 600);
        primaryStage.setScene(s);
        primaryStage.show();
    }
    private Node createButton() {
        Button button = new Button("hello world");
        button.hoverProperty().addListener((ob,ol,ne) -> {
            ScaleTransition t = new
ScaleTransition(Duration.millis(500), button);
            if( ne ) {
                t.setFromX(1);
                t.setFromY(1);
                t.setToX(1.2);
                t.setToY(1.2);
            } else {
                t.setFromX(1.2);
                t.setFromY(1.2);
                t.setToX(1);
                t.setToY(1);
            }
            t.play();
        });
        return button;
    }
    public static void main(String[] args) {
        launch(args);
    }
}
* Maximize the window
* Hover over a button (eg the one in the right lower corner)
You'll notice that the animation is not smooth, setting cache flags on
the container does not improve the situation, nor does using a ONE_PASS_BOX.
Removing the effect on the container node "fixes" the problem.
This is on a MacBook Pro and Windows Surface both having a Intel Iris
Plus 650 graphics card.
Tom
--
Tom Schindl, CTO
BestSolution.at EDV Systemhaus GmbH
Eduard-Bodem-Gasse 5-7. A-6020 Innsbruck
Reg. Nr. FN 222302s am Firmenbuchgericht Innsbruck
Loading...