< prev index next >

src/windows/classes/sun/awt/windows/TranslucentWindowPainter.java

Print this page
rev 1556 : 6794764: Translucent windows are completely repainted on every paint event, on Windows
6719382: Printing of AWT components on windows is not working
6726866: Repainting artifacts when resizing or dragging JInternalFrames in non-opaque toplevel
6683775: Painting artifacts is seen when panel is made setOpaque(false) for a translucent window
Reviewed-by: anthony, tdv, alexp


  88                 // a pipeline isn't enabled
  89                 if (gcName.startsWith("D3D")) {
  90                     return new VIOptD3DWindowPainter(peer);
  91                 } else if (forceOpt && gcName.startsWith("WGL")) {
  92                     // on some boards (namely, ATI, even on pcix bus) ogl is
  93                     // very slow reading pixels back so for now it is disabled
  94                     // unless forced
  95                     return new VIOptWGLWindowPainter(peer);
  96                 }
  97             }
  98         }
  99         return new BIWindowPainter(peer);
 100     }
 101 
 102     protected TranslucentWindowPainter(WWindowPeer peer) {
 103         this.peer = peer;
 104         this.window = (Window)peer.getTarget();
 105     }
 106 
 107     /**
 108      * Creates (if needed), clears and returns the buffer for this painter.

 109      */
 110     protected abstract Image getBackBuffer();
 111 
 112     /**
 113      * Updates the the window associated with this painter with the contents
 114      * of the passed image.
 115      * The image can not be null, and NPE will be thrown if it is.
 116      */
 117     protected abstract boolean update(Image bb);
 118 
 119     /**
 120      * Flushes the resources associated with the painter. They will be
 121      * recreated as needed.
 122      */
 123     public abstract void flush();
 124 
 125     /**
 126      * Updates the window associated with the painter given the passed image.
 127      * If the passed image is null the painter will use its own buffer for
 128      * rendering the contents of the window into it and updating the window.
 129      *
 130      * If the passed buffer has dimensions different from the window, it is
 131      * copied into the internal buffer first and the latter is used to update
 132      * the window.
 133      *
 134      * @param bb the image to update the non opaque window with, or null.
 135      * If not null, the image must be of ARGB_PRE type.
 136      */
 137     public void updateWindow(Image bb) {
 138         boolean done = false;
 139         if (bb != null && (window.getWidth()  != bb.getWidth(null) ||
 140                            window.getHeight() != bb.getHeight(null)))
 141         {
 142             Image ourBB = getBackBuffer();
 143             Graphics2D g = (Graphics2D)ourBB.getGraphics();
 144             g.drawImage(bb, 0, 0, null);
 145             g.dispose();
 146             bb = ourBB;
 147         }
 148         do {
 149             if (bb == null) {
 150                 bb = getBackBuffer();
 151                 Graphics2D g = (Graphics2D)bb.getGraphics();
 152                 try {
 153                     window.paintAll(g);
 154                 } finally {
 155                     g.dispose();
 156                 }
 157             }
 158 
 159             peer.paintAppletWarning((Graphics2D)bb.getGraphics(),
 160                                     bb.getWidth(null), bb.getHeight(null));
 161 
 162             done = update(bb);
 163             // in case they passed us a lost VI, next time around we'll use our
 164             // own bb because we can not validate and restore the contents of
 165             // their VI
 166             if (!done) {
 167                 bb = null;


 168             }
 169         } while (!done);
 170     }
 171 
 172     private static final Image clearImage(Image bb) {
 173         Graphics2D g = (Graphics2D)bb.getGraphics();
 174         int w = bb.getWidth(null);
 175         int h = bb.getHeight(null);
 176 
 177         g.setComposite(AlphaComposite.Src);
 178         g.setColor(new Color(0, 0, 0, 0));
 179         g.fillRect(0, 0, w, h);
 180 
 181         return bb;
 182     }
 183 
 184     /**
 185      * A painter which uses BufferedImage as the internal buffer. The window
 186      * is painted into this buffer, and the contents then are uploaded
 187      * into the layered window.
 188      *
 189      * This painter handles all types of images passed to its paint(Image)
 190      * method (VI, BI, regular Images).
 191      */
 192     private static class BIWindowPainter extends TranslucentWindowPainter {
 193         private WeakReference<BufferedImage> biRef;
 194 
 195         protected BIWindowPainter(WWindowPeer peer) {
 196             super(peer);
 197         }
 198 
 199         private BufferedImage getBIBackBuffer() {

 200             int w = window.getWidth();
 201             int h = window.getHeight();
 202             BufferedImage bb = biRef == null ? null : biRef.get();
 203             if (bb == null || bb.getWidth() != w || bb.getHeight() != h) {
 204                 if (bb != null) {
 205                     bb.flush();
 206                     bb = null;
 207                 }
 208                 bb = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE);
 209                 biRef = new WeakReference<BufferedImage>(bb);
 210             }
 211             return (BufferedImage)clearImage(bb);
 212         }
 213 
 214         @Override
 215         protected Image getBackBuffer() {
 216             return getBIBackBuffer();
 217         }
 218 
 219         @Override
 220         protected boolean update(Image bb) {
 221             VolatileImage viBB = null;
 222 
 223             if (bb instanceof BufferedImage) {
 224                 BufferedImage bi = (BufferedImage)bb;
 225                 int data[] =
 226                     ((DataBufferInt)bi.getRaster().getDataBuffer()).getData();
 227                 peer.updateWindowImpl(data, bi.getWidth(), bi.getHeight());
 228                 return true;
 229             } else if (bb instanceof VolatileImage) {
 230                 viBB = (VolatileImage)bb;
 231                 if (bb instanceof DestSurfaceProvider) {
 232                     Surface s = ((DestSurfaceProvider)bb).getDestSurface();
 233                     if (s instanceof BufImgSurfaceData) {
 234                         // the image is probably lost, upload the data from the
 235                         // backup surface to avoid creating another heap-based
 236                         // image (the parent's buffer)
 237                         int w = viBB.getWidth();
 238                         int h = viBB.getHeight();
 239                         BufImgSurfaceData bisd = (BufImgSurfaceData)s;
 240                         int data[] = ((DataBufferInt)bisd.getRaster(0,0,w,h).
 241                             getDataBuffer()).getData();
 242                         peer.updateWindowImpl(data, w, h);
 243                         return true;
 244                     }
 245                 }
 246             }
 247 
 248             // copy the passed image into our own buffer, then upload
 249             BufferedImage bi = getBIBackBuffer();
 250             Graphics2D g = (Graphics2D)bi.getGraphics();
 251             g.setComposite(AlphaComposite.Src);
 252             g.drawImage(bb, 0, 0, null);
 253 
 254             int data[] =
 255                 ((DataBufferInt)bi.getRaster().getDataBuffer()).getData();
 256             peer.updateWindowImpl(data, bi.getWidth(), bi.getHeight());
 257 
 258             return (viBB != null ? !viBB.contentsLost() : true);
 259         }
 260 
 261         public void flush() {
 262             if (biRef != null) {
 263                 biRef.clear();

 264             }
 265         }
 266     }
 267 
 268     /**
 269      * A version of the painter which uses VolatileImage as the internal buffer.
 270      * The window is painted into this VI and then copied into the parent's
 271      * Java heap-based buffer (which is then uploaded to the layered window)
 272      */
 273     private static class VIWindowPainter extends BIWindowPainter {
 274         private WeakReference<VolatileImage> viRef;
 275 
 276         protected VIWindowPainter(WWindowPeer peer) {
 277             super(peer);
 278         }
 279 
 280         @Override
 281         protected Image getBackBuffer() {
 282             int w = window.getWidth();
 283             int h = window.getHeight();
 284             GraphicsConfiguration gc = peer.getGraphicsConfiguration();
 285 
 286             VolatileImage viBB = viRef == null ? null : viRef.get();
 287 
 288             if (viBB == null || viBB.getWidth() != w || viBB.getHeight() != h ||
 289                 viBB.validate(gc) == IMAGE_INCOMPATIBLE)
 290             {
 291                 if (viBB != null) {
 292                     viBB.flush();
 293                     viBB = null;
 294                 }
 295 
 296                 if (gc instanceof AccelGraphicsConfig) {
 297                     AccelGraphicsConfig agc = ((AccelGraphicsConfig)gc);
 298                     viBB = agc.createCompatibleVolatileImage(w, h,
 299                                                              TRANSLUCENT,
 300                                                              RT_PLAIN);
 301                 }
 302                 if (viBB == null) {
 303                     viBB = gc.createCompatibleVolatileImage(w, h, TRANSLUCENT);
 304                 }
 305                 viBB.validate(gc);
 306                 viRef = new WeakReference<VolatileImage>(viBB);
 307             }
 308 
 309             return clearImage(viBB);
 310         }
 311 
 312         @Override
 313         public void flush() {
 314             if (viRef != null) {
 315                 VolatileImage viBB = viRef.get();
 316                 if (viBB != null) {
 317                     viBB.flush();
 318                     viBB = null;
 319                 }
 320                 viRef.clear();
 321             }
 322         }
 323     }
 324 
 325     /**
 326      * Optimized version of hw painter. Uses VolatileImages for the
 327      * buffer, and uses an optimized path to pull the data from those into
 328      * the layered window, bypassing Java heap-based image.
 329      */
 330     private abstract static class VIOptWindowPainter extends VIWindowPainter {
 331 
 332         protected VIOptWindowPainter(WWindowPeer peer) {
 333             super(peer);
 334         }
 335 
 336         protected abstract boolean updateWindowAccel(long psdops, int w, int h);
 337 
 338         @Override
 339         protected boolean update(Image bb) {
 340             if (bb instanceof DestSurfaceProvider) {




  88                 // a pipeline isn't enabled
  89                 if (gcName.startsWith("D3D")) {
  90                     return new VIOptD3DWindowPainter(peer);
  91                 } else if (forceOpt && gcName.startsWith("WGL")) {
  92                     // on some boards (namely, ATI, even on pcix bus) ogl is
  93                     // very slow reading pixels back so for now it is disabled
  94                     // unless forced
  95                     return new VIOptWGLWindowPainter(peer);
  96                 }
  97             }
  98         }
  99         return new BIWindowPainter(peer);
 100     }
 101 
 102     protected TranslucentWindowPainter(WWindowPeer peer) {
 103         this.peer = peer;
 104         this.window = (Window)peer.getTarget();
 105     }
 106 
 107     /**
 108      * Creates (if needed), clears (if requested) and returns the buffer
 109      * for this painter.
 110      */
 111     protected abstract Image getBackBuffer(boolean clear);
 112 
 113     /**
 114      * Updates the the window associated with this painter with the contents
 115      * of the passed image.
 116      * The image can not be null, and NPE will be thrown if it is.
 117      */
 118     protected abstract boolean update(Image bb);
 119 
 120     /**
 121      * Flushes the resources associated with the painter. They will be
 122      * recreated as needed.
 123      */
 124     public abstract void flush();
 125 
 126     /**
 127      * Updates the window associated with the painter.


 128      *
 129      * @param repaint indicates if the window should be completely repainted
 130      * to the back buffer using {@link java.awt.Window#paintAll} before update.




 131      */
 132     public void updateWindow(boolean repaint) {
 133         boolean done = false;
 134         Image bb = getBackBuffer(repaint);
 135         while (!done) {
 136             if (repaint) {









 137                 Graphics2D g = (Graphics2D)bb.getGraphics();
 138                 try {
 139                     window.paintAll(g);
 140                 } finally {
 141                     g.dispose();
 142                 }
 143             }
 144 



 145             done = update(bb);



 146             if (!done) {
 147                 repaint = true;
 148                 bb = getBackBuffer(true);
 149             }
 150         }

 151     }
 152 
 153     private static final Image clearImage(Image bb) {
 154         Graphics2D g = (Graphics2D)bb.getGraphics();
 155         int w = bb.getWidth(null);
 156         int h = bb.getHeight(null);
 157 
 158         g.setComposite(AlphaComposite.Src);
 159         g.setColor(new Color(0, 0, 0, 0));
 160         g.fillRect(0, 0, w, h);
 161 
 162         return bb;
 163     }
 164 
 165     /**
 166      * A painter which uses BufferedImage as the internal buffer. The window
 167      * is painted into this buffer, and the contents then are uploaded
 168      * into the layered window.
 169      *
 170      * This painter handles all types of images passed to its paint(Image)
 171      * method (VI, BI, regular Images).
 172      */
 173     private static class BIWindowPainter extends TranslucentWindowPainter {
 174         private BufferedImage backBuffer;
 175 
 176         protected BIWindowPainter(WWindowPeer peer) {
 177             super(peer);
 178         }
 179 
 180         @Override
 181         protected Image getBackBuffer(boolean clear) {
 182             int w = window.getWidth();
 183             int h = window.getHeight();
 184             if (backBuffer == null ||
 185                 backBuffer.getWidth() != w ||
 186                 backBuffer.getHeight() != h)
 187             {
 188                 flush();
 189                 backBuffer = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE);


 190             }
 191             return clear ? (BufferedImage)clearImage(backBuffer) : backBuffer;





 192         }
 193 
 194         @Override
 195         protected boolean update(Image bb) {
 196             VolatileImage viBB = null;
 197 
 198             if (bb instanceof BufferedImage) {
 199                 BufferedImage bi = (BufferedImage)bb;
 200                 int data[] =
 201                     ((DataBufferInt)bi.getRaster().getDataBuffer()).getData();
 202                 peer.updateWindowImpl(data, bi.getWidth(), bi.getHeight());
 203                 return true;
 204             } else if (bb instanceof VolatileImage) {
 205                 viBB = (VolatileImage)bb;
 206                 if (bb instanceof DestSurfaceProvider) {
 207                     Surface s = ((DestSurfaceProvider)bb).getDestSurface();
 208                     if (s instanceof BufImgSurfaceData) {
 209                         // the image is probably lost, upload the data from the
 210                         // backup surface to avoid creating another heap-based
 211                         // image (the parent's buffer)
 212                         int w = viBB.getWidth();
 213                         int h = viBB.getHeight();
 214                         BufImgSurfaceData bisd = (BufImgSurfaceData)s;
 215                         int data[] = ((DataBufferInt)bisd.getRaster(0,0,w,h).
 216                             getDataBuffer()).getData();
 217                         peer.updateWindowImpl(data, w, h);
 218                         return true;
 219                     }
 220                 }
 221             }
 222 
 223             // copy the passed image into our own buffer, then upload
 224             BufferedImage bi = (BufferedImage)clearImage(backBuffer);



 225 
 226             int data[] =
 227                 ((DataBufferInt)bi.getRaster().getDataBuffer()).getData();
 228             peer.updateWindowImpl(data, bi.getWidth(), bi.getHeight());
 229 
 230             return (viBB != null ? !viBB.contentsLost() : true);
 231         }
 232 
 233         public void flush() {
 234             if (backBuffer != null) {
 235                 backBuffer.flush();
 236                 backBuffer = null;
 237             }
 238         }
 239     }
 240 
 241     /**
 242      * A version of the painter which uses VolatileImage as the internal buffer.
 243      * The window is painted into this VI and then copied into the parent's
 244      * Java heap-based buffer (which is then uploaded to the layered window)
 245      */
 246     private static class VIWindowPainter extends BIWindowPainter {
 247         private VolatileImage viBB;
 248 
 249         protected VIWindowPainter(WWindowPeer peer) {
 250             super(peer);
 251         }
 252 
 253         @Override
 254         protected Image getBackBuffer(boolean clear) {
 255             int w = window.getWidth();
 256             int h = window.getHeight();
 257             GraphicsConfiguration gc = peer.getGraphicsConfiguration();
 258 


 259             if (viBB == null || viBB.getWidth() != w || viBB.getHeight() != h ||
 260                 viBB.validate(gc) == IMAGE_INCOMPATIBLE)
 261             {
 262                 flush();



 263 
 264                 if (gc instanceof AccelGraphicsConfig) {
 265                     AccelGraphicsConfig agc = ((AccelGraphicsConfig)gc);
 266                     viBB = agc.createCompatibleVolatileImage(w, h,
 267                                                              TRANSLUCENT,
 268                                                              RT_PLAIN);
 269                 }
 270                 if (viBB == null) {
 271                     viBB = gc.createCompatibleVolatileImage(w, h, TRANSLUCENT);
 272                 }
 273                 viBB.validate(gc);

 274             }
 275 
 276             return clear ? clearImage(viBB) : viBB;
 277         }
 278 
 279         @Override
 280         public void flush() {


 281             if (viBB != null) {
 282                 viBB.flush();
 283                 viBB = null;


 284             }
 285         }
 286     }
 287 
 288     /**
 289      * Optimized version of hw painter. Uses VolatileImages for the
 290      * buffer, and uses an optimized path to pull the data from those into
 291      * the layered window, bypassing Java heap-based image.
 292      */
 293     private abstract static class VIOptWindowPainter extends VIWindowPainter {
 294 
 295         protected VIOptWindowPainter(WWindowPeer peer) {
 296             super(peer);
 297         }
 298 
 299         protected abstract boolean updateWindowAccel(long psdops, int w, int h);
 300 
 301         @Override
 302         protected boolean update(Image bb) {
 303             if (bb instanceof DestSurfaceProvider) {


< prev index next >