glDrawElements() 使 Lollipop 崩溃但在 KitKat 上正常
glDrawElements() crashes Lollipop but OK on KitKat
我正在尝试为 Android 学习 OpenGL ES 1.0。在今天早上我将设备升级到 Android 5.0.1 Lollipop 之前,我的应用程序运行良好。我最初尝试调试此问题后,很快发现我的应用程序仍可在模拟器 运行 KitKat 上运行,但在 Lollipop 上崩溃,无论是在我的设备上还是在模拟器上。
我的应用程序使用 OpenGL 绘制了一个简单的立方体,每一面都有不同的纹理。我已将其排除在 glDrawElements() 行崩溃的位置。
package com.briansworld.gravitycubestep7;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.opengles.GL10;
// draw a cube
// store the cube's position within the multicube
// bind the textures here
class Cube
{
private FloatBuffer mVertexBuffer;
private FloatBuffer myTexBuffer;
private ByteBuffer myIndexBuffer;
public int x, y, z; // used to keep track of which cube is which, not cube position
// constructor
public Cube(int x, int y, int z) // need to add texture ID's
{
this.x = x;
this.y = y;
this.z = z;
float vertices[] =
{
-1.0f, -1.0f, 1.0f, // front
1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f, // right
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f, // rear
-1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f, // left
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, -1.0f, // bottom
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, -1.0f, // top
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f
};
float texBuffer[] =
{
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f
};
byte indexBuffer[] =
{
0, 1, 3, 0, 3, 2,
4, 5, 7, 4, 7, 6,
8, 9, 11, 8, 11, 10,
12, 13, 15, 12, 15, 14,
16, 17, 19, 16, 19, 18,
20, 21, 23, 20, 23, 22
};
ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
mVertexBuffer = byteBuf.asFloatBuffer();
mVertexBuffer.put(vertices);
mVertexBuffer.position(0);
byteBuf = ByteBuffer.allocateDirect(texBuffer.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
myTexBuffer = byteBuf.asFloatBuffer();
myTexBuffer.put(texBuffer);
myTexBuffer.position(0);
myIndexBuffer = ByteBuffer.allocate(indexBuffer.length);
myIndexBuffer.put(indexBuffer);
myIndexBuffer.position(0);
}
// need to add functionality to only draw viewable/outside textures
public void draw(GL10 gl, int[] texture)
{
// enable vertex and texture states
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
// set the font face rotation
gl.glFrontFace(GL10.GL_CW);
// set the pointers to the buffers
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, myTexBuffer);
// step each face of the cube and attach a different texture to each side
for (int i = 0; i < 6; i++)
{
gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[i]); // bind the textures
myIndexBuffer.position(6 * i); // step through the buffer
gl.glDrawElements(GL10.GL_TRIANGLES, 6, GL10.GL_UNSIGNED_BYTE, myIndexBuffer);
}
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
}
}
catlog 中错误消息的前几行是:
JNI 检测到应用程序错误:元素指针 0x12ce4382 无效,数组元素为 0x12ce437c
in call to ReleaseArrayElements
from void com.google.android.gles_jni.GLImpl.glDrawElements(int, int, int, java.nio.Buffer)
"GLThread 147" prio=5 tid=12 可运行
|组="main" sCount=0 dsCount=0 obj=0x12c72430 self=0xae286400
| sysTid=2100 nice=0 cgrp=default sched=0/0 handle=0xb4559f00
|状态=R schedstat=( 0 0 0 ) utm=1 stm=16 核心=0 HZ=100
|堆栈=0xa6832000-0xa6834000 堆栈大小=1036KB
|持有互斥量= "mutator lock"(共享持有)
通过for循环的第一次迭代就OK了。在第二次传递时,应用程序在 glDrawElements 行崩溃。为什么这在 KitKat Android 4.4 中没有任何问题,而在 Lollipop Android 5.0 中却崩溃了?我需要做什么不同的事情才能让我的代码与 Lollipop 一起工作?
使用allocateDirect
分配您的索引缓冲区:
myIndexBuffer = ByteBuffer.allocateDirect(indexBuffer.length);
传递给 OpenGLES 的所有缓冲区都应该是直接缓冲区。我不知道为什么它会在 Kit Kat 上运行,也许在幕后进行了一些优化,现在它有所不同。
我正在尝试为 Android 学习 OpenGL ES 1.0。在今天早上我将设备升级到 Android 5.0.1 Lollipop 之前,我的应用程序运行良好。我最初尝试调试此问题后,很快发现我的应用程序仍可在模拟器 运行 KitKat 上运行,但在 Lollipop 上崩溃,无论是在我的设备上还是在模拟器上。
我的应用程序使用 OpenGL 绘制了一个简单的立方体,每一面都有不同的纹理。我已将其排除在 glDrawElements() 行崩溃的位置。
package com.briansworld.gravitycubestep7;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.opengles.GL10;
// draw a cube
// store the cube's position within the multicube
// bind the textures here
class Cube
{
private FloatBuffer mVertexBuffer;
private FloatBuffer myTexBuffer;
private ByteBuffer myIndexBuffer;
public int x, y, z; // used to keep track of which cube is which, not cube position
// constructor
public Cube(int x, int y, int z) // need to add texture ID's
{
this.x = x;
this.y = y;
this.z = z;
float vertices[] =
{
-1.0f, -1.0f, 1.0f, // front
1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f, // right
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f, // rear
-1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f, // left
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, -1.0f, // bottom
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, -1.0f, // top
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f
};
float texBuffer[] =
{
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f
};
byte indexBuffer[] =
{
0, 1, 3, 0, 3, 2,
4, 5, 7, 4, 7, 6,
8, 9, 11, 8, 11, 10,
12, 13, 15, 12, 15, 14,
16, 17, 19, 16, 19, 18,
20, 21, 23, 20, 23, 22
};
ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
mVertexBuffer = byteBuf.asFloatBuffer();
mVertexBuffer.put(vertices);
mVertexBuffer.position(0);
byteBuf = ByteBuffer.allocateDirect(texBuffer.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
myTexBuffer = byteBuf.asFloatBuffer();
myTexBuffer.put(texBuffer);
myTexBuffer.position(0);
myIndexBuffer = ByteBuffer.allocate(indexBuffer.length);
myIndexBuffer.put(indexBuffer);
myIndexBuffer.position(0);
}
// need to add functionality to only draw viewable/outside textures
public void draw(GL10 gl, int[] texture)
{
// enable vertex and texture states
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
// set the font face rotation
gl.glFrontFace(GL10.GL_CW);
// set the pointers to the buffers
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, myTexBuffer);
// step each face of the cube and attach a different texture to each side
for (int i = 0; i < 6; i++)
{
gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[i]); // bind the textures
myIndexBuffer.position(6 * i); // step through the buffer
gl.glDrawElements(GL10.GL_TRIANGLES, 6, GL10.GL_UNSIGNED_BYTE, myIndexBuffer);
}
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
}
}
catlog 中错误消息的前几行是:
JNI 检测到应用程序错误:元素指针 0x12ce4382 无效,数组元素为 0x12ce437c
in call to ReleaseArrayElements
from void com.google.android.gles_jni.GLImpl.glDrawElements(int, int, int, java.nio.Buffer)
"GLThread 147" prio=5 tid=12 可运行
|组="main" sCount=0 dsCount=0 obj=0x12c72430 self=0xae286400
| sysTid=2100 nice=0 cgrp=default sched=0/0 handle=0xb4559f00
|状态=R schedstat=( 0 0 0 ) utm=1 stm=16 核心=0 HZ=100
|堆栈=0xa6832000-0xa6834000 堆栈大小=1036KB
|持有互斥量= "mutator lock"(共享持有)
通过for循环的第一次迭代就OK了。在第二次传递时,应用程序在 glDrawElements 行崩溃。为什么这在 KitKat Android 4.4 中没有任何问题,而在 Lollipop Android 5.0 中却崩溃了?我需要做什么不同的事情才能让我的代码与 Lollipop 一起工作?
使用allocateDirect
分配您的索引缓冲区:
myIndexBuffer = ByteBuffer.allocateDirect(indexBuffer.length);
传递给 OpenGLES 的所有缓冲区都应该是直接缓冲区。我不知道为什么它会在 Kit Kat 上运行,也许在幕后进行了一些优化,现在它有所不同。