diff --git a/include/SDL3/SDL_surface.h b/include/SDL3/SDL_surface.h index 13f1352ac..0fdfdcfb8 100644 --- a/include/SDL3/SDL_surface.h +++ b/include/SDL3/SDL_surface.h @@ -137,6 +137,9 @@ extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateSurface * No copy is made of the pixel data. Pixel data is not managed automatically; * you must free the surface before you free the pixel data. * + * You may pass NULL for pixels and 0 for pitch to create a surface that you + * will fill in with valid values later. + * * \param pixels a pointer to existing pixel data * \param width the width of the surface * \param height the height of the surface diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c index 36d2fdde3..37157ae96 100644 --- a/src/video/SDL_surface.c +++ b/src/video/SDL_surface.c @@ -203,7 +203,6 @@ SDL_CreateSurfaceFrom(void *pixels, Uint32 format) { SDL_Surface *surface; - size_t minimalPitch; if (width < 0) { SDL_InvalidParamError("width"); @@ -215,20 +214,26 @@ SDL_CreateSurfaceFrom(void *pixels, return NULL; } - if (SDL_ISPIXELFORMAT_FOURCC(format)) { - int p; - if (SDL_CalculateYUVSize(format, width, height, NULL, &p) < 0) { + if (pitch == 0 && pixels == NULL) { + /* The application will fill these in later with valid values */ + } else { + size_t minimalPitch; + + if (SDL_ISPIXELFORMAT_FOURCC(format)) { + int p; + if (SDL_CalculateYUVSize(format, width, height, NULL, &p) < 0) { + SDL_InvalidParamError("pitch"); + return NULL; + } + minimalPitch = p; + } else { + minimalPitch = SDL_CalculatePitch(format, width, SDL_TRUE); + } + + if (pitch < 0 || (size_t)pitch < minimalPitch) { SDL_InvalidParamError("pitch"); return NULL; } - minimalPitch = p; - } else { - minimalPitch = SDL_CalculatePitch(format, width, SDL_TRUE); - } - - if (pitch < 0 || (pitch > 0 && ((size_t)pitch) < minimalPitch)) { - SDL_InvalidParamError("pitch"); - return NULL; } surface = SDL_CreateSurface(0, 0, format); diff --git a/test/testautomation_surface.c b/test/testautomation_surface.c index ed9481b80..1c17c6dca 100644 --- a/test/testautomation_surface.c +++ b/test/testautomation_surface.c @@ -621,6 +621,14 @@ int surface_testOverflow(void *arg) SDLTest_AssertCheck(surface == NULL, "Should detect negative pitch"); SDLTest_AssertCheck(SDL_strcmp(SDL_GetError(), expectedError) == 0, "Expected \"%s\", got \"%s\"", expectedError, SDL_GetError()); + surface = SDL_CreateSurfaceFrom(buf, 1, 1, 0, SDL_PIXELFORMAT_RGBA8888); + SDLTest_AssertCheck(surface == NULL, "Should detect zero pitch"); + SDLTest_AssertCheck(SDL_strcmp(SDL_GetError(), expectedError) == 0, + "Expected \"%s\", got \"%s\"", expectedError, SDL_GetError()); + surface = SDL_CreateSurfaceFrom(NULL, 1, 1, 0, SDL_PIXELFORMAT_RGBA8888); + SDLTest_AssertCheck(surface != NULL, "Allow zero pitch for partially set up surfaces: %s", + surface != NULL ? "(success)" : SDL_GetError()); + SDL_DestroySurface(surface); /* Less than 1 byte per pixel: the pitch can legitimately be less than * the width, but it must be enough to hold the appropriate number of