Added SDL_aligned_alloc_zero()
Some checks are pending
Build (All) / Create test plan (push) Waiting to run
Build (All) / level1 (push) Blocked by required conditions
Build (All) / level2 (push) Blocked by required conditions

This commit is contained in:
Sam Lantinga 2026-06-05 09:27:22 -07:00
parent fa2a726cc3
commit 55908f14f8
7 changed files with 53 additions and 9 deletions

View file

@ -1362,7 +1362,9 @@ extern SDL_DECLSPEC SDL_MALLOC void * SDLCALL SDL_malloc(size_t size);
* *
* If the allocation is successful, the returned pointer is guaranteed to be * If the allocation is successful, the returned pointer is guaranteed to be
* aligned to either the *fundamental alignment* (`alignof(max_align_t)` in * aligned to either the *fundamental alignment* (`alignof(max_align_t)` in
* C11 and later) or `2 * sizeof(void *)`, whichever is smaller. * C11 and later) or `2 * sizeof(void *)`, whichever is smaller. Use
* SDL_aligned_alloc_zero() if you need to allocate memory aligned to an
* alignment greater than this guarantee.
* *
* \param nmemb the number of elements in the array. * \param nmemb the number of elements in the array.
* \param size the size of each element of the array. * \param size the size of each element of the array.
@ -1616,6 +1618,30 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetMemoryFunctions(SDL_malloc_func malloc_f
*/ */
extern SDL_DECLSPEC SDL_MALLOC void * SDLCALL SDL_aligned_alloc(size_t alignment, size_t size); extern SDL_DECLSPEC SDL_MALLOC void * SDLCALL SDL_aligned_alloc(size_t alignment, size_t size);
/**
* Allocate zero-initialized memory aligned to a specific alignment.
*
* The memory returned by this function must be freed with SDL_aligned_free(),
* _not_ SDL_free().
*
* If `alignment` is less than the size of `void *`, it will be increased to
* match that.
*
* The returned memory address will be a multiple of the alignment value, and
* the size of the memory allocated will be a multiple of the alignment value.
*
* \param alignment the alignment of the memory.
* \param size the size to allocate.
* \returns a pointer to the aligned memory, or NULL if allocation failed.
*
* \threadsafety It is safe to call this function from any thread.
*
* \since This function is available since SDL 3.6.0.
*
* \sa SDL_aligned_free
*/
extern SDL_DECLSPEC SDL_MALLOC void * SDLCALL SDL_aligned_alloc_zero(size_t alignment, size_t size);
/** /**
* Free memory allocated by SDL_aligned_alloc(). * Free memory allocated by SDL_aligned_alloc().
* *

View file

@ -1290,3 +1290,4 @@ _SDL_LoadJPG
_SDL_HasSVE2 _SDL_HasSVE2
_SDL_GamepadHasCapSense _SDL_GamepadHasCapSense
_SDL_GetGamepadCapSense _SDL_GetGamepadCapSense
_SDL_aligned_alloc_zero

View file

@ -1291,6 +1291,7 @@ SDL3_0.0.0 {
SDL_HasSVE2; SDL_HasSVE2;
SDL_GamepadHasCapSense; SDL_GamepadHasCapSense;
SDL_GetGamepadCapSense; SDL_GetGamepadCapSense;
SDL_aligned_alloc_zero;
# extra symbols go here (don't modify this line) # extra symbols go here (don't modify this line)
local: *; local: *;
}; };

View file

@ -1317,3 +1317,4 @@
#define SDL_HasSVE2 SDL_HasSVE2_REAL #define SDL_HasSVE2 SDL_HasSVE2_REAL
#define SDL_GamepadHasCapSense SDL_GamepadHasCapSense_REAL #define SDL_GamepadHasCapSense SDL_GamepadHasCapSense_REAL
#define SDL_GetGamepadCapSense SDL_GetGamepadCapSense_REAL #define SDL_GetGamepadCapSense SDL_GetGamepadCapSense_REAL
#define SDL_aligned_alloc_zero SDL_aligned_alloc_zero_REAL

View file

@ -1325,3 +1325,4 @@ SDL_DYNAPI_PROC(SDL_Surface*,SDL_LoadJPG,(const char *a),(a),return)
SDL_DYNAPI_PROC(bool,SDL_HasSVE2,(void),(),return) SDL_DYNAPI_PROC(bool,SDL_HasSVE2,(void),(),return)
SDL_DYNAPI_PROC(bool,SDL_GamepadHasCapSense,(SDL_Gamepad *a,SDL_GamepadCapSenseType b),(a,b),return) SDL_DYNAPI_PROC(bool,SDL_GamepadHasCapSense,(SDL_Gamepad *a,SDL_GamepadCapSenseType b),(a,b),return)
SDL_DYNAPI_PROC(bool,SDL_GetGamepadCapSense,(SDL_Gamepad *a,SDL_GamepadCapSenseType b),(a,b),return) SDL_DYNAPI_PROC(bool,SDL_GetGamepadCapSense,(SDL_Gamepad *a,SDL_GamepadCapSenseType b),(a,b),return)
SDL_DYNAPI_PROC(void*,SDL_aligned_alloc_zero,(size_t a,size_t b),(a,b),return)

View file

@ -523,7 +523,7 @@ int SDL_toupper(int x) { return ((x) >= 'a') && ((x) <= 'z') ? ('A' + ((x) - 'a'
int SDL_tolower(int x) { return ((x) >= 'A') && ((x) <= 'Z') ? ('a' + ((x) - 'A')) : (x); } int SDL_tolower(int x) { return ((x) >= 'A') && ((x) <= 'Z') ? ('a' + ((x) - 'A')) : (x); }
int SDL_isblank(int x) { return ((x) == ' ') || ((x) == '\t'); } int SDL_isblank(int x) { return ((x) == ' ') || ((x) == '\t'); }
void *SDL_aligned_alloc(size_t alignment, size_t size) static void *SDL_aligned_alloc_internal(size_t alignment, size_t size, bool clear_memory)
{ {
size_t padding; size_t padding;
Uint8 *result = NULL; Uint8 *result = NULL;
@ -537,7 +537,7 @@ void *SDL_aligned_alloc(size_t alignment, size_t size)
if (SDL_size_add_check_overflow(size, alignment, &size) && if (SDL_size_add_check_overflow(size, alignment, &size) &&
SDL_size_add_check_overflow(size, sizeof(void *), &size) && SDL_size_add_check_overflow(size, sizeof(void *), &size) &&
SDL_size_add_check_overflow(size, padding, &size)) { SDL_size_add_check_overflow(size, padding, &size)) {
void *original = SDL_malloc(size); void *original = clear_memory ? SDL_calloc(1, size) : SDL_malloc(size);
if (original) { if (original) {
// Make sure we have enough space to store the original pointer // Make sure we have enough space to store the original pointer
result = (Uint8 *)original + sizeof(original); result = (Uint8 *)original + sizeof(original);
@ -557,6 +557,16 @@ void *SDL_aligned_alloc(size_t alignment, size_t size)
return result; return result;
} }
void *SDL_aligned_alloc(size_t alignment, size_t size)
{
return SDL_aligned_alloc_internal(alignment, size, false);
}
void *SDL_aligned_alloc_zero(size_t alignment, size_t size)
{
return SDL_aligned_alloc_internal(alignment, size, true);
}
void SDL_aligned_free(void *mem) void SDL_aligned_free(void *mem)
{ {
if (mem) { if (mem) {

View file

@ -230,19 +230,23 @@ static SDL_Surface *SDL_CreateSurfaceInternal(int width, int height, SDL_PixelFo
if (surface->w && surface->h && format != SDL_PIXELFORMAT_MJPG) { if (surface->w && surface->h && format != SDL_PIXELFORMAT_MJPG) {
surface->flags &= ~SDL_SURFACE_PREALLOCATED; surface->flags &= ~SDL_SURFACE_PREALLOCATED;
if (SDL_GetHintBoolean("SDL_SURFACE_MALLOC", false)) { if (SDL_GetHintBoolean("SDL_SURFACE_MALLOC", false)) {
surface->pixels = SDL_malloc(size); if (clear_surface) {
surface->pixels = SDL_calloc(1, size);
} else {
surface->pixels = SDL_malloc(size);
}
} else { } else {
surface->flags |= SDL_SURFACE_SIMD_ALIGNED; surface->flags |= SDL_SURFACE_SIMD_ALIGNED;
surface->pixels = SDL_aligned_alloc(SDL_GetSIMDAlignment(), size); if (clear_surface) {
surface->pixels = SDL_aligned_alloc_zero(SDL_GetSIMDAlignment(), size);
} else {
surface->pixels = SDL_aligned_alloc(SDL_GetSIMDAlignment(), size);
}
} }
if (!surface->pixels) { if (!surface->pixels) {
SDL_DestroySurface(surface); SDL_DestroySurface(surface);
return NULL; return NULL;
} }
if (clear_surface) {
SDL_memset(surface->pixels, 0, size);
}
} }
return surface; return surface;
} }