1 /*
   2  * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.java2d.x11;
  27 
  28 import java.awt.GraphicsDevice;
  29 import java.awt.GraphicsEnvironment;
  30 import java.awt.Color;
  31 import java.awt.Composite;
  32 import java.awt.Rectangle;
  33 import java.awt.GraphicsConfiguration;
  34 import java.awt.Image;
  35 import java.awt.color.ColorSpace;
  36 import java.awt.Transparency;
  37 import java.awt.image.BufferedImage;
  38 import java.awt.image.ColorModel;
  39 import java.awt.image.ComponentColorModel;
  40 import java.awt.image.DirectColorModel;
  41 import java.awt.image.IndexColorModel;
  42 import java.awt.image.Raster;
  43 import java.awt.peer.ComponentPeer;
  44 
  45 import sun.awt.SunHints;
  46 import sun.awt.SunToolkit;
  47 import sun.awt.X11ComponentPeer;
  48 import sun.awt.X11GraphicsConfig;
  49 import sun.awt.X11GraphicsEnvironment;
  50 import sun.awt.image.PixelConverter;
  51 import sun.font.X11TextRenderer;
  52 import sun.java2d.InvalidPipeException;
  53 import sun.java2d.SunGraphics2D;
  54 import sun.java2d.SunGraphicsEnvironment;
  55 import sun.java2d.SurfaceData;
  56 import sun.java2d.SurfaceDataProxy;
  57 import sun.java2d.loops.SurfaceType;
  58 import sun.java2d.loops.CompositeType;
  59 import sun.java2d.loops.RenderLoops;
  60 import sun.java2d.loops.GraphicsPrimitive;
  61 import sun.java2d.loops.XORComposite;
  62 import sun.java2d.loops.Blit;
  63 import sun.java2d.pipe.ValidatePipe;
  64 import sun.java2d.pipe.PixelToShapeConverter;
  65 import sun.java2d.pipe.TextPipe;
  66 import sun.java2d.pipe.Region;
  67 
  68 public abstract class X11SurfaceData extends XSurfaceData {
  69     X11ComponentPeer peer;
  70     X11GraphicsConfig graphicsConfig;
  71     private RenderLoops solidloops;
  72 
  73     protected int depth;
  74 
  75     private static native void initIDs(Class<?> xorComp, boolean tryDGA);
  76     protected native void initSurface(int depth, int width, int height,
  77                                       long drawable);
  78 
  79     public static final String
  80         DESC_INT_BGR_X11        = "Integer BGR Pixmap";
  81     public static final String
  82         DESC_INT_RGB_X11        = "Integer RGB Pixmap";
  83 
  84     public static final String
  85         DESC_4BYTE_ABGR_PRE_X11 = "4 byte ABGR Pixmap with pre-multplied alpha";
  86     public static final String
  87         DESC_INT_ARGB_PRE_X11   = "Integer ARGB Pixmap with pre-multiplied " +
  88                                   "alpha";
  89 
  90     public static final String
  91         DESC_BYTE_IND_OPQ_X11   = "Byte Indexed Opaque Pixmap";
  92 
  93     public static final String
  94         DESC_INT_BGR_X11_BM     = "Integer BGR Pixmap with 1-bit transp";
  95     public static final String
  96         DESC_INT_RGB_X11_BM     = "Integer RGB Pixmap with 1-bit transp";
  97     public static final String
  98         DESC_BYTE_IND_X11_BM    = "Byte Indexed Pixmap with 1-bit transp";
  99 
 100     public static final String
 101         DESC_BYTE_GRAY_X11      = "Byte Gray Opaque Pixmap";
 102     public static final String
 103         DESC_INDEX8_GRAY_X11    = "Index8 Gray Opaque Pixmap";
 104 
 105     public static final String
 106         DESC_BYTE_GRAY_X11_BM   = "Byte Gray Opaque Pixmap with 1-bit transp";
 107     public static final String
 108         DESC_INDEX8_GRAY_X11_BM = "Index8 Gray Opaque Pixmap with 1-bit transp";
 109 
 110     public static final String
 111         DESC_3BYTE_RGB_X11      = "3 Byte RGB Pixmap";
 112     public static final String
 113         DESC_3BYTE_BGR_X11      = "3 Byte BGR Pixmap";
 114 
 115     public static final String
 116         DESC_3BYTE_RGB_X11_BM   = "3 Byte RGB Pixmap with 1-bit transp";
 117     public static final String
 118         DESC_3BYTE_BGR_X11_BM   = "3 Byte BGR Pixmap with 1-bit transp";
 119 
 120     public static final String
 121         DESC_USHORT_555_RGB_X11 = "Ushort 555 RGB Pixmap";
 122     public static final String
 123         DESC_USHORT_565_RGB_X11 = "Ushort 565 RGB Pixmap";
 124 
 125     public static final String
 126         DESC_USHORT_555_RGB_X11_BM
 127                                 = "Ushort 555 RGB Pixmap with 1-bit transp";
 128     public static final String
 129         DESC_USHORT_565_RGB_X11_BM
 130                                 = "Ushort 565 RGB Pixmap with 1-bit transp";
 131     public static final String
 132         DESC_USHORT_INDEXED_X11 = "Ushort Indexed Pixmap";
 133 
 134     public static final String
 135         DESC_USHORT_INDEXED_X11_BM = "Ushort Indexed Pixmap with 1-bit transp";
 136 
 137     public static final SurfaceType IntBgrX11 =
 138         SurfaceType.IntBgr.deriveSubType(DESC_INT_BGR_X11);
 139     public static final SurfaceType IntRgbX11 =
 140         SurfaceType.IntRgb.deriveSubType(DESC_INT_RGB_X11);
 141 
 142     public static final SurfaceType FourByteAbgrPreX11 =
 143         SurfaceType.FourByteAbgrPre.deriveSubType(DESC_4BYTE_ABGR_PRE_X11);
 144     public static final SurfaceType IntArgbPreX11 =
 145         SurfaceType.IntArgbPre.deriveSubType(DESC_INT_ARGB_PRE_X11);
 146 
 147     public static final SurfaceType ThreeByteRgbX11 =
 148         SurfaceType.ThreeByteRgb.deriveSubType(DESC_3BYTE_RGB_X11);
 149     public static final SurfaceType ThreeByteBgrX11 =
 150         SurfaceType.ThreeByteBgr.deriveSubType(DESC_3BYTE_BGR_X11);
 151 
 152     public static final SurfaceType UShort555RgbX11 =
 153         SurfaceType.Ushort555Rgb.deriveSubType(DESC_USHORT_555_RGB_X11);
 154     public static final SurfaceType UShort565RgbX11 =
 155         SurfaceType.Ushort565Rgb.deriveSubType(DESC_USHORT_565_RGB_X11);
 156 
 157     public static final SurfaceType UShortIndexedX11 =
 158         SurfaceType.UshortIndexed.deriveSubType(DESC_USHORT_INDEXED_X11);
 159 
 160     public static final SurfaceType ByteIndexedOpaqueX11 =
 161         SurfaceType.ByteIndexedOpaque.deriveSubType(DESC_BYTE_IND_OPQ_X11);
 162 
 163     public static final SurfaceType ByteGrayX11 =
 164         SurfaceType.ByteGray.deriveSubType(DESC_BYTE_GRAY_X11);
 165     public static final SurfaceType Index8GrayX11 =
 166         SurfaceType.Index8Gray.deriveSubType(DESC_INDEX8_GRAY_X11);
 167 
 168     // Bitmap surface types
 169     public static final SurfaceType IntBgrX11_BM =
 170         SurfaceType.Custom.deriveSubType(DESC_INT_BGR_X11_BM,
 171                                          PixelConverter.Xbgr.instance);
 172     public static final SurfaceType IntRgbX11_BM =
 173         SurfaceType.Custom.deriveSubType(DESC_INT_RGB_X11_BM,
 174                                          PixelConverter.Xrgb.instance);
 175 
 176     public static final SurfaceType ThreeByteRgbX11_BM =
 177         SurfaceType.Custom.deriveSubType(DESC_3BYTE_RGB_X11_BM,
 178                                          PixelConverter.Xbgr.instance);
 179     public static final SurfaceType ThreeByteBgrX11_BM =
 180         SurfaceType.Custom.deriveSubType(DESC_3BYTE_BGR_X11_BM,
 181                                          PixelConverter.Xrgb.instance);
 182 
 183     public static final SurfaceType UShort555RgbX11_BM =
 184         SurfaceType.Custom.deriveSubType(DESC_USHORT_555_RGB_X11_BM,
 185                                          PixelConverter.Ushort555Rgb.instance);
 186     public static final SurfaceType UShort565RgbX11_BM =
 187         SurfaceType.Custom.deriveSubType(DESC_USHORT_565_RGB_X11_BM,
 188                                          PixelConverter.Ushort565Rgb.instance);
 189 
 190     public static final SurfaceType UShortIndexedX11_BM =
 191         SurfaceType.Custom.deriveSubType(DESC_USHORT_INDEXED_X11_BM);
 192 
 193     public static final SurfaceType ByteIndexedX11_BM =
 194         SurfaceType.Custom.deriveSubType(DESC_BYTE_IND_X11_BM);
 195 
 196     public static final SurfaceType ByteGrayX11_BM =
 197         SurfaceType.Custom.deriveSubType(DESC_BYTE_GRAY_X11_BM);
 198     public static final SurfaceType Index8GrayX11_BM =
 199         SurfaceType.Custom.deriveSubType(DESC_INDEX8_GRAY_X11_BM);
 200 
 201 
 202     private static Boolean accelerationEnabled = null;
 203 
 204     public Raster getRaster(int x, int y, int w, int h) {
 205         throw new InternalError("not implemented yet");
 206     }
 207 
 208     protected X11Renderer x11pipe;
 209     protected PixelToShapeConverter x11txpipe;
 210     protected static TextPipe x11textpipe;
 211     protected static boolean dgaAvailable;
 212 
 213     static {
 214        if (!isX11SurfaceDataInitialized() &&
 215            !GraphicsEnvironment.isHeadless()) {
 216             // If a screen magnifier is present, don't attempt to use DGA
 217             String magPresent = java.security.AccessController.doPrivileged
 218                 (new sun.security.action.GetPropertyAction("javax.accessibility.screen_magnifier_present"));
 219             boolean tryDGA = magPresent == null || !"true".equals(magPresent);
 220 
 221             initIDs(XORComposite.class, tryDGA);
 222 
 223             String xtextpipe = java.security.AccessController.doPrivileged
 224                 (new sun.security.action.GetPropertyAction("sun.java2d.xtextpipe"));
 225             if (xtextpipe == null || "true".startsWith(xtextpipe)) {
 226                 if ("true".equals(xtextpipe)) {
 227                     // Only verbose if they use the full string "true"
 228                     System.out.println("using X11 text renderer");
 229                 }
 230                 x11textpipe = new X11TextRenderer();
 231                 if (GraphicsPrimitive.tracingEnabled()) {
 232                     x11textpipe = ((X11TextRenderer) x11textpipe).traceWrap();
 233                 }
 234             } else {
 235                 if ("false".equals(xtextpipe)) {
 236                     // Only verbose if they use the full string "false"
 237                     System.out.println("using DGA text renderer");
 238                 }
 239                 x11textpipe = solidTextRenderer;
 240             }
 241 
 242             dgaAvailable = isDgaAvailable();
 243 
 244             if (isAccelerationEnabled()) {
 245                 X11PMBlitLoops.register();
 246                 X11PMBlitBgLoops.register();
 247             }
 248        }
 249     }
 250 
 251     /**
 252      * Returns true if we can use DGA on any of the screens
 253      */
 254     public static native boolean isDgaAvailable();
 255 
 256     /**
 257      * Returns true if shared memory pixmaps are available
 258      */
 259     private static native boolean isShmPMAvailable();
 260 
 261     public static boolean isAccelerationEnabled() {
 262         if (accelerationEnabled == null) {
 263 
 264             if (GraphicsEnvironment.isHeadless()) {
 265                 accelerationEnabled = Boolean.FALSE;
 266             } else {
 267                 String prop = java.security.AccessController.doPrivileged(
 268                         new sun.security.action.GetPropertyAction("sun.java2d.pmoffscreen"));
 269                 if (prop != null) {
 270                     // true iff prop==true, false otherwise
 271                     accelerationEnabled = Boolean.valueOf(prop);
 272                 } else {
 273                     boolean isDisplayLocal = false;
 274                     GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
 275                     if (ge instanceof SunGraphicsEnvironment) {
 276                         isDisplayLocal = ((SunGraphicsEnvironment) ge).isDisplayLocal();
 277                      }
 278 
 279                     // EXA based drivers tend to place pixmaps in VRAM, slowing down readbacks.
 280                     // Don't use pixmaps if dga is available,
 281                     // or we are local and shared memory Pixmaps are not available.
 282                     accelerationEnabled =
 283                         !(isDgaAvailable() || (isDisplayLocal && !isShmPMAvailable()));
 284                 }
 285             }
 286         }
 287         return accelerationEnabled.booleanValue();
 288     }
 289 
 290     @Override
 291     public SurfaceDataProxy makeProxyFor(SurfaceData srcData) {
 292         return X11SurfaceDataProxy.createProxy(srcData, graphicsConfig);
 293     }
 294 
 295     public void validatePipe(SunGraphics2D sg2d) {
 296         if (sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON &&
 297             sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR &&
 298             (sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY ||
 299              sg2d.compositeState == SunGraphics2D.COMP_XOR))
 300         {
 301             if (x11txpipe == null) {
 302                 /*
 303                  * Note: this is thread-safe since x11txpipe is the
 304                  * second of the two pipes constructed in makePipes().
 305                  * In the rare case we are racing against another
 306                  * thread making new pipes, setting lazypipe is a
 307                  * safe alternative to waiting for the other thread.
 308                  */
 309                 sg2d.drawpipe = lazypipe;
 310                 sg2d.fillpipe = lazypipe;
 311                 sg2d.shapepipe = lazypipe;
 312                 sg2d.imagepipe = lazypipe;
 313                 sg2d.textpipe = lazypipe;
 314                 return;
 315             }
 316 
 317             if (sg2d.clipState == SunGraphics2D.CLIP_SHAPE) {
 318                 // Do this to init textpipe correctly; we will override the
 319                 // other non-text pipes below
 320                 // REMIND: we should clean this up eventually instead of
 321                 // having this work duplicated.
 322                 super.validatePipe(sg2d);
 323             } else {
 324                 switch (sg2d.textAntialiasHint) {
 325 
 326                 case SunHints.INTVAL_TEXT_ANTIALIAS_DEFAULT:
 327                     /* equating to OFF which it is for us */
 328                 case SunHints.INTVAL_TEXT_ANTIALIAS_OFF:
 329                     // Use X11 pipe even if DGA is available since DGA
 330                     // text slows everything down when mixed with X11 calls
 331                     if (sg2d.compositeState == SunGraphics2D.COMP_ISCOPY) {
 332                         sg2d.textpipe = x11textpipe;
 333                     } else {
 334                         sg2d.textpipe = solidTextRenderer;
 335                     }
 336                     break;
 337 
 338                 case SunHints.INTVAL_TEXT_ANTIALIAS_ON:
 339                     // Remind: may use Xrender for these when composite is
 340                     // copy as above, or if remote X11.
 341                     sg2d.textpipe = aaTextRenderer;
 342                     break;
 343 
 344                 default:
 345                     switch (sg2d.getFontInfo().aaHint) {
 346 
 347                     case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_HRGB:
 348                     case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_VRGB:
 349                         sg2d.textpipe = lcdTextRenderer;
 350                         break;
 351 
 352                     case SunHints.INTVAL_TEXT_ANTIALIAS_OFF:
 353                     // Use X11 pipe even if DGA is available since DGA
 354                     // text slows everything down when mixed with X11 calls
 355                     if (sg2d.compositeState == SunGraphics2D.COMP_ISCOPY) {
 356                         sg2d.textpipe = x11textpipe;
 357                     } else {
 358                         sg2d.textpipe = solidTextRenderer;
 359                     }
 360                     break;
 361 
 362                     case SunHints.INTVAL_TEXT_ANTIALIAS_ON:
 363                         sg2d.textpipe = aaTextRenderer;
 364                         break;
 365 
 366                     default:
 367                         sg2d.textpipe = solidTextRenderer;
 368                     }
 369                 }
 370             }
 371 
 372             if (sg2d.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) {
 373                 sg2d.drawpipe = x11txpipe;
 374                 sg2d.fillpipe = x11txpipe;
 375             } else if (sg2d.strokeState != SunGraphics2D.STROKE_THIN){
 376                 sg2d.drawpipe = x11txpipe;
 377                 sg2d.fillpipe = x11pipe;
 378             } else {
 379                 sg2d.drawpipe = x11pipe;
 380                 sg2d.fillpipe = x11pipe;
 381             }
 382             sg2d.shapepipe = x11pipe;
 383             sg2d.imagepipe = imagepipe;
 384 
 385             // This is needed for AA text.
 386             // Note that even an X11TextRenderer can dispatch AA text
 387             // if a GlyphVector overrides the AA setting.
 388             // We use getRenderLoops() rather than setting solidloops
 389             // directly so that we get the appropriate loops in XOR mode.
 390             if (sg2d.loops == null) {
 391                 // assert(some pipe will always be a LoopBasedPipe)
 392                 sg2d.loops = getRenderLoops(sg2d);
 393             }
 394         } else {
 395             super.validatePipe(sg2d);
 396         }
 397     }
 398 
 399     public RenderLoops getRenderLoops(SunGraphics2D sg2d) {
 400         if (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR &&
 401             sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY)
 402         {
 403             return solidloops;
 404         }
 405         return super.getRenderLoops(sg2d);
 406     }
 407 
 408     public GraphicsConfiguration getDeviceConfiguration() {
 409         return graphicsConfig;
 410     }
 411 
 412     /**
 413      * Method for instantiating a Window SurfaceData
 414      */
 415     public static X11WindowSurfaceData createData(X11ComponentPeer peer) {
 416        X11GraphicsConfig gc = getGC(peer);
 417        return new X11WindowSurfaceData(peer, gc, gc.getSurfaceType());
 418     }
 419 
 420     /**
 421      * Method for instantiating a Pixmap SurfaceData (offscreen)
 422      */
 423     public static X11PixmapSurfaceData createData(X11GraphicsConfig gc,
 424                                                   int width, int height,
 425                                                   ColorModel cm, Image image,
 426                                                   long drawable,
 427                                                   int transparency)
 428     {
 429         return new X11PixmapSurfaceData(gc, width, height, image,
 430                                         getSurfaceType(gc, transparency, true),
 431                                         cm, drawable, transparency);
 432     }
 433 
 434 //    /**
 435 //     * Initializes the native Ops pointer.
 436 //     */
 437 //    private native void initOps(X11ComponentPeer peer,
 438 //                                X11GraphicsConfig gc, int depth);
 439 
 440     protected X11SurfaceData(X11ComponentPeer peer,
 441                              X11GraphicsConfig gc,
 442                              SurfaceType sType,
 443                              ColorModel cm) {
 444         super(sType, cm);
 445         this.peer = peer;
 446         this.graphicsConfig = gc;
 447         this.solidloops = graphicsConfig.getSolidLoops(sType);
 448         this.depth = cm.getPixelSize();
 449         initOps(peer, graphicsConfig, depth);
 450         if (isAccelerationEnabled()) {
 451             setBlitProxyKey(gc.getProxyKey());
 452         }
 453     }
 454 
 455     public static X11GraphicsConfig getGC(X11ComponentPeer peer) {
 456         if (peer != null) {
 457             return (X11GraphicsConfig) peer.getGraphicsConfiguration();
 458         } else {
 459             GraphicsEnvironment env =
 460                 GraphicsEnvironment.getLocalGraphicsEnvironment();
 461             GraphicsDevice gd = env.getDefaultScreenDevice();
 462             return (X11GraphicsConfig)gd.getDefaultConfiguration();
 463         }
 464     }
 465 
 466     /**
 467      * Returns a boolean indicating whether or not a copyArea from
 468      * the given rectangle source coordinates might be incomplete
 469      * and result in X11 GraphicsExposure events being generated
 470      * from XCopyArea.
 471      * This method allows the SurfaceData copyArea method to determine
 472      * if it needs to set the GraphicsExposures attribute of the X11 GC
 473      * to True or False to receive or avoid the events.
 474      * @return true if there is any chance that an XCopyArea from the
 475      *              given source coordinates could produce any X11
 476      *              Exposure events.
 477      */
 478     public abstract boolean canSourceSendExposures(int x, int y, int w, int h);
 479 
 480     public boolean copyArea(SunGraphics2D sg2d,
 481                             int x, int y, int w, int h, int dx, int dy)
 482     {
 483         if (x11pipe == null) {
 484             if (!isDrawableValid()) {
 485                 return true;
 486             }
 487             makePipes();
 488         }
 489         CompositeType comptype = sg2d.imageComp;
 490         if (sg2d.transformState < SunGraphics2D.TRANSFORM_TRANSLATESCALE &&
 491             (CompositeType.SrcOverNoEa.equals(comptype) ||
 492              CompositeType.SrcNoEa.equals(comptype)))
 493         {
 494             x += sg2d.transX;
 495             y += sg2d.transY;
 496             SunToolkit.awtLock();
 497             try {
 498                 boolean needExposures = canSourceSendExposures(x, y, w, h);
 499                 long xgc = getBlitGC(sg2d.getCompClip(), needExposures);
 500                 x11pipe.devCopyArea(getNativeOps(), xgc,
 501                                     x, y,
 502                                     x + dx, y + dy,
 503                                     w, h);
 504             } finally {
 505                 SunToolkit.awtUnlock();
 506             }
 507             return true;
 508         }
 509         return false;
 510     }
 511 
 512     public static SurfaceType getSurfaceType(X11GraphicsConfig gc,
 513                                              int transparency)
 514     {
 515         return getSurfaceType(gc, transparency, false);
 516     }
 517 
 518     @SuppressWarnings("fallthrough")
 519     public static SurfaceType getSurfaceType(X11GraphicsConfig gc,
 520                                              int transparency,
 521                                              boolean pixmapSurface)
 522     {
 523         boolean transparent = (transparency == Transparency.BITMASK);
 524         SurfaceType sType;
 525         ColorModel cm = gc.getColorModel();
 526         switch (cm.getPixelSize()) {
 527         case 24:
 528             if (gc.getBitsPerPixel() == 24) {
 529                 if (cm instanceof DirectColorModel) {
 530                     // 4517321: We will always use ThreeByteBgr for 24 bpp
 531                     // surfaces, regardless of the pixel masks reported by
 532                     // X11.  Despite ambiguity in the X11 spec in how 24 bpp
 533                     // surfaces are treated, it appears that the best
 534                     // SurfaceType for these configurations (including
 535                     // some Matrox Millenium and ATI Radeon boards) is
 536                     // ThreeByteBgr.
 537                     sType = transparent ? X11SurfaceData.ThreeByteBgrX11_BM : X11SurfaceData.ThreeByteBgrX11;
 538                 } else {
 539                     throw new sun.java2d.InvalidPipeException("Unsupported bit " +
 540                                                               "depth/cm combo: " +
 541                                                               cm.getPixelSize()  +
 542                                                               ", " + cm);
 543                 }
 544                 break;
 545             }
 546             // Fall through for 32 bit case
 547         case 32:
 548             if (cm instanceof DirectColorModel) {
 549                 if (((SunToolkit)java.awt.Toolkit.getDefaultToolkit()
 550                      ).isTranslucencyCapable(gc) && !pixmapSurface)
 551                 {
 552                     sType = X11SurfaceData.IntArgbPreX11;
 553                 } else {
 554                     if (((DirectColorModel)cm).getRedMask() == 0xff0000) {
 555                         sType = transparent ? X11SurfaceData.IntRgbX11_BM :
 556                                               X11SurfaceData.IntRgbX11;
 557                     } else {
 558                         sType = transparent ? X11SurfaceData.IntBgrX11_BM :
 559                                               X11SurfaceData.IntBgrX11;
 560                     }
 561                 }
 562             } else if (cm instanceof ComponentColorModel) {
 563                    sType = X11SurfaceData.FourByteAbgrPreX11;
 564             } else {
 565 
 566                 throw new sun.java2d.InvalidPipeException("Unsupported bit " +
 567                                                           "depth/cm combo: " +
 568                                                           cm.getPixelSize()  +
 569                                                           ", " + cm);
 570             }
 571             break;
 572         case 15:
 573             sType = transparent ? X11SurfaceData.UShort555RgbX11_BM : X11SurfaceData.UShort555RgbX11;
 574             break;
 575         case 16:
 576             if ((cm instanceof DirectColorModel) &&
 577                 (((DirectColorModel)cm).getGreenMask() == 0x3e0))
 578             {
 579                 // fix for 4352984: Riva128 on Linux
 580                 sType = transparent ? X11SurfaceData.UShort555RgbX11_BM : X11SurfaceData.UShort555RgbX11;
 581             } else {
 582                 sType = transparent ? X11SurfaceData.UShort565RgbX11_BM : X11SurfaceData.UShort565RgbX11;
 583             }
 584             break;
 585         case  12:
 586             if (cm instanceof IndexColorModel) {
 587                 sType = transparent ?
 588                     X11SurfaceData.UShortIndexedX11_BM :
 589                     X11SurfaceData.UShortIndexedX11;
 590             } else {
 591                 throw new sun.java2d.InvalidPipeException("Unsupported bit " +
 592                                                           "depth: " +
 593                                                           cm.getPixelSize() +
 594                                                           " cm="+cm);
 595             }
 596             break;
 597         case 8:
 598             if (cm.getColorSpace().getType() == ColorSpace.TYPE_GRAY &&
 599                 cm instanceof ComponentColorModel) {
 600                 sType = transparent ? X11SurfaceData.ByteGrayX11_BM : X11SurfaceData.ByteGrayX11;
 601             } else if (cm instanceof IndexColorModel &&
 602                        isOpaqueGray((IndexColorModel)cm)) {
 603                 sType = transparent ? X11SurfaceData.Index8GrayX11_BM : X11SurfaceData.Index8GrayX11;
 604             } else {
 605                 sType = transparent ? X11SurfaceData.ByteIndexedX11_BM : X11SurfaceData.ByteIndexedOpaqueX11;
 606             }
 607             break;
 608         default:
 609             throw new sun.java2d.InvalidPipeException("Unsupported bit " +
 610                                                       "depth: " +
 611                                                       cm.getPixelSize());
 612         }
 613         return sType;
 614     }
 615 
 616     public void invalidate() {
 617         if (isValid()) {
 618             setInvalid();
 619             super.invalidate();
 620         }
 621     }
 622 
 623     /**
 624      * The following methods and variables are used to keep the Java-level
 625      * context state in sync with the native X11 GC associated with this
 626      * X11SurfaceData object.
 627      */
 628 
 629     private static native void XSetCopyMode(long xgc);
 630     private static native void XSetXorMode(long xgc);
 631     private static native void XSetForeground(long xgc, int pixel);
 632 
 633     private long xgc;
 634     private Region validatedClip;
 635     private XORComposite validatedXorComp;
 636     private int xorpixelmod;
 637     private int validatedPixel;
 638     private boolean validatedExposures = true;
 639 
 640     public final long getRenderGC(Region clip,
 641                                   int compState, Composite comp,
 642                                   int pixel)
 643     {
 644         return getGC(clip, compState, comp, pixel, validatedExposures);
 645     }
 646 
 647     public final long getBlitGC(Region clip, boolean needExposures) {
 648         return getGC(clip, SunGraphics2D.COMP_ISCOPY, null,
 649                      validatedPixel, needExposures);
 650     }
 651 
 652     final long getGC(Region clip,
 653                      int compState, Composite comp,
 654                      int pixel, boolean needExposures)
 655     {
 656         // assert SunToolkit.isAWTLockHeldByCurrentThread();
 657 
 658         if (!isValid()) {
 659             throw new InvalidPipeException("bounds changed");
 660         }
 661 
 662         // validate clip
 663         if (clip != validatedClip) {
 664             validatedClip = clip;
 665             if (clip != null) {
 666                 XSetClip(xgc,
 667                          clip.getLoX(), clip.getLoY(),
 668                          clip.getHiX(), clip.getHiY(),
 669                          (clip.isRectangular() ? null : clip));
 670             } else {
 671                 XResetClip(xgc);
 672             }
 673         }
 674 
 675         // validate composite
 676         if (compState == SunGraphics2D.COMP_ISCOPY) {
 677             if (validatedXorComp != null) {
 678                 validatedXorComp = null;
 679                 xorpixelmod = 0;
 680                 XSetCopyMode(xgc);
 681             }
 682         } else {
 683             if (validatedXorComp != comp) {
 684                 validatedXorComp = (XORComposite)comp;
 685                 xorpixelmod = validatedXorComp.getXorPixel();
 686                 XSetXorMode(xgc);
 687             }
 688         }
 689 
 690         // validate pixel
 691         pixel ^= xorpixelmod;
 692         if (pixel != validatedPixel) {
 693             validatedPixel = pixel;
 694             XSetForeground(xgc, pixel);
 695         }
 696 
 697         if (validatedExposures != needExposures) {
 698             validatedExposures = needExposures;
 699             XSetGraphicsExposures(xgc, needExposures);
 700         }
 701 
 702         return xgc;
 703     }
 704 
 705     public synchronized void makePipes() {
 706         if (x11pipe == null) {
 707             SunToolkit.awtLock();
 708             try {
 709                 xgc = XCreateGC(getNativeOps());
 710             } finally {
 711                 SunToolkit.awtUnlock();
 712             }
 713             x11pipe = X11Renderer.getInstance();
 714             x11txpipe = new PixelToShapeConverter(x11pipe);
 715         }
 716     }
 717 
 718     public static class X11WindowSurfaceData extends X11SurfaceData {
 719         public X11WindowSurfaceData(X11ComponentPeer peer,
 720                                     X11GraphicsConfig gc,
 721                                     SurfaceType sType) {
 722             super(peer, gc, sType, peer.getColorModel());
 723             if (isDrawableValid()) {
 724                 makePipes();
 725             }
 726         }
 727 
 728         public SurfaceData getReplacement() {
 729             return peer.getSurfaceData();
 730         }
 731 
 732         public Rectangle getBounds() {
 733             Rectangle r = peer.getBounds();
 734             r.x = r.y = 0;
 735             return r;
 736         }
 737 
 738         @Override
 739         public boolean canSourceSendExposures(int x, int y, int w, int h) {
 740             return true;
 741         }
 742 
 743         /**
 744          * Returns destination Component associated with this SurfaceData.
 745          */
 746         public Object getDestination() {
 747             return peer.getTarget();
 748         }
 749     }
 750 
 751     public static class X11PixmapSurfaceData extends X11SurfaceData {
 752 
 753         Image                   offscreenImage;
 754         int                     width;
 755         int                     height;
 756         int                     transparency;
 757 
 758         public X11PixmapSurfaceData(X11GraphicsConfig gc,
 759                                     int width, int height,
 760                                     Image image,
 761                                     SurfaceType sType, ColorModel cm,
 762                                     long drawable, int transparency)
 763         {
 764             super(null, gc, sType, cm);
 765             this.width = width;
 766             this.height = height;
 767             offscreenImage = image;
 768             this.transparency = transparency;
 769             initSurface(depth, width, height, drawable);
 770             makePipes();
 771         }
 772 
 773         public SurfaceData getReplacement() {
 774             return restoreContents(offscreenImage);
 775         }
 776 
 777         /**
 778          * Need this since the surface data is created with
 779          * the color model of the target GC, which is always
 780          * opaque. But in SunGraphics2D.blitSD we choose loops
 781          * based on the transparency on the source SD, so
 782          * it could choose wrong loop (blit instead of blitbg,
 783          * for example).
 784          */
 785         public int getTransparency() {
 786             return transparency;
 787         }
 788 
 789         public Rectangle getBounds() {
 790             return new Rectangle(width, height);
 791         }
 792 
 793         @Override
 794         public boolean canSourceSendExposures(int x, int y, int w, int h) {
 795             return (x < 0 || y < 0 || (x+w) > width || (y+h) > height);
 796         }
 797 
 798         public void flush() {
 799             /*
 800              * We need to invalidate the surface before disposing the
 801              * native Drawable and GC.  This way if an application tries
 802              * to render to an already flushed X11SurfaceData, we will notice
 803              * in the validate() method above that it has been invalidated,
 804              * and we will avoid using those native resources that have
 805              * already been disposed.
 806              */
 807             invalidate();
 808             flushNativeSurface();
 809         }
 810 
 811         /**
 812          * Returns destination Image associated with this SurfaceData.
 813          */
 814         public Object getDestination() {
 815             return offscreenImage;
 816         }
 817     }
 818 
 819     private static LazyPipe lazypipe = new LazyPipe();
 820 
 821     public static class LazyPipe extends ValidatePipe {
 822         public boolean validate(SunGraphics2D sg2d) {
 823             X11SurfaceData xsd = (X11SurfaceData) sg2d.surfaceData;
 824             if (!xsd.isDrawableValid()) {
 825                 return false;
 826             }
 827             xsd.makePipes();
 828             return super.validate(sg2d);
 829         }
 830     }
 831 }