diff --git a/.github/workflows/build-sdl3.yml b/.github/workflows/build-sdl3.yml
new file mode 100644
index 0000000000..b4e86af529
--- /dev/null
+++ b/.github/workflows/build-sdl3.yml
@@ -0,0 +1,88 @@
+# SDL3 porting is WIP
+name: SDL3 build
+
+# Run CI only when a release is created, on changes to main branch, or any PR
+# to main. Do not run CI on any other branch. Also, skip any non-source changes
+# from running on CI
+on:
+  push:
+    branches: main
+    paths-ignore:
+      - 'docs/**'
+      - 'examples/**'
+      - '.gitignore'
+      - '*.rst'
+      - '*.md'
+      - '.github/workflows/*.yml'
+      # re-include current file to not be excluded
+      - '!.github/workflows/build-sdl3.yml'
+
+  pull_request:
+    branches: main
+    paths-ignore:
+      - 'docs/**'
+      - 'examples/**'
+      - '.gitignore'
+      - '*.rst'
+      - '*.md'
+      - '.github/workflows/*.yml'
+      # re-include current file to not be excluded
+      - '!.github/workflows/build-sdl3.yml'
+
+  # the github release drafter can call this workflow
+  workflow_call:
+
+concurrency:
+  group: ${{ github.workflow }}-${{ github.ref }}-ubuntu-sdist
+  cancel-in-progress: true
+
+jobs:
+  build:
+    runs-on: ${{ matrix.os }}
+    strategy:
+      fail-fast: false  # if a particular matrix build fails, don't skip the rest
+      matrix:
+        os: [ubuntu-24.04, windows-latest, macos-14]
+
+    env:
+      # Pip now forces us to either make a venv or set this flag, so we will do
+      # this
+      PIP_BREAK_SYSTEM_PACKAGES: 1
+      # We are using dependencies installed from apt
+      PG_DEPS_FROM_SYSTEM: 1
+
+    steps:
+    - uses: actions/checkout@v4.2.0
+
+    - name: Install deps (linux)
+      if: matrix.os == 'ubuntu-24.04'
+      run: sudo apt-get install libfreetype6-dev libportmidi-dev python3-dev
+
+    - name: Install deps (mac)
+      if: matrix.os == 'macos-14'
+      run: brew install freetype portmidi
+
+    # taken from https://wiki.libsdl.org/SDL3/Installation
+    - name: Install SDL3
+      if: matrix.os != 'windows-latest'
+      run: |
+        git clone https://github.com/libsdl-org/SDL
+        cd SDL
+        mkdir build
+        cd build
+        cmake -DCMAKE_BUILD_TYPE=Release ..
+        cmake --build . --config Release --parallel
+        sudo cmake --install . --config Release
+
+    - name: Make sdist and install it
+      run: >
+        python3 -m pip install . -v -Csetup-args=-Dsdl_api=3
+        -Csetup-args=-Dimage=disabled
+        -Csetup-args=-Dmixer=disabled
+        -Csetup-args=-Dfont=disabled
+
+    # - name: Run tests
+    #   env:
+    #     SDL_VIDEODRIVER: "dummy"
+    #     SDL_AUDIODRIVER: "disk"
+    #   run: python3 -m pygame.tests -v --exclude opengl,music,timing --time_out 300
diff --git a/buildconfig/download_win_prebuilt.py b/buildconfig/download_win_prebuilt.py
index 221920026a..219c66ef33 100644
--- a/buildconfig/download_win_prebuilt.py
+++ b/buildconfig/download_win_prebuilt.py
@@ -82,6 +82,10 @@ def get_urls(x86=True, x64=True):
         '9121a66a4bc45d657d0c15300cee6c7f37ade51d',
         ],
         [
+        'https://github.com/libsdl-org/SDL/releases/download/preview-3.1.3/SDL3-devel-3.1.3-VC.zip',
+        '8e4d7104193ba976406fe9968301de6f6b57f342'
+        ],
+        [
         'https://github.com/pygame-community/SDL_image/releases/download/2.8.2-pgce/SDL2_image-devel-2.8.2-VCpgce.zip',
         '983484dd816abf25cdd5bce88ac69dbca1ea713a'
         ],
