--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.desktop/share/classes/sun/awt/image/VolatileSurfaceManager.java Sun Aug 17 15:54:13 2014 +0100
@@ -0,0 +1,410 @@
+/*
+ * Copyright (c) 2003, 2012, 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.awt.image;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsEnvironment;
+import java.awt.ImageCapabilities;
+import java.awt.image.BufferedImage;
+import java.awt.image.VolatileImage;
+import sun.awt.DisplayChangedListener;
+import sun.awt.image.SunVolatileImage;
+import sun.java2d.SunGraphicsEnvironment;
+import sun.java2d.SurfaceData;
+import sun.java2d.loops.CompositeType;
+import static sun.java2d.pipe.hw.AccelSurface.*;
+
+/**
+ * This SurfaceManager variant manages an accelerated volatile surface, if it
+ * is possible to create that surface. If there is limited accelerated
+ * memory, or if the volatile surface disappears due to an operating system
+ * event, the VolatileSurfaceManager will attempt to restore the
+ * accelerated surface. If that fails, a system memory surface will be
+ * created in its place.
+ */
+public abstract class VolatileSurfaceManager
+ extends SurfaceManager
+ implements DisplayChangedListener
+{
+ /**
+ * A reference to the VolatileImage whose contents are being managed.
+ */
+ protected SunVolatileImage vImg;
+
+ /**
+ * The accelerated SurfaceData object.
+ */
+ protected SurfaceData sdAccel;
+
+ /**
+ * The software-based SurfaceData object. Only create when first asked
+ * to (otherwise it is a waste of memory as it will only be used in
+ * situations of surface loss).
+ */
+ protected SurfaceData sdBackup;
+
+ /**
+ * The current SurfaceData object.
+ */
+ protected SurfaceData sdCurrent;
+
+ /**
+ * A record-keeping object. This keeps track of which SurfaceData was
+ * in use during the last call to validate(). This lets us see whether
+ * the SurfaceData object has changed since then and allows us to return
+ * the correct returnCode to the user in the validate() call.
+ */
+ protected SurfaceData sdPrevious;
+
+ /**
+ * Tracks loss of surface contents; queriable by user to see whether
+ * contents need to be restored.
+ */
+ protected boolean lostSurface;
+
+ /**
+ * Context for extra initialization parameters.
+ */
+ protected Object context;
+
+ protected VolatileSurfaceManager(SunVolatileImage vImg, Object context) {
+ this.vImg = vImg;
+ this.context = context;
+
+ GraphicsEnvironment ge =
+ GraphicsEnvironment.getLocalGraphicsEnvironment();
+ // We could have a HeadlessGE at this point, so double-check before
+ // assuming anything.
+ if (ge instanceof SunGraphicsEnvironment) {
+ ((SunGraphicsEnvironment)ge).addDisplayChangedListener(this);
+ }
+ }
+
+ /**
+ * This init function is separate from the constructor because the
+ * things we are doing here necessitate the object's existence.
+ * Otherwise, we end up calling into a subclass' overridden method
+ * during construction, before that subclass is completely constructed.
+ */
+ public void initialize() {
+ if (isAccelerationEnabled()) {
+ sdAccel = initAcceleratedSurface();
+ if (sdAccel != null) {
+ sdCurrent = sdAccel;
+ }
+ }
+ // only initialize the backup surface for images with unforced
+ // acceleration type
+ if (sdCurrent == null &&
+ vImg.getForcedAccelSurfaceType() == UNDEFINED)
+ {
+ sdCurrent = getBackupSurface();
+ }
+ }
+
+ public SurfaceData getPrimarySurfaceData() {
+ return sdCurrent;
+ }
+
+ /**
+ * Returns true if acceleration is enabled. If not, we simply use the
+ * backup SurfaceData object and return quickly from most methods
+ * in this class.
+ */
+ protected abstract boolean isAccelerationEnabled();
+
+ /**
+ * Get the image ready for rendering. This method is called to make
+ * sure that the accelerated SurfaceData exists and is
+ * ready to be used. Users call this method prior to any set of
+ * rendering to or from the image, to make sure the image is ready
+ * and compatible with the given GraphicsConfiguration.
+ *
+ * The image may not be "ready" if either we had problems creating
+ * it in the first place (e.g., there was no space in vram) or if
+ * the surface became lost (e.g., some other app or the OS caused
+ * vram surfaces to be removed).
+ *
+ * Note that we want to return RESTORED in any situation where the
+ * SurfaceData is different than it was last time. So whether it's
+ * software or hardware, if we have a different SurfaceData object,
+ * then the contents have been altered and we must reflect that
+ * change to the user.
+ */
+ public int validate(GraphicsConfiguration gc) {
+ int returnCode = VolatileImage.IMAGE_OK;
+ boolean lostSurfaceTmp = lostSurface;
+ lostSurface = false;
+
+ if (isAccelerationEnabled()) {
+ if (!isConfigValid(gc)) {
+ // If we're asked to render to a different device than the
+ // one we were created under, return INCOMPATIBLE error code.
+ // Note that a null gc simply ignores the incompatibility
+ // issue
+ returnCode = VolatileImage.IMAGE_INCOMPATIBLE;
+ } else if (sdAccel == null) {
+ // We either had problems creating the surface or the display
+ // mode changed and we nullified the old one. Try it again.
+ sdAccel = initAcceleratedSurface();
+ if (sdAccel != null) {
+ // set the current SurfaceData to accelerated version
+ sdCurrent = sdAccel;
+ // we don't need the system memory surface anymore, so
+ // let's release it now (it can always be restored later)
+ sdBackup = null;
+ returnCode = VolatileImage.IMAGE_RESTORED;
+ } else {
+ sdCurrent = getBackupSurface();
+ }
+ } else if (sdAccel.isSurfaceLost()) {
+ try {
+ restoreAcceleratedSurface();
+ // set the current SurfaceData to accelerated version
+ sdCurrent = sdAccel;
+ // restoration successful: accel surface no longer lost
+ sdAccel.setSurfaceLost(false);
+ // we don't need the system memory surface anymore, so
+ // let's release it now (it can always be restored later)
+ sdBackup = null;
+ returnCode = VolatileImage.IMAGE_RESTORED;
+ } catch (sun.java2d.InvalidPipeException e) {
+ // Set the current SurfaceData to software version so that
+ // drawing can continue. Note that we still have
+ // the lostAccelSurface flag set so that we will continue
+ // to attempt to restore the accelerated surface.
+ sdCurrent = getBackupSurface();
+ }
+ } else if (lostSurfaceTmp) {
+ // Something else triggered this loss/restoration. Could
+ // be a palette change that didn't require a SurfaceData
+ // recreation but merely a re-rendering of the pixels.
+ returnCode = VolatileImage.IMAGE_RESTORED;
+ }
+ } else if (sdAccel != null) {
+ // if the "acceleration enabled" state changed to disabled,
+ // switch to software surface
+ sdCurrent = getBackupSurface();
+ sdAccel = null;
+ returnCode = VolatileImage.IMAGE_RESTORED;
+ }
+
+ if ((returnCode != VolatileImage.IMAGE_INCOMPATIBLE) &&
+ (sdCurrent != sdPrevious))
+ {
+ // contents have changed - return RESTORED to user
+ sdPrevious = sdCurrent;
+ returnCode = VolatileImage.IMAGE_RESTORED;
+ }
+
+ if (returnCode == VolatileImage.IMAGE_RESTORED) {
+ // clear the current surface with the background color,
+ // only if the surface has been restored
+ initContents();
+ }
+
+ return returnCode;
+ }
+
+ /**
+ * Returns true if rendering data was lost since the last validate call.
+ *
+ * @see java.awt.image.VolatileImage#contentsLost
+ */
+ public boolean contentsLost() {
+ return lostSurface;
+ }
+
+ /**
+ * Creates a new accelerated surface that is compatible with the
+ * current GraphicsConfiguration. Returns the new accelerated
+ * SurfaceData object, or null if the surface creation was not successful.
+ *
+ * Platform-specific subclasses should initialize an accelerated
+ * surface (e.g. a DirectDraw surface on Windows, an OpenGL pbuffer,
+ * or an X11 pixmap).
+ */
+ protected abstract SurfaceData initAcceleratedSurface();
+
+ /**
+ * Creates a software-based surface (of type BufImgSurfaceData).
+ * The software representation is only created when needed, which
+ * is only during some situation in which the hardware surface
+ * cannot be allocated. This allows apps to at least run,
+ * albeit more slowly than they would otherwise.
+ */
+ protected SurfaceData getBackupSurface() {
+ if (sdBackup == null) {
+ BufferedImage bImg = vImg.getBackupImage();
+ // Sabotage the acceleration capabilities of the BufImg surface
+ SunWritableRaster.stealTrackable(bImg
+ .getRaster()
+ .getDataBuffer()).setUntrackable();
+ sdBackup = BufImgSurfaceData.createData(bImg);
+ }
+ return sdBackup;
+ }
+
+ /**
+ * Set contents of the current SurfaceData to default state (i.e. clear
+ * the background).
+ */
+ public void initContents() {
+ // images with forced acceleration type may have a null sdCurrent
+ // because we do not create a backup surface for them
+ if (sdCurrent != null) {
+ Graphics g = vImg.createGraphics();
+ g.clearRect(0, 0, vImg.getWidth(), vImg.getHeight());
+ g.dispose();
+ }
+ }
+
+ /**
+ * Called from a SurfaceData object, indicating that our
+ * accelerated surface has been lost and should be restored (perhaps
+ * using a backup system memory surface). Returns the newly restored
+ * primary SurfaceData object.
+ */
+ public SurfaceData restoreContents() {
+ return getBackupSurface();
+ }
+
+ /**
+ * If the accelerated surface is the current SurfaceData for this manager,
+ * sets the variable lostSurface to true, which indicates that something
+ * happened to the image under management. This variable is used in the
+ * validate method to tell the caller that the surface contents need to
+ * be restored.
+ */
+ public void acceleratedSurfaceLost() {
+ if (isAccelerationEnabled() && (sdCurrent == sdAccel)) {
+ lostSurface = true;
+ }
+ }
+
+ /**
+ * Restore sdAccel in case it was lost. Do nothing in this
+ * default case; platform-specific implementations may do more in
+ * this situation as appropriate.
+ */
+ protected void restoreAcceleratedSurface() {
+ }
+
+ /**
+ * Called from SunGraphicsEnv when there has been a display mode change.
+ * Note that we simply invalidate hardware surfaces here; we do not
+ * attempt to recreate or re-render them. This is to avoid threading
+ * conflicts with the native toolkit and associated threads. Instead,
+ * we just nullify the old surface data object and wait for a future
+ * method in the rendering process to recreate the surface.
+ */
+ public void displayChanged() {
+ if (!isAccelerationEnabled()) {
+ return;
+ }
+ lostSurface = true;
+ if (sdAccel != null) {
+ // First, nullify the software surface. This guards against
+ // using a SurfaceData that was created in a different
+ // display mode.
+ sdBackup = null;
+ // Now, invalidate the old hardware-based SurfaceData
+ // Note that getBackupSurface may set sdAccel to null so we have to invalidate it before
+ SurfaceData oldData = sdAccel;
+ sdAccel = null;
+ oldData.invalidate();
+ sdCurrent = getBackupSurface();
+ }
+ // Update graphicsConfig for the vImg in case it changed due to
+ // this display change event
+ vImg.updateGraphicsConfig();
+ }
+
+ /**
+ * When device palette changes, need to force a new copy
+ * of the image into our hardware cache to update the
+ * color indices of the pixels (indexed mode only).
+ */
+ public void paletteChanged() {
+ lostSurface = true;
+ }
+
+ /**
+ * Called by validate() to see whether the GC passed in is ok for
+ * rendering to. This generic implementation checks to see
+ * whether the GC is either null or is from the same
+ * device as the one that this image was created on. Platform-
+ * specific implementations may perform other checks as
+ * appropriate.
+ */
+ protected boolean isConfigValid(GraphicsConfiguration gc) {
+ return ((gc == null) ||
+ (gc.getDevice() == vImg.getGraphicsConfig().getDevice()));
+ }
+
+ @Override
+ public ImageCapabilities getCapabilities(GraphicsConfiguration gc) {
+ if (isConfigValid(gc)) {
+ return isAccelerationEnabled() ?
+ new AcceleratedImageCapabilities() :
+ new ImageCapabilities(false);
+ }
+ return super.getCapabilities(gc);
+ }
+
+ private class AcceleratedImageCapabilities
+ extends ImageCapabilities
+ {
+ AcceleratedImageCapabilities() {
+ super(false);
+ }
+ @Override
+ public boolean isAccelerated() {
+ return (sdCurrent == sdAccel);
+ }
+ @Override
+ public boolean isTrueVolatile() {
+ return isAccelerated();
+ }
+ }
+
+ /**
+ * Releases any associated hardware memory for this image by
+ * calling flush on sdAccel. This method forces a lostSurface
+ * situation so any future operations on the image will need to
+ * revalidate the image first.
+ */
+ public void flush() {
+ lostSurface = true;
+ SurfaceData oldSD = sdAccel;
+ sdAccel = null;
+ if (oldSD != null) {
+ oldSD.flush();
+ }
+ }
+}