src/video/SDL_fillrect.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 10 Jan 2009 18:32:24 +0000
changeset 3012 7e30c2dc7783
parent 2913 ffae53de58f4
child 3536 0267b8b1595c
permissions -rw-r--r--
Fixed Visual C++ release build for Visual C++ 2005
* Some math functions become intrinsic in release mode, so we need to
convert all the math functions into SDL math functions, like we did
with the stdlib functions.
* Constant initializers of 8-bit values become calls to memset() in
release mode, but memset() itself is an intrinsic when explicitly
called. So we'll just explicitly call memset() in those cases.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2009 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 #include "SDL_video.h"
    25 #include "SDL_blit.h"
    26 
    27 
    28 #ifdef __SSE__
    29 /* *INDENT-OFF* */
    30 
    31 #ifdef _MSC_VER
    32 #define SSE_BEGIN \
    33     __m128 c128; \
    34     c128.m128_u32[0] = color; \
    35     c128.m128_u32[1] = color; \
    36     c128.m128_u32[2] = color; \
    37     c128.m128_u32[3] = color;
    38 #else
    39 #define SSE_BEGIN \
    40     DECLARE_ALIGNED(Uint32, cccc[4], 16); \
    41     cccc[0] = color; \
    42     cccc[1] = color; \
    43     cccc[2] = color; \
    44     cccc[3] = color; \
    45     __m128 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     SSE_BEGIN; \
    64  \
    65     while (h--) { \
    66         int i, n = w * bpp; \
    67         Uint8 *p = pixels; \
    68  \
    69         if (n > 63) { \
    70             int adjust = 16 - ((uintptr_t)p & 15); \
    71             if (adjust < 16) { \
    72                 n -= adjust; \
    73                 adjust /= bpp; \
    74                 while (adjust--) { \
    75                     *((type *)p) = (type)color; \
    76                     p += bpp; \
    77                 } \
    78             } \
    79             SSE_WORK; \
    80         } \
    81         if (n & 63) { \
    82             int remainder = (n & 63); \
    83             remainder /= bpp; \
    84             while (remainder--) { \
    85                 *((type *)p) = (type)color; \
    86                 p += bpp; \
    87             } \
    88         } \
    89         pixels += pitch; \
    90     } \
    91  \
    92     SSE_END; \
    93 }
    94 
    95 static void
    96 SDL_FillRect1SSE(Uint8 *pixels, int pitch, Uint32 color, int w, int h)
    97 {
    98     SSE_BEGIN;
    99 
   100     while (h--) {
   101         int i, n = w;
   102         Uint8 *p = pixels;
   103 
   104         if (n > 63) {
   105             int adjust = 16 - ((uintptr_t)p & 15);
   106             if (adjust) {
   107                 n -= adjust;
   108                 SDL_memset(p, color, adjust);
   109                 p += adjust;
   110             }
   111             SSE_WORK;
   112         }
   113         if (n & 63) {
   114             int remainder = (n & 63);
   115             SDL_memset(p, color, remainder);
   116             p += remainder;
   117         }
   118         pixels += pitch;
   119     }
   120 
   121     SSE_END;
   122 }
   123 /*DEFINE_SSE_FILLRECT(1, Uint8)*/
   124 DEFINE_SSE_FILLRECT(2, Uint16)
   125 DEFINE_SSE_FILLRECT(4, Uint32)
   126 
   127 /* *INDENT-ON* */
   128 #endif /* __SSE__ */
   129 
   130 #ifdef __MMX__
   131 /* *INDENT-OFF* */
   132 
   133 #define MMX_BEGIN \
   134     __m64 c64 = _mm_set_pi32(color, color)
   135 
   136 #define MMX_WORK \
   137     for (i = n / 64; i--;) { \
   138         _mm_stream_pi((__m64 *)(p+0), c64); \
   139         _mm_stream_pi((__m64 *)(p+8), c64); \
   140         _mm_stream_pi((__m64 *)(p+16), c64); \
   141         _mm_stream_pi((__m64 *)(p+24), c64); \
   142         _mm_stream_pi((__m64 *)(p+32), c64); \
   143         _mm_stream_pi((__m64 *)(p+40), c64); \
   144         _mm_stream_pi((__m64 *)(p+48), c64); \
   145         _mm_stream_pi((__m64 *)(p+56), c64); \
   146         p += 64; \
   147     }
   148 
   149 #define MMX_END \
   150     _mm_empty()
   151 
   152 #define DEFINE_MMX_FILLRECT(bpp, type) \
   153 static void \
   154 SDL_FillRect##bpp##MMX(Uint8 *pixels, int pitch, Uint32 color, int w, int h) \
   155 { \
   156     MMX_BEGIN; \
   157  \
   158     while (h--) { \
   159         int i, n = w * bpp; \
   160         Uint8 *p = pixels; \
   161  \
   162         if (n > 63) { \
   163             int adjust = 8 - ((uintptr_t)p & 7); \
   164             if (adjust < 8) { \
   165                 n -= adjust; \
   166                 adjust /= bpp; \
   167                 while (adjust--) { \
   168                     *((type *)p) = (type)color; \
   169                     p += bpp; \
   170                 } \
   171             } \
   172             MMX_WORK; \
   173         } \
   174         if (n & 63) { \
   175             int remainder = (n & 63); \
   176             remainder /= bpp; \
   177             while (remainder--) { \
   178                 *((type *)p) = (type)color; \
   179                 p += bpp; \
   180             } \
   181         } \
   182         pixels += pitch; \
   183     } \
   184  \
   185     MMX_END; \
   186 }
   187 
   188 static void
   189 SDL_FillRect1MMX(Uint8 *pixels, int pitch, Uint32 color, int w, int h)
   190 {
   191     MMX_BEGIN;
   192 
   193     while (h--) {
   194         int i, n = w;
   195         Uint8 *p = pixels;
   196 
   197         if (n > 63) {
   198             int adjust = 8 - ((uintptr_t)p & 7);
   199             if (adjust) {
   200                 n -= adjust;
   201                 SDL_memset(p, color, adjust);
   202                 p += adjust;
   203             }
   204             MMX_WORK;
   205         }
   206         if (n & 63) {
   207             int remainder = (n & 63);
   208             SDL_memset(p, color, remainder);
   209             p += remainder;
   210         }
   211         pixels += pitch;
   212     }
   213 
   214     MMX_END;
   215 }
   216 /*DEFINE_MMX_FILLRECT(1, Uint8)*/
   217 DEFINE_MMX_FILLRECT(2, Uint16)
   218 DEFINE_MMX_FILLRECT(4, Uint32)
   219 
   220 /* *INDENT-ON* */
   221 #endif /* __MMX__ */
   222 
   223 static void
   224 SDL_FillRect1(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
   225 {
   226     while (h--) {
   227         int n = w;
   228         Uint8 *p = pixels;
   229 
   230         if (n > 3) {
   231             switch ((uintptr_t) p & 3) {
   232             case 1:
   233                 *p++ = (Uint8) color;
   234                 --n;
   235             case 2:
   236                 *p++ = (Uint8) color;
   237                 --n;
   238             case 3:
   239                 *p++ = (Uint8) color;
   240                 --n;
   241             }
   242             SDL_memset4(p, color, (n >> 2));
   243         }
   244         if (n & 3) {
   245             p += (n & ~3);
   246             switch (n & 3) {
   247             case 3:
   248                 *p++ = (Uint8) color;
   249             case 2:
   250                 *p++ = (Uint8) color;
   251             case 1:
   252                 *p++ = (Uint8) color;
   253             }
   254         }
   255         pixels += pitch;
   256     }
   257 }
   258 
   259 static void
   260 SDL_FillRect2(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
   261 {
   262     while (h--) {
   263         int n = w;
   264         Uint16 *p = (Uint16 *) pixels;
   265 
   266         if (n > 1) {
   267             if ((uintptr_t) p & 2) {
   268                 *p++ = (Uint16) color;
   269                 --n;
   270             }
   271             SDL_memset4(p, color, (n >> 1));
   272         }
   273         if (n & 1) {
   274             p[n - 1] = (Uint16) color;
   275         }
   276         pixels += pitch;
   277     }
   278 }
   279 
   280 static void
   281 SDL_FillRect3(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
   282 {
   283     Uint8 r = (Uint8) ((color >> 16) & 0xFF);
   284     Uint8 g = (Uint8) ((color >> 8) & 0xFF);
   285     Uint8 b = (Uint8) (color & 0xFF);
   286 
   287     while (h--) {
   288         int n = w;
   289         Uint8 *p = pixels;
   290 
   291         while (n--) {
   292             *p++ = r;
   293             *p++ = g;
   294             *p++ = b;
   295         }
   296         pixels += pitch;
   297     }
   298 }
   299 
   300 static void
   301 SDL_FillRect4(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
   302 {
   303     while (h--) {
   304         SDL_memset4(pixels, color, w);
   305         pixels += pitch;
   306     }
   307 }
   308 
   309 /* 
   310  * This function performs a fast fill of the given rectangle with 'color'
   311  */
   312 int
   313 SDL_FillRect(SDL_Surface * dst, SDL_Rect * dstrect, Uint32 color)
   314 {
   315     Uint8 *pixels;
   316 
   317     /* This function doesn't work on surfaces < 8 bpp */
   318     if (dst->format->BitsPerPixel < 8) {
   319         SDL_SetError("SDL_FillRect(): Unsupported surface format");
   320         return (-1);
   321     }
   322 
   323     /* If 'dstrect' == NULL, then fill the whole surface */
   324     if (dstrect) {
   325         /* Perform clipping */
   326         if (!SDL_IntersectRect(dstrect, &dst->clip_rect, dstrect)) {
   327             return (0);
   328         }
   329     } else {
   330         dstrect = &dst->clip_rect;
   331     }
   332 
   333     /* Perform software fill */
   334     if (!dst->pixels) {
   335         SDL_SetError("SDL_FillRect(): You must lock the surface");
   336         return (-1);
   337     }
   338 
   339     pixels =
   340         (Uint8 *) dst->pixels + dstrect->y * dst->pitch +
   341         dstrect->x * dst->format->BytesPerPixel;
   342 
   343     switch (dst->format->BytesPerPixel) {
   344     case 1:
   345         {
   346             color |= (color << 8);
   347             color |= (color << 16);
   348 #ifdef __SSE__
   349             if (SDL_HasSSE()) {
   350                 SDL_FillRect1SSE(pixels, dst->pitch, color, dstrect->w,
   351                                  dstrect->h);
   352                 break;
   353             }
   354 #endif
   355 #ifdef __MMX__
   356             if (SDL_HasMMX()) {
   357                 SDL_FillRect1MMX(pixels, dst->pitch, color, dstrect->w,
   358                                  dstrect->h);
   359                 break;
   360             }
   361 #endif
   362             SDL_FillRect1(pixels, dst->pitch, color, dstrect->w, dstrect->h);
   363             break;
   364         }
   365 
   366     case 2:
   367         {
   368             color |= (color << 16);
   369 #ifdef __SSE__
   370             if (SDL_HasSSE()) {
   371                 SDL_FillRect2SSE(pixels, dst->pitch, color, dstrect->w,
   372                                  dstrect->h);
   373                 break;
   374             }
   375 #endif
   376 #ifdef __MMX__
   377             if (SDL_HasMMX()) {
   378                 SDL_FillRect2MMX(pixels, dst->pitch, color, dstrect->w,
   379                                  dstrect->h);
   380                 break;
   381             }
   382 #endif
   383             SDL_FillRect2(pixels, dst->pitch, color, dstrect->w, dstrect->h);
   384             break;
   385         }
   386 
   387     case 3:
   388         /* 24-bit RGB is a slow path, at least for now. */
   389         {
   390             SDL_FillRect3(pixels, dst->pitch, color, dstrect->w, dstrect->h);
   391             break;
   392         }
   393 
   394     case 4:
   395         {
   396 #ifdef __SSE__
   397             if (SDL_HasSSE()) {
   398                 SDL_FillRect4SSE(pixels, dst->pitch, color, dstrect->w,
   399                                  dstrect->h);
   400                 break;
   401             }
   402 #endif
   403 #ifdef __MMX__
   404             if (SDL_HasMMX()) {
   405                 SDL_FillRect4MMX(pixels, dst->pitch, color, dstrect->w,
   406                                  dstrect->h);
   407                 break;
   408             }
   409 #endif
   410             SDL_FillRect4(pixels, dst->pitch, color, dstrect->w, dstrect->h);
   411             break;
   412         }
   413     }
   414 
   415     /* We're done! */
   416     return (0);
   417 }
   418 
   419 /* vi: set ts=4 sw=4 expandtab: */