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.Component; 29 import java.awt.GraphicsConfiguration; 30 import java.awt.Image; 31 import java.awt.Transparency; 32 import java.awt.image.ColorModel; 33 import sun.awt.Win32GraphicsConfig; 34 import sun.awt.image.SunVolatileImage; 35 import sun.awt.image.SurfaceManager; 36 import sun.awt.image.VolatileSurfaceManager; 37 import sun.awt.windows.WComponentPeer; 38 import sun.java2d.InvalidPipeException; 39 import sun.java2d.SurfaceData; 40 import static sun.java2d.pipe.hw.AccelSurface.*; 41 import static sun.java2d.d3d.D3DContext.D3DContextCaps.*; 42 import sun.java2d.windows.GDIWindowSurfaceData; 43 44 public class D3DVolatileSurfaceManager 45 extends VolatileSurfaceManager 46 { 47 private boolean accelerationEnabled; 48 private int restoreCountdown; 49 50 public D3DVolatileSurfaceManager(SunVolatileImage vImg, Object context) { 51 super(vImg, context); 52 53 /* 54 * We will attempt to accelerate this image only under the 55 * following conditions: 56 * - the image is opaque OR 57 * - the image is translucent AND 58 * - the GraphicsConfig supports the FBO extension OR 59 * - the GraphicsConfig has a stored alpha channel 60 */ 61 int transparency = vImg.getTransparency(); 62 D3DGraphicsDevice gd = (D3DGraphicsDevice) 63 vImg.getGraphicsConfig().getDevice(); 64 accelerationEnabled = 65 (transparency == Transparency.OPAQUE) || 66 (transparency == Transparency.TRANSLUCENT && 67 (gd.isCapPresent(CAPS_RT_PLAIN_ALPHA) || 68 gd.isCapPresent(CAPS_RT_TEXTURE_ALPHA))); 69 } 70 71 protected boolean isAccelerationEnabled() { 72 return accelerationEnabled; 73 } 74 public void setAccelerationEnabled(boolean accelerationEnabled) { 75 this.accelerationEnabled = accelerationEnabled; 76 } 77 78 /** 79 * Create a pbuffer-based SurfaceData object (or init the backbuffer 80 * of an existing window if this is a double buffered GraphicsConfig). 81 */ 82 @SuppressWarnings("deprecation") 83 protected SurfaceData initAcceleratedSurface() { 84 SurfaceData sData; 85 Component comp = vImg.getComponent(); 86 WComponentPeer peer = 87 (comp != null) ? (WComponentPeer)comp.getPeer() : null; 88 89 try { 90 boolean forceback = false; 91 if (context instanceof Boolean) { 92 forceback = ((Boolean)context).booleanValue(); 93 } 94 95 if (forceback) { 96 // peer must be non-null in this case 97 sData = D3DSurfaceData.createData(peer, vImg); 98 } else { 99 D3DGraphicsConfig gc = 100 (D3DGraphicsConfig)vImg.getGraphicsConfig(); 101 ColorModel cm = gc.getColorModel(vImg.getTransparency()); 102 int type = vImg.getForcedAccelSurfaceType(); 103 // if acceleration type is forced (type != UNDEFINED) then 104 // use the forced type, otherwise use RT_TEXTURE 105 if (type == UNDEFINED) { 106 type = RT_TEXTURE; 107 } 108 sData = D3DSurfaceData.createData(gc, 109 vImg.getWidth(), 110 vImg.getHeight(), 111 cm, vImg, 112 type); 113 } 114 } catch (NullPointerException ex) { 115 sData = null; 116 } catch (OutOfMemoryError er) { 117 sData = null; 118 } catch (InvalidPipeException ipe) { 119 sData = null; 120 } 121 122 return sData; 123 } 124 125 protected boolean isConfigValid(GraphicsConfiguration gc) { 126 return ((gc == null) || (gc == vImg.getGraphicsConfig())); 127 } 128 129 /** 130 * Set the number of iterations for restoreAcceleratedSurface to fail 131 * before attempting to restore the accelerated surface. 132 * 133 * @see #restoreAcceleratedSurface 134 * @see #handleVItoScreenOp 135 */ 136 private synchronized void setRestoreCountdown(int count) { 137 restoreCountdown = count; 138 } 139 140 /** 141 * Note that we create a new surface instead of restoring 142 * an old one. This will help with D3DContext revalidation. 143 */ 144 @Override 145 protected void restoreAcceleratedSurface() { 146 synchronized (this) { 147 if (restoreCountdown > 0) { 148 restoreCountdown--; 149 throw new 150 InvalidPipeException("Will attempt to restore surface " + 151 " in " + restoreCountdown); 152 } 153 } 154 155 SurfaceData sData = initAcceleratedSurface(); 156 if (sData != null) { 157 sdAccel = sData; 158 } else { 159 throw new InvalidPipeException("could not restore surface"); 160 // REMIND: alternatively, we could try this: 161 // ((D3DSurfaceData)sdAccel).restoreSurface(); 162 } 163 } 164 165 /** 166 * We're asked to restore contents by the accelerated surface, which means 167 * that it had been lost. 168 */ 169 @Override 170 public SurfaceData restoreContents() { 171 acceleratedSurfaceLost(); 172 return super.restoreContents(); 173 } 174 175 /** 176 * If the destination surface's peer can potentially handle accelerated 177 * on-screen rendering then it is likely that the condition which resulted 178 * in VI to Screen operation is temporary, so this method sets the 179 * restore countdown in hope that the on-screen accelerated rendering will 180 * resume. In the meantime the backup surface of the VISM will be used. 181 * 182 * The countdown is needed because otherwise we may never break out 183 * of "do { vi.validate()..} while(vi.lost)" loop since validate() could 184 * restore the source surface every time and it will get lost again on the 185 * next copy attempt, and we would never get a chance to use the backup 186 * surface. By using the countdown we allow the backup surface to be used 187 * while the screen surface gets sorted out, or if it for some reason can 188 * never be restored. 189 * 190 * If the destination surface's peer could never do accelerated onscreen 191 * rendering then the acceleration for the SurfaceManager associated with 192 * the source surface is disabled forever. 193 */ 194 static void handleVItoScreenOp(SurfaceData src, SurfaceData dst) { 195 if (src instanceof D3DSurfaceData && 196 dst instanceof GDIWindowSurfaceData) 197 { 198 D3DSurfaceData d3dsd = (D3DSurfaceData)src; 199 SurfaceManager mgr = 200 SurfaceManager.getManager((Image)d3dsd.getDestination()); 201 if (mgr instanceof D3DVolatileSurfaceManager) { 202 D3DVolatileSurfaceManager vsm = (D3DVolatileSurfaceManager)mgr; 203 if (vsm != null) { 204 d3dsd.setSurfaceLost(true); 205 206 GDIWindowSurfaceData wsd = (GDIWindowSurfaceData)dst; 207 WComponentPeer p = wsd.getPeer(); 208 if (D3DScreenUpdateManager.canUseD3DOnScreen(p, 209 (Win32GraphicsConfig)p.getGraphicsConfiguration(), 210 p.getBackBuffersNum())) 211 { 212 // 10 is only chosen to be greater than the number of 213 // times a sane person would call validate() inside 214 // a validation loop, and to reduce thrashing between 215 // accelerated and backup surfaces 216 vsm.setRestoreCountdown(10); 217 } else { 218 vsm.setAccelerationEnabled(false); 219 } 220 } 221 } 222 } 223 } 224 225 @Override 226 public void initContents() { 227 if (vImg.getForcedAccelSurfaceType() != TEXTURE) { 228 super.initContents(); 229 } 230 } 231 }