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()
whereby Activity
is
from android.app.Activity
package.
Inside MainActivity
there is an instance of GLSurfaceView
from android.opengl.GLSurfaceView
package.
A class named MyGLSurfaceView
is created to implement or inherits from GLSurfaceView
.
Inside it, it has an instance of GLSurfaceView.Renderer
.
A class named MyGLRenderer
is created to implement or inherits from GLSurfaceView.Renderer
.
A class named Model
is created in the same package with the required OpenGL 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")
}
}
}
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.