1 /*
2  * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * - Redistribution of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  *
11  * - Redistribution in binary form must reproduce the above copyright
12  *   notice, this list of conditions and the following disclaimer in the
13  *   documentation and/or other materials provided with the distribution.
14  *
15  * Neither the name of Sun Microsystems, Inc. or the names of
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * This software is provided "AS IS," without a warranty of any kind. ALL
20  * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
21  * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
22  * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
23  * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
24  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
25  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
26  * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
27  * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
28  * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
29  * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
30  * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31  *
32  * You acknowledge that this software is not designed or intended for use
33  * in the design, construction, operation or maintenance of any nuclear
34  * facility.
35  *
36  * Sun gratefully acknowledges that this software was originally authored
37  * and developed by Kenneth Bradley Russell and Christopher John Kline.
38  */
39 
40 package com.sun.opengl.impl.windows;
41 
42 import java.awt.Component;
43 import java.awt.Graphics;
44 import java.awt.Rectangle;
45 import java.nio.*;
46 import java.util.*;
47 import javax.media.opengl.*;
48 import com.sun.opengl.impl.*;
49 import com.sun.opengl.util.BufferUtil;
50 
51 public class WindowsGLDrawableFactory extends GLDrawableFactoryImpl {
52   private static final boolean DEBUG = Debug.debug("WindowsGLDrawableFactory");
53   private static final boolean VERBOSE = Debug.verbose();
54 
55   // Handle to GLU32.dll
56   // FIXME: this should go away once we delete support for the C GLU library
57   private long hglu32;
58 
59   static {
NativeLibLoader.loadCore()60     NativeLibLoader.loadCore();
61   }
62 
chooseGraphicsConfiguration(GLCapabilities capabilities, GLCapabilitiesChooser chooser, AbstractGraphicsDevice device)63   public AbstractGraphicsConfiguration chooseGraphicsConfiguration(GLCapabilities capabilities,
64                                                                    GLCapabilitiesChooser chooser,
65                                                                    AbstractGraphicsDevice device) {
66     return null;
67   }
68 
getGLDrawable(Object target, GLCapabilities capabilities, GLCapabilitiesChooser chooser)69   public GLDrawable getGLDrawable(Object target,
70                                   GLCapabilities capabilities,
71                                   GLCapabilitiesChooser chooser) {
72     if (target == null) {
73       throw new IllegalArgumentException("Null target");
74     }
75     if (!(target instanceof Component)) {
76       throw new IllegalArgumentException("GLDrawables not supported for objects of type " +
77                                          target.getClass().getName() + " (only Components are supported in this implementation)");
78     }
79     if (capabilities == null) {
80       capabilities = new GLCapabilities();
81     }
82     if (chooser == null) {
83       chooser = new DefaultGLCapabilitiesChooser();
84     }
85     return new WindowsOnscreenGLDrawable((Component) target, capabilities, chooser);
86   }
87 
createOffscreenDrawable(GLCapabilities capabilities, GLCapabilitiesChooser chooser)88   public GLDrawableImpl createOffscreenDrawable(GLCapabilities capabilities,
89                                                 GLCapabilitiesChooser chooser) {
90     return new WindowsOffscreenGLDrawable(capabilities, chooser);
91   }
92 
93   private boolean pbufferSupportInitialized = false;
94   private boolean canCreateGLPbuffer = false;
canCreateGLPbuffer()95   public boolean canCreateGLPbuffer() {
96     if (!pbufferSupportInitialized) {
97       Runnable r = new Runnable() {
98           public void run() {
99             WindowsDummyGLDrawable dummyDrawable = new WindowsDummyGLDrawable();
100             GLContext dummyContext  = dummyDrawable.createContext(null);
101             if (dummyContext != null) {
102               GLContext lastContext = GLContext.getCurrent();
103               if (lastContext != null) {
104                 lastContext.release();
105               }
106               dummyContext.makeCurrent();
107               GL dummyGL = dummyContext.getGL();
108               canCreateGLPbuffer = dummyGL.isExtensionAvailable("GL_ARB_pbuffer");
109               pbufferSupportInitialized = true;
110               dummyContext.release();
111               dummyContext.destroy();
112               dummyDrawable.destroy();
113               if (lastContext != null) {
114                 lastContext.makeCurrent();
115               }
116             }
117           }
118         };
119       maybeDoSingleThreadedWorkaround(r);
120     }
121     if (DEBUG) {
122       System.err.println("WindowsGLDrawableFactory.canCreateGLPbuffer() = " + canCreateGLPbuffer);
123     }
124     return canCreateGLPbuffer;
125   }
126 
createGLPbuffer(final GLCapabilities capabilities, final GLCapabilitiesChooser chooser, final int initialWidth, final int initialHeight, final GLContext shareWith)127   public GLPbuffer createGLPbuffer(final GLCapabilities capabilities,
128                                    final GLCapabilitiesChooser chooser,
129                                    final int initialWidth,
130                                    final int initialHeight,
131                                    final GLContext shareWith) {
132     if (!canCreateGLPbuffer()) {
133       throw new GLException("Pbuffer support not available with current graphics card");
134     }
135     final List returnList = new ArrayList();
136     Runnable r = new Runnable() {
137         public void run() {
138           WindowsDummyGLDrawable dummyDrawable = new WindowsDummyGLDrawable();
139           WindowsGLContext       dummyContext  = (WindowsGLContext) dummyDrawable.createContext(null);
140           GLContext lastContext = GLContext.getCurrent();
141           if (lastContext != null) {
142             lastContext.release();
143           }
144           dummyContext.makeCurrent();
145           WGLExt dummyWGLExt = dummyContext.getWGLExt();
146           try {
147             WindowsPbufferGLDrawable pbufferDrawable = new WindowsPbufferGLDrawable(capabilities,
148                                                                                     initialWidth,
149                                                                                     initialHeight,
150                                                                                     dummyDrawable,
151                                                                                     dummyWGLExt);
152             GLPbufferImpl pbuffer = new GLPbufferImpl(pbufferDrawable, shareWith);
153             returnList.add(pbuffer);
154             dummyContext.release();
155             dummyContext.destroy();
156             dummyDrawable.destroy();
157           } finally {
158             if (lastContext != null) {
159               lastContext.makeCurrent();
160             }
161           }
162         }
163       };
164     maybeDoSingleThreadedWorkaround(r);
165     return (GLPbuffer) returnList.get(0);
166   }
167 
createExternalGLContext()168   public GLContext createExternalGLContext() {
169     return new WindowsExternalGLContext();
170   }
171 
canCreateExternalGLDrawable()172   public boolean canCreateExternalGLDrawable() {
173     return true;
174   }
175 
createExternalGLDrawable()176   public GLDrawable createExternalGLDrawable() {
177     return new WindowsExternalGLDrawable();
178   }
179 
loadGLULibrary()180   public void loadGLULibrary() {
181     if (hglu32 == 0) {
182       hglu32 = WGL.LoadLibraryA("GLU32");
183       if (hglu32 == 0) {
184         throw new GLException("Error loading GLU32.DLL");
185       }
186     }
187   }
188 
dynamicLookupFunction(String glFuncName)189   public long dynamicLookupFunction(String glFuncName) {
190     long res = WGL.wglGetProcAddress(glFuncName);
191     if (res == 0) {
192       // GLU routines aren't known to the OpenGL function lookup
193       if (hglu32 != 0) {
194         res = WGL.GetProcAddress(hglu32, glFuncName);
195       }
196     }
197     return res;
198   }
199 
wglGetLastError()200   static String wglGetLastError() {
201     long err = WGL.GetLastError();
202     String detail = null;
203     switch ((int) err) {
204       case WGL.ERROR_INVALID_PIXEL_FORMAT: detail = "ERROR_INVALID_PIXEL_FORMAT";       break;
205       case WGL.ERROR_NO_SYSTEM_RESOURCES:  detail = "ERROR_NO_SYSTEM_RESOURCES";        break;
206       case WGL.ERROR_INVALID_DATA:         detail = "ERROR_INVALID_DATA";               break;
207       case WGL.ERROR_PROC_NOT_FOUND:       detail = "ERROR_PROC_NOT_FOUND";             break;
208       case WGL.ERROR_INVALID_WINDOW_HANDLE:detail = "ERROR_INVALID_WINDOW_HANDLE";      break;
209       default:                             detail = "(Unknown error code " + err + ")"; break;
210     }
211     return detail;
212   }
213 
maybeDoSingleThreadedWorkaround(Runnable action)214   private void maybeDoSingleThreadedWorkaround(Runnable action) {
215     if (Threading.isSingleThreaded() &&
216         !Threading.isOpenGLThread()) {
217       Threading.invokeOnOpenGLThread(action);
218     } else {
219       action.run();
220     }
221   }
222 
lockAWTForJava2D()223   public void lockAWTForJava2D() {
224   }
225 
unlockAWTForJava2D()226   public void unlockAWTForJava2D() {
227   }
228 
canCreateContextOnJava2DSurface()229   public boolean canCreateContextOnJava2DSurface() {
230     return false;
231   }
232 
createContextOnJava2DSurface(Graphics g, GLContext shareWith)233   public GLContext createContextOnJava2DSurface(Graphics g, GLContext shareWith)
234     throws GLException {
235     throw new GLException("Unimplemented on this platform");
236   }
237 
238   //------------------------------------------------------
239   // Gamma-related functionality
240   //
241 
242   private static final int GAMMA_RAMP_LENGTH = 256;
243 
getGammaRampLength()244   protected int getGammaRampLength() {
245     return GAMMA_RAMP_LENGTH;
246   }
247 
setGammaRamp(float[] ramp)248   protected boolean setGammaRamp(float[] ramp) {
249     short[] rampData = new short[3 * GAMMA_RAMP_LENGTH];
250     for (int i = 0; i < GAMMA_RAMP_LENGTH; i++) {
251       short scaledValue = (short) (ramp[i] * 65535);
252       rampData[i] = scaledValue;
253       rampData[i +     GAMMA_RAMP_LENGTH] = scaledValue;
254       rampData[i + 2 * GAMMA_RAMP_LENGTH] = scaledValue;
255     }
256 
257     long screenDC = WGL.GetDC(0);
258     boolean res = WGL.SetDeviceGammaRamp(screenDC, ShortBuffer.wrap(rampData));
259     WGL.ReleaseDC(0, screenDC);
260     return res;
261   }
262 
getGammaRamp()263   protected Buffer getGammaRamp() {
264     ShortBuffer rampData = ShortBuffer.allocate(3 * GAMMA_RAMP_LENGTH);
265     long screenDC = WGL.GetDC(0);
266     boolean res = WGL.GetDeviceGammaRamp(screenDC, rampData);
267     WGL.ReleaseDC(0, screenDC);
268     if (!res) {
269       return null;
270     }
271     return rampData;
272   }
273 
resetGammaRamp(Buffer originalGammaRamp)274   protected void resetGammaRamp(Buffer originalGammaRamp) {
275     if (originalGammaRamp == null) {
276       // getGammaRamp failed earlier
277       return;
278     }
279     long screenDC = WGL.GetDC(0);
280     WGL.SetDeviceGammaRamp(screenDC, originalGammaRamp);
281     WGL.ReleaseDC(0, screenDC);
282   }
283 }
284