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 javax.media.opengl.*; 43 import com.sun.opengl.impl.*; 44 45 public abstract class WindowsGLDrawable extends GLDrawableImpl { 46 protected static final boolean DEBUG = Debug.debug("WindowsGLDrawable"); 47 48 protected long hdc; 49 protected GLCapabilities capabilities; 50 protected GLCapabilitiesChooser chooser; 51 protected boolean pixelFormatChosen; 52 53 protected static final int MAX_PFORMATS = 256; 54 protected static final int MAX_ATTRIBS = 256; 55 WindowsGLDrawable(GLCapabilities capabilities, GLCapabilitiesChooser chooser)56 public WindowsGLDrawable(GLCapabilities capabilities, 57 GLCapabilitiesChooser chooser) { 58 this.capabilities = (GLCapabilities) capabilities.clone(); 59 this.chooser = chooser; 60 } 61 setRealized(boolean val)62 public void setRealized(boolean val) { 63 throw new GLException("Should not call this (should only be called for onscreen GLDrawables)"); 64 } 65 destroy()66 public void destroy() { 67 throw new GLException("Should not call this (should only be called for offscreen GLDrawables)"); 68 } 69 swapBuffers()70 public void swapBuffers() throws GLException { 71 } 72 getHDC()73 public long getHDC() { 74 return hdc; 75 } 76 choosePixelFormat(boolean onscreen)77 protected void choosePixelFormat(boolean onscreen) { 78 PIXELFORMATDESCRIPTOR pfd = null; 79 int pixelFormat = 0; 80 GLCapabilities chosenCaps = null; 81 if (onscreen) { 82 if ((pixelFormat = WGL.GetPixelFormat(hdc)) != 0) { 83 // The Java2D/OpenGL pipeline probably already set a pixel 84 // format for this canvas. 85 if (DEBUG) { 86 System.err.println("NOTE: pixel format already chosen (by Java2D/OpenGL pipeline?) for window: " + 87 WGL.GetPixelFormat(hdc)); 88 } 89 pfd = newPixelFormatDescriptor(); 90 if (WGL.DescribePixelFormat(hdc, pixelFormat, pfd.size(), pfd) == 0) { 91 // FIXME: should this just be a warning? Not really critical... 92 throw new GLException("Unable to describe pixel format " + pixelFormat + 93 " of window set by Java2D/OpenGL pipeline"); 94 } 95 setChosenGLCapabilities(pfd2GLCapabilities(pfd)); 96 pixelFormatChosen = true; 97 return; 98 } 99 100 GLCapabilities[] availableCaps = null; 101 int numFormats = 0; 102 pfd = newPixelFormatDescriptor(); 103 // Produce a recommended pixel format selection for the GLCapabilitiesChooser. 104 // Use wglChoosePixelFormatARB if user requested multisampling and if we have it available 105 WindowsGLDrawable dummyDrawable = null; 106 GLContextImpl dummyContext = null; 107 WGLExt dummyWGLExt = null; 108 if (capabilities.getSampleBuffers()) { 109 dummyDrawable = new WindowsDummyGLDrawable(); 110 dummyContext = (GLContextImpl) dummyDrawable.createContext(null); 111 if (dummyContext != null) { 112 dummyContext.makeCurrent(); 113 dummyWGLExt = (WGLExt) dummyContext.getPlatformGLExtensions(); 114 } 115 } 116 int recommendedPixelFormat = -1; 117 boolean haveWGLChoosePixelFormatARB = false; 118 boolean haveWGLARBMultisample = false; 119 boolean gotAvailableCaps = false; 120 if (dummyWGLExt != null) { 121 try { 122 haveWGLChoosePixelFormatARB = dummyWGLExt.isExtensionAvailable("WGL_ARB_pixel_format"); 123 if (haveWGLChoosePixelFormatARB) { 124 haveWGLARBMultisample = dummyWGLExt.isExtensionAvailable("WGL_ARB_multisample"); 125 126 int[] iattributes = new int [2 * MAX_ATTRIBS]; 127 int[] iresults = new int [2 * MAX_ATTRIBS]; 128 float[] fattributes = new float[1]; 129 130 if (glCapabilities2iattributes(capabilities, 131 iattributes, 132 dummyWGLExt, 133 false, 134 null)) { 135 int[] pformats = new int[MAX_PFORMATS]; 136 int[] numFormatsTmp = new int[1]; 137 if (dummyWGLExt.wglChoosePixelFormatARB(hdc, 138 iattributes, 0, 139 fattributes, 0, 140 MAX_PFORMATS, 141 pformats, 0, 142 numFormatsTmp, 0)) { 143 numFormats = numFormatsTmp[0]; 144 if (numFormats > 0) { 145 // Remove one-basing of pixel format (added on later) 146 recommendedPixelFormat = pformats[0] - 1; 147 if (DEBUG) { 148 System.err.println(getThreadName() + ": Used wglChoosePixelFormatARB to recommend pixel format " + recommendedPixelFormat); 149 } 150 } 151 } else { 152 if (DEBUG) { 153 System.err.println(getThreadName() + ": wglChoosePixelFormatARB failed: " + WGL.GetLastError() ); 154 Thread.dumpStack(); 155 } 156 } 157 if (DEBUG) { 158 if (recommendedPixelFormat < 0) { 159 System.err.print(getThreadName() + ": wglChoosePixelFormatARB didn't recommend a pixel format"); 160 if (capabilities.getSampleBuffers()) { 161 System.err.print(" for multisampled GLCapabilities"); 162 } 163 System.err.println(); 164 } 165 } 166 167 // Produce a list of GLCapabilities to give to the 168 // GLCapabilitiesChooser. 169 // Use wglGetPixelFormatAttribivARB instead of 170 // DescribePixelFormat to get higher-precision information 171 // about the pixel format (should make the GLCapabilities 172 // more precise as well...i.e., remove the 173 // "HardwareAccelerated" bit, which is basically 174 // meaningless, and put in whether it can render to a 175 // window, to a pbuffer, or to a pixmap) 176 int niattribs = 0; 177 iattributes[0] = WGLExt.WGL_NUMBER_PIXEL_FORMATS_ARB; 178 if (dummyWGLExt.wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, iattributes, 0, iresults, 0)) { 179 numFormats = iresults[0]; 180 181 if (DEBUG) { 182 System.err.println("wglGetPixelFormatAttribivARB reported WGL_NUMBER_PIXEL_FORMATS_ARB = " + numFormats); 183 } 184 185 // Should we be filtering out the pixel formats which aren't 186 // applicable, as we are doing here? 187 // We don't have enough information in the GLCapabilities to 188 // represent those that aren't... 189 iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_WINDOW_ARB; 190 iattributes[niattribs++] = WGLExt.WGL_ACCELERATION_ARB; 191 iattributes[niattribs++] = WGLExt.WGL_SUPPORT_OPENGL_ARB; 192 iattributes[niattribs++] = WGLExt.WGL_DEPTH_BITS_ARB; 193 iattributes[niattribs++] = WGLExt.WGL_STENCIL_BITS_ARB; 194 iattributes[niattribs++] = WGLExt.WGL_DOUBLE_BUFFER_ARB; 195 iattributes[niattribs++] = WGLExt.WGL_STEREO_ARB; 196 iattributes[niattribs++] = WGLExt.WGL_PIXEL_TYPE_ARB; 197 iattributes[niattribs++] = WGLExt.WGL_RED_BITS_ARB; 198 iattributes[niattribs++] = WGLExt.WGL_GREEN_BITS_ARB; 199 iattributes[niattribs++] = WGLExt.WGL_BLUE_BITS_ARB; 200 iattributes[niattribs++] = WGLExt.WGL_ALPHA_BITS_ARB; 201 iattributes[niattribs++] = WGLExt.WGL_ACCUM_RED_BITS_ARB; 202 iattributes[niattribs++] = WGLExt.WGL_ACCUM_GREEN_BITS_ARB; 203 iattributes[niattribs++] = WGLExt.WGL_ACCUM_BLUE_BITS_ARB; 204 iattributes[niattribs++] = WGLExt.WGL_ACCUM_ALPHA_BITS_ARB; 205 if (haveWGLARBMultisample) { 206 iattributes[niattribs++] = WGLExt.WGL_SAMPLE_BUFFERS_ARB; 207 iattributes[niattribs++] = WGLExt.WGL_SAMPLES_ARB; 208 } 209 210 availableCaps = new GLCapabilities[numFormats]; 211 for (int i = 0; i < numFormats; i++) { 212 if (!dummyWGLExt.wglGetPixelFormatAttribivARB(hdc, i+1, 0, niattribs, iattributes, 0, iresults, 0)) { 213 throw new GLException("Error getting pixel format attributes for pixel format " + (i + 1) + " of device context"); 214 } 215 availableCaps[i] = iattributes2GLCapabilities(iattributes, niattribs, iresults, true); 216 } 217 gotAvailableCaps = true; 218 } else { 219 long lastErr = WGL.GetLastError(); 220 // Intel Extreme graphics fails with a zero error code 221 if (lastErr != 0) { 222 throw new GLException("Unable to enumerate pixel formats of window using wglGetPixelFormatAttribivARB: error code " + WGL.GetLastError()); 223 } 224 } 225 } 226 } 227 } finally { 228 dummyContext.release(); 229 dummyContext.destroy(); 230 dummyDrawable.destroy(); 231 } 232 } 233 234 // Fallback path for older cards, in particular Intel Extreme motherboard graphics 235 if (!gotAvailableCaps) { 236 if (DEBUG) { 237 if (!capabilities.getSampleBuffers()) { 238 System.err.println(getThreadName() + ": Using ChoosePixelFormat because multisampling not requested"); 239 } else { 240 System.err.println(getThreadName() + ": Using ChoosePixelFormat because no wglChoosePixelFormatARB"); 241 } 242 } 243 pfd = glCapabilities2PFD(capabilities, onscreen); 244 // Remove one-basing of pixel format (added on later) 245 recommendedPixelFormat = WGL.ChoosePixelFormat(hdc, pfd) - 1; 246 247 numFormats = WGL.DescribePixelFormat(hdc, 1, 0, null); 248 if (numFormats == 0) { 249 throw new GLException("Unable to enumerate pixel formats of window for GLCapabilitiesChooser"); 250 } 251 availableCaps = new GLCapabilities[numFormats]; 252 for (int i = 0; i < numFormats; i++) { 253 if (WGL.DescribePixelFormat(hdc, 1 + i, pfd.size(), pfd) == 0) { 254 throw new GLException("Error describing pixel format " + (1 + i) + " of device context"); 255 } 256 availableCaps[i] = pfd2GLCapabilities(pfd); 257 } 258 } 259 260 // NOTE: officially, should make a copy of all of these 261 // GLCapabilities to avoid mutation by the end user during the 262 // chooseCapabilities call, but for the time being, assume they 263 // won't be changed 264 265 // Supply information to chooser 266 pixelFormat = chooser.chooseCapabilities(capabilities, availableCaps, recommendedPixelFormat); 267 if ((pixelFormat < 0) || (pixelFormat >= numFormats)) { 268 throw new GLException("Invalid result " + pixelFormat + 269 " from GLCapabilitiesChooser (should be between 0 and " + 270 (numFormats - 1) + ")"); 271 } 272 if (DEBUG) { 273 System.err.println(getThreadName() + ": Chosen pixel format (" + pixelFormat + "):"); 274 System.err.println(availableCaps[pixelFormat]); 275 } 276 chosenCaps = availableCaps[pixelFormat]; 277 pixelFormat += 1; // one-base the index 278 if (WGL.DescribePixelFormat(hdc, pixelFormat, pfd.size(), pfd) == 0) { 279 throw new GLException("Error re-describing the chosen pixel format: " + WGL.GetLastError()); 280 } 281 } else { 282 // For now, use ChoosePixelFormat for offscreen surfaces until 283 // we figure out how to properly choose an offscreen- 284 // compatible pixel format 285 pfd = glCapabilities2PFD(capabilities, onscreen); 286 pixelFormat = WGL.ChoosePixelFormat(hdc, pfd); 287 } 288 if (!WGL.SetPixelFormat(hdc, pixelFormat, pfd)) { 289 long lastError = WGL.GetLastError(); 290 if (DEBUG) { 291 System.err.println(getThreadName() + ": SetPixelFormat failed: current context = " + WGL.wglGetCurrentContext() + 292 ", current DC = " + WGL.wglGetCurrentDC()); 293 System.err.println(getThreadName() + ": GetPixelFormat(hdc " + toHexString(hdc) + ") returns " + WGL.GetPixelFormat(hdc)); 294 } 295 throw new GLException("Unable to set pixel format " + pixelFormat + " for device context " + toHexString(hdc) + ": error code " + lastError); 296 } 297 // Reuse the previously-constructed GLCapabilities because it 298 // turns out that using DescribePixelFormat on some pixel formats 299 // (which, for example, support full-scene antialiasing) for some 300 // reason return that they are not OpenGL-capable 301 if (chosenCaps != null) { 302 setChosenGLCapabilities(chosenCaps); 303 } else { 304 setChosenGLCapabilities(pfd2GLCapabilities(pfd)); 305 } 306 pixelFormatChosen = true; 307 } 308 glCapabilities2PFD(GLCapabilities caps, boolean onscreen)309 protected static PIXELFORMATDESCRIPTOR glCapabilities2PFD(GLCapabilities caps, boolean onscreen) { 310 int colorDepth = (caps.getRedBits() + 311 caps.getGreenBits() + 312 caps.getBlueBits()); 313 if (colorDepth < 15) { 314 throw new GLException("Bit depths < 15 (i.e., non-true-color) not supported"); 315 } 316 PIXELFORMATDESCRIPTOR pfd = newPixelFormatDescriptor(); 317 int pfdFlags = (WGL.PFD_SUPPORT_OPENGL | 318 WGL.PFD_GENERIC_ACCELERATED); 319 if (caps.getDoubleBuffered()) { 320 pfdFlags |= WGL.PFD_DOUBLEBUFFER; 321 } 322 if (onscreen) { 323 pfdFlags |= WGL.PFD_DRAW_TO_WINDOW; 324 } else { 325 pfdFlags |= WGL.PFD_DRAW_TO_BITMAP; 326 } 327 if (caps.getStereo()) { 328 pfdFlags |= WGL.PFD_STEREO; 329 } 330 pfd.dwFlags(pfdFlags); 331 pfd.iPixelType((byte) WGL.PFD_TYPE_RGBA); 332 pfd.cColorBits((byte) colorDepth); 333 pfd.cRedBits ((byte) caps.getRedBits()); 334 pfd.cGreenBits((byte) caps.getGreenBits()); 335 pfd.cBlueBits ((byte) caps.getBlueBits()); 336 pfd.cAlphaBits((byte) caps.getAlphaBits()); 337 int accumDepth = (caps.getAccumRedBits() + 338 caps.getAccumGreenBits() + 339 caps.getAccumBlueBits()); 340 pfd.cAccumBits ((byte) accumDepth); 341 pfd.cAccumRedBits ((byte) caps.getAccumRedBits()); 342 pfd.cAccumGreenBits((byte) caps.getAccumGreenBits()); 343 pfd.cAccumBlueBits ((byte) caps.getAccumBlueBits()); 344 pfd.cAccumAlphaBits((byte) caps.getAccumAlphaBits()); 345 pfd.cDepthBits((byte) caps.getDepthBits()); 346 pfd.cStencilBits((byte) caps.getStencilBits()); 347 pfd.iLayerType((byte) WGL.PFD_MAIN_PLANE); 348 return pfd; 349 } 350 newPixelFormatDescriptor()351 protected static PIXELFORMATDESCRIPTOR newPixelFormatDescriptor() { 352 PIXELFORMATDESCRIPTOR pfd = PIXELFORMATDESCRIPTOR.create(); 353 pfd.nSize((short) pfd.size()); 354 pfd.nVersion((short) 1); 355 return pfd; 356 } 357 pfd2GLCapabilities(PIXELFORMATDESCRIPTOR pfd)358 protected static GLCapabilities pfd2GLCapabilities(PIXELFORMATDESCRIPTOR pfd) { 359 if ((pfd.dwFlags() & WGL.PFD_SUPPORT_OPENGL) == 0) { 360 return null; 361 } 362 GLCapabilities res = new GLCapabilities(); 363 res.setRedBits (pfd.cRedBits()); 364 res.setGreenBits (pfd.cGreenBits()); 365 res.setBlueBits (pfd.cBlueBits()); 366 res.setAlphaBits (pfd.cAlphaBits()); 367 res.setAccumRedBits (pfd.cAccumRedBits()); 368 res.setAccumGreenBits(pfd.cAccumGreenBits()); 369 res.setAccumBlueBits (pfd.cAccumBlueBits()); 370 res.setAccumAlphaBits(pfd.cAccumAlphaBits()); 371 res.setDepthBits (pfd.cDepthBits()); 372 res.setStencilBits (pfd.cStencilBits()); 373 res.setDoubleBuffered((pfd.dwFlags() & WGL.PFD_DOUBLEBUFFER) != 0); 374 res.setStereo ((pfd.dwFlags() & WGL.PFD_STEREO) != 0); 375 res.setHardwareAccelerated(((pfd.dwFlags() & WGL.PFD_GENERIC_FORMAT) == 0) || 376 ((pfd.dwFlags() & WGL.PFD_GENERIC_ACCELERATED) != 0)); 377 return res; 378 } 379 glCapabilities2iattributes(GLCapabilities capabilities, int[] iattributes, WGLExt wglExt, boolean pbuffer, int[] floatMode)380 protected static boolean glCapabilities2iattributes(GLCapabilities capabilities, 381 int[] iattributes, 382 WGLExt wglExt, 383 boolean pbuffer, 384 int[] floatMode) throws GLException { 385 if (!wglExt.isExtensionAvailable("WGL_ARB_pixel_format")) { 386 return false; 387 } 388 389 int niattribs = 0; 390 391 iattributes[niattribs++] = WGLExt.WGL_SUPPORT_OPENGL_ARB; 392 iattributes[niattribs++] = GL.GL_TRUE; 393 if (pbuffer) { 394 iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_PBUFFER_ARB; 395 iattributes[niattribs++] = GL.GL_TRUE; 396 } else { 397 iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_WINDOW_ARB; 398 iattributes[niattribs++] = GL.GL_TRUE; 399 } 400 401 iattributes[niattribs++] = WGLExt.WGL_DOUBLE_BUFFER_ARB; 402 if (capabilities.getDoubleBuffered()) { 403 iattributes[niattribs++] = GL.GL_TRUE; 404 } else { 405 iattributes[niattribs++] = GL.GL_FALSE; 406 } 407 408 iattributes[niattribs++] = WGLExt.WGL_STEREO_ARB; 409 if (capabilities.getStereo()) { 410 iattributes[niattribs++] = GL.GL_TRUE; 411 } else { 412 iattributes[niattribs++] = GL.GL_FALSE; 413 } 414 415 iattributes[niattribs++] = WGLExt.WGL_DEPTH_BITS_ARB; 416 iattributes[niattribs++] = capabilities.getDepthBits(); 417 iattributes[niattribs++] = WGLExt.WGL_RED_BITS_ARB; 418 iattributes[niattribs++] = capabilities.getRedBits(); 419 iattributes[niattribs++] = WGLExt.WGL_GREEN_BITS_ARB; 420 iattributes[niattribs++] = capabilities.getGreenBits(); 421 iattributes[niattribs++] = WGLExt.WGL_BLUE_BITS_ARB; 422 iattributes[niattribs++] = capabilities.getBlueBits(); 423 iattributes[niattribs++] = WGLExt.WGL_ALPHA_BITS_ARB; 424 iattributes[niattribs++] = capabilities.getAlphaBits(); 425 iattributes[niattribs++] = WGLExt.WGL_STENCIL_BITS_ARB; 426 iattributes[niattribs++] = capabilities.getStencilBits(); 427 if (capabilities.getAccumRedBits() > 0 || 428 capabilities.getAccumGreenBits() > 0 || 429 capabilities.getAccumBlueBits() > 0 || 430 capabilities.getAccumAlphaBits() > 0) { 431 iattributes[niattribs++] = WGLExt.WGL_ACCUM_BITS_ARB; 432 iattributes[niattribs++] = (capabilities.getAccumRedBits() + 433 capabilities.getAccumGreenBits() + 434 capabilities.getAccumBlueBits() + 435 capabilities.getAccumAlphaBits()); 436 iattributes[niattribs++] = WGLExt.WGL_ACCUM_RED_BITS_ARB; 437 iattributes[niattribs++] = capabilities.getAccumRedBits(); 438 iattributes[niattribs++] = WGLExt.WGL_ACCUM_GREEN_BITS_ARB; 439 iattributes[niattribs++] = capabilities.getAccumGreenBits(); 440 iattributes[niattribs++] = WGLExt.WGL_ACCUM_BLUE_BITS_ARB; 441 iattributes[niattribs++] = capabilities.getAccumBlueBits(); 442 iattributes[niattribs++] = WGLExt.WGL_ACCUM_ALPHA_BITS_ARB; 443 iattributes[niattribs++] = capabilities.getAccumAlphaBits(); 444 } 445 446 if (wglExt.isExtensionAvailable("WGL_ARB_multisample")) { 447 if (capabilities.getSampleBuffers()) { 448 iattributes[niattribs++] = WGLExt.WGL_SAMPLE_BUFFERS_ARB; 449 iattributes[niattribs++] = GL.GL_TRUE; 450 iattributes[niattribs++] = WGLExt.WGL_SAMPLES_ARB; 451 iattributes[niattribs++] = capabilities.getNumSamples(); 452 } 453 } 454 455 boolean rtt = capabilities.getPbufferRenderToTexture(); 456 boolean rect = capabilities.getPbufferRenderToTextureRectangle(); 457 boolean useFloat = capabilities.getPbufferFloatingPointBuffers(); 458 boolean ati = false; 459 if (pbuffer) { 460 // Check some invariants and set up some state 461 if (rect && !rtt) { 462 throw new GLException("Render-to-texture-rectangle requires render-to-texture to be specified"); 463 } 464 465 if (rect) { 466 if (!wglExt.isExtensionAvailable("GL_NV_texture_rectangle")) { 467 throw new GLException("Render-to-texture-rectangle requires GL_NV_texture_rectangle extension"); 468 } 469 } 470 471 if (useFloat) { 472 if (!wglExt.isExtensionAvailable("WGL_ATI_pixel_format_float") && 473 !wglExt.isExtensionAvailable("WGL_NV_float_buffer")) { 474 throw new GLException("Floating-point pbuffers not supported by this hardware"); 475 } 476 477 // Prefer NVidia extension over ATI 478 if (wglExt.isExtensionAvailable("WGL_NV_float_buffer")) { 479 ati = false; 480 floatMode[0] = GLPbuffer.NV_FLOAT; 481 } else { 482 ati = true; 483 floatMode[0] = GLPbuffer.ATI_FLOAT; 484 } 485 if (DEBUG) { 486 System.err.println("Using " + (ati ? "ATI" : "NVidia") + " floating-point extension"); 487 } 488 } 489 490 // See whether we need to change the pixel type to support ATI's 491 // floating-point pbuffers 492 if (useFloat && ati) { 493 if (rtt) { 494 throw new GLException("Render-to-floating-point-texture not supported on ATI hardware"); 495 } else { 496 iattributes[niattribs++] = WGLExt.WGL_PIXEL_TYPE_ARB; 497 iattributes[niattribs++] = WGLExt.WGL_TYPE_RGBA_FLOAT_ATI; 498 } 499 } else { 500 if (!rtt) { 501 // Currently we don't support non-truecolor visuals in the 502 // GLCapabilities, so we don't offer the option of making 503 // color-index pbuffers. 504 iattributes[niattribs++] = WGLExt.WGL_PIXEL_TYPE_ARB; 505 iattributes[niattribs++] = WGLExt.WGL_TYPE_RGBA_ARB; 506 } 507 } 508 509 if (useFloat && !ati) { 510 iattributes[niattribs++] = WGLExt.WGL_FLOAT_COMPONENTS_NV; 511 iattributes[niattribs++] = GL.GL_TRUE; 512 } 513 514 if (rtt) { 515 if (useFloat) { 516 assert(!ati); 517 if (!rect) { 518 throw new GLException("Render-to-floating-point-texture only supported on NVidia hardware with render-to-texture-rectangle"); 519 } 520 iattributes[niattribs++] = WGLExt.WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV; 521 iattributes[niattribs++] = GL.GL_TRUE; 522 } else { 523 iattributes[niattribs++] = rect ? WGLExt.WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV : WGLExt.WGL_BIND_TO_TEXTURE_RGB_ARB; 524 iattributes[niattribs++] = GL.GL_TRUE; 525 } 526 } 527 } else { 528 iattributes[niattribs++] = WGLExt.WGL_PIXEL_TYPE_ARB; 529 iattributes[niattribs++] = WGLExt.WGL_TYPE_RGBA_ARB; 530 } 531 532 return true; 533 } 534 iattributes2GLCapabilities(int[] iattribs, int niattribs, int[] iresults, boolean requireRenderToWindow)535 protected static GLCapabilities iattributes2GLCapabilities(int[] iattribs, 536 int niattribs, 537 int[] iresults, 538 boolean requireRenderToWindow) { 539 GLCapabilities res = new GLCapabilities(); 540 for (int i = 0; i < niattribs; i++) { 541 int attr = iattribs[i]; 542 switch (attr) { 543 case WGLExt.WGL_DRAW_TO_WINDOW_ARB: 544 if (requireRenderToWindow && iresults[i] != GL.GL_TRUE) 545 return null; 546 break; 547 548 case WGLExt.WGL_DRAW_TO_PBUFFER_ARB: 549 break; 550 551 case WGLExt.WGL_ACCELERATION_ARB: 552 res.setHardwareAccelerated(iresults[i] == WGLExt.WGL_FULL_ACCELERATION_ARB); 553 break; 554 555 case WGLExt.WGL_SUPPORT_OPENGL_ARB: 556 if (iresults[i] != GL.GL_TRUE) 557 return null; 558 break; 559 560 case WGLExt.WGL_DEPTH_BITS_ARB: 561 res.setDepthBits(iresults[i]); 562 break; 563 564 case WGLExt.WGL_STENCIL_BITS_ARB: 565 res.setStencilBits(iresults[i]); 566 break; 567 568 case WGLExt.WGL_DOUBLE_BUFFER_ARB: 569 res.setDoubleBuffered(iresults[i] == GL.GL_TRUE); 570 break; 571 572 case WGLExt.WGL_STEREO_ARB: 573 res.setStereo(iresults[i] == GL.GL_TRUE); 574 break; 575 576 case WGLExt.WGL_PIXEL_TYPE_ARB: 577 // Fail softly with unknown results here 578 if (iresults[i] == WGLExt.WGL_TYPE_RGBA_ARB || 579 iresults[i] == WGLExt.WGL_TYPE_RGBA_FLOAT_ATI) { 580 res.setPbufferFloatingPointBuffers(true); 581 } 582 break; 583 584 case WGLExt.WGL_FLOAT_COMPONENTS_NV: 585 if (iresults[i] != 0) { 586 res.setPbufferFloatingPointBuffers(true); 587 } 588 break; 589 590 case WGLExt.WGL_RED_BITS_ARB: 591 res.setRedBits(iresults[i]); 592 break; 593 594 case WGLExt.WGL_GREEN_BITS_ARB: 595 res.setGreenBits(iresults[i]); 596 break; 597 598 case WGLExt.WGL_BLUE_BITS_ARB: 599 res.setBlueBits(iresults[i]); 600 break; 601 602 case WGLExt.WGL_ALPHA_BITS_ARB: 603 res.setAlphaBits(iresults[i]); 604 break; 605 606 case WGLExt.WGL_ACCUM_RED_BITS_ARB: 607 res.setAccumRedBits(iresults[i]); 608 break; 609 610 case WGLExt.WGL_ACCUM_GREEN_BITS_ARB: 611 res.setAccumGreenBits(iresults[i]); 612 break; 613 614 case WGLExt.WGL_ACCUM_BLUE_BITS_ARB: 615 res.setAccumBlueBits(iresults[i]); 616 break; 617 618 case WGLExt.WGL_ACCUM_ALPHA_BITS_ARB: 619 res.setAccumAlphaBits(iresults[i]); 620 break; 621 622 case WGLExt.WGL_SAMPLE_BUFFERS_ARB: 623 res.setSampleBuffers(iresults[i] != 0); 624 break; 625 626 case WGLExt.WGL_SAMPLES_ARB: 627 res.setNumSamples(iresults[i]); 628 break; 629 630 default: 631 throw new GLException("Unknown pixel format attribute " + iattribs[i]); 632 } 633 } 634 return res; 635 } 636 getThreadName()637 protected static String getThreadName() { 638 return Thread.currentThread().getName(); 639 } 640 } 641