I am trying to use multiple EGL contexts to load textures outside of my main thread. I'm getting an EGL_BAD_CONTEXT error after my eglCreateContext call.
Inside my android.opengl.Renderer
public void onSurfaceCreated (javax.microedition.khronos.opengles.GL10 gl, EGLConfig config) {
// ...
EGLContext sharedContext = egl.getCurrentContext();
EGLDisplay display = eglGetCurrentDisplay();
eglCreateContext(display, config, sharedContext, new int[] { EGL_CONTEXT_CLIENT_VERSION, 2 } );
}
The EGL_BAD_CONTEXT lead me to the documentation here, that says
EGL_BAD_CONTEXT is generated if share_context is not an EGL rendering context of the same client API type as the newly created context and is not EGL_NO_CONTEXT.
That's why I added in the EGL_CONTEXT_CLIENT_VERSION parameter, but it seems to have made no effect.
What I'm seeing is that, even though I'm getting this error, the context seems semi-valid. I'm able to use it on another thread
egl.eglMakeCurrent(display, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, context);
After this, creating textures on that thread does not cause an error. But I do see that the texture names are not shared, each thread seems to count up from 0 itself.
My next assumption was that I need to share the surface between contexts. But, if I pass through the same surface from the original context into my eglMakeCurrent, but I fail completely with
E/AndroidRuntime(3210): java.lang.IllegalArgumentException
E/AndroidRuntime(3210): at com.google.android.gles_jni.EGLImpl._eglCreateContext(Native Method)
E/AndroidRuntime(3210): at com.google.android.gles_jni.EGLImpl.eglCreateContext(EGLImpl.java:54)
I feel as though I'm almost there, does somebody know what's missing?
Turns out, thanks to some help from this question:
My secondary context requires a surface. It is not the same as the original context's surface.
I needed to create that new surface using eglCreatePbufferSurface. The reason my attempts with this had failed before is that it defaults to a width and height of 0. By setting that to a 1x1 surface, it worked perfectly.
egl.eglCreatePbufferSurface(display, config, new int[] { EGL10.EGL_WIDTH, 1, EGL10.EGL_HEIGHT, 1, EGL10.EGL_NONE });
Related
I'm using a JOGL FPSAnimator and Apple's FullScreenUtilies class. I implemented this some time ago, and it worked fine. Here is my code for enabling the native OS X fullscreen capability, similar to other code on SO and around the web:
String className = "com.apple.eawt.FullScreenUtilities";
String methodName = "setWindowCanFullScreen";
try {
Class<?> clazz = Class.forName(className);
Method method = clazz.getMethod(methodName,
new Class<?>[] { Window.class, boolean.class });
method.invoke(null, frame, true);
} catch ...
It also works fine in the context of a simple test program I made in an attempt to isolate the issue. I'm not sure at what point the behaviour changed - I haven't spotted anything incriminating in SVN logs. It's likely that I first implemented the feature on an earlier version of OS X, and have also upgraded JOGL version and MyDoggy which we use for docking since. However, all of these things work with fullscreen in the context of other applications.
When I press the green fullscreen button, the usual OSX fullscreen transition starts (it gets its own desktop space), but the window appears frozen from that point on.
The main AWT Event thread carries on running, and I can see that my GLEventListener.display() method is being regularly called. I've tried adding a return to the beginning of that method to eliminate the impact of my rendering code, this unsurprisingly made no difference.
For testing purposes, I added a FullScreenListener:
FullScreenUtilities.addFullScreenListenerTo(frame, new FullScreenAdapter() {
#Override
public void windowEnteringFullScreen(FullScreenEvent arg0) {
log(">>> Entering fullscreen... <<<");
}
#Override
public void windowEnteredFullScreen(FullScreenEvent arg0) {
log(">>> Entered fullscreen. <<<");
}
});
As anticipated, I get the entering fullscreen event, but not the entered one.
It's a fairly large program, but there should be a fairly small surface of things that are potentially relevant here... unfortunately I haven't managed to trace them down. Happy if anyone has any pointers.
I know this is an error with accessing memory outside the readspace but i have absolutely no idea how to fix this. I'm new to android, so i don't exactly know how to print out a more detailed error list from logcat in eclipse. I've tried everything from disposing literally everything, to calling System.gc to setting all my variables to null. However, whenever i switch screens the fatal signal occurs. I just need someone to tell me what exactly is going on or how i could get more details about the error.
I had the same error, what solved it was to make sure i'm on the UI thread, like this:
Gdx.app.postRunnable(new Runnable() {
#Override
public void run() {
// Your crashing code here
}
});
In my case i received same error when i try to create a new body and attach it's fixture, from beginContact (inside Contact Listener). After i moved outside Contact Listener my body creation everything was ok. Probably some conflict appears in Fixture createFixture (FixtureDef def) because according to manual: Contacts are not created until the next time step.
I'm working with the VLCJ Bindings and have finally been able to get several roadblocks. Now I am here.
I have no need (at this time), nor desire for, a visible Media Player component (the EmbeddedMediaPlayerComponent). All I need (for now) is to play Audio Files.
I have the following method in place to handle that for me:
public static void Play(File AudioFile){
if (!LibVLCLoader.Loaded) LibVLCLoader.loadLibVLC();
EmbeddedMediaPlayerComponent EMPC = new EmbeddedMediaPlayerComponent();
if (EMPC.getMediaPlayer().prepareMedia(AudioFile.getAbsolutePath())){
EMPC.getMediaPlayer().addMediaPlayerEventListener(new MediaPlayerEventAdapter(){
#Override public void subItemFinished(MediaPlayer p, int i){
EMPC.release(true);
}
});
Platform.runLater(() -> EMPC.getMediaPlayer().play());
}
}
But I keep getting this exception:
Exception in thread "JavaFX Application Thread" java.lang.IllegalStateException: The video surface component must be displayable
Which I understand. It makes sense. But I don't NEED it visible. I just need the sound. How can I make that happen?
EmbeddedMediaPlayer is only for the case where you want to literally embed a video surface inside your application.
If you just need audio, there's an AudioMediaPlayerComponent for expressly this purpose.
To create such a component, simply:
AudioMediaPlayerComponent audioMediaPlayerComponent =
new AudioMediaPlayerComponent();
You can subclass it, for example to customise behaviour and easily implement event handlers.
Using the so-called "component" media players gives you a slightly nicer/easier API than using the non-"component" media players that are created via the MediaPlayerFactory.
This works just fine if your media is an audio file.
If your media is actually video, but you only want to play the audio track, then even if you use the AudioMediaPlayerComponent by default VLC will open a video window. In this case you still need to actually disable the video output - the simplest way to do this is to tell VLC to use vcodec=dummy.
I really don't agree with tricks like creating a window and moving it off-screen, or sizing it down to 1x1, it's just not necessary.
In the code posted in the original question there is an unrelated problem. The EMPC and EMP variable will go out-of-scope when the Play() method terminates, making the media player eligible for garbage collection. What will happen is that some random time later your application will likely crash because the native hooks that vlcj uses will call back into a Java object that no longer exists. You need to keep your media player references alive via hard references.
Okay so it turns out you can create your own MediaPlayer object outside of the EmbeddedMediaPlayerComponent like so:
public static void Play(File AudioFile){
if (!LibVLCLoader.Loaded) LibVLCLoader.loadLibVLC();
MediaPlayerFactory MPF = new MediaPlayerFactory(
"--video-title=vlcj video output",
"--no-snapshot-preview",
"--quiet",
"--quiet-synchro",
"--sub-filter=logo:marq",
"--intf=dummy"
);
EmbeddedMediaPlayer EMP = MPF.newEmbeddedMediaPlayer();
if (EMP.prepareMedia(AudioFile.getAbsolutePath())){
EMP.addMediaPlayerEventListener(new MediaPlayerEventAdapter(){
#Override public void subItemFinished(MediaPlayer p, int i){
EMP.release();
MPF.release();
}
});
Platform.runLater(() -> EMP.play());
} else{
EMP.release();
MPF.release();
}
}
I'm writing a game over libgdx; I'm using the junit framework to simplify unit-testing my code.
Now there's part of the code (a map generator, a class converting my own map format into TiledMap...) which I need to test thoroughly, but it uses libgdx code: from file handling to asset loading.
I'm not planning to test the actual graphical output, or the game itself, in this way: but I want to test the single components (calculation, asset access...) to avoid blatant errors.
I've tried to do something like this in the "setUpBeforeClass" method:
LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
cfg.useGL20 = true;
cfg.width = 480;
cfg.height = 320;
cfg.resizable = true;
LwjglApplication app = new LwjglApplication( new TestApplicationListener(), cfg);
And calling within tearDownAfterClass():
Gfx.app.exit()
But it does create a window I do not need, and seems overkill when all I need is the file handling initialized. Is there a better way to initialize the libGDX components without creating an entire application object?
Thanks.
EDIT
Going back over it (thanks to Sam in the comments), I realize GL access is needed (loading assets requires it), but this approach does not seem to work: the graphic library does not seem to be initialized. GDX documentation hasn't helped. Any clue?
This question hasn't been answered and I am surprised nobody has pointed out the headless backend, which is ideal for this situation. Combine this with your favorite mocking library and you should be good to go.
public class HeadlessLauncher {
public static void main(final String[] args) {
final HeadlessApplicationConfiguration config = new HeadlessApplicationConfiguration();
config.renderInterval = Globals.TICK_RATE; // Likely want 1f/60 for 60 fps
new HeadlessApplication(new MyApplication(), config);
}
}
As already showed there is a HeadlessApplication backend which gives you an initialized libGDX but has no OpenGL context. For working with OpenGL you indeed need the LwjglApplication backend which creates an OpenGL window.
If you have problems writing tests which rely on the OpenGL context keep in mind that OpenGL is only attached to the thread of your LwjglApplication which is not the tread of your tests. Your tests have to call Gdx.app.postRunnable(Runnable r) to access the thread with the OpenGl context.
You may want to use synchronized and CountDownLatch to pause the test while waiting for your application to execute the command.
I'm struggling a bit with my use of fragments for ICS. I've got a fragment (call it AnalysisFragment) that does a fair amount of number-crunching work, reading in a file and then performing a number of calculations on it. Most of this work is initiated in onActivityCreated, because I need to consult the app's settings file prior to doing the work, which in turn requires having the context, which is accessible through the activity, which isn't necessarily available until onActivityCreated is invoked.
Well, this work seems to be getting done again (twice!) whenever I rotate the display. In my LogCat, I see onDestroyView and onDestroy happening (once), followed by onCreate, onCreateView, and onActivityCreated (twice), all pertaining to AnalysisFragment.
Obviously, the work of re-painting the screen for a different orientation has to be done over again, but is there any way I can add avoid the number-crunching work a 2nd time (not to mention a 3rd time)?
I maybe should add that I'm instantiating a new copy of AnalysisFragment whenever the user selects a new file to analyze, as follows
public static AnalysisFragment newInstance
(
String ndsFileName,
ViewIndicator viewIndicator
)
{
AnalysisFragment analysisFragment = new AnalysisFragment( );
Bundle bundle = new Bundle( );
bundle.putString( "nds_file_name", ndsFileName );
bundle.putString( "view_indicator", viewIndicator.toString( ) );
analysisFragment.setArguments( bundle );
return analysisFragment;
}
However, during a re-orientation, Android must be doing it for me. After shutting down the instance I created, it instantiates another using the same bundle for the new screen orientation. Eventually, onActivityCreated gets called on the new instance, and my code is off reading in the same file it read moments ago and re-doing the number crunching.
Any insight would be appreciated ...