/*
 * Copyright 1999-2007 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package sun.java2d.x11;

import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Rectangle;
import java.awt.GraphicsConfiguration;
import java.awt.Image;
import java.awt.color.ColorSpace;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.ComponentColorModel;
import java.awt.image.DirectColorModel;
import java.awt.image.IndexColorModel;
import java.awt.image.Raster;
import java.awt.peer.ComponentPeer;

import sun.awt.SunHints;
import sun.awt.SunToolkit;
import sun.awt.X11ComponentPeer;
import sun.awt.X11GraphicsConfig;
import sun.awt.image.PixelConverter;
import sun.font.X11TextRenderer;
import sun.java2d.InvalidPipeException;
import sun.java2d.SunGraphics2D;
import sun.java2d.SurfaceData;
import sun.java2d.SurfaceDataProxy;
import sun.java2d.loops.SurfaceType;
import sun.java2d.loops.CompositeType;
import sun.java2d.loops.RenderLoops;
import sun.java2d.loops.GraphicsPrimitive;
import sun.java2d.loops.XORComposite;
import sun.java2d.loops.Blit;
import sun.java2d.pipe.ValidatePipe;
import sun.java2d.pipe.PixelToShapeConverter;
import sun.java2d.pipe.TextPipe;
import sun.java2d.pipe.Region;

public abstract class X11SurfaceData extends SurfaceData {
    X11ComponentPeer peer;
    X11GraphicsConfig graphicsConfig;
    private RenderLoops solidloops;

    protected int depth;

    private static native void initIDs(Class xorComp, boolean tryDGA);
    protected native void initSurface(int depth, int width, int height,
                                      long drawable);
    native boolean isDrawableValid();
    protected native void flushNativeSurface();

    public static final String
        DESC_INT_BGR_X11        = "Integer BGR Pixmap";
    public static final String
        DESC_INT_RGB_X11        = "Integer RGB Pixmap";
    public static final String
        DESC_BYTE_IND_OPQ_X11   = "Byte Indexed Opaque Pixmap";

    public static final String
        DESC_INT_BGR_X11_BM     = "Integer BGR Pixmap with 1-bit transp";
    public static final String
        DESC_INT_RGB_X11_BM     = "Integer RGB Pixmap with 1-bit transp";
    public static final String
        DESC_BYTE_IND_X11_BM    = "Byte Indexed Pixmap with 1-bit transp";

    public static final String
        DESC_BYTE_GRAY_X11      = "Byte Gray Opaque Pixmap";
    public static final String
        DESC_INDEX8_GRAY_X11    = "Index8 Gray Opaque Pixmap";

    public static final String
        DESC_BYTE_GRAY_X11_BM   = "Byte Gray Opaque Pixmap with 1-bit transp";
    public static final String
        DESC_INDEX8_GRAY_X11_BM = "Index8 Gray Opaque Pixmap with 1-bit transp";

    public static final String
        DESC_3BYTE_RGB_X11      = "3 Byte RGB Pixmap";
    public static final String
        DESC_3BYTE_BGR_X11      = "3 Byte BGR Pixmap";

    public static final String
        DESC_3BYTE_RGB_X11_BM   = "3 Byte RGB Pixmap with 1-bit transp";
    public static final String
        DESC_3BYTE_BGR_X11_BM   = "3 Byte BGR Pixmap with 1-bit transp";

    public static final String
        DESC_USHORT_555_RGB_X11 = "Ushort 555 RGB Pixmap";
    public static final String
        DESC_USHORT_565_RGB_X11 = "Ushort 565 RGB Pixmap";

    public static final String
        DESC_USHORT_555_RGB_X11_BM
                                = "Ushort 555 RGB Pixmap with 1-bit transp";
    public static final String
        DESC_USHORT_565_RGB_X11_BM
                                = "Ushort 565 RGB Pixmap with 1-bit transp";
    public static final String
        DESC_USHORT_INDEXED_X11 = "Ushort Indexed Pixmap";

    public static final String
        DESC_USHORT_INDEXED_X11_BM = "Ushort Indexed Pixmap with 1-bit transp";

    public static final SurfaceType IntBgrX11 =
        SurfaceType.IntBgr.deriveSubType(DESC_INT_BGR_X11);
    public static final SurfaceType IntRgbX11 =
        SurfaceType.IntRgb.deriveSubType(DESC_INT_RGB_X11);

    public static final SurfaceType ThreeByteRgbX11 =
        SurfaceType.ThreeByteRgb.deriveSubType(DESC_3BYTE_RGB_X11);
    public static final SurfaceType ThreeByteBgrX11 =
        SurfaceType.ThreeByteBgr.deriveSubType(DESC_3BYTE_BGR_X11);

    public static final SurfaceType UShort555RgbX11 =
        SurfaceType.Ushort555Rgb.deriveSubType(DESC_USHORT_555_RGB_X11);
    public static final SurfaceType UShort565RgbX11 =
        SurfaceType.Ushort565Rgb.deriveSubType(DESC_USHORT_565_RGB_X11);

    public static final SurfaceType UShortIndexedX11 =
        SurfaceType.UshortIndexed.deriveSubType(DESC_USHORT_INDEXED_X11);

    public static final SurfaceType ByteIndexedOpaqueX11 =
        SurfaceType.ByteIndexedOpaque.deriveSubType(DESC_BYTE_IND_OPQ_X11);

    public static final SurfaceType ByteGrayX11 =
        SurfaceType.ByteGray.deriveSubType(DESC_BYTE_GRAY_X11);
    public static final SurfaceType Index8GrayX11 =
        SurfaceType.Index8Gray.deriveSubType(DESC_INDEX8_GRAY_X11);

    // Bitmap surface types
    public static final SurfaceType IntBgrX11_BM =
        SurfaceType.Custom.deriveSubType(DESC_INT_BGR_X11_BM,
                                         PixelConverter.Xbgr.instance);
    public static final SurfaceType IntRgbX11_BM =
        SurfaceType.Custom.deriveSubType(DESC_INT_RGB_X11_BM,
                                         PixelConverter.Xrgb.instance);

    public static final SurfaceType ThreeByteRgbX11_BM =
        SurfaceType.Custom.deriveSubType(DESC_3BYTE_RGB_X11_BM,
                                         PixelConverter.Xbgr.instance);
    public static final SurfaceType ThreeByteBgrX11_BM =
        SurfaceType.Custom.deriveSubType(DESC_3BYTE_BGR_X11_BM,
                                         PixelConverter.Xrgb.instance);

    public static final SurfaceType UShort555RgbX11_BM =
        SurfaceType.Custom.deriveSubType(DESC_USHORT_555_RGB_X11_BM,
                                         PixelConverter.Ushort555Rgb.instance);
    public static final SurfaceType UShort565RgbX11_BM =
        SurfaceType.Custom.deriveSubType(DESC_USHORT_565_RGB_X11_BM,
                                         PixelConverter.Ushort565Rgb.instance);

    public static final SurfaceType UShortIndexedX11_BM =
        SurfaceType.Custom.deriveSubType(DESC_USHORT_INDEXED_X11_BM);

    public static final SurfaceType ByteIndexedX11_BM =
        SurfaceType.Custom.deriveSubType(DESC_BYTE_IND_X11_BM);

    public static final SurfaceType ByteGrayX11_BM =
        SurfaceType.Custom.deriveSubType(DESC_BYTE_GRAY_X11_BM);
    public static final SurfaceType Index8GrayX11_BM =
        SurfaceType.Custom.deriveSubType(DESC_INDEX8_GRAY_X11_BM);


    private static Boolean accelerationEnabled = null;

    public Raster getRaster(int x, int y, int w, int h) {
        throw new InternalError("not implemented yet");
    }

    protected X11Renderer x11pipe;
    protected PixelToShapeConverter x11txpipe;
    protected static TextPipe x11textpipe;
    protected static boolean dgaAvailable;

    static {
        if (!GraphicsEnvironment.isHeadless()) {
            // If a screen magnifier is present, don't attempt to use DGA
            String magPresent = (String) java.security.AccessController.doPrivileged
                (new sun.security.action.GetPropertyAction("javax.accessibility.screen_magnifier_present"));
            boolean tryDGA = magPresent == null || !"true".equals(magPresent);

            initIDs(XORComposite.class, tryDGA);

            String xtextpipe = (String) java.security.AccessController.doPrivileged
                (new sun.security.action.GetPropertyAction("sun.java2d.xtextpipe"));
            if (xtextpipe == null || "true".startsWith(xtextpipe)) {
                if ("true".equals(xtextpipe)) {
                    // Only verbose if they use the full string "true"
                    System.out.println("using X11 text renderer");
                }
                x11textpipe = new X11TextRenderer();
                if (GraphicsPrimitive.tracingEnabled()) {
                    x11textpipe = ((X11TextRenderer) x11textpipe).traceWrap();
                }
            } else {
                if ("false".equals(xtextpipe)) {
                    // Only verbose if they use the full string "false"
                    System.out.println("using DGA text renderer");
                }
                x11textpipe = solidTextRenderer;
            }

            dgaAvailable = isDgaAvailable();

            if (isAccelerationEnabled()) {
                X11PMBlitLoops.register();
                X11PMBlitBgLoops.register();
            }
        }
    }

    /**
     * Returns true if we can use DGA on any of the screens
     */
    public static native boolean isDgaAvailable();

    public static boolean isAccelerationEnabled() {
        if (accelerationEnabled == null) {

            if (GraphicsEnvironment.isHeadless()) {
                accelerationEnabled = Boolean.FALSE;
            } else {
                String prop =
                    (String) java.security.AccessController.doPrivileged(
                        new sun.security.action.GetPropertyAction("sun.java2d.pmoffscreen"));
                if (prop != null) {
                    // true iff prop==true, false otherwise
                    accelerationEnabled = Boolean.valueOf(prop);
                } else {
                    // use pixmaps if there is no dga, no matter local or remote
                    accelerationEnabled = Boolean.valueOf(!isDgaAvailable());
                }
            }
        }
        return accelerationEnabled.booleanValue();
    }

    @Override
    public SurfaceDataProxy makeProxyFor(SurfaceData srcData) {
        return X11SurfaceDataProxy.createProxy(srcData, graphicsConfig);
    }

    public void validatePipe(SunGraphics2D sg2d) {
        if (sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON &&
            sg2d.paintState <= sg2d.PAINT_ALPHACOLOR &&
            (sg2d.compositeState <= sg2d.COMP_ISCOPY ||
             sg2d.compositeState == sg2d.COMP_XOR))
        {
            if (x11txpipe == null) {
                /*
                 * Note: this is thread-safe since x11txpipe is the
                 * second of the two pipes constructed in makePipes().
                 * In the rare case we are racing against another
                 * thread making new pipes, setting lazypipe is a
                 * safe alternative to waiting for the other thread.
                 */
                sg2d.drawpipe = lazypipe;
                sg2d.fillpipe = lazypipe;
                sg2d.shapepipe = lazypipe;
                sg2d.imagepipe = lazypipe;
                sg2d.textpipe = lazypipe;
                return;
            }

            if (sg2d.clipState == sg2d.CLIP_SHAPE) {
                // Do this to init textpipe correctly; we will override the
                // other non-text pipes below
                // REMIND: we should clean this up eventually instead of
                // having this work duplicated.
                super.validatePipe(sg2d);
            } else {
                switch (sg2d.textAntialiasHint) {

                case SunHints.INTVAL_TEXT_ANTIALIAS_DEFAULT:
                    /* equating to OFF which it is for us */
                case SunHints.INTVAL_TEXT_ANTIALIAS_OFF:
                    // Use X11 pipe even if DGA is available since DGA
                    // text slows everything down when mixed with X11 calls
                    if (sg2d.compositeState == sg2d.COMP_ISCOPY) {
                        sg2d.textpipe = x11textpipe;
                    } else {
                        sg2d.textpipe = solidTextRenderer;
                    }
                    break;

                case SunHints.INTVAL_TEXT_ANTIALIAS_ON:
                    // Remind: may use Xrender for these when composite is
                    // copy as above, or if remote X11.
                    sg2d.textpipe = aaTextRenderer;
                    break;

                default:
                    switch (sg2d.getFontInfo().aaHint) {

                    case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_HRGB:
                    case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_VRGB:
                        sg2d.textpipe = lcdTextRenderer;
                        break;

                    case SunHints.INTVAL_TEXT_ANTIALIAS_OFF:
                    // Use X11 pipe even if DGA is available since DGA
                    // text slows everything down when mixed with X11 calls
                    if (sg2d.compositeState == sg2d.COMP_ISCOPY) {
                        sg2d.textpipe = x11textpipe;
                    } else {
                        sg2d.textpipe = solidTextRenderer;
                    }
                    break;

                    case SunHints.INTVAL_TEXT_ANTIALIAS_ON:
                        sg2d.textpipe = aaTextRenderer;
                        break;

                    default:
                        sg2d.textpipe = solidTextRenderer;
                    }
                }
            }

            if (sg2d.transformState >= sg2d.TRANSFORM_TRANSLATESCALE) {
                sg2d.drawpipe = x11txpipe;
                sg2d.fillpipe = x11txpipe;
            } else if (sg2d.strokeState != sg2d.STROKE_THIN){
                sg2d.drawpipe = x11txpipe;
                sg2d.fillpipe = x11pipe;
            } else {
                sg2d.drawpipe = x11pipe;
                sg2d.fillpipe = x11pipe;
            }
            sg2d.shapepipe = x11pipe;
            sg2d.imagepipe = imagepipe;

            // This is needed for AA text.
            // Note that even an X11TextRenderer can dispatch AA text
            // if a GlyphVector overrides the AA setting.
            // We use getRenderLoops() rather than setting solidloops
            // directly so that we get the appropriate loops in XOR mode.
            sg2d.loops = getRenderLoops(sg2d);
        } else {
            super.validatePipe(sg2d);
        }
    }

    public RenderLoops getRenderLoops(SunGraphics2D sg2d) {
        if (sg2d.paintState <= sg2d.PAINT_ALPHACOLOR &&
            sg2d.compositeState <= sg2d.COMP_ISCOPY)
        {
            return solidloops;
        }
        return super.getRenderLoops(sg2d);
    }

    public GraphicsConfiguration getDeviceConfiguration() {
        return graphicsConfig;
    }

    /**
     * Method for instantiating a Window SurfaceData
     */
    public static X11WindowSurfaceData createData(X11ComponentPeer peer) {
       X11GraphicsConfig gc = getGC(peer);
       return new X11WindowSurfaceData(peer, gc, gc.getSurfaceType());
    }

    /**
     * Method for instantiating a Pixmap SurfaceData (offscreen)
     */
    public static X11PixmapSurfaceData createData(X11GraphicsConfig gc,
                                                  int width, int height,
                                                  ColorModel cm, Image image,
                                                  long drawable,
                                                  int transparency)
    {
        return new X11PixmapSurfaceData(gc, width, height, image,
                                        getSurfaceType(gc, transparency),
                                        cm, drawable, transparency);
    }

    /**
     * Initializes the native Ops pointer.
     */
    private native void initOps(X11ComponentPeer peer,
                                X11GraphicsConfig gc, int depth);

    protected X11SurfaceData(X11ComponentPeer peer,
                             X11GraphicsConfig gc,
                             SurfaceType sType,
                             ColorModel cm) {
        super(sType, cm);
        this.peer = peer;
        this.graphicsConfig = gc;
        this.solidloops = graphicsConfig.getSolidLoops(sType);
        this.depth = cm.getPixelSize();
        initOps(peer, graphicsConfig, depth);
        if (isAccelerationEnabled()) {
            setBlitProxyKey(gc.getProxyKey());
        }
    }

    public static X11GraphicsConfig getGC(X11ComponentPeer peer) {
        if (peer != null) {
            return (X11GraphicsConfig) peer.getGraphicsConfiguration();
        } else {
            GraphicsEnvironment env =
                GraphicsEnvironment.getLocalGraphicsEnvironment();
            GraphicsDevice gd = env.getDefaultScreenDevice();
            return (X11GraphicsConfig)gd.getDefaultConfiguration();
        }
    }

    /**
     * Returns a boolean indicating whether or not a copyArea from
     * the given rectangle source coordinates might be incomplete
     * and result in X11 GraphicsExposure events being generated
     * from XCopyArea.
     * This method allows the SurfaceData copyArea method to determine
     * if it needs to set the GraphicsExposures attribute of the X11 GC
     * to True or False to receive or avoid the events.
     * @return true if there is any chance that an XCopyArea from the
     *              given source coordinates could produce any X11
     *              Exposure events.
     */
    public abstract boolean canSourceSendExposures(int x, int y, int w, int h);

    public boolean copyArea(SunGraphics2D sg2d,
                            int x, int y, int w, int h, int dx, int dy)
    {
        if (x11pipe == null) {
            if (!isDrawableValid()) {
                return true;
            }
            makePipes();
        }
        CompositeType comptype = sg2d.imageComp;
        if (sg2d.transformState < sg2d.TRANSFORM_TRANSLATESCALE &&
            (CompositeType.SrcOverNoEa.equals(comptype) ||
             CompositeType.SrcNoEa.equals(comptype)))
        {
            x += sg2d.transX;
            y += sg2d.transY;
            SunToolkit.awtLock();
            try {
                boolean needExposures = canSourceSendExposures(x, y, w, h);
                long xgc = getBlitGC(sg2d.getCompClip(), needExposures);
                x11pipe.devCopyArea(getNativeOps(), xgc,
                                    x, y,
                                    x + dx, y + dy,
                                    w, h);
            } finally {
                SunToolkit.awtUnlock();
            }
            return true;
        }
        return false;
    }

    public static SurfaceType getSurfaceType(X11GraphicsConfig gc,
                                             int transparency)
    {
        boolean transparent = (transparency == Transparency.BITMASK);
        SurfaceType sType;
        ColorModel cm = gc.getColorModel();
        switch (cm.getPixelSize()) {
        case 24:
            if (gc.getBitsPerPixel() == 24) {
                if (cm instanceof DirectColorModel) {
                    // 4517321: We will always use ThreeByteBgr for 24 bpp
                    // surfaces, regardless of the pixel masks reported by
                    // X11.  Despite ambiguity in the X11 spec in how 24 bpp
                    // surfaces are treated, it appears that the best
                    // SurfaceType for these configurations (including
                    // some Matrox Millenium and ATI Radeon boards) is
                    // ThreeByteBgr.
                    sType = transparent ? X11SurfaceData.ThreeByteBgrX11_BM : X11SurfaceData.ThreeByteBgrX11;
                } else {
                    throw new sun.java2d.InvalidPipeException("Unsupported bit " +
                                                              "depth/cm combo: " +
                                                              cm.getPixelSize()  +
                                                              ", " + cm);
                }
                break;
            }
            // Fall through for 32 bit case
        case 32:
            if (cm instanceof DirectColorModel) {
                if (((DirectColorModel)cm).getRedMask() == 0xff0000) {
                    sType = transparent ? X11SurfaceData.IntRgbX11_BM : X11SurfaceData.IntRgbX11;
                } else {
                    sType = transparent ? X11SurfaceData.IntBgrX11_BM : X11SurfaceData.IntBgrX11;
                }
            } else {
                throw new sun.java2d.InvalidPipeException("Unsupported bit " +
                                                          "depth/cm combo: " +
                                                          cm.getPixelSize()  +
                                                          ", " + cm);
            }
            break;
        case 15:
            sType = transparent ? X11SurfaceData.UShort555RgbX11_BM : X11SurfaceData.UShort555RgbX11;
            break;
        case 16:
            if ((cm instanceof DirectColorModel) &&
                (((DirectColorModel)cm).getGreenMask() == 0x3e0))
            {
                // fix for 4352984: Riva128 on Linux
                sType = transparent ? X11SurfaceData.UShort555RgbX11_BM : X11SurfaceData.UShort555RgbX11;
            } else {
                sType = transparent ? X11SurfaceData.UShort565RgbX11_BM : X11SurfaceData.UShort565RgbX11;
            }
            break;
        case  12:
            if (cm instanceof IndexColorModel) {
                sType = transparent ?
                    X11SurfaceData.UShortIndexedX11_BM :
                    X11SurfaceData.UShortIndexedX11;
            } else {
                throw new sun.java2d.InvalidPipeException("Unsupported bit " +
                                                          "depth: " +
                                                          cm.getPixelSize() +
                                                          " cm="+cm);
            }
            break;
        case 8:
            if (cm.getColorSpace().getType() == ColorSpace.TYPE_GRAY &&
                cm instanceof ComponentColorModel) {
                sType = transparent ? X11SurfaceData.ByteGrayX11_BM : X11SurfaceData.ByteGrayX11;
            } else if (cm instanceof IndexColorModel &&
                       isOpaqueGray((IndexColorModel)cm)) {
                sType = transparent ? X11SurfaceData.Index8GrayX11_BM : X11SurfaceData.Index8GrayX11;
            } else {
                sType = transparent ? X11SurfaceData.ByteIndexedX11_BM : X11SurfaceData.ByteIndexedOpaqueX11;
            }
            break;
        default:
            throw new sun.java2d.InvalidPipeException("Unsupported bit " +
                                                      "depth: " +
                                                      cm.getPixelSize());
        }
        return sType;
    }

    public native void setInvalid();

    public void invalidate() {
        if (isValid()) {
            setInvalid();
            super.invalidate();
        }
    }

    /**
     * The following methods and variables are used to keep the Java-level
     * context state in sync with the native X11 GC associated with this
     * X11SurfaceData object.
     */

    private static native long XCreateGC(long pXSData);
    private static native void XResetClip(long xgc);
    private static native void XSetClip(long xgc,
                                        int lox, int loy, int hix, int hiy,
                                        Region complexclip);
    private static native void XSetCopyMode(long xgc);
    private static native void XSetXorMode(long xgc);
    private static native void XSetForeground(long xgc, int pixel);
    private static native void XSetGraphicsExposures(long xgc,
                                                     boolean needExposures);

    private long xgc;
    private Region validatedClip;
    private XORComposite validatedXorComp;
    private int xorpixelmod;
    private int validatedPixel;
    private boolean validatedExposures = true;

    public final long getRenderGC(Region clip,
                                  int compState, Composite comp,
                                  int pixel)
    {
        return getGC(clip, compState, comp, pixel, validatedExposures);
    }

    public final long getBlitGC(Region clip, boolean needExposures) {
        return getGC(clip, SunGraphics2D.COMP_ISCOPY, null,
                     validatedPixel, needExposures);
    }

    final long getGC(Region clip,
                     int compState, Composite comp,
                     int pixel, boolean needExposures)
    {
        // assert SunToolkit.isAWTLockHeldByCurrentThread();

        if (!isValid()) {
            throw new InvalidPipeException("bounds changed");
        }

        // validate clip
        if (clip != validatedClip) {
            validatedClip = clip;
            if (clip != null) {
                XSetClip(xgc,
                         clip.getLoX(), clip.getLoY(),
                         clip.getHiX(), clip.getHiY(),
                         (clip.isRectangular() ? null : clip));
            } else {
                XResetClip(xgc);
            }
        }

        // validate composite
        if (compState == SunGraphics2D.COMP_ISCOPY) {
            if (validatedXorComp != null) {
                validatedXorComp = null;
                xorpixelmod = 0;
                XSetCopyMode(xgc);
            }
        } else {
            if (validatedXorComp != comp) {
                validatedXorComp = (XORComposite)comp;
                xorpixelmod = validatedXorComp.getXorPixel();
                XSetXorMode(xgc);
            }
        }

        // validate pixel
        pixel ^= xorpixelmod;
        if (pixel != validatedPixel) {
            validatedPixel = pixel;
            XSetForeground(xgc, pixel);
        }

        if (validatedExposures != needExposures) {
            validatedExposures = needExposures;
            XSetGraphicsExposures(xgc, needExposures);
        }

        return xgc;
    }

    public synchronized void makePipes() {
        if (x11pipe == null) {
            SunToolkit.awtLock();
            try {
                xgc = XCreateGC(getNativeOps());
            } finally {
                SunToolkit.awtUnlock();
            }
            x11pipe = X11Renderer.getInstance();
            x11txpipe = new PixelToShapeConverter(x11pipe);
        }
    }

    public static class X11WindowSurfaceData extends X11SurfaceData {
        public X11WindowSurfaceData(X11ComponentPeer peer,
                                    X11GraphicsConfig gc,
                                    SurfaceType sType) {
            super(peer, gc, sType, peer.getColorModel());
            if (isDrawableValid()) {
                makePipes();
            }
        }

        public SurfaceData getReplacement() {
            return peer.getSurfaceData();
        }

        public Rectangle getBounds() {
            Rectangle r = peer.getBounds();
            r.x = r.y = 0;
            return r;
        }

        @Override
        public boolean canSourceSendExposures(int x, int y, int w, int h) {
            return true;
        }

        /**
         * Returns destination Component associated with this SurfaceData.
         */
        public Object getDestination() {
            return peer.getTarget();
        }
    }

    public static class X11PixmapSurfaceData extends X11SurfaceData {

        Image                   offscreenImage;
        int                     width;
        int                     height;
        int                     transparency;

        public X11PixmapSurfaceData(X11GraphicsConfig gc,
                                    int width, int height,
                                    Image image,
                                    SurfaceType sType, ColorModel cm,
                                    long drawable, int transparency)
        {
            super(null, gc, sType, cm);
            this.width = width;
            this.height = height;
            offscreenImage = image;
            this.transparency = transparency;
            initSurface(depth, width, height, drawable);
            makePipes();
        }

        public SurfaceData getReplacement() {
            return restoreContents(offscreenImage);
        }

        /**
         * Need this since the surface data is created with
         * the color model of the target GC, which is always
         * opaque. But in SunGraphics2D.blitSD we choose loops
         * based on the transparency on the source SD, so
         * it could choose wrong loop (blit instead of blitbg,
         * for example).
         */
        public int getTransparency() {
            return transparency;
        }

        public Rectangle getBounds() {
            return new Rectangle(width, height);
        }

        @Override
        public boolean canSourceSendExposures(int x, int y, int w, int h) {
            return (x < 0 || y < 0 || (x+w) > width || (y+h) > height);
        }

        public void flush() {
            /*
             * We need to invalidate the surface before disposing the
             * native Drawable and GC.  This way if an application tries
             * to render to an already flushed X11SurfaceData, we will notice
             * in the validate() method above that it has been invalidated,
             * and we will avoid using those native resources that have
             * already been disposed.
             */
            invalidate();
            flushNativeSurface();
        }

        /**
         * Returns destination Image associated with this SurfaceData.
         */
        public Object getDestination() {
            return offscreenImage;
        }
    }

    private static LazyPipe lazypipe = new LazyPipe();

    public static class LazyPipe extends ValidatePipe {
        public boolean validate(SunGraphics2D sg2d) {
            X11SurfaceData xsd = (X11SurfaceData) sg2d.surfaceData;
            if (!xsd.isDrawableValid()) {
                return false;
            }
            xsd.makePipes();
            return super.validate(sg2d);
        }
    }
}
