src/video/SDL_fill.c
changeset 2253 6d99edd791bf
child 2830 af3dd02cf043
equal deleted inserted replaced
2252:b80e3d57941f 2253:6d99edd791bf
       
     1 /*
       
     2     SDL - Simple DirectMedia Layer
       
     3     Copyright (C) 1997-2006 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 > 15) { \
       
    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 DEFINE_SSE_FILLRECT(1, Uint8)
       
    96 DEFINE_SSE_FILLRECT(2, Uint16)
       
    97 DEFINE_SSE_FILLRECT(4, Uint32)
       
    98 
       
    99 /* *INDENT-ON* */
       
   100 #endif /* __SSE__ */
       
   101 
       
   102 #ifdef __MMX__
       
   103 /* *INDENT-OFF* */
       
   104 
       
   105 #define MMX_BEGIN \
       
   106     __m64 c64 = _mm_set_pi32(color, color)
       
   107 
       
   108 #define MMX_WORK \
       
   109     for (i = n / 64; i--;) { \
       
   110         _mm_stream_pi((__m64 *)(p+0), c64); \
       
   111         _mm_stream_pi((__m64 *)(p+8), c64); \
       
   112         _mm_stream_pi((__m64 *)(p+16), c64); \
       
   113         _mm_stream_pi((__m64 *)(p+24), c64); \
       
   114         _mm_stream_pi((__m64 *)(p+32), c64); \
       
   115         _mm_stream_pi((__m64 *)(p+40), c64); \
       
   116         _mm_stream_pi((__m64 *)(p+48), c64); \
       
   117         _mm_stream_pi((__m64 *)(p+56), c64); \
       
   118         p += 64; \
       
   119     }
       
   120 
       
   121 #define MMX_END \
       
   122     _mm_empty()
       
   123 
       
   124 #define DEFINE_MMX_FILLRECT(bpp, type) \
       
   125 static void \
       
   126 SDL_FillRect##bpp##MMX(Uint8 *pixels, int pitch, Uint32 color, int w, int h) \
       
   127 { \
       
   128     MMX_BEGIN; \
       
   129  \
       
   130     while (h--) { \
       
   131         int i, n = w * bpp; \
       
   132         Uint8 *p = pixels; \
       
   133  \
       
   134         if (n > 7) { \
       
   135             int adjust = 8 - ((uintptr_t)p & 7); \
       
   136             if (adjust < 8) { \
       
   137                 n -= adjust; \
       
   138                 adjust /= bpp; \
       
   139                 while(adjust--) { \
       
   140                     *((type *)p) = (type)color; \
       
   141                     p += bpp; \
       
   142                 } \
       
   143             } \
       
   144             MMX_WORK; \
       
   145         } \
       
   146         if (n & 63) { \
       
   147             int remainder = (n & 63); \
       
   148             remainder /= bpp; \
       
   149             while(remainder--) { \
       
   150                 *((type *)p) = (type)color; \
       
   151                 p += bpp; \
       
   152             } \
       
   153         } \
       
   154         pixels += pitch; \
       
   155     } \
       
   156  \
       
   157     MMX_END; \
       
   158 }
       
   159 
       
   160 DEFINE_MMX_FILLRECT(1, Uint8)
       
   161 DEFINE_MMX_FILLRECT(2, Uint16)
       
   162 DEFINE_MMX_FILLRECT(4, Uint32)
       
   163 
       
   164 /* *INDENT-ON* */
       
   165 #endif /* __MMX__ */
       
   166 
       
   167 static void
       
   168 SDL_FillRect1(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
       
   169 {
       
   170     while (h--) {
       
   171         int n = w;
       
   172         Uint8 *p = pixels;
       
   173 
       
   174         if (n > 3) {
       
   175             switch ((uintptr_t) p & 3) {
       
   176             case 1:
       
   177                 *p++ = (Uint8) color;
       
   178                 --n;
       
   179             case 2:
       
   180                 *p++ = (Uint8) color;
       
   181                 --n;
       
   182             case 3:
       
   183                 *p++ = (Uint8) color;
       
   184                 --n;
       
   185             }
       
   186             SDL_memset4(p, color, (n >> 2));
       
   187         }
       
   188         if (n & 3) {
       
   189             p += (n & ~3);
       
   190             switch (n & 3) {
       
   191             case 3:
       
   192                 *p++ = (Uint8) color;
       
   193             case 2:
       
   194                 *p++ = (Uint8) color;
       
   195             case 1:
       
   196                 *p++ = (Uint8) color;
       
   197             }
       
   198         }
       
   199         pixels += pitch;
       
   200     }
       
   201 }
       
   202 
       
   203 static void
       
   204 SDL_FillRect2(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
       
   205 {
       
   206     while (h--) {
       
   207         int n = w;
       
   208         Uint16 *p = (Uint16 *) pixels;
       
   209 
       
   210         if (n > 1) {
       
   211             if ((uintptr_t) p & 2) {
       
   212                 *p++ = (Uint16) color;
       
   213                 --n;
       
   214             }
       
   215             SDL_memset4(p, color, (n >> 1));
       
   216         }
       
   217         if (n & 1) {
       
   218             p[n - 1] = (Uint16) color;
       
   219         }
       
   220         pixels += pitch;
       
   221     }
       
   222 }
       
   223 
       
   224 static void
       
   225 SDL_FillRect3(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
       
   226 {
       
   227     Uint8 r = (Uint8) ((color >> 16) & 0xFF);
       
   228     Uint8 g = (Uint8) ((color >> 8) & 0xFF);
       
   229     Uint8 b = (Uint8) (color & 0xFF);
       
   230 
       
   231     while (h--) {
       
   232         int n = w;
       
   233         Uint8 *p = pixels;
       
   234 
       
   235         while (n--) {
       
   236             *p++ = r;
       
   237             *p++ = g;
       
   238             *p++ = b;
       
   239         }
       
   240         pixels += pitch;
       
   241     }
       
   242 }
       
   243 
       
   244 static void
       
   245 SDL_FillRect4(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
       
   246 {
       
   247     while (h--) {
       
   248         SDL_memset4(pixels, color, w);
       
   249         pixels += pitch;
       
   250     }
       
   251 }
       
   252 
       
   253 /* 
       
   254  * This function performs a fast fill of the given rectangle with 'color'
       
   255  */
       
   256 int
       
   257 SDL_FillRect(SDL_Surface * dst, SDL_Rect * dstrect, Uint32 color)
       
   258 {
       
   259     Uint8 *pixels;
       
   260 
       
   261     /* This function doesn't work on surfaces < 8 bpp */
       
   262     if (dst->format->BitsPerPixel < 8) {
       
   263         SDL_SetError("SDL_FillRect(): Unsupported surface format");
       
   264         return (-1);
       
   265     }
       
   266 
       
   267     /* If 'dstrect' == NULL, then fill the whole surface */
       
   268     if (dstrect) {
       
   269         /* Perform clipping */
       
   270         if (!SDL_IntersectRect(dstrect, &dst->clip_rect, dstrect)) {
       
   271             return (0);
       
   272         }
       
   273     } else {
       
   274         dstrect = &dst->clip_rect;
       
   275     }
       
   276 
       
   277     /* Perform software fill */
       
   278     if (!dst->pixels) {
       
   279         SDL_SetError("SDL_FillRect(): You must lock the surface");
       
   280         return (-1);
       
   281     }
       
   282 
       
   283     pixels =
       
   284         (Uint8 *) dst->pixels + dstrect->y * dst->pitch +
       
   285         dstrect->x * dst->format->BytesPerPixel;
       
   286 
       
   287     switch (dst->format->BytesPerPixel) {
       
   288     case 1:
       
   289         {
       
   290             color |= (color << 8);
       
   291             color |= (color << 16);
       
   292 #ifdef __SSE__
       
   293             if (SDL_HasSSE()) {
       
   294                 SDL_FillRect1SSE(pixels, dst->pitch, color, dstrect->w,
       
   295                                  dstrect->h);
       
   296                 break;
       
   297             }
       
   298 #endif
       
   299 #ifdef __MMX__
       
   300             if (SDL_HasMMX()) {
       
   301                 SDL_FillRect1MMX(pixels, dst->pitch, color, dstrect->w,
       
   302                                  dstrect->h);
       
   303                 break;
       
   304             }
       
   305 #endif
       
   306             SDL_FillRect1(pixels, dst->pitch, color, dstrect->w, dstrect->h);
       
   307             break;
       
   308         }
       
   309 
       
   310     case 2:
       
   311         {
       
   312             color |= (color << 16);
       
   313 #ifdef __SSE__
       
   314             if (SDL_HasSSE()) {
       
   315                 SDL_FillRect2SSE(pixels, dst->pitch, color, dstrect->w,
       
   316                                  dstrect->h);
       
   317                 break;
       
   318             }
       
   319 #endif
       
   320 #ifdef __MMX__
       
   321             if (SDL_HasMMX()) {
       
   322                 SDL_FillRect2MMX(pixels, dst->pitch, color, dstrect->w,
       
   323                                  dstrect->h);
       
   324                 break;
       
   325             }
       
   326 #endif
       
   327             SDL_FillRect2(pixels, dst->pitch, color, dstrect->w, dstrect->h);
       
   328             break;
       
   329         }
       
   330 
       
   331     case 3:
       
   332         /* 24-bit RGB is a slow path, at least for now. */
       
   333         {
       
   334             SDL_FillRect3(pixels, dst->pitch, color, dstrect->w, dstrect->h);
       
   335             break;
       
   336         }
       
   337 
       
   338     case 4:
       
   339         {
       
   340 #ifdef __SSE__
       
   341             if (SDL_HasSSE()) {
       
   342                 SDL_FillRect4SSE(pixels, dst->pitch, color, dstrect->w,
       
   343                                  dstrect->h);
       
   344                 break;
       
   345             }
       
   346 #endif
       
   347 #ifdef __MMX__
       
   348             if (SDL_HasMMX()) {
       
   349                 SDL_FillRect4MMX(pixels, dst->pitch, color, dstrect->w,
       
   350                                  dstrect->h);
       
   351                 break;
       
   352             }
       
   353 #endif
       
   354             SDL_FillRect4(pixels, dst->pitch, color, dstrect->w, dstrect->h);
       
   355             break;
       
   356         }
       
   357     }
       
   358 
       
   359     SDL_UnlockSurface(dst);
       
   360 
       
   361     /* We're done! */
       
   362     return (0);
       
   363 }
       
   364 
       
   365 /* vi: set ts=4 sw=4 expandtab: */