LWJGL Forum

Programming => OpenGL => Topic started by: CaseyB on September 16, 2005, 21:43:22

Title: OpenGL Support
Post by: CaseyB on September 16, 2005, 21:43:22
I am going to write a rendering engine with two back ends.  I want to check if the computers hardware for OpenGL support and if it exists load the OpenGL version, if not then load the Java2D version.  I have found many examples of how to check for certain extension, but I can't find how to check for hardware OpenGL support!  I am sure there's a way to do it, what am I overlooking?

Casey
Title: OpenGL Support
Post by: darkprophet on September 17, 2005, 13:08:54

if (GLContext.getCapabilities().GL11) {
initGL();
} else {
init2D();


DP
Title: OpenGL Support
Post by: CaseyB on September 18, 2005, 03:18:40
Awesome, Thank you!!
Title: OpenGL Support
Post by: CaseyB on September 19, 2005, 18:43:28
GL11 cannot be resolved or is not a field, it does give me a list of extensions that I can check for, but not a wholesale yay or nay.  Any other ideas?
Title: OpenGL Support
Post by: darkprophet on September 19, 2005, 22:00:59
mind slip, replace GL11 with OpenGL11

DP
Title: OpenGL Support
Post by: CaseyB on September 20, 2005, 03:44:42
I knew I had to be something simple I was overlooking!!  I'll give it a go tomorrow!  :wink:
Title: OpenGL Support
Post by: CaseyB on September 20, 2005, 14:07:01
When I do that it kills the JVM.  If I replace that condition with a simple true or false, it works fine, so it has to be that line!  Any ideas?  Here is the error log:

#
# An unexpected error has been detected by HotSpot Virtual Machine:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00a8d682, pid=2776, tid=3936
#
# Java VM: Java HotSpot(TM) Client VM (1.5.0_04-b05 mixed mode)
# Problematic frame:
# j  com.sensis.gdm.CanvasFactory.newInstance()Lcom/sensis/gdm/CanvasFactory;+32
#

---------------  T H R E A D  ---------------

Current thread (0x00355ea0):  JavaThread "main" [_thread_in_Java, id=3936]

siginfo: ExceptionCode=0xc0000005, reading address 0x00001792

Registers:
EAX=0x00000000, EBX=0x00001792, ECX=0x00000000, EDX=0x00000014
ESP=0x0006fa34, EBP=0x0006fa50, ESI=0x27224518, EDI=0x0006fa64
EIP=0x00a8d682, EFLAGS=0x00010246

Top of Stack: (sp=0x0006fa34)
0x0006fa34:   0006fa34 27224518 0006fa64 27224a28
0x0006fa44:   00000000 272245d0 0006fa68 0006fa84
0x0006fa54:   00a829fa 00000000 00000000 00000000
0x0006fa64:   02a9edc0 0006fa68 26fce6d6 0006fa94
0x0006fa74:   27003ad8 00000000 26fce730 0006fa94
0x0006fa84:   0006fab8 00a82923 00000000 02b2b080
0x0006fa94:   02acc280 02acc280 0006fa9c 26fce5ec
0x0006faa4:   0006fac4 27003ad8 00000000 26fce638

Instructions: (pc=0x00a8d682)
0x00a8d672:   44 91 1c 59 c1 e8 1c 83 e0 0f 0f 85 0a 00 00 00
0x00a8d682:   0f be 04 19 50 e9 a4 00 00 00 83 f8 03 0f 85 09


Stack: [0x00030000,0x00070000),  sp=0x0006fa34,  free space=254k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
j  com.sensis.gdm.CanvasFactory.newInstance()Lcom/sensis/gdm/CanvasFactory;+32
j  test.FactoryTest.<init>()V+22
j  test.FactoryTest.main([Ljava/lang/String;)V+4
v  ~StubRoutines::call_stub
V  [jvm.dll+0x82696]
V  [jvm.dll+0xd6fd9]
V  [jvm.dll+0x82567]
V  [jvm.dll+0x895e6]
C  [javaw.exe+0x14c0]
C  [javaw.exe+0x313d]
C  [kernel32.dll+0x16d4f]


---------------  P R O C E S S  ---------------

Java Threads: ( => current thread )
 0x2b289a00 JavaThread "AWT-Windows" daemon [_thread_in_native, id=3400]
 0x2b2895d0 JavaThread "AWT-Shutdown" [_thread_blocked, id=3496]
 0x2b283d30 JavaThread "Java2D Disposer" daemon [_thread_blocked, id=3940]
 0x00a41950 JavaThread "Low Memory Detector" daemon [_thread_blocked, id=1796]
 0x00a40528 JavaThread "CompilerThread0" daemon [_thread_blocked, id=180]
 0x00a3f8b0 JavaThread "Signal Dispatcher" daemon [_thread_blocked, id=3476]
 0x00a36b58 JavaThread "Finalizer" daemon [_thread_blocked, id=3644]
 0x009e9b30 JavaThread "Reference Handler" daemon [_thread_blocked, id=3216]
=>0x00355ea0 JavaThread "main" [_thread_in_Java, id=3936]

Other Threads:
 0x00a32bb0 VMThread [id=3032]
 0x00a42b28 WatcherThread [id=3888]

VM state:not at safepoint (normal execution)

VM Mutex/Monitor currently owned by a thread: None

Heap
def new generation   total 41088K, used 2200K [0x02a80000, 0x05710000, 0x05710000)
 eden space 36544K,   6% used [0x02a80000, 0x02ca6310, 0x04e30000)
 from space 4544K,   0% used [0x04e30000, 0x04e30000, 0x052a0000)
 to   space 4544K,   0% used [0x052a0000, 0x052a0000, 0x05710000)
tenured generation   total 548288K, used 0K [0x05710000, 0x26e80000, 0x26e80000)
  the space 548288K,   0% used [0x05710000, 0x05710000, 0x05710200, 0x26e80000)
compacting perm gen  total 8192K, used 4177K [0x26e80000, 0x27680000, 0x2ae80000)
  the space 8192K,  50% used [0x26e80000, 0x27294558, 0x27294600, 0x27680000)
No shared spaces configured.

Dynamic libraries:
0x00400000 - 0x0040c000 C:\Program Files\Java\jre1.5.0_04\bin\javaw.exe
0x7c900000 - 0x7c9b0000 C:\WINDOWS\system32\ntdll.dll
0x7c800000 - 0x7c8f4000 C:\WINDOWS\system32\kernel32.dll
0x77dd0000 - 0x77e6b000 C:\WINDOWS\system32\ADVAPI32.dll
0x77e70000 - 0x77f01000 C:\WINDOWS\system32\RPCRT4.dll
0x77d40000 - 0x77dd0000 C:\WINDOWS\system32\USER32.dll
0x77f10000 - 0x77f56000 C:\WINDOWS\system32\GDI32.dll
0x77c10000 - 0x77c68000 C:\WINDOWS\system32\MSVCRT.dll
0x6d640000 - 0x6d7c9000 C:\Program Files\Java\jre1.5.0_04\bin\client\jvm.dll
0x76b40000 - 0x76b6d000 C:\WINDOWS\system32\WINMM.dll
0x6d280000 - 0x6d288000 C:\Program Files\Java\jre1.5.0_04\bin\hpi.dll
0x76bf0000 - 0x76bfb000 C:\WINDOWS\system32\PSAPI.DLL
0x6d610000 - 0x6d61c000 C:\Program Files\Java\jre1.5.0_04\bin\verify.dll
0x6d300000 - 0x6d31d000 C:\Program Files\Java\jre1.5.0_04\bin\java.dll
0x6d630000 - 0x6d63f000 C:\Program Files\Java\jre1.5.0_04\bin\zip.dll
0x6d000000 - 0x6d167000 C:\Program Files\Java\jre1.5.0_04\bin\awt.dll
0x73000000 - 0x73026000 C:\WINDOWS\system32\WINSPOOL.DRV
0x76390000 - 0x763ad000 C:\WINDOWS\system32\IMM32.dll
0x774e0000 - 0x7761d000 C:\WINDOWS\system32\ole32.dll
0x73760000 - 0x737a9000 C:\WINDOWS\system32\ddraw.dll
0x73bc0000 - 0x73bc6000 C:\WINDOWS\system32\DCIMAN32.dll
0x73940000 - 0x73a10000 C:\WINDOWS\system32\D3DIM700.DLL
0x6d240000 - 0x6d27d000 C:\Program Files\Java\jre1.5.0_04\bin\fontmanager.dll
0x74720000 - 0x7476b000 C:\WINDOWS\system32\MSCTF.dll
0x7c9c0000 - 0x7d1d4000 C:\WINDOWS\system32\shell32.dll
0x77f60000 - 0x77fd6000 C:\WINDOWS\system32\SHLWAPI.dll
0x773d0000 - 0x774d2000 C:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.2600.2180_x-ww_a84f1ff9\comctl32.dll
0x5d090000 - 0x5d127000 C:\WINDOWS\system32\comctl32.dll
0x2b570000 - 0x2b5b1000 C:\WINDOWS\SYSTEM32\lwjgl.dll
0x72280000 - 0x722aa000 C:\WINDOWS\system32\DINPUT.dll
0x5ed00000 - 0x5edcc000 C:\WINDOWS\system32\OPENGL32.dll
0x68b20000 - 0x68b40000 C:\WINDOWS\system32\GLU32.dll
0x77c00000 - 0x77c08000 C:\WINDOWS\system32\VERSION.dll

VM Arguments:
jvm_args: -Xms580m -Xmx580m
java_command: test.FactoryTest

Environment Variables:
PATH=C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;c:\matlab6p5p1\bin\win32;C:\Program Files\Common Files\Autodesk Shared\
USERNAME=cborders
OS=Windows_NT
PROCESSOR_IDENTIFIER=x86 Family 15 Model 4 Stepping 1, GenuineIntel



---------------  S Y S T E M  ---------------

OS: Windows XP Build 2600 Service Pack 2

CPU:total 1 family 15, cmov, cx8, fxsr, mmx, sse, sse2, ht

Memory: 4k page, physical 1038408k(508088k free), swap 1712236k(664764k free)

vm_info: Java HotSpot(TM) Client VM (1.5.0_04-b05) for windows-x86, built on Jun  3 2005 02:10:41 by "java_re" with MS VC++ 6.0
[/code]
Title: OpenGL Support
Post by: elias on September 21, 2005, 06:08:34
Heh. The problem here is that GLContext.getCapabilities() is null, since it is only initialized when a context is active. The right way to check for OpenGL is to create the Display or a Pbuffer.

However, even a null ContextCapabilities reference should not result in a native crash, so I investigated further and it seems that CaseyB has run into a JVM bug! To verify that it really is a JVM bug, I've created a somewhat minimal test case that can be found here:

http://odense.kollegienet.dk/~naur/JVMCrash.zip

it contains a stand alone cut down version of ContextCapabilities and a JVMCrash.java that looks like this:


public class JVMCrash {
   public static void main(String[] args) {
       ContextCapabilities f = null;
System.out.println("f = " + f + " | f.OpenGL11 = " + f.OpenGL11);
   }
}


The test contains no native code, so it is proof that this is a JVM bug. The bug seems to be caused by large classes, since deleting fields from the ContextCapabilities class will make the native crash disappear and result in the expected NullPointerException.

I'll post a bug to sun.

- elias
Title: OpenGL Support
Post by: princec on September 21, 2005, 15:02:52
This bug is probably caused by us exceeding the 64kb limit on class file size. ContextCapabilities is 90-odd kb. I should think that it's not checked properly on local class loads (ie. the verifier is not turned on) and this might lead to some unexpected behaviour.

Cas :)
Title: OpenGL Support
Post by: CaseyB on September 21, 2005, 15:47:58
I downloaded the newest snapshot of 6.0 and it's broken there too!  If it is a class size restriction issue is there a way around it??

-=EDIT=-
I googled "LWJGL Pbuffer" and found some very useful code by gregorypierce that lets me check for the support I need!!  Thank you guys!
Title: OpenGL Support
Post by: elias on September 21, 2005, 16:52:13
Don't use the getCapabilities check. The correct way to check for OpenGL support is to try to create a Display or a Pbuffer.

- elias
Title: OpenGL Support
Post by: CaseyB on September 21, 2005, 16:59:41
so it would be:
Pbuffer pbuffer = new Pbuffer(1, 1, new PixelFormat(), null, null);
if(pbuffer != null)
{
    // OpenGL
}
else
{
   // Java2D
}


You see the trouble that I'm having is that I don't have an OpenGL-less computer to test this on, so I don't know if it will simply not create the pbuffer or if it will crash most egregiously!
Title: OpenGL Support
Post by: princec on September 21, 2005, 17:11:36
Further investigation reveals that the class size itself is not the issue but the size of some part of the class file; in this case I think we're using more than 64kb for the constant pool because of all those variables.

Cas :)
Title: OpenGL Support
Post by: elias on September 21, 2005, 17:28:12
If it crashes, it's a lwjgl bug and you should report it :). But why not simply create the Display right away, and if it fails, fall back to Java2D? It seems wasteful to create a Pbuffer just the check if the Display can be created (assuming you want to display something, not just do offline rendering).

