blob: 38af32de54422d24f3484468adc9da1ab4c0dc51 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2004-2007 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.java2d.opengl;
27
28import java.awt.AWTException;
29import java.awt.BufferCapabilities;
30import java.awt.Component;
31import java.awt.Graphics;
32import java.awt.ImageCapabilities;
33import java.awt.Transparency;
34import java.awt.color.ColorSpace;
35import java.awt.image.ColorModel;
36import java.awt.image.DataBuffer;
37import java.awt.image.DirectColorModel;
38import java.awt.image.VolatileImage;
39import sun.awt.Win32GraphicsConfig;
40import sun.awt.Win32GraphicsDevice;
41import sun.awt.image.SunVolatileImage;
42import sun.awt.windows.WComponentPeer;
43import sun.java2d.Disposer;
44import sun.java2d.DisposerRecord;
45import sun.java2d.SurfaceData;
46
47public class WGLGraphicsConfig
48 extends Win32GraphicsConfig
49 implements OGLGraphicsConfig
50{
51 protected static boolean wglAvailable;
52 private static ImageCapabilities imageCaps = new WGLImageCaps();
53
54 private BufferCapabilities bufferCaps;
55 private long pConfigInfo;
56 private int oglCaps;
57 private OGLContext context;
58 private Object disposerReferent = new Object();
59
60 public static native int getDefaultPixFmt(int screennum);
61 private static native boolean initWGL();
62 private static native long getWGLConfigInfo(int screennum, int visualnum);
63 private static native int getOGLCapabilities(long configInfo);
64
65 static {
66 wglAvailable = initWGL();
67 }
68
69 protected WGLGraphicsConfig(Win32GraphicsDevice device, int visualnum,
70 long configInfo, int oglCaps)
71 {
72 super(device, visualnum);
73 this.pConfigInfo = configInfo;
74 this.oglCaps = oglCaps;
75 context = new OGLContext(OGLRenderQueue.getInstance());
76
77 // add a record to the Disposer so that we destroy the native
78 // WGLGraphicsConfigInfo data when this object goes away
79 Disposer.addRecord(disposerReferent,
80 new WGLGCDisposerRecord(pConfigInfo));
81 }
82
83 public Object getProxyKey() {
84 return this;
85 }
86
87 public SurfaceData createManagedSurface(int w, int h, int transparency) {
88 return WGLSurfaceData.createData(this, w, h,
89 getColorModel(transparency),
90 null,
91 OGLSurfaceData.TEXTURE);
92 }
93
94 public static WGLGraphicsConfig getConfig(Win32GraphicsDevice device,
95 int pixfmt)
96 {
97 if (!wglAvailable) {
98 return null;
99 }
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 =
110 new WGLGetConfigInfo(device.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 private WGLGetConfigInfo(int screen, int pixfmt) {
134 this.screen = screen;
135 this.pixfmt = pixfmt;
136 }
137 public void run() {
138 cfginfo = getWGLConfigInfo(screen, pixfmt);
139 }
140 public long getConfigInfo() {
141 return cfginfo;
142 }
143 }
144
145 public static boolean isWGLAvailable() {
146 return wglAvailable;
147 }
148
149 /**
150 * Returns true if the provided capability bit is present for this config.
151 * See OGLContext.java for a list of supported capabilities.
152 */
153 public final boolean isCapPresent(int cap) {
154 return ((oglCaps & cap) != 0);
155 }
156
157 public final long getNativeConfigInfo() {
158 return pConfigInfo;
159 }
160
161 public final OGLContext getContext() {
162 return context;
163 }
164
165 private static class WGLGCDisposerRecord implements DisposerRecord {
166 private long pCfgInfo;
167 public WGLGCDisposerRecord(long pCfgInfo) {
168 this.pCfgInfo = pCfgInfo;
169 }
170 public void dispose() {
171 if (pCfgInfo != 0) {
172 OGLRenderQueue.disposeGraphicsConfig(pCfgInfo);
173 pCfgInfo = 0;
174 }
175 }
176 }
177
178 @Override
179 public synchronized void displayChanged() {
180 super.displayChanged();
181 // the context could hold a reference to a WGLSurfaceData, which in
182 // turn has a reference back to this WGLGraphicsConfig, so in order
183 // for this instance to be disposed we need to break the connection
184 OGLRenderQueue rq = OGLRenderQueue.getInstance();
185 rq.lock();
186 try {
187 OGLContext.invalidateCurrentContext();
188 } finally {
189 rq.unlock();
190 }
191 }
192
193 @Override
194 public ColorModel getColorModel(int transparency) {
195 switch (transparency) {
196 case Transparency.OPAQUE:
197 // REMIND: once the ColorModel spec is changed, this should be
198 // an opaque premultiplied DCM...
199 return new DirectColorModel(24, 0xff0000, 0xff00, 0xff);
200 case Transparency.BITMASK:
201 return new DirectColorModel(25, 0xff0000, 0xff00, 0xff, 0x1000000);
202 case Transparency.TRANSLUCENT:
203 ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
204 return new DirectColorModel(cs, 32,
205 0xff0000, 0xff00, 0xff, 0xff000000,
206 true, DataBuffer.TYPE_INT);
207 default:
208 return null;
209 }
210 }
211
212 @Override
213 public String toString() {
214 return ("WGLGraphicsConfig[dev="+screen+",pixfmt="+visual+"]");
215 }
216
217 /**
218 * The following methods are invoked from WComponentPeer.java rather
219 * than having the Win32-dependent implementations hardcoded in that
220 * class. This way the appropriate actions are taken based on the peer's
221 * GraphicsConfig, whether it is a Win32GraphicsConfig or a
222 * WGLGraphicsConfig.
223 */
224
225 /**
226 * Creates a new SurfaceData that will be associated with the given
227 * WComponentPeer.
228 */
229 @Override
230 public SurfaceData createSurfaceData(WComponentPeer peer,
231 int numBackBuffers)
232 {
233 return WGLSurfaceData.createData(peer);
234 }
235
236 /**
237 * The following methods correspond to the multibuffering methods in
238 * WComponentPeer.java...
239 */
240
241 /**
242 * Checks that the requested configuration is natively supported; if not,
243 * an AWTException is thrown.
244 */
245 @Override
246 public void assertOperationSupported(Component target,
247 int numBuffers,
248 BufferCapabilities caps)
249 throws AWTException
250 {
251 if (numBuffers > 2) {
252 throw new AWTException(
253 "Only double or single buffering is supported");
254 }
255 BufferCapabilities configCaps = getBufferCapabilities();
256 if (!configCaps.isPageFlipping()) {
257 throw new AWTException("Page flipping is not supported");
258 }
259 if (caps.getFlipContents() == BufferCapabilities.FlipContents.PRIOR) {
260 throw new AWTException("FlipContents.PRIOR is not supported");
261 }
262 }
263
264 /**
265 * Creates a WGL-based backbuffer for the given peer and returns the
266 * image wrapper.
267 */
268 @Override
269 public VolatileImage createBackBuffer(WComponentPeer peer) {
270 Component target = (Component)peer.getTarget();
271 return new SunVolatileImage(target,
272 target.getWidth(), target.getHeight(),
273 Boolean.TRUE);
274 }
275
276 /**
277 * Performs the native WGL flip operation for the given target Component.
278 */
279 @Override
280 public void flip(WComponentPeer peer,
281 Component target, VolatileImage backBuffer,
282 BufferCapabilities.FlipContents flipAction)
283 {
284 if (flipAction == BufferCapabilities.FlipContents.COPIED) {
285 Graphics g = peer.getGraphics();
286 try {
287 g.drawImage(backBuffer, 0, 0, null);
288 } finally {
289 g.dispose();
290 }
291 return;
292 } else if (flipAction == BufferCapabilities.FlipContents.PRIOR) {
293 // not supported by WGL...
294 return;
295 }
296
297 OGLSurfaceData.swapBuffers(peer.getData());
298
299 if (flipAction == BufferCapabilities.FlipContents.BACKGROUND) {
300 Graphics g = backBuffer.getGraphics();
301 try {
302 g.setColor(target.getBackground());
303 g.fillRect(0, 0,
304 backBuffer.getWidth(),
305 backBuffer.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,
315 dblBuf ? FlipContents.UNDEFINED : 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 public boolean isTrueVolatile() {
333 return true;
334 }
335 }
336
337 @Override
338 public ImageCapabilities getImageCapabilities() {
339 return imageCaps;
340 }
341}