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.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 protected SurfaceData initAcceleratedSurface() { 83 SurfaceData sData; 84 Component comp = vImg.getComponent(); 85 WComponentPeer peer = 86 (comp != null) ? (WComponentPeer)comp.getPeer() : null; 87 88 try { 89 boolean forceback = false; 90 if (context instanceof Boolean) { 91 forceback = ((Boolean)context).booleanValue(); 92 } 93 94 if (forceback) { 95 // peer must be non-null in this case 96 sData = D3DSurfaceData.createData(peer, vImg); 97 } else { 98 D3DGraphicsConfig gc = 99 (D3DGraphicsConfig)vImg.getGraphicsConfig(); 100 ColorModel cm = gc.getColorModel(vImg.getTransparency()); 101 int type = vImg.getForcedAccelSurfaceType(); 102 // if acceleration type is forced (type != UNDEFINED) then 103 // use the forced type, otherwise use RT_TEXTURE 104 if (type == UNDEFINED) { 105 type = RT_TEXTURE; 106 } 107 sData = D3DSurfaceData.createData(gc, 108 vImg.getWidth(), 109 vImg.getHeight(), 110 cm, vImg, 111 type); 112 } 113 } catch (NullPointerException ex) { 114 sData = null; 115 } catch (OutOfMemoryError er) { 116 sData = null; 117 } catch (InvalidPipeException ipe) { 118 sData = null; 119 } 120 121 return sData; 122 } 123 124 protected boolean isConfigValid(GraphicsConfiguration gc) { 125 return ((gc == null) || (gc == vImg.getGraphicsConfig())); 126 } 127 128 /** 129 * Set the number of iterations for restoreAcceleratedSurface to fail 130 * before attempting to restore the accelerated surface. 131 * 132 * @see #restoreAcceleratedSurface 133 * @see #handleVItoScreenOp 134 */ 135 private synchronized void setRestoreCountdown(int count) { 136 restoreCountdown = count; 137 } 138 139 /** 140 * Note that we create a new surface instead of restoring 141 * an old one. This will help with D3DContext revalidation. 142 */ 143 @Override 144 protected void restoreAcceleratedSurface() { 145 synchronized (this) { 146 if (restoreCountdown > 0) { 147 restoreCountdown--; 148 throw new 149 InvalidPipeException("Will attempt to restore surface " + 150 " in " + restoreCountdown); 151 } 152 } 153 154 SurfaceData sData = initAcceleratedSurface(); 155 if (sData != null) { 156 sdAccel = sData; 157 } else { 158 throw new InvalidPipeException("could not restore surface"); 159 // REMIND: alternatively, we could try this: 160 // ((D3DSurfaceData)sdAccel).restoreSurface(); 161 } 162 } 163 164 /** 165 * We're asked to restore contents by the accelerated surface, which means 166 * that it had been lost. 167 */ 168 @Override 169 public SurfaceData restoreContents() { 170 acceleratedSurfaceLost(); 171 return super.restoreContents(); 172 } 173 174 /** 175 * If the destination surface's peer can potentially handle accelerated 176 * on-screen rendering then it is likely that the condition which resulted 177 * in VI to Screen operation is temporary, so this method sets the 178 * restore countdown in hope that the on-screen accelerated rendering will 179 * resume. In the meantime the backup surface of the VISM will be used. 180 * 181 * The countdown is needed because otherwise we may never break out 182 * of "do { vi.validate()..} while(vi.lost)" loop since validate() could 183 * restore the source surface every time and it will get lost again on the 184 * next copy attempt, and we would never get a chance to use the backup 185 * surface. By using the countdown we allow the backup surface to be used 186 * while the screen surface gets sorted out, or if it for some reason can 187 * never be restored. 188 * 189 * If the destination surface's peer could never do accelerated onscreen 190 * rendering then the acceleration for the SurfaceManager associated with 191 * the source surface is disabled forever. 192 */ 193 static void handleVItoScreenOp(SurfaceData src, SurfaceData dst) { 194 if (src instanceof D3DSurfaceData && 195 dst instanceof GDIWindowSurfaceData) 196 { 197 D3DSurfaceData d3dsd = (D3DSurfaceData)src; 198 SurfaceManager mgr = 199 SurfaceManager.getManager((Image)d3dsd.getDestination()); 200 if (mgr instanceof D3DVolatileSurfaceManager) { 201 D3DVolatileSurfaceManager vsm = (D3DVolatileSurfaceManager)mgr; 202 if (vsm != null) { 203 d3dsd.setSurfaceLost(true); 204 205 GDIWindowSurfaceData wsd = (GDIWindowSurfaceData)dst; 206 WComponentPeer p = wsd.getPeer(); 207 if (D3DScreenUpdateManager.canUseD3DOnScreen(p, 208 (Win32GraphicsConfig)p.getGraphicsConfiguration(), 209 p.getBackBuffersNum())) 210 { 211 // 10 is only chosen to be greater than the number of 212 // times a sane person would call validate() inside 213 // a validation loop, and to reduce thrashing between 214 // accelerated and backup surfaces 215 vsm.setRestoreCountdown(10); 216 } else { 217 vsm.setAccelerationEnabled(false); 218 } 219 } 220 } 221 } 222 } 223 224 @Override 225 public void initContents() { 226 if (vImg.getForcedAccelSurfaceType() != TEXTURE) { 227 super.initContents(); 228 } 229 } 230 }