diff options
author | Alexey Ushakov <avu@openjdk.org> | 2019-09-05 17:35:46 +0300 |
---|---|---|
committer | Vitaly Provodin <vitaly.provodin@jetbrains.com> | 2020-06-17 09:30:02 +0700 |
commit | 8bd8d2d13251ac27eda9cad3a3449c551c11b4fd (patch) | |
tree | 8c04f987817228eb9ccc64ec6d5984dd37fc2f93 | |
parent | 9adf77a512d4de248f6186c4d19ec9daa9c25813 (diff) | |
download | JetBrainsRuntime-8bd8d2d13251ac27eda9cad3a3449c551c11b4fd.tar.gz |
8230657: Create fine grained render perf test for metal pipeline
To run the tests:
cd src/demo/share/java2d/RenderPerfTest
sh gradlew test -i
or
sh gradlew test --tests *testWiredBoxBubbles* -i
-rw-r--r-- | src/demo/share/java2d/RenderPerfTest/build.gradle | 58 | ||||
-rw-r--r-- | src/demo/share/java2d/RenderPerfTest/gradle/wrapper/gradle-wrapper.jar | bin | 0 -> 55190 bytes | |||
-rw-r--r-- | src/demo/share/java2d/RenderPerfTest/gradle/wrapper/gradle-wrapper.properties | 5 | ||||
-rw-r--r-- | src/demo/share/java2d/RenderPerfTest/gradlew | 172 | ||||
-rw-r--r-- | src/demo/share/java2d/RenderPerfTest/gradlew.bat | 84 | ||||
-rw-r--r-- | src/demo/share/java2d/RenderPerfTest/src/test/java/RenderPerfTest.java | 825 | ||||
-rw-r--r-- | src/demo/share/java2d/RenderPerfTest/src/test/resources/images/duke.png | bin | 0 -> 2124 bytes |
7 files changed, 1144 insertions, 0 deletions
diff --git a/src/demo/share/java2d/RenderPerfTest/build.gradle b/src/demo/share/java2d/RenderPerfTest/build.gradle new file mode 100644 index 00000000000..bb65ec2448a --- /dev/null +++ b/src/demo/share/java2d/RenderPerfTest/build.gradle @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +apply plugin: 'java' + +repositories { + mavenCentral() +} + +dependencies { + testCompile('junit:junit:4.12'){ + exclude group: 'org.hamcrest' + } + testCompile 'org.hamcrest:hamcrest-library:1.3' + testCompile 'org.apache.commons:commons-lang3:3.0' +} + +def test_jvm = { + if (project.hasProperty('jdkhome')) { + file(jdkhome + (org.gradle.internal.os.OperatingSystem.current().isWindows()?"/bin/java.exe" : "/bin/java")).absolutePath + } else { + if (org.gradle.internal.os.OperatingSystem.current().isMacOsX()) { + file('../../../../../build/macosx-x86_64-server-release/jdk/bin/java').absolutePath + } else if (org.gradle.internal.os.OperatingSystem.current().isLinux()) { + file('../../../../../build/linux-x86_64-server-release/jdk/bin/java').absolutePath + } else { + file('../../../../../build/windows-x86_64-server-release/jdk/bin/java.exe').absolutePath + } + } +} + +test { + systemProperty "sun.java2d.metal", "true" + executable = test_jvm() + outputs.upToDateWhen { false } +}
\ No newline at end of file diff --git a/src/demo/share/java2d/RenderPerfTest/gradle/wrapper/gradle-wrapper.jar b/src/demo/share/java2d/RenderPerfTest/gradle/wrapper/gradle-wrapper.jar Binary files differnew file mode 100644 index 00000000000..87b738cbd05 --- /dev/null +++ b/src/demo/share/java2d/RenderPerfTest/gradle/wrapper/gradle-wrapper.jar diff --git a/src/demo/share/java2d/RenderPerfTest/gradle/wrapper/gradle-wrapper.properties b/src/demo/share/java2d/RenderPerfTest/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000000..44e7c4d1d7b --- /dev/null +++ b/src/demo/share/java2d/RenderPerfTest/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/src/demo/share/java2d/RenderPerfTest/gradlew b/src/demo/share/java2d/RenderPerfTest/gradlew new file mode 100644 index 00000000000..af6708ff229 --- /dev/null +++ b/src/demo/share/java2d/RenderPerfTest/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/src/demo/share/java2d/RenderPerfTest/gradlew.bat b/src/demo/share/java2d/RenderPerfTest/gradlew.bat new file mode 100644 index 00000000000..0f8d5937c4a --- /dev/null +++ b/src/demo/share/java2d/RenderPerfTest/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/src/demo/share/java2d/RenderPerfTest/src/test/java/RenderPerfTest.java b/src/demo/share/java2d/RenderPerfTest/src/test/java/RenderPerfTest.java new file mode 100644 index 00000000000..a1adb4911c6 --- /dev/null +++ b/src/demo/share/java2d/RenderPerfTest/src/test/java/RenderPerfTest.java @@ -0,0 +1,825 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import org.junit.Ignore; +import org.junit.Test; + +import javax.imageio.ImageIO; +import javax.swing.*; +import java.awt.*; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.awt.geom.QuadCurve2D; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.Objects; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicBoolean; + + +public class RenderPerfTest { + private final static int N = 1000; + private final static float WIDTH = 800; + private final static float HEIGHT = 800; + private final static float R = 25; + private final static int BW = 50; + private final static int BH = 50; + private final static int COUNT = 300; + private final static int DELAY = 10; + private final static int RESOLUTION = 5; + private final static int COLOR_TOLERANCE = 10; + + + interface Renderable { + void render(Graphics2D g2d); + void update(); + } + + static class Particles { + private float[] bx; + private float[] by; + private float[] vx; + private float[] vy; + private float r; + private int n; + + private float x0; + private float y0; + private float width; + private float height; + + Particles(int n, float r, float x0, float y0, float width, float height) { + bx = new float[n]; + by = new float[n]; + vx = new float[n]; + vy = new float[n]; + this.n = n; + this.r = r; + this.x0 = x0; + this.y0 = y0; + this.width = width; + this.height = height; + for (int i = 0; i < n; i++) { + bx[i] = (float) (x0 + r + 0.1 + Math.random() * (width - 2 * r - 0.2 - x0)); + by[i] = (float) (y0 + r + 0.1 + Math.random() * (height - 2 * r - 0.2 - y0)); + vx[i] = 0.1f * (float) (Math.random() * 2 * r - r); + vy[i] = 0.1f * (float) (Math.random() * 2 * r - r); + } + + } + + void render(Graphics2D g2d, ParticleRenderer renderer) { + for (int i = 0; i < n; i++) { + renderer.render(g2d, i, bx, by, vx, vy); + } + } + + void update() { + for (int i = 0; i < n; i++) { + bx[i] += vx[i]; + if (bx[i] + r > width || bx[i] - r < x0) vx[i] = -vx[i]; + by[i] += vy[i]; + if (by[i] + r > height || by[i] - r < y0) vy[i] = -vy[i]; + } + + } + } + + interface ParticleRenderer { + void render(Graphics2D g2d, int id, float[] x, float[] y, float[] vx, float[] vy); + + } + + private static void report(String name, double value) { + System.err.println(name + " : " + String.format("%.2f FPS", value)); + } + + static class FlatParticleRenderer implements ParticleRenderer { + Color[] colors; + float r; + + FlatParticleRenderer(int n, float r) { + colors = new Color[n]; + this.r = r; + for (int i = 0; i < n; i++) { + colors[i] = new Color((float) Math.random(), + (float) Math.random(), (float) Math.random()); + } + } + + @Override + public void render(Graphics2D g2d, int id, float[] x, float[] y, float[] vx, float[] vy) { + g2d.setColor(colors[id % colors.length]); + g2d.fillOval((int)(x[id] - r), (int)(y[id] - r), (int)(2*r), (int)(2*r)); + } + + } + + static class WhiteTextParticleRenderer implements ParticleRenderer { + float r; + Object hint; + + WhiteTextParticleRenderer(float r, Object hint) { + this.r = r; + this.hint = hint; + } + + void setPaint(Graphics2D g2d, int id) { + g2d.setColor(Color.WHITE); + } + + @Override + public void render(Graphics2D g2d, int id, float[] x, float[] y, float[] vx, float[] vy) { + g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, hint); + + setPaint(g2d, id); + g2d.drawString("The quick brown fox jumps over the lazy dog", + (int)(x[id] - r), (int)(y[id] - r)); + g2d.drawString("The quick brown fox jumps over the lazy dog", + (int)(x[id] - r), (int)y[id]); + g2d.drawString("The quick brown fox jumps over the lazy dog", + (int)(x[id] - r), (int)(y[id] + r)); + } + } + + static class TextParticleRenderer extends WhiteTextParticleRenderer { + Color[] colors; + + float r; + + TextParticleRenderer(int n, float r, Object hint) { + super(r, hint); + colors = new Color[n]; + this.r = r; + for (int i = 0; i < n; i++) { + colors[i] = new Color((float) Math.random(), + (float) Math.random(), (float) Math.random()); + } + } + + void setPaint(Graphics2D g2d, int id) { + g2d.setColor(colors[id % colors.length]); + } + } + + static class FlatOvalRotParticleRenderer extends FlatParticleRenderer { + + + FlatOvalRotParticleRenderer(int n, float r) { + super(n, r); + } + + void setPaint(Graphics2D g2d, int id) { + g2d.setColor(colors[id % colors.length]); + } + + @Override + public void render(Graphics2D g2d, int id, float[] x, float[] y, float[] vx, float[] vy) { + setPaint(g2d, id); + if (Math.abs(vx[id] + vy[id]) > 0.001) { + AffineTransform t = (AffineTransform) g2d.getTransform().clone(); + double l = vx[id] / Math.sqrt(vx[id] * vx[id] + vy[id] * vy[id]); + if (vy[id] < 0) { + l = -l; + } + g2d.translate(x[id], y[id]); + g2d.rotate(Math.acos(l)); + g2d.fillOval(-(int)r, (int)(-0.5*r), (int) (2 * r), (int)r); + g2d.setTransform(t); + } else { + g2d.fillOval((int)(x[id] - r), (int)(y[id] - 0.5*r), + (int) (2 * r), (int) r); + } + } + } + + static class LinGradOvalRotParticleRenderer extends FlatOvalRotParticleRenderer { + + + LinGradOvalRotParticleRenderer(int n, float r) { + super(n, r); + } + + @Override + void setPaint(Graphics2D g2d, int id) { + Point2D start = new Point2D.Double(- r, - 0.5*r); + Point2D end = new Point2D.Double( 2 * r, r); + float[] dist = {0.0f, 1.0f}; + Color[] cls = {colors[id %colors.length], colors[(colors.length - id) %colors.length]}; + LinearGradientPaint p = + new LinearGradientPaint(start, end, dist, cls); + g2d.setPaint(p); + } + } + + static class FlatBoxParticleRenderer extends FlatParticleRenderer { + + + FlatBoxParticleRenderer(int n, float r) { + super(n, r); + } + @Override + public void render(Graphics2D g2d, int id, float[] x, float[] y, float[] vx, float[] vy) { + g2d.setColor(colors[id % colors.length]); + g2d.fillRect((int)(x[id] - r), (int)(y[id] - r), (int)(2*r), (int)(2*r)); + + } + + } + + static class ImgParticleRenderer extends FlatParticleRenderer { + BufferedImage dukeImg; + + ImgParticleRenderer(int n, float r) { + super(n, r); + try { + File dukeFile = new File(Objects.requireNonNull( + RenderPerfTest.class.getClassLoader().getResource("images/duke.png")).toURI()); + + if (!dukeFile.exists()) throw new RuntimeException(dukeFile.toString() + " not found"); + + + dukeImg = ImageIO.read(dukeFile); + } catch (IOException | URISyntaxException e) { + throw new RuntimeException(e); + } + } + + @Override + public void render(Graphics2D g2d, int id, float[] x, float[] y, float[] vx, float[] vy) { + g2d.setColor(colors[id % colors.length]); + g2d.drawImage(dukeImg, (int)(x[id] - r), (int)(y[id] - r), (int)(2*r), (int)(2*r), null); + } + + } + + static class FlatBoxRotParticleRenderer extends FlatParticleRenderer { + + + FlatBoxRotParticleRenderer(int n, float r) { + super(n, r); + } + @Override + public void render(Graphics2D g2d, int id, float[] x, float[] y, float[] vx, float[] vy) { + g2d.setColor(colors[id % colors.length]); + if (Math.abs(vx[id] + vy[id]) > 0.001) { + AffineTransform t = (AffineTransform) g2d.getTransform().clone(); + double l = vx[id] / Math.sqrt(vx[id] * vx[id] + vy[id] * vy[id]); + if (vy[id] < 0) { + l = -l; + } + g2d.translate(x[id], y[id]); + g2d.rotate(Math.acos(l)); + g2d.fillRect(-(int)r, -(int)r, (int) (2 * r), (int) (2 * r)); + g2d.setTransform(t); + } else { + g2d.fillRect((int)(x[id] - r), (int)(y[id] - r), + (int) (2 * r), (int) (2 * r)); + } + } + } + + static class WiredParticleRenderer extends FlatParticleRenderer { + + + WiredParticleRenderer(int n, float r) { + super(n, r); + } + @Override + public void render(Graphics2D g2d, int id, float[] x, float[] y, float[] vx, float[] vy) { + g2d.setColor(colors[id % colors.length]); + g2d.drawOval((int)(x[id] - r), (int)(y[id] - r), (int)(2*r), (int)(2*r)); + } + + } + static class WiredBoxParticleRenderer extends FlatParticleRenderer { + + WiredBoxParticleRenderer(int n, float r) { + super(n, r); + } + + @Override + public void render(Graphics2D g2d, int id, float[] x, float[] y, float[] vx, float[] vy) { + g2d.setColor(colors[id % colors.length]); + g2d.drawRect((int)(x[id] - r), (int)(y[id] - r), (int)(2*r), (int)(2*r)); + } + + } + static class SegParticleRenderer extends FlatParticleRenderer { + + SegParticleRenderer(int n, float r) { + super(n, r); + } + + @Override + public void render(Graphics2D g2d, int id, float[] x, float[] y, float[] vx, float[] vy) { + double v = Math.sqrt(vx[id]*vx[id]+vy[id]*vy[id]); + float nvx = (float) (vx[id]/v); + float nvy = (float) (vy[id]/v); + g2d.setColor(colors[id % colors.length]); + g2d.drawLine((int)(x[id] - r*nvx), (int)(y[id] - r*nvy), + (int)(x[id] + 2*r*nvx), (int)(y[id] + 2*r*nvy)); + } + + } + + + static class WiredQuadParticleRenderer extends FlatParticleRenderer { + + WiredQuadParticleRenderer(int n, float r) { + super(n, r); + } + + @Override + public void render(Graphics2D g2d, int id, float[] x, float[] y, float[] vx, float[] vy) { + if (id > 2 && (id % 3) == 0) { + g2d.setColor(colors[id % colors.length]); + g2d.draw(new QuadCurve2D.Float(x[id-3], y[id-3], x[id-2], y[id-2], x[id-1], y[id-1])); + } + + } + } + + static class FlatQuadParticleRenderer extends FlatParticleRenderer { + + FlatQuadParticleRenderer(int n, float r) { + super(n, r); + } + + @Override + public void render(Graphics2D g2d, int id, float[] x, float[] y, float[] vx, float[] vy) { + if (id > 2 && (id % 3) == 0) { + g2d.setColor(colors[id % colors.length]); + g2d.fill(new QuadCurve2D.Float(x[id-3], y[id-3], x[id-2], y[id-2], x[id-1], y[id-1])); + } + + } + } + + static class PerfMeter { + + private int frame = 0; + + private JPanel panel; + + private long time; + private double execTime = 0; + private Color expColor = Color.RED; + AtomicBoolean waiting = new AtomicBoolean(false); + + double exec(final Renderable renderable) throws Exception { + final CountDownLatch latch = new CountDownLatch(COUNT); + final CountDownLatch latchFrame = new CountDownLatch(1); + + final JFrame f = new JFrame(); + f.addWindowListener(new WindowAdapter() { + @Override + public void windowClosed(WindowEvent e) { + latchFrame.countDown(); + } + }); + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + + panel = new JPanel() + { + @Override + protected void paintComponent(Graphics g) { + + super.paintComponent(g); + time = System.nanoTime(); + Graphics2D g2d = (Graphics2D) g; + renderable.render(g2d); + g2d.setColor(expColor); + g.fillRect(0, 0, BW, BH); + } + }; + + panel.setPreferredSize(new Dimension((int)(WIDTH + BW), (int)(HEIGHT + BH))); + panel.setBackground(Color.BLACK); + f.add(panel); + f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + f.pack(); + f.setVisible(true); + } + }); + Robot robot = new Robot(); + + Timer timer = new Timer(DELAY, e -> { + + if (waiting.compareAndSet(false, true)) { + Color c = robot.getPixelColor( + panel.getTopLevelAncestor().getX() + panel.getTopLevelAncestor().getInsets().left + BW / 2, + panel.getTopLevelAncestor().getY() + panel.getTopLevelAncestor().getInsets().top + BW / 2); + if (isAlmostEqual(c, Color.BLUE)) { + expColor = Color.RED; + } else { + expColor = Color.BLUE; + } + renderable.update(); + panel.getParent().repaint(); + + } else { + while (!isAlmostEqual( + robot.getPixelColor( + panel.getTopLevelAncestor().getX() + panel.getTopLevelAncestor().getInsets().left + BW/2, + panel.getTopLevelAncestor().getY() + panel.getTopLevelAncestor().getInsets().top + BH/2), + expColor)) + { + try { + Thread.sleep(RESOLUTION); + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + } + time = System.nanoTime() - time; + execTime += time; + frame++; + waiting.set(false); + } + + latch.countDown(); + }); + timer.start(); + latch.await(); + SwingUtilities.invokeAndWait(() -> { + timer.stop(); + f.setVisible(false); + f.dispose(); + }); + + latchFrame.await(); + return 1e9/(execTime / frame); + } + + private boolean isAlmostEqual(Color c1, Color c2) { + return Math.abs(c1.getRed() - c2.getRed()) < COLOR_TOLERANCE || + Math.abs(c1.getGreen() - c2.getGreen()) < COLOR_TOLERANCE || + Math.abs(c1.getBlue() - c2.getBlue()) < COLOR_TOLERANCE; + + } + } + + private static final Particles balls = new Particles(N, R, BW, BH, WIDTH, HEIGHT); + private static final ParticleRenderer flatRenderer = new FlatParticleRenderer(N, R); + private static final ParticleRenderer flatOvalRotRenderer = new FlatOvalRotParticleRenderer(N, R); + private static final ParticleRenderer flatBoxRenderer = new FlatBoxParticleRenderer(N, R); + private static final ParticleRenderer flatBoxRotRenderer = new FlatBoxRotParticleRenderer(N, R); + private static final ParticleRenderer linGradOvalRotRenderer = new LinGradOvalRotParticleRenderer(N, R); + private static final ParticleRenderer wiredRenderer = new WiredParticleRenderer(N, R); + private static final ParticleRenderer wiredBoxRenderer = new WiredBoxParticleRenderer(N, R); + private static final ParticleRenderer segRenderer = new SegParticleRenderer(N, R); + private static final ParticleRenderer flatQuadRenderer = new FlatQuadParticleRenderer(N, R); + private static final ParticleRenderer wiredQuadRenderer = new WiredQuadParticleRenderer(N, R); + private static final ParticleRenderer imgRenderer = new ImgParticleRenderer(N, R); + private static final ParticleRenderer textRendererNoAA = + new TextParticleRenderer(N, R, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); + private static final ParticleRenderer textRendererLCD = + new TextParticleRenderer(N, R, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB); + private static final ParticleRenderer textRendererGray = + new TextParticleRenderer(N, R, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + + private static final ParticleRenderer whiteTextRendererNoAA = + new WhiteTextParticleRenderer(R, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); + private static final ParticleRenderer whiteTextRendererLCD = + new WhiteTextParticleRenderer(R, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB); + private static final ParticleRenderer whiteTextRendererGray = + new WhiteTextParticleRenderer(R, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + + + @Test + public void testFlatBubbles() throws Exception { + + double fps = (new PerfMeter()).exec(new Renderable() { + @Override + public void render(Graphics2D g2d) { + balls.render(g2d, flatRenderer); + } + + @Override + public void update() { + balls.update(); + } + }); + + report("FlatOval", fps); + } + + @Test + public void testFlatBoxBubbles() throws Exception { + + double fps = (new PerfMeter()).exec(new Renderable() { + @Override + public void render(Graphics2D g2d) { + balls.render(g2d, flatBoxRenderer); + } + + @Override + public void update() { + balls.update(); + } + }); + + report("FlatBox", fps); + } + + @Test + public void testImgBubbles() throws Exception { + + double fps = (new PerfMeter()).exec(new Renderable() { + @Override + public void render(Graphics2D g2d) { + balls.render(g2d, imgRenderer); + } + + @Override + public void update() { + balls.update(); + } + }); + + report("Image", fps); + } + + @Test + public void testFlatBoxRotBubbles() throws Exception { + + double fps = (new PerfMeter()).exec(new Renderable() { + @Override + public void render(Graphics2D g2d) { + balls.render(g2d, flatBoxRotRenderer); + } + + @Override + public void update() { + balls.update(); + } + }); + + report("RotatedBox", fps); + } + + @Test + public void testFlatOvalRotBubbles() throws Exception { + + double fps = (new PerfMeter()).exec(new Renderable() { + @Override + public void render(Graphics2D g2d) { + balls.render(g2d, flatOvalRotRenderer); + } + + @Override + public void update() { + balls.update(); + } + }); + + report("RotatedOval", fps); + } + + @Test + public void testLinGradOvalRotBubbles() throws Exception { + + double fps = (new PerfMeter()).exec(new Renderable() { + @Override + public void render(Graphics2D g2d) { + balls.render(g2d, linGradOvalRotRenderer); + } + + @Override + public void update() { + balls.update(); + } + }); + + report("LinGradRotatedOval", fps); + } + + + @Test + public void testWiredBubbles() throws Exception { + + double fps = (new PerfMeter()).exec(new Renderable() { + @Override + public void render(Graphics2D g2d) { + balls.render(g2d, wiredRenderer); + } + + @Override + public void update() { + balls.update(); + } + }); + + report("WiredOval", fps); + } + + @Test + public void testWiredBoxBubbles() throws Exception { + + double fps = (new PerfMeter()).exec(new Renderable() { + @Override + public void render(Graphics2D g2d) { + balls.render(g2d, wiredBoxRenderer); + } + + @Override + public void update() { + balls.update(); + } + }); + + report("WiredBox", fps); + } + + @Test + public void testLines() throws Exception { + + double fps = (new PerfMeter()).exec(new Renderable() { + @Override + public void render(Graphics2D g2d) { + balls.render(g2d, segRenderer); + } + + @Override + public void update() { + balls.update(); + } + }); + + report("Lines", fps); + } + + @Test + public void testFlatQuad() throws Exception { + + double fps = (new PerfMeter()).exec(new Renderable() { + @Override + public void render(Graphics2D g2d) { + balls.render(g2d, flatQuadRenderer); + } + + @Override + public void update() { + balls.update(); + } + }); + + report("FlatQuad", fps); + } + + @Test + public void testWiredQuad() throws Exception { + + double fps = (new PerfMeter()).exec(new Renderable() { + @Override + public void render(Graphics2D g2d) { + balls.render(g2d, wiredQuadRenderer); + } + + @Override + public void update() { + balls.update(); + } + }); + + report("WiredQuad", fps); + } + + @Ignore @Test + public void testTextBubblesNoAA() throws Exception { + + double fps = (new PerfMeter()).exec(new Renderable() { + @Override + public void render(Graphics2D g2d) { + balls.render(g2d, textRendererNoAA); + } + + @Override + public void update() { + balls.update(); + } + }); + + report("TextNoAA", fps); + } + + @Ignore @Test + public void testTextBubblesLCD() throws Exception { + + double fps = (new PerfMeter()).exec(new Renderable() { + @Override + public void render(Graphics2D g2d) { + balls.render(g2d, textRendererLCD); + } + + @Override + public void update() { + balls.update(); + } + }); + + report("TextLCD", fps); + } + + @Ignore @Test + public void testTextBubblesGray() throws Exception { + + double fps = (new PerfMeter()).exec(new Renderable() { + @Override + public void render(Graphics2D g2d) { + balls.render(g2d, textRendererGray); + } + + @Override + public void update() { + balls.update(); + } + }); + + report("TextGray", fps); + } + + @Ignore @Test + public void testWhiteTextBubblesNoAA() throws Exception { + + double fps = (new PerfMeter()).exec(new Renderable() { + @Override + public void render(Graphics2D g2d) { + balls.render(g2d, whiteTextRendererNoAA); + } + + @Override + public void update() { + balls.update(); + } + }); + + report("WhiteTextNoAA", fps); + } + + @Ignore @Test + public void testWhiteTextBubblesLCD() throws Exception { + + double fps = (new PerfMeter()).exec(new Renderable() { + @Override + public void render(Graphics2D g2d) { + balls.render(g2d, whiteTextRendererLCD); + } + + @Override + public void update() { + balls.update(); + } + }); + + report("WhiteTextLCD", fps); + } + + @Ignore @Test + public void testWhiteTextBubblesGray() throws Exception { + + double fps = (new PerfMeter()).exec(new Renderable() { + @Override + public void render(Graphics2D g2d) { + balls.render(g2d, whiteTextRendererGray); + } + + @Override + public void update() { + balls.update(); + } + }); + + report("WhiteTextGray", fps); + } + +} diff --git a/src/demo/share/java2d/RenderPerfTest/src/test/resources/images/duke.png b/src/demo/share/java2d/RenderPerfTest/src/test/resources/images/duke.png Binary files differnew file mode 100644 index 00000000000..9a52fa05b41 --- /dev/null +++ b/src/demo/share/java2d/RenderPerfTest/src/test/resources/images/duke.png |