GLRenderer


class GLRenderer


Class responsible for coordination of requests to render into surfaces using OpenGL. This creates a backing thread to handle EGL dependencies and draw leveraging OpenGL across multiple android.view.Surface instances that can be attached and detached throughout the lifecycle of an application. Usage of this class is recommended to be done on the UI thread.

Summary

Nested types

Callbacks invoked when the GL dependencies are created and destroyed.

Interface used for creating an EGLSurface with a user defined configuration from the provided surface as well as a callback used to render content into the surface for a given frame

Handle to a android.view.Surface that is given to GLRenderer to handle rendering.

Public constructors

GLRenderer(
    eglSpecFactory: () -> EGLSpec,
    eglConfigFactory: EGLManager.() -> EGLConfig
)

Public functions

GLRenderer.RenderTarget
attach(surfaceView: SurfaceView, renderer: GLRenderer.RenderCallback)

Adds the android.view.Surface provided by the given SurfaceView to be managed by the backing thread.

GLRenderer.RenderTarget
attach(textureView: TextureView, renderer: GLRenderer.RenderCallback)

Adds the android.view.Surface provided by the given TextureView to be managed by the backing thread.

GLRenderer.RenderTarget
attach(
    surface: Surface,
    width: Int,
    height: Int,
    renderer: GLRenderer.RenderCallback
)

Adds the android.view.Surface to be managed by the GLThread.

GLRenderer.RenderTarget
createRenderTarget(
    width: Int,
    height: Int,
    renderer: GLRenderer.RenderCallback
)

Creates a new RenderTarget without a corresponding android.view.Surface.

Unit
detach(
    target: GLRenderer.RenderTarget,
    cancelPending: Boolean,
    @WorkerThread onDetachComplete: ((GLRenderer.RenderTarget) -> Unit)?
)

Removes the corresponding RenderTarget from management of the GLThread.

Unit
execute(runnable: Runnable)

Queue a Runnable to be executed on the GL rendering thread.

Boolean

Determines if the GLThread has been started.

Unit

Add an EGLContextCallback to receive callbacks for construction and destruction of EGL dependencies.

Unit
requestRender(
    target: GLRenderer.RenderTarget,
    onRenderComplete: ((GLRenderer.RenderTarget) -> Unit)?
)

Mark the corresponding surface session with the given token as dirty to schedule a call to RenderCallback#onDrawFrame.

Unit
resize(
    target: GLRenderer.RenderTarget,
    width: Int,
    height: Int,
    onResizeComplete: ((GLRenderer.RenderTarget) -> Unit)?
)

Resize the corresponding surface associated with the RenderTarget to the specified width and height and re-render.

Unit
start(name: String)

Starts the GLThread.

Unit
stop(cancelPending: Boolean, onStop: ((GLRenderer) -> Unit)?)

Stop the corresponding GL thread.

Unit

Remove EGLContextCallback to no longer receive callbacks for construction and destruction of EGL dependencies.

Public constructors

GLRenderer

