0 Replies Latest reply: Feb 2, 2011 4:50 AM by 836216 RSS

    Drawing slowdown after showing popup

    836216
      Hi,
      i have found mysterious slowdown in graphic drawing after showing popup that exits frame borders. Don't know if this is a bug or i'm doing something wrong. Can anyone check this?

      It is reproducible with AMD(ati) chips, don't know about others. Adding -Dsun.java2d.d3d=false makes drawing slower, but removes slowdown after popup
      Steps to reproduce:
      1. Start the program, it will output in console time used for every repaint
      2. Right click near to the bottom edge of the frame to open popup. Popup must be opened partially outside the frame, openning in center of the frame doesn't reproduce anything.
      3. Look at the repainting times in console after popup

      I have the following results:
      time to draw: 0.079728
      time to draw: 0.064673
      time to draw: 0.157063
      time to draw: 0.131399
      Showing popup
      time to draw: 94.156793
      time to draw: 40.368163
      time to draw: 43.982313
      time to draw: 47.154361

      Times with -Dsun.java2d.d3d=false are:
      time to draw: 4.288254
      time to draw: 5.001366
      time to draw: 4.158566
      time to draw: 5.349709
      time to draw: 4.113739

      This bug makes accelerated drawing 10 times slower than without acceleration :(


      Here is the code to reproduce the issue:
      package bug.test;
      
      import javax.swing.JComponent;
      import javax.swing.JFrame;
      import javax.swing.SwingUtilities;
      import javax.swing.JPopupMenu;
      import javax.swing.JMenuItem;
      import javax.swing.JMenu;
      import java.awt.Graphics;
      import java.awt.Color;
      import java.awt.Point;
      import java.awt.event.MouseMotionListener;
      import java.awt.event.MouseEvent;
      import java.awt.event.MouseListener;
      import java.awt.image.VolatileImage;
      
      public class BugTestFrame extends JFrame {
          public BugTestFrame() {
              super("Bug test");
              setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
              setContentPane(new DrawablePanel());
          }
      
          private static class DrawablePanel extends JComponent implements MouseMotionListener, MouseListener {
              private VolatileImage backBuffer;
              private Point mousePosition = new Point(0, 0);
              private int staticContentRedraws;
              private int dynamicContentRedraws;
      
              public DrawablePanel() {
                  addMouseMotionListener(this);
                  addMouseListener(this);
              }
      
              @Override
              public void paintComponent(Graphics g) {
                  long startTime = System.nanoTime();
                  reinitBackBufferIfNecessary();
                  redrawStaticContent(g);
                  redrawDynamicContent(g);
                  System.out.println("time to draw: " + ((System.nanoTime() - startTime) / 1000000d));
              }
      
              private void reinitBackBufferIfNecessary() {
                  if (backBuffer == null || backBuffer.getHeight() != getHeight() || backBuffer.getWidth() != getWidth()) {
                      createBackBuffer();
                  }
              }
      
              private void redrawStaticContent(Graphics g) {
                  do {
                      int valCode = backBuffer.validate(getGraphicsConfiguration());
                      if (valCode == VolatileImage.IMAGE_RESTORED) {
                          redrawDataOntoBackBuffer();
                      } else if (valCode == VolatileImage.IMAGE_INCOMPATIBLE) {
                          createBackBuffer();
                          redrawDataOntoBackBuffer();
                      }
                      g.drawImage(backBuffer, 0, 0, this);
                  }
                  while (backBuffer.contentsLost());
              }
      
              private void createBackBuffer() {
                  if (backBuffer != null) {
                      backBuffer.flush();
                      backBuffer = null;
                  }
                  backBuffer = createVolatileImage(getWidth(), getHeight());
              }
      
              private void redrawDataOntoBackBuffer() {
                  Graphics gBB = backBuffer.createGraphics();
                  try {
                      gBB.setColor(Color.WHITE);
                      gBB.fillRect(0, 0, backBuffer.getWidth(), backBuffer.getHeight());
                      gBB.setColor(Color.GRAY.brighter());
                      for (int h = 15; h < backBuffer.getHeight(); h += 15) {
                          gBB.drawLine(0, h, backBuffer.getWidth(), h);
                      }
                      for (int w = 15; w < backBuffer.getWidth(); w += 15) {
                          gBB.drawLine(w, 0, w, getHeight());
                      }
                      ++staticContentRedraws;
                  } finally {
                      gBB.dispose();
                  }
              }
      
              private void redrawDynamicContent(Graphics g) {
                  g.drawLine(0, mousePosition.y, getWidth(), mousePosition.y);
                  g.drawLine(mousePosition.x, 0, mousePosition.x, getHeight());
                  ++dynamicContentRedraws;
                  g.drawString("Static content redraws: " + staticContentRedraws, 10, 10);
                  g.drawString("Dynamic content redraws: " + dynamicContentRedraws, 10, 30);
              }
      
              private void showPopup(int x, int y) {
                  JPopupMenu popup = new JPopupMenu("popup menu");
                  for (int i = 1; i <= 5; i++) {
                      JMenuItem menuItem = new JMenuItem("item" + i);
                      popup.add(menuItem);
                  }
                  popup.show(this, x, y);
                  System.out.println("Showing popup");
              }
      
              public void mouseDragged(MouseEvent e) {
                  mousePosition.x = e.getX();
                  mousePosition.y = e.getY();
                  repaint();
              }
      
              public void mouseMoved(MouseEvent e) {
                  mousePosition.x = e.getX();
                  mousePosition.y = e.getY();
                  repaint();
              }
      
              public void mouseClicked(MouseEvent e) {
              }
      
              public void mousePressed(MouseEvent e) {
                  if (e.isPopupTrigger()) {
                      showPopup(e.getX(), e.getY());
                  }
              }
      
              public void mouseReleased(MouseEvent e) {
                  if (e.isPopupTrigger()) {
                      showPopup(e.getX(), e.getY());
                  }
              }
      
              public void mouseEntered(MouseEvent e) {
              }
      
              public void mouseExited(MouseEvent e) {
              }
          }
      
          public static void main(String[] args) {
              SwingUtilities.invokeLater(new Runnable() {
                  public void run() {
                      BugTestFrame frame = new BugTestFrame();
                      frame.pack();
                      frame.setSize(800, 600);
                      frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
                      frame.setVisible(true);
                  }
              });
          }
      }