@@ -242,6 +246,17 @@ def copy(src, dst):
                 'SDL2-2.30.7'
             )
         )
+        copy(
+            os.path.join(
+                temp_dir,
+                'SDL3-devel-3.1.3-VC/SDL3-3.1.3'
+            ),
+            os.path.join(
+                move_to_dir,
+                prebuilt_dir,
+                'SDL3-3.1.3'
+            )
+        )
 
 def update(x86=True, x64=True):
     move_to_dir = "."
diff --git a/meson.build b/meson.build
index d002aaf55b..27cefa4c9c 100644
--- a/meson.build
+++ b/meson.build
@@ -78,6 +78,16 @@ endif
 
 pg_dir = py.get_install_dir() / pg
 
+sdl_api = get_option('sdl_api')
+sdl = 'SDL@0@'.format(sdl_api)
+sdl_mixer = '@0@_mixer'.format(sdl)
+sdl_ttf = '@0@_ttf'.format(sdl)
+sdl_image = '@0@_image'.format(sdl)
+
+if sdl_api == 3
+    add_global_arguments('-DPG_SDL3=1', language: 'c')
+endif
+
 pg_inc_dirs = []
 pg_lib_dirs = []
 if plat == 'win' and host_machine.cpu_family().startswith('x86')
@@ -99,60 +109,68 @@ if plat == 'win' and host_machine.cpu_family().startswith('x86')
         )
     endif
 
-    sdl_ver = '2.30.7'
+    sdl_ver = (sdl_api == 3) ? '3.1.3' : '2.30.7'
     sdl_image_ver = '2.8.2'
     sdl_mixer_ver = '2.8.0'
     sdl_ttf_ver = '2.22.0'
 
     dlls = []
 
-    # SDL2
-    sdl_dir = prebuilt_dir / 'SDL2-@0@'.format(sdl_ver)
+    # SDL
+    sdl_dir = prebuilt_dir / '@0@-@1@'.format(sdl, sdl_ver)
     sdl_lib_dir = sdl_dir / 'lib' / arch_suffix
     pg_inc_dirs += fs.relative_to(sdl_dir / 'include', base_dir)
     pg_lib_dirs += sdl_lib_dir
