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 D3DGraphicsConfig(D3DGraphicsDevice device)64 protected D3DGraphicsConfig(D3DGraphicsDevice device) { 65 super(device, 0); 66 this.device = device; 67 } 68 createManagedSurface(int w, int h, int transparency)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 displayChanged()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 getColorModel(int transparency)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 toString()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 createSurfaceData(WComponentPeer peer, int numBackBuffers)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 assertOperationSupported(Component target, int numBuffers, BufferCapabilities caps)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 createBackBuffer(WComponentPeer peer)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 flip(WComponentPeer peer, Component target, VolatileImage backBuffer, int x1, int y1, int x2, int y2, BufferCapabilities.FlipContents flipAction)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 { D3DBufferCaps()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 isMultiBufferAvailable()225 public boolean isMultiBufferAvailable() { 226 return true; 227 } 228 229 } 230 231 @Override getBufferCapabilities()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 { D3DImageCaps()240 private D3DImageCaps() { 241 super(true); 242 } 243 @Override isTrueVolatile()244 public boolean isTrueVolatile() { 245 return true; 246 } 247 } 248 249 @Override getImageCapabilities()250 public ImageCapabilities getImageCapabilities() { 251 return imageCaps; 252 } 253 getD3DDevice()254 D3DGraphicsDevice getD3DDevice() { 255 return device; 256 } 257 258 /** 259 * {@inheritDoc} 260 * 261 * @see sun.java2d.pipe.hw.BufferedContextProvider#getContext 262 */ 263 @Override getContext()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 createCompatibleVolatileImage(int width, int height, int transparency, int type)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 getContextCapabilities()314 public ContextCapabilities getContextCapabilities() { 315 return device.getContextCapabilities(); 316 } 317 318 @Override addDeviceEventListener(AccelDeviceEventListener l)319 public void addDeviceEventListener(AccelDeviceEventListener l) { 320 AccelDeviceEventNotifier.addListener(l, device.getScreen()); 321 } 322 323 @Override removeDeviceEventListener(AccelDeviceEventListener l)324 public void removeDeviceEventListener(AccelDeviceEventListener l) { 325 AccelDeviceEventNotifier.removeListener(l); 326 } 327 } 328