src/render/software/SDL_blendpoint.c
author Ryan C. Gordon
Mon, 23 Jan 2017 12:06:10 -0500
changeset 10837 c2f241c2f6ad
parent 10737 3406a0f8b041
child 11811 5d94cb6b24d3
permissions -rw-r--r--
audio: Fix same bug as last commit, but for _mm_bslli_si128 vs _mm_slli_si128.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2017 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_blendpoint.h"
    27 
    28 
    29 static int
    30 SDL_BlendPoint_RGB555(SDL_Surface * dst, int x, int y, SDL_BlendMode blendMode, Uint8 r,
    31                       Uint8 g, Uint8 b, Uint8 a)
    32 {
    33     unsigned inva = 0xff - a;
    34 
    35     switch (blendMode) {
    36     case SDL_BLENDMODE_BLEND:
    37         DRAW_SETPIXELXY_BLEND_RGB555(x, y);
    38         break;
    39     case SDL_BLENDMODE_ADD:
    40         DRAW_SETPIXELXY_ADD_RGB555(x, y);
    41         break;
    42     case SDL_BLENDMODE_MOD:
    43         DRAW_SETPIXELXY_MOD_RGB555(x, y);
    44         break;
    45     default:
    46         DRAW_SETPIXELXY_RGB555(x, y);
    47         break;
    48     }
    49     return 0;
    50 }
    51 
    52 static int
    53 SDL_BlendPoint_RGB565(SDL_Surface * dst, int x, int y, SDL_BlendMode blendMode, Uint8 r,
    54                       Uint8 g, Uint8 b, Uint8 a)
    55 {
    56     unsigned inva = 0xff - a;
    57 
    58     switch (blendMode) {
    59     case SDL_BLENDMODE_BLEND:
    60         DRAW_SETPIXELXY_BLEND_RGB565(x, y);
    61         break;
    62     case SDL_BLENDMODE_ADD:
    63         DRAW_SETPIXELXY_ADD_RGB565(x, y);
    64         break;
    65     case SDL_BLENDMODE_MOD:
    66         DRAW_SETPIXELXY_MOD_RGB565(x, y);
    67         break;
    68     default:
    69         DRAW_SETPIXELXY_RGB565(x, y);
    70         break;
    71     }
    72     return 0;
    73 }
    74 
    75 static int
    76 SDL_BlendPoint_RGB888(SDL_Surface * dst, int x, int y, SDL_BlendMode blendMode, Uint8 r,
    77                       Uint8 g, Uint8 b, Uint8 a)
    78 {
    79     unsigned inva = 0xff - a;
    80 
    81     switch (blendMode) {
    82     case SDL_BLENDMODE_BLEND:
    83         DRAW_SETPIXELXY_BLEND_RGB888(x, y);
    84         break;
    85     case SDL_BLENDMODE_ADD:
    86         DRAW_SETPIXELXY_ADD_RGB888(x, y);
    87         break;
    88     case SDL_BLENDMODE_MOD:
    89         DRAW_SETPIXELXY_MOD_RGB888(x, y);
    90         break;
    91     default:
    92         DRAW_SETPIXELXY_RGB888(x, y);
    93         break;
    94     }
    95     return 0;
    96 }
    97 
    98 static int
    99 SDL_BlendPoint_ARGB8888(SDL_Surface * dst, int x, int y, SDL_BlendMode blendMode,
   100                         Uint8 r, Uint8 g, Uint8 b, Uint8 a)
   101 {
   102     unsigned inva = 0xff - a;
   103 
   104     switch (blendMode) {
   105     case SDL_BLENDMODE_BLEND:
   106         DRAW_SETPIXELXY_BLEND_ARGB8888(x, y);
   107         break;
   108     case SDL_BLENDMODE_ADD:
   109         DRAW_SETPIXELXY_ADD_ARGB8888(x, y);
   110         break;
   111     case SDL_BLENDMODE_MOD:
   112         DRAW_SETPIXELXY_MOD_ARGB8888(x, y);
   113         break;
   114     default:
   115         DRAW_SETPIXELXY_ARGB8888(x, y);
   116         break;
   117     }
   118     return 0;
   119 }
   120 
   121 static int
   122 SDL_BlendPoint_RGB(SDL_Surface * dst, int x, int y, SDL_BlendMode blendMode, Uint8 r,
   123                    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             DRAW_SETPIXELXY2_BLEND_RGB(x, y);
   133             break;
   134         case SDL_BLENDMODE_ADD:
   135             DRAW_SETPIXELXY2_ADD_RGB(x, y);
   136             break;
   137         case SDL_BLENDMODE_MOD:
   138             DRAW_SETPIXELXY2_MOD_RGB(x, y);
   139             break;
   140         default:
   141             DRAW_SETPIXELXY2_RGB(x, y);
   142             break;
   143         }
   144         return 0;
   145     case 4:
   146         switch (blendMode) {
   147         case SDL_BLENDMODE_BLEND:
   148             DRAW_SETPIXELXY4_BLEND_RGB(x, y);
   149             break;
   150         case SDL_BLENDMODE_ADD:
   151             DRAW_SETPIXELXY4_ADD_RGB(x, y);
   152             break;
   153         case SDL_BLENDMODE_MOD:
   154             DRAW_SETPIXELXY4_MOD_RGB(x, y);
   155             break;
   156         default:
   157             DRAW_SETPIXELXY4_RGB(x, y);
   158             break;
   159         }
   160         return 0;
   161     default:
   162         return SDL_Unsupported();
   163     }
   164 }
   165 
   166 static int
   167 SDL_BlendPoint_RGBA(SDL_Surface * dst, int x, int y, SDL_BlendMode blendMode, Uint8 r,
   168                     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             DRAW_SETPIXELXY4_BLEND_RGBA(x, y);
   178             break;
   179         case SDL_BLENDMODE_ADD:
   180             DRAW_SETPIXELXY4_ADD_RGBA(x, y);
   181             break;
   182         case SDL_BLENDMODE_MOD:
   183             DRAW_SETPIXELXY4_MOD_RGBA(x, y);
   184             break;
   185         default:
   186             DRAW_SETPIXELXY4_RGBA(x, y);
   187             break;
   188         }
   189         return 0;
   190     default:
   191         return SDL_Unsupported();
   192     }
   193 }
   194 
   195 int
   196 SDL_BlendPoint(SDL_Surface * dst, int x, int y, SDL_BlendMode blendMode, Uint8 r,
   197                Uint8 g, Uint8 b, Uint8 a)
   198 {
   199     if (!dst) {
   200         return SDL_SetError("Passed NULL destination surface");
   201     }
   202 
   203     /* This function doesn't work on surfaces < 8 bpp */
   204     if (dst->format->BitsPerPixel < 8) {
   205         return SDL_SetError("SDL_BlendPoint(): Unsupported surface format");
   206     }
   207 
   208     /* Perform clipping */
   209     if (x < dst->clip_rect.x || y < dst->clip_rect.y ||
   210         x >= (dst->clip_rect.x + dst->clip_rect.w) ||
   211         y >= (dst->clip_rect.y + dst->clip_rect.h)) {
   212         return 0;
   213     }
   214 
   215     if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) {
   216         r = DRAW_MUL(r, a);
   217         g = DRAW_MUL(g, a);
   218         b = DRAW_MUL(b, a);
   219     }
   220 
   221     switch (dst->format->BitsPerPixel) {
   222     case 15:
   223         switch (dst->format->Rmask) {
   224         case 0x7C00:
   225             return SDL_BlendPoint_RGB555(dst, x, y, blendMode, r, g, b, a);
   226         }
   227         break;
   228     case 16:
   229         switch (dst->format->Rmask) {
   230         case 0xF800:
   231             return SDL_BlendPoint_RGB565(dst, x, y, blendMode, r, g, b, a);
   232         }
   233         break;
   234     case 32:
   235         switch (dst->format->Rmask) {
   236         case 0x00FF0000:
   237             if (!dst->format->Amask) {
   238                 return SDL_BlendPoint_RGB888(dst, x, y, blendMode, r, g, b, a);
   239             } else {
   240                 return SDL_BlendPoint_ARGB8888(dst, x, y, blendMode, r, g, b, a);
   241             }
   242             /* break; -Wunreachable-code-break */
   243         }
   244         break;
   245     default:
   246         break;
   247     }
   248 
   249     if (!dst->format->Amask) {
   250         return SDL_BlendPoint_RGB(dst, x, y, blendMode, r, g, b, a);
   251     } else {
   252         return SDL_BlendPoint_RGBA(dst, x, y, blendMode, r, g, b, a);
   253     }
   254 }
   255 
   256 int
   257 SDL_BlendPoints(SDL_Surface * dst, const SDL_Point * points, int count,
   258                 SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
   259 {
   260     int minx, miny;
   261     int maxx, maxy;
   262     int i;
   263     int x, y;
   264     int (*func)(SDL_Surface * dst, int x, int y,
   265                 SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) = NULL;
   266     int status = 0;
   267 
   268     if (!dst) {
   269         return SDL_SetError("Passed NULL destination surface");
   270     }
   271 
   272     /* This function doesn't work on surfaces < 8 bpp */
   273     if (dst->format->BitsPerPixel < 8) {
   274         return SDL_SetError("SDL_BlendPoints(): Unsupported surface format");
   275     }
   276 
   277     if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) {
   278         r = DRAW_MUL(r, a);
   279         g = DRAW_MUL(g, a);
   280         b = DRAW_MUL(b, a);
   281     }
   282 
   283     /* FIXME: Does this function pointer slow things down significantly? */
   284     switch (dst->format->BitsPerPixel) {
   285     case 15:
   286         switch (dst->format->Rmask) {
   287         case 0x7C00:
   288             func = SDL_BlendPoint_RGB555;
   289             break;
   290         }
   291         break;
   292     case 16:
   293         switch (dst->format->Rmask) {
   294         case 0xF800:
   295             func = SDL_BlendPoint_RGB565;
   296             break;
   297         }
   298         break;
   299     case 32:
   300         switch (dst->format->Rmask) {
   301         case 0x00FF0000:
   302             if (!dst->format->Amask) {
   303                 func = SDL_BlendPoint_RGB888;
   304             } else {
   305                 func = SDL_BlendPoint_ARGB8888;
   306             }
   307             break;
   308         }
   309         break;
   310     default:
   311         break;
   312     }
   313 
   314     if (!func) {
   315         if (!dst->format->Amask) {
   316             func = SDL_BlendPoint_RGB;
   317         } else {
   318             func = SDL_BlendPoint_RGBA;
   319         }
   320     }
   321 
   322     minx = dst->clip_rect.x;
   323     maxx = dst->clip_rect.x + dst->clip_rect.w - 1;
   324     miny = dst->clip_rect.y;
   325     maxy = dst->clip_rect.y + dst->clip_rect.h - 1;
   326 
   327     for (i = 0; i < count; ++i) {
   328         x = points[i].x;
   329         y = points[i].y;
   330 
   331         if (x < minx || x > maxx || y < miny || y > maxy) {
   332             continue;
   333         }
   334         status = func(dst, x, y, blendMode, r, g, b, a);
   335     }
   336     return status;
   337 }
   338 
   339 #endif /* !SDL_RENDER_DISABLED */
   340 
   341 /* vi: set ts=4 sw=4 expandtab: */