1 /* 2 * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 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 26 package sun.java2d.d3d; 27 28 import java.awt.AWTException; 29 import java.awt.BufferCapabilities; 30 import java.awt.BufferCapabilities.FlipContents; 31 import java.awt.Component; 32 import java.awt.Graphics; 33 import java.awt.ImageCapabilities; 34 import java.awt.Transparency; 35 import java.awt.color.ColorSpace; 36 import java.awt.image.ColorModel; 37 import java.awt.image.DataBuffer; 38 import java.awt.image.DirectColorModel; 39 import java.awt.image.VolatileImage; 40 import sun.awt.Win32GraphicsConfig; 41 import sun.awt.image.SunVolatileImage; 42 import sun.awt.image.SurfaceManager; 43 import sun.awt.windows.WComponentPeer; 44 import sun.java2d.Surface; 45 import sun.java2d.SurfaceData; 46 import sun.java2d.pipe.hw.AccelDeviceEventNotifier; 47 import sun.java2d.pipe.hw.AccelTypedVolatileImage; 48 import sun.java2d.pipe.hw.AccelGraphicsConfig; 49 import sun.java2d.pipe.hw.AccelSurface; 50 import sun.java2d.pipe.hw.ContextCapabilities; 51 import static sun.java2d.pipe.hw.AccelSurface.*; 52 import static sun.java2d.d3d.D3DContext.D3DContextCaps.*; 53 import sun.java2d.pipe.hw.AccelDeviceEventListener; 54 55 public class D3DGraphicsConfig 56 extends Win32GraphicsConfig 57 implements AccelGraphicsConfig 58 { 59 private static ImageCapabilities imageCaps = new D3DImageCaps(); 60 61 private BufferCapabilities bufferCaps; 62 private D3DGraphicsDevice device; 63 64 @SuppressWarnings("deprecation") 65 protected D3DGraphicsConfig(D3DGraphicsDevice device) { 66 super(device, 0); 67 this.device = device; 68 } 69 70 public SurfaceData createManagedSurface(int w, int h, int transparency) { 71 return D3DSurfaceData.createData(this, w, h, 72 getColorModel(transparency), 73 null, 74 D3DSurfaceData.TEXTURE); 75 } 76 77 @Override 78 public synchronized void displayChanged() { 79 super.displayChanged(); 80 // the context could hold a reference to a D3DSurfaceData, which in 81 // turn has a reference back to this D3DGraphicsConfig, so in order 82 // for this instance to be disposed we need to break the connection 83 D3DRenderQueue rq = D3DRenderQueue.getInstance(); 84 rq.lock(); 85 try { 86 D3DContext.invalidateCurrentContext(); 87 } finally { 88 rq.unlock(); 89 } 90 } 91 92 @Override 93 public ColorModel getColorModel(int transparency) { 94 switch (transparency) { 95 case Transparency.OPAQUE: 96 // REMIND: once the ColorModel spec is changed, this should be 97 // an opaque premultiplied DCM... 98 return new DirectColorModel(24, 0xff0000, 0xff00, 0xff); 99 case Transparency.BITMASK: 100 return new DirectColorModel(25, 0xff0000, 0xff00, 0xff, 0x1000000); 101 case Transparency.TRANSLUCENT: 102 ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); 103 return new DirectColorModel(cs, 32, 104 0xff0000, 0xff00, 0xff, 0xff000000, 105 true, DataBuffer.TYPE_INT); 106 default: 107 return null; 108 } 109 } 110 111 @Override 112 public String toString() { 113 return ("D3DGraphicsConfig[dev="+screen+",pixfmt="+visual+"]"); 114 } 115 116 /** 117 * The following methods are invoked from WComponentPeer.java rather 118 * than having the Win32-dependent implementations hardcoded in that 119 * class. This way the appropriate actions are taken based on the peer's 120 * GraphicsConfig, whether it is a Win32GraphicsConfig or a 121 * D3DGraphicsConfig. 122 */ 123 124 /** 125 * Creates a new SurfaceData that will be associated with the given 126 * WComponentPeer. D3D9 doesn't allow rendering to the screen, 127 * so a GDI surface will be returned. 128 */ 129 @Override 130 public SurfaceData createSurfaceData(WComponentPeer peer, 131 int numBackBuffers) 132 { 133 return super.createSurfaceData(peer, numBackBuffers); 134 } 135 136 /** 137 * The following methods correspond to the multibuffering methods in 138 * WComponentPeer.java... 139 */ 140 141 /** 142 * Checks that the requested configuration is natively supported; if not, 143 * an AWTException is thrown. 144 */ 145 @Override 146 public void assertOperationSupported(Component target, 147 int numBuffers, 148 BufferCapabilities caps) 149 throws AWTException 150 { 151 if (numBuffers < 2 || numBuffers > 4) { 152 throw new AWTException("Only 2-4 buffers supported"); 153 } 154 if (caps.getFlipContents() == BufferCapabilities.FlipContents.COPIED && 155 numBuffers != 2) 156 { 157 throw new AWTException("FlipContents.COPIED is only" + 158 "supported for 2 buffers"); 159 } 160 } 161 162 /** 163 * Creates a D3D-based backbuffer for the given peer and returns the 164 * image wrapper. 165 */ 166 @Override 167 public VolatileImage createBackBuffer(WComponentPeer peer) { 168 Component target = (Component)peer.getTarget(); 169 // it is possible for the component to have size 0x0, adjust it to 170 // be at least 1x1 to avoid IAE 171 int w = Math.max(1, target.getWidth()); 172 int h = Math.max(1, target.getHeight()); 173 return new SunVolatileImage(target, w, h, Boolean.TRUE); 174 } 175 176 /** 177 * Performs the native D3D flip operation for the given target Component. 178 */ 179 @Override 180 public void flip(WComponentPeer peer, 181 Component target, VolatileImage backBuffer, 182 int x1, int y1, int x2, int y2, 183 BufferCapabilities.FlipContents flipAction) 184 { 185 // REMIND: we should actually get a surface data for the 186 // backBuffer's VI 187 SurfaceManager d3dvsm = 188 SurfaceManager.getManager(backBuffer); 189 SurfaceData sd = d3dvsm.getPrimarySurfaceData(); 190 if (sd instanceof D3DSurfaceData) { 191 D3DSurfaceData d3dsd = (D3DSurfaceData)sd; 192 D3DSurfaceData.swapBuffers(d3dsd, x1, y1, x2, y2); 193 } else { 194 // the surface was likely lost could not have been restored 195 Graphics g = peer.getGraphics(); 196 try { 197 g.drawImage(backBuffer, 198 x1, y1, x2, y2, 199 x1, y1, x2, y2, 200 null); 201 } finally { 202 g.dispose(); 203 } 204 } 205 206 if (flipAction == BufferCapabilities.FlipContents.BACKGROUND) { 207 Graphics g = backBuffer.getGraphics(); 208 try { 209 g.setColor(target.getBackground()); 210 g.fillRect(0, 0, 211 backBuffer.getWidth(), 212 backBuffer.getHeight()); 213 } finally { 214 g.dispose(); 215 } 216 } 217 } 218 219 private static class D3DBufferCaps extends BufferCapabilities { 220 public D3DBufferCaps() { 221 // REMIND: should we indicate that the front-buffer 222 // (the on-screen rendering) is not accelerated? 223 super(imageCaps, imageCaps, FlipContents.UNDEFINED); 224 } 225 @Override 226 public boolean isMultiBufferAvailable() { 227 return true; 228 } 229 230 } 231 232 @Override 233 public BufferCapabilities getBufferCapabilities() { 234 if (bufferCaps == null) { 235 bufferCaps = new D3DBufferCaps(); 236 } 237 return bufferCaps; 238 } 239 240 private static class D3DImageCaps extends ImageCapabilities { 241 private D3DImageCaps() { 242 super(true); 243 } 244 @Override 245 public boolean isTrueVolatile() { 246 return true; 247 } 248 } 249 250 @Override 251 public ImageCapabilities getImageCapabilities() { 252 return imageCaps; 253 } 254 255 D3DGraphicsDevice getD3DDevice() { 256 return device; 257 } 258 259 /** 260 * {@inheritDoc} 261 * 262 * @see sun.java2d.pipe.hw.BufferedContextProvider#getContext 263 */ 264 @Override 265 public D3DContext getContext() { 266 return device.getContext(); 267 } 268 269 /** 270 * {@inheritDoc} 271 * 272 * @see sun.java2d.pipe.hw.AccelGraphicsConfig#createCompatibleVolatileImage 273 */ 274 @Override 275 public VolatileImage 276 createCompatibleVolatileImage(int width, int height, 277 int transparency, int type) 278 { 279 if (type == FLIP_BACKBUFFER || type == WINDOW || type == UNDEFINED || 280 transparency == Transparency.BITMASK) 281 { 282 return null; 283 } 284 boolean isOpaque = transparency == Transparency.OPAQUE; 285 if (type == RT_TEXTURE) { 286 int cap = isOpaque ? CAPS_RT_TEXTURE_OPAQUE : CAPS_RT_TEXTURE_ALPHA; 287 if (!device.isCapPresent(cap)) { 288 return null; 289 } 290 } else if (type == RT_PLAIN) { 291 if (!isOpaque && !device.isCapPresent(CAPS_RT_PLAIN_ALPHA)) { 292 return null; 293 } 294 } 295 296 SunVolatileImage vi = new AccelTypedVolatileImage(this, width, height, 297 transparency, type); 298 Surface sd = vi.getDestSurface(); 299 if (!(sd instanceof AccelSurface) || 300 ((AccelSurface)sd).getType() != type) 301 { 302 vi.flush(); 303 vi = null; 304 } 305 306 return vi; 307 } 308 309 /** 310 * {@inheritDoc} 311 * 312 * @see sun.java2d.pipe.hw.AccelGraphicsConfig#getContextCapabilities 313 */ 314 @Override 315 public ContextCapabilities getContextCapabilities() { 316 return device.getContextCapabilities(); 317 } 318 319 @Override 320 public void addDeviceEventListener(AccelDeviceEventListener l) { 321 AccelDeviceEventNotifier.addListener(l, device.getScreen()); 322 } 323 324 @Override 325 public void removeDeviceEventListener(AccelDeviceEventListener l) { 326 AccelDeviceEventNotifier.removeListener(l); 327 } 328 }