| Summary: | Software renderer does incorrect blending with SDL_RenderCopyEx | ||
|---|---|---|---|
| Product: | SDL | Reporter: | Simon Hug <chli.hug> |
| Component: | render | Assignee: | Sam Lantinga <slouken> |
| Status: | RESOLVED FIXED | QA Contact: | Sam Lantinga <slouken> |
| Severity: | normal | ||
| Priority: | P2 | ||
| Version: | HG 2.0 | ||
| Hardware: | All | ||
| OS: | All | ||
| Attachments: |
Test case for the software renderer blending.
Image data for the test case. Patch that makes the software renderer blending consistent. Patch that makes the software renderer blending consistent. Patch that makes the software renderer blending consistent. Patch that makes the software renderer blending consistent. Test case (v2) for the software renderer blending. |
||
Created attachment 2488 [details]
Image data for the test case.
Attached is an image file for the test case.
Created attachment 2489 [details] Patch that makes the software renderer blending consistent. This patch fixes the issues mentioned above. It mainly changes the code so it tries to do things without the colorkey and removes the automatic format conversion part from the SDLgfx_rotateSurface function. Getting the format right is something the caller has to do now and the required code has been added to the SW_RenderCopyEx function. There's a small change to the SW_CreateTexture function. RLE encoding a surface with an alpha mask can be a lossy process. Depending on how the user uses the RGBA channels, this may be undesired. The change that surfaces with an alpha mask don't get encoded makes the software renderer consistent with the other renderers. The SW_RenderCopyEx function now does these steps: Lock the source surface if necessary. Create a clone of the source by using the pixel buffer directly. Check the format and set a flag if a conversion is necessary. Check if scaling or cropping is necessary and set the flag for that as well. Check if color and alpha modulation has to be done before the rotate. Check if the source is an opaque surface. If not, it creates a mask surface that is necessary for the NONE blend mode. If any of the flags were set, a new surface is created and the source will be converted, scaled, cropped, and modulated. The rest of the function stays somewhat the same. The mask also needs to be rotated of course and then there is the NONE blend mode... It's surprisingly hard to get the pixel from a rotated surface to the destination buffer without affecting the pixel outside the rotated area. I found a way to do this with three blits which is pretty hard on the performance. Perhaps someone has an idea how to do this faster? As mentioned above, the SDLgfx_rotateSurface now only takes 8-bit paletted or 32-bit with alpha mask surfaces. It additionally sets the new surfaces up for the MOD blend mode. I shortly tested the 8-bit path of SDLgfx_rotateSurface and it seemed to work so far. This path is not used by the software renderer anyway. Some other things I want to mention: I think the previous changes to these functions came from bug 1550. It seems bug 2198 has already been fixed at some point. Can you please update this patch for the latest SDL code in Mercurial? Thanks! Created attachment 2568 [details]
Patch that makes the software renderer blending consistent.
Attached a patch that imports cleanly with current tip.
Created attachment 2569 [details]
Patch that makes the software renderer blending consistent.
Whoops. Let's try that again. This one actually references current tip.
Created attachment 2626 [details]
Patch that makes the software renderer blending consistent.
Updated the patch for current tip.
Created attachment 2627 [details]
Test case (v2) for the software renderer blending.
Updated test case. Added some control to manually rotate the texture to test the new 90 degree fast path.
Wow, these steps look insanely slow. What's the fast path? Your patch is applied, thanks! https://hg.libsdl.org/SDL/rev/6b2307dbec54 Yeah, super slow. I did however just use the existing blit functions to get the desired effect and didn't feel comfortable adding new stuff that increases the complexity. I'm sure there would be all kinds of optimizations possible if the rotate function would write directly to the destination surface. Too daunting for me to code, though. With '90 degree fast path' I meant the code that was added with changeset 1e1ce9f6d215 [1] (Fri, 07 Oct 2016 18:00:30 -0700). At least that code refers to itself as the 'fast path'. [1] https://hg.libsdl.org/SDL/rev/1e1ce9f6d215 |
Created attachment 2487 [details] Test case for the software renderer blending. The software renderer produces incorrect results when blending textures at an angle with certain blend modes. It seems that there were some edge cases that weren't considered when the SW_RenderCopyEx function was last changed. Or another bug possibly covered up the problem. (More on that in another bug report.) Most of the issues come from the fact that the rotating function sets a black colorkey. This is problematic because black is most likely appearing in the surface and the final blit will ignore these pixels. Unless a colorkey is already set (the software renderer currently never sets one), it's very hard to find a free color. Of course it could scan over the whole image until one is found, but that seems inefficient. The following blend modes have issues when drawn at an angle. NONE: The black pixels get ignored, making them essentially transparent. This breaks the 'dstRGBA = srcRGBA' definition of the NONE blend mode. MOD: Again, the black pixels get ignored. This also breaks the 'dstRGB = dstRGB * srcRGB' definition of the MOD blend mode, where black pixels would make the destination black as well. A white colorkey will work though, with some preparations. BLEND: There are some issues when blending a texture with a translucent RGBA target texture. I - uh - forgot what the problem here exactly is. Attached is a test case which creates two renderers, one hardware and one software, and displays them next to each other. It's expected that they should look very similar, if not the same. The controls are described in a comment at the top the C file. The image data for the test will be in the next comment.