Strange alpha rendering on Android

Hey all,

we are trying to solve a really strange and complex problem.
We are rendering via SDL_GPU on an Android SurfaceView. We are using the example SDLActivity from the SDL2 Project.

We need to render a video under our SDL view. To simplify all the video stuff we are using the ExoPlayer to load and display the video. We are rendering a video via ExoPlayer into another Surface View which lies under the SDL SurfaceView. Now we need to make the video visible under the SDL Surface as it is covering the whole screen. To make this possible we set the Pixelformat via getHolder().setFormat(PixelFormat.RGBA_8888);

This makes the video visible under the SDL view. But then something reeeeeallly strange happens as soon as we add any view that has opacity above a view that is opaque: The video becomes visible on the exact same area. Here is an image of ho it looks as soon as we render something transparent inside our SDL surface: PlayerOpacityProblem

The red box hence our transparent gray is rendered above the opaque background, but the video becomes visible on that area.

Does anyone have an idea what could be the reason for that behaviour and how it might be solved?
Please let us know if there is more information needed for this issue. Hope there is an :angel:

I’m not 100% sure on this because I haven’t tried such a thing myself, but try to disable writing to the alpha channel on the framebuffer (e.g. with glColorMask). The alpha channel in the buffer that is being drawn to is not necessary for drawing transparent stuff, but if you write the values there if changes how you surface opacity (I would guess).

see https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glColorMask.xml

Oh I just realized you said you are using SDL_GPU. I haven’t used that. Maybe it has some way to disable writing alpha or if not I think it should be possible to use OpenGL calls with it too.

I did not really get what you mean by disabling writing the alpha. Why does it solve the problem and how to achieve translucent shapes then? Is this approach similar to a pre-multiplied alpha approach? While experimenting i could get rid of the effect by setting the blend mode to GPU_BLEND_NORMAL_FACTOR_ALPHA on the SDL Surface, but i have no idea why it works and there are still some strange edge cases where the video in the background becomes visible on transparent textures.

Normal transparency between stuff that is drawn on a buffer does not normally need an alpha channel on the destination buffer (only on the source). What I was thinking is that you could first draw a shape determining the area that is transparent and then after that disable writing to the alpha channel and draw rest of the stuff normally. This would effectively “mask” some portion of the buffer to be transparent while transparency between different draw calls would still work.

The method above should work too, but it should not be needed if you adjust your blend mode. Most likely you are writing “wrong” values to the destination alpha channel (in the frame buffer). I did a quick test and you should be able to draw everything normally if you draw with a blend mode that results in a alpha channel that is interpolated between source and destination alpha values. In OpenGL it would be:

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

(see https://www.khronos.org/opengl/wiki/Blending#Colors for more info)

Like I said I haven’t used SDL_GPU but with quick googling I came across GPU_SetShapeBlendFunction that seems to set these values for drawing shapes at least.