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