2
0
Эх сурвалжийг харах

Added SDL_RotateSurface()

Fixes https://github.com/libsdl-org/SDL/issues/14269
Sam Lantinga 2 өдөр өмнө
parent
commit
e18d63a4e2

+ 2 - 2
VisualC-GDK/SDL/SDL.vcxproj

@@ -504,7 +504,6 @@
     <ClInclude Include="..\..\src\render\software\SDL_drawline.h" />
     <ClInclude Include="..\..\src\render\software\SDL_drawpoint.h" />
     <ClInclude Include="..\..\src\render\software\SDL_render_sw_c.h" />
-    <ClInclude Include="..\..\src\render\software\SDL_rotate.h" />
     <ClInclude Include="..\..\src\render\software\SDL_triangle.h" />
     <ClInclude Include="..\..\src\SDL_assert_c.h" />
     <ClInclude Include="..\..\src\SDL_error_c.h" />
@@ -604,6 +603,7 @@
     <ClInclude Include="..\..\src\video\SDL_pixels_c.h" />
     <ClInclude Include="..\..\src\video\SDL_rect_c.h" />
     <ClInclude Include="..\..\src\video\SDL_RLEaccel_c.h" />
+    <ClInclude Include="..\..\src\video\SDL_rotate.h" />
     <ClInclude Include="..\..\src\video\SDL_stb_c.h" />
     <ClInclude Include="..\..\src\video\SDL_surface_c.h" />
     <ClInclude Include="..\..\src\video\SDL_sysvideo.h" />
@@ -809,7 +809,6 @@
     <ClCompile Include="..\..\src\render\software\SDL_drawline.c" />
     <ClCompile Include="..\..\src\render\software\SDL_drawpoint.c" />
     <ClCompile Include="..\..\src\render\software\SDL_render_sw.c" />
-    <ClCompile Include="..\..\src\render\software\SDL_rotate.c" />
     <ClCompile Include="..\..\src\render\software\SDL_triangle.c" />
     <ClCompile Include="..\..\src\render\vulkan\SDL_render_vulkan.c" />
     <ClCompile Include="..\..\src\render\vulkan\SDL_shaders_vulkan.c" />
@@ -891,6 +890,7 @@
     <ClCompile Include="..\..\src\video\SDL_pixels.c" />
     <ClCompile Include="..\..\src\video\SDL_rect.c" />
     <ClCompile Include="..\..\src\video\SDL_RLEaccel.c" />
+    <ClCompile Include="..\..\src\video\SDL_rotate.c" />
     <ClCompile Include="..\..\src\video\SDL_stb.c" />
     <ClCompile Include="..\..\src\video\SDL_stretch.c" />
     <ClCompile Include="..\..\src\video\SDL_surface.c" />

+ 2 - 2
VisualC-GDK/SDL/SDL.vcxproj.filters

@@ -127,7 +127,6 @@
     <ClCompile Include="..\..\src\render\software\SDL_drawline.c" />
     <ClCompile Include="..\..\src\render\software\SDL_drawpoint.c" />
     <ClCompile Include="..\..\src\render\software\SDL_render_sw.c" />
-    <ClCompile Include="..\..\src\render\software\SDL_rotate.c" />
     <ClCompile Include="..\..\src\render\software\SDL_triangle.c" />
     <ClCompile Include="..\..\src\SDL.c" />
     <ClCompile Include="..\..\src\SDL_assert.c" />
@@ -186,6 +185,7 @@
     <ClCompile Include="..\..\src\video\SDL_pixels.c" />
     <ClCompile Include="..\..\src\video\SDL_rect.c" />
     <ClCompile Include="..\..\src\video\SDL_RLEaccel.c" />
+    <ClCompile Include="..\..\src\video\SDL_rotate.c" />
     <ClCompile Include="..\..\src\video\SDL_stb.c" />
     <ClCompile Include="..\..\src\video\SDL_stretch.c" />
     <ClCompile Include="..\..\src\video\SDL_surface.c" />
@@ -406,7 +406,6 @@
     <ClInclude Include="..\..\src\render\software\SDL_drawline.h" />
     <ClInclude Include="..\..\src\render\software\SDL_drawpoint.h" />
     <ClInclude Include="..\..\src\render\software\SDL_render_sw_c.h" />
-    <ClInclude Include="..\..\src\render\software\SDL_rotate.h" />
     <ClInclude Include="..\..\src\render\software\SDL_triangle.h" />
     <ClInclude Include="..\..\src\SDL_assert_c.h" />
     <ClInclude Include="..\..\src\SDL_error_c.h" />
