Skip to content

Comments

fix color channel byte order in gfx/primitives.rs#1522

Merged
antonilol merged 2 commits intoRust-SDL2:masterfrom
antonilol:fix-gfx-color
Feb 19, 2026
Merged

fix color channel byte order in gfx/primitives.rs#1522
antonilol merged 2 commits intoRust-SDL2:masterfrom
antonilol:fix-gfx-color

Conversation

@antonilol
Copy link
Contributor

This restores the intended behavior from before #1470 without reintroducing the UB that PR removed.

Tested on my machine (little endian)
@Guddler could you test this on your big endian platform?

I used this code:

canvas.set_draw_color(Color::GRAY);
canvas.clear();

// row 1: red, green, blue
canvas.filled_circle(200, 200, 75, Color::RED)?;
canvas.filled_circle(400, 200, 75, Color::GREEN)?;
canvas.filled_circle(600, 200, 75, Color::BLUE)?;

// row 2: white, black
canvas.filled_circle(200, 400, 75, Color::WHITE)?;
canvas.filled_circle(400, 400, 75, Color::BLACK)?;

should fix #1502

@Guddler
Copy link

Guddler commented Feb 11, 2026

I will report back. I need to remember how I was running rust on my BE system! I think it must have been from Linux (normal OS is MorphOS which doesn't have a rust port). If it was Linux then I still have the disk and can test.

@Guddler
Copy link

Guddler commented Feb 15, 2026

Unfortunately, on my PPC system, I can no longer build the SDL2 dependency. I get lots and lots of errors that I haven't dug into yet but look a lot like 32bit is now failing (or no longer supported), lots of instances of "attempt to compute 8_usize - 16_usize, which would overflow". Note, the 8 and 16 there are just examples but the second number is always double the first.

If I try to cross-compile from my M4 Mac to PPC then I can build for ppc64, just not ppc32. However, I don't have PPC linkers on my Mac so I wouldn't be able to complete that build anyway, I just know the build step doesn't throw those same errors, which is what makes me think it's a PPC32 vs PPC64 issue. My PPC system (the Big Endian system) is technically a PPC64 CPU (e5500), but I don't believe PPC64 linux has been run successfully on it at this point so we run plain PPC instead.

Anyway, this all means that at this point, I can only confirm that the colours look correct now on M4 Mac, I cannot confirm on BE as yet. When I get some more time I will continue to see if I can get this built on PPC32, both native and via a Linux system that I can build.

@antonilol
Copy link
Contributor Author

lots of instances of "attempt to compute 8_usize - 16_usize, which would overflow". Note, the 8 and 16 there are just examples but the second number is always double the first.

This has been introduced by bindgen running layout checks at compile time instead of runtime since an update, adding the use-bindgen feature will make it generate bindings for the correct target and should make it compile correctly.

@Guddler
Copy link

Guddler commented Feb 15, 2026

Thank you - that got it compiled.

Now I need to strip everything back to a simple example that just renders a blank screen of a background colour because currently my answer would be that the colours do not look right on BE, no. If I clear the screen using a colour of Colour::RGB(0, 0, 0) for example, my output screen is red, where clearly I would expect black.

So I need to make sure I'm not doing anything stupid even though my Mac and my PPC systems are using the same code.

@antonilol
Copy link
Contributor Author

That is consistent with #1502 and would mean it did not work correctly before #1470 on BE systems.

Colour::RGB(0, 0, 0) which is (0, 0, 0, 255) somehow turns red, flipping it results in (255, 0, 0, 0) which I think should be black because of the zeroed alpha channel, but ignoring alpha this could be right.

@antonilol
Copy link
Contributor Author

Could you check if it works now with this new commit?

@Guddler
Copy link

Guddler commented Feb 15, 2026

For circles (filled_circle()), the colours look correct now. More generally I think there are other areas that are not byte swapping:

        // Erase screen
        canvas.set_draw_color(Color::BLUE);
        canvas.fill_rect(screen_area)?;

        // Circle stuff
        let _ = canvas.filled_circle(200, 200, 75, Color::RED);
        let _ = canvas.filled_circle(600, 200, 75, Color::BLACK);
        let _ = canvas.filled_circle(200, 400, 75, Color::YELLOW);
        let _ = canvas.filled_circle(600, 400, 75, Color::CYAN);

        canvas.present();

That code for example - the circles are in the correct colour, but the background is Yellow, not blue. I also have another example where lines are not the correct colour.

@Guddler
Copy link

Guddler commented Feb 15, 2026

Using clear instead of fill_rect gives the correct result. Your code above for example - perfect.

@antonilol
Copy link
Contributor Author

canvas.set_draw_color(Color::BLUE);
canvas.fill_rect(screen_area)?;

...
but the background is Yellow, not blue.

This is not related to sdl gfx but to sdl renderer, and this actually surprises me because I don't see colors being handled like ints or bytes there. Surely SDL2 works correctly on big endian platforms, right?
set_draw_color calls SDL_SetRenderDrawColor, SDL stores the color for later use in "drawing operations (Rect, Line and Clear)". I find it very strange that there is any difference in colors between clear and rect operations.

Does an example using only C code work?

Like this (chatgpt slop):

#include <SDL2/SDL.h>

int main(int argc, char* argv[])
{
    SDL_Init(SDL_INIT_VIDEO);

    SDL_Window* window = SDL_CreateWindow(
        "SDL2 Example",
        SDL_WINDOWPOS_CENTERED,
        SDL_WINDOWPOS_CENTERED,
        800, 600,
        SDL_WINDOW_SHOWN
    );

    SDL_Renderer* renderer = SDL_CreateRenderer(
        window,
        -1,
        SDL_RENDERER_ACCELERATED
    );

    // Equivalent to canvas.set_draw_color(Color::BLUE);
    SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);

    // Equivalent to canvas.fill_rect(None)?;
    // Passing NULL fills the entire rendering target
    SDL_RenderFillRect(renderer, NULL);

    SDL_RenderPresent(renderer);

    SDL_Delay(3000);

    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();

    return 0;
}

