From ee1c90a358c8c87af05df47225056fc465f46401 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 16 Sep 2025 18:23:06 -0700 Subject: [PATCH] Improved handling of function parameter validation SDL supports the following use cases: * Normal operation with fast parameter checks (default): SDL_SetHint(SDL_HINT_INVALID_PARAM_CHECKS, "1"); * Object parameters are checked for use-after-free issues: SDL_SetHint(SDL_HINT_INVALID_PARAM_CHECKS, "2"); * Enable full validation, plus assert on invalid parameters: #define SDL_ASSERT_INVALID_PARAMS * Disable all parameter validation: #define SDL_DISABLE_INVALID_PARAMS --- include/SDL3/SDL_hints.h | 14 + src/SDL_internal.h | 15 + src/SDL_utils.c | 32 ++ src/render/SDL_render.c | 884 +++++++++++++++++++++++---------------- 4 files changed, 592 insertions(+), 353 deletions(-) diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index ebab026586..a2df82a94c 100644 --- a/include/SDL3/SDL_hints.h +++ b/include/SDL3/SDL_hints.h @@ -685,6 +685,20 @@ extern "C" { */ #define SDL_HINT_DISPLAY_USABLE_BOUNDS "SDL_DISPLAY_USABLE_BOUNDS" +/** + * Set the level of checking for invalid parameters passed to SDL functions. + * + * The variable can be set to the following values: + * + * - "1": Enable fast parameter error checking, e.g. quick NULL checks, etc. (default) + * - "2": Enable full parameter error checking, e.g. validating objects are the correct type, etc. + * + * This hint can be set anytime. + * + * \since This hint is available since SDL 3.4.0. + */ +#define SDL_HINT_INVALID_PARAM_CHECKS "SDL_INVALID_PARAM_CHECKS" + /** * Disable giving back control to the browser automatically when running with * asyncify. diff --git a/src/SDL_internal.h b/src/SDL_internal.h index 3d027f794b..28ebebaac4 100644 --- a/src/SDL_internal.h +++ b/src/SDL_internal.h @@ -290,6 +290,21 @@ extern SDL_NORETURN void SDL_ExitProcess(int exitcode); #define POP_SDL_ERROR() \ SDL_SetError("%s", _error); SDL_free(_error); } +#if defined(SDL_DISABLE_INVALID_PARAMS) +#ifdef DEBUG +// If you define SDL_DISABLE_INVALID_PARAMS, you're promising that you'll +// never pass an invalid parameter to SDL, since it may crash or lead to +// hard to diagnose bugs. Let's assert that this is true in debug builds. +#define CHECK_PARAM(invalid) SDL_assert_always(!(invalid)); if (false) +#else +#define CHECK_PARAM(invalid) if (false) +#endif +#elif defined(SDL_ASSERT_INVALID_PARAMS) +#define CHECK_PARAM(invalid) SDL_assert_always(!(invalid)); if (invalid) +#else +#define CHECK_PARAM(invalid) if (invalid) +#endif + // Do any initialization that needs to happen before threads are started extern void SDL_InitMainThread(void); diff --git a/src/SDL_utils.c b/src/SDL_utils.c index 47fa28c06d..4999a537b0 100644 --- a/src/SDL_utils.c +++ b/src/SDL_utils.c @@ -137,6 +137,32 @@ Uint32 SDL_GetNextObjectID(void) static SDL_InitState SDL_objects_init; static SDL_HashTable *SDL_objects; +static bool SDL_object_validation; + +static void SDLCALL SDL_InvalidParamChecksChanged(void *userdata, const char *name, const char *oldValue, const char *hint) +{ + bool validation_enabled = false; + +#ifdef SDL_ASSERT_INVALID_PARAMS + // Full validation is enabled by default + validation_enabled = true; +#endif + + if (hint) { + switch (*hint) { + case '0': + case '1': + validation_enabled = false; + break; + case '2': + validation_enabled = true; + break; + default: + break; + } + } + SDL_object_validation = validation_enabled; +} static Uint32 SDLCALL SDL_HashObject(void *unused, const void *key) { @@ -159,6 +185,7 @@ void SDL_SetObjectValid(void *object, SDL_ObjectType type, bool valid) if (!initialized) { return; } + SDL_AddHintCallback(SDL_HINT_INVALID_PARAM_CHECKS, SDL_InvalidParamChecksChanged, NULL); } if (valid) { @@ -174,6 +201,10 @@ bool SDL_ObjectValid(void *object, SDL_ObjectType type) return false; } + if (!SDL_object_validation) { + return true; + } + const void *object_type; if (!SDL_FindInHashTable(SDL_objects, object, &object_type)) { return false; @@ -242,6 +273,7 @@ void SDL_SetObjectsInvalid(void) SDL_DestroyHashTable(SDL_objects); SDL_objects = NULL; SDL_SetInitialized(&SDL_objects_init, false); + SDL_RemoveHintCallback(SDL_HINT_INVALID_PARAM_CHECKS, SDL_InvalidParamChecksChanged, NULL); } } diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index 03faa51640..1d0a522837 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -50,22 +50,22 @@ this should probably be removed at some point in the future. --ryan. */ #define SDL_PROP_TEXTURE_PARENT_POINTER "SDL.internal.texture.parent" #define CHECK_RENDERER_MAGIC_BUT_NOT_DESTROYED_FLAG(renderer, result) \ - if (!SDL_ObjectValid(renderer, SDL_OBJECT_TYPE_RENDERER)) { \ + CHECK_PARAM(!SDL_ObjectValid(renderer, SDL_OBJECT_TYPE_RENDERER)) { \ SDL_InvalidParamError("renderer"); \ return result; \ } -#define CHECK_RENDERER_MAGIC(renderer, result) \ - CHECK_RENDERER_MAGIC_BUT_NOT_DESTROYED_FLAG(renderer, result); \ - if ((renderer)->destroyed) { \ +#define CHECK_RENDERER_MAGIC(renderer, result) \ + CHECK_RENDERER_MAGIC_BUT_NOT_DESTROYED_FLAG(renderer, result); \ + CHECK_PARAM(renderer->destroyed) { \ SDL_SetError("Renderer's window has been destroyed, can't use further"); \ - return result; \ + return result; \ } -#define CHECK_TEXTURE_MAGIC(texture, result) \ - if (!SDL_ObjectValid(texture, SDL_OBJECT_TYPE_TEXTURE)) { \ - SDL_InvalidParamError("texture"); \ - return result; \ +#define CHECK_TEXTURE_MAGIC(texture, result) \ + CHECK_PARAM(!SDL_ObjectValid(texture, SDL_OBJECT_TYPE_TEXTURE)) { \ + SDL_InvalidParamError("texture"); \ + return result; \ } // Predefined blend modes @@ -832,9 +832,11 @@ int SDL_GetNumRenderDrivers(void) const char *SDL_GetRenderDriver(int index) { #ifndef SDL_RENDER_DISABLED - if (index < 0 || index >= SDL_GetNumRenderDrivers()) { - SDL_InvalidParamError("index"); - return NULL; + PARAMETER_CHECKS { + CHECK_PARAM(index < 0 || index >= SDL_GetNumRenderDrivers()) { + SDL_InvalidParamError("index"); + return NULL; + } } return render_drivers[index]->name; #else @@ -885,17 +887,18 @@ static bool SDL_RendererEventWatch(void *userdata, SDL_Event *event) bool SDL_CreateWindowAndRenderer(const char *title, int width, int height, SDL_WindowFlags window_flags, SDL_Window **window, SDL_Renderer **renderer) { - bool hidden = (window_flags & SDL_WINDOW_HIDDEN) != 0; + PARAMETER_CHECKS { + CHECK_PARAM(!window) { + return SDL_InvalidParamError("window"); + } - if (!window) { - return SDL_InvalidParamError("window"); - } - - if (!renderer) { - return SDL_InvalidParamError("renderer"); + CHECK_PARAM(!renderer) { + return SDL_InvalidParamError("renderer"); + } } // Hide the window so if the renderer recreates it, we don't get a visual flash on screen + bool hidden = (window_flags & SDL_WINDOW_HIDDEN) != 0; window_flags |= SDL_WINDOW_HIDDEN; *window = SDL_CreateWindow(title, width, height, window_flags); if (!*window) { @@ -985,6 +988,23 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props) const char *hint; SDL_PropertiesID new_props; + PARAMETER_CHECKS { + CHECK_PARAM((!window && !surface) || (window && surface)) { + SDL_InvalidParamError("window"); + return NULL; + } + + CHECK_PARAM(window && SDL_WindowHasSurface(window)) { + SDL_SetError("Surface already associated with window"); + return NULL; + } + + CHECK_PARAM(window && SDL_GetRenderer(window)) { + SDL_SetError("Renderer already associated with window"); + return NULL; + } + } + #ifdef SDL_PLATFORM_ANDROID if (!Android_WaitActiveAndLockActivity()) { return NULL; @@ -998,21 +1018,6 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props) SDL_SetObjectValid(renderer, SDL_OBJECT_TYPE_RENDERER, true); - if ((!window && !surface) || (window && surface)) { - SDL_InvalidParamError("window"); - goto error; - } - - if (window && SDL_WindowHasSurface(window)) { - SDL_SetError("Surface already associated with window"); - goto error; - } - - if (window && SDL_GetRenderer(window)) { - SDL_SetError("Renderer already associated with window"); - goto error; - } - hint = SDL_GetHint(SDL_HINT_RENDER_VSYNC); if (hint && *hint) { SDL_SetNumberProperty(props, SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_NUMBER, SDL_GetHintBoolean(SDL_HINT_RENDER_VSYNC, true)); @@ -1202,9 +1207,11 @@ SDL_Renderer *SDL_CreateRenderer(SDL_Window *window, const char *name) SDL_Renderer *SDL_CreateGPURenderer(SDL_Window *window, SDL_GPUShaderFormat format_flags, SDL_GPUDevice **device) { - if (!device) { - SDL_InvalidParamError("device"); - return NULL; + PARAMETER_CHECKS { + CHECK_PARAM(!device) { + SDL_InvalidParamError("device"); + return NULL; + } } *device = NULL; @@ -1236,9 +1243,11 @@ SDL_Renderer *SDL_CreateSoftwareRenderer(SDL_Surface *surface) #ifdef SDL_VIDEO_RENDER_SW SDL_Renderer *renderer; - if (!surface) { - SDL_InvalidParamError("surface"); - return NULL; + PARAMETER_CHECKS { + CHECK_PARAM(!surface) { + SDL_InvalidParamError("surface"); + return NULL; + } } SDL_PropertiesID props = SDL_CreateProperties(); @@ -1259,20 +1268,26 @@ SDL_Renderer *SDL_GetRenderer(SDL_Window *window) SDL_Window *SDL_GetRenderWindow(SDL_Renderer *renderer) { - CHECK_RENDERER_MAGIC(renderer, NULL); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, NULL); + } return renderer->window; } const char *SDL_GetRendererName(SDL_Renderer *renderer) { - CHECK_RENDERER_MAGIC(renderer, NULL); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, NULL); + } return SDL_GetPersistentString(renderer->name); } SDL_PropertiesID SDL_GetRendererProperties(SDL_Renderer *renderer) { - CHECK_RENDERER_MAGIC(renderer, 0); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, 0); + } if (renderer->props == 0) { renderer->props = SDL_CreateProperties(); @@ -1282,14 +1297,16 @@ SDL_PropertiesID SDL_GetRendererProperties(SDL_Renderer *renderer) bool SDL_GetRenderOutputSize(SDL_Renderer *renderer, int *w, int *h) { - if (w) { - *w = 0; - } - if (h) { - *h = 0; - } + PARAMETER_CHECKS { + if (w) { + *w = 0; + } + if (h) { + *h = 0; + } - CHECK_RENDERER_MAGIC(renderer, false); + CHECK_RENDERER_MAGIC(renderer, false); + } if (renderer->GetOutputSize) { return renderer->GetOutputSize(renderer, w, h); @@ -1303,14 +1320,16 @@ bool SDL_GetRenderOutputSize(SDL_Renderer *renderer, int *w, int *h) bool SDL_GetCurrentRenderOutputSize(SDL_Renderer *renderer, int *w, int *h) { - if (w) { - *w = 0; - } - if (h) { - *h = 0; - } + PARAMETER_CHECKS { + if (w) { + *w = 0; + } + if (h) { + *h = 0; + } - CHECK_RENDERER_MAGIC(renderer, false); + CHECK_RENDERER_MAGIC(renderer, false); + } const SDL_RenderViewState *view = renderer->view; if (w) { @@ -1412,29 +1431,32 @@ SDL_Texture *SDL_CreateTextureWithProperties(SDL_Renderer *renderer, SDL_Propert SDL_Colorspace default_colorspace; bool texture_is_fourcc_and_target; - CHECK_RENDERER_MAGIC(renderer, NULL); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, NULL); + } if (!format) { format = renderer->texture_formats[0]; } - if (SDL_BYTESPERPIXEL(format) == 0) { - SDL_SetError("Invalid texture format"); - return NULL; - } - if (SDL_ISPIXELFORMAT_INDEXED(format)) { - if (!IsSupportedFormat(renderer, format)) { + + PARAMETER_CHECKS { + CHECK_PARAM(SDL_BYTESPERPIXEL(format) == 0) { + SDL_SetError("Invalid texture format"); + return NULL; + } + CHECK_PARAM(SDL_ISPIXELFORMAT_INDEXED(format) && !IsSupportedFormat(renderer, format)) { SDL_SetError("Palettized textures are not supported"); return NULL; } - } - if (w <= 0 || h <= 0) { - SDL_SetError("Texture dimensions can't be 0"); - return NULL; - } - int max_texture_size = (int)SDL_GetNumberProperty(SDL_GetRendererProperties(renderer), SDL_PROP_RENDERER_MAX_TEXTURE_SIZE_NUMBER, 0); - if (max_texture_size && (w > max_texture_size || h > max_texture_size)) { - SDL_SetError("Texture dimensions are limited to %dx%d", max_texture_size, max_texture_size); - return NULL; + CHECK_PARAM(w <= 0 || h <= 0) { + SDL_SetError("Texture dimensions can't be 0"); + return NULL; + } + int max_texture_size = (int)SDL_GetNumberProperty(SDL_GetRendererProperties(renderer), SDL_PROP_RENDERER_MAX_TEXTURE_SIZE_NUMBER, 0); + CHECK_PARAM(max_texture_size && (w > max_texture_size || h > max_texture_size)) { + SDL_SetError("Texture dimensions are limited to %dx%d", max_texture_size, max_texture_size); + return NULL; + } } default_colorspace = SDL_GetDefaultColorspaceForFormat(format); @@ -1697,11 +1719,13 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s SDL_Colorspace surface_colorspace = SDL_COLORSPACE_UNKNOWN; SDL_Colorspace texture_colorspace = SDL_COLORSPACE_UNKNOWN; - CHECK_RENDERER_MAGIC(renderer, NULL); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, NULL); - if (!SDL_SurfaceValid(surface)) { - SDL_InvalidParamError("SDL_CreateTextureFromSurface(): surface"); - return NULL; + CHECK_PARAM(!SDL_SurfaceValid(surface)) { + SDL_InvalidParamError("SDL_CreateTextureFromSurface(): surface"); + return NULL; + } } // See what the best texture format is @@ -1824,14 +1848,18 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s SDL_Renderer *SDL_GetRendererFromTexture(SDL_Texture *texture) { - CHECK_TEXTURE_MAGIC(texture, NULL); + PARAMETER_CHECKS { + CHECK_TEXTURE_MAGIC(texture, NULL); + } return texture->renderer; } SDL_PropertiesID SDL_GetTextureProperties(SDL_Texture *texture) { - CHECK_TEXTURE_MAGIC(texture, 0); + PARAMETER_CHECKS { + CHECK_TEXTURE_MAGIC(texture, 0); + } if (texture->props == 0) { texture->props = SDL_CreateProperties(); @@ -1841,14 +1869,16 @@ SDL_PropertiesID SDL_GetTextureProperties(SDL_Texture *texture) bool SDL_GetTextureSize(SDL_Texture *texture, float *w, float *h) { - if (w) { - *w = 0; - } - if (h) { - *h = 0; - } + PARAMETER_CHECKS { + if (w) { + *w = 0; + } + if (h) { + *h = 0; + } - CHECK_TEXTURE_MAGIC(texture, false); + CHECK_TEXTURE_MAGIC(texture, false); + } if (w) { *w = (float)texture->w; @@ -1870,7 +1900,9 @@ bool SDL_SetTextureColorMod(SDL_Texture *texture, Uint8 r, Uint8 g, Uint8 b) bool SDL_SetTextureColorModFloat(SDL_Texture *texture, float r, float g, float b) { - CHECK_TEXTURE_MAGIC(texture, false); + PARAMETER_CHECKS { + CHECK_TEXTURE_MAGIC(texture, false); + } texture->color.r = r; texture->color.g = g; @@ -1914,17 +1946,19 @@ bool SDL_GetTextureColorModFloat(SDL_Texture *texture, float *r, float *g, float { SDL_FColor color; - if (r) { - *r = 1.0f; - } - if (g) { - *g = 1.0f; - } - if (b) { - *b = 1.0f; - } + PARAMETER_CHECKS { + if (r) { + *r = 1.0f; + } + if (g) { + *g = 1.0f; + } + if (b) { + *b = 1.0f; + } - CHECK_TEXTURE_MAGIC(texture, false); + CHECK_TEXTURE_MAGIC(texture, false); + } color = texture->color; @@ -1949,7 +1983,9 @@ bool SDL_SetTextureAlphaMod(SDL_Texture *texture, Uint8 alpha) bool SDL_SetTextureAlphaModFloat(SDL_Texture *texture, float alpha) { - CHECK_TEXTURE_MAGIC(texture, false); + PARAMETER_CHECKS { + CHECK_TEXTURE_MAGIC(texture, false); + } texture->color.a = alpha; if (texture->native) { @@ -1977,11 +2013,13 @@ bool SDL_GetTextureAlphaMod(SDL_Texture *texture, Uint8 *alpha) bool SDL_GetTextureAlphaModFloat(SDL_Texture *texture, float *alpha) { - if (alpha) { - *alpha = 1.0f; - } + PARAMETER_CHECKS { + if (alpha) { + *alpha = 1.0f; + } - CHECK_TEXTURE_MAGIC(texture, false); + CHECK_TEXTURE_MAGIC(texture, false); + } if (alpha) { *alpha = texture->color.a; @@ -1993,10 +2031,12 @@ bool SDL_SetTextureBlendMode(SDL_Texture *texture, SDL_BlendMode blendMode) { SDL_Renderer *renderer; - CHECK_TEXTURE_MAGIC(texture, false); + PARAMETER_CHECKS { + CHECK_TEXTURE_MAGIC(texture, false); - if (blendMode == SDL_BLENDMODE_INVALID) { - return SDL_InvalidParamError("blendMode"); + CHECK_PARAM(blendMode == SDL_BLENDMODE_INVALID) { + return SDL_InvalidParamError("blendMode"); + } } renderer = texture->renderer; @@ -2012,11 +2052,13 @@ bool SDL_SetTextureBlendMode(SDL_Texture *texture, SDL_BlendMode blendMode) bool SDL_GetTextureBlendMode(SDL_Texture *texture, SDL_BlendMode *blendMode) { - if (blendMode) { - *blendMode = SDL_BLENDMODE_INVALID; - } + PARAMETER_CHECKS { + if (blendMode) { + *blendMode = SDL_BLENDMODE_INVALID; + } - CHECK_TEXTURE_MAGIC(texture, false); + CHECK_TEXTURE_MAGIC(texture, false); + } if (blendMode) { *blendMode = texture->blendMode; @@ -2026,15 +2068,17 @@ bool SDL_GetTextureBlendMode(SDL_Texture *texture, SDL_BlendMode *blendMode) bool SDL_SetTextureScaleMode(SDL_Texture *texture, SDL_ScaleMode scaleMode) { - CHECK_TEXTURE_MAGIC(texture, false); + PARAMETER_CHECKS { + CHECK_TEXTURE_MAGIC(texture, false); - switch (scaleMode) { - case SDL_SCALEMODE_NEAREST: - case SDL_SCALEMODE_LINEAR: - case SDL_SCALEMODE_PIXELART: - break; - default: - return SDL_InvalidParamError("scaleMode"); + switch (scaleMode) { + case SDL_SCALEMODE_NEAREST: + case SDL_SCALEMODE_LINEAR: + case SDL_SCALEMODE_PIXELART: + break; + default: + return SDL_InvalidParamError("scaleMode"); + } } texture->scaleMode = scaleMode; @@ -2047,11 +2091,13 @@ bool SDL_SetTextureScaleMode(SDL_Texture *texture, SDL_ScaleMode scaleMode) bool SDL_GetTextureScaleMode(SDL_Texture *texture, SDL_ScaleMode *scaleMode) { - if (scaleMode) { - *scaleMode = SDL_SCALEMODE_LINEAR; - } + PARAMETER_CHECKS { + if (scaleMode) { + *scaleMode = SDL_SCALEMODE_LINEAR; + } - CHECK_TEXTURE_MAGIC(texture, false); + CHECK_TEXTURE_MAGIC(texture, false); + } if (scaleMode) { *scaleMode = texture->scaleMode; @@ -2151,13 +2197,15 @@ bool SDL_UpdateTexture(SDL_Texture *texture, const SDL_Rect *rect, const void *p { SDL_Rect real_rect; - CHECK_TEXTURE_MAGIC(texture, false); + PARAMETER_CHECKS { + CHECK_TEXTURE_MAGIC(texture, false); - if (!pixels) { - return SDL_InvalidParamError("pixels"); - } - if (!pitch) { - return SDL_InvalidParamError("pitch"); + CHECK_PARAM(!pixels) { + return SDL_InvalidParamError("pixels"); + } + CHECK_PARAM(!pitch) { + return SDL_InvalidParamError("pitch"); + } } real_rect.x = 0; @@ -2302,30 +2350,32 @@ bool SDL_UpdateYUVTexture(SDL_Texture *texture, const SDL_Rect *rect, SDL_Renderer *renderer; SDL_Rect real_rect; - CHECK_TEXTURE_MAGIC(texture, false); + PARAMETER_CHECKS { + CHECK_TEXTURE_MAGIC(texture, false); - if (!Yplane) { - return SDL_InvalidParamError("Yplane"); - } - if (!Ypitch) { - return SDL_InvalidParamError("Ypitch"); - } - if (!Uplane) { - return SDL_InvalidParamError("Uplane"); - } - if (!Upitch) { - return SDL_InvalidParamError("Upitch"); - } - if (!Vplane) { - return SDL_InvalidParamError("Vplane"); - } - if (!Vpitch) { - return SDL_InvalidParamError("Vpitch"); - } + CHECK_PARAM(!Yplane) { + return SDL_InvalidParamError("Yplane"); + } + CHECK_PARAM(!Ypitch) { + return SDL_InvalidParamError("Ypitch"); + } + CHECK_PARAM(!Uplane) { + return SDL_InvalidParamError("Uplane"); + } + CHECK_PARAM(!Upitch) { + return SDL_InvalidParamError("Upitch"); + } + CHECK_PARAM(!Vplane) { + return SDL_InvalidParamError("Vplane"); + } + CHECK_PARAM(!Vpitch) { + return SDL_InvalidParamError("Vpitch"); + } - if (texture->format != SDL_PIXELFORMAT_YV12 && - texture->format != SDL_PIXELFORMAT_IYUV) { - return SDL_SetError("Texture format must by YV12 or IYUV"); + CHECK_PARAM(texture->format != SDL_PIXELFORMAT_YV12 && + texture->format != SDL_PIXELFORMAT_IYUV) { + return SDL_SetError("Texture format must by YV12 or IYUV"); + } } real_rect.x = 0; @@ -2368,24 +2418,26 @@ bool SDL_UpdateNVTexture(SDL_Texture *texture, const SDL_Rect *rect, SDL_Renderer *renderer; SDL_Rect real_rect; - CHECK_TEXTURE_MAGIC(texture, false); + PARAMETER_CHECKS { + CHECK_TEXTURE_MAGIC(texture, false); - if (!Yplane) { - return SDL_InvalidParamError("Yplane"); - } - if (!Ypitch) { - return SDL_InvalidParamError("Ypitch"); - } - if (!UVplane) { - return SDL_InvalidParamError("UVplane"); - } - if (!UVpitch) { - return SDL_InvalidParamError("UVpitch"); - } + CHECK_PARAM(!Yplane) { + return SDL_InvalidParamError("Yplane"); + } + CHECK_PARAM(!Ypitch) { + return SDL_InvalidParamError("Ypitch"); + } + CHECK_PARAM(!UVplane) { + return SDL_InvalidParamError("UVplane"); + } + CHECK_PARAM(!UVpitch) { + return SDL_InvalidParamError("UVpitch"); + } - if (texture->format != SDL_PIXELFORMAT_NV12 && - texture->format != SDL_PIXELFORMAT_NV21) { - return SDL_SetError("Texture format must by NV12 or NV21"); + CHECK_PARAM(texture->format != SDL_PIXELFORMAT_NV12 && + texture->format != SDL_PIXELFORMAT_NV21) { + return SDL_SetError("Texture format must by NV12 or NV21"); + } } real_rect.x = 0; @@ -2443,10 +2495,12 @@ bool SDL_LockTexture(SDL_Texture *texture, const SDL_Rect *rect, void **pixels, { SDL_Rect full_rect; - CHECK_TEXTURE_MAGIC(texture, false); + PARAMETER_CHECKS { + CHECK_TEXTURE_MAGIC(texture, false); - if (texture->access != SDL_TEXTUREACCESS_STREAMING) { - return SDL_SetError("SDL_LockTexture(): texture must be streaming"); + CHECK_PARAM(texture->access != SDL_TEXTUREACCESS_STREAMING) { + return SDL_SetError("SDL_LockTexture(): texture must be streaming"); + } } if (!rect) { @@ -2483,8 +2537,12 @@ bool SDL_LockTextureToSurface(SDL_Texture *texture, const SDL_Rect *rect, SDL_Su void *pixels = NULL; int pitch = 0; // fix static analysis - if (!texture || !surface) { - return false; + PARAMETER_CHECKS { + CHECK_TEXTURE_MAGIC(texture, false); + + CHECK_PARAM(!surface) { + return SDL_InvalidParamError("surface"); + } } real_rect.x = 0; @@ -2553,11 +2611,14 @@ static void SDL_UnlockTextureNative(SDL_Texture *texture) void SDL_UnlockTexture(SDL_Texture *texture) { - CHECK_TEXTURE_MAGIC(texture,); + PARAMETER_CHECKS { + CHECK_TEXTURE_MAGIC(texture,); - if (texture->access != SDL_TEXTUREACCESS_STREAMING) { - return; + if (texture->access != SDL_TEXTUREACCESS_STREAMING) { + return; + } } + #ifdef SDL_HAVE_YUV if (texture->yuv) { SDL_UnlockTextureYUV(texture); @@ -2576,15 +2637,23 @@ void SDL_UnlockTexture(SDL_Texture *texture) bool SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) { + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false); + } + // texture == NULL is valid and means reset the target to the window if (texture) { - CHECK_TEXTURE_MAGIC(texture, false); - if (renderer != texture->renderer) { - return SDL_SetError("Texture was not created with this renderer"); - } - if (texture->access != SDL_TEXTUREACCESS_TARGET) { - return SDL_SetError("Texture not created with SDL_TEXTUREACCESS_TARGET"); + PARAMETER_CHECKS { + CHECK_TEXTURE_MAGIC(texture, false); + + CHECK_PARAM(renderer != texture->renderer) { + return SDL_SetError("Texture was not created with this renderer"); + } + CHECK_PARAM(texture->access != SDL_TEXTUREACCESS_TARGET) { + return SDL_SetError("Texture not created with SDL_TEXTUREACCESS_TARGET"); + } } + if (texture->native) { // Always render to the native texture texture = texture->native; @@ -2628,7 +2697,10 @@ bool SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) SDL_Texture *SDL_GetRenderTarget(SDL_Renderer *renderer) { - CHECK_RENDERER_MAGIC(renderer, NULL); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, NULL); + } + if (!renderer->target) { return NULL; } @@ -2783,11 +2855,13 @@ bool SDL_GetRenderLogicalPresentation(SDL_Renderer *renderer, int *w, int *h, SD { #define SETVAL(ptr, val) if (ptr) { *ptr = val; } - SETVAL(w, 0); - SETVAL(h, 0); - SETVAL(mode, SDL_LOGICAL_PRESENTATION_DISABLED); + PARAMETER_CHECKS { + SETVAL(w, 0); + SETVAL(h, 0); + SETVAL(mode, SDL_LOGICAL_PRESENTATION_DISABLED); - CHECK_RENDERER_MAGIC(renderer, false); + CHECK_RENDERER_MAGIC(renderer, false); + } const SDL_RenderViewState *view = renderer->view; SETVAL(w, view->logical_w); @@ -2801,11 +2875,13 @@ bool SDL_GetRenderLogicalPresentation(SDL_Renderer *renderer, int *w, int *h, SD bool SDL_GetRenderLogicalPresentationRect(SDL_Renderer *renderer, SDL_FRect *rect) { - if (rect) { - SDL_zerop(rect); - } + PARAMETER_CHECKS { + if (rect) { + SDL_zerop(rect); + } - CHECK_RENDERER_MAGIC(renderer, false); + CHECK_RENDERER_MAGIC(renderer, false); + } if (rect) { SDL_copyp(rect, &renderer->view->logical_dst_rect); @@ -2840,7 +2916,9 @@ bool SDL_RenderCoordinatesFromWindow(SDL_Renderer *renderer, float window_x, flo { float render_x, render_y; - CHECK_RENDERER_MAGIC(renderer, false); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false); + } // Convert from window coordinates to pixels within the window render_x = window_x * renderer->dpi_scale.x; @@ -2869,7 +2947,9 @@ bool SDL_RenderCoordinatesFromWindow(SDL_Renderer *renderer, float window_x, flo bool SDL_RenderCoordinatesToWindow(SDL_Renderer *renderer, float x, float y, float *window_x, float *window_y) { - CHECK_RENDERER_MAGIC(renderer, false); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false); + } const SDL_RenderViewState *view = &renderer->main_view; x = (view->viewport.x + x) * view->scale.x; @@ -2898,7 +2978,9 @@ bool SDL_RenderCoordinatesToWindow(SDL_Renderer *renderer, float x, float y, flo bool SDL_ConvertEventToRenderCoordinates(SDL_Renderer *renderer, SDL_Event *event) { - CHECK_RENDERER_MAGIC(renderer, false); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false); + } if (event->type == SDL_EVENT_MOUSE_MOTION) { SDL_Window *window = SDL_GetWindowFromID(event->motion.windowID); @@ -2967,7 +3049,9 @@ bool SDL_ConvertEventToRenderCoordinates(SDL_Renderer *renderer, SDL_Event *even bool SDL_SetRenderViewport(SDL_Renderer *renderer, const SDL_Rect *rect) { - CHECK_RENDERER_MAGIC(renderer, false); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false); + } SDL_RenderViewState *view = renderer->view; if (rect) { @@ -2986,11 +3070,13 @@ bool SDL_SetRenderViewport(SDL_Renderer *renderer, const SDL_Rect *rect) bool SDL_GetRenderViewport(SDL_Renderer *renderer, SDL_Rect *rect) { - if (rect) { - SDL_zerop(rect); - } + PARAMETER_CHECKS { + if (rect) { + SDL_zerop(rect); + } - CHECK_RENDERER_MAGIC(renderer, false); + CHECK_RENDERER_MAGIC(renderer, false); + } if (rect) { const SDL_RenderViewState *view = renderer->view; @@ -3012,7 +3098,9 @@ bool SDL_GetRenderViewport(SDL_Renderer *renderer, SDL_Rect *rect) bool SDL_RenderViewportSet(SDL_Renderer *renderer) { - CHECK_RENDERER_MAGIC(renderer, false); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false); + } const SDL_RenderViewState *view = renderer->view; return (view->viewport.w >= 0 && view->viewport.h >= 0); @@ -3042,11 +3130,13 @@ static void GetRenderViewportSize(SDL_Renderer *renderer, SDL_FRect *rect) bool SDL_GetRenderSafeArea(SDL_Renderer *renderer, SDL_Rect *rect) { - if (rect) { - SDL_zerop(rect); - } + PARAMETER_CHECKS { + if (rect) { + SDL_zerop(rect); + } - CHECK_RENDERER_MAGIC(renderer, false); + CHECK_RENDERER_MAGIC(renderer, false); + } if (renderer->target || !renderer->window) { // The entire viewport is safe for rendering @@ -3089,7 +3179,9 @@ bool SDL_GetRenderSafeArea(SDL_Renderer *renderer, SDL_Rect *rect) bool SDL_SetRenderClipRect(SDL_Renderer *renderer, const SDL_Rect *rect) { - CHECK_RENDERER_MAGIC(renderer, false) + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false) + } SDL_RenderViewState *view = renderer->view; if (rect && rect->w >= 0 && rect->h >= 0) { @@ -3106,11 +3198,13 @@ bool SDL_SetRenderClipRect(SDL_Renderer *renderer, const SDL_Rect *rect) bool SDL_GetRenderClipRect(SDL_Renderer *renderer, SDL_Rect *rect) { - if (rect) { - SDL_zerop(rect); - } + PARAMETER_CHECKS { + if (rect) { + SDL_zerop(rect); + } - CHECK_RENDERER_MAGIC(renderer, false) + CHECK_RENDERER_MAGIC(renderer, false) + } if (rect) { SDL_copyp(rect, &renderer->view->clip_rect); @@ -3120,7 +3214,9 @@ bool SDL_GetRenderClipRect(SDL_Renderer *renderer, SDL_Rect *rect) bool SDL_RenderClipEnabled(SDL_Renderer *renderer) { - CHECK_RENDERER_MAGIC(renderer, false) + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false) + } return renderer->view->clipping_enabled; } @@ -3128,7 +3224,9 @@ bool SDL_SetRenderScale(SDL_Renderer *renderer, float scaleX, float scaleY) { bool result = true; - CHECK_RENDERER_MAGIC(renderer, false); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false); + } SDL_RenderViewState *view = renderer->view; @@ -3151,14 +3249,16 @@ bool SDL_SetRenderScale(SDL_Renderer *renderer, float scaleX, float scaleY) bool SDL_GetRenderScale(SDL_Renderer *renderer, float *scaleX, float *scaleY) { - if (scaleX) { - *scaleX = 1.0f; - } - if (scaleY) { - *scaleY = 1.0f; - } + PARAMETER_CHECKS { + if (scaleX) { + *scaleX = 1.0f; + } + if (scaleY) { + *scaleY = 1.0f; + } - CHECK_RENDERER_MAGIC(renderer, false); + CHECK_RENDERER_MAGIC(renderer, false); + } const SDL_RenderViewState *view = renderer->view; @@ -3183,7 +3283,9 @@ bool SDL_SetRenderDrawColor(SDL_Renderer *renderer, Uint8 r, Uint8 g, Uint8 b, U bool SDL_SetRenderDrawColorFloat(SDL_Renderer *renderer, float r, float g, float b, float a) { - CHECK_RENDERER_MAGIC(renderer, false); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false); + } renderer->color.r = r; renderer->color.g = g; @@ -3231,20 +3333,22 @@ bool SDL_GetRenderDrawColorFloat(SDL_Renderer *renderer, float *r, float *g, flo { SDL_FColor color; - if (r) { - *r = 0.0f; - } - if (g) { - *g = 0.0f; - } - if (b) { - *b = 0.0f; - } - if (a) { - *a = 0.0f; - } + PARAMETER_CHECKS { + if (r) { + *r = 0.0f; + } + if (g) { + *g = 0.0f; + } + if (b) { + *b = 0.0f; + } + if (a) { + *a = 0.0f; + } - CHECK_RENDERER_MAGIC(renderer, false); + CHECK_RENDERER_MAGIC(renderer, false); + } color = renderer->color; @@ -3265,7 +3369,9 @@ bool SDL_GetRenderDrawColorFloat(SDL_Renderer *renderer, float *r, float *g, flo bool SDL_SetRenderColorScale(SDL_Renderer *renderer, float scale) { - CHECK_RENDERER_MAGIC(renderer, false); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false); + } renderer->desired_color_scale = scale; UpdateColorScale(renderer); @@ -3274,11 +3380,13 @@ bool SDL_SetRenderColorScale(SDL_Renderer *renderer, float scale) bool SDL_GetRenderColorScale(SDL_Renderer *renderer, float *scale) { - if (scale) { - *scale = 1.0f; - } + PARAMETER_CHECKS { + if (scale) { + *scale = 1.0f; + } - CHECK_RENDERER_MAGIC(renderer, false); + CHECK_RENDERER_MAGIC(renderer, false); + } if (scale) { *scale = renderer->desired_color_scale; @@ -3288,10 +3396,12 @@ bool SDL_GetRenderColorScale(SDL_Renderer *renderer, float *scale) bool SDL_SetRenderDrawBlendMode(SDL_Renderer *renderer, SDL_BlendMode blendMode) { - CHECK_RENDERER_MAGIC(renderer, false); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false); - if (blendMode == SDL_BLENDMODE_INVALID) { - return SDL_InvalidParamError("blendMode"); + CHECK_PARAM(blendMode == SDL_BLENDMODE_INVALID) { + return SDL_InvalidParamError("blendMode"); + } } if (!IsSupportedBlendMode(renderer, blendMode)) { @@ -3304,11 +3414,13 @@ bool SDL_SetRenderDrawBlendMode(SDL_Renderer *renderer, SDL_BlendMode blendMode) bool SDL_GetRenderDrawBlendMode(SDL_Renderer *renderer, SDL_BlendMode *blendMode) { - if (blendMode) { - *blendMode = SDL_BLENDMODE_INVALID; - } + PARAMETER_CHECKS { + if (blendMode) { + *blendMode = SDL_BLENDMODE_INVALID; + } - CHECK_RENDERER_MAGIC(renderer, false); + CHECK_RENDERER_MAGIC(renderer, false); + } if (blendMode) { *blendMode = renderer->blendMode; @@ -3318,7 +3430,9 @@ bool SDL_GetRenderDrawBlendMode(SDL_Renderer *renderer, SDL_BlendMode *blendMode bool SDL_RenderClear(SDL_Renderer *renderer) { - CHECK_RENDERER_MAGIC(renderer, false); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false); + } return QueueCmdClear(renderer); } @@ -3368,11 +3482,14 @@ bool SDL_RenderPoints(SDL_Renderer *renderer, const SDL_FPoint *points, int coun { bool result; - CHECK_RENDERER_MAGIC(renderer, false); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false); - if (!points) { - return SDL_InvalidParamError("SDL_RenderPoints(): points"); + CHECK_PARAM(!points) { + return SDL_InvalidParamError("SDL_RenderPoints(): points"); + } } + if (count < 1) { return true; } @@ -3574,11 +3691,14 @@ bool SDL_RenderLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count { bool result = true; - CHECK_RENDERER_MAGIC(renderer, false); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false); - if (!points) { - return SDL_InvalidParamError("SDL_RenderLines(): points"); + CHECK_PARAM(!points) { + return SDL_InvalidParamError("SDL_RenderLines(): points"); + } } + if (count < 2) { return true; } @@ -3728,7 +3848,9 @@ bool SDL_RenderRect(SDL_Renderer *renderer, const SDL_FRect *rect) SDL_FRect frect; SDL_FPoint points[5]; - CHECK_RENDERER_MAGIC(renderer, false); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false); + } // If 'rect' == NULL, then outline the whole surface if (!rect) { @@ -3753,11 +3875,14 @@ bool SDL_RenderRects(SDL_Renderer *renderer, const SDL_FRect *rects, int count) { int i; - CHECK_RENDERER_MAGIC(renderer, false); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false); - if (!rects) { - return SDL_InvalidParamError("SDL_RenderRects(): rects"); + CHECK_PARAM(!rects) { + return SDL_InvalidParamError("SDL_RenderRects(): rects"); + } } + if (count < 1) { return true; } @@ -3781,7 +3906,9 @@ bool SDL_RenderFillRect(SDL_Renderer *renderer, const SDL_FRect *rect) { SDL_FRect frect; - CHECK_RENDERER_MAGIC(renderer, false); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false); + } // If 'rect' == NULL, then fill the whole surface if (!rect) { @@ -3798,11 +3925,14 @@ bool SDL_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int cou bool result; bool isstack; - CHECK_RENDERER_MAGIC(renderer, false); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false); - if (!rects) { - return SDL_InvalidParamError("SDL_RenderFillRects(): rects"); + CHECK_PARAM(!rects) { + return SDL_InvalidParamError("SDL_RenderFillRects(): rects"); + } } + if (count < 1) { return true; } @@ -3897,11 +4027,13 @@ static bool SDL_RenderTextureInternal(SDL_Renderer *renderer, SDL_Texture *textu bool SDL_RenderTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_FRect *srcrect, const SDL_FRect *dstrect) { - CHECK_RENDERER_MAGIC(renderer, false); - CHECK_TEXTURE_MAGIC(texture, false); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false); + CHECK_TEXTURE_MAGIC(texture, false); - if (renderer != texture->renderer) { - return SDL_SetError("Texture was not created with this renderer"); + CHECK_PARAM(renderer != texture->renderer) { + return SDL_SetError("Texture was not created with this renderer"); + } } #if DONT_DRAW_WHILE_HIDDEN @@ -3944,11 +4076,13 @@ bool SDL_RenderTextureAffine(SDL_Renderer *renderer, SDL_Texture *texture, SDL_FRect real_dstrect; bool result; - CHECK_RENDERER_MAGIC(renderer, false); - CHECK_TEXTURE_MAGIC(texture, false); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false); + CHECK_TEXTURE_MAGIC(texture, false); - if (renderer != texture->renderer) { - return SDL_SetError("Texture was not created with this renderer"); + CHECK_PARAM(renderer != texture->renderer) { + return SDL_SetError("Texture was not created with this renderer"); + } } if (!renderer->QueueCopyEx && !renderer->QueueGeometry) { return SDL_SetError("Renderer does not support RenderCopyEx"); @@ -4067,11 +4201,13 @@ bool SDL_RenderTextureRotated(SDL_Renderer *renderer, SDL_Texture *texture, return SDL_RenderTexture(renderer, texture, srcrect, dstrect); } - CHECK_RENDERER_MAGIC(renderer, false); - CHECK_TEXTURE_MAGIC(texture, false); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false); + CHECK_TEXTURE_MAGIC(texture, false); - if (renderer != texture->renderer) { - return SDL_SetError("Texture was not created with this renderer"); + CHECK_PARAM(renderer != texture->renderer) { + return SDL_SetError("Texture was not created with this renderer"); + } } if (!renderer->QueueCopyEx && !renderer->QueueGeometry) { return SDL_SetError("Renderer does not support RenderCopyEx"); @@ -4323,15 +4459,17 @@ bool SDL_RenderTextureTiled(SDL_Renderer *renderer, SDL_Texture *texture, const { SDL_FRect real_srcrect; - CHECK_RENDERER_MAGIC(renderer, false); - CHECK_TEXTURE_MAGIC(texture, false); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false); + CHECK_TEXTURE_MAGIC(texture, false); - if (renderer != texture->renderer) { - return SDL_SetError("Texture was not created with this renderer"); - } + CHECK_PARAM(renderer != texture->renderer) { + return SDL_SetError("Texture was not created with this renderer"); + } - if (scale <= 0.0f) { - return SDL_InvalidParamError("scale"); + CHECK_PARAM(scale <= 0.0f) { + return SDL_InvalidParamError("scale"); + } } #if DONT_DRAW_WHILE_HIDDEN @@ -4390,11 +4528,13 @@ bool SDL_RenderTexture9Grid(SDL_Renderer *renderer, SDL_Texture *texture, const float dst_top_height; float dst_bottom_height; - CHECK_RENDERER_MAGIC(renderer, false); - CHECK_TEXTURE_MAGIC(texture, false); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false); + CHECK_TEXTURE_MAGIC(texture, false); - if (renderer != texture->renderer) { - return SDL_SetError("Texture was not created with this renderer"); + CHECK_PARAM(renderer != texture->renderer) { + return SDL_SetError("Texture was not created with this renderer"); + } } if (!srcrect) { @@ -4527,11 +4667,13 @@ bool SDL_RenderTexture9GridTiled(SDL_Renderer *renderer, SDL_Texture *texture, c float dst_top_height; float dst_bottom_height; - CHECK_RENDERER_MAGIC(renderer, false); - CHECK_TEXTURE_MAGIC(texture, false); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false); + CHECK_TEXTURE_MAGIC(texture, false); - if (renderer != texture->renderer) { - return SDL_SetError("Texture was not created with this renderer"); + CHECK_PARAM(renderer != texture->renderer) { + return SDL_SetError("Texture was not created with this renderer"); + } } if (!srcrect) { @@ -5075,44 +5217,48 @@ bool SDL_RenderGeometryRaw(SDL_Renderer *renderer, SDL_TextureAddressMode texture_address_mode_u; SDL_TextureAddressMode texture_address_mode_v; - CHECK_RENDERER_MAGIC(renderer, false); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false); + + if (texture) { + CHECK_TEXTURE_MAGIC(texture, false); + + CHECK_PARAM(renderer != texture->renderer) { + return SDL_SetError("Texture was not created with this renderer"); + } + } + + CHECK_PARAM(!xy) { + return SDL_InvalidParamError("xy"); + } + + CHECK_PARAM(!color) { + return SDL_InvalidParamError("color"); + } + + CHECK_PARAM(texture && !uv) { + return SDL_InvalidParamError("uv"); + } + + CHECK_PARAM(count % 3 != 0) { + return SDL_InvalidParamError(indices ? "num_indices" : "num_vertices"); + } + + if (indices) { + CHECK_PARAM(size_indices != 1 && size_indices != 2 && size_indices != 4) { + return SDL_InvalidParamError("size_indices"); + } + } + } + + if (!indices) { + size_indices = 0; + } if (!renderer->QueueGeometry) { return SDL_Unsupported(); } - if (texture) { - CHECK_TEXTURE_MAGIC(texture, false); - - if (renderer != texture->renderer) { - return SDL_SetError("Texture was not created with this renderer"); - } - } - - if (!xy) { - return SDL_InvalidParamError("xy"); - } - - if (!color) { - return SDL_InvalidParamError("color"); - } - - if (texture && !uv) { - return SDL_InvalidParamError("uv"); - } - - if (count % 3 != 0) { - return SDL_InvalidParamError(indices ? "num_indices" : "num_vertices"); - } - - if (indices) { - if (size_indices != 1 && size_indices != 2 && size_indices != 4) { - return SDL_InvalidParamError("size_indices"); - } - } else { - size_indices = 0; - } - #if DONT_DRAW_WHILE_HIDDEN // Don't draw while we're hidden if (renderer->hidden) { @@ -5203,7 +5349,9 @@ bool SDL_RenderGeometryRaw(SDL_Renderer *renderer, bool SDL_SetRenderTextureAddressMode(SDL_Renderer *renderer, SDL_TextureAddressMode u_mode, SDL_TextureAddressMode v_mode) { - CHECK_RENDERER_MAGIC(renderer, false); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false); + } renderer->texture_address_mode_u = u_mode; renderer->texture_address_mode_v = v_mode; @@ -5212,14 +5360,16 @@ bool SDL_SetRenderTextureAddressMode(SDL_Renderer *renderer, SDL_TextureAddressM bool SDL_GetRenderTextureAddressMode(SDL_Renderer *renderer, SDL_TextureAddressMode *u_mode, SDL_TextureAddressMode *v_mode) { - if (u_mode) { - *u_mode = SDL_TEXTURE_ADDRESS_INVALID; - } - if (v_mode) { - *v_mode = SDL_TEXTURE_ADDRESS_INVALID; - } + PARAMETER_CHECKS { + if (u_mode) { + *u_mode = SDL_TEXTURE_ADDRESS_INVALID; + } + if (v_mode) { + *v_mode = SDL_TEXTURE_ADDRESS_INVALID; + } - CHECK_RENDERER_MAGIC(renderer, false); + CHECK_RENDERER_MAGIC(renderer, false); + } if (u_mode) { *u_mode = renderer->texture_address_mode_u; @@ -5232,7 +5382,9 @@ bool SDL_GetRenderTextureAddressMode(SDL_Renderer *renderer, SDL_TextureAddressM SDL_Surface *SDL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect) { - CHECK_RENDERER_MAGIC(renderer, NULL); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, NULL); + } if (!renderer->RenderReadPixels) { SDL_Unsupported(); @@ -5335,10 +5487,12 @@ bool SDL_RenderPresent(SDL_Renderer *renderer) { bool presented = true; - CHECK_RENDERER_MAGIC(renderer, false); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false); - if (renderer->target) { - return SDL_SetError("You can't present on a render target"); + CHECK_PARAM(renderer->target) { + return SDL_SetError("You can't present on a render target"); + } } if (renderer->transparent_window) { @@ -5412,7 +5566,9 @@ static void SDL_DestroyTextureInternal(SDL_Texture *texture, bool is_destroying) void SDL_DestroyTexture(SDL_Texture *texture) { - CHECK_TEXTURE_MAGIC(texture, ); + PARAMETER_CHECKS { + CHECK_TEXTURE_MAGIC(texture, ); + } if (--texture->refcount > 0) { return; @@ -5504,7 +5660,9 @@ void SDL_DestroyRendererWithoutFreeing(SDL_Renderer *renderer) void SDL_DestroyRenderer(SDL_Renderer *renderer) { - CHECK_RENDERER_MAGIC_BUT_NOT_DESTROYED_FLAG(renderer,); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC_BUT_NOT_DESTROYED_FLAG(renderer,); + } // if we've already destroyed the renderer through SDL_DestroyWindow, we just need // to free the renderer pointer. This lets apps destroy the window and renderer @@ -5535,7 +5693,9 @@ void SDL_DestroyRenderer(SDL_Renderer *renderer) void *SDL_GetRenderMetalLayer(SDL_Renderer *renderer) { - CHECK_RENDERER_MAGIC(renderer, NULL); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, NULL); + } if (renderer->GetMetalLayer) { FlushRenderCommands(renderer); // in case the app is going to mess with it. @@ -5546,7 +5706,9 @@ void *SDL_GetRenderMetalLayer(SDL_Renderer *renderer) void *SDL_GetRenderMetalCommandEncoder(SDL_Renderer *renderer) { - CHECK_RENDERER_MAGIC(renderer, NULL); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, NULL); + } if (renderer->GetMetalCommandEncoder) { FlushRenderCommands(renderer); // in case the app is going to mess with it. @@ -5557,7 +5719,9 @@ void *SDL_GetRenderMetalCommandEncoder(SDL_Renderer *renderer) bool SDL_AddVulkanRenderSemaphores(SDL_Renderer *renderer, Uint32 wait_stage_mask, Sint64 wait_semaphore, Sint64 signal_semaphore) { - CHECK_RENDERER_MAGIC(renderer, false); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false); + } if (!renderer->AddVulkanRenderSemaphores) { return SDL_Unsupported(); @@ -5665,7 +5829,9 @@ SDL_BlendOperation SDL_GetBlendModeAlphaOperation(SDL_BlendMode blendMode) bool SDL_SetRenderVSync(SDL_Renderer *renderer, int vsync) { - CHECK_RENDERER_MAGIC(renderer, false); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false); + } renderer->wanted_vsync = vsync ? true : false; @@ -5705,11 +5871,13 @@ bool SDL_SetRenderVSync(SDL_Renderer *renderer, int vsync) bool SDL_GetRenderVSync(SDL_Renderer *renderer, int *vsync) { - if (vsync) { - *vsync = 0; - } + PARAMETER_CHECKS { + if (vsync) { + *vsync = 0; + } - CHECK_RENDERER_MAGIC(renderer, false); + CHECK_RENDERER_MAGIC(renderer, false); + } if (vsync) { *vsync = (int)SDL_GetNumberProperty(SDL_GetRendererProperties(renderer), SDL_PROP_RENDERER_VSYNC_NUMBER, 0); @@ -5810,7 +5978,9 @@ static bool DrawDebugCharacter(SDL_Renderer *renderer, float x, float y, Uint32 bool SDL_RenderDebugText(SDL_Renderer *renderer, float x, float y, const char *s) { - CHECK_RENDERER_MAGIC(renderer, false); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false); + } // Allocate a texture atlas for this renderer if needed. if (!renderer->debug_char_texture_atlas) { @@ -5865,7 +6035,9 @@ bool SDL_RenderDebugTextFormat(SDL_Renderer *renderer, float x, float y, SDL_PRI bool SDL_SetDefaultTextureScaleMode(SDL_Renderer *renderer, SDL_ScaleMode scale_mode) { - CHECK_RENDERER_MAGIC(renderer, false); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false); + } renderer->scale_mode = scale_mode; @@ -5874,11 +6046,13 @@ bool SDL_SetDefaultTextureScaleMode(SDL_Renderer *renderer, SDL_ScaleMode scale_ bool SDL_GetDefaultTextureScaleMode(SDL_Renderer *renderer, SDL_ScaleMode *scale_mode) { - if (scale_mode) { - *scale_mode = SDL_SCALEMODE_LINEAR; - } + PARAMETER_CHECKS { + if (scale_mode) { + *scale_mode = SDL_SCALEMODE_LINEAR; + } - CHECK_RENDERER_MAGIC(renderer, false); + CHECK_RENDERER_MAGIC(renderer, false); + } if (scale_mode) { *scale_mode = renderer->scale_mode; @@ -5888,16 +6062,18 @@ bool SDL_GetDefaultTextureScaleMode(SDL_Renderer *renderer, SDL_ScaleMode *scale SDL_GPURenderState *SDL_CreateGPURenderState(SDL_Renderer *renderer, SDL_GPURenderStateCreateInfo *createinfo) { - CHECK_RENDERER_MAGIC(renderer, NULL); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, NULL); - if (!createinfo) { - SDL_InvalidParamError("createinfo"); - return NULL; - } + CHECK_PARAM(!createinfo) { + SDL_InvalidParamError("createinfo"); + return NULL; + } - if (!createinfo->fragment_shader) { - SDL_SetError("A fragment_shader is required"); - return NULL; + CHECK_PARAM(!createinfo->fragment_shader) { + SDL_SetError("A fragment_shader is required"); + return NULL; + } } SDL_GPUDevice *device = (SDL_GPUDevice *)SDL_GetPointerProperty(renderer->props, SDL_PROP_RENDERER_GPU_DEVICE_POINTER, NULL); @@ -5993,7 +6169,9 @@ bool SDL_SetGPURenderStateFragmentUniforms(SDL_GPURenderState *state, Uint32 slo bool SDL_SetRenderGPUState(SDL_Renderer *renderer, SDL_GPURenderState *state) { - CHECK_RENDERER_MAGIC(renderer, false); + PARAMETER_CHECKS { + CHECK_RENDERER_MAGIC(renderer, false); + } renderer->gpu_render_state = state; return true;