@@ -460,6 +459,7 @@
     <ClInclude Include="..\..\src\video\SDL_pixels_c.h" />
     <ClInclude Include="..\..\src\video\SDL_rect_c.h" />
     <ClInclude Include="..\..\src\video\SDL_RLEaccel_c.h" />
+    <ClInclude Include="..\..\src\video\SDL_rotate.h" />
     <ClInclude Include="..\..\src\video\SDL_stb_c.h" />
     <ClInclude Include="..\..\src\video\SDL_surface_c.h" />
     <ClInclude Include="..\..\src\video\SDL_sysvideo.h" />

+ 2 - 2
VisualC/SDL/SDL.vcxproj

@@ -417,7 +417,6 @@
     <ClInclude Include="..\..\src\render\software\SDL_drawline.h" />
     <ClInclude Include="..\..\src\render\software\SDL_drawpoint.h" />
     <ClInclude Include="..\..\src\render\software\SDL_render_sw_c.h" />
-    <ClInclude Include="..\..\src\render\software\SDL_rotate.h" />
     <ClInclude Include="..\..\src\render\software\SDL_triangle.h" />
     <ClInclude Include="..\..\src\render\vulkan\SDL_shaders_vulkan.h" />
     <ClInclude Include="..\..\src\SDL_assert_c.h" />
@@ -513,6 +512,7 @@
     <ClInclude Include="..\..\src\video\SDL_pixels_c.h" />
     <ClInclude Include="..\..\src\video\SDL_rect_c.h" />
     <ClInclude Include="..\..\src\video\SDL_RLEaccel_c.h" />
+    <ClInclude Include="..\..\src\video\SDL_rotate.h" />
     <ClInclude Include="..\..\src\video\SDL_stb_c.h" />
     <ClInclude Include="..\..\src\video\SDL_surface_c.h" />
     <ClInclude Include="..\..\src\video\SDL_sysvideo.h" />
@@ -676,7 +676,6 @@
     <ClCompile Include="..\..\src\render\software\SDL_drawline.c" />
     <ClCompile Include="..\..\src\render\software\SDL_drawpoint.c" />
     <ClCompile Include="..\..\src\render\software\SDL_render_sw.c" />
-    <ClCompile Include="..\..\src\render\software\SDL_rotate.c" />
     <ClCompile Include="..\..\src\render\software\SDL_triangle.c" />
     <ClCompile Include="..\..\src\SDL.c" />
     <ClCompile Include="..\..\src\SDL_assert.c" />
@@ -747,6 +746,7 @@
     <ClCompile Include="..\..\src\video\SDL_pixels.c" />
     <ClCompile Include="..\..\src\video\SDL_rect.c" />
     <ClCompile Include="..\..\src\video\SDL_RLEaccel.c" />
+    <ClCompile Include="..\..\src\video\SDL_rotate.c" />
     <ClCompile Include="..\..\src\video\SDL_stb.c" />
     <ClCompile Include="..\..\src\video\SDL_stretch.c" />
     <ClCompile Include="..\..\src\video\SDL_surface.c" />

+ 6 - 6
VisualC/SDL/SDL.vcxproj.filters

@@ -693,6 +693,9 @@
     <ClInclude Include="..\..\src\video\SDL_RLEaccel_c.h">
       <Filter>video</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\src\video\SDL_rotate.h">
+      <Filter>video</Filter>
+    </ClInclude>
     <ClInclude Include="..\..\src\video\SDL_surface_c.h">
       <Filter>video</Filter>
     </ClInclude>
@@ -885,9 +888,6 @@
     <ClInclude Include="..\..\src\render\software\SDL_render_sw_c.h">
       <Filter>render\software</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\src\render\software\SDL_rotate.h">
-      <Filter>render\software</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\src\render\software\SDL_triangle.h">
       <Filter>render\software</Filter>
     </ClInclude>
@@ -1380,6 +1380,9 @@
     <ClCompile Include="..\..\src\video\SDL_rect.c">
       <Filter>video</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\src\video\SDL_rotate.c">
+      <Filter>video</Filter>
+    </ClCompile>
     <ClCompile Include="..\..\src\video\SDL_stb.c">
       <Filter>video</Filter>
     </ClCompile>
@@ -1589,9 +1592,6 @@
     <ClCompile Include="..\..\src\render\software\SDL_render_sw.c">
       <Filter>render\software</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\src\render\software\SDL_rotate.c">
-      <Filter>render\software</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\src\render\software\SDL_triangle.c">
       <Filter>render\software</Filter>
     </ClCompile>

