/* JNIOverhead.java - demonstrator for classpath/gcj fillrect performance issue Copyright (C) 2006 Free Software Foundation, Inc. This file is part of GNU Classpath examples. GNU Classpath is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Classpath 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 for more details. You should have received a copy of the GNU General Public License along with GNU Classpath; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package gnu.classpath.examples.java2d; import gnu.classpath.examples.swing.DemoFactory; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.SwingUtilities; /** * @author Norman Hendrich */ public class JNIOverhead extends JPanel implements ActionListener { static JNIOverhead fillRectDemo; LCDCanvas lcd; Worker worker; JLabel label; JCheckBox translate; JCheckBox lines; int nx = 128; int ny = 64; int matrix[][], future[][]; int generation = 0; // 20 msec, or 50 repaints per sec (theoretically) int sleepMillis = 20; long lastMillis = System.currentTimeMillis(); boolean enableRepaints = true; /** * If true, test translation. */ boolean testTranslation = false; /** * If true, paint lines rather than rectangles */ boolean paintLines; public void actionPerformed(ActionEvent e) { if (e.getActionCommand().equals("CLOSE")) { System.exit(0); } } public JNIOverhead() { setSize(nx, ny); createContent(); } public void createContent() { setLayout(new BorderLayout()); JPanel p = new JPanel(new BorderLayout()); lcd = new LCDCanvas(); label = new JLabel(); label.setText("not running"); translate = new JCheckBox("translate"); translate.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { testTranslation = translate.isSelected(); } }); lines = new JCheckBox("lines"); lines.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { paintLines = lines.isSelected(); } }); JPanel bottom = new JPanel(); bottom.add(lines); bottom.add(translate); p.add(lcd, BorderLayout.CENTER); p.add(bottom, BorderLayout.SOUTH); p.add(label, BorderLayout.NORTH); add(p); } public void setSize(int _nx,int _ny ) { nx = _nx; ny = _ny; matrix = new int[nx][ny]; future = new int[nx][ny]; } public void initFrameContent() { JPanel closePanel = new JPanel(); JButton closeButton = new JButton("Close"); closeButton.setActionCommand("CLOSE"); closeButton.addActionListener(this); closePanel.add(closeButton); add(closePanel, BorderLayout.SOUTH); } public void setSleepMillis(int millis) { sleepMillis = millis; } public class LCDCanvas extends JPanel { private int sx, sy; private Color activePixel = new Color(30, 30, 40); private Color passivePixel = new Color(200, 180, 240); private Color gridPixel = new Color(255, 240, 240); public LCDCanvas() { super(); sx = 4 * nx; sy = 4 * ny; } public void paintComponent(Graphics g) { // for buffered drawing - not used atm // g.drawImage( buffer, 0, 0, null ); long t1 = System.currentTimeMillis(); g.setColor(gridPixel); g.fillRect(0, 0, sx, sy); Color pixelColor = null; int dx, dy; if (paintLines) { for (int ix = 0; ix < nx; ix++) for (int iy = 0; iy < ny; iy++) { if (matrix[ix][iy] != 0) pixelColor = activePixel; else pixelColor = passivePixel; dx = 4 * ix; dy = 4 * iy; g.setColor(pixelColor); if (testTranslation) { g.translate(dx, dy); g.drawLine(0, 0, 5, 5); g.translate(- dx, - dy); } else g.drawLine(dx, dy, dx + 5, dy + 5); } } else for (int ix = 0; ix < nx; ix++) { for (int iy = 0; iy < ny; iy++) { if (matrix[ix][iy] != 0) pixelColor = activePixel; else pixelColor = passivePixel; dx = 4 * ix; dy = 4 * iy; g.setColor(pixelColor); if (testTranslation) { g.translate(dx, dy); g.fillRect(0, 0, 3, 3); g.translate(- dx, - dy); } else g.fillRect(dx, dy, 3, 3); } } long t2 = System.currentTimeMillis(); label.setText("paintComponent took " + (t2 - t1) + " msec. " + "(" + (nx * ny + 1) + " " + (paintLines ? "drawLine" : "fillRect") + " calls)"); } public Dimension getPreferredSize() { return new Dimension(sx,sy); } public Dimension getMinimumSize() { return new Dimension(sx,sy); } } public class Worker extends Thread { public void run() { boolean running = true; while(running) { iteration(); if (enableRepaints) display(); if (sleepMillis > 0) { try { Thread.sleep( sleepMillis ); } catch(InterruptedException ie) { running = false; } } } } } /** * stupid animation algorithm: show binary representation of current * iteration. */ public void iteration() { generation++; for (int i = 0; i < nx; i++) { long tmp1 = 1L << i; for (int j = 0; j < ny; j++) { // count neighbors long tmp2 = (1L << j); long tmp3 = generation & tmp1 & tmp2; if (tmp3 != 0) matrix[i][j] = 1; else matrix[i][j] = 0; } } if ((generation % 100) == 0) { long t = System.currentTimeMillis(); // System.out.println( // " generation= " + generation + // " iterations/sec= " + 100.0*1000/(t-lastMillis) ); lastMillis = t; } } public void display() { lcd.repaint(); } public static void usage() { System.out.println( "Usage: <java> FillRect2 [-sleep <millis>] [-size <int>] [-nopaint]\n" + "Example: jamvm FillRect2 -sleep 10 -size 100\n" ); System.exit(0); } public static void main(String args[]) throws Exception { fillRectDemo = new JNIOverhead(); for (int i = 0; i < args.length; i++) { if ("-help".equals(args[i])) { usage(); } if ("-sleep".equals(args[i])) { fillRectDemo.setSleepMillis( Integer.parseInt(args[i + 1])); i++; } if ("-size".equals(args[i])) { int size = Integer.parseInt(args[i + 1]); fillRectDemo.setSize(size, size); i++; } if ("-nopaint".equals(args[i])) { fillRectDemo.enableRepaints = false; } } SwingUtilities.invokeLater (new Runnable() { public void run() { fillRectDemo.initFrameContent(); JFrame frame = new JFrame("FillRect performance test"); frame.getContentPane().add(fillRectDemo); frame.pack(); frame.show(); fillRectDemo.worker = fillRectDemo.new Worker(); fillRectDemo.worker.start(); } }); } /** * Returns a DemoFactory that creates a SliderDemo. * * @return a DemoFactory that creates a SliderDemo */ public static DemoFactory createDemoFactory() { return new DemoFactory() { public JComponent createDemo() { fillRectDemo = new JNIOverhead(); SwingUtilities.invokeLater (new Runnable() { public void run() { fillRectDemo.worker = fillRectDemo.new Worker(); fillRectDemo.worker.start(); } }); return fillRectDemo; } }; } }