GLRenderer(
    eglSpecFactory: () -> EGLSpec = { EGLSpec.V14 },
    eglConfigFactory: EGLManager.() -> EGLConfig = { // 8 bit channels should always be supported loadConfig(EGLConfigAttributes.RGBA_8888) ?: throw IllegalStateException("Unable to obtain config for 8 bit EGL " + "configuration") }
)
Parameters
eglSpecFactory: () -> EGLSpec = { EGLSpec.V14 }

Callback invoked to determine the EGL spec version to use for EGL management. This is invoked on the GL Thread

eglConfigFactory: EGLManager.() -> EGLConfig = { // 8 bit channels should always be supported loadConfig(EGLConfigAttributes.RGBA_8888) ?: throw IllegalStateException("Unable to obtain config for 8 bit EGL " + "configuration") }

Callback invoked to determine the appropriate EGLConfig used to create the EGL context. This is invoked on the GL Thread

Public functions

attach

Added in 1.0.2
fun attach(surfaceView: SurfaceView, renderer: GLRenderer.RenderCallback): GLRenderer.RenderTarget

Adds the android.view.Surface provided by the given SurfaceView to be managed by the backing thread.

A corresponding EGLSurface is created on the GLThread as well as a callback for rendering into the surface through RenderCallback.

This method automatically configures a SurfaceHolder.Callback used to attach the android.view.Surface when the underlying SurfaceHolder that contains the surface is available. Similarly this surface will be detached from GLRenderer when the surface provided by the SurfaceView is destroyed (i.e. SurfaceHolder.Callback.surfaceDestroyed is called.

If the android.view.Surface is already available by the time this method is invoked, it is attached synchronously.

Parameters
surfaceView: SurfaceView

SurfaceView that provides the surface to be rendered by the backing thread

renderer: GLRenderer.RenderCallback

callbacks used to create a corresponding EGLSurface from the given surface as well as render content into the created EGLSurface

Returns
GLRenderer.RenderTarget

RenderTarget used for subsequent requests to communicate with the provided Surface (ex. requestRender or detach).

Throws
kotlin.IllegalStateException

If this method was called when the GLThread has not started (i.e. start has not been called)

attach

Added in 1.0.2
fun attach(textureView: TextureView, renderer: GLRenderer.RenderCallback): GLRenderer.RenderTarget

Adds the android.view.Surface provided by the given TextureView to be managed by the backing thread.

A corresponding EGLSurface is created on the GLThread as well as a callback for rendering into the surface through RenderCallback.

This method automatically configures a TextureView.SurfaceTextureListener used to create a android.view.Surface when the underlying SurfaceTexture is available. Similarly this surface will be detached from GLRenderer if the underlying SurfaceTexture is destroyed (i.e. TextureView.SurfaceTextureListener.onSurfaceTextureDestroyed is called.

If the SurfaceTexture is already available by the time this method is called, then it is attached synchronously.

Parameters
textureView: TextureView

TextureView that provides the surface to be rendered into on the GLThread

renderer: GLRenderer.RenderCallback

callbacks used to create a corresponding EGLSurface from the given surface as well as render content into the created EGLSurface

Returns
GLRenderer.RenderTarget

RenderTarget used for subsequent requests to communicate with the provided Surface (ex. requestRender or detach).

Throws
kotlin.IllegalStateException

If this method was called when the GLThread has not started (i.e. start has not been called)

attach

Added in 1.0.2
fun attach(
    surface: Surface,
    width: Int,
    height: Int,
    renderer: GLRenderer.RenderCallback
): GLRenderer.RenderTarget

Adds the android.view.Surface to be managed by the GLThread. A corresponding EGLSurface is created on the GLThread as well as a callback for rendering into the surface through RenderCallback. Unlike the other attach methods that consume a SurfaceView or TextureView, this method does not handle any lifecycle callbacks associated with the target surface. Therefore it is up to the consumer to properly setup/teardown resources associated with this surface.

Parameters
surface: Surface

Target surface to be managed by the backing thread

width: Int

Desired width of the surface

height: Int

Desired height of the surface

renderer: GLRenderer.RenderCallback

Callbacks used to create a corresponding EGLSurface from the given surface as well as render content into the created EGLSurface

Returns
GLRenderer.RenderTarget

RenderTarget used for subsequent requests to communicate with the provided Surface (ex. requestRender or detach).

Throws
kotlin.IllegalStateException

If this method was called when the GLThread has not started (i.e. start has not been called)

createRenderTarget

Added in 1.0.2
fun createRenderTarget(
    width: Int,
    height: Int,
    renderer: GLRenderer.RenderCallback
): GLRenderer.RenderTarget

Creates a new RenderTarget without a corresponding android.view.Surface. This avoids creation of an EGLSurface which is useful in scenarios where only rendering to a frame buffer object is required.

Parameters
width: Int

Desired width of the RenderTarget

height: Int

Desired height of the RenderTarget

renderer: GLRenderer.RenderCallback

Callbacks used to issue OpenGL commands to the RenderTarget

Returns
GLRenderer.RenderTarget

RenderTarget used for subsequent requests to render through RenderTarget.requestRender or to remove itself from the GLRenderer through RenderTarget.detach

Throws
kotlin.IllegalStateException

If this method was called when the GLThread has not started (i.e. start has not been called)

detach

Added in 1.0.2
fun detach(
    target: GLRenderer.RenderTarget,
    cancelPending: Boolean,
    @WorkerThread onDetachComplete: ((GLRenderer.RenderTarget) -> Unit)? = null
): Unit

Removes the corresponding RenderTarget from management of the GLThread. This destroys the EGLSurface associated with this surface and subsequent requests to render into the surface with the provided token are ignored.

If the cancelPending flag is set to true, any queued request to render that has not started yet is cancelled. However, if this is invoked in the middle of the frame being rendered, it will continue to process the current frame.

Additionally if this flag is false, all pending requests to render will be processed before the RenderTarget is detached.

Note the detach operation will only occur if the GLRenderer is started, that is if isRunning returns true. Otherwise this is a no-op. GLRenderer will automatically detach all RenderTarget instances as part of its teardown process.

execute

Added in 1.0.2
fun execute(runnable: Runnable): Unit

Queue a Runnable to be executed on the GL rendering thread. Note it is important that this Runnable does not block otherwise it can stall the GL thread. The EGLContext will be created after start is invoked and before the runnable is executed.

Parameters
runnable: Runnable

Runnable to be executed

isRunning

Added in 1.0.2
fun isRunning(): Boolean

Determines if the GLThread has been started. That is start has been invoked on this GLRenderer instance without a corresponding call to stop.

registerEGLContextCallback

Added in 1.0.2
fun registerEGLContextCallback(callback: GLRenderer.EGLContextCallback): Unit

Add an EGLContextCallback to receive callbacks for construction and destruction of EGL dependencies.

These callbacks are invoked on the backing thread.

requestRender

Added in 1.0.2
fun requestRender(
    target: GLRenderer.RenderTarget,
    onRenderComplete: ((GLRenderer.RenderTarget) -> Unit)? = null
): Unit

Mark the corresponding surface session with the given token as dirty to schedule a call to RenderCallback#onDrawFrame. If there is already a queued request to render into the provided surface with the specified token, this request is ignored.

Note the render operation will only occur if the GLRenderer is started, that is if isRunning returns true. Otherwise this is a no-op.

Parameters
target: GLRenderer.RenderTarget

RenderTarget to be re-rendered

onRenderComplete: ((GLRenderer.RenderTarget) -> Unit)? = null

Optional callback invoked on the backing thread after the frame has been rendered.

resize

Added in 1.0.2
fun resize(
    target: GLRenderer.RenderTarget,
    width: Int,
    height: Int,
    onResizeComplete: ((GLRenderer.RenderTarget) -> Unit)? = null
): Unit

Resize the corresponding surface associated with the RenderTarget to the specified width and height and re-render. This will destroy the EGLSurface created by RenderCallback.onSurfaceCreated and invoke it again with the updated dimensions. An optional callback is invoked on the backing thread after the resize operation is complete.

Note the resize operation will only occur if the GLRenderer is started, that is if isRunning returns true. Otherwise this is a no-op.

Parameters
target: GLRenderer.RenderTarget

RenderTarget to be resized

width: Int

Updated width of the corresponding surface

height: Int

Updated height of the corresponding surface

onResizeComplete: ((GLRenderer.RenderTarget) -> Unit)? = null

Optional callback invoked on the backing thread when the resize operation is complete

start

Added in 1.0.2
fun start(name: String = "GLThread"): Unit

Starts the GLThread. After this method is called, consumers can attempt to attach android.view.Surface instances through attach as well as schedule content to be drawn through requestRender

Parameters
name: String = "GLThread"

Optional name to provide to the GLThread

Throws
kotlin.IllegalStateException

if EGLConfig with desired attributes cannot be created

stop

Added in 1.0.2
fun stop(cancelPending: Boolean, onStop: ((GLRenderer) -> Unit)? = null): Unit

Stop the corresponding GL thread. This destroys all EGLSurfaces as well as any other EGL dependencies. All queued requests that have not been processed yet are cancelled.

Note the stop operation will only occur if the GLRenderer was previously started, that is isRunning returns true. Otherwise this is a no-op.

Parameters
cancelPending: Boolean

If true all pending requests and cancelled and the backing thread is torn down immediately. If false, all pending requests are processed first before tearing down the backing thread. Subsequent requests made after this call are ignored.

onStop: ((GLRenderer) -> Unit)? = null

Optional callback invoked on the backing thread after it is torn down.

unregisterEGLContextCallback

Added in 1.0.2
fun unregisterEGLContextCallback(callback: GLRenderer.EGLContextCallback): Unit

Remove EGLContextCallback to no longer receive callbacks for construction and destruction of EGL dependencies.

These callbacks are invoked on the backing thread