-    dlls += sdl_lib_dir / 'SDL2.dll'
-
-    # SDL2_image
-    sdl_image_dir = prebuilt_dir / 'SDL2_image-@0@'.format(sdl_image_ver)
-    sdl_image_lib_dir = sdl_image_dir / 'lib' / arch_suffix
-    pg_inc_dirs += fs.relative_to(sdl_image_dir / 'include', base_dir)
-    pg_lib_dirs += sdl_image_lib_dir
-    dlls += [
-        sdl_image_lib_dir / 'SDL2_image.dll',
-        sdl_image_lib_dir / 'optional' / 'libjpeg-62.dll',
-        sdl_image_lib_dir / 'optional' / 'libpng16-16.dll',
-        sdl_image_lib_dir / 'optional' / 'libtiff-5.dll',
-        sdl_image_lib_dir / 'optional' / 'libwebp-7.dll',
-        sdl_image_lib_dir / 'optional' / 'libwebpdemux-2.dll',
-    ]
-
-    # SDL2_mixer
-    sdl_mixer_dir = prebuilt_dir / 'SDL2_mixer-@0@'.format(sdl_mixer_ver)
-    sdl_mixer_lib_dir = sdl_mixer_dir / 'lib' / arch_suffix
-    pg_inc_dirs += fs.relative_to(sdl_mixer_dir / 'include', base_dir)
-    pg_lib_dirs += sdl_mixer_lib_dir
-    dlls += [
-        sdl_mixer_lib_dir / 'SDL2_mixer.dll',
-        sdl_mixer_lib_dir / 'optional' / 'libogg-0.dll',
-        sdl_mixer_lib_dir / 'optional' / 'libopus-0.dll',
-        sdl_mixer_lib_dir / 'optional' / 'libopusfile-0.dll',
-        sdl_mixer_lib_dir / 'optional' / 'libwavpack-1.dll',
-        sdl_mixer_lib_dir / 'optional' / 'libxmp.dll',
-    ]
-
-    # SDL2_ttf
-    sdl_ttf_dir = prebuilt_dir / 'SDL2_ttf-@0@'.format(sdl_ttf_ver)
-    sdl_ttf_lib_dir = sdl_ttf_dir / 'lib' / arch_suffix
-    pg_inc_dirs += fs.relative_to(sdl_ttf_dir / 'include', base_dir)
-    pg_lib_dirs += sdl_ttf_lib_dir
-    dlls += sdl_ttf_lib_dir / 'SDL2_ttf.dll'
+    dlls += sdl_lib_dir / '@0@.dll'.format(sdl)
+
+    # SDL_image
+    if get_option('image').enabled()
+        sdl_image_dir = prebuilt_dir / '@0@-@1@'.format(sdl_image, sdl_image_ver)
+        sdl_image_lib_dir = sdl_image_dir / 'lib' / arch_suffix
+        pg_inc_dirs += fs.relative_to(sdl_image_dir / 'include', base_dir)
+        pg_lib_dirs += sdl_image_lib_dir
+        dlls += [
+            sdl_image_lib_dir / '@0@.dll'.format(sdl_image),
+            sdl_image_lib_dir / 'optional' / 'libjpeg-62.dll',
+            sdl_image_lib_dir / 'optional' / 'libpng16-16.dll',
+            sdl_image_lib_dir / 'optional' / 'libtiff-5.dll',
+            sdl_image_lib_dir / 'optional' / 'libwebp-7.dll',
+            sdl_image_lib_dir / 'optional' / 'libwebpdemux-2.dll',
+        ]
+    endif
+
+    # SDL_mixer
+    if get_option('mixer').enabled()
+        sdl_mixer_dir = prebuilt_dir / '@0@-@1@'.format(sdl_mixer, sdl_mixer_ver)
+        sdl_mixer_lib_dir = sdl_mixer_dir / 'lib' / arch_suffix
+        pg_inc_dirs += fs.relative_to(sdl_mixer_dir / 'include', base_dir)
+        pg_lib_dirs += sdl_mixer_lib_dir
+        dlls += [
+            sdl_mixer_lib_dir / '@0@.dll'.format(sdl_mixer),
+            sdl_mixer_lib_dir / 'optional' / 'libogg-0.dll',
+            sdl_mixer_lib_dir / 'optional' / 'libopus-0.dll',
+            sdl_mixer_lib_dir / 'optional' / 'libopusfile-0.dll',
+            sdl_mixer_lib_dir / 'optional' / 'libwavpack-1.dll',
+            sdl_mixer_lib_dir / 'optional' / 'libxmp.dll',
+        ]
+    endif
+
+    # SDL_ttf
+    if get_option('font').enabled()
+        sdl_ttf_dir = prebuilt_dir / '@0@-@1@'.format(sdl_ttf, sdl_ttf_ver)
+        sdl_ttf_lib_dir = sdl_ttf_dir / 'lib' / arch_suffix
+        pg_inc_dirs += fs.relative_to(sdl_ttf_dir / 'include', base_dir)
+        pg_lib_dirs += sdl_ttf_lib_dir
+        dlls += sdl_ttf_lib_dir / '@0@.dll'.format(sdl_ttf)
+    endif
 
     # freetype, portmidi and porttime
-    common_lib_dir = prebuilt_dir / 'lib'
-    pg_inc_dirs += fs.relative_to(prebuilt_dir / 'include', base_dir)
-    pg_lib_dirs += common_lib_dir
-    dlls += [common_lib_dir / 'freetype.dll', common_lib_dir / 'portmidi.dll']
+    if get_option('freetype').enabled() and get_option('midi').enabled()
+        common_lib_dir = prebuilt_dir / 'lib'
+        pg_inc_dirs += fs.relative_to(prebuilt_dir / 'include', base_dir)
+        pg_lib_dirs += common_lib_dir
+        dlls += [common_lib_dir / 'freetype.dll', common_lib_dir / 'portmidi.dll']
+    endif
 
     # clean unneeded file that causes build issues
     unneeded_file = common_lib_dir / 'libportmidi.dll.a'