Besides, Pbuffer creation can fail where Display creation succeeds. For example when the OpenGL drivers doesn't support Pbuffers. However, if you keep the Pbuffer check, remember to destroy it again.

- elias
Title: OpenGL Support
Post by: CaseyB on September 21, 2005, 18:07:41
I am using an AWTGLCanvas as part of a larger app, so I am writing classes that extend java.awt.Canvas and AWTGLCanvas and loading the correct one depending on the results of the test!
Title: OpenGL Support
Post by: elias on September 21, 2005, 18:17:36
Test by creating the AWTGLCanvas then?

- elias
Title: OpenGL Support
Post by: CaseyB on September 22, 2005, 21:41:24
Ok, I found an old P2 350MHz that has an integrated video card with no OpenGL support!  I tried loading the OpenGL version of my class that used the AWTGLCanvas and it loaded without an error, but it puked on the first paint!  So I went back to using the Pbuffer.  What happened there was that when it tried to create the Pbuffer it would throw and exception so I just caught that and used that to decide to load the Java2D version.  Here is my code for that part:
try
{
    System.out.println("Trying OpenGL");
    try
    {
         Pbuffer buff = new Pbuffer(1, 1, new PixelFormat(), null, null);

         if (classLoader == null)
         {
              theClass = Class.forName(openGL);
         }
         else
         {
              theClass = classLoader.loadClass(openGL);
         }
         System.out.println("OpenGL Succeeded");
         buff.destroy();
    }
    catch(ExceptionInInitializerError eiie)
    {
         System.out.println("OpenGL Failed\nTrying Java2D");
         if (classLoader == null)
         {
              theClass = Class.forName(java2D);
         }
         else
         {
              theClass = classLoader.loadClass(java2D);
         }
         System.out.println("Java2D Succeeded");
    }
}
catch (ClassNotFoundException cnfe)
{
    throw cnfe;
}
Title: OpenGL Support
Post by: Whackjack on October 21, 2005, 17:50:55
It seems to me that by doing it this way (trying to create a Display or PBuffer), you're still missing out on what capabilities are available.  For instance, what if I want to use GL15 instead of GL11?  Is this something that has been bugged for LWJGL or are we just out of luck?
Title: OpenGL Support
Post by: CaseyB on October 21, 2005, 19:09:58
Once you create an OpenGL context you should be able to test for an OpenGL 1.5 feature and decide based on that.
Title: OpenGL Support
Post by: Whackjack on October 21, 2005, 19:33:16
*Confused* I thought it was just decided that the getCapabilities() method causes a JVM crash?  Or is there another method that I'm missing?

