Hi Jessica,

we found this problem too and it’s very very disappointing. A real world 
desktop application on JDK 7 or 8 on a Mac doesn’t perform well - it’s tooo 
slow and we can’t ship our software with JDK 7 or 8 using BufferedImages. In 
our opinion JDK7/8 is not ready to release on Mac! But it is released! So why I 
can’t find thousand of bug reports concerning „BufferedImages on JDK7/8 on Mac 
are not hardware accelerated“????

Jessica, did you find any solution for the problem? Maybe there is a property 
to enable the VolatileImage backed BufferedImage?

Best,
Tobi


Am 24.06.2013 um 20:09 schrieb Jessica Finley <jfin...@tech4learning.com>:

> Hiya folks,
> 
> I've run into a couple of problems with OpenJDK on Mac.  Firstly, and what 
> started me down this path, is the performance of rendering BufferedImages 
> seems to have really tanked.  It's as if they are not supported by hardware 
> anymore (from vague references I've seen around the web, I understand that 
> BufferedImages are supposed to be hardware accelerated.. and based on the 
> performance on Windows (java 7) and Mac Java 6, I can believe that).  In 
> OpenJDK 7 and 8, rendering lots of BufferedImages causes performance to truly 
> and horribly suffer on certain Macs (the Macs with the low end graphics cards 
> really seem to show this, but it's noticeable on all Macs I've tested on).
> 
> In an effort to speed up our software, I started using VolatileImages instead 
> of BufferedImages in certain places and it has brought performance up to 
> awesome.  However, I noticed the problem that I describe in Sun Bug Id: 
> 9004409.  When I paint VolatileImage.getSnapshot() to either the screen 
> graphics or to a BufferedImage, the transparent pixels are rendered 
> incorrectly - they have black values instead of transparent values, as if the 
> transparent pixels were first rendered over a solid black background and then 
> the result is what is copied out to the BufferedImage.
> 
> Now, if I render the VolatileImage directly to the screen graphics, I don't 
> see the problem, but any way I can figure out how to render the VolatileImage 
> to or as a BufferedImage results in incorrect transparent pixels.
> 
> Below is a sample program that demonstrates the problem and compares it to 
> BufferedImages which always render correctly.  
> 
> This problem only occurs on Mac Java 7 and 8… all works as expected on 
> Windows Java 7 and Mac Java 6.
> 
> Any thoughts on this?  Is there a work around anyone knows of?  Also, am I 
> correct in my conjecture that BufferedImages are supposed to be hardware 
> accelerated, but they are not in OpenJDK?
> 
> Thanks for your time,
> Jess
> 
> ----------------------------------------
> 
> import java.awt.AlphaComposite;
> import java.awt.BorderLayout;
> import java.awt.Color;
> import java.awt.Dimension;
> import java.awt.Graphics2D;
> import java.awt.GraphicsConfiguration;
> import java.awt.GraphicsEnvironment;
> import java.awt.GridBagConstraints;
> import java.awt.GridBagLayout;
> import java.awt.Insets;
> import java.awt.Transparency;
> import java.awt.event.ActionEvent;
> import java.awt.event.ActionListener;
> import java.awt.image.BufferedImage;
> import java.awt.image.VolatileImage;
> 
> import javax.swing.JButton;
> import javax.swing.JFrame;
> import javax.swing.JLabel;
> import javax.swing.JPanel;
> import javax.swing.SwingUtilities;
> 
> /**
> * Shows the difference between the painting of a translucent BufferedImage 
> and a translucent
> * VolatileImage.
> * 
> * 
> * On Java 6, this works fine.  On Java 7, the VolatileImages are not painted 
> correctly, when painted
> * onto a BufferedImage prior to being painted to screen graphics.
> * 
> * @author jfinley
> *
> */
> public class PaintTest {
> 
>       public PaintTest() {
>               
>               JPanel bufferedImagePanel = new JPanel() {
>                       protected void paintComponent(java.awt.Graphics g) {
>                               super.paintComponent(g);
>                               BufferedImage image = getBufferedImage();
>                               g.drawImage(image, 0, 0, null);
>                       };
>               };
> 
>               JPanel bufferedImagePanel2 = new JPanel() {
>                       protected void paintComponent(java.awt.Graphics g) {
>                               super.paintComponent(g);
>                               BufferedImage bImage = getBufferedImage();
>                               
>                               BufferedImage image = new BufferedImage(100, 
> 100, BufferedImage.TYPE_INT_ARGB);
>                               Graphics2D g2 = image.createGraphics();
>                               
>                               //not really necessary, but in there for 
> completeness
>                               g2.setComposite(AlphaComposite.Clear);
>                               g2.setColor(new Color(255, 255, 255, 0));
>                               g2.fillRect(0,0, image.getWidth(), 
> image.getHeight());
>                               
>                               g2.setComposite(AlphaComposite.SrcOver);
>                               g2.drawImage(bImage,  0, 0, null);
>                               g2.dispose();
>                               
>                               g.drawImage(image, 0, 0, null);
>                       };
>               };
>               
>               JPanel volatileImagePanel = new JPanel() {
>                       protected void paintComponent(java.awt.Graphics g) {
>                               super.paintComponent(g);
>                               VolatileImage vImage = getVolatileImage();
>                               
>                               /**
>                                * If we draw the VolatileImage directly to g, 
> it works fine... but
>                                * if we draw VolatileImage.getSnapshot(), or 
> otherwise convert the VolatileImage
>                                * to a buffered image, we get the black halo 
> funk of death.
>                                */
>                               g.drawImage(vImage, 0, 0, null); //works
>                               //g.drawImage(vImage.getSnapshot(), 0, 0, 
> null); //black halo funk of death
>                       };
>               };
>               
>               JPanel volatileImagePanel2 = new JPanel() {
>                       protected void paintComponent(java.awt.Graphics g) {
>                               super.paintComponent(g);
>                               VolatileImage vImage = getVolatileImage();
>                               
>                               /**
>                                * If we draw the VolatileImage directly to g, 
> it works fine... but
>                                * if we draw VolatileImage.getSnapshot(), or 
> otherwise convert the VolatileImage
>                                * to a buffered image, we get the black halo 
> funk of death.
>                                */
>                               //g.drawImage(vImage, 0, 0, null); //works
>                               g.drawImage(vImage.getSnapshot(), 0, 0, null); 
> //black halo funk of death
>                       };
>               };
>               
>               JPanel volatileImagePanel3 = new JPanel() {
>                       protected void paintComponent(java.awt.Graphics g) {
>                               super.paintComponent(g);
>                               VolatileImage vImage = getVolatileImage();
>                               
>                               /**
>                                * If we draw the VolatileImage directly to g, 
> it works fine... but
>                                * if we draw VolatileImage.getSnapshot(), or 
> otherwise convert the VolatileImage
>                                * to a buffered image, we get the black halo 
> funk of death.
>                                */
>                               //g.drawImage(vImage, 0, 0, null); //works
>                               //g.drawImage(vImage.getSnapshot(), 0, 0, 
> null); //black halo funk of death
>                               
>                               BufferedImage image = new BufferedImage(100, 
> 100, BufferedImage.TYPE_INT_ARGB);
>                               Graphics2D g2 = image.createGraphics();
>                               
>                               //not really necessary, but in there for 
> completeness
>                               g2.setComposite(AlphaComposite.Clear);
>                               g2.setColor(new Color(255, 255, 255, 0));
>                               g2.fillRect(0,0, image.getWidth(), 
> image.getHeight());
>                               
>                               g2.setComposite(AlphaComposite.SrcOver);
>                               g2.drawImage(vImage,  0, 0, null);
>                               g2.dispose();
>                               
>                               g.drawImage(image, 0, 0, null);
>                       };
>               };
> 
>               final JPanel mainPanel = new JPanel(new GridBagLayout());
>               GridBagConstraints gbc = new GridBagConstraints(0, 1, 1, 1, 0, 
> 0, 
>                               GridBagConstraints.CENTER, 
> GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0);
> 
>               mainPanel.add(new JLabel("Direct to g"), gbc);
>               gbc.gridy++;
>               mainPanel.add(new JLabel("BufferImage Proxy"), gbc);
>               gbc.gridy++;
>               mainPanel.add(new JLabel("BufferImage Proxy 2"), gbc);
>               
>               gbc.gridx = 1; gbc.gridy = 0;
>               mainPanel.add(new JLabel("BufferedImages"), gbc);
>               gbc.gridx++;
>               mainPanel.add(new JLabel("VolatileImages"), gbc);
> 
>               gbc.gridx = 1; gbc.gridy = 1; gbc.weightx = 1; gbc.weighty = 1;
>               mainPanel.add(bufferedImagePanel, gbc);
>               gbc.gridy++;
>               mainPanel.add(bufferedImagePanel2, gbc);
>               gbc.gridx = 2; gbc.gridy = 1;
>               mainPanel.add(volatileImagePanel, gbc);
>               gbc.gridy++;
>               mainPanel.add(volatileImagePanel2, gbc);
>               gbc.gridy++;
>               mainPanel.add(volatileImagePanel3, gbc);
> 
>               
>               JButton repaintButton = new JButton("Repaint");
>               repaintButton.addActionListener(new ActionListener(){
>                       public void actionPerformed(ActionEvent e) {
>                               mainPanel.repaint();
>                       }
>               });
>               
>               gbc.gridx = 1; gbc.gridy++; gbc.gridwidth = 2; gbc.weighty = 0;
>               mainPanel.add(repaintButton, gbc);
> 
> 
>               JFrame mainFrame = new JFrame("O.M.G.");
>               mainFrame.getContentPane().setLayout(new BorderLayout());
>               mainFrame.getContentPane().add(mainPanel, BorderLayout.CENTER);
>               mainFrame.setPreferredSize(new Dimension(400, 400));
>               mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
>               mainFrame.pack();
>               mainFrame.setVisible(true);
>               
>       }
>       
>       private BufferedImage getBufferedImage() {
>               BufferedImage image = new BufferedImage(100, 100, 
> BufferedImage.TRANSLUCENT);
>               Graphics2D g = image.createGraphics();
>               
>               //not really necessary, in here for completeness
>               g.setComposite(AlphaComposite.Clear);
>               g.setColor(new Color(255, 255, 255, 0));
>               g.fillRect(0,0, image.getWidth(), image.getHeight());
>               
>               g.setComposite(AlphaComposite.SrcOver);
>               g.setColor(new Color(255, 0, 0, 128));
>               g.fillRect(10, 10, image.getWidth()-20, image.getHeight()-20);
> 
>               g.dispose();
>               return image;
>       }
> 
>       private VolatileImage getVolatileImage() {
>               GraphicsConfiguration gc = 
> GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
>               VolatileImage vImage = gc.createCompatibleVolatileImage(100, 
> 100, Transparency.TRANSLUCENT);
>               Graphics2D g = vImage.createGraphics();
>               
>               //necessary, as VolatileImages start out filled opaque white
>               g.setComposite(AlphaComposite.Clear);
>               g.setColor(new Color(255, 255, 255, 0));
>               g.fillRect(0,0, vImage.getWidth(), vImage.getHeight());
>               
>               g.setComposite(AlphaComposite.SrcOver);
>               g.setColor(new Color(255, 0, 0, 128));
>               g.fillRect(10, 10, vImage.getWidth()-20, vImage.getHeight()-20);
> 
>               g.dispose();
>               return vImage;
>       }
> 
>       public static void main(String[] args) {
>               SwingUtilities.invokeLater(new Runnable(){
>                       public void run() {
>                               new PaintTest();
>                       }
>               });
>       }
> }

Reply via email to