Question about Al.create(*) method.

Started by ksabo_lwjgl, May 16, 2007, 07:26:02

Previous topic - Next topic

ksabo_lwjgl

I'm just curious as to why the method (in org.lwjgl.openal.AL):
static void create(String deviceArguments, int contextFrequency, int contextRefresh, boolean contextSynchronized, boolean openDevice)
}

is not public.

I for one don't want the default device opened for me.

Doing the following fails:
AL.create();
ALCcontext alcContext = alcGetCurrentContext();
ALCdevice alcDevice = alcGetContextsDevice(alcContext);
alcMakeContextCurrent(null);
alcDestroyContext(alcContext);
alcCloseDevice(alcDevice);

and then later on calling
alcIsExtensionPresent(null, "ALC_ENUMERATION_EXT")


This causes a problem because ALC10.getDevice() doesnt allow null.
public static boolean alcIsExtensionPresent(ALCdevice device, String extName) {
	boolean result = nalcIsExtensionPresent(getDevice(device), extName);
	Util.checkALCError();
	return result;
}
static long getDevice(ALCdevice device) {
	if(device != null) {
		return device.device;
	}
	return 0L;
}

I'm trying to port over some C++ code and things just seem a little odd.

All in all it doesn't seem to matter if you call alcOpenDevice("blah"); multiple times as my existing code doesn't seem to be affected by the device already being opened by AL.create(). I'm just a little curious as to why this approach was taken. I guess I was just expecting something along the lines of AL.loadNativeCode() and then I would deal w/ all the al stuff.

I'm also curious as to why the destroy method does not call alcMakeContextCurrent(null);. According to the docs "alcMakeContextCurrent should be used to make sure the
context to be destroyed is not current (NULL is valid for alcMakeContextCurrent).".

Thanks for the help,

Karl

Matzon

Are you using LWJGL 1.0?

The latest 1.1 exposes context and device, allowing the following test:
import org.lwjgl.LWJGLException;
import org.lwjgl.openal.AL;
import org.lwjgl.openal.ALC10;
import org.lwjgl.openal.ALCcontext;
import org.lwjgl.openal.ALCdevice;


public class ForumTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		try {
			System.out.println("Creating AL");
			AL.create();
			
			ALCcontext alcContext = ALC10.alcGetCurrentContext();
			ALCdevice alcDevice = ALC10.alcGetContextsDevice(alcContext);
			
			System.out.println("Context: " + alcContext + ", Device: " + alcDevice);			
			ALC10.alcMakeContextCurrent(null);
			
			System.out.println("nuked context: " + ALC10.alcGetCurrentContext());
			
			ALC10.alcDestroyContext(alcContext);
			ALC10.alcCloseDevice(alcDevice);
		} catch (LWJGLException le) {
			le.printStackTrace();
		}

		System.out.println("ALC_ENUMERATION_EXT: " + ALC10.alcIsExtensionPresent(null, "ALC_ENUMERATION_EXT"));
		AL.destroy();
	}
}


to give this result:
Creating AL
QuoteContext: org.lwjgl.openal.ALCcontext@156ee8e, Device: org.lwjgl.openal.ALCdevice@47b480
nuked context: null
ALC_ENUMERATION_EXT: true

However, doing the ALC10.alcMakeContextCurrent(null); as is recommended causes a VM crash, so this is something which I will investigate...

Currently there is no way to only load the native code without creating a default context and device. I am not sure I see any benefits in doing a whole lot of work to allow this, since you can just nuke the context and device after the default one has been created?

ksabo_lwjgl

I agree you can easily nuke the current context. But that causes the problem I pointed out earlier. If you nuke the context and then call:
alcIsExtensionPresent(null, "ALC_ENUMERATION_EXT")


The JVM crashes... hmmm I'm going to have to look into this more. I miss read the getDevice code...


**Edited**

Matzon

the problem seems to be that the following two lines:
ALCcontext alcContext = ALC10.alcGetCurrentContext();
			ALCdevice alcDevice = ALC10.alcGetContextsDevice(alcContext);

grabs the same device and context that AL uses internally - so when destroy is called on AL it will fail.
Adding this code to ALC10:
// nuke internal copy if same address
		if(context.context == AL.context.context) {
			AL.context = null;
		}
- and similar for device, will keep AL happy - and you can do what you want without any issues - except for the forced creation of the initial device and context.
I am not sure if this is a particularly nice way to handle it tho, so not comitted yet.

ksabo_lwjgl

The code:
AL.create();
ALCcontext alcContext = alcGetCurrentContext();
ALCdevice alcDevice = alcGetContextsDevice(alcContext);
alcMakeContextCurrent(null);
alcDestroyContext(alcContext);
alcCloseDevice(alcDevice);
System.out.println("HERE1");
System.out.flush();
alcIsExtensionPresent(null, "ALC_ENUMERATION_EXT");
System.out.println("HERE2");
System.out.flush();


