Atlas - SDL_fillrect.c
Home / ext / SDL / src / video Lines: 1 | Size: 11496 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2025 Sam Lantinga <[email protected]> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21#include "SDL_internal.h" 22 23#include "SDL_surface_c.h" 24 25#ifdef SDL_SSE_INTRINSICS 26/* *INDENT-OFF* */ // clang-format off 27 28#if defined(_MSC_VER) && !defined(__clang__) 29#define SSE_BEGIN \ 30 __m128 c128; \ 31 c128.m128_u32[0] = color; \ 32 c128.m128_u32[1] = color; \ 33 c128.m128_u32[2] = color; \ 34 c128.m128_u32[3] = color; 35#else 36#define SSE_BEGIN \ 37 __m128 c128; \ 38 DECLARE_ALIGNED(Uint32, cccc[4], 16); \ 39 cccc[0] = color; \ 40 cccc[1] = color; \ 41 cccc[2] = color; \ 42 cccc[3] = color; \ 43 c128 = *(__m128 *)cccc; 44#endif 45 46#define SSE_WORK \ 47 for (i = n / 64; i--;) { \ 48 _mm_stream_ps((float *)(p+0), c128); \ 49 _mm_stream_ps((float *)(p+16), c128); \ 50 _mm_stream_ps((float *)(p+32), c128); \ 51 _mm_stream_ps((float *)(p+48), c128); \ 52 p += 64; \ 53 } 54 55#define SSE_END 56 57#define DEFINE_SSE_FILLRECT(bpp, type) \ 58static void SDL_TARGETING("sse") SDL_FillSurfaceRect##bpp##SSE(Uint8 *pixels, int pitch, Uint32 color, int w, int h) \ 59{ \ 60 int i, n; \ 61 Uint8 *p = NULL; \ 62 \ 63 /* If the number of bytes per row is equal to the pitch, treat */ \ 64 /* all rows as one long continuous row (for better performance) */ \ 65 if ((w) * (bpp) == pitch) { \ 66 w = w * h; \ 67 h = 1; \ 68 } \ 69 \ 70 SSE_BEGIN; \ 71 \ 72 while (h--) { \ 73 n = (w) * (bpp); \ 74 p = pixels; \ 75 \ 76 if (n > 63) { \ 77 int adjust = 16 - ((uintptr_t)p & 15); \ 78 if (adjust < 16) { \ 79 n -= adjust; \ 80 adjust /= (bpp); \ 81 while (adjust--) { \ 82 *((type *)p) = (type)color; \ 83 p += (bpp); \ 84 } \ 85 } \ 86 SSE_WORK; \ 87 } \ 88 if (n & 63) { \ 89 int remainder = (n & 63); \ 90 remainder /= (bpp); \ 91 while (remainder--) { \ 92 *((type *)p) = (type)color; \ 93 p += (bpp); \ 94 } \ 95 } \ 96 pixels += pitch; \ 97 } \ 98 \ 99 SSE_END; \ 100} 101 102static void SDL_TARGETING("sse") SDL_FillSurfaceRect1SSE(Uint8 *pixels, int pitch, Uint32 color, int w, int h) 103{ 104 int i, n; 105 106 SSE_BEGIN; 107 while (h--) { 108 Uint8 *p = pixels; 109 n = w; 110 111 if (n > 63) { 112 int adjust = 16 - ((uintptr_t)p & 15); 113 if (adjust) { 114 n -= adjust; 115 SDL_memset(p, color, adjust); 116 p += adjust; 117 } 118 SSE_WORK; 119 } 120 if (n & 63) { 121 int remainder = (n & 63); 122 SDL_memset(p, color, remainder); 123 } 124 pixels += pitch; 125 } 126 127 SSE_END; 128} 129// DEFINE_SSE_FILLRECT(1, Uint8) 130DEFINE_SSE_FILLRECT(2, Uint16) 131DEFINE_SSE_FILLRECT(4, Uint32) 132 133/* *INDENT-ON* */ // clang-format on 134#endif // __SSE__ 135 136#ifdef SDL_LSX_INTRINSICS 137/* *INDENT-OFF* */ // clang-format off 138 139#define LSX_BEGIN __m128i c128 = __lsx_vreplgr2vr_w(color); 140 141#define LSX_WORK \ 142 for (i = n / 64; i--;) { \ 143 __lsx_vst(c128, p, 0); \ 144 __lsx_vst(c128, p, 16); \ 145 __lsx_vst(c128, p, 32); \ 146 __lsx_vst(c128, p, 48); \ 147 p += 64; \ 148 } 149 150#define DEFINE_LSX_FILLRECT(bpp, type) \ 151static void SDL_TARGETING("lsx") SDL_FillSurfaceRect##bpp##LSX(Uint8 *pixels, int pitch, Uint32 color, int w, int h) \ 152{ \ 153 int i, n; \ 154 Uint8 *p = NULL; \ 155 \ 156 /* If the number of bytes per row is equal to the pitch, treat */ \ 157 /* all rows as one long continuous row (for better performance) */ \ 158 if ((w) * (bpp) == pitch) { \ 159 w = w * h; \ 160 h = 1; \ 161 } \ 162 \ 163 LSX_BEGIN; \ 164 \ 165 while (h--) { \ 166 n = (w) * (bpp); \ 167 p = pixels; \ 168 \ 169 if (n > 63) { \ 170 int adjust = 16 - ((uintptr_t)p & 15); \ 171 if (adjust < 16) { \ 172 n -= adjust; \ 173 adjust /= (bpp); \ 174 while (adjust--) { \ 175 *((type *)p) = (type)color; \ 176 p += (bpp); \ 177 } \ 178 } \ 179 LSX_WORK; \ 180 } \ 181 if (n & 63) { \ 182 int remainder = (n & 63); \ 183 remainder /= (bpp); \ 184 while (remainder--) { \ 185 *((type *)p) = (type)color; \ 186 p += (bpp); \ 187 } \ 188 } \ 189 pixels += pitch; \ 190 } \ 191 \ 192} 193 194DEFINE_LSX_FILLRECT(4, Uint32) 195 196/* *INDENT-ON* */ // clang-format on 197#endif /* __LSX__ */ 198 199static void SDL_FillSurfaceRect1(Uint8 *pixels, int pitch, Uint32 color, int w, int h) 200{ 201 int n; 202 Uint8 *p = NULL; 203 204 while (h--) { 205 n = w; 206 p = pixels; 207 208 if (n > 3) { 209 switch ((uintptr_t)p & 3) { 210 case 1: 211 *p++ = (Uint8)color; 212 --n; 213 SDL_FALLTHROUGH; 214 case 2: 215 *p++ = (Uint8)color; 216 --n; 217 SDL_FALLTHROUGH; 218 case 3: 219 *p++ = (Uint8)color; 220 --n; 221 } 222 SDL_memset4(p, color, (n >> 2)); 223 } 224 if (n & 3) { 225 p += (n & ~3); 226 switch (n & 3) { 227 case 3: 228 *p++ = (Uint8)color; 229 SDL_FALLTHROUGH; 230 case 2: 231 *p++ = (Uint8)color; 232 SDL_FALLTHROUGH; 233 case 1: 234 *p++ = (Uint8)color; 235 } 236 } 237 pixels += pitch; 238 } 239} 240 241static void SDL_FillSurfaceRect2(Uint8 *pixels, int pitch, Uint32 color, int w, int h) 242{ 243 int n; 244 Uint16 *p = NULL; 245 246 while (h--) { 247 n = w; 248 p = (Uint16 *)pixels; 249 250 if (n > 1) { 251 if ((uintptr_t)p & 2) { 252 *p++ = (Uint16)color; 253 --n; 254 } 255 SDL_memset4(p, color, (n >> 1)); 256 } 257 if (n & 1) { 258 p[n - 1] = (Uint16)color; 259 } 260 pixels += pitch; 261 } 262} 263 264static void SDL_FillSurfaceRect3(Uint8 *pixels, int pitch, Uint32 color, int w, int h) 265{ 266#if SDL_BYTEORDER == SDL_LIL_ENDIAN 267 Uint8 b1 = (Uint8)(color & 0xFF); 268 Uint8 b2 = (Uint8)((color >> 8) & 0xFF); 269 Uint8 b3 = (Uint8)((color >> 16) & 0xFF); 270#elif SDL_BYTEORDER == SDL_BIG_ENDIAN 271 Uint8 b1 = (Uint8)((color >> 16) & 0xFF); 272 Uint8 b2 = (Uint8)((color >> 8) & 0xFF); 273 Uint8 b3 = (Uint8)(color & 0xFF); 274#endif 275 int n; 276 Uint8 *p = NULL; 277 278 while (h--) { 279 n = w; 280 p = pixels; 281 282 while (n--) { 283 *p++ = b1; 284 *p++ = b2; 285 *p++ = b3; 286 } 287 pixels += pitch; 288 } 289} 290 291static void SDL_FillSurfaceRect4(Uint8 *pixels, int pitch, Uint32 color, int w, int h) 292{ 293 while (h--) { 294 SDL_memset4(pixels, color, w); 295 pixels += pitch; 296 } 297} 298 299/* 300 * This function performs a fast fill of the given rectangle with 'color' 301 */ 302bool SDL_FillSurfaceRect(SDL_Surface *dst, const SDL_Rect *rect, Uint32 color) 303{ 304 CHECK_PARAM(!SDL_SurfaceValid(dst)) { 305 return SDL_InvalidParamError("SDL_FillSurfaceRect(): dst"); 306 } 307 308 // If 'rect' == NULL, then fill the whole surface 309 if (!rect) { 310 rect = &dst->clip_rect; 311 // Don't attempt to fill if the surface's clip_rect is empty 312 if (SDL_RectEmpty(rect)) { 313 return true; 314 } 315 } 316 317 return SDL_FillSurfaceRects(dst, rect, 1, color); 318} 319 320bool SDL_FillSurfaceRects(SDL_Surface *dst, const SDL_Rect *rects, int count, Uint32 color) 321{ 322 SDL_Rect clipped; 323 Uint8 *pixels; 324 const SDL_Rect *rect; 325 void (*fill_function)(Uint8 * pixels, int pitch, Uint32 color, int w, int h) = NULL; 326 int i; 327 328 CHECK_PARAM(!SDL_SurfaceValid(dst)) { 329 return SDL_InvalidParamError("SDL_FillSurfaceRects(): dst"); 330 } 331 332 CHECK_PARAM(!rects) { 333 return SDL_InvalidParamError("SDL_FillSurfaceRects(): rects"); 334 } 335 336 if (!dst->pixels && SDL_MUSTLOCK(dst)) { 337 return SDL_SetError("SDL_FillSurfaceRects(): You must lock the surface"); 338 } 339 340 // Nothing to do 341 if (dst->w == 0 || dst->h == 0 || !dst->pixels) { 342 return true; 343 } 344 345 /* This function doesn't usually work on surfaces < 8 bpp 346 * Except: support for 4bits, when filling full size. 347 */ 348 if (SDL_BITSPERPIXEL(dst->format) < 8) { 349 if (count == 1) { 350 const SDL_Rect *r = &rects[0]; 351 if (r->x == 0 && r->y == 0 && r->w == dst->w && r->h == dst->h) { 352 if (SDL_BITSPERPIXEL(dst->format) == 4) { 353 Uint8 b = (((Uint8)color << 4) | (Uint8)color); 354 SDL_memset(dst->pixels, b, (size_t)dst->h * dst->pitch); 355 return true; 356 } 357 } 358 } 359 return SDL_SetError("SDL_FillSurfaceRects(): Unsupported surface format"); 360 } 361 362 if (fill_function == NULL) { 363 switch (SDL_BYTESPERPIXEL(dst->format)) { 364 case 1: 365 { 366 color |= (color << 8); 367 color |= (color << 16); 368#ifdef SDL_SSE_INTRINSICS 369 if (SDL_HasSSE()) { 370 fill_function = SDL_FillSurfaceRect1SSE; 371 break; 372 } 373#endif 374 fill_function = SDL_FillSurfaceRect1; 375 break; 376 } 377 378 case 2: 379 { 380 color |= (color << 16); 381#ifdef SDL_SSE_INTRINSICS 382 if (SDL_HasSSE()) { 383 fill_function = SDL_FillSurfaceRect2SSE; 384 break; 385 } 386#endif 387 fill_function = SDL_FillSurfaceRect2; 388 break; 389 } 390 391 case 3: 392 // 24-bit RGB is a slow path, at least for now. 393 { 394 fill_function = SDL_FillSurfaceRect3; 395 break; 396 } 397 398 case 4: 399 { 400#ifdef SDL_SSE_INTRINSICS 401 if (SDL_HasSSE()) { 402 fill_function = SDL_FillSurfaceRect4SSE; 403 break; 404 } 405#endif 406#ifdef SDL_LSX_INTRINSICS 407 if (SDL_HasLSX()) { 408 fill_function = SDL_FillSurfaceRect4LSX; 409 break; 410 } 411#endif 412 fill_function = SDL_FillSurfaceRect4; 413 break; 414 } 415 416 default: 417 return SDL_SetError("Unsupported pixel format"); 418 } 419 } 420 421 for (i = 0; i < count; ++i) { 422 rect = &rects[i]; 423 // Perform clipping 424 if (!SDL_GetRectIntersection(rect, &dst->clip_rect, &clipped)) { 425 continue; 426 } 427 rect = &clipped; 428 429 pixels = (Uint8 *)dst->pixels + rect->y * dst->pitch + 430 rect->x * SDL_BYTESPERPIXEL(dst->format); 431 432 fill_function(pixels, dst->pitch, color, rect->w, rect->h); 433 } 434 435 // We're done! 436 return true; 437} 438[FILE END](C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.