src/video/SDL_blendpoint.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 15 Dec 2009 08:11:06 +0000
changeset 3565 f43c8f688f77
parent 3536 0267b8b1595c
child 3697 f7b03b6838cb
permissions -rw-r--r--
Fixed bug #906

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