001: /*
002: * Copyright 2003-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.java2d.opengl;
027:
028: import java.awt.AWTException;
029: import java.awt.BufferCapabilities;
030: import java.awt.Component;
031: import java.awt.Graphics;
032: import java.awt.Image;
033: import java.awt.ImageCapabilities;
034: import java.awt.Transparency;
035: import java.awt.color.ColorSpace;
036: import java.awt.image.BufferedImage;
037: import java.awt.image.ColorModel;
038: import java.awt.image.DataBuffer;
039: import java.awt.image.DirectColorModel;
040: import java.awt.image.VolatileImage;
041: import java.awt.image.WritableRaster;
042: import sun.awt.X11ComponentPeer;
043: import sun.awt.X11GraphicsConfig;
044: import sun.awt.X11GraphicsDevice;
045: import sun.awt.X11GraphicsEnvironment;
046: import sun.awt.image.OffScreenImage;
047: import sun.awt.image.SunVolatileImage;
048: import sun.java2d.SurfaceData;
049:
050: public class GLXGraphicsConfig extends X11GraphicsConfig implements
051: OGLGraphicsConfig {
052: private static ImageCapabilities imageCaps = new GLXImageCaps();
053: private BufferCapabilities bufferCaps;
054: private long pConfigInfo;
055: private int oglCaps;
056: private OGLContext context;
057:
058: private static native long getGLXConfigInfo(int screennum,
059: int visualnum);
060:
061: private static native int getOGLCapabilities(long configInfo);
062:
063: private native void initConfig(long aData, long ctxinfo);
064:
065: private GLXGraphicsConfig(X11GraphicsDevice device, int visualnum,
066: long configInfo, int oglCaps) {
067: super (device, visualnum, 0, 0,
068: (oglCaps & OGLContext.CAPS_DOUBLEBUFFERED) != 0);
069: pConfigInfo = configInfo;
070: initConfig(getAData(), configInfo);
071: this .oglCaps = oglCaps;
072: context = new OGLContext(OGLRenderQueue.getInstance());
073: }
074:
075: public Object getProxyKey() {
076: return this ;
077: }
078:
079: public SurfaceData createManagedSurface(int w, int h,
080: int transparency) {
081: return GLXSurfaceData.createData(this , w, h,
082: getColorModel(transparency), null,
083: OGLSurfaceData.TEXTURE);
084: }
085:
086: public static GLXGraphicsConfig getConfig(X11GraphicsDevice device,
087: int visualnum) {
088: if (!X11GraphicsEnvironment.isGLXAvailable()) {
089: return null;
090: }
091:
092: long cfginfo = 0;
093: OGLRenderQueue rq = OGLRenderQueue.getInstance();
094: rq.lock();
095: try {
096: // getGLXConfigInfo() creates and destroys temporary
097: // surfaces/contexts, so we should first invalidate the current
098: // Java-level context and flush the queue...
099: OGLContext.invalidateCurrentContext();
100: GLXGetConfigInfo action = new GLXGetConfigInfo(device
101: .getScreen(), visualnum);
102: rq.flushAndInvokeNow(action);
103: cfginfo = action.getConfigInfo();
104: } finally {
105: rq.unlock();
106: }
107: if (cfginfo == 0) {
108: return null;
109: }
110:
111: int oglCaps = getOGLCapabilities(cfginfo);
112:
113: return new GLXGraphicsConfig(device, visualnum, cfginfo,
114: oglCaps);
115: }
116:
117: /**
118: * This is a small helper class that allows us to execute
119: * getGLXConfigInfo() on the queue flushing thread.
120: */
121: private static class GLXGetConfigInfo implements Runnable {
122: private int screen;
123: private int visual;
124: private long cfginfo;
125:
126: private GLXGetConfigInfo(int screen, int visual) {
127: this .screen = screen;
128: this .visual = visual;
129: }
130:
131: public void run() {
132: cfginfo = getGLXConfigInfo(screen, visual);
133: }
134:
135: public long getConfigInfo() {
136: return cfginfo;
137: }
138: }
139:
140: /**
141: * Returns true if the provided capability bit is present for this config.
142: * See OGLContext.java for a list of supported capabilities.
143: */
144: public final boolean isCapPresent(int cap) {
145: return ((oglCaps & cap) != 0);
146: }
147:
148: public final long getNativeConfigInfo() {
149: return pConfigInfo;
150: }
151:
152: public final OGLContext getContext() {
153: return context;
154: }
155:
156: @Override
157: public BufferedImage createCompatibleImage(int width, int height) {
158: ColorModel model = new DirectColorModel(24, 0xff0000, 0xff00,
159: 0xff);
160: WritableRaster raster = model.createCompatibleWritableRaster(
161: width, height);
162: return new BufferedImage(model, raster, model
163: .isAlphaPremultiplied(), null);
164: }
165:
166: @Override
167: public ColorModel getColorModel(int transparency) {
168: switch (transparency) {
169: case Transparency.OPAQUE:
170: // REMIND: once the ColorModel spec is changed, this should be
171: // an opaque premultiplied DCM...
172: return new DirectColorModel(24, 0xff0000, 0xff00, 0xff);
173: case Transparency.BITMASK:
174: return new DirectColorModel(25, 0xff0000, 0xff00, 0xff,
175: 0x1000000);
176: case Transparency.TRANSLUCENT:
177: ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
178: return new DirectColorModel(cs, 32, 0xff0000, 0xff00, 0xff,
179: 0xff000000, true, DataBuffer.TYPE_INT);
180: default:
181: return null;
182: }
183: }
184:
185: public String toString() {
186: return ("GLXGraphicsConfig[dev=" + screen + ",vis=0x"
187: + Integer.toHexString(visual) + "]");
188: }
189:
190: /**
191: * The following methods are invoked from MToolkit or XToolkit.java and
192: * X11ComponentPeer.java rather than having the X11-dependent
193: * implementations hardcoded in those classes. This way the appropriate
194: * actions are taken based on the peer's GraphicsConfig, whether it is
195: * an X11GraphicsConfig or a GLXGraphicsConfig.
196: */
197:
198: /**
199: * Creates a new SurfaceData that will be associated with the given
200: * X11ComponentPeer.
201: */
202: @Override
203: public SurfaceData createSurfaceData(X11ComponentPeer peer) {
204: return GLXSurfaceData.createData(peer);
205: }
206:
207: /**
208: * Creates a new hidden-acceleration image of the given width and height
209: * that is associated with the target Component.
210: */
211: @Override
212: public Image createAcceleratedImage(Component target, int width,
213: int height) {
214: ColorModel model = getColorModel(Transparency.OPAQUE);
215: WritableRaster wr = model.createCompatibleWritableRaster(width,
216: height);
217: return new OffScreenImage(target, model, wr, model
218: .isAlphaPremultiplied());
219: }
220:
221: /**
222: * The following methods correspond to the multibuffering methods in
223: * X11ComponentPeer.java...
224: */
225:
226: /**
227: * Attempts to create a GLX-based backbuffer for the given peer. If
228: * the requested configuration is not natively supported, an AWTException
229: * is thrown. Otherwise, if the backbuffer creation is successful, a
230: * value of 1 is returned.
231: */
232: @Override
233: public long createBackBuffer(X11ComponentPeer peer, int numBuffers,
234: BufferCapabilities caps) throws AWTException {
235: if (numBuffers > 2) {
236: throw new AWTException(
237: "Only double or single buffering is supported");
238: }
239: BufferCapabilities configCaps = getBufferCapabilities();
240: if (!configCaps.isPageFlipping()) {
241: throw new AWTException("Page flipping is not supported");
242: }
243: if (caps.getFlipContents() == BufferCapabilities.FlipContents.PRIOR) {
244: throw new AWTException(
245: "FlipContents.PRIOR is not supported");
246: }
247:
248: // non-zero return value means backbuffer creation was successful
249: // (checked in X11ComponentPeer.flip(), etc.)
250: return 1;
251: }
252:
253: /**
254: * Destroys the backbuffer object represented by the given handle value.
255: */
256: @Override
257: public void destroyBackBuffer(long backBuffer) {
258: }
259:
260: /**
261: * Creates a VolatileImage that essentially wraps the target Component's
262: * backbuffer (the provided backbuffer handle is essentially ignored).
263: */
264: @Override
265: public VolatileImage createBackBufferImage(Component target,
266: long backBuffer) {
267: return new SunVolatileImage(target, target.getWidth(), target
268: .getHeight(), Boolean.TRUE);
269: }
270:
271: /**
272: * Performs the native GLX flip operation for the given target Component.
273: */
274: @Override
275: public void flip(X11ComponentPeer peer, Component target,
276: VolatileImage xBackBuffer,
277: BufferCapabilities.FlipContents flipAction) {
278: if (flipAction == BufferCapabilities.FlipContents.COPIED) {
279: Graphics g = peer.getGraphics();
280: try {
281: g.drawImage(xBackBuffer, 0, 0, null);
282: } finally {
283: g.dispose();
284: }
285: return;
286: } else if (flipAction == BufferCapabilities.FlipContents.PRIOR) {
287: // not supported by GLX...
288: return;
289: }
290:
291: OGLSurfaceData.swapBuffers(peer.getContentWindow());
292:
293: if (flipAction == BufferCapabilities.FlipContents.BACKGROUND) {
294: Graphics g = xBackBuffer.getGraphics();
295: try {
296: g.setColor(target.getBackground());
297: g.fillRect(0, 0, xBackBuffer.getWidth(), xBackBuffer
298: .getHeight());
299: } finally {
300: g.dispose();
301: }
302: }
303: }
304:
305: private static class GLXBufferCaps extends BufferCapabilities {
306: public GLXBufferCaps(boolean dblBuf) {
307: super (imageCaps, imageCaps, dblBuf ? FlipContents.UNDEFINED
308: : null);
309: }
310: }
311:
312: @Override
313: public BufferCapabilities getBufferCapabilities() {
314: if (bufferCaps == null) {
315: bufferCaps = new GLXBufferCaps(isDoubleBuffered());
316: }
317: return bufferCaps;
318: }
319:
320: private static class GLXImageCaps extends ImageCapabilities {
321: private GLXImageCaps() {
322: super (true);
323: }
324:
325: public boolean isTrueVolatile() {
326: return true;
327: }
328: }
329:
330: @Override
331: public ImageCapabilities getImageCapabilities() {
332: return imageCaps;
333: }
334: }
|