Need Best Practice for way to stably instantiate JME Canvas

We could use some recommendations for a way to stably instantiate the JME Canvas within a custom NetBeans application that will work across multiple platforms. We have succesfully instantiated the Canvas (and other JME operations) based on TestCanvas.java and TestSafeCanvas. Each trial implementation worked on some platforms but generated errors on others. Since the beta version of the jME3 SDK runs stably on ALL of our platforms (Windows XP, Windows 7, Linux and Mac - each with different hardware) we are hopeful that using the SDK as a template will stabilize our app across platforms.

We have embedded only 3 changes: add SceneViewerTopComponent, SceneApplication and edited the module’s Installer.java to start SceneApplication. This works on Windows 7 only (see log 3) and not on the others (see log 2). What are we missing?

Three logs are included below. The first two are from the same Windows XP/32-bit laptop with the latest video drivers from the vendor (Test apps work on this machine). The first log shows successful start-up of SDK. The second log shows the errors during start-up of our app when SceneApplication is started from the Installer. The third log shows the successful start-up of our app on a different machine with a newer graphics card.



First log (shows JME SDK runs on machine) ==================================

Running on jMonkeyEngine 3.0.0 Beta

Extraction Directory: C:Documents and SettingsusernameApplication Data.jmonkeyplatform3.0beta

Using LWJGL 2.8.1

Offscreen buffer created.

Adapter: smsmdd

Driver Version: 4.0.6163.1000

Vendor: Intel

OpenGL Version: 2.1.0 - Build 6.14.10.5355

Renderer: Mobile Intel® 4 Series Express Chipset Family

GLSL Ver: 1.20 - Intel Build 6.14.10.5355

Timer resolution: 1,000 ticks per second

Caps: [FrameBuffer, FrameBufferMRT, OpenGL20, OpenGL21, ARBprogram, GLSL100, GLSL110, GLSL120, VertexTextureFetch, FloatTexture, FloatColorBuffer, FloatDepthBuffer, PackedFloatTexture, SharedExponentTexture, PackedFloatColorBuffer, NonPowerOfTwoTextures, MeshInstancing, VertexBufferArray]

DesktopAssetManager created.

Camera created (W: 640, H: 480)

Camera created (W: 640, H: 480)

AudioRenderer supports 64 channels

Audio effect extension version: 1.0

Audio max auxilary sends: 4

Camera created (W: 120, H: 120)

Loaded material definition: Unshaded

Child (BitmapFont) attached to this node (null)



Second log (with edits shows our app fails on machine) ============================

Property: ‘java.runtime.name’ contains ‘Java™ SE Runtime Environment’.

Property: ‘sun.boot.library.path’ contains ‘C:Program FilesJavajdk1.6.0_21jrebin’.

Property: ‘java.vm.version’ contains ‘17.0-b17’.

Property: ‘netbeans.dynamic.classpath’ contains 'C:Program FilesNetBeans 6.9.1platformcorecore.jar;C:Program FilesNetBeans 6.9.1platformcoreorg-openide-filesystems.jar;C:Program FilesNetBeans 6.9.1platformcorelocalecore_ja.jar;C:Program FilesNetBeans 6.9.1platformcorelocalecore_pt_BR.jar;C:Program FilesNetBeans 6.9.1platformcorelocalecore_zh_CN.jar;C:Program FilesNetBeans 6.9.1platformcorelocaleorg-openide-filesystems_ja.jar;C:Program FilesNetBeans 6.9.1platformcorelocaleorg-openide-filesystems_pt_BR.jar;C:Program FilesNetBeans 6.9.1platformcorelocaleorg-openide-filesystems_zh_CN.jar;



Property: ‘java.awt.graphicsenv’ contains ‘sun.awt.Win32GraphicsEnvironment’.



INFO [com.jme3.system.JmeSystem]: Running on jMonkeyEngine 3.0.0 Beta

INFO [com.jme3.system.Natives]: Extraction Directory: C:Documents and SettingsusernameDesktopqbt1.0appname

[Debug output] Installer restored: to SceneApplication.getApplication

[Debug output]SceneApplication: start

[Debug output]SceneApplication: useCanvas: false

[Debug output]SceneApplication:renderer:CUSTOMcom.jme3.system.awt.AwtPanelsContext

