从GLSurfaceView转换到TextureView(通过GLTextureView)

24

当Android 4.0(冰淇淋三明治)发布时,SDK中引入了一个新的视图,即TextureView。在文档中,它说TextureView可以用于显示OpenGL场景的内容。

如果你想知道如何实现这一点,可以参考下面的链接:

https://groups.google.com/forum/?fromgroups=#!topic/android-developers/U5RXFGpAHPE

但是我只想用TextureView替换GLSurfaceView,并保持我的其他代码不变,以获得TextureView的优势。


3
http://source.android.com/devices/graphics/architecture.html 介绍了 GLSurfaceView 和 TextureView 在系统层面上的比较以及它们之间的权衡。FWIW. - fadden
4个回答

36

答案:

1)从GLSurfaceView的源代码开始,将文件命名为GLTextureView.java。

2)更改标题为:GLTextureView extends TextureView implements SurfaceTextureListener

3)将构造函数重命名为GLTextureView。删除init()方法中的代码。

4)组织import语句。始终选择非GLSurfaceView选项。

5)查找每个SurfaceHolder实例,并将其更改为SurfaceTexture。

6)为SurfaceTextureListener添加未实现的方法,每个方法应如下所示:

  • onSurfaceTextureAvailable - surfaceCreated(surface)
  • onSurfaceTextureDestroyed - surfaceDestroyed(surface),(返回true)
  • onSurfaceTextureSizeChanged - surfaceChanged(surface, 0, width, height)
  • onSurfaceTextureUpdated - requestRender()

7)应该有一行调用getHolder()的代码,将其更改为getSurfaceTexture()。

8)在init()方法中,加入以下行:setSurfaceTextureListener(this)

然后添加一个OnLayoutChangeListener并使其调用surfaceChanged(getSurfaceTexture(), 0, right - left, bottom - top)

这样你就能够用GLTextureView替换你的GLSurfaceView代码,获得GLTextureView的好处。同时,请确保你的应用程序支持硬件加速,并且你的Renderer扩展GLTextureView.Renderer。


补充Robin和William的回答:当您想将SurfaceView转换为TextureView时,此方法适用于所有情况。 - Edison
2
能否提供一个示例?我找到了这个:https://github.com/eaglesakura/gltextureview/blob/master/GLTextureView/src/com/eaglesakura/view/GLTextureView.java 这是否类似于您所描述的方法? - Martijn Mellens
2
请注意,尽管此答案有效,但您不想执行第5步的最后一步,即onSurfaceTextureUpdated - requestRender()。有了这行代码,即使将rendermode设置为RENDERMODE_WHEN_DIRTY,onDrawFrame也会被连续调用。如果没有它,RENDERMODE_WHEN_DIRTY的行为就像应该的那样。 - iTwenty
@William Goodalte,您能否请看一下这个帖子? http://stackoverflow.com/questions/32482565/replace-glsurfaceview-with-textureview-android - Kaidul
在某些 Android 版本上,这将以尽可能快的速度绘制 - >1000fps!为了限制帧率,请使用 RENDERMODE_DIRTY 并使用 Choreographer 调用 requestRender()。 - Learn OpenGL ES
  1. 找到每个SurfaceHolder的实例并将其更改为SurfaceTexture - 我不理解这个阶段。例如,我有一个扩展的SurfaceView用于流式传输,并且它有许多SurfaceHolder的设置。我如何将它们应用于SurfaceTexture?
- Eugene Alexeev

14

太好了!

对Goodale先生的精彩回答作出一点微小的补充:

我认为GLSurfaceView的4.1.1版本已经被修改,以避免在零宽度/高度的表面上进行渲染。并且似乎没有一个不必要的onSurfaceTextureChanged通知紧跟在onSurfaceTextureAvailable后面。

如果您使用4.1.1源代码开始编写程序,则onSurfaceTextureAvailable应该以下列方式呈现:

public void onSurfaceTextureAvailable(SurfaceTexture surface, int width,
        int height) 
{
    this.surfaceCreated(surface);
    this.surfaceChanged(surface, 0,width,height);
}

除此之外,我只用了不到五分钟就可以正常运行!谢谢。


5

感谢Goodale先生和Davies先生的回答!

我有一些关于将GLSurfaceView转换为GLTextureView的额外内容。

第一点是关于渲染模式。如此处所述,只需在onSurfaceTextureUpdated中删除requestRender()调用即可。

第二个问题是关于
mGLESVersion = SystemProperties.getInt("ro.opengles.version", ConfigurationInfo.GL_ES_VERSION_UNDEFINED); 只需使用链接,但需要Context来执行context.getClassLoader(); 您可以从init()中调用getInt的反射版本,并将结果保存在静态字段sGLESVersion中: sGLESVersion = getInt(getContext(), "ro.opengles.version",ConfigurationInfo.GL_ES_VERSION_UNDEFINED);

最后一个最简单的更改是关于EGLLogWrapper.getErrorString(error)。 只需从EGLLogWrapper源代码中复制getErrorString即可。

请查看我将GLSurfaceView转换为GLTextureView的最终版本,该版本位于GitHub Gist上。


我在Android 5.0上尝试了这个(使用compileSdkVersion 21)。如果我尝试使GLTextureView透明,它会崩溃-我调用了setEGLConfigChooser(8, 8, 8, 8, 16, 0); and setOpaque(false)。我应该在gradle中尝试您的gist时使用特定的compileSdkVersion吗? - kiranpradeep
值得注意的是,您可以使用以下代码而无需反射来完成此操作:final ActivityManager activityManager = (ActivityManager) c.getSystemService(Context.ACTIVITY_SERVICE); final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo(); sGLESVersion = configurationInfo.reqGlEsVersion; - Cara Esten Hurtle
我认为这只是因为找不到配置文件。尝试使用setEGLConfigChooser(8, 8, 8, 8, 24, 0); - AndreyICE

4
如果您想要复制/粘贴一个准备好的类,我在这里写了一个:GLTextureView。 您可以像使用GLSurfaceView一样调用setRenderer(GLSurfaceView.Renderer)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接