/*
 * Copyright (c) 2005, 2013, 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 javax.swing;

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.lang.reflect.*;
import java.lang.ref.WeakReference;
import java.util.*;

import com.sun.java.swing.SwingUtilities3;

import sun.awt.SubRegionShowable;
import sun.java2d.SunGraphics2D;
import sun.java2d.pipe.hw.ExtendedBufferCapabilities;
import sun.awt.SunToolkit;
import sun.util.logging.PlatformLogger;

/**
 * A PaintManager implementation that uses a BufferStrategy for
 * rendering.
 *
 * @author Scott Violet
 */
class BufferStrategyPaintManager extends RepaintManager.PaintManager {
    //
    // All drawing is done to a BufferStrategy.  At the end of painting
    // (endPaint) the region that was painted is flushed to the screen
    // (using BufferStrategy.show).
    //
    // PaintManager.show is overriden to show directly from the
    // BufferStrategy (when using blit), if successful true is
    // returned and a paint event will not be generated.  To avoid
    // showing from the buffer while painting a locking scheme is
    // implemented.  When beginPaint is invoked the field painting is
    // set to true.  If painting is true and show is invoked we
    // immediately return false.  This is done to avoid blocking the
    // toolkit thread while painting happens.  In a similar way when
    // show is invoked the field showing is set to true, beginPaint
    // will then block until showing is true.  This scheme ensures we
    // only ever have one thread using the BufferStrategy and it also
    // ensures the toolkit thread remains as responsive as possible.
    //
    // If we're using a flip strategy the contents of the backbuffer may
    // have changed and so show only attempts to show from the backbuffer
    // if we get a blit strategy.
    //

    //
    // Methods used to create BufferStrategy for Applets.
    //
    private static Method COMPONENT_CREATE_BUFFER_STRATEGY_METHOD;
    private static Method COMPONENT_GET_BUFFER_STRATEGY_METHOD;

    private static final PlatformLogger LOGGER = PlatformLogger.getLogger(
                           "javax.swing.BufferStrategyPaintManager");

    /**
     * List of BufferInfos.  We don't use a Map primarily because
     * there are typically only a handful of top level components making
     * a Map overkill.
     */
    private ArrayList<BufferInfo> bufferInfos;

    /**
     * Indicates <code>beginPaint</code> has been invoked.  This is
     * set to true for the life of beginPaint/endPaint pair.
     */
    private boolean painting;
    /**
     * Indicates we're in the process of showing.  All painting, on the EDT,
     * is blocked while this is true.
     */
    private boolean showing;

    //
    // Region that we need to flush.  When beginPaint is called these are
    // reset and any subsequent calls to paint/copyArea then update these
    // fields accordingly.  When endPaint is called we then try and show
    // the accumulated region.
    // These fields are in the coordinate system of the root.
    //
    private int accumulatedX;
    private int accumulatedY;
    private int accumulatedMaxX;
    private int accumulatedMaxY;

    //
    // The following fields are set by prepare
    //

    /**
     * Farthest JComponent ancestor for the current paint/copyArea.
     */
    private JComponent rootJ;
    /**
     * Location of component being painted relative to root.
     */
    private int xOffset;
    /**
     * Location of component being painted relative to root.
     */
    private int yOffset;
    /**
     * Graphics from the BufferStrategy.
     */
    private Graphics bsg;
    /**
     * BufferStrategy currently being used.
     */
    private BufferStrategy bufferStrategy;
    /**
     * BufferInfo corresponding to root.
     */
    private BufferInfo bufferInfo;

    /**
     * Set to true if the bufferInfo needs to be disposed when current
     * paint loop is done.
     */
    private boolean disposeBufferOnEnd;

    private static Method getGetBufferStrategyMethod() {
        if (COMPONENT_GET_BUFFER_STRATEGY_METHOD == null) {
            getMethods();
        }
        return COMPONENT_GET_BUFFER_STRATEGY_METHOD;
    }

    private static Method getCreateBufferStrategyMethod() {
        if (COMPONENT_CREATE_BUFFER_STRATEGY_METHOD == null) {
            getMethods();
        }
        return COMPONENT_CREATE_BUFFER_STRATEGY_METHOD;
    }