INFO [org.springframework.context.support.FileSystemXmlApplicationContext]: Refreshing org.springframework.context.support.FileSystemXmlApplicationContext@c6a26b: display name [org.springframework.context.support.FileSystemXmlApplicationContext@c6a26b]; startup date [Thu Dec 15 08:36:36 EST 2011]; root of context hierarchy

INFO [com.jme3.system.lwjgl.LwjglOffscreenBuffer]: Using LWJGL 2.8.2

[Debug output]SceneApplication: stop

[Debug output]Installer restored: from SceneApplication.getApplication

INFO [org.netbeans.core.startup.NbEvents]: Turning on modules:

org.openide.util.lookup [8.3.1 201007282301]

org.openide.util [8.6.2 201012081820]

org.openide.modules [7.17.2 201012081820]

org.openide.awt [7.23.1 201007282301]

org.netbeans.api.progress/1 [1.20.2 201007282301]

[Omitted]

SEVERE [com.jme3.system.lwjgl.LwjglOffscreenBuffer]: Offscreen surfaces are not supported.

SEVERE [org.openide.util.Exceptions]

java.lang.IllegalStateException

at com.jme3.system.lwjgl.LwjglOffscreenBuffer.runLoop(LwjglOffscreenBuffer.java:111)

at com.jme3.system.lwjgl.LwjglOffscreenBuffer.run(LwjglOffscreenBuffer.java:147)

[catch] at java.lang.Thread.run(Thread.java:619)



Third log (shows our app works on newer machine) ========================

INFO [com.jme3.system.JmeSystem]: Running on jMonkeyEngine 3.0.0 Beta

INFO [com.jme3.system.Natives]: Extraction Directory: C:UsersusernameDesktopjme3sdkbuildtestuserdir

INFO [com.jme3.system.lwjgl.LwjglOffscreenBuffer]: Using LWJGL 2.8.2

INFO [com.jme3.system.lwjgl.LwjglOffscreenBuffer]: Offscreen buffer created.

INFO [com.jme3.system.lwjgl.LwjglContext]: Adapter: nvd3dumx,nvwgf2umx,nvwgf2umx

INFO [com.jme3.system.lwjgl.LwjglContext]: Driver Version: null

INFO [com.jme3.system.lwjgl.LwjglContext]: Vendor: NVIDIA Corporation

INFO [com.jme3.system.lwjgl.LwjglContext]: OpenGL Version: 3.3.0

INFO [com.jme3.system.lwjgl.LwjglContext]: Renderer: GeForce 8800 GT/PCI/SSE2

INFO [com.jme3.system.lwjgl.LwjglContext]: GLSL Ver: 3.30 NVIDIA via Cg compiler

INFO [com.jme3.system.lwjgl.LwjglTimer]: Timer resolution: 1,000 ticks per second

INFO [com.jme3.renderer.lwjgl.LwjglRenderer]: Caps: [FrameBuffer, FrameBufferMRT, FrameBufferMultisample, TextureMultisample, OpenGL20, OpenGL21, OpenGL30, OpenGL31, OpenGL32, ARBprogram, GLSL100, GLSL110, GLSL120, GLSL130, GLSL140, GLSL150, VertexTextureFetch, TextureArray, TextureBuffer, FloatTexture, FloatColorBuffer, FloatDepthBuffer, PackedFloatTexture, SharedExponentTexture, PackedFloatColorBuffer, TextureCompressionLATC, NonPowerOfTwoTextures, MeshInstancing, VertexBufferArray]

INFO [com.jme3.asset.AssetManager]: DesktopAssetManager created.

INFO [com.jme3.renderer.Camera]: Camera created (W: 640, H: 480)

INFO [com.jme3.renderer.Camera]: Camera created (W: 640, H: 480)

INFO [com.jme3.audio.lwjgl.LwjglAudioRenderer]: AudioRenderer supports 64 channels

INFO [com.jme3.audio.lwjgl.LwjglAudioRenderer]: Audio effect extension version: 1.0

INFO [com.jme3.audio.lwjgl.LwjglAudioRenderer]: Audio max auxilary sends: 4

INFO [com.jme3.renderer.Camera]: Camera created (W: 120, H: 120)

INFO [com.jme3.material.MaterialDef]: Loaded material definition: Unshaded

INFO [com.jme3.scene.Node]: Child (BitmapFont) attached to this node (null)

INFO [com.jme3.scene.Node]: Child (null) attached to this node (Stats Gui Node)

