Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Start getting base module ready for SDL3 #3171

Merged
merged 3 commits into from
Nov 2, 2024

Conversation

Starbuck5
Copy link
Member

@Starbuck5 Starbuck5 commented Oct 13, 2024

Before this PR there are 3 issues preventing base from compiling on SDL3, this PR handles 2 of them (the easy ones). all 3.

  • SDL_getenv has changed to return a const char* instead of char*, so I reworked pg_EnvShouldBlendAlphaSDL2 to return an integer yes/no instead of a pointer where NULL/non NULL is interpreted as yes/no.
  • SDL_INIT_TIMER has been removed, so I made a PG_INIT_TIMER which is 0 on SDL3
  • SDL_ConvertSurface in SDL3 only exists as SDL2's SDL_ConvertSurfaceWithFormat, so restructured default pixelformat system to use enum values instead of structs. This is a complex looking change but I think is a good simplification overall.

The remaining issue is the pixelformat changes interacting with get and set default pixelformat.

Wanted to get this PR out so these two simpler changes can go through before worrying about what will need to happen with the pixelformat.

@Starbuck5 Starbuck5 requested a review from a team as a code owner October 13, 2024 00:18
@Starbuck5 Starbuck5 added the sdl3 label Oct 13, 2024
@ankith26
Copy link
Member

ankith26 commented Oct 13, 2024

The remaining issue is the pixelformat changes interacting with get and set default pixelformat.

I think the fix for this should be easy enough to get done with in this PR. I'd like to see base.c actually compiling while reviewing a SDL3 port PR. I'm thinking we just make the pixel format functions deal with SDL3 SDL_PixelFormat integers. If any caller needs more info they can extract that with SDL3 API.

The callers can be fixed in future PRs on a submodule basis, just the function definition can be fixed now. And we can use our usual strategy of not changing the SDL2 codepath at all.

@Starbuck5
Copy link
Member Author

Not changing the SDL2 codepath is all well and good, but I'd also like to avoid completely separate SDL2/SDL3 codepaths.

I hadn't yet figured out whether to store the enum or the details in SDL3 or in SDL2, or how the consumer could be refitted in SDL2 to use enum instead of mask values.

Earlier in the porting effort I moved almost everything over from mask style to enum style, this is one I didn't touch.

My thought was that this PR contains simple enough code changes to go through without burdening the review of the pixelformat stuff (which could get complicated!)

Copy link
Member

@MyreMylar MyreMylar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, LGTM 👍

@bilhox bilhox modified the milestones: 3.0.0, 2.5.3 Oct 13, 2024
@ankith26
Copy link
Member

I'd like some solution that gets base.c compiling in this PR, even if it's not the final solution or ideal solution. We can always change it later (and I believe when the tests actually start running we are gonna hit many more issues and have to do changes anyways)

No longer exists in SDL3, so simple compat is to mock it out to a macro that is zero in SDL3.
SDL_getenv now returns a const char* instead of a char*, so rather than worry about propagating that through or casting it away, lets just have pg_EnvShouldBlendAlphaSDL2 return an int, and have the callers evaluate that instead of evaluating whether a char* is NULL or not. This requires no changes to the callers.
@Starbuck5 Starbuck5 force-pushed the start-base-sdl3 branch 2 times, most recently from e1cc0ec to de257d7 Compare October 31, 2024 07:55
@Starbuck5
Copy link
Member Author

Starbuck5 commented Oct 31, 2024

As requested I have made the module compile fully, and as predicted it completely blows up the scope of this PR.

PR now changes the SDL2 codepath, includes changes to other modules, and the diff significantly larger. If I were reviewing this, I would want it in a separate PR.

Here is an infographic to help explain the changes:
maskpixelformat_infographic

src_c/surface.c Outdated Show resolved Hide resolved
#define PG_ConvertSurfaceFormat SDL_ConvertSurfaceFormat
#define PG_ConvertSurfaceFormat SDL_ConvertSurface

#define PG_PixelFormatEnum SDL_PixelFormat
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the addition of this macro. I believe defining another macro like

#if SDL_VERSION_ATLEAST(3, 0, 0)
#define PG_SURF_format(s) ((s)->format)
#else
#define PG_SURF_format(s) ((s)->format->format)
#endif

would also be useful

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to wait a bit on that, see what abstractions evolve out of porting other modules for that case. My preliminary work has shown a big challenge in getting colorkey data and keeping it with the format, so maybe the bare format enum will be a rarity.

