diff --git a/include/SDL3/SDL_stdinc.h b/include/SDL3/SDL_stdinc.h index e8f41543a0..8e8a0f8888 100644 --- a/include/SDL3/SDL_stdinc.h +++ b/include/SDL3/SDL_stdinc.h @@ -2600,6 +2600,26 @@ extern SDL_DECLSPEC void * SDLCALL SDL_memmove(SDL_OUT_BYTECAP(len) void *dst, S */ extern SDL_DECLSPEC void * SDLCALL SDL_memset(SDL_OUT_BYTECAP(len) void *dst, int c, size_t len); +/** + * Initialize all 16-bit words of buffer of memory to a specific value. + * + * This function will set a buffer of `words` Uint16 values, pointed to by + * `dst`, to the value specified in `val`. + * + * Unlike SDL_memset, this sets 16-bit values, not bytes, so it's not limited + * to a range of 0-255. + * + * \param dst the destination memory region. Must not be NULL. + * \param val the Uint16 value to set. + * \param words the number of Uint16 values to set in `dst`. + * \returns `dst`. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.6.0. + */ +extern SDL_DECLSPEC void * SDLCALL SDL_memset2(void *dst, Uint16 val, size_t words); + /** * Initialize all 32-bit words of buffer of memory to a specific value. * diff --git a/src/dynapi/SDL_dynapi.exports b/src/dynapi/SDL_dynapi.exports index 9864557071..b9fc41795a 100644 --- a/src/dynapi/SDL_dynapi.exports +++ b/src/dynapi/SDL_dynapi.exports @@ -1290,3 +1290,4 @@ _SDL_LoadJPG _SDL_HasSVE2 _SDL_GamepadHasCapSense _SDL_GetGamepadCapSense +_SDL_memset2 diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 3958a52aa6..9c791f39ef 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -1291,6 +1291,7 @@ SDL3_0.0.0 { SDL_HasSVE2; SDL_GamepadHasCapSense; SDL_GetGamepadCapSense; + SDL_memset2; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index b54d32ae6d..6ae05c394f 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -1317,3 +1317,4 @@ #define SDL_HasSVE2 SDL_HasSVE2_REAL #define SDL_GamepadHasCapSense SDL_GamepadHasCapSense_REAL #define SDL_GetGamepadCapSense SDL_GetGamepadCapSense_REAL +#define SDL_memset2 SDL_memset2_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 4f8ac0ba0c..95092e7049 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -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_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(void*,SDL_memset2,(void *a,Uint16 b,size_t c),(a,b,c),return) diff --git a/src/render/software/SDL_drawline.c b/src/render/software/SDL_drawline.c index 057af0186e..006c6fbf6c 100644 --- a/src/render/software/SDL_drawline.c +++ b/src/render/software/SDL_drawline.c @@ -31,15 +31,14 @@ static void SDL_DrawLine1(SDL_Surface *dst, int x1, int y1, int x2, int y2, Uint { if (y1 == y2) { int length; - int pitch = (dst->pitch / dst->fmt->bytes_per_pixel); Uint8 *pixels; if (x1 <= x2) { - pixels = (Uint8 *)dst->pixels + y1 * pitch + x1; + pixels = (Uint8 *)dst->pixels + y1 * dst->pitch + x1 * sizeof(Uint8); length = draw_end ? (x2 - x1 + 1) : (x2 - x1); } else { - pixels = (Uint8 *)dst->pixels + y1 * pitch + x2; + pixels = (Uint8 *)dst->pixels + y1 * dst->pitch + x2 * sizeof(Uint8); if (!draw_end) { - ++pixels; + pixels += sizeof(Uint8); } length = draw_end ? (x1 - x2 + 1) : (x1 - x2); } @@ -57,7 +56,19 @@ static void SDL_DrawLine2(SDL_Surface *dst, int x1, int y1, int x2, int y2, Uint bool draw_end) { if (y1 == y2) { - HLINE(Uint16, DRAW_FASTSETPIXEL2, draw_end); + int length; + Uint8 *pixels; + if (x1 <= x2) { + pixels = (Uint8 *)dst->pixels + y1 * dst->pitch + x1 * sizeof(Uint16); + length = draw_end ? (x2 - x1 + 1) : (x2 - x1); + } else { + pixels = (Uint8 *)dst->pixels + y1 * dst->pitch + x2 * sizeof(Uint16); + if (!draw_end) { + pixels += sizeof(Uint16); + } + length = draw_end ? (x1 - x2 + 1) : (x1 - x2); + } + SDL_memset2(pixels, color, length); } else if (x1 == x2) { VLINE(Uint16, DRAW_FASTSETPIXEL2, draw_end); } else if (ABS(x1 - x2) == ABS(y1 - y2)) { @@ -86,7 +97,19 @@ static void SDL_DrawLine4(SDL_Surface *dst, int x1, int y1, int x2, int y2, Uint bool draw_end) { if (y1 == y2) { - HLINE(Uint32, DRAW_FASTSETPIXEL4, draw_end); + int length; + Uint8 *pixels; + if (x1 <= x2) { + pixels = (Uint8 *)dst->pixels + y1 * dst->pitch + x1 * sizeof(Uint32); + length = draw_end ? (x2 - x1 + 1) : (x2 - x1); + } else { + pixels = (Uint8 *)dst->pixels + y1 * dst->pitch + x2 * sizeof(Uint32); + if (!draw_end) { + pixels += sizeof(Uint32); + } + length = draw_end ? (x1 - x2 + 1) : (x1 - x2); + } + SDL_memset4(pixels, color, length); } else if (x1 == x2) { VLINE(Uint32, DRAW_FASTSETPIXEL4, draw_end); } else if (ABS(x1 - x2) == ABS(y1 - y2)) { diff --git a/src/stdlib/SDL_memset.c b/src/stdlib/SDL_memset.c index d12df67cf1..c459d3ba41 100644 --- a/src/stdlib/SDL_memset.c +++ b/src/stdlib/SDL_memset.c @@ -59,9 +59,7 @@ void *SDL_memset(SDL_OUT_BYTECAP(len) void *dst, int c, size_t len) dstp4 = (Uint32 *)dstp1; left = (len % 4); len /= 4; - while (len--) { - *dstp4++ = value4; - } + SDL_memset4(dstp4, value4, len); dstp1 = (Uint8 *)dstp4; switch (left) { @@ -79,6 +77,28 @@ void *SDL_memset(SDL_OUT_BYTECAP(len) void *dst, int c, size_t len) #endif // HAVE_MEMSET } +// Note that memset() is a byte assignment and this is a 16-bit assignment, so they're not directly equivalent. +void *SDL_memset2(void *dst, Uint16 val, size_t words) +{ + size_t _n = words; + Uint16 *_p = SDL_static_cast(Uint16 *, dst); + Uint16 _val = (val); + + if (_n > 1) { + if ((uintptr_t)_p & 2) { + *_p++ = _val; + --_n; + } + SDL_memset4(_p, (_val << 16) | _val, (_n >> 1)); + } + + if (_n & 1) { + _p[_n - 1] = _val; + } + + return dst; +} + // Note that memset() is a byte assignment and this is a 32-bit assignment, so they're not directly equivalent. void *SDL_memset4(void *dst, Uint32 val, size_t dwords) { diff --git a/src/video/SDL_fillrect.c b/src/video/SDL_fillrect.c index cd42b56ed6..e07272d155 100644 --- a/src/video/SDL_fillrect.c +++ b/src/video/SDL_fillrect.c @@ -198,65 +198,16 @@ DEFINE_LSX_FILLRECT(4, Uint32) static void SDL_FillSurfaceRect1(Uint8 *pixels, int pitch, Uint32 color, int w, int h) { - int n; - Uint8 *p = NULL; - while (h--) { - n = w; - p = pixels; - - if (n > 3) { - switch ((uintptr_t)p & 3) { - case 1: - *p++ = (Uint8)color; - --n; - SDL_FALLTHROUGH; - case 2: - *p++ = (Uint8)color; - --n; - SDL_FALLTHROUGH; - case 3: - *p++ = (Uint8)color; - --n; - } - SDL_memset4(p, color, (n >> 2)); - } - if (n & 3) { - p += (n & ~3); - switch (n & 3) { - case 3: - *p++ = (Uint8)color; - SDL_FALLTHROUGH; - case 2: - *p++ = (Uint8)color; - SDL_FALLTHROUGH; - case 1: - *p++ = (Uint8)color; - } - } + SDL_memset(pixels, color, w); pixels += pitch; } } static void SDL_FillSurfaceRect2(Uint8 *pixels, int pitch, Uint32 color, int w, int h) { - int n; - Uint16 *p = NULL; - while (h--) { - n = w; - p = (Uint16 *)pixels; - - if (n > 1) { - if ((uintptr_t)p & 2) { - *p++ = (Uint16)color; - --n; - } - SDL_memset4(p, color, (n >> 1)); - } - if (n & 1) { - p[n - 1] = (Uint16)color; - } + SDL_memset2(pixels, color, w); pixels += pitch; } }