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