(compile: gcc -o test -lSDL2 test.c, run: ./test)

This correctly gives a completely blue screen for me

@Guddler
Copy link

Guddler commented Feb 18, 2026

Please leave this with me and I will test ASAP, hopefully this evening.

In short, yes, SDL2 works generally on BE systems. I have 2 (unfinished) games in C/SDL2 render correctly on MorphOS and Amiga OS4. Neither of those OS's have a Rust port (I wish I knew how to do that!). The 3rd system which is Linux Mint PPC (an unofficial distro) is where I am testing this Rust Big Endian stuff and I don't recall if I've run my games on there or not.

I will test the supplied code, and my games and report back.

The reality is that I'm unlikely to actually use Rust directly on these systems as the build process is a bit slow on them. But it would certainly be nice to be able to cross-compile for them on my main systems (MacOS).

I think I hit a further problem with SDL2 compilation following an apt-upgrade as well so I also need to investigate that.

( [edit] The hardware: https://mirari.vitasys.nl )

@Guddler
Copy link

Guddler commented Feb 19, 2026

In short, the colours are messed up in SDL2 on Linux Mint PPC32. Instead of RGBA you need to specify ABGR to get the right colours. This affects the plain C example code and my games. It could be the reason for the issue in Rust as well unfortunately. The problem is not there in alternative OS's.

I'm not familiar with the inner workings of it all enough to know if this is normal and I need to adjust for a different pixel format, or if the code should just run on any platform. I would have thought as such a basic level it should just run?

I am trying to get another distro to run so I can determine if it is SDL2-devel on PPC32 Linux in general, or just the version on Mint. Alternative distro's aren't easy for this platform but hopefully I'll get one running over the weekend so I can get to the bottom of this.

@antonilol
Copy link
Contributor Author

In short, the colours are messed up in SDL2 on Linux Mint PPC32. Instead of RGBA you need to specify ABGR to get the right colours. This affects the plain C example code and my games. It could be the reason for the issue in Rust as well unfortunately. The problem is not there in alternative OS's.

I'm not familiar with the inner workings of it all enough to know if this is normal and I need to adjust for a different pixel format, or if the code should just run on any platform. I would have thought as such a basic level it should just run?

The SDL C function SDL_SetRenderDrawColor has parameters for red, green, blue and alpha and does not mention that they need to be byte swapped on some platforms, so this is probably a bug in SDL or in something SDL uses (OS APIs?).

I am trying to get another distro to run so I can determine if it is SDL2-devel on PPC32 Linux in general, or just the version on Mint. Alternative distro's aren't easy for this platform but hopefully I'll get one running over the weekend so I can get to the bottom of this.

Good luck! This problem does not seem rust-sdl2 related so I will merge this PR.

@antonilol antonilol merged commit de686d0 into Rust-SDL2:master Feb 19, 2026
11 of 17 checks passed
@antonilol antonilol deleted the fix-gfx-color branch February 19, 2026 19:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Colour doesn't appear to work correctly with circle functions

2 participants