SDL_blendpoint.c (9278B)
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_blendpoint.h" 27 28 29static int 30SDL_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 52static int 53SDL_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 75static int 76SDL_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 98static int 99SDL_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 121static int 122SDL_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 166static int 167SDL_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 195int 196SDL_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, 239 a); 240 } else { 241 return SDL_BlendPoint_ARGB8888(dst, x, y, blendMode, r, g, b, 242 a); 243 } 244 break; 245 } 246 break; 247 default: 248 break; 249 } 250 251 if (!dst->format->Amask) { 252 return SDL_BlendPoint_RGB(dst, x, y, blendMode, r, g, b, a); 253 } else { 254 return SDL_BlendPoint_RGBA(dst, x, y, blendMode, r, g, b, a); 255 } 256} 257 258int 259SDL_BlendPoints(SDL_Surface * dst, const SDL_Point * points, int count, 260 SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 261{ 262 int minx, miny; 263 int maxx, maxy; 264 int i; 265 int x, y; 266 int (*func)(SDL_Surface * dst, int x, int y, 267 SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) = NULL; 268 int status = 0; 269 270 if (!dst) { 271 return SDL_SetError("Passed NULL destination surface"); 272 } 273 274 /* This function doesn't work on surfaces < 8 bpp */ 275 if (dst->format->BitsPerPixel < 8) { 276 return SDL_SetError("SDL_BlendPoints(): Unsupported surface format"); 277 } 278 279 if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) { 280 r = DRAW_MUL(r, a); 281 g = DRAW_MUL(g, a); 282 b = DRAW_MUL(b, a); 283 } 284 285 /* FIXME: Does this function pointer slow things down significantly? */ 286 switch (dst->format->BitsPerPixel) { 287 case 15: 288 switch (dst->format->Rmask) { 289 case 0x7C00: 290 func = SDL_BlendPoint_RGB555; 291 break; 292 } 293 break; 294 case 16: 295 switch (dst->format->Rmask) { 296 case 0xF800: 297 func = SDL_BlendPoint_RGB565; 298 break; 299 } 300 break; 301 case 32: 302 switch (dst->format->Rmask) { 303 case 0x00FF0000: 304 if (!dst->format->Amask) { 305 func = SDL_BlendPoint_RGB888; 306 } else { 307 func = SDL_BlendPoint_ARGB8888; 308 } 309 break; 310 } 311 break; 312 default: 313 break; 314 } 315 316 if (!func) { 317 if (!dst->format->Amask) { 318 func = SDL_BlendPoint_RGB; 319 } else { 320 func = SDL_BlendPoint_RGBA; 321 } 322 } 323 324 minx = dst->clip_rect.x; 325 maxx = dst->clip_rect.x + dst->clip_rect.w - 1; 326 miny = dst->clip_rect.y; 327 maxy = dst->clip_rect.y + dst->clip_rect.h - 1; 328 329 for (i = 0; i < count; ++i) { 330 x = points[i].x; 331 y = points[i].y; 332 333 if (x < minx || x > maxx || y < miny || y > maxy) { 334 continue; 335 } 336 status = func(dst, x, y, blendMode, r, g, b, a); 337 } 338 return status; 339} 340 341#endif /* !SDL_RENDER_DISABLED */ 342 343/* vi: set ts=4 sw=4 expandtab: */