Oh... are you saying that I should create the Display first, and then call getCapabilities() on the newly created GLContext?  Perhaps I misinterpreted what the original problem was...
Title: OpenGL Support
Post by: CaseyB on October 21, 2005, 20:32:16
Quote from: "Whackjack"are you saying that I should create the Display first, and then call getCapabilities() on the newly created GLContext?

Exactly!  The problem that I was having was that I couldn't be sure that the client machine had an OpenGL capable graphics card so I just wanted to test for OpenGL 1.1 compatability.  In order to do the getCapabilities() test you need an existing OpenGL context.  So you should perform the check on an existing Display... unless I have totally gone off my rocker! :)
Title: OpenGL Support
Post by: Whackjack on October 21, 2005, 21:15:04
Thanks, CaseyB... That does make sense, even if it's a little backwards.  I guess I was thinking along the lines you were in that you could test for OpenGL compatibility before trying to create anything.
I'll keep this in my mind for future reference.  Thanks again!
Title: OpenGL Support
Post by: darkprophet on December 06, 2005, 22:44:57
The bug in the JVM has been resolved in Mustang b62:

Quote
   6342951   Implicit null checks on large objects cause JVM crash

That was quick, I expected a 3 year wait atleast!  :roll:
Edit: 1.5.0_7 seems to have the update too...everybody update!
DP
Title: OpenGL Support
Post by: elias on December 07, 2005, 08:24:25
Quote from: "darkprophet"The bug in the JVM has been resolved in Mustang b62:

Quote
   6342951   Implicit null checks on large objects cause JVM crash

That was quick, I expected a 3 year wait atleast!  :roll:
Edit: 1.5.0_7 seems to have the update too...everybody update!
DP

Nah, anything else than ASAP would have been strange, since this bug is a sure way to issue DOS attacks on a running (shared) JVM.

- elias