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