src/video/SDL_fillrect.c
author Gabriel Jacobo
Wed, 21 Aug 2013 10:12:16 -0300
changeset 7679 b1fe132bc6a4
parent 7678 286c42d7c5ed
child 7680 6ab959ebea26
permissions -rw-r--r--
Fixes for -Wdeclaration-after-statement
     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     MMX_BEGIN;
   200 
   201     while (h--) {
   202         int i, n = w;
   203         Uint8 *p = pixels;
   204 
   205         if (n > 63) {
   206             int adjust = 8 - ((uintptr_t)p & 7);
   207             if (adjust) {
   208                 n -= adjust;
   209                 SDL_memset(p, color, adjust);
   210                 p += adjust;
   211             }
   212             MMX_WORK;
   213         }
   214         if (n & 63) {
   215             int remainder = (n & 63);
   216             SDL_memset(p, color, remainder);
   217             p += remainder;
   218         }
   219         pixels += pitch;
   220     }
   221 
   222     MMX_END;
   223 }
   224 /* DEFINE_MMX_FILLRECT(1, Uint8) */
   225 DEFINE_MMX_FILLRECT(2, Uint16)
   226 DEFINE_MMX_FILLRECT(4, Uint32)
   227 
   228 /* *INDENT-ON* */
   229 #endif /* __MMX__ */
   230 
   231 static void
   232 SDL_FillRect1(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
   233 {
   234     while (h--) {
   235         int n = w;
   236         Uint8 *p = pixels;
   237 
   238         if (n > 3) {
   239             switch ((uintptr_t) p & 3) {
   240             case 1:
   241                 *p++ = (Uint8) color;
   242                 --n;
   243             case 2:
   244                 *p++ = (Uint8) color;
   245                 --n;
   246             case 3:
   247                 *p++ = (Uint8) color;
   248                 --n;
   249             }
   250             SDL_memset4(p, color, (n >> 2));
   251         }
   252         if (n & 3) {
   253             p += (n & ~3);
   254             switch (n & 3) {
   255             case 3:
   256                 *p++ = (Uint8) color;
   257             case 2:
   258                 *p++ = (Uint8) color;
   259             case 1:
   260                 *p++ = (Uint8) color;
   261             }
   262         }
   263         pixels += pitch;
   264     }
   265 }
   266 
   267 static void
   268 SDL_FillRect2(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
   269 {
   270     while (h--) {
   271         int n = w;
   272         Uint16 *p = (Uint16 *) pixels;
   273 
   274         if (n > 1) {
   275             if ((uintptr_t) p & 2) {
   276                 *p++ = (Uint16) color;
   277                 --n;
   278             }
   279             SDL_memset4(p, color, (n >> 1));
   280         }
   281         if (n & 1) {
   282             p[n - 1] = (Uint16) color;
   283         }
   284         pixels += pitch;
   285     }
   286 }
   287 
   288 static void
   289 SDL_FillRect3(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
   290 {
   291     Uint8 r = (Uint8) ((color >> 16) & 0xFF);
   292     Uint8 g = (Uint8) ((color >> 8) & 0xFF);
   293     Uint8 b = (Uint8) (color & 0xFF);
   294 
   295     while (h--) {
   296         int n = w;
   297         Uint8 *p = pixels;
   298 
   299         while (n--) {
   300             *p++ = r;
   301             *p++ = g;
   302             *p++ = b;
   303         }
   304         pixels += pitch;
   305     }
   306 }
   307 
   308 static void
   309 SDL_FillRect4(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
   310 {
   311     while (h--) {
   312         SDL_memset4(pixels, color, w);
   313         pixels += pitch;
   314     }
   315 }
   316 
   317 /* 
   318  * This function performs a fast fill of the given rectangle with 'color'
   319  */
   320 int
   321 SDL_FillRect(SDL_Surface * dst, const SDL_Rect * rect, Uint32 color)
   322 {
   323     SDL_Rect clipped;
   324     Uint8 *pixels;
   325 
   326     if (!dst) {
   327         return SDL_SetError("Passed NULL destination surface");
   328     }
   329 
   330     /* This function doesn't work on surfaces < 8 bpp */
   331     if (dst->format->BitsPerPixel < 8) {
   332         return SDL_SetError("SDL_FillRect(): Unsupported surface format");
   333     }
   334 
   335     /* If 'rect' == NULL, then fill the whole surface */
   336     if (rect) {
   337         /* Perform clipping */
   338         if (!SDL_IntersectRect(rect, &dst->clip_rect, &clipped)) {
   339             return 0;
   340         }
   341         rect = &clipped;
   342     } else {
   343         rect = &dst->clip_rect;
   344     }
   345 
   346     /* Perform software fill */
   347     if (!dst->pixels) {
   348         return SDL_SetError("SDL_FillRect(): You must lock the surface");
   349     }
   350 
   351     pixels = (Uint8 *) dst->pixels + rect->y * dst->pitch +
   352                                      rect->x * dst->format->BytesPerPixel;
   353 
   354     switch (dst->format->BytesPerPixel) {
   355     case 1:
   356         {
   357             color |= (color << 8);
   358             color |= (color << 16);
   359 #ifdef __SSE__
   360             if (SDL_HasSSE()) {
   361                 SDL_FillRect1SSE(pixels, dst->pitch, color, rect->w, rect->h);
   362                 break;
   363             }
   364 #endif
   365 #ifdef __MMX__
   366             if (SDL_HasMMX()) {
   367                 SDL_FillRect1MMX(pixels, dst->pitch, color, rect->w, rect->h);
   368                 break;
   369             }
   370 #endif
   371             SDL_FillRect1(pixels, dst->pitch, color, rect->w, rect->h);
   372             break;
   373         }
   374 
   375     case 2:
   376         {
   377             color |= (color << 16);
   378 #ifdef __SSE__
   379             if (SDL_HasSSE()) {
   380                 SDL_FillRect2SSE(pixels, dst->pitch, color, rect->w, rect->h);
   381                 break;
   382             }
   383 #endif
   384 #ifdef __MMX__
   385             if (SDL_HasMMX()) {
   386                 SDL_FillRect2MMX(pixels, dst->pitch, color, rect->w, rect->h);
   387                 break;
   388             }
   389 #endif
   390             SDL_FillRect2(pixels, dst->pitch, color, rect->w, rect->h);
   391             break;
   392         }
   393 
   394     case 3:
   395         /* 24-bit RGB is a slow path, at least for now. */
   396         {
   397             SDL_FillRect3(pixels, dst->pitch, color, rect->w, rect->h);
   398             break;
   399         }
   400 
   401     case 4:
   402         {
   403 #ifdef __SSE__
   404             if (SDL_HasSSE()) {
   405                 SDL_FillRect4SSE(pixels, dst->pitch, color, rect->w, rect->h);
   406                 break;
   407             }
   408 #endif
   409 #ifdef __MMX__
   410             if (SDL_HasMMX()) {
   411                 SDL_FillRect4MMX(pixels, dst->pitch, color, rect->w, rect->h);
   412                 break;
   413             }
   414 #endif
   415             SDL_FillRect4(pixels, dst->pitch, color, rect->w, rect->h);
   416             break;
   417         }
   418     }
   419 
   420     /* We're done! */
   421     return 0;
   422 }
   423 
   424 int
   425 SDL_FillRects(SDL_Surface * dst, const SDL_Rect * rects, int count,
   426               Uint32 color)
   427 {
   428     int i;
   429     int status = 0;
   430 
   431     if (!rects) {
   432         return SDL_SetError("SDL_FillRects() passed NULL rects");
   433     }
   434 
   435     for (i = 0; i < count; ++i) {
   436         status += SDL_FillRect(dst, &rects[i], color);
   437     }
   438     return status;
   439 }
   440 
   441 /* vi: set ts=4 sw=4 expandtab: */