hints: Add SDL_HINT_CREATE_SURFACE_CLEAR.

This also tries to use SDL_calloc instead of SDL_malloc in the no-SIMD-align
path, in case the system offers a faster way to obtain zero'd bytes through
calloc.

Fixes #15715.
Closes #15736.
This commit is contained in:
Ryan C. Gordon 2026-06-04 18:11:27 -04:00
parent 7341f04a12
commit f4936d10d6
No known key found for this signature in database
GPG key ID: FA148B892AB48044
2 changed files with 33 additions and 4 deletions

View file

@ -702,6 +702,29 @@ extern "C" {
*/ */
#define SDL_HINT_CPU_FEATURE_MASK "SDL_CPU_FEATURE_MASK" #define SDL_HINT_CPU_FEATURE_MASK "SDL_CPU_FEATURE_MASK"
/**
* A variable that decides whether SDL_CreateSurface() clears pixels.
*
* By default, SDL_CreateSurface() will clear the newly-created surface by
* setting all bytes of its `pixels` buffer to zero; for many formats this
* clears the surface black, as a reasonable default.
*
* However, clearing the surface is wasted effort if the app plans to
* initialize the entire surface immediately after creation. Disabling this
* hint leaves the newly-allocated buffer of pixels uninitialized, and the
* app will be responsible for setting every pixel before its first use.
*
* The variable can be set to the following values:
*
* - "0": Surface pixels will _not_ be initialized during creation.
* - "1": Surface pixels will be zeroed during creation. (default)
*
* This hint can be set anytime, affecting later calls to SDL_CreateSurface().
*
* \since This hint is available since SDL 3.6.0.
*/
#define SDL_HINT_CREATE_SURFACE_CLEAR "SDL_CREATE_SURFACE_CLEAR"
/** /**
* A variable controlling whether DirectInput should be used for controllers. * A variable controlling whether DirectInput should be used for controllers.
* *

View file

@ -228,9 +228,15 @@ SDL_Surface *SDL_CreateSurface(int width, int height, SDL_PixelFormat format)
} }
if (surface->w && surface->h && format != SDL_PIXELFORMAT_MJPG) { if (surface->w && surface->h && format != SDL_PIXELFORMAT_MJPG) {
bool must_clear = SDL_GetHintBoolean(SDL_HINT_CREATE_SURFACE_CLEAR, true);
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 (must_clear) {
surface->pixels = SDL_calloc(1, size);
must_clear = false; // SDL_calloc already did it, don't memset again, below.
} 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); surface->pixels = SDL_aligned_alloc(SDL_GetSIMDAlignment(), size);
@ -239,9 +245,9 @@ SDL_Surface *SDL_CreateSurface(int width, int height, SDL_PixelFormat format)
SDL_DestroySurface(surface); SDL_DestroySurface(surface);
return NULL; return NULL;
} }
if (must_clear) {
// This is important for bitmaps SDL_memset(surface->pixels, 0, size);
SDL_memset(surface->pixels, 0, size); }
} }
return surface; return surface;
} }