alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (VolatileSurfaceManager.java)

This example Java source code file (VolatileSurfaceManager.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

acceleratedimagecapabilities, awt, bufferedimage, displaychangedlistener, graphics, graphicsenvironment, image, imagecapabilities, java2d, object, override, sungraphicsenvironment, sunvolatileimage, surfacedata, undefined, volatilesurfacemanager

The VolatileSurfaceManager.java Java example source code

/*
 * 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();
        }
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java VolatileSurfaceManager.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.