1 /* 2 * Copyright (c) 1997, 2013, 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.awt; 27 28 import java.awt.AWTException; 29 import java.awt.BufferCapabilities; 30 import java.awt.BufferCapabilities.FlipContents; 31 import java.awt.Component; 32 import java.awt.Toolkit; 33 import java.awt.GraphicsConfiguration; 34 import java.awt.GraphicsDevice; 35 import java.awt.Image; 36 import java.awt.ImageCapabilities; 37 import java.awt.Transparency; 38 import java.awt.image.BufferedImage; 39 import java.awt.image.ColorModel; 40 import java.awt.color.ColorSpace; 41 import java.awt.image.ComponentColorModel; 42 import java.awt.image.DirectColorModel; 43 import java.awt.image.DataBuffer; 44 import java.awt.image.VolatileImage; 45 import java.awt.image.WritableRaster; 46 import java.awt.geom.AffineTransform; 47 import java.awt.Rectangle; 48 import sun.java2d.Disposer; 49 import sun.java2d.DisposerRecord; 50 import sun.java2d.SurfaceData; 51 import sun.java2d.loops.RenderLoops; 52 import sun.java2d.loops.SurfaceType; 53 import sun.java2d.loops.CompositeType; 54 import sun.java2d.x11.X11SurfaceData; 55 import sun.awt.image.OffScreenImage; 56 import sun.awt.image.SunVolatileImage; 57 import sun.awt.image.SurfaceManager; 58 import sun.awt.X11ComponentPeer; 59 60 /** 61 * This is an implementation of a GraphicsConfiguration object for a 62 * single X11 visual. 63 * 64 * @see GraphicsEnvironment 65 * @see GraphicsDevice 66 */ 67 public class X11GraphicsConfig extends GraphicsConfiguration 68 implements SurfaceManager.ProxiedGraphicsConfig 69 { 70 protected X11GraphicsDevice screen; 71 protected int visual; 72 int depth; 73 int colormap; 74 ColorModel colorModel; 75 long aData; 76 boolean doubleBuffer; 77 private Object disposerReferent = new Object(); 78 private BufferCapabilities bufferCaps; 79 private static ImageCapabilities imageCaps = 80 new ImageCapabilities(X11SurfaceData.isAccelerationEnabled()); 81 82 // will be set on native level from init() 83 protected int bitsPerPixel; 84 85 protected SurfaceType surfaceType; 86 87 public RenderLoops solidloops; 88 getConfig(X11GraphicsDevice device, int visualnum, int depth, int colormap, boolean doubleBuffer)89 public static X11GraphicsConfig getConfig(X11GraphicsDevice device, 90 int visualnum, int depth, 91 int colormap, 92 boolean doubleBuffer) 93 { 94 return new X11GraphicsConfig(device, visualnum, depth, colormap, doubleBuffer); 95 } 96 97 /* 98 * Note this method is currently here for backward compatibility 99 * as this was the method used in jdk 1.2 beta4 to create the 100 * X11GraphicsConfig objects. Java3D code had called this method 101 * explicitly so without this, if a user tries to use JDK1.2 fcs 102 * with Java3D beta1, a NoSuchMethod execption is thrown and 103 * the program exits. REMOVE this method after Java3D fcs is 104 * released! 105 */ getConfig(X11GraphicsDevice device, int visualnum, int depth, int colormap, int type)106 public static X11GraphicsConfig getConfig(X11GraphicsDevice device, 107 int visualnum, int depth, 108 int colormap, int type) 109 { 110 return new X11GraphicsConfig(device, visualnum, depth, colormap, false); 111 } 112 getNumColors()113 private native int getNumColors(); init(int visualNum, int screen)114 private native void init(int visualNum, int screen); makeColorModel()115 private native ColorModel makeColorModel(); 116 X11GraphicsConfig(X11GraphicsDevice device, int visualnum, int depth, int colormap, boolean doubleBuffer)117 protected X11GraphicsConfig(X11GraphicsDevice device, 118 int visualnum, int depth, 119 int colormap, boolean doubleBuffer) 120 { 121 this.screen = device; 122 this.visual = visualnum; 123 this.doubleBuffer = doubleBuffer; 124 this.depth = depth; 125 this.colormap = colormap; 126 init (visualnum, screen.getScreen()); 127 128 // add a record to the Disposer so that we destroy the native 129 // AwtGraphicsConfigData when this object goes away (i.e. after a 130 // display change event) 131 long x11CfgData = getAData(); 132 Disposer.addRecord(disposerReferent, 133 new X11GCDisposerRecord(x11CfgData)); 134 } 135 136 /** 137 * Return the graphics device associated with this configuration. 138 */ getDevice()139 public GraphicsDevice getDevice() { 140 return screen; 141 } 142 143 /** 144 * Returns the visual id associated with this configuration. 145 */ getVisual()146 public int getVisual () { 147 return visual; 148 } 149 150 151 /** 152 * Returns the depth associated with this configuration. 153 */ getDepth()154 public int getDepth () { 155 return depth; 156 } 157 158 /** 159 * Returns the colormap associated with this configuration. 160 */ getColormap()161 public int getColormap () { 162 return colormap; 163 } 164 165 /** 166 * Returns a number of bits allocated per pixel 167 * (might be different from depth) 168 */ getBitsPerPixel()169 public int getBitsPerPixel() { 170 return bitsPerPixel; 171 } 172 getSurfaceType()173 public synchronized SurfaceType getSurfaceType() { 174 if (surfaceType != null) { 175 return surfaceType; 176 } 177 178 surfaceType = X11SurfaceData.getSurfaceType(this, Transparency.OPAQUE); 179 return surfaceType; 180 } 181 getProxyKey()182 public Object getProxyKey() { 183 return screen.getProxyKeyFor(getSurfaceType()); 184 } 185 186 /** 187 * Return the RenderLoops this type of destination uses for 188 * solid fills and strokes. 189 */ getSolidLoops(SurfaceType stype)190 public synchronized RenderLoops getSolidLoops(SurfaceType stype) { 191 if (solidloops == null) { 192 solidloops = SurfaceData.makeRenderLoops(SurfaceType.OpaqueColor, 193 CompositeType.SrcNoEa, 194 stype); 195 } 196 return solidloops; 197 } 198 199 /** 200 * Returns the color model associated with this configuration. 201 */ getColorModel()202 public synchronized ColorModel getColorModel() { 203 if (colorModel == null) { 204 // Force SystemColors to be resolved before we create the CM 205 java.awt.SystemColor.window.getRGB(); 206 // This method, makeColorModel(), can return null if the 207 // toolkit is not initialized yet. 208 // The toolkit will then call back to this routine after it 209 // is initialized and makeColorModel() should return a non-null 210 // colorModel. 211 colorModel = makeColorModel(); 212 if (colorModel == null) 213 colorModel = Toolkit.getDefaultToolkit ().getColorModel (); 214 } 215 216 return colorModel; 217 } 218 219 /** 220 * Returns the color model associated with this configuration that 221 * supports the specified transparency. 222 */ getColorModel(int transparency)223 public ColorModel getColorModel(int transparency) { 224 switch (transparency) { 225 case Transparency.OPAQUE: 226 return getColorModel(); 227 case Transparency.BITMASK: 228 return new DirectColorModel(25, 0xff0000, 0xff00, 0xff, 0x1000000); 229 case Transparency.TRANSLUCENT: 230 return ColorModel.getRGBdefault(); 231 default: 232 return null; 233 } 234 } 235 createDCM32(int rMask, int gMask, int bMask, int aMask, boolean aPre)236 public static DirectColorModel createDCM32(int rMask, int gMask, int bMask, 237 int aMask, boolean aPre) { 238 return new DirectColorModel( 239 ColorSpace.getInstance(ColorSpace.CS_sRGB), 240 32, rMask, gMask, bMask, aMask, aPre, DataBuffer.TYPE_INT); 241 } 242 createABGRCCM()243 public static ComponentColorModel createABGRCCM() { 244 ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); 245 int[] nBits = {8, 8, 8, 8}; 246 int[] bOffs = {3, 2, 1, 0}; 247 return new ComponentColorModel(cs, nBits, true, true, 248 Transparency.TRANSLUCENT, 249 DataBuffer.TYPE_BYTE); 250 } 251 252 /** 253 * Returns the default Transform for this configuration. This 254 * Transform is typically the Identity transform for most normal 255 * screens. Device coordinates for screen and printer devices will 256 * have the origin in the upper left-hand corner of the target region of 257 * the device, with X coordinates 258 * increasing to the right and Y coordinates increasing downwards. 259 * For image buffers, this Transform will be the Identity transform. 260 */ getDefaultTransform()261 public AffineTransform getDefaultTransform() { 262 return new AffineTransform(); 263 } 264 265 /** 266 * 267 * Returns a Transform that can be composed with the default Transform 268 * of a Graphics2D so that 72 units in user space will equal 1 inch 269 * in device space. 270 * Given a Graphics2D, g, one can reset the transformation to create 271 * such a mapping by using the following pseudocode: 272 * <pre> 273 * GraphicsConfiguration gc = g.getGraphicsConfiguration(); 274 * 275 * g.setTransform(gc.getDefaultTransform()); 276 * g.transform(gc.getNormalizingTransform()); 277 * </pre> 278 * Note that sometimes this Transform will be identity (e.g. for 279 * printers or metafile output) and that this Transform is only 280 * as accurate as the information supplied by the underlying system. 281 * For image buffers, this Transform will be the Identity transform, 282 * since there is no valid distance measurement. 283 */ getNormalizingTransform()284 public AffineTransform getNormalizingTransform() { 285 double xscale = getXResolution(screen.getScreen()) / 72.0; 286 double yscale = getYResolution(screen.getScreen()) / 72.0; 287 return new AffineTransform(xscale, 0.0, 0.0, yscale, 0.0, 0.0); 288 } 289 getXResolution(int screen)290 private native double getXResolution(int screen); getYResolution(int screen)291 private native double getYResolution(int screen); 292 getAData()293 public long getAData() { 294 return aData; 295 } 296 toString()297 public String toString() { 298 return ("X11GraphicsConfig[dev="+screen+ 299 ",vis=0x"+Integer.toHexString(visual)+ 300 "]"); 301 } 302 303 /* 304 * Initialize JNI field and method IDs for fields that may be 305 * accessed from C. 306 */ initIDs()307 private static native void initIDs(); 308 309 static { initIDs()310 initIDs (); 311 } 312 getBounds()313 public Rectangle getBounds() { 314 return pGetBounds(screen.getScreen()); 315 } 316 pGetBounds(int screenNum)317 public native Rectangle pGetBounds(int screenNum); 318 319 private static class XDBECapabilities extends BufferCapabilities { XDBECapabilities()320 public XDBECapabilities() { 321 super(imageCaps, imageCaps, FlipContents.UNDEFINED); 322 } 323 } 324 getBufferCapabilities()325 public BufferCapabilities getBufferCapabilities() { 326 if (bufferCaps == null) { 327 if (doubleBuffer) { 328 bufferCaps = new XDBECapabilities(); 329 } else { 330 bufferCaps = super.getBufferCapabilities(); 331 } 332 } 333 return bufferCaps; 334 } 335 getImageCapabilities()336 public ImageCapabilities getImageCapabilities() { 337 return imageCaps; 338 } 339 isDoubleBuffered()340 public boolean isDoubleBuffered() { 341 return doubleBuffer; 342 } 343 dispose(long x11ConfigData)344 private static native void dispose(long x11ConfigData); 345 346 private static class X11GCDisposerRecord implements DisposerRecord { 347 private long x11ConfigData; X11GCDisposerRecord(long x11CfgData)348 public X11GCDisposerRecord(long x11CfgData) { 349 this.x11ConfigData = x11CfgData; 350 } dispose()351 public synchronized void dispose() { 352 if (x11ConfigData != 0L) { 353 X11GraphicsConfig.dispose(x11ConfigData); 354 x11ConfigData = 0L; 355 } 356 } 357 } 358 359 /** 360 * The following methods are invoked from {M,X}Toolkit.java and 361 * X11ComponentPeer.java rather than having the X11-dependent 362 * implementations hardcoded in those classes. This way the appropriate 363 * actions are taken based on the peer's GraphicsConfig, whether it is 364 * an X11GraphicsConfig or a GLXGraphicsConfig. 365 */ 366 367 /** 368 * Creates a new SurfaceData that will be associated with the given 369 * X11ComponentPeer. 370 */ createSurfaceData(X11ComponentPeer peer)371 public SurfaceData createSurfaceData(X11ComponentPeer peer) { 372 return X11SurfaceData.createData(peer); 373 } 374 375 /** 376 * Creates a new hidden-acceleration image of the given width and height 377 * that is associated with the target Component. 378 */ createAcceleratedImage(Component target, int width, int height)379 public Image createAcceleratedImage(Component target, 380 int width, int height) 381 { 382 // As of 1.7 we no longer create pmoffscreens here... 383 ColorModel model = getColorModel(Transparency.OPAQUE); 384 WritableRaster wr = 385 model.createCompatibleWritableRaster(width, height); 386 return new OffScreenImage(target, model, wr, 387 model.isAlphaPremultiplied()); 388 } 389 390 /** 391 * The following methods correspond to the multibuffering methods in 392 * X11ComponentPeer.java... 393 */ 394 createBackBuffer(long window, int swapAction)395 private native long createBackBuffer(long window, int swapAction); swapBuffers(long window, int swapAction)396 private native void swapBuffers(long window, int swapAction); 397 398 /** 399 * Attempts to create an XDBE-based backbuffer for the given peer. If 400 * the requested configuration is not natively supported, an AWTException 401 * is thrown. Otherwise, if the backbuffer creation is successful, a 402 * handle to the native backbuffer is returned. 403 */ createBackBuffer(X11ComponentPeer peer, int numBuffers, BufferCapabilities caps)404 public long createBackBuffer(X11ComponentPeer peer, 405 int numBuffers, BufferCapabilities caps) 406 throws AWTException 407 { 408 if (!X11GraphicsDevice.isDBESupported()) { 409 throw new AWTException("Page flipping is not supported"); 410 } 411 if (numBuffers > 2) { 412 throw new AWTException( 413 "Only double or single buffering is supported"); 414 } 415 BufferCapabilities configCaps = getBufferCapabilities(); 416 if (!configCaps.isPageFlipping()) { 417 throw new AWTException("Page flipping is not supported"); 418 } 419 420 long window = peer.getContentWindow(); 421 int swapAction = getSwapAction(caps.getFlipContents()); 422 423 return createBackBuffer(window, swapAction); 424 } 425 426 /** 427 * Destroys the backbuffer object represented by the given handle value. 428 */ destroyBackBuffer(long backBuffer)429 public native void destroyBackBuffer(long backBuffer); 430 431 /** 432 * Creates a VolatileImage that essentially wraps the target Component's 433 * backbuffer, using the provided backbuffer handle. 434 */ createBackBufferImage(Component target, long backBuffer)435 public VolatileImage createBackBufferImage(Component target, 436 long backBuffer) 437 { 438 // it is possible for the component to have size 0x0, adjust it to 439 // be at least 1x1 to avoid IAE 440 int w = Math.max(1, target.getWidth()); 441 int h = Math.max(1, target.getHeight()); 442 return new SunVolatileImage(target, 443 w, h, 444 Long.valueOf(backBuffer)); 445 } 446 447 /** 448 * Performs the native XDBE flip operation for the given target Component. 449 */ flip(X11ComponentPeer peer, Component target, VolatileImage xBackBuffer, int x1, int y1, int x2, int y2, BufferCapabilities.FlipContents flipAction)450 public void flip(X11ComponentPeer peer, 451 Component target, VolatileImage xBackBuffer, 452 int x1, int y1, int x2, int y2, 453 BufferCapabilities.FlipContents flipAction) 454 { 455 long window = peer.getContentWindow(); 456 int swapAction = getSwapAction(flipAction); 457 swapBuffers(window, swapAction); 458 } 459 460 /** 461 * Maps the given FlipContents constant to the associated XDBE swap 462 * action constant. 463 */ getSwapAction( BufferCapabilities.FlipContents flipAction)464 private static int getSwapAction( 465 BufferCapabilities.FlipContents flipAction) { 466 if (flipAction == BufferCapabilities.FlipContents.BACKGROUND) { 467 return 0x01; 468 } else if (flipAction == BufferCapabilities.FlipContents.PRIOR) { 469 return 0x02; 470 } else if (flipAction == BufferCapabilities.FlipContents.COPIED) { 471 return 0x03; 472 } else { 473 return 0x00; // UNDEFINED 474 } 475 } 476 477 @Override isTranslucencyCapable()478 public boolean isTranslucencyCapable() { 479 return isTranslucencyCapable(getAData()); 480 } 481 isTranslucencyCapable(long x11ConfigData)482 private native boolean isTranslucencyCapable(long x11ConfigData); 483 } 484