+ 8 - 8
Xcode/SDL/SDL.xcodeproj/project.pbxproj

@@ -288,7 +288,6 @@
 		A7D8B9E323E2514400DCD162 /* SDL_drawline.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A8F123E2514000DCD162 /* SDL_drawline.c */; };
 		A7D8B9E923E2514400DCD162 /* SDL_blendline.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A8F223E2514000DCD162 /* SDL_blendline.h */; };
 		A7D8B9EF23E2514400DCD162 /* SDL_drawpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A8F323E2514000DCD162 /* SDL_drawpoint.h */; };
-		A7D8B9F523E2514400DCD162 /* SDL_rotate.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A8F423E2514000DCD162 /* SDL_rotate.c */; };
 		A7D8B9FB23E2514400DCD162 /* SDL_render_sw_c.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A8F523E2514000DCD162 /* SDL_render_sw_c.h */; };
 		A7D8BA0123E2514400DCD162 /* SDL_blendfillrect.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A8F623E2514000DCD162 /* SDL_blendfillrect.h */; };
 		A7D8BA0723E2514400DCD162 /* SDL_drawline.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A8F723E2514000DCD162 /* SDL_drawline.h */; };
@@ -298,7 +297,6 @@
 		A7D8BA1F23E2514400DCD162 /* SDL_blendline.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A8FB23E2514000DCD162 /* SDL_blendline.c */; };
 		A7D8BA2523E2514400DCD162 /* SDL_drawpoint.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A8FC23E2514000DCD162 /* SDL_drawpoint.c */; };
 		A7D8BA2B23E2514400DCD162 /* SDL_blendfillrect.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A8FD23E2514000DCD162 /* SDL_blendfillrect.c */; };
-		A7D8BA3123E2514400DCD162 /* SDL_rotate.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A8FE23E2514000DCD162 /* SDL_rotate.h */; };
 		A7D8BA4923E2514400DCD162 /* SDL_render_gles2.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A90423E2514000DCD162 /* SDL_render_gles2.c */; };
 		A7D8BA4F23E2514400DCD162 /* SDL_shaders_gles2.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A90523E2514000DCD162 /* SDL_shaders_gles2.h */; };
 		A7D8BA5523E2514400DCD162 /* SDL_gles2funcs.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A90623E2514000DCD162 /* SDL_gles2funcs.h */; };
@@ -523,6 +521,8 @@
 		F3D60A8328C16A1900788A3A /* SDL_hidapi_wii.c in Sources */ = {isa = PBXBuildFile; fileRef = F3D60A8228C16A1800788A3A /* SDL_hidapi_wii.c */; };
 		F3D8BDFC2D6D2C7000B22FA1 /* SDL_eventwatch_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F3D8BDFB2D6D2C7000B22FA1 /* SDL_eventwatch_c.h */; };
 		F3D8BDFD2D6D2C7000B22FA1 /* SDL_eventwatch.c in Sources */ = {isa = PBXBuildFile; fileRef = F3D8BDFA2D6D2C7000B22FA1 /* SDL_eventwatch.c */; };
+		F3DB66342EA9ACC300568044 /* SDL_rotate.c in Sources */ = {isa = PBXBuildFile; fileRef = F3DB66332EA9ACC300568044 /* SDL_rotate.c */; };
+		F3DB66352EA9ACC300568044 /* SDL_rotate.h in Headers */ = {isa = PBXBuildFile; fileRef = F3DB66322EA9ACC300568044 /* SDL_rotate.h */; };
 		F3DC38C92E5FC60300CD73DE /* SDL_libusb.h in Headers */ = {isa = PBXBuildFile; fileRef = F3DC38C72E5FC60300CD73DE /* SDL_libusb.h */; };
 		F3DC38CA2E5FC60300CD73DE /* SDL_libusb.c in Sources */ = {isa = PBXBuildFile; fileRef = F3DC38C82E5FC60300CD73DE /* SDL_libusb.c */; };
 		F3DDCC562AFD42B600B0842B /* SDL_clipboard_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F3DDCC4D2AFD42B500B0842B /* SDL_clipboard_c.h */; };
