src/video/SDL_fillrect.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 17 Jul 2019 13:01:44 -0700
changeset 12945 36035e851264
parent 12503 806492103856
permissions -rw-r--r--
Added support for the Victrix Pro Fight Stick for PS4
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2019 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) \
    60 static void \
    61 SDL_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 
    98 static void
    99 SDL_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) */
   127 DEFINE_SSE_FILLRECT(2, Uint16)
   128 DEFINE_SSE_FILLRECT(4, Uint32)
   129 
   130 /* *INDENT-ON* */
   131 #endif /* __SSE__ */
   132 
   133 static void
   134 SDL_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;                    /* fallthrough */
   148             case 2:
   149                 *p++ = (Uint8) color;
   150                 --n;                    /* fallthrough */
   151             case 3:
   152                 *p++ = (Uint8) color;
   153                 --n;                    /* fallthrough */
   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;   /* fallthrough */
   162             case 2:
   163                 *p++ = (Uint8) color;   /* fallthrough */
   164             case 1:
   165                 *p++ = (Uint8) color;   /* fallthrough */
   166             }
   167         }
   168         pixels += pitch;
   169     }
   170 }
   171 
   172 static void
   173 SDL_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 
   196 static void
   197 SDL_FillRect3(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
   198 {
   199 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
   200     Uint8 b1 = (Uint8) (color & 0xFF);
   201     Uint8 b2 = (Uint8) ((color >> 8) & 0xFF);
   202     Uint8 b3 = (Uint8) ((color >> 16) & 0xFF);
   203 #elif SDL_BYTEORDER == SDL_BIG_ENDIAN
   204     Uint8 b1 = (Uint8) ((color >> 16) & 0xFF);
   205     Uint8 b2 = (Uint8) ((color >> 8) & 0xFF);
   206     Uint8 b3 = (Uint8) (color & 0xFF);
   207 #endif
   208     int n;
   209     Uint8 *p = NULL;
   210 
   211     while (h--) {
   212         n = w;
   213         p = pixels;
   214 
   215         while (n--) {
   216             *p++ = b1;
   217             *p++ = b2;
   218             *p++ = b3;
   219         }
   220         pixels += pitch;
   221     }
   222 }
   223 
   224 static void
   225 SDL_FillRect4(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
   226 {
   227     while (h--) {
   228         SDL_memset4(pixels, color, w);
   229         pixels += pitch;
   230     }
   231 }
   232 
   233 /* 
   234  * This function performs a fast fill of the given rectangle with 'color'
   235  */
   236 int
   237 SDL_FillRect(SDL_Surface * dst, const SDL_Rect * rect, Uint32 color)
   238 {
   239     SDL_Rect clipped;
   240     Uint8 *pixels;
   241 
   242     if (!dst) {
   243         return SDL_SetError("Passed NULL destination surface");
   244     }
   245 
   246     /* This function doesn't work on surfaces < 8 bpp */
   247     if (dst->format->BitsPerPixel < 8) {
   248         return SDL_SetError("SDL_FillRect(): Unsupported surface format");
   249     }
   250 
   251     /* If 'rect' == NULL, then fill the whole surface */
   252     if (rect) {
   253         /* Perform clipping */
   254         if (!SDL_IntersectRect(rect, &dst->clip_rect, &clipped)) {
   255             return 0;
   256         }
   257         rect = &clipped;
   258     } else {
   259         rect = &dst->clip_rect;
   260         /* Don't attempt to fill if the surface's clip_rect is empty */
   261         if (SDL_RectEmpty(rect)) {
   262             return 0;
   263         }
   264     }
   265 
   266     /* Perform software fill */
   267     if (!dst->pixels) {
   268         return SDL_SetError("SDL_FillRect(): You must lock the surface");
   269     }
   270 
   271     pixels = (Uint8 *) dst->pixels + rect->y * dst->pitch +
   272                                      rect->x * dst->format->BytesPerPixel;
   273 
   274     switch (dst->format->BytesPerPixel) {
   275     case 1:
   276         {
   277             color |= (color << 8);
   278             color |= (color << 16);
   279 #ifdef __SSE__
   280             if (SDL_HasSSE()) {
   281                 SDL_FillRect1SSE(pixels, dst->pitch, color, rect->w, rect->h);
   282                 break;
   283             }
   284 #endif
   285             SDL_FillRect1(pixels, dst->pitch, color, rect->w, rect->h);
   286             break;
   287         }
   288 
   289     case 2:
   290         {
   291             color |= (color << 16);
   292 #ifdef __SSE__
   293             if (SDL_HasSSE()) {
   294                 SDL_FillRect2SSE(pixels, dst->pitch, color, rect->w, rect->h);
   295                 break;
   296             }
   297 #endif
   298             SDL_FillRect2(pixels, dst->pitch, color, rect->w, rect->h);
   299             break;
   300         }
   301 
   302     case 3:
   303         /* 24-bit RGB is a slow path, at least for now. */
   304         {
   305             SDL_FillRect3(pixels, dst->pitch, color, rect->w, rect->h);
   306             break;
   307         }
   308 
   309     case 4:
   310         {
   311 #ifdef __SSE__
   312             if (SDL_HasSSE()) {
   313                 SDL_FillRect4SSE(pixels, dst->pitch, color, rect->w, rect->h);
   314                 break;
   315             }
   316 #endif
   317             SDL_FillRect4(pixels, dst->pitch, color, rect->w, rect->h);
   318             break;
   319         }
   320     }
   321 
   322     /* We're done! */
   323     return 0;
   324 }
   325 
   326 int
   327 SDL_FillRects(SDL_Surface * dst, const SDL_Rect * rects, int count,
   328               Uint32 color)
   329 {
   330     int i;
   331     int status = 0;
   332 
   333     if (!rects) {
   334         return SDL_SetError("SDL_FillRects() passed NULL rects");
   335     }
   336 
   337     for (i = 0; i < count; ++i) {
   338         status += SDL_FillRect(dst, &rects[i], color);
   339     }
   340     return status;
   341 }
   342 
   343 /* vi: set ts=4 sw=4 expandtab: */