src/render/software/SDL_blendfillrect.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 02 Feb 2014 00:53:27 -0800
changeset 8149 681eb46b8ac4
parent 8093 b43765095a6f
child 9619 b94b6d0bff0f
permissions -rw-r--r--
Fixed bug 2374 - Update copyright for 2014...

Is it that time already??
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2014 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_internal.h"
    22 
    23 #if !SDL_RENDER_DISABLED
    24 
    25 #include "SDL_draw.h"
    26 #include "SDL_blendfillrect.h"
    27 
    28 
    29 static int
    30 SDL_BlendFillRect_RGB555(SDL_Surface * dst, const SDL_Rect * rect,
    31                          SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    32 {
    33     unsigned inva = 0xff - a;
    34 
    35     switch (blendMode) {
    36     case SDL_BLENDMODE_BLEND:
    37         FILLRECT(Uint16, DRAW_SETPIXEL_BLEND_RGB555);
    38         break;
    39     case SDL_BLENDMODE_ADD:
    40         FILLRECT(Uint16, DRAW_SETPIXEL_ADD_RGB555);
    41         break;
    42     case SDL_BLENDMODE_MOD:
    43         FILLRECT(Uint16, DRAW_SETPIXEL_MOD_RGB555);
    44         break;
    45     default:
    46         FILLRECT(Uint16, DRAW_SETPIXEL_RGB555);
    47         break;
    48     }
    49     return 0;
    50 }
    51 
    52 static int
    53 SDL_BlendFillRect_RGB565(SDL_Surface * dst, const SDL_Rect * rect,
    54                          SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    55 {
    56     unsigned inva = 0xff - a;
    57 
    58     switch (blendMode) {
    59     case SDL_BLENDMODE_BLEND:
    60         FILLRECT(Uint16, DRAW_SETPIXEL_BLEND_RGB565);
    61         break;
    62     case SDL_BLENDMODE_ADD:
    63         FILLRECT(Uint16, DRAW_SETPIXEL_ADD_RGB565);
    64         break;
    65     case SDL_BLENDMODE_MOD:
    66         FILLRECT(Uint16, DRAW_SETPIXEL_MOD_RGB565);
    67         break;
    68     default:
    69         FILLRECT(Uint16, DRAW_SETPIXEL_RGB565);
    70         break;
    71     }
    72     return 0;
    73 }
    74 
    75 static int
    76 SDL_BlendFillRect_RGB888(SDL_Surface * dst, const SDL_Rect * rect,
    77                          SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    78 {
    79     unsigned inva = 0xff - a;
    80 
    81     switch (blendMode) {
    82     case SDL_BLENDMODE_BLEND:
    83         FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_RGB888);
    84         break;
    85     case SDL_BLENDMODE_ADD:
    86         FILLRECT(Uint32, DRAW_SETPIXEL_ADD_RGB888);
    87         break;
    88     case SDL_BLENDMODE_MOD:
    89         FILLRECT(Uint32, DRAW_SETPIXEL_MOD_RGB888);
    90         break;
    91     default:
    92         FILLRECT(Uint32, DRAW_SETPIXEL_RGB888);
    93         break;
    94     }
    95     return 0;
    96 }
    97 
    98 static int
    99 SDL_BlendFillRect_ARGB8888(SDL_Surface * dst, const SDL_Rect * rect,
   100                            SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
   101 {
   102     unsigned inva = 0xff - a;
   103 
   104     switch (blendMode) {
   105     case SDL_BLENDMODE_BLEND:
   106         FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_ARGB8888);
   107         break;
   108     case SDL_BLENDMODE_ADD:
   109         FILLRECT(Uint32, DRAW_SETPIXEL_ADD_ARGB8888);
   110         break;
   111     case SDL_BLENDMODE_MOD:
   112         FILLRECT(Uint32, DRAW_SETPIXEL_MOD_ARGB8888);
   113         break;
   114     default:
   115         FILLRECT(Uint32, DRAW_SETPIXEL_ARGB8888);
   116         break;
   117     }
   118     return 0;
   119 }
   120 
   121 static int
   122 SDL_BlendFillRect_RGB(SDL_Surface * dst, const SDL_Rect * rect,
   123                       SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
   124 {
   125     SDL_PixelFormat *fmt = dst->format;
   126     unsigned inva = 0xff - a;
   127 
   128     switch (fmt->BytesPerPixel) {
   129     case 2:
   130         switch (blendMode) {
   131         case SDL_BLENDMODE_BLEND:
   132             FILLRECT(Uint16, DRAW_SETPIXEL_BLEND_RGB);
   133             break;
   134         case SDL_BLENDMODE_ADD:
   135             FILLRECT(Uint16, DRAW_SETPIXEL_ADD_RGB);
   136             break;
   137         case SDL_BLENDMODE_MOD:
   138             FILLRECT(Uint16, DRAW_SETPIXEL_MOD_RGB);
   139             break;
   140         default:
   141             FILLRECT(Uint16, DRAW_SETPIXEL_RGB);
   142             break;
   143         }
   144         return 0;
   145     case 4:
   146         switch (blendMode) {
   147         case SDL_BLENDMODE_BLEND:
   148             FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_RGB);
   149             break;
   150         case SDL_BLENDMODE_ADD:
   151             FILLRECT(Uint32, DRAW_SETPIXEL_ADD_RGB);
   152             break;
   153         case SDL_BLENDMODE_MOD:
   154             FILLRECT(Uint32, DRAW_SETPIXEL_MOD_RGB);
   155             break;
   156         default:
   157             FILLRECT(Uint32, DRAW_SETPIXEL_RGB);
   158             break;
   159         }
   160         return 0;
   161     default:
   162         return SDL_Unsupported();
   163     }
   164 }
   165 
   166 static int
   167 SDL_BlendFillRect_RGBA(SDL_Surface * dst, const SDL_Rect * rect,
   168                        SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
   169 {
   170     SDL_PixelFormat *fmt = dst->format;
   171     unsigned inva = 0xff - a;
   172 
   173     switch (fmt->BytesPerPixel) {
   174     case 4:
   175         switch (blendMode) {
   176         case SDL_BLENDMODE_BLEND:
   177             FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_RGBA);
   178             break;
   179         case SDL_BLENDMODE_ADD:
   180             FILLRECT(Uint32, DRAW_SETPIXEL_ADD_RGBA);
   181             break;
   182         case SDL_BLENDMODE_MOD:
   183             FILLRECT(Uint32, DRAW_SETPIXEL_MOD_RGBA);
   184             break;
   185         default:
   186             FILLRECT(Uint32, DRAW_SETPIXEL_RGBA);
   187             break;
   188         }
   189         return 0;
   190     default:
   191         return SDL_Unsupported();
   192     }
   193 }
   194 
   195 int
   196 SDL_BlendFillRect(SDL_Surface * dst, const SDL_Rect * rect,
   197                   SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
   198 {
   199     SDL_Rect clipped;
   200 
   201     if (!dst) {
   202         return SDL_SetError("Passed NULL destination surface");
   203     }
   204 
   205     /* This function doesn't work on surfaces < 8 bpp */
   206     if (dst->format->BitsPerPixel < 8) {
   207         return SDL_SetError("SDL_BlendFillRect(): Unsupported surface format");
   208     }
   209 
   210     /* If 'rect' == NULL, then fill the whole surface */
   211     if (rect) {
   212         /* Perform clipping */
   213         if (!SDL_IntersectRect(rect, &dst->clip_rect, &clipped)) {
   214             return 0;
   215         }
   216         rect = &clipped;
   217     } else {
   218         rect = &dst->clip_rect;
   219     }
   220 
   221     if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) {
   222         r = DRAW_MUL(r, a);
   223         g = DRAW_MUL(g, a);
   224         b = DRAW_MUL(b, a);
   225     }
   226 
   227     switch (dst->format->BitsPerPixel) {
   228     case 15:
   229         switch (dst->format->Rmask) {
   230         case 0x7C00:
   231             return SDL_BlendFillRect_RGB555(dst, rect, blendMode, r, g, b, a);
   232         }
   233         break;
   234     case 16:
   235         switch (dst->format->Rmask) {
   236         case 0xF800:
   237             return SDL_BlendFillRect_RGB565(dst, rect, blendMode, r, g, b, a);
   238         }
   239         break;
   240     case 32:
   241         switch (dst->format->Rmask) {
   242         case 0x00FF0000:
   243             if (!dst->format->Amask) {
   244                 return SDL_BlendFillRect_RGB888(dst, rect, blendMode, r, g, b, a);
   245             } else {
   246                 return SDL_BlendFillRect_ARGB8888(dst, rect, blendMode, r, g, b, a);
   247             }
   248             break;
   249         }
   250         break;
   251     default:
   252         break;
   253     }
   254 
   255     if (!dst->format->Amask) {
   256         return SDL_BlendFillRect_RGB(dst, rect, blendMode, r, g, b, a);
   257     } else {
   258         return SDL_BlendFillRect_RGBA(dst, rect, blendMode, r, g, b, a);
   259     }
   260 }
   261 
   262 int
   263 SDL_BlendFillRects(SDL_Surface * dst, const SDL_Rect * rects, int count,
   264                    SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
   265 {
   266     SDL_Rect rect;
   267     int i;
   268     int (*func)(SDL_Surface * dst, const SDL_Rect * rect,
   269                 SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) = NULL;
   270     int status = 0;
   271 
   272     if (!dst) {
   273         return SDL_SetError("Passed NULL destination surface");
   274     }
   275 
   276     /* This function doesn't work on surfaces < 8 bpp */
   277     if (dst->format->BitsPerPixel < 8) {
   278         return SDL_SetError("SDL_BlendFillRects(): Unsupported surface format");
   279     }
   280 
   281     if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) {
   282         r = DRAW_MUL(r, a);
   283         g = DRAW_MUL(g, a);
   284         b = DRAW_MUL(b, a);
   285     }
   286 
   287     /* FIXME: Does this function pointer slow things down significantly? */
   288     switch (dst->format->BitsPerPixel) {
   289     case 15:
   290         switch (dst->format->Rmask) {
   291         case 0x7C00:
   292             func = SDL_BlendFillRect_RGB555;
   293         }
   294         break;
   295     case 16:
   296         switch (dst->format->Rmask) {
   297         case 0xF800:
   298             func = SDL_BlendFillRect_RGB565;
   299         }
   300         break;
   301     case 32:
   302         switch (dst->format->Rmask) {
   303         case 0x00FF0000:
   304             if (!dst->format->Amask) {
   305                 func = SDL_BlendFillRect_RGB888;
   306             } else {
   307                 func = SDL_BlendFillRect_ARGB8888;
   308             }
   309             break;
   310         }
   311         break;
   312     default:
   313         break;
   314     }
   315 
   316     if (!func) {
   317         if (!dst->format->Amask) {
   318             func = SDL_BlendFillRect_RGB;
   319         } else {
   320             func = SDL_BlendFillRect_RGBA;
   321         }
   322     }
   323 
   324     for (i = 0; i < count; ++i) {
   325         /* Perform clipping */
   326         if (!SDL_IntersectRect(&rects[i], &dst->clip_rect, &rect)) {
   327             continue;
   328         }
   329         status = func(dst, &rect, blendMode, r, g, b, a);
   330     }
   331     return status;
   332 }
   333 
   334 #endif /* !SDL_RENDER_DISABLED */
   335 
   336 /* vi: set ts=4 sw=4 expandtab: */