src/video/SDL_fillrect.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 14 Jul 2013 11:28:44 -0700
changeset 7776 d4a39491577f
parent 7682 f182a912606a
child 7998 097e3fac1979
permissions -rw-r--r--
Added the platform specific messagebox function to the video function list
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2013 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_config.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     Uint8 *p = NULL;
   103     
   104     SSE_BEGIN;
   105     while (h--) {
   106         n = w;
   107         p = pixels;
   108 
   109         if (n > 63) {
   110             int adjust = 16 - ((uintptr_t)p & 15);
   111             if (adjust) {
   112                 n -= adjust;
   113                 SDL_memset(p, color, adjust);
   114                 p += adjust;
   115             }
   116             SSE_WORK;
   117         }
   118         if (n & 63) {
   119             int remainder = (n & 63);
   120             SDL_memset(p, color, remainder);
   121             p += remainder;
   122         }
   123         pixels += pitch;
   124     }
   125 
   126     SSE_END;
   127 }
   128 /* DEFINE_SSE_FILLRECT(1, Uint8) */
   129 DEFINE_SSE_FILLRECT(2, Uint16)
   130 DEFINE_SSE_FILLRECT(4, Uint32)
   131 
   132 /* *INDENT-ON* */
   133 #endif /* __SSE__ */
   134 
   135 #ifdef __MMX__
   136 /* *INDENT-OFF* */
   137 
   138 #define MMX_BEGIN \
   139     __m64 c64 = _mm_set_pi32(color, color)
   140 
   141 #define MMX_WORK \
   142     for (i = n / 64; i--;) { \
   143         _mm_stream_pi((__m64 *)(p+0), c64); \
   144         _mm_stream_pi((__m64 *)(p+8), c64); \
   145         _mm_stream_pi((__m64 *)(p+16), c64); \
   146         _mm_stream_pi((__m64 *)(p+24), c64); \
   147         _mm_stream_pi((__m64 *)(p+32), c64); \
   148         _mm_stream_pi((__m64 *)(p+40), c64); \
   149         _mm_stream_pi((__m64 *)(p+48), c64); \
   150         _mm_stream_pi((__m64 *)(p+56), c64); \
   151         p += 64; \
   152     }
   153 
   154 #define MMX_END \
   155     _mm_empty()
   156 
   157 #define DEFINE_MMX_FILLRECT(bpp, type) \
   158 static void \
   159 SDL_FillRect##bpp##MMX(Uint8 *pixels, int pitch, Uint32 color, int w, int h) \
   160 { \
   161     int i, n; \
   162     Uint8 *p = NULL; \
   163  \
   164     MMX_BEGIN; \
   165  \
   166     while (h--) { \
   167         n = w * bpp; \
   168         p = pixels; \
   169  \
   170         if (n > 63) { \
   171             int adjust = 8 - ((uintptr_t)p & 7); \
   172             if (adjust < 8) { \
   173                 n -= adjust; \
   174                 adjust /= bpp; \
   175                 while (adjust--) { \
   176                     *((type *)p) = (type)color; \
   177                     p += bpp; \
   178                 } \
   179             } \
   180             MMX_WORK; \
   181         } \
   182         if (n & 63) { \
   183             int remainder = (n & 63); \
   184             remainder /= bpp; \
   185             while (remainder--) { \
   186                 *((type *)p) = (type)color; \
   187                 p += bpp; \
   188             } \
   189         } \
   190         pixels += pitch; \
   191     } \
   192  \
   193     MMX_END; \
   194 }
   195 
   196 static void
   197 SDL_FillRect1MMX(Uint8 *pixels, int pitch, Uint32 color, int w, int h)
   198 {
   199     int i, n;
   200     Uint8 *p = NULL;
   201     
   202     MMX_BEGIN;
   203 
   204     while (h--) {
   205         n = w;
   206         p = pixels;
   207 
   208         if (n > 63) {
   209             int adjust = 8 - ((uintptr_t)p & 7);
   210             if (adjust) {
   211                 n -= adjust;
   212                 SDL_memset(p, color, adjust);
   213                 p += adjust;
   214             }
   215             MMX_WORK;
   216         }
   217         if (n & 63) {
   218             int remainder = (n & 63);
   219             SDL_memset(p, color, remainder);
   220             p += remainder;
   221         }
   222         pixels += pitch;
   223     }
   224 
   225     MMX_END;
   226 }
   227 /* DEFINE_MMX_FILLRECT(1, Uint8) */
   228 DEFINE_MMX_FILLRECT(2, Uint16)
   229 DEFINE_MMX_FILLRECT(4, Uint32)
   230 
   231 /* *INDENT-ON* */
   232 #endif /* __MMX__ */
   233 
   234 static void
   235 SDL_FillRect1(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
   236 {
   237     int n;
   238     Uint8 *p = NULL;
   239     
   240     while (h--) {
   241         n = w;
   242         p = pixels;
   243 
   244         if (n > 3) {
   245             switch ((uintptr_t) p & 3) {
   246             case 1:
   247                 *p++ = (Uint8) color;
   248                 --n;
   249             case 2:
   250                 *p++ = (Uint8) color;
   251                 --n;
   252             case 3:
   253                 *p++ = (Uint8) color;
   254                 --n;
   255             }
   256             SDL_memset4(p, color, (n >> 2));
   257         }
   258         if (n & 3) {
   259             p += (n & ~3);
   260             switch (n & 3) {
   261             case 3:
   262                 *p++ = (Uint8) color;
   263             case 2:
   264                 *p++ = (Uint8) color;
   265             case 1:
   266                 *p++ = (Uint8) color;
   267             }
   268         }
   269         pixels += pitch;
   270     }
   271 }
   272 
   273 static void
   274 SDL_FillRect2(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
   275 {
   276     int n;
   277     Uint16 *p = NULL;
   278     
   279     while (h--) {
   280         n = w;
   281         p = (Uint16 *) pixels;
   282 
   283         if (n > 1) {
   284             if ((uintptr_t) p & 2) {
   285                 *p++ = (Uint16) color;
   286                 --n;
   287             }
   288             SDL_memset4(p, color, (n >> 1));
   289         }
   290         if (n & 1) {
   291             p[n - 1] = (Uint16) color;
   292         }
   293         pixels += pitch;
   294     }
   295 }
   296 
   297 static void
   298 SDL_FillRect3(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
   299 {
   300     Uint8 r = (Uint8) ((color >> 16) & 0xFF);
   301     Uint8 g = (Uint8) ((color >> 8) & 0xFF);
   302     Uint8 b = (Uint8) (color & 0xFF);
   303     int n;
   304     Uint8 *p = NULL;
   305 
   306     while (h--) {
   307         n = w;
   308         p = pixels;
   309 
   310         while (n--) {
   311             *p++ = r;
   312             *p++ = g;
   313             *p++ = b;
   314         }
   315         pixels += pitch;
   316     }
   317 }
   318 
   319 static void
   320 SDL_FillRect4(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
   321 {
   322     while (h--) {
   323         SDL_memset4(pixels, color, w);
   324         pixels += pitch;
   325     }
   326 }
   327 
   328 /* 
   329  * This function performs a fast fill of the given rectangle with 'color'
   330  */
   331 int
   332 SDL_FillRect(SDL_Surface * dst, const SDL_Rect * rect, Uint32 color)
   333 {
   334     SDL_Rect clipped;
   335     Uint8 *pixels;
   336 
   337     if (!dst) {
   338         return SDL_SetError("Passed NULL destination surface");
   339     }
   340 
   341     /* This function doesn't work on surfaces < 8 bpp */
   342     if (dst->format->BitsPerPixel < 8) {
   343         return SDL_SetError("SDL_FillRect(): Unsupported surface format");
   344     }
   345 
   346     /* If 'rect' == NULL, then fill the whole surface */
   347     if (rect) {
   348         /* Perform clipping */
   349         if (!SDL_IntersectRect(rect, &dst->clip_rect, &clipped)) {
   350             return 0;
   351         }
   352         rect = &clipped;
   353     } else {
   354         rect = &dst->clip_rect;
   355     }
   356 
   357     /* Perform software fill */
   358     if (!dst->pixels) {
   359         return SDL_SetError("SDL_FillRect(): You must lock the surface");
   360     }
   361 
   362     pixels = (Uint8 *) dst->pixels + rect->y * dst->pitch +
   363                                      rect->x * dst->format->BytesPerPixel;
   364 
   365     switch (dst->format->BytesPerPixel) {
   366     case 1:
   367         {
   368             color |= (color << 8);
   369             color |= (color << 16);
   370 #ifdef __SSE__
   371             if (SDL_HasSSE()) {
   372                 SDL_FillRect1SSE(pixels, dst->pitch, color, rect->w, rect->h);
   373                 break;
   374             }
   375 #endif
   376 #ifdef __MMX__
   377             if (SDL_HasMMX()) {
   378                 SDL_FillRect1MMX(pixels, dst->pitch, color, rect->w, rect->h);
   379                 break;
   380             }
   381 #endif
   382             SDL_FillRect1(pixels, dst->pitch, color, rect->w, rect->h);
   383             break;
   384         }
   385 
   386     case 2:
   387         {
   388             color |= (color << 16);
   389 #ifdef __SSE__
   390             if (SDL_HasSSE()) {
   391                 SDL_FillRect2SSE(pixels, dst->pitch, color, rect->w, rect->h);
   392                 break;
   393             }
   394 #endif
   395 #ifdef __MMX__
   396             if (SDL_HasMMX()) {
   397                 SDL_FillRect2MMX(pixels, dst->pitch, color, rect->w, rect->h);
   398                 break;
   399             }
   400 #endif
   401             SDL_FillRect2(pixels, dst->pitch, color, rect->w, rect->h);
   402             break;
   403         }
   404 
   405     case 3:
   406         /* 24-bit RGB is a slow path, at least for now. */
   407         {
   408             SDL_FillRect3(pixels, dst->pitch, color, rect->w, rect->h);
   409             break;
   410         }
   411 
   412     case 4:
   413         {
   414 #ifdef __SSE__
   415             if (SDL_HasSSE()) {
   416                 SDL_FillRect4SSE(pixels, dst->pitch, color, rect->w, rect->h);
   417                 break;
   418             }
   419 #endif
   420 #ifdef __MMX__
   421             if (SDL_HasMMX()) {
   422                 SDL_FillRect4MMX(pixels, dst->pitch, color, rect->w, rect->h);
   423                 break;
   424             }
   425 #endif
   426             SDL_FillRect4(pixels, dst->pitch, color, rect->w, rect->h);
   427             break;
   428         }
   429     }
   430 
   431     /* We're done! */
   432     return 0;
   433 }
   434 
   435 int
   436 SDL_FillRects(SDL_Surface * dst, const SDL_Rect * rects, int count,
   437               Uint32 color)
   438 {
   439     int i;
   440     int status = 0;
   441 
   442     if (!rects) {
   443         return SDL_SetError("SDL_FillRects() passed NULL rects");
   444     }
   445 
   446     for (i = 0; i < count; ++i) {
   447         status += SDL_FillRect(dst, &rects[i], color);
   448     }
   449     return status;
   450 }
   451 
   452 /* vi: set ts=4 sw=4 expandtab: */