| /* |
| * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package sun.java2d.d3d; |
| |
| import java.awt.Component; |
| import java.awt.GraphicsConfiguration; |
| import java.awt.Image; |
| import java.awt.Transparency; |
| import java.awt.image.ColorModel; |
| import sun.awt.Win32GraphicsConfig; |
| import sun.awt.image.SunVolatileImage; |
| import sun.awt.image.SurfaceManager; |
| import sun.awt.image.VolatileSurfaceManager; |
| import sun.awt.windows.WComponentPeer; |
| import sun.java2d.InvalidPipeException; |
| import sun.java2d.SurfaceData; |
| import static sun.java2d.pipe.hw.AccelSurface.*; |
| import static sun.java2d.d3d.D3DContext.D3DContextCaps.*; |
| import sun.java2d.windows.GDIWindowSurfaceData; |
| |
| public class D3DVolatileSurfaceManager |
| extends VolatileSurfaceManager |
| { |
| private boolean accelerationEnabled; |
| private int restoreCountdown; |
| |
| public D3DVolatileSurfaceManager(SunVolatileImage vImg, Object context) { |
| super(vImg, context); |
| |
| /* |
| * We will attempt to accelerate this image only under the |
| * following conditions: |
| * - the image is opaque OR |
| * - the image is translucent AND |
| * - the GraphicsConfig supports the FBO extension OR |
| * - the GraphicsConfig has a stored alpha channel |
| */ |
| int transparency = vImg.getTransparency(); |
| D3DGraphicsDevice gd = (D3DGraphicsDevice) |
| vImg.getGraphicsConfig().getDevice(); |
| accelerationEnabled = |
| (transparency == Transparency.OPAQUE) || |
| (transparency == Transparency.TRANSLUCENT && |
| (gd.isCapPresent(CAPS_RT_PLAIN_ALPHA) || |
| gd.isCapPresent(CAPS_RT_TEXTURE_ALPHA))); |
| } |
| |
| protected boolean isAccelerationEnabled() { |
| return accelerationEnabled; |
| } |
| public void setAccelerationEnabled(boolean accelerationEnabled) { |
| this.accelerationEnabled = accelerationEnabled; |
| } |
| |
| /** |
| * Create a pbuffer-based SurfaceData object (or init the backbuffer |
| * of an existing window if this is a double buffered GraphicsConfig). |
| */ |
| protected SurfaceData initAcceleratedSurface() { |
| SurfaceData sData; |
| Component comp = vImg.getComponent(); |
| WComponentPeer peer = |
| (comp != null) ? (WComponentPeer)comp.getPeer() : null; |
| |
| try { |
| boolean forceback = false; |
| if (context instanceof Boolean) { |
| forceback = ((Boolean)context).booleanValue(); |
| } |
| |
| if (forceback) { |
| // peer must be non-null in this case |
| sData = D3DSurfaceData.createData(peer, vImg); |
| } else { |
| D3DGraphicsConfig gc = |
| (D3DGraphicsConfig)vImg.getGraphicsConfig(); |
| ColorModel cm = gc.getColorModel(vImg.getTransparency()); |
| int type = vImg.getForcedAccelSurfaceType(); |
| // if acceleration type is forced (type != UNDEFINED) then |
| // use the forced type, otherwise use RT_TEXTURE |
| if (type == UNDEFINED) { |
| type = RT_TEXTURE; |
| } |
| sData = D3DSurfaceData.createData(gc, |
| vImg.getWidth(), |
| vImg.getHeight(), |
| cm, vImg, |
| type); |
| } |
| } catch (NullPointerException ex) { |
| sData = null; |
| } catch (OutOfMemoryError er) { |
| sData = null; |
| } catch (InvalidPipeException ipe) { |
| sData = null; |
| } |
| |
| return sData; |
| } |
| |
| protected boolean isConfigValid(GraphicsConfiguration gc) { |
| return ((gc == null) || (gc == vImg.getGraphicsConfig())); |
| } |
| |
| /** |
| * Set the number of iterations for restoreAcceleratedSurface to fail |
| * before attempting to restore the accelerated surface. |
| * |
| * @see #restoreAcceleratedSurface |
| * @see #handleVItoScreenOp |
| */ |
| private synchronized void setRestoreCountdown(int count) { |
| restoreCountdown = count; |
| } |
| |
| /** |
| * Note that we create a new surface instead of restoring |
| * an old one. This will help with D3DContext revalidation. |
| */ |
| @Override |
| protected void restoreAcceleratedSurface() { |
| synchronized (this) { |
| if (restoreCountdown > 0) { |
| restoreCountdown--; |
| throw new |
| InvalidPipeException("Will attempt to restore surface " + |
| " in " + restoreCountdown); |
| } |
| } |
| |
| SurfaceData sData = initAcceleratedSurface(); |
| if (sData != null) { |
| sdAccel = sData; |
| } else { |
| throw new InvalidPipeException("could not restore surface"); |
| // REMIND: alternatively, we could try this: |
| // ((D3DSurfaceData)sdAccel).restoreSurface(); |
| } |
| } |
| |
| /** |
| * We're asked to restore contents by the accelerated surface, which means |
| * that it had been lost. |
| */ |
| @Override |
| public SurfaceData restoreContents() { |
| acceleratedSurfaceLost(); |
| return super.restoreContents(); |
| } |
| |
| /** |
| * If the destination surface's peer can potentially handle accelerated |
| * on-screen rendering then it is likely that the condition which resulted |
| * in VI to Screen operation is temporary, so this method sets the |
| * restore countdown in hope that the on-screen accelerated rendering will |
| * resume. In the meantime the backup surface of the VISM will be used. |
| * |
| * The countdown is needed because otherwise we may never break out |
| * of "do { vi.validate()..} while(vi.lost)" loop since validate() could |
| * restore the source surface every time and it will get lost again on the |
| * next copy attempt, and we would never get a chance to use the backup |
| * surface. By using the countdown we allow the backup surface to be used |
| * while the screen surface gets sorted out, or if it for some reason can |
| * never be restored. |
| * |
| * If the destination surface's peer could never do accelerated onscreen |
| * rendering then the acceleration for the SurfaceManager associated with |
| * the source surface is disabled forever. |
| */ |
| static void handleVItoScreenOp(SurfaceData src, SurfaceData dst) { |
| if (src instanceof D3DSurfaceData && |
| dst instanceof GDIWindowSurfaceData) |
| { |
| D3DSurfaceData d3dsd = (D3DSurfaceData)src; |
| SurfaceManager mgr = |
| SurfaceManager.getManager((Image)d3dsd.getDestination()); |
| if (mgr instanceof D3DVolatileSurfaceManager) { |
| D3DVolatileSurfaceManager vsm = (D3DVolatileSurfaceManager)mgr; |
| if (vsm != null) { |
| d3dsd.setSurfaceLost(true); |
| |
| GDIWindowSurfaceData wsd = (GDIWindowSurfaceData)dst; |
| WComponentPeer p = wsd.getPeer(); |
| if (D3DScreenUpdateManager.canUseD3DOnScreen(p, |
| (Win32GraphicsConfig)p.getGraphicsConfiguration(), |
| p.getBackBuffersNum())) |
| { |
| // 10 is only chosen to be greater than the number of |
| // times a sane person would call validate() inside |
| // a validation loop, and to reduce thrashing between |
| // accelerated and backup surfaces |
| vsm.setRestoreCountdown(10); |
| } else { |
| vsm.setAccelerationEnabled(false); |
| } |
| } |
| } |
| } |
| } |
| |
| @Override |
| public void initContents() { |
| if (vImg.getForcedAccelSurfaceType() != TEXTURE) { |
| super.initContents(); |
| } |
| } |
| } |