[英]“call to OpenGL ES API with no current context” while using imageloader in android
[英]Android NDK OpenGL glDeleteTextures causes error: call to OpenGL ES API with no current context
我正在使用一个可从外部摄像机渲染视频的android应用程序。 当我们在ndk中与摄像机进行通信时,视频帧通过NDK层中的opengl渲染到屏幕上,并且速度更快。 我没有编写代码,因为它来自第三方(相机的开发者),并且他们在MyGLSurfaceView中实现了surfaceDestroyed方法,如下所示:
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.d(TAG, "Inside GL surfaceDestroyed" );
// TODO Auto-generated method stub
myRenderer.surfaceDestroyed(); //call this to clean up the renderer.
super.surfaceDestroyed(holder);
}
myRenderer在哪里
myRenderer = new MyGLRenderer(mContext);
现在,在渲染器中编写了以下代码:
public class MyGLRenderer implements Renderer {
public void surfaceDestroyed()
{
Log.d(TAG, "Inside surfaceDestroyed" );
/* Note: As per doc, GLSurfaceView kills the renderer and deletes any textures associated with it.
* However, it does not clean up textures created in NDK. So, we need to do this explicitly.
*/
mGLAdapter.destroyGlTexturesJni(myRenderer);
}
请注意,在NDK中创建的纹理将不会被清除。 这是真的? 我问的原因是从此调用中收到以下错误:
01-19 12:01:19.715: E/libEGL(27208): call to OpenGL ES API with no current context (logged once per thread)
我已经放置了一些调试语句,以找出错误在NDK代码中的确切位置,并发现该错误位于某个名为ImageRender(调用Clean)的类的析构函数中,这是触发该错误的行:
void ImageRender::Clean()
{
// destruct texture
if (m_unTexture != -1)
glDeleteTextures( 1,&m_unTexture );
....
看起来他们在这里设置了m_unTexture(这是gl上下文吗?):
int ImageRender::InitTexture( const int nWidth, const int nHeight )
{
// Enable texture 2D first.
glEnable( GL_TEXTURE_2D );
// create texture
glGenTextures( 1,&m_unTexture );
// bind texture to target.
glBindTexture( GL_TEXTURE_2D,m_unTexture );
...
如果他们检查glGetError并遍历代码,如果他们没有得到GL_NO_ERROR,则将其设置为-1,这样他们就知道它是无效的。
好的,所以我的问题是我是否真的需要清理在NDK中创建的纹理,如果是的话,如何才能没有看到的错误。 我尝试使用以下方式致电:
//from MyGLSurfaceView
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.d(TAG, "Inside GL surfaceDestroyed" );
// TODO Auto-generated method stub
queueEvent(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
myRenderer.surfaceDestroyed(); //call this to clean up the renderer.
}
});
super.surfaceDestroyed(holder);
}
以确保渲染器在opengl线程上被调用,但是存在相同的错误。
有什么建议么? 顺便说一句,如果我只是简单地不调用此方法,那么代码似乎可以正常工作,虽然我已经做了一段时间了,但是我遇到的问题是,当我启动一个使用opengl框架的活动时,该活动将被初始化为先前的opengl活动。 似乎仅在某些时间,重新接通此电话可以解决问题。
您不能在UI线程上调用myRenderer.surfaceDestroyed,因为它没有OpenGL上下文。 您必须使用queueEvent在OpenGL线程上运行surfaceDestroyed。 您使用Runnable实现的问题如下-queueEvent是非阻塞的。 因此,最有可能在调用myRenderer.surfaceDestroyed()和GL上下文被销毁之前,调用任何本机代码之前调用super.surfaceDestroyed(holder)。
不知道这是否行得通,但是尝试在queueEvent调用之后阻止UI线程,然后等待Runnable完成其工作。 像这样:
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.d(TAG, "Inside GL surfaceDestroyed" );
queueEvent(new Runnable() {
@Override
public void run() {
myRenderer.surfaceDestroyed();
synchronized (myRenderer) {
myRenderer.notify();
}
}
});
synchronized (myRenderer)
{
try { myRenderer.wait(100); }
catch (InterruptedException e) { }
}
super.surfaceDestroyed(holder);
}
这将最多阻止UI线程100毫秒,从而允许您的本机代码清理上下文。 如果需要,增加100到更多。
在最坏的情况下-只是不要自己释放GL资源。 让GL上下文为您释放它们。
回答另一个问题:m_unTexture是GL纹理名称(不是GL上下文)。 -1值似乎只是纹理名称的默认初始化值,如果glGenTextures()无法为纹理分配新名称,该值将不会被触及。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.