Reputation: 1230
I have an android app that uses a GlSurfaceView
to render a 3D fullscreen scene inside a fragment. I have noticed in the profiler, that the GlSurfaceView
is actually running twice (in two threads), hogging resources and tanking the FPS. I have confirmed the issue by rendering the same OpenGL scene (using the same Renderer
implementation) to a live wallpaper and profiling it, which only runs it once.
Am I doing anything wrong here?
The code is as follows:
MySurfaceView
class MySurfaceView(ctx: Context): GLSurfaceView(ctx)
{
init
{
setEGLContextClientVersion(3)
preserveEGLContextOnPause = true
setRenderer( /* instantiating the renderer class */ )
}
}
OpenGLFragment
class OpenGLFragment: Fragment()
{
private lateinit var glView: GLSurfaceView
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View?
{
this.glView = MySurfaceView(this.activity)
return this.glView
}
}
MainActivity
class MainActivity : FragmentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val fm = supportFragmentManager
for (i in 0 until fm.getBackStackEntryCount()) {
fm.popBackStack()
}
supportFragmentManager.beginTransaction().add(R.id.main_container, OpenGLFragment())
.addToBackStack(null).commit()
}
}
Upvotes: 5
Views: 670
Reputation: 891
There are a few things that you should check:
setRenderer
once in the lifecycle of the GLSurfaceView. See GLSurfaceView.setRenderer.glView.onPause()
and glView.onResume()
to stop rendering, if the view is in background? See GLSurfaceView life-cycle.transaction.replace()
instead of transaction.add()
. You may end up having multiple OpenGlFragments
active at the same time.Upvotes: 2
Reputation: 3260
It seems that you are trying to add fragment instead of replacing the container.
Here is my code:
supportFragmentManager.beginTransaction()
.replace(R.id.main_container, GLFragment())
.addToBackStack(null)
.commit()
Fragment(using your code does not compile with this.activity
)
class GLFragment : Fragment() {
private lateinit var glView: GLSurfaceView
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
this.glView = MySurfaceView(requireActivity())
return this.glView
}
}
GLView:
class MySurfaceView constructor(context: Context) : GLSurfaceView(context) {
init {
setEGLContextClientVersion(2) // I have used 2 because running on emulator
preserveEGLContextOnPause = true
setRenderer(ClearRenderer())
}
}
internal class ClearRenderer : GLSurfaceView.Renderer {
override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
}
override fun onSurfaceChanged(gl: GL10, w: Int, h: Int) {
gl.glViewport(0, 0, w, h)
}
override fun onDrawFrame(gl: GL10) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT or GL10.GL_DEPTH_BUFFER_BIT)
}
}
and here is profiler screenshot:
So to recapitulate replace the add
with replace
, replace the this.activity
with requireActivity()
the requireActivity()
also does not return null and it is guaranteed.
Hope it helps!!!
Upvotes: 3