src/video/SDL_fillrect.c
author Ryan C. Gordon
Sun, 31 Mar 2013 12:48:50 -0400
changeset 7037 3fedf1f25b94
parent 6885 700f1b25f77f
child 7677 871d43c6968a
permissions -rw-r--r--
Make SDL_SetError and friends unconditionally return -1.

This lets us change things like this...

if (Failed) {
SDL_SetError("We failed");
return -1;
}

...into this...

if (Failed) {
return SDL_SetError("We failed");
}


Fixes Bugzilla #1778.
     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     DECLARE_ALIGNED(Uint32, cccc[4], 16); \
    40     cccc[0] = color; \
    41     cccc[1] = color; \
    42     cccc[2] = color; \
    43     cccc[3] = color; \
    44     __m128 c128 = *(__m128 *)cccc;
    45 #endif
    46 
    47 #define SSE_WORK \
    48     for (i = n / 64; i--;) { \
    49         _mm_stream_ps((float *)(p+0), c128); \
    50         _mm_stream_ps((float *)(p+16), c128); \
    51         _mm_stream_ps((float *)(p+32), c128); \
    52         _mm_stream_ps((float *)(p+48), c128); \
    53         p += 64; \
    54     }
    55 
    56 #define SSE_END
    57 
    58 #define DEFINE_SSE_FILLRECT(bpp, type) \
    59 static void \
    60 SDL_FillRect##bpp##SSE(Uint8 *pixels, int pitch, Uint32 color, int w, int h) \
    61 { \
    62     SSE_BEGIN; \
    63  \
    64     while (h--) { \
    65         int i, n = w * bpp; \
    66         Uint8 *p = pixels; \
    67  \
    68         if (n > 63) { \
    69             int adjust = 16 - ((uintptr_t)p & 15); \
    70             if (adjust < 16) { \
    71                 n -= adjust; \
    72                 adjust /= bpp; \
    73                 while (adjust--) { \
    74                     *((type *)p) = (type)color; \
    75                     p += bpp; \
    76                 } \
    77             } \
    78             SSE_WORK; \
    79         } \
    80         if (n & 63) { \
    81             int remainder = (n & 63); \
    82             remainder /= bpp; \
    83             while (remainder--) { \
    84                 *((type *)p) = (type)color; \
    85                 p += bpp; \
    86             } \
    87         } \
    88         pixels += pitch; \
    89     } \
    90  \
    91     SSE_END; \
    92 }
    93 
    94 static void
    95 SDL_FillRect1SSE(Uint8 *pixels, int pitch, Uint32 color, int w, int h)
    96 {
    97     SSE_BEGIN;
    98 
    99     while (h--) {
   100         int i, n = w;
   101         Uint8 *p = pixels;
   102 
   103         if (n > 63) {
   104             int adjust = 16 - ((uintptr_t)p & 15);
   105             if (adjust) {
   106                 n -= adjust;
   107                 SDL_memset(p, color, adjust);
   108                 p += adjust;
   109             }
   110             SSE_WORK;
   111         }
   112         if (n & 63) {
   113             int remainder = (n & 63);
   114             SDL_memset(p, color, remainder);
   115             p += remainder;
   116         }
   117         pixels += pitch;
   118     }
   119 
   120     SSE_END;
   121 }
   122 /*DEFINE_SSE_FILLRECT(1, Uint8)*/
   123 DEFINE_SSE_FILLRECT(2, Uint16)
   124 DEFINE_SSE_FILLRECT(4, Uint32)
   125 
   126 /* *INDENT-ON* */
   127 #endif /* __SSE__ */
   128 
   129 #ifdef __MMX__
   130 /* *INDENT-OFF* */
   131 
   132 #define MMX_BEGIN \
   133     __m64 c64 = _mm_set_pi32(color, color)
   134 
   135 #define MMX_WORK \
   136     for (i = n / 64; i--;) { \
   137         _mm_stream_pi((__m64 *)(p+0), c64); \
   138         _mm_stream_pi((__m64 *)(p+8), c64); \
   139         _mm_stream_pi((__m64 *)(p+16), c64); \
   140         _mm_stream_pi((__m64 *)(p+24), c64); \
   141         _mm_stream_pi((__m64 *)(p+32), c64); \
   142         _mm_stream_pi((__m64 *)(p+40), c64); \
   143         _mm_stream_pi((__m64 *)(p+48), c64); \
   144         _mm_stream_pi((__m64 *)(p+56), c64); \
   145         p += 64; \
   146     }
   147 
   148 #define MMX_END \
   149     _mm_empty()
   150 
   151 #define DEFINE_MMX_FILLRECT(bpp, type) \
   152 static void \
   153 SDL_FillRect##bpp##MMX(Uint8 *pixels, int pitch, Uint32 color, int w, int h) \
   154 { \
   155     MMX_BEGIN; \
   156  \
   157     while (h--) { \
   158         int i, n = w * bpp; \
   159         Uint8 *p = pixels; \
   160  \
   161         if (n > 63) { \
   162             int adjust = 8 - ((uintptr_t)p & 7); \
   163             if (adjust < 8) { \
   164                 n -= adjust; \
   165                 adjust /= bpp; \
   166                 while (adjust--) { \
   167                     *((type *)p) = (type)color; \
   168                     p += bpp; \
   169                 } \
   170             } \
   171             MMX_WORK; \
   172         } \
   173         if (n & 63) { \
   174             int remainder = (n & 63); \
   175             remainder /= bpp; \
   176             while (remainder--) { \
   177                 *((type *)p) = (type)color; \
   178                 p += bpp; \
   179             } \
   180         } \
   181         pixels += pitch; \
   182     } \
   183  \
   184     MMX_END; \
   185 }
   186 
   187 static void
   188 SDL_FillRect1MMX(Uint8 *pixels, int pitch, Uint32 color, int w, int h)
   189 {
   190     MMX_BEGIN;
   191 
   192     while (h--) {
   193         int i, n = w;
   194         Uint8 *p = pixels;
   195 
   196         if (n > 63) {
   197             int adjust = 8 - ((uintptr_t)p & 7);
   198             if (adjust) {
   199                 n -= adjust;
   200                 SDL_memset(p, color, adjust);
   201                 p += adjust;
   202             }
   203             MMX_WORK;
   204         }
   205         if (n & 63) {
   206             int remainder = (n & 63);
   207             SDL_memset(p, color, remainder);
   208             p += remainder;
   209         }
   210         pixels += pitch;
   211     }
   212 
   213     MMX_END;
   214 }
   215 /*DEFINE_MMX_FILLRECT(1, Uint8)*/
   216 DEFINE_MMX_FILLRECT(2, Uint16)
   217 DEFINE_MMX_FILLRECT(4, Uint32)
   218 
   219 /* *INDENT-ON* */
   220 #endif /* __MMX__ */
   221 
   222 static void
   223 SDL_FillRect1(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
   224 {
   225     while (h--) {
   226         int n = w;
   227         Uint8 *p = pixels;
   228 
   229         if (n > 3) {
   230             switch ((uintptr_t) p & 3) {
   231             case 1:
   232                 *p++ = (Uint8) color;
   233                 --n;
   234             case 2:
   235                 *p++ = (Uint8) color;
   236                 --n;
   237             case 3:
   238                 *p++ = (Uint8) color;
   239                 --n;
   240             }
   241             SDL_memset4(p, color, (n >> 2));
   242         }
   243         if (n & 3) {
   244             p += (n & ~3);
   245             switch (n & 3) {
   246             case 3:
   247                 *p++ = (Uint8) color;
   248             case 2:
   249                 *p++ = (Uint8) color;
   250             case 1:
   251                 *p++ = (Uint8) color;
   252             }
   253         }
   254         pixels += pitch;
   255     }
   256 }
   257 
   258 static void
   259 SDL_FillRect2(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
   260 {
   261     while (h--) {
   262         int n = w;
   263         Uint16 *p = (Uint16 *) pixels;
   264 
   265         if (n > 1) {
   266             if ((uintptr_t) p & 2) {
   267                 *p++ = (Uint16) color;
   268                 --n;
   269             }
   270             SDL_memset4(p, color, (n >> 1));
   271         }
   272         if (n & 1) {
   273             p[n - 1] = (Uint16) color;
   274         }
   275         pixels += pitch;
   276     }
   277 }
   278 
   279 static void
   280 SDL_FillRect3(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
   281 {
   282     Uint8 r = (Uint8) ((color >> 16) & 0xFF);
   283     Uint8 g = (Uint8) ((color >> 8) & 0xFF);
   284     Uint8 b = (Uint8) (color & 0xFF);
   285 
   286     while (h--) {
   287         int n = w;
   288         Uint8 *p = pixels;
   289 
   290         while (n--) {
   291             *p++ = r;
   292             *p++ = g;
   293             *p++ = b;
   294         }
   295         pixels += pitch;
   296     }
   297 }
   298 
   299 static void
   300 SDL_FillRect4(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
   301 {
   302     while (h--) {
   303         SDL_memset4(pixels, color, w);
   304         pixels += pitch;
   305     }
   306 }
   307 
   308 /* 
   309  * This function performs a fast fill of the given rectangle with 'color'
   310  */
   311 int
   312 SDL_FillRect(SDL_Surface * dst, const SDL_Rect * rect, Uint32 color)
   313 {
   314     SDL_Rect clipped;
   315     Uint8 *pixels;
   316 
   317     if (!dst) {
   318         return SDL_SetError("Passed NULL destination surface");
   319     }
   320 
   321     /* This function doesn't work on surfaces < 8 bpp */
   322     if (dst->format->BitsPerPixel < 8) {
   323         return SDL_SetError("SDL_FillRect(): Unsupported surface format");
   324     }
   325 
   326     /* If 'rect' == NULL, then fill the whole surface */
   327     if (rect) {
   328         /* Perform clipping */
   329         if (!SDL_IntersectRect(rect, &dst->clip_rect, &clipped)) {
   330             return 0;
   331         }
   332         rect = &clipped;
   333     } else {
   334         rect = &dst->clip_rect;
   335     }
   336 
   337     /* Perform software fill */
   338     if (!dst->pixels) {
   339         return SDL_SetError("SDL_FillRect(): You must lock the surface");
   340     }
   341 
   342     pixels = (Uint8 *) dst->pixels + rect->y * dst->pitch +
   343                                      rect->x * dst->format->BytesPerPixel;
   344 
   345     switch (dst->format->BytesPerPixel) {
   346     case 1:
   347         {
   348             color |= (color << 8);
   349             color |= (color << 16);
   350 #ifdef __SSE__
   351             if (SDL_HasSSE()) {
   352                 SDL_FillRect1SSE(pixels, dst->pitch, color, rect->w, rect->h);
   353                 break;
   354             }
   355 #endif
   356 #ifdef __MMX__
   357             if (SDL_HasMMX()) {
   358                 SDL_FillRect1MMX(pixels, dst->pitch, color, rect->w, rect->h);
   359                 break;
   360             }
   361 #endif
   362             SDL_FillRect1(pixels, dst->pitch, color, rect->w, rect->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, rect->w, rect->h);
   372                 break;
   373             }
   374 #endif
   375 #ifdef __MMX__
   376             if (SDL_HasMMX()) {
   377                 SDL_FillRect2MMX(pixels, dst->pitch, color, rect->w, rect->h);
   378                 break;
   379             }
   380 #endif
   381             SDL_FillRect2(pixels, dst->pitch, color, rect->w, rect->h);
   382             break;
   383         }
   384 
   385     case 3:
   386         /* 24-bit RGB is a slow path, at least for now. */
   387         {
   388             SDL_FillRect3(pixels, dst->pitch, color, rect->w, rect->h);
   389             break;
   390         }
   391 
   392     case 4:
   393         {
   394 #ifdef __SSE__
   395             if (SDL_HasSSE()) {
   396                 SDL_FillRect4SSE(pixels, dst->pitch, color, rect->w, rect->h);
   397                 break;
   398             }
   399 #endif
   400 #ifdef __MMX__
   401             if (SDL_HasMMX()) {
   402                 SDL_FillRect4MMX(pixels, dst->pitch, color, rect->w, rect->h);
   403                 break;
   404             }
   405 #endif
   406             SDL_FillRect4(pixels, dst->pitch, color, rect->w, rect->h);
   407             break;
   408         }
   409     }
   410 
   411     /* We're done! */
   412     return 0;
   413 }
   414 
   415 int
   416 SDL_FillRects(SDL_Surface * dst, const SDL_Rect * rects, int count,
   417               Uint32 color)
   418 {
   419     int i;
   420     int status = 0;
   421 
   422     if (!rects) {
   423         return SDL_SetError("SDL_FillRects() passed NULL rects");
   424     }
   425 
   426     for (i = 0; i < count; ++i) {
   427         status += SDL_FillRect(dst, &rects[i], color);
   428     }
   429     return status;
   430 }
   431 
   432 /* vi: set ts=4 sw=4 expandtab: */