@@ -877,7 +877,6 @@
 		A7D8A8F123E2514000DCD162 /* SDL_drawline.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_drawline.c; sourceTree = "<group>"; };
 		A7D8A8F223E2514000DCD162 /* SDL_blendline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_blendline.h; sourceTree = "<group>"; };
 		A7D8A8F323E2514000DCD162 /* SDL_drawpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_drawpoint.h; sourceTree = "<group>"; };
-		A7D8A8F423E2514000DCD162 /* SDL_rotate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_rotate.c; sourceTree = "<group>"; };
 		A7D8A8F523E2514000DCD162 /* SDL_render_sw_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_render_sw_c.h; sourceTree = "<group>"; };
 		A7D8A8F623E2514000DCD162 /* SDL_blendfillrect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_blendfillrect.h; sourceTree = "<group>"; };
 		A7D8A8F723E2514000DCD162 /* SDL_drawline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_drawline.h; sourceTree = "<group>"; };
@@ -887,7 +886,6 @@
 		A7D8A8FB23E2514000DCD162 /* SDL_blendline.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_blendline.c; sourceTree = "<group>"; };
 		A7D8A8FC23E2514000DCD162 /* SDL_drawpoint.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_drawpoint.c; sourceTree = "<group>"; };
 		A7D8A8FD23E2514000DCD162 /* SDL_blendfillrect.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_blendfillrect.c; sourceTree = "<group>"; };
-		A7D8A8FE23E2514000DCD162 /* SDL_rotate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_rotate.h; sourceTree = "<group>"; };
 		A7D8A90423E2514000DCD162 /* SDL_render_gles2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_render_gles2.c; sourceTree = "<group>"; };
 		A7D8A90523E2514000DCD162 /* SDL_shaders_gles2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_shaders_gles2.h; sourceTree = "<group>"; };
 		A7D8A90623E2514000DCD162 /* SDL_gles2funcs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_gles2funcs.h; sourceTree = "<group>"; };
@@ -1105,6 +1103,8 @@
 		F3D60A8228C16A1800788A3A /* SDL_hidapi_wii.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_wii.c; sourceTree = "<group>"; };
 		F3D8BDFA2D6D2C7000B22FA1 /* SDL_eventwatch.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SDL_eventwatch.c; sourceTree = "<group>"; };
 		F3D8BDFB2D6D2C7000B22FA1 /* SDL_eventwatch_c.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDL_eventwatch_c.h; sourceTree = "<group>"; };
+		F3DB66322EA9ACC300568044 /* SDL_rotate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDL_rotate.h; sourceTree = "<group>"; };
+		F3DB66332EA9ACC300568044 /* SDL_rotate.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SDL_rotate.c; sourceTree = "<group>"; };
 		F3DC38C72E5FC60300CD73DE /* SDL_libusb.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDL_libusb.h; sourceTree = "<group>"; };
 		F3DC38C82E5FC60300CD73DE /* SDL_libusb.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SDL_libusb.c; sourceTree = "<group>"; };
 		F3DDCC4D2AFD42B500B0842B /* SDL_clipboard_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_clipboard_c.h; sourceTree = "<group>"; };
@@ -1661,6 +1661,8 @@
 				F3DDCC542AFD42B600B0842B /* SDL_rect_impl.h */,
 				A7D8A61523E2513D00DCD162 /* SDL_RLEaccel.c */,
 				A7D8A76723E2513E00DCD162 /* SDL_RLEaccel_c.h */,
+				F3DB66322EA9ACC300568044 /* SDL_rotate.h */,
+				F3DB66332EA9ACC300568044 /* SDL_rotate.c */,
 				F3EFA5E92D5AB97300BCF22F /* SDL_stb.c */,
 				F3EFA5EA2D5AB97300BCF22F /* SDL_stb_c.h */,
 				A7D8A60323E2513D00DCD162 /* SDL_stretch.c */,
@@ -2220,8 +2222,6 @@
 				A7D8A8F323E2514000DCD162 /* SDL_drawpoint.h */,
 				A7D8A8F523E2514000DCD162 /* SDL_render_sw_c.h */,
 				A7D8A8F923E2514000DCD162 /* SDL_render_sw.c */,
-				A7D8A8F423E2514000DCD162 /* SDL_rotate.c */,
-				A7D8A8FE23E2514000DCD162 /* SDL_rotate.h */,
 			);
 			path = software;
 			sourceTree = "<group>";
@@ -2532,6 +2532,7 @@
 				A7D8AEEE23E2514100DCD162 /* SDL_cocoaopengles.h in Headers */,
 				F3D46ACA2D20625800D9CBDF /* SDL_storage.h in Headers */,
 				F3D46ACB2D20625800D9CBDF /* SDL_sensor.h in Headers */,
+				F3DB66352EA9ACC300568044 /* SDL_rotate.h in Headers */,
 				F3D46ACC2D20625800D9CBDF /* SDL_properties.h in Headers */,
 				F3D46ACD2D20625800D9CBDF /* SDL_bits.h in Headers */,
 				F3D46ACE2D20625800D9CBDF /* SDL_keyboard.h in Headers */,
