9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package sun.awt.windows; 26 27 import java.awt.AlphaComposite; 28 import java.awt.Color; 29 import java.awt.Graphics2D; 30 import java.awt.GraphicsConfiguration; 31 import java.awt.Image; 32 import java.awt.Window; 33 import java.awt.image.BufferedImage; 34 import java.awt.image.DataBufferInt; 35 import java.awt.image.VolatileImage; 36 import java.security.AccessController; 37 import sun.awt.image.BufImgSurfaceData; 38 import sun.java2d.DestSurfaceProvider; 39 import sun.java2d.InvalidPipeException; 40 import sun.java2d.Surface; 41 import sun.java2d.pipe.RenderQueue; 42 import sun.java2d.pipe.BufferedContext; 43 import sun.java2d.pipe.hw.AccelGraphicsConfig; 44 import sun.java2d.pipe.hw.AccelSurface; 45 import sun.security.action.GetPropertyAction; 46 47 import static java.awt.image.VolatileImage.*; 48 import static sun.java2d.pipe.hw.AccelSurface.*; 49 import static sun.java2d.pipe.hw.ContextCapabilities.*; 50 51 /** 52 * This class handles the updates of the non-opaque windows. 53 * The window associated with the peer is updated either given an image or 54 * the window is repainted to an internal buffer which is then used to update 55 * the window. 56 * 57 * Note: this class does not attempt to be thread safe, it is expected to be 58 * called from a single thread (EDT). 59 */ 60 abstract class TranslucentWindowPainter { 100 101 protected TranslucentWindowPainter(WWindowPeer peer) { 102 this.peer = peer; 103 this.window = (Window)peer.getTarget(); 104 } 105 106 /** 107 * Creates (if needed), clears (if requested) and returns the buffer 108 * for this painter. 109 */ 110 protected abstract Image getBackBuffer(boolean clear); 111 112 /** 113 * Updates 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. 127 * 128 * @param repaint indicates if the window should be completely repainted 129 * to the back buffer using {@link java.awt.Window#paintAll} before update. 130 */ 131 public void updateWindow(boolean repaint) { 132 boolean done = false; 133 Image bb = getBackBuffer(repaint); 134 while (!done) { 135 if (repaint) { 136 Graphics2D g = (Graphics2D)bb.getGraphics(); 137 try { 138 window.paintAll(g); 139 } finally { 140 g.dispose(); 141 } 142 } 143 144 done = update(bb); 145 if (!done) { 146 repaint = true; 147 bb = getBackBuffer(true); 148 } 149 } 150 } 151 152 private static final Image clearImage(Image bb) { 153 Graphics2D g = (Graphics2D)bb.getGraphics(); 154 int w = bb.getWidth(null); 155 int h = bb.getHeight(null); 156 157 g.setComposite(AlphaComposite.Src); 158 g.setColor(new Color(0, 0, 0, 0)); 159 g.fillRect(0, 0, w, h); 160 161 return bb; 162 } 163 164 /** 165 * A painter which uses BufferedImage as the internal buffer. The window 166 * is painted into this buffer, and the contents then are uploaded 167 * into the layered window. 168 * 169 * This painter handles all types of images passed to its paint(Image) 170 * method (VI, BI, regular Images). 171 */ 172 private static class BIWindowPainter extends TranslucentWindowPainter { 173 private BufferedImage backBuffer; 174 175 protected BIWindowPainter(WWindowPeer peer) { 176 super(peer); 177 } 178 179 @Override 180 protected Image getBackBuffer(boolean clear) { 181 int w = window.getWidth(); 182 int h = window.getHeight(); 183 if (backBuffer == null || 184 backBuffer.getWidth() != w || 185 backBuffer.getHeight() != h) 186 { 187 flush(); 188 backBuffer = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE); 189 } 190 return clear ? (BufferedImage)clearImage(backBuffer) : backBuffer; 191 } 192 193 @Override 194 protected boolean update(Image bb) { 195 VolatileImage viBB = null; 196 197 if (bb instanceof BufferedImage) { 198 BufferedImage bi = (BufferedImage)bb; 199 int data[] = 200 ((DataBufferInt)bi.getRaster().getDataBuffer()).getData(); 201 peer.updateWindowImpl(data, bi.getWidth(), bi.getHeight()); 202 return true; 219 } 220 } 221 222 // copy the passed image into our own buffer, then upload 223 BufferedImage bi = (BufferedImage)clearImage(backBuffer); 224 225 int data[] = 226 ((DataBufferInt)bi.getRaster().getDataBuffer()).getData(); 227 peer.updateWindowImpl(data, bi.getWidth(), bi.getHeight()); 228 229 return (viBB != null ? !viBB.contentsLost() : true); 230 } 231 232 @Override 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 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) { 304 Surface s = ((DestSurfaceProvider)bb).getDestSurface(); | 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package sun.awt.windows; 26 27 import java.awt.AlphaComposite; 28 import java.awt.Color; 29 import java.awt.Graphics; 30 import java.awt.Graphics2D; 31 import java.awt.GraphicsConfiguration; 32 import java.awt.Image; 33 import java.awt.Window; 34 import java.awt.geom.AffineTransform; 35 import java.awt.image.BufferedImage; 36 import java.awt.image.DataBufferInt; 37 import java.awt.image.VolatileImage; 38 import java.security.AccessController; 39 import sun.awt.image.BufImgSurfaceData; 40 import sun.java2d.DestSurfaceProvider; 41 import sun.java2d.InvalidPipeException; 42 import sun.java2d.Surface; 43 import sun.java2d.pipe.Region; 44 import sun.java2d.pipe.RenderQueue; 45 import sun.java2d.pipe.BufferedContext; 46 import sun.java2d.pipe.hw.AccelGraphicsConfig; 47 import sun.java2d.pipe.hw.AccelSurface; 48 import sun.security.action.GetPropertyAction; 49 50 import static java.awt.image.VolatileImage.*; 51 import static sun.java2d.pipe.hw.AccelSurface.*; 52 import static sun.java2d.pipe.hw.ContextCapabilities.*; 53 54 /** 55 * This class handles the updates of the non-opaque windows. 56 * The window associated with the peer is updated either given an image or 57 * the window is repainted to an internal buffer which is then used to update 58 * the window. 59 * 60 * Note: this class does not attempt to be thread safe, it is expected to be 61 * called from a single thread (EDT). 62 */ 63 abstract class TranslucentWindowPainter { 103 104 protected TranslucentWindowPainter(WWindowPeer peer) { 105 this.peer = peer; 106 this.window = (Window)peer.getTarget(); 107 } 108 109 /** 110 * Creates (if needed), clears (if requested) and returns the buffer 111 * for this painter. 112 */ 113 protected abstract Image getBackBuffer(boolean clear); 114 115 /** 116 * Updates the window associated with this painter with the contents 117 * of the passed image. 118 * The image can not be null, and NPE will be thrown if it is. 119 */ 120 protected abstract boolean update(Image bb); 121 122 /** 123 * Create (if needed), clears back buffer (if requested) and return 124 * graphics for this class depending upon the buffer type 125 */ 126 protected abstract Graphics getGraphics(boolean clear); 127 128 /** 129 * Flushes the resources associated with the painter. They will be 130 * recreated as needed. 131 */ 132 public abstract void flush(); 133 134 /** 135 * Updates the window associated with the painter. 136 * 137 * @param repaint indicates if the window should be completely repainted 138 * to the back buffer using {@link java.awt.Window#paintAll} before update. 139 */ 140 public void updateWindow(boolean repaint) { 141 boolean done = false; 142 while (!done) { 143 if (repaint) { 144 Graphics2D g = (Graphics2D) getGraphics(repaint); 145 try { 146 window.paintAll(g); 147 } finally { 148 g.dispose(); 149 } 150 } 151 152 done = update(getBackBuffer(false)); 153 if (!done) { 154 repaint = true; 155 } 156 } 157 } 158 159 private static final Image clearImage(Image bb) { 160 Graphics2D g = (Graphics2D)bb.getGraphics(); 161 int w = bb.getWidth(null); 162 int h = bb.getHeight(null); 163 164 g.setComposite(AlphaComposite.Src); 165 g.setColor(new Color(0, 0, 0, 0)); 166 g.fillRect(0, 0, w, h); 167 168 return bb; 169 } 170 171 /** 172 * A painter which uses BufferedImage as the internal buffer. The window 173 * is painted into this buffer, and the contents then are uploaded 174 * into the layered window. 175 * 176 * This painter handles all types of images passed to its paint(Image) 177 * method (VI, BI, regular Images). 178 */ 179 private static class BIWindowPainter extends TranslucentWindowPainter { 180 private BufferedImage backBuffer; 181 182 protected BIWindowPainter(WWindowPeer peer) { 183 super(peer); 184 } 185 186 @Override 187 protected Image getBackBuffer(boolean clear) { 188 GraphicsConfiguration gc = peer.getGraphicsConfiguration(); 189 AffineTransform transform = gc.getDefaultTransform(); 190 int w = Region.clipRound( 191 window.getWidth() * transform.getScaleX()); 192 int h = Region.clipRound( 193 window.getHeight() * transform.getScaleY()); 194 if (backBuffer == null || 195 backBuffer.getWidth() != w || 196 backBuffer.getHeight() != h) 197 { 198 flush(); 199 backBuffer = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE); 200 } 201 return clear ? (BufferedImage)clearImage(backBuffer) : backBuffer; 202 } 203 204 @Override 205 protected boolean update(Image bb) { 206 VolatileImage viBB = null; 207 208 if (bb instanceof BufferedImage) { 209 BufferedImage bi = (BufferedImage)bb; 210 int data[] = 211 ((DataBufferInt)bi.getRaster().getDataBuffer()).getData(); 212 peer.updateWindowImpl(data, bi.getWidth(), bi.getHeight()); 213 return true; 230 } 231 } 232 233 // copy the passed image into our own buffer, then upload 234 BufferedImage bi = (BufferedImage)clearImage(backBuffer); 235 236 int data[] = 237 ((DataBufferInt)bi.getRaster().getDataBuffer()).getData(); 238 peer.updateWindowImpl(data, bi.getWidth(), bi.getHeight()); 239 240 return (viBB != null ? !viBB.contentsLost() : true); 241 } 242 243 @Override 244 public void flush() { 245 if (backBuffer != null) { 246 backBuffer.flush(); 247 backBuffer = null; 248 } 249 } 250 251 @Override 252 protected Graphics getGraphics(boolean clear) { 253 Graphics g = getBackBuffer(clear).getGraphics(); 254 /* 255 This graphics object returned by BuffereImage is not scaled to 256 graphics configuration, but this graphics object can be used by 257 components inside this TranslucentWindow. So need to scale this 258 before returning. 259 */ 260 ((Graphics2D)g).transform(peer.getGraphicsConfiguration().getDefaultTransform()); 261 return g; 262 } 263 } 264 265 /** 266 * A version of the painter which uses VolatileImage as the internal buffer. 267 * The window is painted into this VI and then copied into the parent's 268 * Java heap-based buffer (which is then uploaded to the layered window) 269 */ 270 private static class VIWindowPainter extends BIWindowPainter { 271 private VolatileImage viBB; 272 273 protected VIWindowPainter(WWindowPeer peer) { 274 super(peer); 275 } 276 277 @Override 278 protected Image getBackBuffer(boolean clear) { 279 int w = window.getWidth(); 280 int h = window.getHeight(); 281 GraphicsConfiguration gc = peer.getGraphicsConfiguration(); 282 289 AccelGraphicsConfig agc = ((AccelGraphicsConfig)gc); 290 viBB = agc.createCompatibleVolatileImage(w, h, 291 TRANSLUCENT, 292 RT_PLAIN); 293 } 294 if (viBB == null) { 295 viBB = gc.createCompatibleVolatileImage(w, h, TRANSLUCENT); 296 } 297 viBB.validate(gc); 298 } 299 300 return clear ? clearImage(viBB) : viBB; 301 } 302 303 @Override 304 public void flush() { 305 if (viBB != null) { 306 viBB.flush(); 307 viBB = null; 308 } 309 } 310 311 @Override 312 protected Graphics getGraphics(boolean clear) { 313 return getBackBuffer(clear).getGraphics(); 314 } 315 } 316 317 /** 318 * Optimized version of hw painter. Uses VolatileImages for the 319 * buffer, and uses an optimized path to pull the data from those into 320 * the layered window, bypassing Java heap-based image. 321 */ 322 private abstract static class VIOptWindowPainter extends VIWindowPainter { 323 324 protected VIOptWindowPainter(WWindowPeer peer) { 325 super(peer); 326 } 327 328 protected abstract boolean updateWindowAccel(long psdops, int w, int h); 329 330 @Override 331 protected boolean update(Image bb) { 332 if (bb instanceof DestSurfaceProvider) { 333 Surface s = ((DestSurfaceProvider)bb).getDestSurface(); |