SDL_blendfillrect.c (9458B)
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 29static int 30SDL_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 52static int 53SDL_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 75static int 76SDL_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 98static int 99SDL_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 121static int 122SDL_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 166static int 167SDL_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 195int 196SDL_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 262int 263SDL_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: */