Path: blob/master/test/jdk/performance/client/RenderPerfTest/src/renderperf/RenderPerfLCDTest.java
41154 views
/*1* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223package renderperf;2425import java.awt.Color;26import java.awt.Dimension;27import java.awt.Frame;28import java.awt.Graphics;29import java.awt.Graphics2D;30import java.awt.RenderingHints;31import java.awt.Robot;3233import java.awt.event.WindowAdapter;34import java.awt.event.WindowEvent;35import java.awt.geom.AffineTransform;36import java.awt.geom.Point2D;37import java.awt.geom.QuadCurve2D;38import java.awt.image.BufferedImage;39import java.io.IOException;40import java.lang.reflect.InvocationTargetException;41import java.lang.reflect.Method;42import java.util.HashSet;43import java.util.Objects;44import java.util.concurrent.CountDownLatch;45import java.util.concurrent.atomic.AtomicBoolean;4647import javax.imageio.ImageIO;48import javax.swing.JPanel;49import javax.swing.SwingUtilities;50import javax.swing.Timer;5152public class RenderPerfLCDTest {53private static HashSet<String> ignoredTests = new HashSet<>();5455private final static int N = 1000;56private final static float WIDTH = 800;57private final static float HEIGHT = 800;58private final static float R = 25;59private final static int BW = 50;60private final static int BH = 50;61private final static int COUNT = 300;62private final static int DELAY = 10;63private final static int RESOLUTION = 5;64private final static int COLOR_TOLERANCE = 10;65private final static int MAX_MEASURE_TIME = 5000;666768interface Configurable {69void configure(Graphics2D g2d);70}7172interface Renderable {73void setup(Graphics2D g2d);74void render(Graphics2D g2d);75void update();76}7778static class Particles {79private float[] bx;80private float[] by;81private float[] vx;82private float[] vy;83private float r;84private int n;8586private float x0;87private float y0;88private float width;89private float height;9091Particles(int n, float r, float x0, float y0, float width, float height) {92bx = new float[n];93by = new float[n];94vx = new float[n];95vy = new float[n];96this.n = n;97this.r = r;98this.x0 = x0;99this.y0 = y0;100this.width = width;101this.height = height;102for (int i = 0; i < n; i++) {103bx[i] = (float) (x0 + r + 0.1 + Math.random() * (width - 2 * r - 0.2 - x0));104by[i] = (float) (y0 + r + 0.1 + Math.random() * (height - 2 * r - 0.2 - y0));105vx[i] = 0.1f * (float) (Math.random() * 2 * r - r);106vy[i] = 0.1f * (float) (Math.random() * 2 * r - r);107}108109}110111void render(Graphics2D g2d, ParticleRenderer renderer) {112for (int i = 0; i < n; i++) {113renderer.render(g2d, i, bx, by, vx, vy);114}115}116117void update() {118for (int i = 0; i < n; i++) {119bx[i] += vx[i];120if (bx[i] + r > width || bx[i] - r < x0) vx[i] = -vx[i];121by[i] += vy[i];122if (by[i] + r > height || by[i] - r < y0) vy[i] = -vy[i];123}124125}126127}128129ParticleRenderable createPR(ParticleRenderer renderer) {130return new ParticleRenderable(renderer);131}132133static class ParticleRenderable implements Renderable {134ParticleRenderer renderer;135Configurable configure;136137ParticleRenderable(ParticleRenderer renderer, Configurable configure) {138this.renderer = renderer;139this.configure = configure;140}141142ParticleRenderable(ParticleRenderer renderer) {143this(renderer, null);144}145146@Override147public void setup(Graphics2D g2d) {148if (configure != null) configure.configure(g2d);149}150151@Override152public void render(Graphics2D g2d) {153balls.render(g2d, renderer);154}155156@Override157public void update() {158balls.update();159}160161public ParticleRenderable configure(Configurable configure) {162this.configure = configure;163return this;164}165}166167interface ParticleRenderer {168void render(Graphics2D g2d, int id, float[] x, float[] y, float[] vx, float[] vy);169170}171172static class WhiteTextParticleRenderer implements ParticleRenderer {173float r;174175WhiteTextParticleRenderer(float r) {176this.r = r;177}178179void setPaint(Graphics2D g2d, int id) {180g2d.setColor(Color.WHITE);181}182183@Override184public void render(Graphics2D g2d, int id, float[] x, float[] y, float[] vx, float[] vy) {185setPaint(g2d, id);186g2d.drawString("The quick brown fox jumps over the lazy dog",187(int)(x[id] - r), (int)(y[id] - r));188g2d.drawString("The quick brown fox jumps over the lazy dog",189(int)(x[id] - r), (int)y[id]);190g2d.drawString("The quick brown fox jumps over the lazy dog",191(int)(x[id] - r), (int)(y[id] + r));192}193}194195static class TextParticleRenderer extends WhiteTextParticleRenderer {196Color[] colors;197198float r;199200TextParticleRenderer(int n, float r) {201super(r);202colors = new Color[n];203this.r = r;204for (int i = 0; i < n; i++) {205colors[i] = new Color((float) Math.random(),206(float) Math.random(), (float) Math.random());207}208}209210void setPaint(Graphics2D g2d, int id) {211g2d.setColor(colors[id % colors.length]);212}213}214215static class PerfMeter {216private String name;217private int frame = 0;218219private JPanel panel;220221private long time;222private double execTime = 0;223private Color expColor = Color.RED;224AtomicBoolean waiting = new AtomicBoolean(false);225private double fps;226227PerfMeter(String name) {228this.name = name;229}230231PerfMeter exec(final Renderable renderable) throws Exception {232final CountDownLatch latch = new CountDownLatch(COUNT);233final CountDownLatch latchFrame = new CountDownLatch(1);234final long endTime = System.currentTimeMillis() + MAX_MEASURE_TIME;235236final Frame f = new Frame();237f.addWindowListener(new WindowAdapter() {238@Override239public void windowClosed(WindowEvent e) {240latchFrame.countDown();241}242});243244SwingUtilities.invokeAndWait(new Runnable() {245@Override246public void run() {247248panel = new JPanel()249{250@Override251protected void paintComponent(Graphics g) {252253super.paintComponent(g);254time = System.nanoTime();255Graphics2D g2d = (Graphics2D) g.create();256renderable.setup(g2d);257renderable.render(g2d);258g2d.setColor(expColor);259g.fillRect(0, 0, BW, BH);260}261};262263panel.setPreferredSize(new Dimension((int)(WIDTH + BW), (int)(HEIGHT + BH)));264panel.setBackground(Color.BLACK);265f.add(panel);266//f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);267f.pack();268f.setVisible(true);269}270});271Robot robot = new Robot();272273Timer timer = new Timer(DELAY, e -> {274275if (waiting.compareAndSet(false, true)) {276Color c = robot.getPixelColor(277panel.getTopLevelAncestor().getX() + panel.getTopLevelAncestor().getInsets().left + BW / 2,278panel.getTopLevelAncestor().getY() + panel.getTopLevelAncestor().getInsets().top + BW / 2);279if (isAlmostEqual(c, Color.BLUE)) {280expColor = Color.RED;281} else {282expColor = Color.BLUE;283}284renderable.update();285panel.getParent().repaint();286287} else {288while (!isAlmostEqual(289robot.getPixelColor(290panel.getTopLevelAncestor().getX() + panel.getTopLevelAncestor().getInsets().left + BW/2,291panel.getTopLevelAncestor().getY() + panel.getTopLevelAncestor().getInsets().top + BH/2),292expColor))293{294try {295Thread.sleep(RESOLUTION);296} catch (InterruptedException ex) {297ex.printStackTrace();298}299}300time = System.nanoTime() - time;301execTime += time;302frame++;303waiting.set(false);304}305306if (System.currentTimeMillis() < endTime) {307latch.countDown();308} else {309while(latch.getCount() > 0) latch.countDown();310}311});312timer.start();313latch.await();314SwingUtilities.invokeAndWait(() -> {315timer.stop();316f.setVisible(false);317f.dispose();318});319320latchFrame.await();321if (execTime != 0 && frame != 0) {322fps = 1e9 / (execTime / frame);323} else {324fps = 0;325}326327return this;328}329330private void report() {331System.err.println(name + " : " + String.format("%.2f FPS", fps));332}333334private boolean isAlmostEqual(Color c1, Color c2) {335return Math.abs(c1.getRed() - c2.getRed()) < COLOR_TOLERANCE ||336Math.abs(c1.getGreen() - c2.getGreen()) < COLOR_TOLERANCE ||337Math.abs(c1.getBlue() - c2.getBlue()) < COLOR_TOLERANCE;338339}340}341342private static final Particles balls = new Particles(N, R, BW, BH, WIDTH, HEIGHT);343private static final ParticleRenderer textRenderer = new TextParticleRenderer(N, R);344345private static final Configurable TextLCD = (Graphics2D g2d) ->346g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,347RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);348349public void testTextBubblesLCD() throws Exception {350(new PerfMeter("TextLCD")).exec(createPR(textRenderer).configure(TextLCD)).report();351}352353public static void main(String[] args)354throws InvocationTargetException, IllegalAccessException, NoSuchMethodException355{356RenderPerfLCDTest test = new RenderPerfLCDTest();357358if (args.length > 0) {359for (String testCase : args) {360Method m = RenderPerfLCDTest.class.getDeclaredMethod(testCase);361m.invoke(test);362}363} else {364Method[] methods = RenderPerfLCDTest.class.getDeclaredMethods();365for (Method m : methods) {366if (m.getName().startsWith("test") && !ignoredTests.contains(m.getName())) {367m.invoke(test);368}369}370}371}372}373374375