[置顶] APP移植到小米Pad上的Crash分析

最近APP计划适配小米Pad,直接拿线上的code build,发现启动时CRASH,而且是必现的。线上code我们都发布了很多个版本了,怎么会有这种问题呢?

CRASH问题

Eclipse看logcat输出,最终定位到OpenGL的一次draw call函数上:

gl.glColor4f(bodyColor4f[0], bodyColor4f[1], bodyColor4f[2], bodyColor4f[3]);
	// set vertices
	gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVerticesBuffer);
	gl.glDisable(GL10.GL_TEXTURE_2D);
	// draw
	gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, CIRCLE_VERTEX_SIZE);
	gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glColor4f(1, 1, 1, 1);
问题发生在glDrawArrays函数处。 这段code是绘制一处半透明的圆圈。

问题分析

所有手机上运行都没问题,唯独小米Pad,因此猜想:这段代码一定没有问题,只不过不够严谨。进一步怀疑是OpenGL状态管理的不严谨

进一步分析:这段代码使用颜色数组模式绘制一个圆,因此glDrawArrays前禁掉了GL_TEXTURE_2D,绘制完成后开启GL_TEXTURE_2D。因此将怀疑的范围进一步缩小到顶点数组的模式状态。

glDrawArrays时候,虽然禁掉了GL_TEXTURE_2D,但是GL_TEXTURE_COORD_ARRAY 还处于激活状态。这段代码通过颜色模式绘制圆,glVertexPointer只上传了顶点的位置和颜色数据,但是GL_COLOR_ARRAY和GL_VERTEX_ARRAY,GL_TEXTURE_COORD_ARRAY都处于激活状态,GL 如果检查不够严格(没有考虑当前GL_TEXTURE_2D是否激活),仍然按三个状态去取每个顶点的位置、颜色、纹理数据,此时就导致显存Buffer的越界,从而导致CRASH。

验证分析

在glDrawArrays前显示禁掉顶点纹理坐标数组,绘制完成后开启。

gl.glColor4f(bodyColor4f[0], bodyColor4f[1], bodyColor4f[2], bodyColor4f[3]);
	// set vertices
	gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVerticesBuffer);
	gl.glDisable(GL10.GL_TEXTURE_2D);	
	gl.glDisable(GL_TEXTURE_COORD_ARRAY);		// dizuo open
	// draw
	gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, CIRCLE_VERTEX_SIZE);
	gl.glEnable(GL10.GL_TEXTURE_2D);
	gl.glEnable(GL_TEXTURE_COORD_ARRAY);		// dizuo close
gl.glColor4f(1, 1, 1, 1);
再次Build,运行OK。 跟之前分析的完全一致。。

进一步反思:

手机上为何没有CRASH?

手机上对这种不严谨行为做法:OpenGL取顶点数据的时候,结合了当前GL_TEXTURE_2D的状态,纹理没有激活就不取纹理顶点数据,不管glVertexPointer到底实际是否传了纹理数据。。。

因此,OpenGL开发还是要显式管理状态。否则一些莫名其妙地CRASH就不请自来了。。。


更多OpenGL常见错误总结:http://blog.csdn.net/ryfdizuo/article/details/9961143


你可能感兴趣的:(android,Crash,适配,OpenGL,小米Pad)