Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8019590

Graphics2D.drawImage() much slower in 7u25 due to CUSTOM BufferedImage type

XMLWordPrintable

    • 2d
    • windows_7

      FULL PRODUCT VERSION :
      java version " 1.7.0_25 "
      Java(TM) SE Runtime Environment (build 1.7.0_25-b16)
      Java HotSpot(TM) Client VM (build 23.25-b01, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [Version 6.1.7601]

      A DESCRIPTION OF THE PROBLEM :
      Drawing speed has dropped dramatically due to a change in determining BufferedImage 'type'. Starting with 7u25, custom subclasses of ColorModel (et al) always produce BufferedImage type = TYPE_CUSTOM due to the addition of method BufferedImage.isStandard(). Prior to 7u25, type could be set to a value that resulted in optimized blit operations, e.g. TYPE_INT_RGB.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the given sample application against both 7u21 and 7u25.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      BufferedImage types should be the same, and drawing rates should be similar.
      ACTUAL -
      7u21: BufferedImage type is TYPE_INT_RGB, drawing rate is ~160 fps.
      7u25: BufferedImage type is TYPE_CUSTOM, drawing rate is ~40 fps.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      package com.attachmate.example;

      import javax.swing.*;
      import java.awt.*;
      import java.awt.color.ColorSpace;
      import java.awt.image.*;
      import java.lang.reflect.InvocationTargetException;
      import java.util.concurrent.TimeUnit;

      /**
       * Demonstrates poor drawing performance starting with Java 7u25.
       */
      public class DrawImageDemo
      {
          static class CustomColorModel extends DirectColorModel
          {
              public CustomColorModel(int bits, int rmask, int gmask, int bmask, int amask, boolean isAlphaPremultiplied)
              {
                  super(ColorSpace.getInstance(ColorSpace.CS_sRGB),
                        bits,
                        rmask,
                        gmask,
                        bmask,
                        amask,
                        isAlphaPremultiplied,
                        DataBuffer.TYPE_INT
                  );
              }
          }

          public static void main(String[] args) throws InvocationTargetException, InterruptedException
          {
              new DrawImageDemo().run();
          }

          private void run() throws InvocationTargetException, InterruptedException
          {
              final int width = 600;
              final int height = 600;
              final int redMask = 0x00ff0000;
              final int grnMask = 0x0000ff00;
              final int bluMask = 0x000000ff;
              final boolean isPremultipliedAlpha = false;

              final SampleModel sampleModel = new SinglePixelPackedSampleModel(
                      DataBuffer.TYPE_INT, width, height, width, new int[]{redMask, grnMask, bluMask} );

              final BufferedImage image = new BufferedImage(new CustomColorModel(24, redMask, grnMask, bluMask, 0, isPremultipliedAlpha),
                                                            Raster.createWritableRaster(sampleModel, null),
                                                            isPremultipliedAlpha,
                                                            null );

              System.out.println( " BufferedImage type = " + image.getType() + " (expecting TYPE_INT_RGB = " + BufferedImage.TYPE_INT_RGB + ')');

              final JFrame frame = new JFrame( " Demo " );
              final JPanel panel = new JPanel() {
                  protected void paintComponent(Graphics g)
                  {
                      super.paintComponent(g);
                      synchronized (image) { ((Graphics2D) g).drawImage(image, null, null); }
                  }
              };
              SwingUtilities.invokeLater(new Runnable() {
                  public void run()
                  {
                      panel.setPreferredSize(new Dimension(width, height));
                      frame.getContentPane().add(panel);
                      frame.pack();
                      frame.setVisible(true);
                  }
              });

              final Graphics2D drawingG2d = image.createGraphics();
              final long endTime = milliTime() + TimeUnit.MILLISECONDS.convert(10, TimeUnit.SECONDS);
              int frames = 0;
              while(milliTime() < endTime)
              {
                  final Color paintColor = (frames % 2 == 0) ? Color.GREEN : Color.BLUE;
                  synchronized (image)
                  {
                      drawingG2d.setPaint(paintColor);
                      drawingG2d.fillRect(0, 0, width, height);
                  }
                  SwingUtilities.invokeAndWait( new Runnable() {
                      public void run()
                      {
                          panel.paintImmediately(0, 0, width, height);
                      }
                  });
                  ++frames;
              }
              drawingG2d.dispose();

              SwingUtilities.invokeLater( new Runnable() {
                  public void run()
                  {
                      frame.setVisible(false);
                      frame.dispose();
                  }
              });

              System.out.println( " Draw rate = " + (frames / 10) + " fps " );
          }

          private long milliTime()
          {
              return TimeUnit.MILLISECONDS.convert(System.nanoTime(), TimeUnit.NANOSECONDS);
          }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Loading ColorModel subclasses via the bootclasspath may work around the problem. This may be problematic for Web Start, however.

            prr Philip Race
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            7 Start watching this issue

              Created:
              Updated: