001: /*
002: * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.awt;
027:
028: import java.awt.AWTException;
029: import java.awt.BufferCapabilities;
030: import java.awt.Component;
031: import java.awt.Toolkit;
032: import java.awt.GraphicsConfiguration;
033: import java.awt.GraphicsDevice;
034: import java.awt.Image;
035: import java.awt.ImageCapabilities;
036: import java.awt.image.DataBuffer;
037: import java.awt.Transparency;
038: import java.awt.image.BufferedImage;
039: import java.awt.image.ColorModel;
040: import java.awt.image.DirectColorModel;
041: import java.awt.image.ImageProducer;
042: import java.awt.image.IndexColorModel;
043: import java.awt.image.Raster;
044: import java.awt.image.VolatileImage;
045: import java.awt.image.WritableRaster;
046: import java.awt.geom.AffineTransform;
047: import java.awt.Rectangle;
048: import sun.java2d.Disposer;
049: import sun.java2d.DisposerRecord;
050: import sun.java2d.SurfaceData;
051: import sun.java2d.loops.RenderLoops;
052: import sun.java2d.loops.SurfaceType;
053: import sun.java2d.loops.CompositeType;
054: import sun.java2d.x11.X11SurfaceData;
055: import sun.awt.image.OffScreenImage;
056: import sun.awt.image.SunVolatileImage;
057: import sun.awt.image.SurfaceManager;
058: import sun.awt.X11ComponentPeer;
059:
060: /**
061: * This is an implementation of a GraphicsConfiguration object for a
062: * single X11 visual.
063: *
064: * @see GraphicsEnvironment
065: * @see GraphicsDevice
066: * @version 1.77, 05/05/07
067: */
068: public class X11GraphicsConfig extends GraphicsConfiguration implements
069: SurfaceManager.ProxiedGraphicsConfig {
070: protected X11GraphicsDevice screen;
071: protected int visual;
072: int depth;
073: int colormap;
074: ColorModel colorModel;
075: long aData;
076: boolean doubleBuffer;
077: private Object disposerReferent = new Object();
078: private BufferCapabilities bufferCaps;
079: private static ImageCapabilities imageCaps = new ImageCapabilities(
080: X11SurfaceData.isAccelerationEnabled());
081:
082: // will be set on native level from init()
083: protected int bitsPerPixel;
084:
085: protected SurfaceType surfaceType;
086:
087: public RenderLoops solidloops;
088:
089: public static X11GraphicsConfig getConfig(X11GraphicsDevice device,
090: int visualnum, int depth, int colormap, boolean doubleBuffer) {
091: return new X11GraphicsConfig(device, visualnum, depth,
092: colormap, doubleBuffer);
093: }
094:
095: /*
096: * Note this method is currently here for backward compatability
097: * as this was the method used in jdk 1.2 beta4 to create the
098: * X11GraphicsConfig objects. Java3D code had called this method
099: * explicitly so without this, if a user tries to use JDK1.2 fcs
100: * with Java3D beta1, a NoSuchMethod execption is thrown and
101: * the program exits. REMOVE this method after Java3D fcs is
102: * released!
103: */
104: public static X11GraphicsConfig getConfig(X11GraphicsDevice device,
105: int visualnum, int depth, int colormap, int type) {
106: return new X11GraphicsConfig(device, visualnum, depth,
107: colormap, false);
108: }
109:
110: private native int getNumColors();
111:
112: private native void init(int visualNum, int screen);
113:
114: private native ColorModel makeColorModel();
115:
116: protected X11GraphicsConfig(X11GraphicsDevice device,
117: int visualnum, int depth, int colormap, boolean doubleBuffer) {
118: this .screen = device;
119: this .visual = visualnum;
120: this .doubleBuffer = doubleBuffer;
121: this .depth = depth;
122: this .colormap = colormap;
123: init(visualnum, screen.getScreen());
124:
125: // add a record to the Disposer so that we destroy the native
126: // AwtGraphicsConfigData when this object goes away (i.e. after a
127: // display change event)
128: long x11CfgData = getAData();
129: Disposer.addRecord(disposerReferent, new X11GCDisposerRecord(
130: x11CfgData));
131: }
132:
133: /**
134: * Return the graphics device associated with this configuration.
135: */
136: public GraphicsDevice getDevice() {
137: return screen;
138: }
139:
140: /**
141: * Returns the visual id associated with this configuration.
142: */
143: public int getVisual() {
144: return visual;
145: }
146:
147: /**
148: * Returns the depth associated with this configuration.
149: */
150: public int getDepth() {
151: return depth;
152: }
153:
154: /**
155: * Returns the colormap associated with this configuration.
156: */
157: public int getColormap() {
158: return colormap;
159: }
160:
161: /**
162: * Returns a number of bits allocated per pixel
163: * (might be different from depth)
164: */
165: public int getBitsPerPixel() {
166: return bitsPerPixel;
167: }
168:
169: public synchronized SurfaceType getSurfaceType() {
170: if (surfaceType != null) {
171: return surfaceType;
172: }
173:
174: surfaceType = X11SurfaceData.getSurfaceType(this ,
175: Transparency.OPAQUE);
176: return surfaceType;
177: }
178:
179: public Object getProxyKey() {
180: return screen.getProxyKeyFor(getSurfaceType());
181: }
182:
183: /**
184: * Return the RenderLoops this type of destination uses for
185: * solid fills and strokes.
186: */
187: public synchronized RenderLoops getSolidLoops(SurfaceType stype) {
188: if (solidloops == null) {
189: solidloops = SurfaceData.makeRenderLoops(
190: SurfaceType.OpaqueColor, CompositeType.SrcNoEa,
191: stype);
192: }
193: return solidloops;
194: }
195:
196: /**
197: * Returns the color model associated with this configuration.
198: */
199: public synchronized ColorModel getColorModel() {
200: if (colorModel == null) {
201: // Force SystemColors to be resolved before we create the CM
202: java.awt.SystemColor.window.getRGB();
203: // This method, makeColorModel(), can return null if the
204: // toolkit is not initialized yet.
205: // The toolkit will then call back to this routine after it
206: // is initialized and makeColorModel() should return a non-null
207: // colorModel.
208: colorModel = makeColorModel();
209: if (colorModel == null)
210: colorModel = Toolkit.getDefaultToolkit()
211: .getColorModel();
212: }
213:
214: return colorModel;
215: }
216:
217: /**
218: * Returns the color model associated with this configuration that
219: * supports the specified transparency.
220: */
221: public ColorModel getColorModel(int transparency) {
222: switch (transparency) {
223: case Transparency.OPAQUE:
224: return getColorModel();
225: case Transparency.BITMASK:
226: return new DirectColorModel(25, 0xff0000, 0xff00, 0xff,
227: 0x1000000);
228: case Transparency.TRANSLUCENT:
229: return ColorModel.getRGBdefault();
230: default:
231: return null;
232: }
233: }
234:
235: /**
236: * Returns the default Transform for this configuration. This
237: * Transform is typically the Identity transform for most normal
238: * screens. Device coordinates for screen and printer devices will
239: * have the origin in the upper left-hand corner of the target region of
240: * the device, with X coordinates
241: * increasing to the right and Y coordinates increasing downwards.
242: * For image buffers, this Transform will be the Identity transform.
243: */
244: public AffineTransform getDefaultTransform() {
245: return new AffineTransform();
246: }
247:
248: /**
249: *
250: * Returns a Transform that can be composed with the default Transform
251: * of a Graphics2D so that 72 units in user space will equal 1 inch
252: * in device space.
253: * Given a Graphics2D, g, one can reset the transformation to create
254: * such a mapping by using the following pseudocode:
255: * <pre>
256: * GraphicsConfiguration gc = g.getGraphicsConfiguration();
257: *
258: * g.setTransform(gc.getDefaultTransform());
259: * g.transform(gc.getNormalizingTransform());
260: * </pre>
261: * Note that sometimes this Transform will be identity (e.g. for
262: * printers or metafile output) and that this Transform is only
263: * as accurate as the information supplied by the underlying system.
264: * For image buffers, this Transform will be the Identity transform,
265: * since there is no valid distance measurement.
266: */
267: public AffineTransform getNormalizingTransform() {
268: double xscale = getXResolution(screen.getScreen()) / 72.0;
269: double yscale = getYResolution(screen.getScreen()) / 72.0;
270: return new AffineTransform(xscale, 0.0, 0.0, yscale, 0.0, 0.0);
271: }
272:
273: private native double getXResolution(int screen);
274:
275: private native double getYResolution(int screen);
276:
277: public long getAData() {
278: return aData;
279: }
280:
281: public String toString() {
282: return ("X11GraphicsConfig[dev=" + screen + ",vis=0x"
283: + Integer.toHexString(visual) + "]");
284: }
285:
286: /*
287: * Initialize JNI field and method IDs for fields that may be
288: * accessed from C.
289: */
290: private static native void initIDs();
291:
292: static {
293: initIDs();
294: }
295:
296: public Rectangle getBounds() {
297: return pGetBounds(screen.getScreen());
298: }
299:
300: public native Rectangle pGetBounds(int screenNum);
301:
302: private static class XDBECapabilities extends BufferCapabilities {
303: public XDBECapabilities() {
304: super (imageCaps, imageCaps, FlipContents.UNDEFINED);
305: }
306: }
307:
308: public BufferCapabilities getBufferCapabilities() {
309: if (bufferCaps == null) {
310: if (doubleBuffer) {
311: bufferCaps = new XDBECapabilities();
312: } else {
313: bufferCaps = super .getBufferCapabilities();
314: }
315: }
316: return bufferCaps;
317: }
318:
319: public ImageCapabilities getImageCapabilities() {
320: return imageCaps;
321: }
322:
323: public boolean isDoubleBuffered() {
324: return doubleBuffer;
325: }
326:
327: private static native void dispose(long x11ConfigData);
328:
329: private static class X11GCDisposerRecord implements DisposerRecord {
330: private long x11ConfigData;
331:
332: public X11GCDisposerRecord(long x11CfgData) {
333: this .x11ConfigData = x11CfgData;
334: }
335:
336: public synchronized void dispose() {
337: if (x11ConfigData != 0L) {
338: X11GraphicsConfig.dispose(x11ConfigData);
339: x11ConfigData = 0L;
340: }
341: }
342: }
343:
344: /**
345: * The following methods are invoked from {M,X}Toolkit.java and
346: * X11ComponentPeer.java rather than having the X11-dependent
347: * implementations hardcoded in those classes. This way the appropriate
348: * actions are taken based on the peer's GraphicsConfig, whether it is
349: * an X11GraphicsConfig or a GLXGraphicsConfig.
350: */
351:
352: /**
353: * Creates a new SurfaceData that will be associated with the given
354: * X11ComponentPeer.
355: */
356: public SurfaceData createSurfaceData(X11ComponentPeer peer) {
357: return X11SurfaceData.createData(peer);
358: }
359:
360: /**
361: * Creates a new hidden-acceleration image of the given width and height
362: * that is associated with the target Component.
363: */
364: public Image createAcceleratedImage(Component target, int width,
365: int height) {
366: // As of 1.7 we no longer create pmoffscreens here...
367: ColorModel model = getColorModel(Transparency.OPAQUE);
368: WritableRaster wr = model.createCompatibleWritableRaster(width,
369: height);
370: return new OffScreenImage(target, model, wr, model
371: .isAlphaPremultiplied());
372: }
373:
374: /**
375: * The following methods correspond to the multibuffering methods in
376: * X11ComponentPeer.java...
377: */
378:
379: private native long createBackBuffer(long window, int swapAction);
380:
381: private native void swapBuffers(long window, int swapAction);
382:
383: /**
384: * Attempts to create an XDBE-based backbuffer for the given peer. If
385: * the requested configuration is not natively supported, an AWTException
386: * is thrown. Otherwise, if the backbuffer creation is successful, a
387: * handle to the native backbuffer is returned.
388: */
389: public long createBackBuffer(X11ComponentPeer peer, int numBuffers,
390: BufferCapabilities caps) throws AWTException {
391: if (!X11GraphicsDevice.isDBESupported()) {
392: throw new AWTException("Page flipping is not supported");
393: }
394: if (numBuffers > 2) {
395: throw new AWTException(
396: "Only double or single buffering is supported");
397: }
398: BufferCapabilities configCaps = getBufferCapabilities();
399: if (!configCaps.isPageFlipping()) {
400: throw new AWTException("Page flipping is not supported");
401: }
402:
403: long window = peer.getContentWindow();
404: int swapAction = getSwapAction(caps.getFlipContents());
405:
406: return createBackBuffer(window, swapAction);
407: }
408:
409: /**
410: * Destroys the backbuffer object represented by the given handle value.
411: */
412: public native void destroyBackBuffer(long backBuffer);
413:
414: /**
415: * Creates a VolatileImage that essentially wraps the target Component's
416: * backbuffer, using the provided backbuffer handle.
417: */
418: public VolatileImage createBackBufferImage(Component target,
419: long backBuffer) {
420: return new SunVolatileImage(target, target.getWidth(), target
421: .getHeight(), new Long(backBuffer));
422: }
423:
424: /**
425: * Performs the native XDBE flip operation for the given target Component.
426: */
427: public void flip(X11ComponentPeer peer, Component target,
428: VolatileImage xBackBuffer,
429: BufferCapabilities.FlipContents flipAction) {
430: long window = peer.getContentWindow();
431: int swapAction = getSwapAction(flipAction);
432: swapBuffers(window, swapAction);
433: }
434:
435: /**
436: * Maps the given FlipContents constant to the associated XDBE swap
437: * action constant.
438: */
439: private static int getSwapAction(
440: BufferCapabilities.FlipContents flipAction) {
441: if (flipAction == BufferCapabilities.FlipContents.BACKGROUND) {
442: return 0x01;
443: } else if (flipAction == BufferCapabilities.FlipContents.PRIOR) {
444: return 0x02;
445: } else if (flipAction == BufferCapabilities.FlipContents.COPIED) {
446: return 0x03;
447: } else {
448: return 0x00; // UNDEFINED
449: }
450: }
451: }
|