@@ -2669,7 +2670,6 @@
 				F3DDCC5D2AFD42B600B0842B /* SDL_rect_impl.h in Headers */,
 				A7D8B9FB23E2514400DCD162 /* SDL_render_sw_c.h in Headers */,
 				E4F257972C81903800FCEAFC /* SDL_sysgpu.h in Headers */,
-				A7D8BA3123E2514400DCD162 /* SDL_rotate.h in Headers */,
 				A7D8A98D23E2514000DCD162 /* SDL_sensor_c.h in Headers */,
 				A7D8BA7323E2514400DCD162 /* SDL_shaders_gl.h in Headers */,
 				A7D8BA4F23E2514400DCD162 /* SDL_shaders_gles2.h in Headers */,
@@ -2912,7 +2912,6 @@
 				A7D8AEC423E2514100DCD162 /* SDL_cocoaevents.m in Sources */,
 				E479118F2BA9555500CE3B7F /* SDL_genericstorage.c in Sources */,
 				A7D8B86623E2514400DCD162 /* SDL_audiocvt.c in Sources */,
-				A7D8B9F523E2514400DCD162 /* SDL_rotate.c in Sources */,
 				A7D8BBE323E2574800DCD162 /* SDL_uikitvideo.m in Sources */,
 				F338A1182D1B37D8007CDFDF /* SDL_tray.m in Sources */,
 				5616CA4E252BB2A6005D5928 /* SDL_sysurl.m in Sources */,
@@ -2940,6 +2939,7 @@
 				E4F257962C81903800FCEAFC /* SDL_gpu.c in Sources */,
 				F3D60A8328C16A1900788A3A /* SDL_hidapi_wii.c in Sources */,
 				A7D8B9DD23E2514400DCD162 /* SDL_blendpoint.c in Sources */,
+				F3DB66342EA9ACC300568044 /* SDL_rotate.c in Sources */,
 				A7D8B4EE23E2514300DCD162 /* SDL_gamepad.c in Sources */,
 				E4A568B62AF763940062EEC4 /* SDL_sysmain_callbacks.c in Sources */,
 				F316ABD82B5C3185002EF551 /* SDL_memset.c in Sources */,

+ 18 - 0
include/SDL3/SDL_surface.h