@@ -183,7 +201,7 @@ else
     foreach inc_dir : bases
         foreach sub_inc : [
             '',
-            '/SDL2',
+            '/@0@'.format(sdl),
             '/freetype2',
         ]
             full_inc = inc_dir / 'include' + sub_inc
@@ -204,45 +222,45 @@ else
 endif
 
 # TODO: add version constraints?
-sdl_dep = dependency('sdl2', required: false)
+sdl_dep = dependency(sdl, required: false)
 if not sdl_dep.found()
     sdl_dep = declare_dependency(
         include_directories: pg_inc_dirs,
-        dependencies: cc.find_library('SDL2', dirs: pg_lib_dirs),
+        dependencies: cc.find_library(sdl, dirs: pg_lib_dirs),
     )
 endif
 
 # optional
-sdl_image_dep = dependency('SDL2_image', required: false)
+sdl_image_dep = dependency(sdl_image, required: false)
 if not sdl_image_dep.found()
     sdl_image_dep = declare_dependency(
         include_directories: pg_inc_dirs,
         dependencies: cc.find_library(
-            'SDL2_image',
+            sdl_image,
             dirs: pg_lib_dirs,
             required: get_option('image'),
         ),
     )
 endif
 
-sdl_mixer_dep = dependency('SDL2_mixer', required: false)
+sdl_mixer_dep = dependency(sdl_mixer, required: false)
 if not sdl_mixer_dep.found()
     sdl_mixer_dep = declare_dependency(
         include_directories: pg_inc_dirs,
         dependencies: cc.find_library(
-            'SDL2_mixer',
+            sdl_mixer,
             dirs: pg_lib_dirs,
             required: get_option('mixer'),
         ),
     )
 endif
 
