首先,我应该说,我正在使用Android API 27在像素的模拟器上运行此程序,但我在Android API 26上也遇到了同样的崩溃。
我只是试图绘制一个二维精灵并设置它的动画。我有一个线程与渲染循环同时运行(在GLSurfaceView和GLSurfaceView.render中),用不同的纹理坐标更新精灵表中的VBO。但据我所知,问题并不是从哪里来的。
基本上,我所能告诉的是,在我绑定和解除绑定我的VBO后,glDrawElements崩溃了,特别是解除绑定。具体来说,它是一个空指针取消引用错误。不过,当我解除绑定我的元素缓冲区对象时,这个问题不会发生。
编辑:我刚刚发布了这篇文章,我意识到我忘了提到,在glBindBuffer上快速阅读后,我发现:
保留值零,但没有默认的缓冲区对象每个缓冲对象目标。相反,缓冲区有效地设置为零解除绑定以前绑定的任何缓冲区对象,并恢复客户端内存该缓冲区对象目标的使用情况(如果该目标支持)。
关于恢复内存的部分可能是造成这种情况的原因吗?如果是的话,我该如何解除绑定。
以下是Sprite.java的代码:
package com.matthew.beatclimber;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import android.opengl.Matrix;
import android.content.Context;
import java.util.Timer;
import java.util.TimerTask;
/**
* Created by matthew on 10/28/17.
*/
/*
Note to self:
This can be done to bind a attribute location to a literal
GLES20.glBindAttribLocation(program, 0, "vPosition");
*/
public class Sprite
{
private FloatBuffer vertexBuffer;
private ShortBuffer indexBuffer;
private Timer animateTimer;
private SpriteSheet spriteSheet;
private int[] vbo = {0}, ebo = {0}, texture = {0};
private int vertexShader, fragmentShader, program;
static float[] vertices = {
-16.0f, 16.0f, 0.0f, 1.0f, /*Tex Coords*/ -1.0f, 1.0f, //Top Left
-16.0f, -16.0f, 0.0f, 1.0f, -1.0f, -1.0f, //Bot Left
16.0f, -16.0f, 0.0f, 1.0f, 1.0f, -1.0f, //Bot Right
//-1.0f, 1.0f, 3.0f, 1.0f, /*Tex Coords*/ -1.0f, 1.0f, //Top Left
//1.0f, -1.0f, 3.0f, 1.0f, 1.0f, -1.0f, //Bot Right
16.0f, 16.0f, 0.0f, 1.0f, 1.0f, 1.0f //Top Right
};
private static final short[] order = { 0, 1, 2, 0, 2, 3};
private float[] model = new float[16];
static float[] ortho = new float[16];
char[] infoLog = new char[512];
private static final String vertexShaderCode =
"attribute vec4 vPosition;" +
"attribute vec2 TexCoords;" +
"varying vec2 texCoords;" +
"uniform mat4 ortho;" +
"uniform mat4 model;"+
"void main() {" +
" gl_Position = ortho * model * vPosition;" +
" texCoords = TexCoords;" +
"}";
private static final String fragmentShaderCode =
"precision mediump float;" +
"uniform sampler2D tex1;" +
"varying vec2 texCoords;" +
"void main() {" +
" gl_FragColor = mix(texture2D(tex1, texCoords), vec4(texCoords, 0.0, 1.0), 0.2);" +
"}";
public Sprite(int screenWidth, int screenHeight)
{
//Set model equal to a identity matrix
Matrix.setIdentityM(model, 0);
Matrix.translateM(model, 0, screenWidth / 2, screenHeight / 2, 0);
Matrix.scaleM(model, 0, 32, 32, 0);
ByteBuffer bb = ByteBuffer.allocateDirect(vertices.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
ByteBuffer dlb = ByteBuffer.allocateDirect(order.length * 2);
dlb.order(ByteOrder.nativeOrder());
indexBuffer = dlb.asShortBuffer();
indexBuffer.put(order);
indexBuffer.position(0);
//Create shader program
vertexShader = OpenGLES31Activity.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
fragmentShader = OpenGLES31Activity.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
program = GLES20.glCreateProgram();
int[] success = new int[2];
GLES20.glGetShaderiv(vertexShader, GLES20.GL_COMPILE_STATUS, success, 0);
GLES20.glGetShaderiv(fragmentShader, GLES20.GL_COMPILE_STATUS, success, 1);
GLES20.glAttachShader(program, vertexShader);
GLES20.glAttachShader(program, fragmentShader);
GLES20.glBindAttribLocation(program, 0, "vPosition");
GLES20.glBindAttribLocation(program, 1, "TexCoords");
GLES20.glLinkProgram(program);
if((success[0] == GLES20.GL_FALSE))
{
GLES20.glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
String info = GLES20.glGetShaderInfoLog(vertexShader);
System.out.println("ERROR: VERTEX: " + info);
}
if ((success[1] == GLES20.GL_FALSE))
{
GLES20.glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
String info = GLES20.glGetShaderInfoLog(fragmentShader);
System.out.println("ERROR: FRAG: " + info);
}
//Create Buffer Objects (Vertex and Element Buffer Objects)
GLES20.glGenBuffers(1, vbo, 0);
GLES20.glGenBuffers(1, ebo, 0);
//Bind Objects
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo[0]);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, ebo[0]);
//Write Data
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertexBuffer.capacity() * 4, vertexBuffer, GLES20.GL_DYNAMIC_DRAW);
GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, indexBuffer.capacity() * 2, indexBuffer, GLES20.GL_STATIC_DRAW);
//Unbind objects
//GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
//GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
animateTimer = new Timer();
}
public synchronized void draw()
{
//Use Shader Program
GLES20.glUseProgram(program);
//////////////////////Configure Attribute (Core OpenGL ie: in)//////////////////////////
//Get Attribute Locations
//int attribLocationPos = GLES20.glGetAttribLocation(program, "vPosition");
//int attribLocationTex = GLES20.glGetAttribLocation(program, "TexCoords");
//Enable Vertex Attribute Array
GLES20.glEnableVertexAttribArray(0);
GLES20.glVertexAttribPointer(0, 4, GLES20.GL_FLOAT, false, 24, 0);
//Tex Coord Attribute
GLES20.glEnableVertexAttribArray(1);
GLES20.glVertexAttribPointer(1, 2, GLES20.GL_FLOAT, false, 24, 16);
//Bind Objects
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo[0]);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, ebo[0]);
//int[] i = new int[1];
//int[] j = new int[1];
//GLES20.glGetIntegerv(GLES20.GL_ARRAY_BUFFER_BINDING, i, 0);
//GLES20.glGetIntegerv(GLES20.GL_ELEMENT_ARRAY_BUFFER_BINDING, j, 0);
//System.out.println(i + " " + j);
//Set model matrix uniform to model
GLES20.glUniformMatrix4fv(GLES20.glGetUniformLocation(program, "model"), 1, false, model, 0);
GLES20.glUniformMatrix4fv(GLES20.glGetUniformLocation(program, "ortho"), 1, false, ortho, 0);
//Texture Stuff
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture[0]);
//Draw Square
GLES20.glDrawElements(GLES20.GL_TRIANGLES, order.length, GLES20.GL_UNSIGNED_SHORT, 0);
//GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
//Disable Vertex Attribute Array
GLES20.glDisableVertexAttribArray(0);
GLES20.glDisableVertexAttribArray(1);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
//GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
//Stop using program
//GLES20.glUseProgram(0);
}
public void createTextureSpriteSheet(Context context, int resourceID, int spriteWidth, int spriteHeight, int sheetWidth, int sheetHeight, int frame)
{
InputStream is = context.getResources().openRawResource(resourceID);
Bitmap bitmap;
try {
bitmap = BitmapFactory.decodeStream(is);
} finally {
try {
is.close();
} catch(IOException e) {
// Ignore.
}
}
//bitmap = BitmapFactory.decodeFile("R.raw.blobbosheet.png
ByteBuffer data = ByteBuffer.allocateDirect(bitmap.getByteCount());
data.order(ByteOrder.nativeOrder());
bitmap.copyPixelsToBuffer(data);
System.out.println("Bitmap: " + bitmap.getWidth() + " " + bitmap.getHeight());
data.position(0);
GLES20.glGenTextures(1, texture, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture[0]);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, bitmap.getWidth(), bitmap.getHeight(), 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, data);
//GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D);
spriteSheet = new SpriteSheet(sheetWidth, sheetHeight, spriteWidth, spriteHeight, 8);
float[] texCoords = spriteSheet.getSpriteCoords(frame);
for(int i = 0; i < 8; i++)
{
System.out.println("TexCoord: " + i + " is : " + texCoords[i]);
}
spriteSheet.setFrame(frame);
//Update Tex Coords
vertices[4] = texCoords[0];
vertices[5] = texCoords[1];
vertices[10] = texCoords[2];
vertices[11] = texCoords[3];
vertices[16] = texCoords[4];
vertices[17] = texCoords[5];
vertices[22] = texCoords[6];
vertices[23] = texCoords[7];
updateVBO();
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
}
public void switchSprite(int frame)
{
float[] texCoords = spriteSheet.getSpriteCoords(frame);
spriteSheet.setFrame(frame);
//Update Tex Coords
vertices[4] = texCoords[0];
vertices[5] = texCoords[1];
vertices[10] = texCoords[2];
vertices[11] = texCoords[3];
vertices[16] = texCoords[4];
vertices[17] = texCoords[5];
vertices[22] = texCoords[6];
vertices[23] = texCoords[7];
updateVBO();
}
public void nextFrame()
{
float[] texCoords = spriteSheet.nextFrame();
for(int i = 0; i < 8; i++)
{
System.out.println("TexCoord: " + i + " is : " + texCoords[i]);
}
//Update Tex Coords
vertices[4] = texCoords[0];
vertices[5] = texCoords[1];
vertices[10] = texCoords[2];
vertices[11] = texCoords[3];
vertices[16] = texCoords[4];
vertices[17] = texCoords[5];
vertices[22] = texCoords[6];
vertices[23] = texCoords[7];
updateVBO();
}
public void animate(int startFrame, int framesPerSec, final int numbOfFrames)
{
switchSprite(startFrame);
TimerTask task = new TimerTask()
{
int count = 0;
public void run()
{
nextFrame();
count++;
System.out.println("Animate Thread Going!");
if(count == numbOfFrames)
{
System.out.println("Animate Thread Canceled");
cancel();
}
}
};
animateTimer.scheduleAtFixedRate(task, 0, 1000 / framesPerSec);
}
public synchronized void updateVBO()
{
System.out.println("In updateVBO()");
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo[0]);
vertexBuffer.clear();
vertexBuffer.put(vertices).flip();
float[] test = new float[vertexBuffer.capacity()];
vertexBuffer.get(test);
for(float i : test)
{
System.out.println(i + ", ");
}
vertexBuffer.clear();
vertexBuffer.put(vertices).flip();
for(int i = 4; i < 23; i += 6)
{
System.out.println("TexCoord: " + i + " is : " + vertices[i]);
System.out.println("TexCoord: " + i + " is : " + vertices[i + 1]);
}
System.out.println(vertexBuffer.capacity() * 4 + " " + vertexBuffer.remaining());
GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, 0, vertexBuffer.capacity() * 4, vertexBuffer);
//GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertexBuffer.capacity() * 4, )
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
}
}
和我的渲染器的代码:
package com.matthew.beatclimber;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.Matrix;
import android.content.Context;
import android.util.DisplayMetrics;
import android.view.Display;
import android.app.Activity;
/**
* Created by matthew on 10/28/17.
*/
public class MyGLRenderer implements GLSurfaceView.Renderer
{
Sprite sprite;
float[] orthoProjection = new float[16];
Context context;
public MyGLRenderer(Context context)
{
this.context = context;
}
@Override
public void onSurfaceCreated(GL10 gl10, EGLConfig config) {
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
sprite = new Sprite(1080, 1704);
sprite.createTextureSpriteSheet(context, R.drawable.blobbosheet, 32, 32, 256, 32, 0);
sprite.animate(0, 2, -1);
}
@Override
public void onSurfaceChanged(GL10 gl10, int width, int height) {
GLES20.glViewport(0, 0, width, height);
Matrix.orthoM(orthoProjection, 0, 0, width, 0, height, -1, 100);
Sprite.ortho = orthoProjection;
}
@Override
public void onDrawFrame(GL10 gl10)
{
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
System.out.println("Drawing");
sprite.draw();
}
}
这里还有它转储到日志中的内容:
11-04 17:50:41.569 13651-13670/com.matthew.beatclimber A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x10 in tid 13670 (GLThread 490), pid 13651 (hew.beatclimber)
11-04 17:50:41.606 13678-13678/? A/DEBUG: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
11-04 17:50:41.606 13678-13678/? A/DEBUG: Build fingerprint: 'google/sdk_gphone_x86/generic_x86:8.1.0/OPM1.171004.001/4376136:userdebug/dev-keys'
11-04 17:50:41.606 13678-13678/? A/DEBUG: Revision: '0'
11-04 17:50:41.606 13678-13678/? A/DEBUG: ABI: 'x86'
11-04 17:50:41.606 13678-13678/? A/DEBUG: pid: 13651, tid: 13670, name: GLThread 490 >>> com.matthew.beatclimber <<<
11-04 17:50:41.606 13678-13678/? A/DEBUG: signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x10
11-04 17:50:41.606 13678-13678/? A/DEBUG: Cause: null pointer dereference
11-04 17:50:41.606 13678-13678/? A/DEBUG: eax 00000010 ebx 9eaf3be4 ecx 00000008 edx 8f4000ea
11-04 17:50:41.606 13678-13678/? A/DEBUG: esi 00000010 edi 00000000
11-04 17:50:41.606 13678-13678/? A/DEBUG: xcs 00000073 xds 0000007b xes 0000007b xfs 0000003b xss 0000007b
11-04 17:50:41.606 13678-13678/? A/DEBUG: eip ab72b33c ebp 8ff7c5c8 esp 8ff7c588 flags 00010202
11-04 17:50:41.907 13678-13678/? A/DEBUG: backtrace:
11-04 17:50:41.907 13678-13678/? A/DEBUG: #00 pc 0001a33c /system/lib/libc.so (memcpy+732)
11-04 17:50:41.907 13678-13678/? A/DEBUG: #01 pc 00021cd0 /vendor/lib/egl/libEGL_emulation.so (glUtilsPackPointerData+480)
11-04 17:50:41.907 13678-13678/? A/DEBUG: #02 pc 0003bb98 /vendor/lib/libGLESv2_enc.so ((anonymous namespace)::glVertexAttribPointerData_enc(void*, unsigned int, int, unsigned int, unsigned char, int, void*, unsigned int)+184)
11-04 17:50:41.907 13678-13678/? A/DEBUG: #03 pc 000286c4 /vendor/lib/libGLESv2_enc.so (GL2Encoder::sendVertexAttributes(int, int, bool, int)+1124)
11-04 17:50:41.907 13678-13678/? A/DEBUG: #04 pc 000167ce /vendor/lib/libGLESv2_enc.so (GL2Encoder::s_glDrawElements(void*, unsigned int, int, unsigned int, void const*)+958)
11-04 17:50:41.907 13678-13678/? A/DEBUG: #05 pc 00009c3f /vendor/lib/egl/libGLESv2_emulation.so (glDrawElements+79)
11-04 17:50:41.907 13678-13678/? A/DEBUG: #06 pc 00099c16 /system/lib/libandroid_runtime.so (android_glDrawElements__IIII(_JNIEnv*, _jobject*, int, int, int, int)+38)
11-04 17:50:41.907 13678-13678/? A/DEBUG: #07 pc 00e82a36 /system/framework/x86/boot-framework.oat (offset 0x5fc000) (android.opengl.GLES10.glClearColorx [DEDUPED]+182)
11-04 17:50:41.907 13678-13678/? A/DEBUG: #08 pc 00642032 /system/lib/libart.so (art_quick_invoke_static_stub+418)
11-04 17:50:41.907 13678-13678/? A/DEBUG: #09 pc 00116009 /system/lib/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+265)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #10 pc 0032143f /system/lib/libart.so (art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*)+335)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #11 pc 0031a6a4 /system/lib/libart.so (_ZN3art11interpreter6DoCallILb0ELb0EEEbPNS_9ArtMethodEPNS_6ThreadERNS_11ShadowFrameEPKNS_11InstructionEtPNS_6JValueE+836)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #12 pc 0062927a /system/lib/libart.so (MterpInvokeStatic+282)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #13 pc 00633021 /system/lib/libart.so (artMterpAsmInstructionStart+14497)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #14 pc 002f392b /system/lib/libart.so (art::interpreter::Execute(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue, bool)+539)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #15 pc 002fa1e7 /system/lib/libart.so (art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame*, art::JValue*)+231)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #16 pc 0031a68a /system/lib/libart.so (_ZN3art11interpreter6DoCallILb0ELb0EEEbPNS_9ArtMethodEPNS_6ThreadERNS_11ShadowFrameEPKNS_11InstructionEtPNS_6JValueE+810)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #17 pc 00627a44 /system/lib/libart.so (MterpInvokeVirtual+756)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #18 pc 00632ea1 /system/lib/libart.so (artMterpAsmInstructionStart+14113)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #19 pc 002f392b /system/lib/libart.so (art::interpreter::Execute(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue, bool)+539)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #20 pc 002fa1e7 /system/lib/libart.so (art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame*, art::JValue*)+231)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #21 pc 0031a68a /system/lib/libart.so (_ZN3art11interpreter6DoCallILb0ELb0EEEbPNS_9ArtMethodEPNS_6ThreadERNS_11ShadowFrameEPKNS_11InstructionEtPNS_6JValueE+810)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #22 pc 00628c0f /system/lib/libart.so (MterpInvokeInterface+1647)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #23 pc 006330a1 /system/lib/libart.so (artMterpAsmInstructionStart+14625)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #24 pc 002f392b /system/lib/libart.so (art::interpreter::Execute(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue, bool)+539)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #25 pc 002fa1e7 /system/lib/libart.so (art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame*, art::JValue*)+231)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #26 pc 0031a68a /system/lib/libart.so (_ZN3art11interpreter6DoCallILb0ELb0EEEbPNS_9ArtMethodEPNS_6ThreadERNS_11ShadowFrameEPKNS_11InstructionEtPNS_6JValueE+810)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #27 pc 0062905c /system/lib/libart.so (MterpInvokeDirect+428)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #28 pc 00632fa1 /system/lib/libart.so (artMterpAsmInstructionStart+14369)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #29 pc 002f392b /system/lib/libart.so (art::interpreter::Execute(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue, bool)+539)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #30 pc 002fa0cb /system/lib/libart.so (art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame*)+139)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #31 pc 006175ef /system/lib/libart.so (artQuickToInterpreterBridge+1311)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #32 pc 00647f2d /system/lib/libart.so (art_quick_to_interpreter_bridge+77)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #33 pc 00641e62 /system/lib/libart.so (art_quick_invoke_stub+338)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #34 pc 00115fdf /system/lib/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+223)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #35 pc 00544aeb /system/lib/libart.so (art::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, art::ArgArray*, art::JValue*, char const*)+91)
11-04 17:50:41.909 13678-13678/? A/DEBUG: #36 pc 00545fb8 /system/lib/libart.so (art::InvokeVirtualOrInterfaceWithJValues(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jmethodID*, jvalue*)+744)
11-04 17:50:41.909 13678-13678/? A/DEBUG: #37 pc 0057512f /system/lib/libart.so (art::Thread::CreateCallback(void*)+1487)
11-04 17:50:41.909 13678-13678/? A/DEBUG: #38 pc 00071445 /system/lib/libc.so (__pthread_start(void*)+53)
11-04 17:50:41.909 13678-13678/? A/DEBUG: #39 pc 000205db /system/lib/libc.so (__start_thread+75)
11-04 17:50:41.909 13678-13678/? A/DEBUG: #40 pc 0001ec16 /system/lib/libc.so (__bionic_clone+70)
11-04 17:50:42.190 1484-1484/? E//system/bin/tombstoned: Tombstone written to: /data/tombstones/tombstone_04
操作顺序有点混乱。设置顶点属性指针时,必须先绑定缓冲区,然后设置指针。
public synchronized void draw()
{
//Use Shader Program
GLES20.glUseProgram(program);
//Enable Vertex Attribute Array
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo[0]);
GLES20.glEnableVertexAttribArray(0);
GLES20.glVertexAttribPointer(0, 4, GLES20.GL_FLOAT, false, 24, 0);
//Tex Coord Attribute
GLES20.glEnableVertexAttribArray(1);
GLES20.glVertexAttribPointer(1, 2, GLES20.GL_FLOAT, false, 24, 16);
//Bind Index Buffer
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, ebo[0]);
...
}
添加缓冲区解除绑定代码时会出现错误,因为在其他情况下,正确的缓冲区仍然从构造函数绑定。