/*
 * Copyright (c) 2003, 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.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;
            sdCurrent = getBackupSurface();
            // Now, invalidate the old hardware-based SurfaceData
            SurfaceData oldData = sdAccel;
            sdAccel = null;
            oldData.invalidate();
        }
        // 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();
        }
    }
}
