I've managed a basic MMAL based video playback on a DRM GL surface on the Pi4. I've now run into an odd issue that I don't have any explanation for. Have a look at this image:
Edit: Here's a video.
What you see in screen capture is a red gl surface with a single mmal decoded video rendered two times. What I observe is that the second time I draw the video texture it constantly flickers in an unpredictable way. In the snapshow above, both textures should have the same height and the right one is randomly cut off in the lower part. Some observations:
- Decoding a second video with another mmal pipeline and showing its texture works. No flickering in that case. Showing any of those textures a second time results in flickering for this additional texture.
- The flickering occurs even if the first texture is rendered completely outside the visible area.
- Drawing the texture happens in the main thread, while all the mmal work is in a background thread. Similar to this code here I swap out the reference to the current buffer. As drawing is a a separate action in my code, I've locked this section so that swapping out `current_buffer` only happens while the main thread isn't holding that lock while GlDraw'ing that texture. Unfortunately this doesn't help.
- I tried to only swap out the `current_buffer` both just before or after a eglSwapBuffers. Still flickers.
- I've incremented the number of EGL_LINUX_DMA_BUF_EXT buffers I cycle through. From my understanding I need at least two, so one is being worked on while the other is currently available to draw on the screen. I've upped that value to 3 and 10 and besides the additional memory usage it still flickers.
- Usually the drawing is triggered by user code that then calls the C code actually issuing the glDraw commands. I've modified that part so the C does does those two call instead upon a single invocation. That way there's way there's no way anything else between those two calls might change the GL state. It flickers.
- Oddly enough using a single glDrawArrays call with a glVertexAttribPointer pointing to 8 instead of the 4 vertices (essentially drawing two squares awkwardly connected at a single edge) works without flickering.
- It even flickers if I suspend the thread handing the mmal buffer headers containing new frames (So essentially if I sleep(10) here). So the buffer header holding the vcsm_handle shouldn't be touch in my understanding.
I'm running out of ideas at this point. It almost seems like drawing a GL_TEXTURE_EXTERNAL_OES texture once results in some internal state that then prevents it from being drawn a second time in the same frame without flickering. But that's pure speculation and so far I haven't been able to reproduce this issue by modifying the linked code. Of course it's not directly comparable as that code uses a X GL surface instead of DRM and I'm not sure if that might influence what happens. Any hint might be useful.