The jvm dump:
#
# An unexpected error has been detected by Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x0c03f6f0, pid=2524, tid=2536
#
# Java VM: Java HotSpot(TM) Client VM (1.6.0-b105 mixed mode)
# Problematic frame:
# C  0x0c03f6f0
#
# If you would like to submit a bug report, please visit:
#   http://java.sun.com/webapps/bugreport/crash.jsp
#

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

Current thread (0x00386400):  JavaThread "main" [_thread_in_native, id=2536]

siginfo: ExceptionCode=0xc0000005, reading address 0x0c03f6f0

Registers:
EAX=0x0c250020, EBX=0x06d448b8, ECX=0x0c03f6f0, EDX=0x0be02168
ESP=0x003ef488, EBP=0x003ef4dc, ESI=0x0be02168, EDI=0x00386400
EIP=0x0c03f6f0, EFLAGS=0x00210202

Top of Stack: (sp=0x003ef488)
0x003ef488:   0bdd4e00 0c250020 06d448b8 100052ab
0x003ef498:   0be02168 008ea460 003864e8 003ef4e4
0x003ef4a8:   0be02168 00000000 003ef49c 0bdc24c0
0x003ef4b8:   003ef678 003ef4bc 00000000 003ef4f0
0x003ef4c8:   06d44ed0 00000000 06d448b8 00000000
0x003ef4d8:   003ef4ec 003ef514 008e2d95 06d44e70
0x003ef4e8:   008e8419 0be02168 00000000 003ef4f4
0x003ef4f8:   06d4481c 003ef51c 06d44ed0 00000000 

Instructions: (pc=0x0c03f6f0)
0x0c03f6e0:   
[error occurred during error reporting, step 100, id 0xc0000005]

