We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 3684

Summary: Add support for a pre-multiplied alpha blending mode
Product: SDL Reporter: Ben Kurtovic <ben.kurtovic>
Component: renderAssignee: Sam Lantinga <slouken>
Status: WAITING --- QA Contact: Sam Lantinga <slouken>
Severity: enhancement    
Priority: P2    
Version: HG 2.1   
Hardware: All   
OS: All   
Attachments: Adds a SDL_BLENDMODE_PMA blending mode for pre-multiplied alpha blending
Adds a SDL_BLENDMODE_PMA blending mode for pre-multiplied alpha blending

Description Ben Kurtovic 2017-06-26 22:00:46 UTC
Created attachment 2778 [details]
Adds a SDL_BLENDMODE_PMA blending mode for pre-multiplied alpha blending

Hello!

Recently I have hit a snag relating to SDL's lack of support for a pre-multiplied alpha blending mode. While this is easy to do with raw OpenGL (my renderer backend), it is really painful/infeasible to manually adjust the GL blend function for a SDL texture in client code. Since this issue has come up before[1], I thought it would be a good idea to add support to SDL directly.

Wikipedia's article on alpha compositing[2] explains PMA better than I could hope to in here, so please review that if you want to understand the motivation better.

My patch adds a member to the SDL_BlendMode enum called SDL_BLENDMODE_PMA (not a great name I admit, maybe SDL_BLENDMODE_PREMULTIPLIED would be better, but it's easy to change). The idea is SDL_BLENDMODE_PMA blends just like SDL_BLENDMODE_BLEND, but assumes the RGB channels of the source texture/surface have had the alpha channel pre-multiplied in. I added support for it in all of the render backends that I could figure out, which is generally trivial thanks to how hardware blending functions are specified. I also added it to the unaccelerated software rendering code, which is also easy since a lot of that code just premultiplies the alpha value before doing its computations, so we only needed to skip that step.

Side note: since OpenGL/Direct3D/etc have similar ways of specifying blend functions, it would be really nice if SDL could let us chose our own without the hard-coding. However, that's a much bigger project than this.

If we want to be completely thorough, I believe PMA could also be supported in the surface RLE acceleration code, but it seems somewhat non-trivial and I don't have the motivation to figure it out, so I left it unimplemented there.

Also, I couldn't test this on the non-OpenGL backends because I don't have the right hardware. I tried to add test code to the existing testautomation_surface.c and testautomation_render.c files, but it appears that the existing tests for the other modes are broken anyway, so I'm not sure how much effort should be spent there.

[1] https://forums.libsdl.org/viewtopic.php?p=41646
[2] https://en.wikipedia.org/wiki/Alpha_compositing
Comment 1 Ben Kurtovic 2017-06-28 08:40:59 UTC
Created attachment 2781 [details]
Adds a SDL_BLENDMODE_PMA blending mode for pre-multiplied alpha blending

Realized my original solution didn't support SDL_TEXTUREMODULATE_ALPHA when used without SDL_TEXTUREMODULATE_COLOR because the modulated RGBA value wouldn't account for the pre-multiplied alpha channel. Fixed in the new patch, which pre-multiplies the alpha into the RGB value in SetAlphaMod and does a couple things differently in a few renderers that needed it.

Tested with OpenGL and the software renderer; as before, I don't have the hardware to test the other renderers.
Comment 2 Sam Lantinga 2017-08-14 12:57:34 UTC
This is partly fixed with this commit:
https://hg.libsdl.org/SDL/rev/180e8906dc3c

        SDL_BLENDMODE_BLEND_PREMULTIPLIED = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, SDL_BLENDOPERATION_ADD, SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA,SDL_BLENDOPERATION_ADD);

You elegantly folded that into the software renderer, which still needs to be done here, and this patch doesn't handle the modulation you mentioned. What's a good way to test that?

Can you re-base your patch on top of this commit, and change the name to SDL_BLENDMODE_BLEND_PREMULTIPLIED?

Thanks!