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