Stack: [0x003a0000,0x003f0000),  sp=0x003ef488,  free space=317k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C  0x0c03f6f0
j  org.lwjgl.openal.ALC10.alcGetError(Lorg/lwjgl/openal/ALCdevice;)I+4
j  org.lwjgl.openal.Util.checkALCError()V+3
j  org.lwjgl.openal.ALC10.alcIsExtensionPresent(Lorg/lwjgl/openal/ALCdevice;Ljava/lang/String;)Z+9
j  duath.jaudio.AudioTest.setUp()V+43
v  ~StubRoutines::call_stub

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j  org.lwjgl.openal.ALC10.nalcGetError(J)I+0
j  org.lwjgl.openal.ALC10.alcGetError(Lorg/lwjgl/openal/ALCdevice;)I+4
j  org.lwjgl.openal.Util.checkALCError()V+3
j  org.lwjgl.openal.ALC10.alcIsExtensionPresent(Lorg/lwjgl/openal/ALCdevice;Ljava/lang/String;)Z+9
j  duath.jaudio.AudioTest.setUp()V+43
v  ~StubRoutines::call_stub
j  sun.reflect.NativeMethodAccessorImpl.invoke0(Ljava/lang/reflect/Method;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+0
j  sun.reflect.NativeMethodAccessorImpl.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+87
j  sun.reflect.DelegatingMethodAccessorImpl.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+6
j  java.lang.reflect.Method.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+161
j  org.junit.internal.runners.BeforeAndAfterRunner.invokeMethod(Ljava/lang/reflect/Method;)V+9
j  org.junit.internal.runners.BeforeAndAfterRunner.runBefores()V+40
j  org.junit.internal.runners.BeforeAndAfterRunner.runProtected()V+1
j  org.junit.internal.runners.TestMethodRunner.runMethod()V+1
j  org.junit.internal.runners.TestMethodRunner.run()V+64
j  org.junit.internal.runners.TestClassMethodsRunner.invokeTestMethod(Ljava/lang/reflect/Method;Lorg/junit/runner/notification/RunNotifier;)V+28
j  org.junit.internal.runners.TestClassMethodsRunner.run(Lorg/junit/runner/notification/RunNotifier;)V+53
j  org.junit.internal.runners.TestClassRunner$1.runUnprotected()V+11
j  org.junit.internal.runners.BeforeAndAfterRunner.runProtected()V+5
j  org.junit.internal.runners.TestClassRunner.run(Lorg/junit/runner/notification/RunNotifier;)V+22
j  org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(Lorg/eclipse/jdt/internal/junit/runner/TestExecution;)V+41
j  org.eclipse.jdt.internal.junit.runner.TestExecution.run([Lorg/eclipse/jdt/internal/junit/runner/ITestReference;)V+17
j  org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests([Ljava/lang/String;Ljava/lang/String;Lorg/eclipse/jdt/internal/junit/runner/TestExecution;)V+61
j  org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(Lorg/eclipse/jdt/internal/junit/runner/TestExecution;)V+10
j  org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run()V+70
j  org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main([Ljava/lang/String;)V+14
v  ~StubRoutines::call_stub

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

Java Threads: ( => current thread )
  0x0aaea800 JavaThread "ReaderThread" [_thread_in_native, id=556]
  0x0aa8d000 JavaThread "Low Memory Detector" daemon [_thread_blocked, id=516]
  0x0aa8bc00 JavaThread "CompilerThread0" daemon [_thread_blocked, id=548]
  0x0aa87400 JavaThread "Attach Listener" daemon [_thread_blocked, id=1332]
  0x0aa86400 JavaThread "Signal Dispatcher" daemon [_thread_blocked, id=496]
  0x0aa73800 JavaThread "Finalizer" daemon [_thread_blocked, id=964]
  0x0aa72800 JavaThread "Reference Handler" daemon [_thread_blocked, id=2512]
=>0x00386400 JavaThread "main" [_thread_in_native, id=2536]

Other Threads:
  0x0aa6f800 VMThread [id=2516]
  0x0aa8e800 WatcherThread [id=552]

VM state:not at safepoint (normal execution)

VM Mutex/Monitor currently owned by a thread: None

Heap
 def new generation   total 960K, used 243K [0x02960000, 0x02a60000, 0x02e40000)
  eden space 896K,  22% used [0x02960000, 0x02991658, 0x02a40000)
  from space 64K,  71% used [0x02a50000, 0x02a5b7c0, 0x02a60000)
  to   space 64K,   0% used [0x02a40000, 0x02a40000, 0x02a50000)
 tenured generation   total 4096K, used 512K [0x02e40000, 0x03240000, 0x06960000)
   the space 4096K,  12% used [0x02e40000, 0x02ec0200, 0x02ec0200, 0x03240000)
 compacting perm gen  total 12288K, used 4031K [0x06960000, 0x07560000, 0x0a960000)
   the space 12288K,  32% used [0x06960000, 0x06d4fd60, 0x06d4fe00, 0x07560000)
No shared spaces configured.

Dynamic libraries:
0x00400000 - 0x00423000 	C:\Program Files\Java\jdk1.6.0\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
0x7e410000 - 0x7e4a0000 	C:\WINDOWS\system32\USER32.dll
0x77f10000 - 0x77f57000 	C:\WINDOWS\system32\GDI32.dll
0x7c340000 - 0x7c396000 	C:\Program Files\Java\jdk1.6.0\jre\bin\msvcr71.dll
0x6d7c0000 - 0x6da07000 	C:\Program Files\Java\jdk1.6.0\jre\bin\client\jvm.dll
0x76b40000 - 0x76b6d000 	C:\WINDOWS\system32\WINMM.dll
0x6d310000 - 0x6d318000 	C:\Program Files\Java\jdk1.6.0\jre\bin\hpi.dll
0x76bf0000 - 0x76bfb000 	C:\WINDOWS\system32\PSAPI.DLL
0x6d770000 - 0x6d77c000 	C:\Program Files\Java\jdk1.6.0\jre\bin\verify.dll
0x6d3b0000 - 0x6d3cf000 	C:\Program Files\Java\jdk1.6.0\jre\bin\java.dll
0x6d7b0000 - 0x6d7bf000 	C:\Program Files\Java\jdk1.6.0\jre\bin\zip.dll
0x6d570000 - 0x6d583000 	C:\Program Files\Java\jdk1.6.0\jre\bin\net.dll
0x71ab0000 - 0x71ac7000 	C:\WINDOWS\system32\WS2_32.dll
0x77c10000 - 0x77c68000 	C:\WINDOWS\system32\msvcrt.dll
0x71aa0000 - 0x71aa8000 	C:\WINDOWS\system32\WS2HELP.dll
0x71a50000 - 0x71a8f000 	C:\WINDOWS\system32\mswsock.dll
0x662b0000 - 0x66308000 	C:\WINDOWS\system32\hnetcfg.dll
0x71a90000 - 0x71a98000 	C:\WINDOWS\System32\wshtcpip.dll
0x10000000 - 0x1004c000 	C:\downloaded\lwjgl\1.1\lwjgl-1.1\native\win32\lwjgl.dll
0x72280000 - 0x722aa000 	C:\WINDOWS\system32\DINPUT.dll
0x774e0000 - 0x7761d000 	C:\WINDOWS\system32\ole32.dll
0x5ed00000 - 0x5edcc000 	C:\WINDOWS\system32\OPENGL32.dll
0x68b20000 - 0x68b40000 	C:\WINDOWS\system32\GLU32.dll
0x73760000 - 0x737a9000 	C:\WINDOWS\system32\DDRAW.dll
0x73bc0000 - 0x73bc6000 	C:\WINDOWS\system32\DCIMAN32.dll
0x77c00000 - 0x77c08000 	C:\WINDOWS\system32\VERSION.dll
0x0bdd0000 - 0x0bdee000 	C:\WINDOWS\system32\OpenAL32.dll
0x76c30000 - 0x76c5e000 	C:\WINDOWS\system32\WINTRUST.dll
0x77a80000 - 0x77b14000 	C:\WINDOWS\system32\CRYPT32.dll
0x77b20000 - 0x77b32000 	C:\WINDOWS\system32\MSASN1.dll
0x76c90000 - 0x76cb8000 	C:\WINDOWS\system32\IMAGEHLP.dll
0x72d20000 - 0x72d29000 	C:\WINDOWS\system32\wdmaud.drv
0x72d10000 - 0x72d18000 	C:\WINDOWS\system32\msacm32.drv
0x77be0000 - 0x77bf5000 	C:\WINDOWS\system32\MSACM32.dll
0x77bd0000 - 0x77bd7000 	C:\WINDOWS\system32\midimap.dll
0x5ad70000 - 0x5ada8000 	C:\WINDOWS\system32\uxtheme.dll
0x76fd0000 - 0x7704f000 	C:\WINDOWS\system32\CLBCATQ.DLL
0x77050000 - 0x77115000 	C:\WINDOWS\system32\COMRes.dll
0x77120000 - 0x771ac000 	C:\WINDOWS\system32\OLEAUT32.dll
0x73f10000 - 0x73f6c000 	C:\WINDOWS\system32\dsound.dll
0x73ee0000 - 0x73ee4000 	C:\WINDOWS\system32\KsUser.dll

VM Arguments:
jvm_args: -Djava.library.path=C:\WINDOWS\system32;C:\downloaded\lwjgl\1.1\lwjgl-1.1\native\win32;C:\downloaded\lwjgl\1.1\lwjgl_optional-1.1\native\win32
java_command: org.eclipse.jdt.internal.junit.runner.RemoteTestRunner -version 3 -port 1101 -testLoaderClass org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader -loaderpluginname org.eclipse.jdt.junit4.runtime -classNames duath.jaudio.AudioTest
Launcher Type: SUN_STANDARD

Environment Variables:
JAVA_HOME=C:\Program Files\Java\jdk1.6.0
PATH=C:\Program Files\Java\jdk1.6.0\bin\..\jre\bin\client;C:\Program Files\Java\jdk1.6.0\bin\..\jre\bin;C:\MinGW\bin;C:\cygwin\bin;C:\msys\bin;C:\Program Files\Java\jdk1.6.0\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\Program Files\QuickTime\QTSystem\
USERNAME=ksabo
OS=Windows_NT
PROCESSOR_IDENTIFIER=x86 Family 6 Model 15 Stepping 6, GenuineIntel



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

OS: Windows XP Build 2600 Service Pack 2

CPU:total 2 family 6, cmov, cx8, fxsr, mmx, sse, sse2

Memory: 4k page, physical 2095148k(1472584k free), swap 1940804k(1321868k free)

vm_info: Java HotSpot(TM) Client VM (1.6.0-b105) for windows-x86, built on Nov 29 2006 00:48:48 by "java_re" with unknown MS VC++:1310

ksabo_lwjgl

ah ok it makes sense again  :P

the check error grabs the device that it assumes was created and left alone in AL

public static void checkALCError() {
		int err = ALC10.alcGetError(AL.getDevice());
		if (err != ALC10.ALC_NO_ERROR)
			throw new OpenALException(ALC10.alcGetString(AL.getDevice(), err));
	}


Hmm now I wonder what will happen if I change the device to one other than what LWJGL is using.  I would guess I wouldn't get my error codes since I would be working w/ a different device... (that is unless I check getError myself).

ksabo_lwjgl

I think org.lwjgl.openal.Util.checkALCError() should take a device as a parameter.  I think that would solve my current issue and possible be more correct for LWJGL since according to eclipse all methods in LWJGL which call org.lwjgl.openal.Util.checkALCError() have a device pointer:

org.lwjgl.openal.ALC10.alcCreateContext(ALCdevice, IntBuffer)
org.lwjgl.openal.ALC10.alcGetEnumValue(ALCdevice, String)
org.lwjgl.openal.ALC10.alcGetInteger(ALCdevice, int, IntBuffer)
org.lwjgl.openal.ALC10.alcGetString(ALCdevice, int)
org.lwjgl.openal.ALC10.alcIsExtensionPresent(ALCdevice, String)

Matzon

Going through the newly exposed context and device stuff there are a number of issue related to this.
An updated version will track created devices and contexts to remove any VM crashes by passing already invalidated contexts and devices. Furthermore checkALCError will be expanded to include the relevant device.
Working on it right now...