-sdl_ttf_dep = dependency('SDL2_ttf', required: false)
+sdl_ttf_dep = dependency(sdl_ttf, required: false)
 if not sdl_ttf_dep.found()
     sdl_ttf_dep = declare_dependency(
         include_directories: pg_inc_dirs,
         dependencies: cc.find_library(
-            'SDL2_ttf',
+            sdl_ttf,
             dirs: pg_lib_dirs,
             required: get_option('font'),
         ),
@@ -296,10 +314,10 @@ pg_base_deps = [sdl_dep, py_dep]
 
 summary(
     {
-        'SDL2': sdl_dep.found(),
-        'SDL2_image': sdl_image_dep.found(),
-        'SDL2_mixer': sdl_mixer_dep.found(),
-        'SDL2_ttf': sdl_ttf_dep.found(),
+        sdl: sdl_dep.found(),
+        sdl_image: sdl_image_dep.found(),
+        sdl_mixer: sdl_mixer_dep.found(),
+        sdl_ttf: sdl_ttf_dep.found(),
         'freetype2': freetype_dep.found(),
         'portmidi': portmidi_dep.found(),
         'porttime': portmidi_dep.found() ? porttime_dep.found() : false,
diff --git a/meson_options.txt b/meson_options.txt
index 8d409fba9c..e433b07f52 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -37,3 +37,6 @@ option('error_docs_missing', type: 'boolean', value: 'false')
 # Controls whether to do a coverage build.
 # This argument must be used together with the editable install.
 option('coverage', type: 'boolean', value: false)
+
+# Controls whether to use SDL3 instead of SDL2. The default is to use SDL2
+option('sdl_api', type: 'integer', min: 2, max: 3, value: 2)
diff --git a/src_c/SDL_gfx/SDL_gfxPrimitives.h b/src_c/SDL_gfx/SDL_gfxPrimitives.h
index ec5dc17c3b..4f75913023 100644
--- a/src_c/SDL_gfx/SDL_gfxPrimitives.h
+++ b/src_c/SDL_gfx/SDL_gfxPrimitives.h
@@ -14,7 +14,11 @@ LGPL (c) A. Schiffler
 #define M_PI 3.1415926535897932384626433832795
 #endif
 
-#include "SDL.h"
+#ifdef PG_SDL3
+#include <SDL3/SDL.h>
+#else
+#include <SDL.h>
+#endif
 
 /* Set up for C function definitions, even when using C++ */
 #ifdef __cplusplus
diff --git a/src_c/_pygame.h b/src_c/_pygame.h
index e87986d776..d330a08290 100644
--- a/src_c/_pygame.h
+++ b/src_c/_pygame.h
@@ -41,7 +41,11 @@
 #undef PYPY_VERSION
 #endif
 
+#ifdef PG_SDL3
+#include <SDL3/SDL.h>
+#else
 #include <SDL.h>
+#endif
 
 #if SDL_VERSION_ATLEAST(3, 0, 0)
 #define PG_ShowCursor SDL_ShowCursor
diff --git a/src_c/meson.build b/src_c/meson.build
index 8e8287c834..70286af44e 100644
--- a/src_c/meson.build
+++ b/src_c/meson.build
@@ -1,4 +1,7 @@
 # first the "required" modules
+
+# TODO: support SDL3
+if sdl_api != 3
 base = py.extension_module(
     'base',
     'base.c',
@@ -7,7 +10,10 @@ base = py.extension_module(
     install: true,
     subdir: pg,
 )
+endif
 
+# TODO: support SDL3
+if sdl_api != 3
 color = py.extension_module(
     'color',
     'color.c',
@@ -16,7 +22,10 @@ color = py.extension_module(
     install: true,
     subdir: pg,
 )
+endif
 
+# TODO: support SDL3
+if sdl_api != 3
 constants = py.extension_module(
     'constants',
     'constants.c',
@@ -25,7 +34,10 @@ constants = py.extension_module(
     install: true,
     subdir: pg,
 )
+endif
 
+# TODO: support SDL3
+if sdl_api != 3
 display = py.extension_module(
     'display',
     'display.c',
@@ -34,7 +46,10 @@ display = py.extension_module(
     install: true,
     subdir: pg,
 )
+endif
 
+# TODO: support SDL3
+if sdl_api != 3
 event = py.extension_module(
     'event',
     'event.c',
@@ -43,7 +58,10 @@ event = py.extension_module(
     install: true,
     subdir: pg,
 )
+endif
 
+# TODO: support SDL3
+if sdl_api != 3
 key = py.extension_module(
     'key',
     'key.c',
@@ -52,7 +70,10 @@ key = py.extension_module(
     install: true,
     subdir: pg,
 )
+endif
 
+# TODO: support SDL3
+if sdl_api != 3
 mouse = py.extension_module(
     'mouse',
     'mouse.c',
@@ -61,7 +82,10 @@ mouse = py.extension_module(
     install: true,
     subdir: pg,
 )
+endif
 
+# TODO: support SDL3
+if sdl_api != 3
 rect = py.extension_module(
     'rect',
     ['rect.c', 'pgcompat_rect.c'],
@@ -70,7 +94,10 @@ rect = py.extension_module(
     install: true,
     subdir: pg,
 )
+endif
 
+# TODO: support SDL3
+if sdl_api != 3
 rwobject = py.extension_module(
     'rwobject',
     'rwobject.c',
@@ -79,7 +106,10 @@ rwobject = py.extension_module(
     install: true,
     subdir: pg,
 )
+endif
 
+# TODO: support SDL3
+if sdl_api != 3
 simd_blitters_avx2 = static_library(
     'simd_blitters_avx2',
     'simd_blitters_avx2.c',
@@ -126,7 +156,10 @@ surface = py.extension_module(
     install: true,
     subdir: pg,
 )
+endif
 
+# TODO: support SDL3
+if sdl_api != 3
 surflock = py.extension_module(
     'surflock',
     'surflock.c',
@@ -135,7 +168,10 @@ surflock = py.extension_module(
     install: true,
     subdir: pg,
 )
+endif
 
+# TODO: support SDL3
+if sdl_api != 3
 time = py.extension_module(
     'time',
     'time.c',
@@ -144,7 +180,10 @@ time = py.extension_module(
     install: true,
     subdir: pg,
 )
+endif
 
+# TODO: support SDL3
+if sdl_api != 3
 joystick = py.extension_module(
     'joystick',
     'joystick.c',
@@ -153,7 +192,11 @@ joystick = py.extension_module(
     install: true,
     subdir: pg,
 )
+endif
+
 
+# TODO: support SDL3
+if sdl_api != 3
 draw = py.extension_module(
     'draw',
     'draw.c',
@@ -162,7 +205,10 @@ draw = py.extension_module(
     install: true,
     subdir: pg,
 )
+endif
 
+# TODO: support SDL3
+if sdl_api != 3
 image = py.extension_module(
     'image',
     'image.c',
@@ -171,7 +217,10 @@ image = py.extension_module(
     install: true,
     subdir: pg,
 )
+endif
 
+# TODO: support SDL3
+if sdl_api != 3
 simd_transform_avx2 = static_library(
     'simd_transform_avx2',
     'simd_transform_avx2.c',
@@ -212,7 +261,10 @@ transform = py.extension_module(
     install: true,
     subdir: pg,
 )
+endif
 
+# TODO: support SDL3
+if sdl_api != 3
 mask = py.extension_module(
     'mask',
     ['mask.c', 'bitmask.c'],
@@ -221,7 +273,10 @@ mask = py.extension_module(
     install: true,
     subdir: pg,
 )
+endif
 
+# TODO: support SDL3
+if sdl_api != 3
 bufferproxy = py.extension_module(
     'bufferproxy',
     'bufferproxy.c',
@@ -230,7 +285,10 @@ bufferproxy = py.extension_module(
     install: true,
     subdir: pg,
 )
+endif
 
+# TODO: support SDL3
+if sdl_api != 3
 pixelarray = py.extension_module(
     'pixelarray',
     'pixelarray.c',
@@ -239,7 +297,10 @@ pixelarray = py.extension_module(
     install: true,
     subdir: pg,
 )
+endif
 
+# TODO: support SDL3
+if sdl_api != 3
 math = py.extension_module(
     'math',
     'math.c',
@@ -248,7 +309,10 @@ math = py.extension_module(
     install: true,
     subdir: pg,
 )
+endif
 
+# TODO: support SDL3
+if sdl_api != 3
 pixelcopy = py.extension_module(
     'pixelcopy',
     'pixelcopy.c',
@@ -257,7 +321,10 @@ pixelcopy = py.extension_module(
     install: true,
     subdir: pg,
 )
+endif
 
+# TODO: support SDL3
+if sdl_api != 3
 newbuffer = py.extension_module(
     'newbuffer',
     'newbuffer.c',
@@ -266,8 +333,11 @@ newbuffer = py.extension_module(
     install: true,
     subdir: pg,
 )
+endif
 
 # new/experimental/uncommon stuff, but built by default
+# TODO: support SDL3
+if sdl_api != 3
 system = py.extension_module(
     'system',
     'system.c',
@@ -276,7 +346,10 @@ system = py.extension_module(
     install: true,
     subdir: pg,
 )
+endif
 
+# TODO: support SDL3
+if sdl_api != 3
 geometry = py.extension_module(
     'geometry',
     'geometry.c',
@@ -285,7 +358,10 @@ geometry = py.extension_module(
     install: true,
     subdir: pg,
 )
+endif
 
+# TODO: support SDL3
+if sdl_api != 3
 window = py.extension_module(
     'window',
     'window.c',
@@ -294,7 +370,10 @@ window = py.extension_module(
     install: true,
     subdir: pg,
 )
+endif
 
+# TODO: support SDL3
+if sdl_api != 3
 gfxdraw = py.extension_module(
     'gfxdraw',
     ['gfxdraw.c', 'SDL_gfx/SDL_gfxPrimitives.c'],
@@ -303,11 +382,18 @@ gfxdraw = py.extension_module(
     install: true,
     subdir: pg,
 )
+endif
 
 # pygame._sdl2
+# TODO: support SDL3
+if sdl_api != 3
 subdir('_sdl2')
+endif
 
 # pygame._camera
+
+# TODO: support SDL3
+if sdl_api != 3
 pg_camera_sources = ['_camera.c']
 pg_camera_link = []
 if plat == 'win'
@@ -338,8 +424,12 @@ _camera = py.extension_module(
     install: true,
     subdir: pg,
 )
+endif
 
 # pygame.scrap
+
+# TODO: support SDL3
+if sdl_api != 3
 pg_scrap_link = [] # TODO: should this link logic be improved/made meson-ey?
 if plat == 'win'
     pg_scrap_link += ['-luser32', '-lgdi32']
@@ -354,8 +444,13 @@ scrap = py.extension_module(
     install: true,
     subdir: pg,
 )
+endif
 
 # optional modules
+
+# TODO: support SDL3
+if sdl_api != 3
+
 if sdl_image_dep.found()
     imageext = py.extension_module(
         'imageext',
@@ -417,6 +512,8 @@ if freetype_dep.found()
     )
 endif
 
+endif
+
 if portmidi_dep.found()
     pypm = py.extension_module(
         'pypm',
diff --git a/src_c/palette.h b/src_c/palette.h
index 702840a624..699a40edb4 100644
--- a/src_c/palette.h
+++ b/src_c/palette.h
@@ -23,7 +23,11 @@
 #ifndef PALETTE_H
 #define PALETTE_H
 
+#ifdef PG_SDL3
+#include <SDL3/SDL.h>
+#else
 #include <SDL.h>
+#endif
 
 /* SDL 2 does not assign a default palette color scheme to a new 8 bit
  * surface. Instead, the palette is set all white. This defines the SDL 1.2
diff --git a/src_c/pgcompat.c b/src_c/pgcompat.c
index 5d64d2e6fd..178102e186 100644
--- a/src_c/pgcompat.c
+++ b/src_c/pgcompat.c
@@ -1 +1,5 @@
+#ifdef PG_SDL3
+#include <SDL3/SDL.h>
+#else
 #include <SDL.h>
+#endif
diff --git a/src_c/pgcompat_rect.h b/src_c/pgcompat_rect.h
index 643059dfcb..5bba69dd21 100644
--- a/src_c/pgcompat_rect.h
+++ b/src_c/pgcompat_rect.h
@@ -1,7 +1,11 @@
 #ifndef PGCOMPAT_RECT_H
 #define PGCOMPAT_RECT_H
 
+#ifdef PG_SDL3
+#include <SDL3/SDL.h>
+#else
 #include <SDL.h>
+#endif
 
 /* SDL 2.0.22 provides some utility functions for FRects */
 #if !(SDL_VERSION_ATLEAST(2, 0, 22))
diff --git a/src_c/scale2x.c b/src_c/scale2x.c
index 61a9beffa5..9249a05a78 100644
--- a/src_c/scale2x.c
+++ b/src_c/scale2x.c
@@ -30,7 +30,12 @@
    surprised with this code!
 */
 
+#ifdef PG_SDL3
+#include <SDL3/SDL.h>
+#else
 #include <SDL.h>
+#endif
+
 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
 
diff --git a/src_c/scrap.c b/src_c/scrap.c
index b34cb6b06e..ef580e7a99 100644
--- a/src_c/scrap.c
+++ b/src_c/scrap.c
@@ -23,7 +23,11 @@
 #include <limits.h>
 #include <stdio.h>
 
-#include "SDL.h"
+#ifdef PG_SDL3
+#include <SDL3/SDL.h>
+#else
+#include <SDL.h>
+#endif
 
 #include "SDL_syswm.h"
 
diff --git a/src_c/scrap_sdl2.c b/src_c/scrap_sdl2.c
index 9c2121c105..5de1f4cdbc 100644
--- a/src_c/scrap_sdl2.c
+++ b/src_c/scrap_sdl2.c
@@ -1,5 +1,10 @@
-#include "SDL.h"
-#include "SDL_clipboard.h"
+#ifdef PG_SDL3
+#include <SDL3/SDL.h>
+#include <SDL3/SDL_clipboard.h>
+#else
+#include <SDL.h>
+#include <SDL_clipboard.h>
+#endif
 
 #define PYGAME_SCRAP_FREE_STRING 1
 
diff --git a/src_c/surface.h b/src_c/surface.h
index 3ae05eb408..4009579d1d 100644
--- a/src_c/surface.h
+++ b/src_c/surface.h
@@ -29,7 +29,12 @@
 #undef _POSIX_C_SOURCE
 #endif
 
+#ifdef PG_SDL3
+#include <SDL3/SDL.h>
+#else
 #include <SDL.h>
+#endif
+
 #include "pygame.h"
 
 /* Blend modes */