英文:
How to implement GLSurfaceView.EGLContextFactory in Android application to create an OpenGL ES context so that we can check the OpenGL ES version?
问题
我的问题是:如何通过实现GLSurfaceView.EGLContextFactory
来打印物理设备支持的最大OpenGL ES版本
?
我正在按照这里的教程设置Android应用程序中使用OpenGL ES的环境。
我的代码结构与教程中的要求完全相同:
-
我的主要活动类设置如下:
class MainActivity: Activity()
,其中Activity
来自android.app.Activity
包。 -
在
MainActivity
内部,有一个来自android.opengl.GLSurfaceView
包的GLSurfaceView
实例。 -
创建了一个名为
MyGLSurfaceView
的类,用于实现或继承自GLSurfaceView
。在其中,它有一个GLSurfaceView.Renderer
的实例。 -
创建了一个名为
MyGLRenderer
的类,用于实现或继承自GLSurfaceView.Renderer
。 -
在与所需的
OpenGL ES
类位于同一包中创建了一个名为Model
的类,以创建环境。
因此,Model
类需要访问来自android.content.Context
包的Android Context
,以执行一些工作,如访问文件。
在这里中告诉我要编写:
private const val EGL_CONTEXT_CLIENT_VERSION = 0x3098
private const val glVersion = 3.0
private class ContextFactory : GLSurfaceView.EGLContextFactory {
override fun createContext(egl: EGL10, display: EGLDisplay, eglConfig: EGLConfig):
EGLContext {
Log.w(TAG, "creating OpenGL ES $glVersion context")
return egl.eglCreateContext(
display,
eglConfig,
EGL10.EGL_NO_CONTEXT,
intArrayOf(EGL_CONTEXT_CLIENT_VERSION, glVersion.toInt(), EGL10.EGL_NONE)
) // returns null if 3.0 is not supported
}
}
但是,我仍然不明白如何实现这段代码。因为我已经在MyGLSurfaceView
的构造函数中创建了OpenGL ES
上下文,就像这样:
init {
// 创建OpenGL ES 2.0上下文
setEGLContextClientVersion(2)
renderer = MyGLRenderer(context)
// 为GLSurfaceView设置渲染器
setRenderer(renderer)
}
文档中说,我必须先创建OpenGL ES
上下文,然后再读取设备支持的版本,比如它能运行的最大版本。
问题是GLSurfaceView.EGLContextFactory
是一个静态接口
,这意味着它是一个全局或共享对象,需要首先实现它,即从该类继承并覆盖createContext()
方法和destroyContext()
方法。
我应该如何实现GLSurfaceView.EGLContextFactory
?我应该将其声明为MyGLSurfaceView
的嵌套类吗?
我尝试过像这样创建一个名为ContextFactory
的嵌套类,它实现了GLSurfaceView.EGLContextFactory
接口:
private const val EGL_CONTEXT_CLIENT_VERSION = 0x3098
private const val glVersion = 3.0
const val TAG = "ContextFactory"
class MyGLSurfaceView(context: Context) : GLSurfaceView(context) {
private val renderer: MyGLRenderer
init {
// 创建OpenGL ES 2.0上下文
setEGLContextClientVersion(2)
renderer = MyGLRenderer(context)
//renderMode = GLSurfaceView.RENDERMODE_WHEN_DIRTY
// 为GLSurfaceView设置渲染器
setRenderer(renderer)
glGetString(glVersion.toInt())
//我假设`ContextFactory`已经被实例化,因为它实现了`静态接口`,所以我不需要在构造函数中创建另一个实例。所以,我直接尝试读取我的设备支持的`最大OpenGL ES版本`。
}
}
但是,在logcat
中,在warn
类别中显示:
Rcall to OpenGL ES API with no current context (logged once per thread)
Reading a NULL string not supported here.
MyGLSurfaceView
类看起来像这样:
import android.content.Context
import android.opengl.GLES20.glGetString
import android.opengl.GLSurfaceView
import android.util.Log
import javax.microedition.khronos.egl.EGL10
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.egl.EGLContext
import javax.microedition.khronos.egl.EGLDisplay
private const val EGL_CONTEXT_CLIENT_VERSION = 0x3098
private const val glVersion = 3.0
const val TAG = "ContextFactory"
class MyGLSurfaceView(context: Context) : GLSurfaceView(context) {
private val renderer: MyGLRenderer
init {
setEGLContextClientVersion(2)
renderer = MyGLRenderer(context)
setRenderer(renderer)
glGetString(glVersion.toInt())
}
private class ContextFactory : GLSurfaceView.EGLContextFactory {
override fun createContext(egl: EGL10?, display: EGLDisplay?, eglConfig:
EGLConfig?): EGLContext? {
Log.w(TAG, "creating OpenGL ES $glVersion context")
if (egl != null) {
return egl.eglCreateContext(
display,
eglConfig,
EGL10.EGL_NO_CONTEXT,
intArrayOf(EGL_CONTEXT_CLIENT_VERSION, glVersion.toInt(),
EGL10.EGL_NONE)
)
}
return null
}
override fun destroyContext(p0: EGL10?, p1: EGLDisplay?, p2: EGLContext?) {
TODO("Not yet implemented")
}
}
}
英文:
My question is How could I print the maximum OpenGL ES version
supported by a physical device by implementing GLSurfaceView.EGLContextFactory
?
I was following a tutorial here on how to setup
the environment in an Android application using OpenGL ES.
The way I structure my code is exactly like the tutorial tells me.
-
My Main Activity is setup like this
class MainActivity: Activity()
wherebyActivity
is
fromandroid.app.Activity
package. -
Inside
MainActivity
there is an instance ofGLSurfaceView
fromandroid.opengl.GLSurfaceView
package. -
A class named
MyGLSurfaceView
is created to implement or inherits fromGLSurfaceView
.
Inside it, it has an instance ofGLSurfaceView.Renderer
. -
A class named
MyGLRenderer
is created to implement or inherits fromGLSurfaceView.Renderer
. -
A class named
Model
is created in the same package with the requiredOpenGL ES
class to create the environment.
so, Model
class needs to access Android Context
from android.content.Context
package to do some work, like to access a file.
In here, it tells me to write:
private const val EGL_CONTEXT_CLIENT_VERSION = 0x3098
private const val glVersion = 3.0
private class ContextFactory : GLSurfaceView.EGLContextFactory {
override fun createContext(egl: EGL10, display: EGLDisplay, eglConfig: EGLConfig):
EGLContext {
Log.w(TAG, "creating OpenGL ES $glVersion context")
return egl.eglCreateContext(
display,
eglConfig,
EGL10.EGL_NO_CONTEXT,
intArrayOf(EGL_CONTEXT_CLIENT_VERSION, glVersion.toInt(), EGL10.EGL_NONE)
) // returns null if 3.0 is not supported
}
}
But, I still do not understand how to implement this code. Because, I already created OpenGL ES
context inside the constructor
of MyGLSurfaceView
like so:
init {
// Create an OpenGL ES 2.0 context
setEGLContextClientVersion(2)
renderer = MyGLRenderer(context)
// Set the Renderer for drawing on the GLSurfaceView
setRenderer(renderer)
}
It says there, in the documentation that I must create the OpenGL ES
context first before
reading the version that the device can support, like the maximum version it can run.
The problem is GLSurfaceView.EGLContextFactory
is a static interface
which means it is a
global
or shared
object and need to be implemented first, i.e inherits from that class and overriding the createContext()
method and destroyContext()
.
How should I implement GLSurfaceView.EGLContextFactory
? should I declare it as nested class of MyGLSurfaceView
.
I have tried like this by creating a nested class called ContextFactory
which implements the interface GLSurfaceView.EGLContextFactory
:
private const val EGL_CONTEXT_CLIENT_VERSION=0x3098
private const val glVersion=3.0
const val TAG="ContextFactory"
class MyGLSurfaceView(context: Context):GLSurfaceView(context) {
private val renderer: MyGLRenderer
init {
// Create an OpenGL ES 2.0 context
setEGLContextClientVersion(2)
renderer = MyGLRenderer(context)
//renderMode = GLSurfaceView.RENDERMODE_WHEN_DIRTY
// Set the Renderer for drawing on the GLSurfaceView
setRenderer(renderer)
glGetString(glVersion.toInt())
//I am assuming `ContextFactory` has already been instantiated since it implements
//a `static interface` so, I do not need to create another instance of it here in
// the constructor. So, I just directly trying to read `maximum OpenGL ES version`
//supported in my device.
}
but in the logcat
inside warn
category it says:
Rcall to OpenGL ES API with no current context (logged once per thread)
Reading a NULL string not supported here.
MyGLSurfaceView
class looks like this:
import android.content.Context
import android.opengl.GLES20.glGetString
import android.opengl.GLSurfaceView
import android.util.Log
import javax.microedition.khronos.egl.EGL10
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.egl.EGLContext
import javax.microedition.khronos.egl.EGLDisplay
private const val EGL_CONTEXT_CLIENT_VERSION=0x3098
private const val glVersion=3.0
const val TAG="ContextFactory"
class MyGLSurfaceView(context: Context):GLSurfaceView(context) {
private val renderer: MyGLRenderer
init {
setEGLContextClientVersion(2)
renderer = MyGLRenderer(context)
setRenderer(renderer)
glGetString(glVersion.toInt())
}
private class ContextFactory: GLSurfaceView.EGLContextFactory{
override fun createContext(egl: EGL10?, display: EGLDisplay?, eglConfig:
EGLConfig?): EGLContext? {
Log.w(TAG, "creating OpenGL ES $glVersion context")
if (egl != null) {
return egl.eglCreateContext(
display,
eglConfig,
EGL10.EGL_NO_CONTEXT,
intArrayOf(EGL_CONTEXT_CLIENT_VERSION, glVersion.toInt(),
EGL10.EGL_NONE)
)
}
return null
}
override fun destroyContext(p0: EGL10?, p1: EGLDisplay?, p2: EGLContext?) {
TODO("Not yet implemented")
}
}
}
答案1
得分: 0
首先创建一个继承自 GLSurfaceView.EGLContextFactory
接口的类,如下所示:
import android.opengl.GLSurfaceView
import android.util.Log
import javax.microedition.khronos.egl.EGL10 //确保从 javax 导入而不是 android.opengles.* 包
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.egl.EGLContext
import javax.microedition.khronos.egl.EGLDisplay
private const val EGL_CONTEXT_CLIENT_VERSION = 0x3098
private const val glVersion = 3.3
class ContextFactory : GLSurfaceView.EGLContextFactory {
override fun createContext(egl: EGL10, display: EGLDisplay, eglConfig: EGLConfig): EGLContext {
// 如果不支持3.0,则返回null
Log.w("OpenGl version", "creating OpenGL ES $glVersion context")
return egl.eglCreateContext(
display,
eglConfig,
EGL10.EGL_NO_CONTEXT,
intArrayOf(EGL_CONTEXT_CLIENT_VERSION, glVersion.toInt(), EGL10.EGL_NONE)
)
}
override fun destroyContext(egl: EGL10, display: EGLDisplay, context: EGLContext) {
egl.eglDestroyContext(display, context)
}
}
在 MyGLSurfaceView
类中:
class MyGLSurfaceView(context: Context) : GLSurfaceView(context) {
private val renderer: MyGLRenderer
private var previousX: Float = 0f
private var previousY: Float = 0f
init {
//setEGLContextClientVersion(2)
setEGLContextFactory(ContextFactory()) //需要使用这个函数而不是上面的一个
renderer = MyGLRenderer(context)
setRenderer(renderer)
}
}
如果程序崩溃,这意味着它不支持ContextFactory
类中指定的当前版本。如果它可以平稳运行,那么它支持当前指定的版本。
还有一点,GLSurfaceView.EGLContextFactory
其实是一个普通接口,不是我之前认为的 static
或 global
接口。
英文:
First create a class that inherits from GLSurfaceView.EGLContextFactory
interface like so:
import android.opengl.GLSurfaceView
import android.util.Log
import javax.microedition.khronos.egl.EGL10 //make sure to import from
//javax not from `android.opengles.*` package
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.egl.EGLContext
import javax.microedition.khronos.egl.EGLDisplay
private const val EGL_CONTEXT_CLIENT_VERSION = 0x3098
private const val glVersion = 3.3
class ContextFactory : GLSurfaceView.EGLContextFactory {
override fun createContext(egl: EGL10, display: EGLDisplay, eglConfig:
EGLConfig): EGLContext {
// returns null if 3.0 is not supported
Log.w("OpenGl version", "creating OpenGL ES $glVersion context")
return egl.eglCreateContext(
display,
eglConfig,
EGL10.EGL_NO_CONTEXT,
intArrayOf(EGL_CONTEXT_CLIENT_VERSION, glVersion.toInt(),
EGL10.EGL_NONE)
) //
}
override fun destroyContext(egl: EGL10, display: EGLDisplay, context:
EGLContext) {
egl.eglDestroyContext(display, context)
}
}
in MyGLSurfaceView
class:
class MyGLSurfaceView(context: Context) : GLSurfaceView(context) {
private val renderer: MyGLRenderer
private var previousX: Float = 0f
private var previousY: Float = 0f
init {
//setEGLContextClientVersion(2)
setEGLContextFactory(ContextFactory()) //need to use this function
//instead of the above one
renderer = MyGLRenderer(context)
setRenderer(renderer)
}
if the program crashes, it means, it doesn't support the current version that was specified in the ContextFactory
class. If it can run smoothly, it means it supports the currently specified version.
One more thing GLSurfaceView.EGLContextFactory
is actually a normal interface, not a static
or global
interface when I thought previously.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论