Mind that you have to do the AWT threading correctly. E.g. open windows only on the AWT EDT thread etc.

Great - adding checks to confirm use of the EDT thread now…

The error is being generated during the call to SceneApplication.getApplication() in the Installer. In our implementation, SceneViewerTopComponent is not instantiated at start up (works as expected on faster machine).The call to SceneApplication.getApplication from the Installer was not executing in the EDT. Assuming it needs to be treated as a window, it was wrapped in EventQueue.invokeAndWait(). This executed successfully on faster desktop (same behavior as before) - and generated the same error on the laptop:

INFO [com.jme3.system.lwjgl.LwjglOffscreenBuffer]: Using LWJGL 2.8.2
SEVERE [com.jme3.system.lwjgl.LwjglOffscreenBuffer]: Offscreen surfaces are not supported.
SEVERE [org.openide.util.Exceptions]
java.lang.IllegalStateException
at com.jme3.system.lwjgl.LwjglOffscreenBuffer.runLoop(LwjglOffscreenBuffer.java:111)
at com.jme3.system.lwjgl.LwjglOffscreenBuffer.run(LwjglOffscreenBuffer.java:147)

FWIW the SDK is using lwjgl 2.8.1, the working and error-generating platforms are using 2.8.2 but the error existed with 2.8.1 .
Is this what you were suggesting?

Well it sounds like you should meditate about the threading issues a bit more ^^. Make sure you do whatever you have to do with the scene only after it has been initialized (e.g. send a runnable to the EDT at the end of simpleInitApp() if you need to check back stuff there). Also don’t block the current thread on the EDT, do things asynchronously (use invokeLater). Does the laptop support OpenGL 2.0 at all? I don’t know why “Offscreen surfaces are not supported” there.

I am off to contemplate threading… But before I do, our primary issue is ruggedizing the initialization which succeeds on some platforms and fails on others. Since the SDK works on all of our platforms, would you agree we should study the SDK and adopt its initialization strategy? So far we are concentrating on getting all platforms to successfully get through SceneApplication.getApplication via the Installer and failing. Does JMESystem need to be initialized in some way?

BTW, the laptop has the latest drivers from vendor and info is below. We get the identical error “Offscreen surfaces are not supported” on another platform. So far, our code fails on two systems and works on one.



Video Card Vendor: Intel

Renderer: Mobile Intel® 4 Series Express Chipset Family

OpenGL Version: 2.1.0 - Build 6.14.10.5355

GLU Version: 1.2.2.0 Microsoft Corporation

Current pixel format: 6

I guess you can look up the proper initialization sequence from the SDK yeah. It actually uses the awt panels instead of the canvas by default now. The threading model the SDK follows is basically AWT = logic thread and OpenGL = 3d draw and worker thread. That is most stuff happens on the AWT thread which is asynchronously sending messages to the scene graph. Things like loading models an similar are often done on the OpenGL thread so the UI can continue to be updated. Generally I’d avoid using the SceneApplication in the installer, why do you need it there? Obviously the scene cannot be initialized in that moment. You should try and move whatever logic needs the scene there to the function that actually opens the scene window.

Thanks for the insight - I will review the awt panel classes. I mistakenly interpreted com.jme3.gde.core.Installer lines:

public void restored() { //start scene app; SceneApplication.getApplication();

as the point of initialization and its removed.

The SceneApplication.getApplication() is now first called from the SceneViewerTopComponent constructor.

The same errors are reported.

Well it is there to start the application for the first time but the initialization sequence is different with awt panels and canvas. Basically a canvas app only starts to update loop when the application window first opens and the awt panel driven app can be running in the background too and fully complete its initialization sequence before the window has opened. I am a bit confused now as you named your classes and methods exactly like mine from the SDK ^^ If you actually are the only one calling this on your application I guess its ok to start the jme3 app in the Installer but I cannot really say if it makes sense for your application. If using AWT panels you could even have a separate application class per panel which is not planned in the SDK, where previews in the main application are used.

After further testing we have implemented our app using both the Swing canvas and the AWT panels. We see that the Swing canvas has somewhat smoother operation within the GUI but like the idea of being able to initialize off-screen using panels. Would anyone recommend one method over the other? Is one faster? Will the AWT panels continue to be used for the SDK?

The SDK allows using both

“Offscreen surfaces are not supported” - This error means the GPU driver doesn’t support offscreen surfaces and thus the AWT panel rendering method cannot be used.