作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在后台线程中加载纹理,然后将位图发送到 GL 线程(通过 GLSurfaceView.queueEvent(...))以将其上传到显卡。为了防止每次图像加载后进行垃圾收集,我重复使用一个具有二维幂的位图来发送纹理以打开 gl。
这就是问题所在,这个位图有时会被覆盖,因为工作线程和 GL 线程互相争斗。据我了解,不可能在一个线程(工作线程)中获取锁并在另一个线程(GL)中解锁它。所以我提出了这样的解决方案(我的线程是 HandlerThread):
public boolean handleMessage(Message msg) {
switch(msg.what) {
case MESSAGE_FROM_MAIN_THREAD:
m_Lock.lock();
loadTextureFromAssets(msg.obj.toString(), msg.arg1);
break;
case MESSAGE_FROM_GL_THREAD:
m_Lock.unlock();
break;
}
return true;
}
m_Lock 是一个 ReentrantLock。但这仍然不起作用,有时纹理会重复(或被下一个纹理部分覆盖)。看起来解锁是按 LIFO 顺序...
除了为每个加载的纹理创建一个新的位图并导致GC之外,还有什么想法吗? ...几乎所有情况都可以通过使用两个位图来加载纹理并在它们之间切换来解决,但这并不是 100% 正确。我想通过适当的线程同步来解决这个问题。
最佳答案
所以经过一天多的时间我明白了这一点。我使用了一个信号量,最初设置为 1 并在 LoadTextureFromAssets(...)
之前获取它并在 Runnable
结束时释放它发送到GL上传纹理:
public boolean handleMessage(Message msg) {
switch(msg.what) {
case MESSAGE_FROM_MAIN_THREAD:
try {
m_Semaphore.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
loadTextureFromAssets(msg.obj.toString(), msg.arg1);
break;
case MESSAGE_FROM_GL_THREAD:
// not needed for now
break;
}
return true;
}
并设置上传方法:
// load the image from assests and then...
m_GLSurface.queueEvent(new Runnable() {
public void run() {
gl.glBindTexture(GL10.GL_TEXTURE_2D, m_TexId);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
if (gl instanceof GL11) {
// GL 1.1 has auto mip-map generation
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR_MIPMAP_LINEAR);
gl.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_GENERATE_MIPMAP, GL11.GL_TRUE);
}
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_RGBA, m_TexBitmap, 0);
m_Semaphore.release();
}
});
这是100%正确的方法吗?
关于java - android opengl纹理在后台线程中加载被覆盖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6828448/
我是一名优秀的程序员,十分优秀!