Hi.
There seem to be quite a few capture issues recently. (There were already a few, but there’s been an uptick. I’m not certain what changed and when.) Some streaming software might also be affected; there was some Discord discussion about that.
I made a guess here that OpenGL’s packer might have became more stringent. Maybe it’s now balking at not-quite-spec things, whereas it was letting them go before? (I think Windows was already this way; annoyingly, on other issues it’s been the other way around. )
I wrote a Vulkan backend a while back. According to somebody who tested with a major project, its capture feature seems to be robust against these sorts of issues. This includes streaming with OBS, where I’m told he was running into problems with GL.
Solar’s OpenGL backend is built on glReadPixels
. My best guess is that we have a “packing” issue. I don’t have a ready use case to verify this, but I’m guessing that if captureWidth % 4 == 0
is NOT true, a problem might arise… or not, if we’re “lucky”. (In my Bytemap plugin on Windows,—where we “unpack”—I had to add a dummy alpha channel to RGB “external” textures, thus my suspicions. I wonder if this might be behind the mysterious “multiple-of-4” width requirement on masks.)
(If this NEVER occurs on mobile, where RGBA
is used unconditionally, I lean even more this way.)
If this analysis is correct, the glReadPixels
line needs to be preceded by something like glPixelStorei( GL_PACK_ALIGNMENT, BitsForFormat( format ) )
.
The BitsForFormat()
function doesn’t exist, but outside OpenGL ES would roughly involve the logic here: RGBA and friends would be 4 bytes per pixel, RGB would have 3, anything else 1. We would first multiply this value by the width passed to glReadPixels
. If (width * bpp) % 4 == 0
, 4 is our alignment; otherwise try 3, and finally 1.
I can’t conveniently test this at the moment, but I’ll pass it along.