@@ -939,6 +939,24 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetSurfaceClipRect(SDL_Surface *surface, SD
  */
 extern SDL_DECLSPEC bool SDLCALL SDL_FlipSurface(SDL_Surface *surface, SDL_FlipMode flip);
 
+/**
+ * Return a copy of a surface rotated clockwise a number of degrees.
+ *
+ * The angle of rotation can be negative for counter-clockwise rotation.
+ *
+ * When the rotation isn't a multiple of 90 degrees, the resulting surface is larger than the original, with the background filled in with the colorkey, if available, or RGBA 255/255/255/0 if not.
+ *
+ * \param surface the surface to rotate.
+ * \param angle the rotation angle, in degrees.
+ * \returns a rotated copy of the surface or NULL on failure; call SDL_GetError() for
+ *          more information.
+ *
+ * \threadsafety This function is not thread safe.
+ *
+ * \since This function is available since SDL 3.2.0.
+ */
+extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_RotateSurface(SDL_Surface *surface, float angle);
+
 /**
  * Creates a new surface identical to the existing surface.
  *

+ 1 - 0
src/dynapi/SDL_dynapi.sym

@@ -1267,6 +1267,7 @@ SDL3_0.0.0 {
     SDL_GetSystemPageSize;
     SDL_GetPenDeviceType;
     SDL_CreateAnimatedCursor;
+    SDL_RotateSurface;
     # extra symbols go here (don't modify this line)
   local: *;
 };

+ 1 - 0
src/dynapi/SDL_dynapi_overrides.h

@@ -1293,3 +1293,4 @@
 #define SDL_GetSystemPageSize SDL_GetSystemPageSize_REAL
 #define SDL_GetPenDeviceType SDL_GetPenDeviceType_REAL
 #define SDL_CreateAnimatedCursor SDL_CreateAnimatedCursor_REAL
+#define SDL_RotateSurface SDL_RotateSurface_REAL

+ 1 - 0
src/dynapi/SDL_dynapi_procs.h

@@ -1301,3 +1301,4 @@ SDL_DYNAPI_PROC(bool,SDL_SavePNG,(SDL_Surface *a,const char *b),(a,b),return)
 SDL_DYNAPI_PROC(int,SDL_GetSystemPageSize,(void),(),return)
 SDL_DYNAPI_PROC(SDL_PenDeviceType,SDL_GetPenDeviceType,(SDL_PenID a),(a),return)
 SDL_DYNAPI_PROC(SDL_Cursor*,SDL_CreateAnimatedCursor,(SDL_CursorFrameInfo *a,int b,int c,int d),(a,b,c,d),return)
+SDL_DYNAPI_PROC(SDL_Surface*,SDL_RotateSurface,(SDL_Surface *a,float b),(a,b),return)

+ 2 - 2
src/render/software/SDL_render_sw.c

@@ -31,9 +31,9 @@
 #include "SDL_blendpoint.h"
 #include "SDL_drawline.h"
 #include "SDL_drawpoint.h"
-#include "SDL_rotate.h"
 #include "SDL_triangle.h"
 #include "../../video/SDL_pixels_c.h"
+#include "../../video/SDL_rotate.h"
 
 // SDL surface based renderer implementation
 
@@ -406,7 +406,7 @@ static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Te
     SDL_GetSurfaceColorMod(src, &rMod, &gMod, &bMod);
 
     // SDLgfx_rotateSurface only accepts 32-bit surfaces with a 8888 layout. Everything else has to be converted.
-    if (src->fmt->bits_per_pixel != 32 || SDL_PIXELLAYOUT(src->format) != SDL_PACKEDLAYOUT_8888 || !SDL_ISPIXELFORMAT_ALPHA(src->format)) {
+    if (!(SDL_BITSPERPIXEL(src->format) == 32 && SDL_PIXELLAYOUT(src->format) == SDL_PACKEDLAYOUT_8888)) {
         blitRequired = true;
     }
 

+ 4 - 11
src/render/software/SDL_rotate.c → src/video/SDL_rotate.c

@@ -30,16 +30,9 @@ Andreas Schiffler -- aschiffler at ferzkopp dot net
 */
 #include "SDL_internal.h"
 
-#ifdef SDL_VIDEO_RENDER_SW
-
-#if defined(SDL_PLATFORM_WINDOWS)
-#include "../../core/windows/SDL_windows.h"
-#endif
-
+#include "SDL_surface_c.h"
 #include "SDL_rotate.h"
 
-#include "../../video/SDL_surface_c.h"
-
 // ---- Internally used structures
 
 /**
@@ -506,8 +499,9 @@ SDL_Surface *SDLgfx_rotateSurface(SDL_Surface *src, double angle, int smooth, in
         }
     }
     // This function requires a 32-bit surface or 8-bit surface with a colorkey
-    is8bit = src->fmt->bits_per_pixel == 8 && colorKeyAvailable;
-    if (!(is8bit || (src->fmt->bits_per_pixel == 32 && SDL_ISPIXELFORMAT_ALPHA(src->format)))) {
+    is8bit = (src->format == SDL_PIXELFORMAT_INDEX8) && colorKeyAvailable;
+    if (!is8bit &&
+        !(SDL_BITSPERPIXEL(src->format) == 32 && SDL_PIXELLAYOUT(src->format) == SDL_PACKEDLAYOUT_8888)) {
         return NULL;
     }
 
@@ -609,4 +603,3 @@ SDL_Surface *SDLgfx_rotateSurface(SDL_Surface *src, double angle, int smooth, in
     return rz_dst;
 }
 
-#endif // SDL_VIDEO_RENDER_SW

+ 0 - 0
src/render/software/SDL_rotate.h → src/video/SDL_rotate.h


+ 33 - 0
src/video/SDL_surface.c

@@ -24,6 +24,7 @@
 #include "SDL_video_c.h"
 #include "SDL_RLEaccel_c.h"
 #include "SDL_pixels_c.h"
+#include "SDL_rotate.h"
 #include "SDL_stb_c.h"
 #include "SDL_yuv_c.h"
 #include "../render/SDL_sysrender.h"
@@ -2167,6 +2168,38 @@ error:
     return NULL;
 }
 
+SDL_Surface *SDL_RotateSurface(SDL_Surface *surface, float angle)
+{
+    SDL_Surface *rotated = NULL;
+
+    CHECK_PARAM(!SDL_SurfaceValid(surface)) {
+        SDL_InvalidParamError("surface");
+        return NULL;
+    }
+
+    SDL_Rect rect_dest;
+    double cangle, sangle;
+    SDL_FPoint center = { surface->w * 0.5f, surface->h * 0.5f };
+    SDLgfx_rotozoomSurfaceSizeTrig(surface->w, surface->h, angle, &center, &rect_dest, &cangle, &sangle);
+
+    // This function requires a 32-bit surface or 8-bit surface with a colorkey
+    if ((SDL_BITSPERPIXEL(surface->format) == 32 && SDL_PIXELLAYOUT(surface->format) == SDL_PACKEDLAYOUT_8888) ||
+        (surface->format == SDL_PIXELFORMAT_INDEX8 && SDL_SurfaceHasColorKey(surface))) {
+        rotated = SDLgfx_rotateSurface(surface, angle, 1, 0, 0, &rect_dest, cangle, sangle, &center);
+    } else {
+        SDL_Surface *convert = SDL_ConvertSurface(surface, SDL_PIXELFORMAT_RGBA32);
+        if (convert) {
+            SDL_Surface *tmp = SDLgfx_rotateSurface(convert, angle, 1, 0, 0, &rect_dest, cangle, sangle, &center);
+            if (tmp) {
+                rotated = SDL_ConvertSurfaceAndColorspace(tmp, surface->format, surface->palette, surface->colorspace, surface->props);
+                SDL_DestroySurface(tmp);
+            }
+            SDL_DestroySurface(convert);
+        }
+    }
+    return rotated;
+}
+
 SDL_Surface *SDL_DuplicateSurface(SDL_Surface *surface)
 {
     CHECK_PARAM(!SDL_SurfaceValid(surface)) {

+ 1 - 0
test/CMakeLists.txt

@@ -393,6 +393,7 @@ if(WIN32 AND CMAKE_SIZEOF_VOID_P EQUAL 4)
     add_sdl_test_executable(pretest SOURCES pretest.c NONINTERACTIVE NONINTERACTIVE_TIMEOUT 60)
 endif()
 add_sdl_test_executable(testrendertarget NEEDS_RESOURCES TESTUTILS SOURCES testrendertarget.c)
+add_sdl_test_executable(testrotate SOURCES testrotate.c)
 add_sdl_test_executable(testscale NEEDS_RESOURCES TESTUTILS SOURCES testscale.c)
 add_sdl_test_executable(testsem NONINTERACTIVE DISABLE_THREADS_ARGS "--no-threads" NONINTERACTIVE_ARGS 10 NONINTERACTIVE_TIMEOUT 30 SOURCES testsem.c)
 add_sdl_test_executable(testsensor SOURCES testsensor.c)

+ 205 - 0
test/testrotate.c

@@ -0,0 +1,205 @@
+/*
+  Copyright (C) 1997-2025 Sam Lantinga <[email protected]>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely.
+*/
+
+#define SDL_MAIN_USE_CALLBACKS 1
+#include <SDL3/SDL_test.h>
+#include <SDL3/SDL_test_common.h>
+#include <SDL3/SDL_main.h>
+
+#define IMAGE_SIZE 256
+
+static SDLTest_CommonState *state;
+static SDL_Surface *image;
+static SDL_Texture *texture;
+static int format_index = -1;
+static SDL_PixelFormat formats[] = {
+    SDL_PIXELFORMAT_RGBA32,
+    SDL_PIXELFORMAT_ARGB32,
+    SDL_PIXELFORMAT_RGBX32,
+    SDL_PIXELFORMAT_XRGB32,
+    SDL_PIXELFORMAT_ARGB1555,
+    SDL_PIXELFORMAT_INDEX8
+};
+static int angle;
+static int direction = 1;
+
+static bool UpdateImageFormat(void)
+{
+    static const SDL_Color colors[] = {
+        { 255, 255, 255, SDL_ALPHA_TRANSPARENT },   /* Colorkey - white with transparent alpha */
+        { 255,   0,   0, SDL_ALPHA_OPAQUE },        /* Red */
+        { 255, 255,   0, SDL_ALPHA_OPAQUE },        /* Yellow */
+        {   0, 255,   0, SDL_ALPHA_OPAQUE },        /* Green */
+        {   0,   0, 255, SDL_ALPHA_OPAQUE },        /* Blue */
+    };
+    SDL_Rect rect;
+    Uint32 color;
+
+    ++format_index;
+    if (format_index == SDL_arraysize(formats)) {
+        format_index = 0;
+    }
+
+    SDL_DestroySurface(image);
+
+    image = SDL_CreateSurface(IMAGE_SIZE, IMAGE_SIZE, formats[format_index]);
+    if (!image) {
+        SDL_Log("Couldn't create surface: %s\n", SDL_GetError());
+        return false;
+    }
+
+    if (image->format == SDL_PIXELFORMAT_INDEX8) {
+        /* Set the palette and colorkey */
+        SDL_Palette *palette = SDL_CreateSurfacePalette(image);
+
+        SDL_SetPaletteColors(palette, colors, 0, SDL_arraysize(colors));
+        SDL_SetSurfaceColorKey(image, true, 0);
+    }
+
+    /* Upper left */
+    rect.x = 0;
+    rect.y = 0;
+    rect.w = IMAGE_SIZE / 2;
+    rect.h = IMAGE_SIZE / 2;
+    color = SDL_MapSurfaceRGB(image, colors[1].r, colors[1].g, colors[1].b);
+    SDL_FillSurfaceRect(image, &rect, color);
+
+    /* Upper right */
+    rect.x += rect.w;
+    color = SDL_MapSurfaceRGB(image, colors[2].r, colors[2].g, colors[2].b);
+    SDL_FillSurfaceRect(image, &rect, color);
+
+    /* Lower left */
+    rect.x = 0;
+    rect.y += rect.h;
+    color = SDL_MapSurfaceRGB(image, colors[3].r, colors[3].g, colors[3].b);
+    SDL_FillSurfaceRect(image, &rect, color);
+
+    /* Lower right */
+    rect.x += rect.w;
+    color = SDL_MapSurfaceRGB(image, colors[4].r, colors[4].g, colors[4].b);
+    SDL_FillSurfaceRect(image, &rect, color);
+
+    return true;
+}
+
+static bool UpdateRotation(SDL_Renderer *renderer)
+{
+    SDL_Surface *rotated;
+
+    angle += direction;
+
+    rotated = SDL_RotateSurface(image, (float)angle);
+    if (!rotated) {
+        SDL_Log("Couldn't rotate surface: %s", SDL_GetError());
+        return false;
+    }
+
+    SDL_DestroyTexture(texture);
+    texture = SDL_CreateTextureFromSurface(renderer, rotated);
+    SDL_DestroySurface(rotated);
+    if (!texture) {
+        SDL_Log("Couldn't create texture: %s", SDL_GetError());
+        return false;
+    }
+
+    return true;
+}
+
+static void Draw(SDL_Renderer *renderer)
+{
+    int w, h;
+    SDL_FRect dst;
+
+    /* Clear the screen */
+    SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
+    SDL_RenderClear(renderer);
+
+    UpdateRotation(renderer);
+
+    /* Draw the rotated image */
+    SDL_GetCurrentRenderOutputSize(renderer, &w, &h);
+    dst.x = (w - texture->w) / 2.0f;
+    dst.y = (h - texture->h) / 2.0f;
+    dst.w = (float)texture->w;
+    dst.h = (float)texture->h;
+    SDL_RenderTexture(renderer, texture, NULL, &dst);
+
+    /* Show the current format */
+    SDL_SetRenderDrawColor(renderer, 255, 255, 255, SDL_ALPHA_OPAQUE);
+    SDL_RenderDebugTextFormat(renderer, 4.0f, 4.0f, "Format: %s, press SPACE to cycle", SDL_GetPixelFormatName(formats[format_index]));
+
+    /* All done! */
+    SDL_RenderPresent(renderer);
+}
+
+void SDL_AppQuit(void *appstate, SDL_AppResult result)
+{
+    SDLTest_CommonQuit(state);
+}
+
+SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
+{
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
+    if (!state) {
+        return SDL_APP_FAILURE;
+    }
+
+    if (!SDLTest_CommonInit(state)) {
+        return SDL_APP_FAILURE;
+    }
+
+    /* Create the spinning image */
+    UpdateImageFormat();
+
+    return SDL_APP_CONTINUE;
+}
+
+
+SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
+{
+    switch (event->type) {
+    case SDL_EVENT_KEY_UP:
+        switch (event->key.key) {
+        case SDLK_SPACE:
+            UpdateImageFormat();
+            break;
+        case SDLK_LEFT:
+            direction = -1;
+            break;
+        case SDLK_RIGHT:
+            direction = 1;
+            break;
+        default:
+            break;
+        }
+        break;
+    default:
+        break;
+    }
+    return SDLTest_CommonEventMainCallbacks(state, event);
+}
+
+SDL_AppResult SDL_AppIterate(void *appstate)
+{
+    int i;
+
+    for (i = 0; i < state->num_windows; ++i) {
+        Draw(state->renderers[i]);
+    }
+
+    /* Wait a bit so we don't spin too quickly to see */
+    SDL_Delay(10);
+
+    return SDL_APP_CONTINUE;
+}