I'm creating a VBO with GLES20 in Android and am currently running into a JNI error. I doublechecked capacity and value counts. I also checked, if the buffer (STANDARD_QUAD in my code) gets and ID. I really don't know how to continue. I tested on 2 different physical devices and one emulator, so the fault must be in the code somewhere.
Code:
ByteBuffer buffer = ByteBuffer.allocate(30 * 4);
buffer.order(ByteOrder.nativeOrder());
buffer.asFloatBuffer().put(new float[]{
0, 0, 0, 0,0,
0, 1, 0, 0,1,
1, 0, 0, 1,0,
1, 1, 0, 1,1,
1, 0, 0, 1,0,
0, 1, 0, 0,1
});
buffer.flip();
int[] vboids = new int[1];
GLES20.glGenBuffers(1, vboids, 0);
STANDARD_QUAD = vboids[0];
System.out.println("init vbo (std quad): " + STANDARD_QUAD + ", buffer.capacity: " + buffer.capacity());
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, STANDARD_QUAD);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, buffer.capacity(), buffer, GLES20.GL_STATIC_DRAW);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
Output:
init vbo (std quad): 1, buffer.capacity: 120
JNI DETECTED ERROR IN APPLICATION: thread Thread[13,tid=19730,Runnable,Thread*=0xb4e08800,peer=0x12c07060,"GLThread 13050"] called too many critical releases
in call to ReleasePrimitiveArrayCritical
from void android.opengl.GLES20.glBufferData(int, int, java.nio.Buffer, int)
"GLThread 13050" prio=5 tid=13 Runnable
| group="main" sCount=0 dsCount=0 obj=0x12c07060 self=0xb4e08800
| sysTid=19730 nice=-11 cgrp=apps sched=0/0 handle=0xaf854300
| state=R schedstat=( 73594541 5530250 17 ) utm=6 stm=1 core=5 HZ=100
| stack=0xa10fe000-0xa1100000 stackSize=1036KB
| held mutexes= "mutator lock"(shared held)
native: #00 pc 00004c58 /system/lib/libbacktrace_libc++.so (UnwindCurrent::Unwind(unsigned int, ucontext*)+23)
native: #01 pc 000034c1 /system/lib/libbacktrace_libc++.so (Backtrace::Unwind(unsigned int, ucontext*)+8)
native: #02 pc 0025c5ad /system/lib/libart.so (art::DumpNativeStack(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, int, char const*, art::mirror::ArtMethod*)+84)
native: #03 pc 0023f8cb /system/lib/libart.so (art::Thread::Dump(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const+162)
native: #04 pc 000b313d /system/lib/libart.so (art::JniAbort(char const*, char const*)+620)
native: #05 pc 000b386d /system/lib/libart.so (art::JniAbortF(char const*, char const*, ...)+68)
native: #06 pc 000b6b65 /system/lib/libart.so (art::ScopedCheck::ScopedCheck(_JNIEnv*, int, char const*)+1436)
native: #07 pc 000c1de7 /system/lib/libart.so (art::CheckJNI::ReleasePrimitiveArrayCritical(_JNIEnv*, _jarray*, void*, int)+42)
native: #08 pc 000684d1 /system/lib/libandroid_runtime.so (???)
native: #09 pc 000736e3 /system/lib/libandroid_runtime.so (???)
native: #10 pc 01574071 /system/framework/arm/boot.oat (Java_android_opengl_GLES20_glBufferData__IILjava_nio_Buffer_2I+128)
at android.opengl.GLES20.glBufferData(Native method)
at my.package.glsl.GuiProgram.initQuad(GuiProgram.java:66)
at my.package.glsl.GuiProgram.onCreated(GuiProgram.java:111)
at my.package.glsl.Program.create(Program.java:67)
at my.package.glsl.Shaders.initialize(Shaders.java:26)
at my.package.myapplication.FullscreenActivity.renderGL(FullscreenActivity.java:66)
at my.package.myapplication.FullscreenActivity.access$000(FullscreenActivity.java:22)
at my.package.myapplication.FullscreenActivity$1.render(FullscreenActivity.java:42)
at my.package.opengl.OpenglRenderer.onDrawFrame(OpenglRenderer.java:38)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1561)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1278)
EDIT:
Changing the code to the following, the error changes.
FloatBuffer buffer = ByteBuffer.allocate(30 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
buffer.put(new float[]{
//...
});
buffer.flip();
//...
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, buffer.capacity() * 4, buffer, GLES20.GL_STATIC_DRAW);
The error changes to JNI DETECTED ERROR IN APPLICATION: jarray was null
. But definitely buffer != null. It's really weird.
I finally solved it by using buffer.position(0)
instead of buffer.flip()
.
According to the docs buffer.flip()
should work correct, as it is also setting the position to 0. The only difference is that flip()
is also setting the limit
to the last position (see the docs for more information).
So it's possible that the limit causes the weird behaviour.