    private static void getMethods() {
        java.security.AccessController.doPrivileged(
                            new java.security.PrivilegedAction<Object>() {
            public Object run() {
                try {
                    COMPONENT_CREATE_BUFFER_STRATEGY_METHOD = Component.class.
                              getDeclaredMethod("createBufferStrategy",
                                                new Class[] { int.class,
                                                BufferCapabilities.class });
                    COMPONENT_CREATE_BUFFER_STRATEGY_METHOD.
                                            setAccessible(true);
                    COMPONENT_GET_BUFFER_STRATEGY_METHOD = Component.class.
                              getDeclaredMethod("getBufferStrategy");
                    COMPONENT_GET_BUFFER_STRATEGY_METHOD.setAccessible(true);
                } catch (SecurityException e) {
                    assert false;
                } catch (NoSuchMethodException nsme) {
                    assert false;
                }
                return null;
            }
        });
    }

    BufferStrategyPaintManager() {
        bufferInfos = new ArrayList<BufferInfo>(1);
    }

    //
    // PaintManager methods
    //

    /**
     * Cleans up any created BufferStrategies.
     */
    protected void dispose() {
        // dipose can be invoked at any random time. To avoid
        // threading dependancies we do the actual diposing via an
        // invokeLater.
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                java.util.List<BufferInfo> bufferInfos;
                synchronized(BufferStrategyPaintManager.this) {
                    while (showing) {
                        try {
                            BufferStrategyPaintManager.this.wait();
                        } catch (InterruptedException ie) {
                        }
                    }
                    bufferInfos = BufferStrategyPaintManager.this.bufferInfos;
                    BufferStrategyPaintManager.this.bufferInfos = null;
                }
                dispose(bufferInfos);
            }
        });
    }

    private void dispose(java.util.List<BufferInfo> bufferInfos) {
        if (LOGGER.isLoggable(PlatformLogger.Level.FINER)) {
            LOGGER.finer("BufferStrategyPaintManager disposed",
                         new RuntimeException());
        }
        if (bufferInfos != null) {
            for (BufferInfo bufferInfo : bufferInfos) {
                bufferInfo.dispose();
            }
        }
    }

    /**
     * Shows the specified region of the back buffer.  This will return
     * true if successful, false otherwise.  This is invoked on the
     * toolkit thread in response to an expose event.
     */
    public boolean show(Container c, int x, int y, int w, int h) {
        synchronized(this) {
            if (painting) {
                // Don't show from backbuffer while in the process of
                // painting.
                return false;
            }
            showing = true;
        }
        try {
            BufferInfo info = getBufferInfo(c);
            BufferStrategy bufferStrategy;
            if (info != null && info.isInSync() &&
                (bufferStrategy = info.getBufferStrategy(false)) != null) {
                SubRegionShowable bsSubRegion =
                        (SubRegionShowable)bufferStrategy;
                boolean paintAllOnExpose = info.getPaintAllOnExpose();
                info.setPaintAllOnExpose(false);
                if (bsSubRegion.showIfNotLost(x, y, (x + w), (y + h))) {
                    return !paintAllOnExpose;
                }
                // Mark the buffer as needing to be repainted.  We don't
                // immediately do a repaint as this method will return false
                // indicating a PaintEvent should be generated which will
                // trigger a complete repaint.
                bufferInfo.setContentsLostDuringExpose(true);
            }
        }
        finally {
            synchronized(this) {
                showing = false;
                notifyAll();
            }
        }
        return false;
    }

    public boolean paint(JComponent paintingComponent,
                         JComponent bufferComponent, Graphics g,
                         int x, int y, int w, int h) {
        Container root = fetchRoot(paintingComponent);

        if (prepare(paintingComponent, root, true, x, y, w, h)) {
            if ((g instanceof SunGraphics2D) &&
                    ((SunGraphics2D)g).getDestination() == root) {
                // BufferStrategy may have already constrained the Graphics. To
                // account for that we revert the constrain, then apply a
                // constrain for Swing on top of that.
                int cx = ((SunGraphics2D)bsg).constrainX;
                int cy = ((SunGraphics2D)bsg).constrainY;
                if (cx != 0 || cy != 0) {
                    bsg.translate(-cx, -cy);
                }
                ((SunGraphics2D)bsg).constrain(xOffset + cx, yOffset + cy,
                                               x + w, y + h);
                bsg.setClip(x, y, w, h);
                paintingComponent.paintToOffscreen(bsg, x, y, w, h,
                                                   x + w, y + h);
                accumulate(xOffset + x, yOffset + y, w, h);
                return true;
            } else {
                // Assume they are going to eventually render to the screen.
                // This disables showing from backbuffer until a complete
                // repaint occurs.
                bufferInfo.setInSync(false);
                // Fall through to old rendering.
            }
        }
        // Invalid root, do what Swing has always done.
        if (LOGGER.isLoggable(PlatformLogger.Level.FINER)) {
            LOGGER.finer("prepare failed");
        }
        return super.paint(paintingComponent, bufferComponent, g, x, y, w, h);
    }

    public void copyArea(JComponent c, Graphics g, int x, int y, int w, int h,
                         int deltaX, int deltaY, boolean clip) {
        // Note: this method is only called internally and we know that
        // g is from a heavyweight Component, so no check is necessary as
        // it is in paint() above.
        //
        // If the buffer isn't in sync there is no point in doing a copyArea,
        // it has garbage.
        Container root = fetchRoot(c);

        if (prepare(c, root, false, 0, 0, 0, 0) && bufferInfo.isInSync()) {
            if (clip) {
                Rectangle cBounds = c.getVisibleRect();
                int relX = xOffset + x;
                int relY = yOffset + y;
                bsg.clipRect(xOffset + cBounds.x,
                             yOffset + cBounds.y,
                             cBounds.width, cBounds.height);
                bsg.copyArea(relX, relY, w, h, deltaX, deltaY);
            }
            else {
                bsg.copyArea(xOffset + x, yOffset + y, w, h, deltaX,
                             deltaY);
            }
            accumulate(x + xOffset + deltaX, y + yOffset + deltaY, w, h);
        } else {
            if (LOGGER.isLoggable(PlatformLogger.Level.FINER)) {
                LOGGER.finer("copyArea: prepare failed or not in sync");
            }
            // Prepare failed, or not in sync. By calling super.copyArea
            // we'll copy on screen. We need to flush any pending paint to
            // the screen otherwise we'll do a copyArea on the wrong thing.
            if (!flushAccumulatedRegion()) {
                // Flush failed, copyArea will be copying garbage,
                // force repaint of all.
                rootJ.repaint();
            } else {
                super.copyArea(c, g, x, y, w, h, deltaX, deltaY, clip);
            }
        }
    }

    public void beginPaint() {
        synchronized(this) {
            painting = true;
            // Make sure another thread isn't attempting to show from
            // the back buffer.
            while(showing) {
                try {
                    wait();
                } catch (InterruptedException ie) {
                }
            }
        }
        if (LOGGER.isLoggable(PlatformLogger.Level.FINEST)) {
            LOGGER.finest("beginPaint");
        }
        // Reset the area that needs to be painted.
        resetAccumulated();
    }

    public void endPaint() {
        if (LOGGER.isLoggable(PlatformLogger.Level.FINEST)) {
            LOGGER.finest("endPaint: region " + accumulatedX + " " +
                       accumulatedY + " " +  accumulatedMaxX + " " +
                       accumulatedMaxY);
        }
        if (painting) {
            if (!flushAccumulatedRegion()) {
                if (!isRepaintingRoot()) {
                    repaintRoot(rootJ);
                }
                else {
                    // Contents lost twice in a row, punt.
                    resetDoubleBufferPerWindow();
                    // In case we've left junk on the screen, force a repaint.
                    rootJ.repaint();
                }
            }
        }

        BufferInfo toDispose = null;
        synchronized(this) {
            painting = false;
            if (disposeBufferOnEnd) {
                disposeBufferOnEnd = false;
                toDispose = bufferInfo;
                bufferInfos.remove(toDispose);
            }
        }
        if (toDispose != null) {
            toDispose.dispose();
        }
    }

    /**
     * Renders the BufferStrategy to the screen.
     *
     * @return true if successful, false otherwise.
     */
    private boolean flushAccumulatedRegion() {
        boolean success = true;
        if (accumulatedX != Integer.MAX_VALUE) {
            SubRegionShowable bsSubRegion = (SubRegionShowable)bufferStrategy;
            boolean contentsLost = bufferStrategy.contentsLost();
            if (!contentsLost) {
                bsSubRegion.show(accumulatedX, accumulatedY,
                                 accumulatedMaxX, accumulatedMaxY);
                contentsLost = bufferStrategy.contentsLost();
            }
            if (contentsLost) {
                if (LOGGER.isLoggable(PlatformLogger.Level.FINER)) {
                    LOGGER.finer("endPaint: contents lost");
                }
                // Shown region was bogus, mark buffer as out of sync.
                bufferInfo.setInSync(false);
                success = false;
            }
        }
        resetAccumulated();
        return success;
    }

    private void resetAccumulated() {
        accumulatedX = Integer.MAX_VALUE;
        accumulatedY = Integer.MAX_VALUE;
        accumulatedMaxX = 0;
        accumulatedMaxY = 0;
    }

    /**
     * Invoked when the double buffering or useTrueDoubleBuffering
     * changes for a JRootPane.  If the rootpane is not double
     * buffered, or true double buffering changes we throw out any
     * cache we may have.
     */
    public void doubleBufferingChanged(final JRootPane rootPane) {
        if ((!rootPane.isDoubleBuffered() ||
                !rootPane.getUseTrueDoubleBuffering()) &&
                rootPane.getParent() != null) {
            if (!SwingUtilities.isEventDispatchThread()) {
                Runnable updater = new Runnable() {
                    public void run() {
                        doubleBufferingChanged0(rootPane);
                    }
                };
                SwingUtilities.invokeLater(updater);
            }
            else {
                doubleBufferingChanged0(rootPane);
            }
        }
    }

    /**
     * Does the work for doubleBufferingChanged.
     */
    private void doubleBufferingChanged0(JRootPane rootPane) {
        // This will only happen on the EDT.
        BufferInfo info;
        synchronized(this) {
            // Make sure another thread isn't attempting to show from
            // the back buffer.
            while(showing) {
                try {
                    wait();
                } catch (InterruptedException ie) {
                }
            }
            info = getBufferInfo(rootPane.getParent());
            if (painting && bufferInfo == info) {
                // We're in the process of painting and the user grabbed
                // the Graphics. If we dispose now, endPaint will attempt
                // to show a bogus BufferStrategy. Set a flag so that
                // endPaint knows it needs to dispose this buffer.
                disposeBufferOnEnd = true;
                info = null;
            } else if (info != null) {
                bufferInfos.remove(info);
            }
        }
        if (info != null) {
            info.dispose();
        }
    }

    /**
     * Calculates information common to paint/copyArea.
     *
     * @return true if should use buffering per window in painting.
     */
    private boolean prepare(JComponent c, Container root, boolean isPaint, int x, int y,
                            int w, int h) {
        if (bsg != null) {
            bsg.dispose();
            bsg = null;
        }
        bufferStrategy = null;
        if (root != null) {
            boolean contentsLost = false;
            BufferInfo bufferInfo = getBufferInfo(root);
            if (bufferInfo == null) {
                contentsLost = true;
                bufferInfo = new BufferInfo(root);
                bufferInfos.add(bufferInfo);
                if (LOGGER.isLoggable(PlatformLogger.Level.FINER)) {
                    LOGGER.finer("prepare: new BufferInfo: " + root);
                }
            }
            this.bufferInfo = bufferInfo;
            if (!bufferInfo.hasBufferStrategyChanged()) {
                bufferStrategy = bufferInfo.getBufferStrategy(true);
                if (bufferStrategy != null) {
                    bsg = bufferStrategy.getDrawGraphics();
                    if (bufferStrategy.contentsRestored()) {
                        contentsLost = true;
                        if (LOGGER.isLoggable(PlatformLogger.Level.FINER)) {
                            LOGGER.finer("prepare: contents restored in prepare");
                        }
                    }
                }
                else {
                    // Couldn't create BufferStrategy, fallback to normal
                    // painting.
                    return false;
                }
                if (bufferInfo.getContentsLostDuringExpose()) {
                    contentsLost = true;
                    bufferInfo.setContentsLostDuringExpose(false);
                    if (LOGGER.isLoggable(PlatformLogger.Level.FINER)) {
                        LOGGER.finer("prepare: contents lost on expose");
                    }
                }
                if (isPaint && c == rootJ && x == 0 && y == 0 &&
                      c.getWidth() == w && c.getHeight() == h) {
                    bufferInfo.setInSync(true);
                }
                else if (contentsLost) {
                    // We either recreated the BufferStrategy, or the contents
                    // of the buffer strategy were restored.  We need to
                    // repaint the root pane so that the back buffer is in sync
                    // again.
                    bufferInfo.setInSync(false);
                    if (!isRepaintingRoot()) {
                        repaintRoot(rootJ);
                    }
                    else {
                        // Contents lost twice in a row, punt
                        resetDoubleBufferPerWindow();
                    }
                }
                return (bufferInfos != null);
            }
        }
        return false;
    }

    private Container fetchRoot(JComponent c) {
        boolean encounteredHW = false;
        rootJ = c;
        Container root = c;
        xOffset = yOffset = 0;
        while (root != null &&
               (!(root instanceof Window) &&
                !SunToolkit.isInstanceOf(root, "java.applet.Applet"))) {
            xOffset += root.getX();
            yOffset += root.getY();
            root = root.getParent();
            if (root != null) {
                if (root instanceof JComponent) {
                    rootJ = (JComponent)root;
                }
                else if (!root.isLightweight()) {
                    if (!encounteredHW) {
                        encounteredHW = true;
                    }
                    else {
                        // We've encountered two hws now and may have
                        // a containment hierarchy with lightweights containing
                        // heavyweights containing other lightweights.
                        // Heavyweights poke holes in lightweight
                        // rendering so that if we call show on the BS
                        // (which is associated with the Window) you will
                        // not see the contents over any child
                        // heavyweights.  If we didn't do this when we
                        // went to show the descendants of the nested hw
                        // you would see nothing, so, we bail out here.
                        return null;
                    }
                }
            }
        }
        if ((root instanceof RootPaneContainer) &&
            (rootJ instanceof JRootPane)) {
            // We're in a Swing heavyeight (JFrame/JWindow...), use double
            // buffering if double buffering enabled on the JRootPane and
            // the JRootPane wants true double buffering.
            if (rootJ.isDoubleBuffered() &&
                    ((JRootPane)rootJ).getUseTrueDoubleBuffering()) {
                // Whether or not a component is double buffered is a
                // bit tricky with Swing. This gives a good approximation
                // of the various ways to turn on double buffering for
                // components.
                return root;
            }
        }
        // Don't do true double buffering.
        return null;
    }

    /**
     * Turns off double buffering per window.
     */
    private void resetDoubleBufferPerWindow() {
        if (bufferInfos != null) {
            dispose(bufferInfos);
            bufferInfos = null;
            repaintManager.setPaintManager(null);
        }
    }

    /**
     * Returns the BufferInfo for the specified root or null if one
     * hasn't been created yet.
     */
    private BufferInfo getBufferInfo(Container root) {
        for (int counter = bufferInfos.size() - 1; counter >= 0; counter--) {
            BufferInfo bufferInfo = bufferInfos.get(counter);
            Container biRoot = bufferInfo.getRoot();
            if (biRoot == null) {
                // Window gc'ed
                bufferInfos.remove(counter);
                if (LOGGER.isLoggable(PlatformLogger.Level.FINER)) {
                    LOGGER.finer("BufferInfo pruned, root null");
                }
            }
            else if (biRoot == root) {
                return bufferInfo;
            }
        }
        return null;
    }

    private void accumulate(int x, int y, int w, int h) {
        accumulatedX = Math.min(x, accumulatedX);
        accumulatedY = Math.min(y, accumulatedY);
        accumulatedMaxX = Math.max(accumulatedMaxX, x + w);
        accumulatedMaxY = Math.max(accumulatedMaxY, y + h);
    }



    /**
     * BufferInfo is used to track the BufferStrategy being used for
     * a particular Component.  In addition to tracking the BufferStrategy
     * it will install a WindowListener and ComponentListener.  When the
     * component is hidden/iconified the buffer is marked as needing to be
     * completely repainted.
     */
    private class BufferInfo extends ComponentAdapter implements
                               WindowListener {
        // NOTE: This class does NOT hold a direct reference to the root, if it
        // did there would be a cycle between the BufferPerWindowPaintManager
        // and the Window so that it could never be GC'ed
        //
        // Reference to BufferStrategy is referenced via WeakReference for
        // same reason.
        private WeakReference<BufferStrategy> weakBS;
        private WeakReference<Container> root;
        // Indicates whether or not the backbuffer and display are in sync.
        // This is set to true when a full repaint on the rootpane is done.
        private boolean inSync;
        // Indicates the contents were lost during and expose event.
        private boolean contentsLostDuringExpose;
        // Indicates we need to generate a paint event on expose.
        private boolean paintAllOnExpose;


        public BufferInfo(Container root) {
            this.root = new WeakReference<Container>(root);
            root.addComponentListener(this);
            if (root instanceof Window) {
                ((Window)root).addWindowListener(this);
            }
        }

        public void setPaintAllOnExpose(boolean paintAllOnExpose) {
            this.paintAllOnExpose = paintAllOnExpose;
        }

        public boolean getPaintAllOnExpose() {
            return paintAllOnExpose;
        }

        public void setContentsLostDuringExpose(boolean value) {
            contentsLostDuringExpose = value;
        }

        public boolean getContentsLostDuringExpose() {
            return contentsLostDuringExpose;
        }

        public void setInSync(boolean inSync) {
            this.inSync = inSync;
        }

        /**
         * Whether or not the contents of the buffer strategy
         * is in sync with the window.  This is set to true when the root
         * pane paints all, and false when contents are lost/restored.
         */
        public boolean isInSync() {
            return inSync;
        }

        /**
         * Returns the Root (Window or Applet) that this BufferInfo references.
         */
        public Container getRoot() {
            return (root == null) ? null : root.get();
        }

        /**
         * Returns the BufferStartegy.  This will return null if
         * the BufferStartegy hasn't been created and <code>create</code> is
         * false, or if there is a problem in creating the
         * <code>BufferStartegy</code>.
         *
         * @param create If true, and the BufferStartegy is currently null,
         *               one will be created.
         */
        public BufferStrategy getBufferStrategy(boolean create) {
            BufferStrategy bs = (weakBS == null) ? null : weakBS.get();
            if (bs == null && create) {
                bs = createBufferStrategy();
                if (bs != null) {
                    weakBS = new WeakReference<BufferStrategy>(bs);
                }
                if (LOGGER.isLoggable(PlatformLogger.Level.FINER)) {
                    LOGGER.finer("getBufferStrategy: created bs: " + bs);
                }
            }
            return bs;
        }

        /**
         * Returns true if the buffer strategy of the component differs
         * from current buffer strategy.
         */
        public boolean hasBufferStrategyChanged() {
            Container root = getRoot();
            if (root != null) {
                BufferStrategy ourBS = null;
                BufferStrategy componentBS = null;

                ourBS = getBufferStrategy(false);
                if (root instanceof Window) {
                    componentBS = ((Window)root).getBufferStrategy();
                }
                else {
                    try {
                        componentBS = (BufferStrategy)
                                 getGetBufferStrategyMethod().invoke(root);
                    } catch (InvocationTargetException ite) {
                        assert false;
                    } catch (IllegalArgumentException iae) {
                        assert false;
                    } catch (IllegalAccessException iae2) {
                        assert false;
                    }
                }
                if (componentBS != ourBS) {
                    // Component has a different BS, dispose ours.
                    if (ourBS != null) {
                        ourBS.dispose();
                    }
                    weakBS = null;
                    return true;
                }
            }
            return false;
        }

        /**
         * Creates the BufferStrategy.  If the appropriate system property
         * has been set we'll try for flip first and then we'll try for
         * blit.
         */
        private BufferStrategy createBufferStrategy() {
            Container root = getRoot();
            if (root == null) {
                return null;
            }
            BufferStrategy bs = null;
            if (SwingUtilities3.isVsyncRequested(root)) {
                bs = createBufferStrategy(root, true);
                if (LOGGER.isLoggable(PlatformLogger.Level.FINER)) {
                    LOGGER.finer("createBufferStrategy: using vsynced strategy");
                }
            }
            if (bs == null) {
                bs = createBufferStrategy(root, false);
            }
            if (!(bs instanceof SubRegionShowable)) {
                // We do this for two reasons:
                // 1. So that we know we can cast to SubRegionShowable and
                //    invoke show with the minimal region to update
                // 2. To avoid the possibility of invoking client code
                //    on the toolkit thread.
                bs = null;
            }
            return bs;
        }

        // Creates and returns a buffer strategy.  If
        // there is a problem creating the buffer strategy this will
        // eat the exception and return null.
        private BufferStrategy createBufferStrategy(Container root,
                boolean isVsynced) {
            BufferCapabilities caps;
            if (isVsynced) {
                caps = new ExtendedBufferCapabilities(
                    new ImageCapabilities(true), new ImageCapabilities(true),
                    BufferCapabilities.FlipContents.COPIED,
                    ExtendedBufferCapabilities.VSyncType.VSYNC_ON);
            } else {
                caps = new BufferCapabilities(
                    new ImageCapabilities(true), new ImageCapabilities(true),
                    null);
            }
            BufferStrategy bs = null;
            if (SunToolkit.isInstanceOf(root, "java.applet.Applet")) {
                try {
                    getCreateBufferStrategyMethod().invoke(root, 2, caps);
                    bs = (BufferStrategy)getGetBufferStrategyMethod().
                                            invoke(root);
                } catch (InvocationTargetException ite) {
                    // Type is not supported
                    if (LOGGER.isLoggable(PlatformLogger.Level.FINER)) {
                        LOGGER.finer("createBufferStratety failed",
                                     ite);
                    }
                } catch (IllegalArgumentException iae) {
                    assert false;
                } catch (IllegalAccessException iae2) {
                    assert false;
                }
            }
            else {
                try {
                    ((Window)root).createBufferStrategy(2, caps);
                    bs = ((Window)root).getBufferStrategy();
                } catch (AWTException e) {
                    // Type not supported
                    if (LOGGER.isLoggable(PlatformLogger.Level.FINER)) {
                        LOGGER.finer("createBufferStratety failed",
                                     e);
                    }
                }
            }
            return bs;
        }

        /**
         * Cleans up and removes any references.
         */
        public void dispose() {
            Container root = getRoot();
            if (LOGGER.isLoggable(PlatformLogger.Level.FINER)) {
                LOGGER.finer("disposed BufferInfo for: " + root);
            }
            if (root != null) {
                root.removeComponentListener(this);
                if (root instanceof Window) {
                    ((Window)root).removeWindowListener(this);
                }
                BufferStrategy bs = getBufferStrategy(false);
                if (bs != null) {
                    bs.dispose();
                }
            }
            this.root = null;
            weakBS = null;
        }

        // We mark the buffer as needing to be painted on a hide/iconify
        // because the developer may have conditionalized painting based on
        // visibility.
        // Ideally we would also move to having the BufferStrategy being
        // a SoftReference in Component here, but that requires changes to
        // Component and the like.
        public void componentHidden(ComponentEvent e) {
            Container root = getRoot();
            if (root != null && root.isVisible()) {
                // This case will only happen if a developer calls
                // hide immediately followed by show.  In this case
                // the event is delivered after show and the window
                // will still be visible.  If a developer altered the
                // contents of the window between the hide/show
                // invocations we won't recognize we need to paint and
                // the contents would be bogus.  Calling repaint here
                // fixs everything up.
                root.repaint();
            }
            else {
                setPaintAllOnExpose(true);
            }
        }

        public void windowIconified(WindowEvent e) {
            setPaintAllOnExpose(true);
        }

        // On a dispose we chuck everything.
        public void windowClosed(WindowEvent e) {
            // Make sure we're not showing.
            synchronized(BufferStrategyPaintManager.this) {
                while (showing) {
                    try {
                        BufferStrategyPaintManager.this.wait();
                    } catch (InterruptedException ie) {
                    }
                }
                bufferInfos.remove(this);
            }
            dispose();
        }

        public void windowOpened(WindowEvent e) {
        }

        public void windowClosing(WindowEvent e) {
        }

        public void windowDeiconified(WindowEvent e) {
        }

        public void windowActivated(WindowEvent e) {
        }

        public void windowDeactivated(WindowEvent e) {
        }
    }
}
