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