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