SDL_fillrect.c (7970B)
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org> 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_video.h" 24#include "SDL_blit.h" 25 26 27#ifdef __SSE__ 28/* *INDENT-OFF* */ 29 30#ifdef _MSC_VER 31#define SSE_BEGIN \ 32 __m128 c128; \ 33 c128.m128_u32[0] = color; \ 34 c128.m128_u32[1] = color; \ 35 c128.m128_u32[2] = color; \ 36 c128.m128_u32[3] = color; 37#else 38#define SSE_BEGIN \ 39 __m128 c128; \ 40 DECLARE_ALIGNED(Uint32, cccc[4], 16); \ 41 cccc[0] = color; \ 42 cccc[1] = color; \ 43 cccc[2] = color; \ 44 cccc[3] = color; \ 45 c128 = *(__m128 *)cccc; 46#endif 47 48#define SSE_WORK \ 49 for (i = n / 64; i--;) { \ 50 _mm_stream_ps((float *)(p+0), c128); \ 51 _mm_stream_ps((float *)(p+16), c128); \ 52 _mm_stream_ps((float *)(p+32), c128); \ 53 _mm_stream_ps((float *)(p+48), c128); \ 54 p += 64; \ 55 } 56 57#define SSE_END 58 59#define DEFINE_SSE_FILLRECT(bpp, type) \ 60static void \ 61SDL_FillRect##bpp##SSE(Uint8 *pixels, int pitch, Uint32 color, int w, int h) \ 62{ \ 63 int i, n; \ 64 Uint8 *p = NULL; \ 65 \ 66 SSE_BEGIN; \ 67 \ 68 while (h--) { \ 69 n = w * bpp; \ 70 p = pixels; \ 71 \ 72 if (n > 63) { \ 73 int adjust = 16 - ((uintptr_t)p & 15); \ 74 if (adjust < 16) { \ 75 n -= adjust; \ 76 adjust /= bpp; \ 77 while (adjust--) { \ 78 *((type *)p) = (type)color; \ 79 p += bpp; \ 80 } \ 81 } \ 82 SSE_WORK; \ 83 } \ 84 if (n & 63) { \ 85 int remainder = (n & 63); \ 86 remainder /= bpp; \ 87 while (remainder--) { \ 88 *((type *)p) = (type)color; \ 89 p += bpp; \ 90 } \ 91 } \ 92 pixels += pitch; \ 93 } \ 94 \ 95 SSE_END; \ 96} 97 98static void 99SDL_FillRect1SSE(Uint8 *pixels, int pitch, Uint32 color, int w, int h) 100{ 101 int i, n; 102 103 SSE_BEGIN; 104 while (h--) { 105 Uint8 *p = pixels; 106 n = w; 107 108 if (n > 63) { 109 int adjust = 16 - ((uintptr_t)p & 15); 110 if (adjust) { 111 n -= adjust; 112 SDL_memset(p, color, adjust); 113 p += adjust; 114 } 115 SSE_WORK; 116 } 117 if (n & 63) { 118 int remainder = (n & 63); 119 SDL_memset(p, color, remainder); 120 } 121 pixels += pitch; 122 } 123 124 SSE_END; 125} 126/* DEFINE_SSE_FILLRECT(1, Uint8) */ 127DEFINE_SSE_FILLRECT(2, Uint16) 128DEFINE_SSE_FILLRECT(4, Uint32) 129 130/* *INDENT-ON* */ 131#endif /* __SSE__ */ 132 133static void 134SDL_FillRect1(Uint8 * pixels, int pitch, Uint32 color, int w, int h) 135{ 136 int n; 137 Uint8 *p = NULL; 138 139 while (h--) { 140 n = w; 141 p = pixels; 142 143 if (n > 3) { 144 switch ((uintptr_t) p & 3) { 145 case 1: 146 *p++ = (Uint8) color; 147 --n; 148 case 2: 149 *p++ = (Uint8) color; 150 --n; 151 case 3: 152 *p++ = (Uint8) color; 153 --n; 154 } 155 SDL_memset4(p, color, (n >> 2)); 156 } 157 if (n & 3) { 158 p += (n & ~3); 159 switch (n & 3) { 160 case 3: 161 *p++ = (Uint8) color; 162 case 2: 163 *p++ = (Uint8) color; 164 case 1: 165 *p++ = (Uint8) color; 166 } 167 } 168 pixels += pitch; 169 } 170} 171 172static void 173SDL_FillRect2(Uint8 * pixels, int pitch, Uint32 color, int w, int h) 174{ 175 int n; 176 Uint16 *p = NULL; 177 178 while (h--) { 179 n = w; 180 p = (Uint16 *) pixels; 181 182 if (n > 1) { 183 if ((uintptr_t) p & 2) { 184 *p++ = (Uint16) color; 185 --n; 186 } 187 SDL_memset4(p, color, (n >> 1)); 188 } 189 if (n & 1) { 190 p[n - 1] = (Uint16) color; 191 } 192 pixels += pitch; 193 } 194} 195 196static void 197SDL_FillRect3(Uint8 * pixels, int pitch, Uint32 color, int w, int h) 198{ 199 Uint8 r = (Uint8) ((color >> 16) & 0xFF); 200 Uint8 g = (Uint8) ((color >> 8) & 0xFF); 201 Uint8 b = (Uint8) (color & 0xFF); 202 int n; 203 Uint8 *p = NULL; 204 205 while (h--) { 206 n = w; 207 p = pixels; 208 209 while (n--) { 210 *p++ = r; 211 *p++ = g; 212 *p++ = b; 213 } 214 pixels += pitch; 215 } 216} 217 218static void 219SDL_FillRect4(Uint8 * pixels, int pitch, Uint32 color, int w, int h) 220{ 221 while (h--) { 222 SDL_memset4(pixels, color, w); 223 pixels += pitch; 224 } 225} 226 227/* 228 * This function performs a fast fill of the given rectangle with 'color' 229 */ 230int 231SDL_FillRect(SDL_Surface * dst, const SDL_Rect * rect, Uint32 color) 232{ 233 SDL_Rect clipped; 234 Uint8 *pixels; 235 236 if (!dst) { 237 return SDL_SetError("Passed NULL destination surface"); 238 } 239 240 /* This function doesn't work on surfaces < 8 bpp */ 241 if (dst->format->BitsPerPixel < 8) { 242 return SDL_SetError("SDL_FillRect(): Unsupported surface format"); 243 } 244 245 /* If 'rect' == NULL, then fill the whole surface */ 246 if (rect) { 247 /* Perform clipping */ 248 if (!SDL_IntersectRect(rect, &dst->clip_rect, &clipped)) { 249 return 0; 250 } 251 rect = &clipped; 252 } else { 253 rect = &dst->clip_rect; 254 } 255 256 /* Perform software fill */ 257 if (!dst->pixels) { 258 return SDL_SetError("SDL_FillRect(): You must lock the surface"); 259 } 260 261 pixels = (Uint8 *) dst->pixels + rect->y * dst->pitch + 262 rect->x * dst->format->BytesPerPixel; 263 264 switch (dst->format->BytesPerPixel) { 265 case 1: 266 { 267 color |= (color << 8); 268 color |= (color << 16); 269#ifdef __SSE__ 270 if (SDL_HasSSE()) { 271 SDL_FillRect1SSE(pixels, dst->pitch, color, rect->w, rect->h); 272 break; 273 } 274#endif 275 SDL_FillRect1(pixels, dst->pitch, color, rect->w, rect->h); 276 break; 277 } 278 279 case 2: 280 { 281 color |= (color << 16); 282#ifdef __SSE__ 283 if (SDL_HasSSE()) { 284 SDL_FillRect2SSE(pixels, dst->pitch, color, rect->w, rect->h); 285 break; 286 } 287#endif 288 SDL_FillRect2(pixels, dst->pitch, color, rect->w, rect->h); 289 break; 290 } 291 292 case 3: 293 /* 24-bit RGB is a slow path, at least for now. */ 294 { 295 SDL_FillRect3(pixels, dst->pitch, color, rect->w, rect->h); 296 break; 297 } 298 299 case 4: 300 { 301#ifdef __SSE__ 302 if (SDL_HasSSE()) { 303 SDL_FillRect4SSE(pixels, dst->pitch, color, rect->w, rect->h); 304 break; 305 } 306#endif 307 SDL_FillRect4(pixels, dst->pitch, color, rect->w, rect->h); 308 break; 309 } 310 } 311 312 /* We're done! */ 313 return 0; 314} 315 316int 317SDL_FillRects(SDL_Surface * dst, const SDL_Rect * rects, int count, 318 Uint32 color) 319{ 320 int i; 321 int status = 0; 322 323 if (!rects) { 324 return SDL_SetError("SDL_FillRects() passed NULL rects"); 325 } 326 327 for (i = 0; i < count; ++i) { 328 status += SDL_FillRect(dst, &rects[i], color); 329 } 330 return status; 331} 332 333/* vi: set ts=4 sw=4 expandtab: */