Rust's glium lib is a nice OpenGL wrapper that facilitate slots of stuff. In order to implement a new backend for it, you must implement https://github.com/glium/glium/blob/cacb970c8ed2e45a6f98d12bd7fcc03748b0e122/src/backend/mod.rs#L36
I want to implement Android's SurfaceTexture as a Backend
Looks like I need to implement a new Backend for SurfaceTexture: https://github.com/glium/glium/blob/master/src/backend/mod.rs#L36
Here are the C++ functions of SurfaceTexture https://developer.android.com/ndk/reference/group/surface-texture#summary
I think that Backend::make_current(&self);
maps to ASurfaceTexture_attachToGLContext(ASurfaceTexture *st, uint32_t texName)
and Backend::is_current(&self) -> bool
can be simulated somehow based on each SurfaceTexture
being marked as active or not when this is called.
Maybe Backend::get_framebuffer_dimensions(&self) -> (u32, u32)
is the size of the SurfaceTexture which is defined at creation so I can use that. I just don't know what to do with Backend::swap_buffers(&self) -> Result<(), SwapBuffersError>
and maybe Backend::unsafe fn get_proc_address(&self, symbol: &str) -> *const c_void
can call some Android API that gets the address of the OpenGL functions
However, ASurfaceTexture_updateTexImage(ASurfaceTexture *st)
looks important and needed, and I don't know what to map it to in the Backend
. Also, what about ASurfaceTexture_detachFromGLContext(ASurfaceTexture *st)
?
PS: I know there are other ways to render to an android widget, but I need to render to a Flutter widget, and the only way it through a SurfaceTexture
I managed to make this work some time ago, with a hack-ish solution, maybe it still works, because
glium
is not changing very much lately.But in my experience using
ASurfaceTexture
yields unreliable results, maybe that is because I used it wrongly, or maybe because Android manufacturers do not pay too much attention to it, I don't know. But I didn't see any real program using it, so I decided to use the well tested JavaGLSurfaceView
instead and a bit of JNI to connect everything.Being
com.example.myapp.GLJNILib
the JNI binding to the Rust native library, where the magic happens. The interface is quite straightforward:Now, this Rust library can be designed in several ways. In my particular projects, since it was a simple game with a single full-screen view, I just created the
glium
context and store it in a global variable. More sophisticated programs could store theBackend
into a Java object, but that complicates the lifetimes and I didn't need it.But first we have to implement the trait
glium::backend::Backend
, which happens to be surprisingly easy, if we assume that every time one of the Rust functions is called the proper GL context is always current:And now we can implement the JNI
init
function:The size will be updated when the size of the view changes (not that
glium
uses that value so much):And similarly the
render
function:Note that
target.finish()
is still needed althoughglium
is not actually doing the swap.