if (pg_default_screen) {
return pg_default_screen->surf->format->format;
}
#endif
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole block of code can be return PG_SURF_format(pg_default_screen->surf); after implementing the macro

return RAISE(pgExc_SDLError, SDL_GetError());
}
if (pg_GetDefaultConvertFormat() == 0) {
pg_SetDefaultConvertFormat(_surf->format->format);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pg_SetDefaultConvertFormat(_surf->format->format);
pg_SetDefaultConvertFormat(PG_SURF_format(_surf));

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this PR is ready, except that this minor issue has not been addressed yet. Adding the abstraction would fix this code for the SDL3 case, now it would error.
I suggested the abstraction because I can see it being used twice in this PR itself, so I assumed it could be potentially useful in the future.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well in my defense this PR is to port base, not window.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair, we can deal with it later then. Anyways it is an issue that a compiler can catch, so it won't go unnoticed

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah when you left your comment I stared at the line and was like how did the compiler not catch that. It took me a sec to realize the compiler isn't catching it because Window.c is not being compiled.

break;
default: /* ARGB8888 */

default:
Copy link
Member

@ankith26 ankith26 Oct 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the explanative diagram, with that I can see the equivalence of this code with the old code.

Now that we are moving to pixelformats here, we could probably further improve this logic to be simpler and more correct, by dealing with the SDL_PIXELORDER macro instead, though that would definitely be for a future PR, I think imma make an attempt at that after merging this one.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I figured my comment was not clear, and I got the itch to work on it now. So what I'm essentially proposing is:

static SDL_Surface *
pg_DisplayFormatAlpha(SDL_Surface *surface)
{
    PG_PixelFormatEnum pfe = SDL_PIXELFORMAT_ARGB8888;
    PG_PixelFormatEnum dformat = pg_GetDefaultConvertFormat();
    if (!dformat) {
        SDL_SetError(
            "No convert format has been set, try display.set_mode()"
            " or Window.get_surface().");
        return NULL;
    }

    if (SDL_ISPIXELFORMAT_ALPHA(dformat)) {
        /* Display surface already has alpha, use the exact same format */
        pfe = dformat;
    }
    else if (SDL_ISPIXELFORMAT_ARRAY(dformat)) {
        /* In SDL2 this path is only triggered for
         * SDL_PIXELFORMAT_RGB24/SDL_PIXELFORMAT_BGR24 */
        switch (SDL_PIXELORDER(dformat)) {
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
            case SDL_ARRAYORDER_RGB:
                pfe = SDL_PIXELFORMAT_ARGB8888;
                break;
            case SDL_ARRAYORDER_BGR:
                pfe = SDL_PIXELFORMAT_BGRA8888;
                break;
#else
            case SDL_ARRAYORDER_RGB:
                pfe = SDL_PIXELFORMAT_BGRA8888;
                break;
            case SDL_ARRAYORDER_BGR:
                pfe = SDL_PIXELFORMAT_ARGB8888;
                break;
#endif
            default:
                break;
        }
    }
    else if (SDL_ISPIXELFORMAT_PACKED(dformat)) {
        switch (SDL_PIXELORDER(dformat)) {
            case SDL_PACKEDORDER_XRGB:
                pfe = SDL_PIXELFORMAT_ARGB8888;
                break;
            case SDL_PACKEDORDER_RGBX:
                pfe = SDL_PIXELFORMAT_RGBA8888;
                break;
            case SDL_PACKEDORDER_XBGR:
                pfe = SDL_PIXELFORMAT_ABGR8888;
                break;
            case SDL_PACKEDORDER_BGRX:
                pfe = SDL_PIXELFORMAT_BGRA8888;
                break;
            default:
                break;
        }
    }
    return PG_ConvertSurfaceFormat(surface, pfe);
}

Still gonna PR it later so it can be independently reviewed

@Starbuck5
Copy link
Member Author

I consider this PR done, unless you insist on the macro Ankith.

Left the last commit unsquashed so the recent changes are viewable on their own. I would squash the last couple commits before merging.

Copy link
Member

@ankith26 ankith26 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks! 🥳

This reworks the functions to work on pixel format enums instead of structs, because in SDL3 the enums are much easier to get than the structs.

This required involved changes to surface.c, but I think the previous mask logic is much clearer now that it is expressed using format enums.
@Starbuck5
Copy link
Member Author

(Just squashed the last 3 commits together)

@ankith26 ankith26 merged commit 4f587cc into pygame-community:main Nov 2, 2024
27 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants