diff options
Diffstat (limited to 'contrib/SDL-3.2.8/src/render/software')
17 files changed, 5771 insertions, 0 deletions
diff --git a/contrib/SDL-3.2.8/src/render/software/SDL_blendfillrect.c b/contrib/SDL-3.2.8/src/render/software/SDL_blendfillrect.c new file mode 100644 index 0000000..4e5c7f8 --- /dev/null +++ b/contrib/SDL-3.2.8/src/render/software/SDL_blendfillrect.c | |||
| @@ -0,0 +1,371 @@ | |||
| 1 | /* | ||
| 2 | Simple DirectMedia Layer | ||
| 3 | Copyright (C) 1997-2025 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 | #ifdef SDL_VIDEO_RENDER_SW | ||
| 24 | |||
| 25 | #include "SDL_draw.h" | ||
| 26 | #include "SDL_blendfillrect.h" | ||
| 27 | |||
| 28 | static bool SDL_BlendFillRect_RGB555(SDL_Surface *dst, const SDL_Rect *rect, | ||
| 29 | SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) | ||
| 30 | { | ||
| 31 | unsigned inva = 0xff - a; | ||
| 32 | |||
| 33 | switch (blendMode) { | ||
| 34 | case SDL_BLENDMODE_BLEND: | ||
| 35 | FILLRECT(Uint16, DRAW_SETPIXEL_BLEND_RGB555); | ||
| 36 | break; | ||
| 37 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 38 | FILLRECT(Uint16, DRAW_SETPIXEL_BLEND_CLAMPED_RGB555); | ||
| 39 | break; | ||
| 40 | case SDL_BLENDMODE_ADD: | ||
| 41 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 42 | FILLRECT(Uint16, DRAW_SETPIXEL_ADD_RGB555); | ||
| 43 | break; | ||
| 44 | case SDL_BLENDMODE_MOD: | ||
| 45 | FILLRECT(Uint16, DRAW_SETPIXEL_MOD_RGB555); | ||
| 46 | break; | ||
| 47 | case SDL_BLENDMODE_MUL: | ||
| 48 | FILLRECT(Uint16, DRAW_SETPIXEL_MUL_RGB555); | ||
| 49 | break; | ||
| 50 | default: | ||
| 51 | FILLRECT(Uint16, DRAW_SETPIXEL_RGB555); | ||
| 52 | break; | ||
| 53 | } | ||
| 54 | return true; | ||
| 55 | } | ||
| 56 | |||
| 57 | static bool SDL_BlendFillRect_RGB565(SDL_Surface *dst, const SDL_Rect *rect, | ||
| 58 | SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) | ||
| 59 | { | ||
| 60 | unsigned inva = 0xff - a; | ||
| 61 | |||
| 62 | switch (blendMode) { | ||
| 63 | case SDL_BLENDMODE_BLEND: | ||
| 64 | FILLRECT(Uint16, DRAW_SETPIXEL_BLEND_RGB565); | ||
| 65 | break; | ||
| 66 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 67 | FILLRECT(Uint16, DRAW_SETPIXEL_BLEND_CLAMPED_RGB565); | ||
| 68 | break; | ||
| 69 | case SDL_BLENDMODE_ADD: | ||
| 70 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 71 | FILLRECT(Uint16, DRAW_SETPIXEL_ADD_RGB565); | ||
| 72 | break; | ||
| 73 | case SDL_BLENDMODE_MOD: | ||
| 74 | FILLRECT(Uint16, DRAW_SETPIXEL_MOD_RGB565); | ||
| 75 | break; | ||
| 76 | case SDL_BLENDMODE_MUL: | ||
| 77 | FILLRECT(Uint16, DRAW_SETPIXEL_MUL_RGB565); | ||
| 78 | break; | ||
| 79 | default: | ||
| 80 | FILLRECT(Uint16, DRAW_SETPIXEL_RGB565); | ||
| 81 | break; | ||
| 82 | } | ||
| 83 | return true; | ||
| 84 | } | ||
| 85 | |||
| 86 | static bool SDL_BlendFillRect_XRGB8888(SDL_Surface *dst, const SDL_Rect *rect, | ||
| 87 | SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) | ||
| 88 | { | ||
| 89 | unsigned inva = 0xff - a; | ||
| 90 | |||
| 91 | switch (blendMode) { | ||
| 92 | case SDL_BLENDMODE_BLEND: | ||
| 93 | FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_XRGB8888); | ||
| 94 | break; | ||
| 95 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 96 | FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_CLAMPED_XRGB8888); | ||
| 97 | break; | ||
| 98 | case SDL_BLENDMODE_ADD: | ||
| 99 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 100 | FILLRECT(Uint32, DRAW_SETPIXEL_ADD_XRGB8888); | ||
| 101 | break; | ||
| 102 | case SDL_BLENDMODE_MOD: | ||
| 103 | FILLRECT(Uint32, DRAW_SETPIXEL_MOD_XRGB8888); | ||
| 104 | break; | ||
| 105 | case SDL_BLENDMODE_MUL: | ||
| 106 | FILLRECT(Uint32, DRAW_SETPIXEL_MUL_XRGB8888); | ||
| 107 | break; | ||
| 108 | default: | ||
| 109 | FILLRECT(Uint32, DRAW_SETPIXEL_XRGB8888); | ||
| 110 | break; | ||
| 111 | } | ||
| 112 | return true; | ||
| 113 | } | ||
| 114 | |||
| 115 | static bool SDL_BlendFillRect_ARGB8888(SDL_Surface *dst, const SDL_Rect *rect, | ||
| 116 | SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) | ||
| 117 | { | ||
| 118 | unsigned inva = 0xff - a; | ||
| 119 | |||
| 120 | switch (blendMode) { | ||
| 121 | case SDL_BLENDMODE_BLEND: | ||
| 122 | FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_ARGB8888); | ||
| 123 | break; | ||
| 124 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 125 | FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_CLAMPED_ARGB8888); | ||
| 126 | break; | ||
| 127 | case SDL_BLENDMODE_ADD: | ||
| 128 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 129 | FILLRECT(Uint32, DRAW_SETPIXEL_ADD_ARGB8888); | ||
| 130 | break; | ||
| 131 | case SDL_BLENDMODE_MOD: | ||
| 132 | FILLRECT(Uint32, DRAW_SETPIXEL_MOD_ARGB8888); | ||
| 133 | break; | ||
| 134 | case SDL_BLENDMODE_MUL: | ||
| 135 | FILLRECT(Uint32, DRAW_SETPIXEL_MUL_ARGB8888); | ||
| 136 | break; | ||
| 137 | default: | ||
| 138 | FILLRECT(Uint32, DRAW_SETPIXEL_ARGB8888); | ||
| 139 | break; | ||
| 140 | } | ||
| 141 | return true; | ||
| 142 | } | ||
| 143 | |||
| 144 | static bool SDL_BlendFillRect_RGB(SDL_Surface *dst, const SDL_Rect *rect, | ||
| 145 | SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) | ||
| 146 | { | ||
| 147 | const SDL_PixelFormatDetails *fmt = dst->fmt; | ||
| 148 | unsigned inva = 0xff - a; | ||
| 149 | |||
| 150 | switch (fmt->bytes_per_pixel) { | ||
| 151 | case 2: | ||
| 152 | switch (blendMode) { | ||
| 153 | case SDL_BLENDMODE_BLEND: | ||
| 154 | FILLRECT(Uint16, DRAW_SETPIXEL_BLEND_RGB); | ||
| 155 | break; | ||
| 156 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 157 | FILLRECT(Uint16, DRAW_SETPIXEL_BLEND_CLAMPED_RGB); | ||
| 158 | break; | ||
| 159 | case SDL_BLENDMODE_ADD: | ||
| 160 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 161 | FILLRECT(Uint16, DRAW_SETPIXEL_ADD_RGB); | ||
| 162 | break; | ||
| 163 | case SDL_BLENDMODE_MOD: | ||
| 164 | FILLRECT(Uint16, DRAW_SETPIXEL_MOD_RGB); | ||
| 165 | break; | ||
| 166 | case SDL_BLENDMODE_MUL: | ||
| 167 | FILLRECT(Uint16, DRAW_SETPIXEL_MUL_RGB); | ||
| 168 | break; | ||
| 169 | default: | ||
| 170 | FILLRECT(Uint16, DRAW_SETPIXEL_RGB); | ||
| 171 | break; | ||
| 172 | } | ||
| 173 | return true; | ||
| 174 | case 4: | ||
| 175 | switch (blendMode) { | ||
| 176 | case SDL_BLENDMODE_BLEND: | ||
| 177 | FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_RGB); | ||
| 178 | break; | ||
| 179 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 180 | FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_CLAMPED_RGB); | ||
| 181 | break; | ||
| 182 | case SDL_BLENDMODE_ADD: | ||
| 183 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 184 | FILLRECT(Uint32, DRAW_SETPIXEL_ADD_RGB); | ||
| 185 | break; | ||
| 186 | case SDL_BLENDMODE_MOD: | ||
| 187 | FILLRECT(Uint32, DRAW_SETPIXEL_MOD_RGB); | ||
| 188 | break; | ||
| 189 | case SDL_BLENDMODE_MUL: | ||
| 190 | FILLRECT(Uint32, DRAW_SETPIXEL_MUL_RGB); | ||
| 191 | break; | ||
| 192 | default: | ||
| 193 | FILLRECT(Uint32, DRAW_SETPIXEL_RGB); | ||
| 194 | break; | ||
| 195 | } | ||
| 196 | return true; | ||
| 197 | default: | ||
| 198 | return SDL_Unsupported(); | ||
| 199 | } | ||
| 200 | } | ||
| 201 | |||
| 202 | static bool SDL_BlendFillRect_RGBA(SDL_Surface *dst, const SDL_Rect *rect, | ||
| 203 | SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) | ||
| 204 | { | ||
| 205 | const SDL_PixelFormatDetails *fmt = dst->fmt; | ||
| 206 | unsigned inva = 0xff - a; | ||
| 207 | |||
| 208 | switch (fmt->bytes_per_pixel) { | ||
| 209 | case 4: | ||
| 210 | switch (blendMode) { | ||
| 211 | case SDL_BLENDMODE_BLEND: | ||
| 212 | FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_RGBA); | ||
| 213 | break; | ||
| 214 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 215 | FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_CLAMPED_RGBA); | ||
| 216 | break; | ||
| 217 | case SDL_BLENDMODE_ADD: | ||
| 218 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 219 | FILLRECT(Uint32, DRAW_SETPIXEL_ADD_RGBA); | ||
| 220 | break; | ||
| 221 | case SDL_BLENDMODE_MOD: | ||
| 222 | FILLRECT(Uint32, DRAW_SETPIXEL_MOD_RGBA); | ||
| 223 | break; | ||
| 224 | case SDL_BLENDMODE_MUL: | ||
| 225 | FILLRECT(Uint32, DRAW_SETPIXEL_MUL_RGBA); | ||
| 226 | break; | ||
| 227 | default: | ||
| 228 | FILLRECT(Uint32, DRAW_SETPIXEL_RGBA); | ||
| 229 | break; | ||
| 230 | } | ||
| 231 | return true; | ||
| 232 | default: | ||
| 233 | return SDL_Unsupported(); | ||
| 234 | } | ||
| 235 | } | ||
| 236 | |||
| 237 | bool SDL_BlendFillRect(SDL_Surface *dst, const SDL_Rect *rect, SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) | ||
| 238 | { | ||
| 239 | SDL_Rect clipped; | ||
| 240 | |||
| 241 | if (!SDL_SurfaceValid(dst)) { | ||
| 242 | return SDL_InvalidParamError("SDL_BlendFillRect(): dst"); | ||
| 243 | } | ||
| 244 | |||
| 245 | // This function doesn't work on surfaces < 8 bpp | ||
| 246 | if (SDL_BITSPERPIXEL(dst->format) < 8) { | ||
| 247 | return SDL_SetError("SDL_BlendFillRect(): Unsupported surface format"); | ||
| 248 | } | ||
| 249 | |||
| 250 | // If 'rect' == NULL, then fill the whole surface | ||
| 251 | if (rect) { | ||
| 252 | // Perform clipping | ||
| 253 | if (!SDL_GetRectIntersection(rect, &dst->clip_rect, &clipped)) { | ||
| 254 | return true; | ||
| 255 | } | ||
| 256 | rect = &clipped; | ||
| 257 | } else { | ||
| 258 | rect = &dst->clip_rect; | ||
| 259 | } | ||
| 260 | |||
| 261 | if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) { | ||
| 262 | r = DRAW_MUL(r, a); | ||
| 263 | g = DRAW_MUL(g, a); | ||
| 264 | b = DRAW_MUL(b, a); | ||
| 265 | } | ||
| 266 | |||
| 267 | switch (dst->fmt->bits_per_pixel) { | ||
| 268 | case 15: | ||
| 269 | switch (dst->fmt->Rmask) { | ||
| 270 | case 0x7C00: | ||
| 271 | return SDL_BlendFillRect_RGB555(dst, rect, blendMode, r, g, b, a); | ||
| 272 | } | ||
| 273 | break; | ||
| 274 | case 16: | ||
| 275 | switch (dst->fmt->Rmask) { | ||
| 276 | case 0xF800: | ||
| 277 | return SDL_BlendFillRect_RGB565(dst, rect, blendMode, r, g, b, a); | ||
| 278 | } | ||
| 279 | break; | ||
| 280 | case 32: | ||
| 281 | switch (dst->fmt->Rmask) { | ||
| 282 | case 0x00FF0000: | ||
| 283 | if (!dst->fmt->Amask) { | ||
| 284 | return SDL_BlendFillRect_XRGB8888(dst, rect, blendMode, r, g, b, a); | ||
| 285 | } else { | ||
| 286 | return SDL_BlendFillRect_ARGB8888(dst, rect, blendMode, r, g, b, a); | ||
| 287 | } | ||
| 288 | // break; -Wunreachable-code-break | ||
| 289 | } | ||
| 290 | break; | ||
| 291 | default: | ||
| 292 | break; | ||
| 293 | } | ||
| 294 | |||
| 295 | if (!dst->fmt->Amask) { | ||
| 296 | return SDL_BlendFillRect_RGB(dst, rect, blendMode, r, g, b, a); | ||
| 297 | } else { | ||
| 298 | return SDL_BlendFillRect_RGBA(dst, rect, blendMode, r, g, b, a); | ||
| 299 | } | ||
| 300 | } | ||
| 301 | |||
| 302 | bool SDL_BlendFillRects(SDL_Surface *dst, const SDL_Rect *rects, int count, SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) | ||
| 303 | { | ||
| 304 | SDL_Rect rect; | ||
| 305 | int i; | ||
| 306 | bool (*func)(SDL_Surface * dst, const SDL_Rect *rect, SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) = NULL; | ||
| 307 | bool result = true; | ||
| 308 | |||
| 309 | if (!SDL_SurfaceValid(dst)) { | ||
| 310 | return SDL_InvalidParamError("SDL_BlendFillRects(): dst"); | ||
| 311 | } | ||
| 312 | |||
| 313 | // This function doesn't work on surfaces < 8 bpp | ||
| 314 | if (dst->fmt->bits_per_pixel < 8) { | ||
| 315 | return SDL_SetError("SDL_BlendFillRects(): Unsupported surface format"); | ||
| 316 | } | ||
| 317 | |||
| 318 | if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) { | ||
| 319 | r = DRAW_MUL(r, a); | ||
| 320 | g = DRAW_MUL(g, a); | ||
| 321 | b = DRAW_MUL(b, a); | ||
| 322 | } | ||
| 323 | |||
| 324 | // FIXME: Does this function pointer slow things down significantly? | ||
| 325 | switch (dst->fmt->bits_per_pixel) { | ||
| 326 | case 15: | ||
| 327 | switch (dst->fmt->Rmask) { | ||
| 328 | case 0x7C00: | ||
| 329 | func = SDL_BlendFillRect_RGB555; | ||
| 330 | } | ||
| 331 | break; | ||
| 332 | case 16: | ||
| 333 | switch (dst->fmt->Rmask) { | ||
| 334 | case 0xF800: | ||
| 335 | func = SDL_BlendFillRect_RGB565; | ||
| 336 | } | ||
| 337 | break; | ||
| 338 | case 32: | ||
| 339 | switch (dst->fmt->Rmask) { | ||
| 340 | case 0x00FF0000: | ||
| 341 | if (!dst->fmt->Amask) { | ||
| 342 | func = SDL_BlendFillRect_XRGB8888; | ||
| 343 | } else { | ||
| 344 | func = SDL_BlendFillRect_ARGB8888; | ||
| 345 | } | ||
| 346 | break; | ||
| 347 | } | ||
| 348 | break; | ||
| 349 | default: | ||
| 350 | break; | ||
| 351 | } | ||
| 352 | |||
| 353 | if (!func) { | ||
| 354 | if (!dst->fmt->Amask) { | ||
| 355 | func = SDL_BlendFillRect_RGB; | ||
| 356 | } else { | ||
| 357 | func = SDL_BlendFillRect_RGBA; | ||
| 358 | } | ||
| 359 | } | ||
| 360 | |||
| 361 | for (i = 0; i < count; ++i) { | ||
| 362 | // Perform clipping | ||
| 363 | if (!SDL_GetRectIntersection(&rects[i], &dst->clip_rect, &rect)) { | ||
| 364 | continue; | ||
| 365 | } | ||
| 366 | result = func(dst, &rect, blendMode, r, g, b, a); | ||
| 367 | } | ||
| 368 | return result; | ||
| 369 | } | ||
| 370 | |||
| 371 | #endif // SDL_VIDEO_RENDER_SW | ||
diff --git a/contrib/SDL-3.2.8/src/render/software/SDL_blendfillrect.h b/contrib/SDL-3.2.8/src/render/software/SDL_blendfillrect.h new file mode 100644 index 0000000..c1ff439 --- /dev/null +++ b/contrib/SDL-3.2.8/src/render/software/SDL_blendfillrect.h | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | /* | ||
| 2 | Simple DirectMedia Layer | ||
| 3 | Copyright (C) 1997-2025 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 | |||
| 22 | #ifndef SDL_blendfillrect_h_ | ||
| 23 | #define SDL_blendfillrect_h_ | ||
| 24 | |||
| 25 | #include "SDL_internal.h" | ||
| 26 | |||
| 27 | extern bool SDL_BlendFillRect(SDL_Surface *dst, const SDL_Rect *rect, SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a); | ||
| 28 | extern bool SDL_BlendFillRects(SDL_Surface *dst, const SDL_Rect *rects, int count, SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a); | ||
| 29 | |||
| 30 | #endif // SDL_blendfillrect_h_ | ||
diff --git a/contrib/SDL-3.2.8/src/render/software/SDL_blendline.c b/contrib/SDL-3.2.8/src/render/software/SDL_blendline.c new file mode 100644 index 0000000..53be2f1 --- /dev/null +++ b/contrib/SDL-3.2.8/src/render/software/SDL_blendline.c | |||
| @@ -0,0 +1,986 @@ | |||
| 1 | /* | ||
| 2 | Simple DirectMedia Layer | ||
| 3 | Copyright (C) 1997-2025 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 | #ifdef SDL_VIDEO_RENDER_SW | ||
| 24 | |||
| 25 | #include "SDL_draw.h" | ||
| 26 | #include "SDL_blendline.h" | ||
| 27 | #include "SDL_blendpoint.h" | ||
| 28 | |||
| 29 | static void SDL_BlendLine_RGB2(SDL_Surface *dst, int x1, int y1, int x2, int y2, | ||
| 30 | SDL_BlendMode blendMode, Uint8 _r, Uint8 _g, Uint8 _b, Uint8 _a, | ||
| 31 | bool draw_end) | ||
| 32 | { | ||
| 33 | const SDL_PixelFormatDetails *fmt = dst->fmt; | ||
| 34 | unsigned r, g, b, a, inva; | ||
| 35 | |||
| 36 | if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) { | ||
| 37 | r = DRAW_MUL(_r, _a); | ||
| 38 | g = DRAW_MUL(_g, _a); | ||
| 39 | b = DRAW_MUL(_b, _a); | ||
| 40 | a = _a; | ||
| 41 | } else { | ||
| 42 | r = _r; | ||
| 43 | g = _g; | ||
| 44 | b = _b; | ||
| 45 | a = _a; | ||
| 46 | } | ||
| 47 | inva = (a ^ 0xff); | ||
| 48 | |||
| 49 | if (y1 == y2) { | ||
| 50 | switch (blendMode) { | ||
| 51 | case SDL_BLENDMODE_BLEND: | ||
| 52 | HLINE(Uint16, DRAW_SETPIXEL_BLEND_RGB, draw_end); | ||
| 53 | break; | ||
| 54 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 55 | HLINE(Uint16, DRAW_SETPIXEL_BLEND_CLAMPED_RGB, draw_end); | ||
| 56 | break; | ||
| 57 | case SDL_BLENDMODE_ADD: | ||
| 58 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 59 | HLINE(Uint16, DRAW_SETPIXEL_ADD_RGB, draw_end); | ||
| 60 | break; | ||
| 61 | case SDL_BLENDMODE_MOD: | ||
| 62 | HLINE(Uint16, DRAW_SETPIXEL_MOD_RGB, draw_end); | ||
| 63 | break; | ||
| 64 | case SDL_BLENDMODE_MUL: | ||
| 65 | HLINE(Uint16, DRAW_SETPIXEL_MUL_RGB, draw_end); | ||
| 66 | break; | ||
| 67 | default: | ||
| 68 | HLINE(Uint16, DRAW_SETPIXEL_RGB, draw_end); | ||
| 69 | break; | ||
| 70 | } | ||
| 71 | } else if (x1 == x2) { | ||
| 72 | switch (blendMode) { | ||
| 73 | case SDL_BLENDMODE_BLEND: | ||
| 74 | VLINE(Uint16, DRAW_SETPIXEL_BLEND_RGB, draw_end); | ||
| 75 | break; | ||
| 76 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 77 | VLINE(Uint16, DRAW_SETPIXEL_BLEND_CLAMPED_RGB, draw_end); | ||
| 78 | break; | ||
| 79 | case SDL_BLENDMODE_ADD: | ||
| 80 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 81 | VLINE(Uint16, DRAW_SETPIXEL_ADD_RGB, draw_end); | ||
| 82 | break; | ||
| 83 | case SDL_BLENDMODE_MOD: | ||
| 84 | VLINE(Uint16, DRAW_SETPIXEL_MOD_RGB, draw_end); | ||
| 85 | break; | ||
| 86 | case SDL_BLENDMODE_MUL: | ||
| 87 | VLINE(Uint16, DRAW_SETPIXEL_MUL_RGB, draw_end); | ||
| 88 | break; | ||
| 89 | default: | ||
| 90 | VLINE(Uint16, DRAW_SETPIXEL_RGB, draw_end); | ||
| 91 | break; | ||
| 92 | } | ||
| 93 | } else if (ABS(x1 - x2) == ABS(y1 - y2)) { | ||
| 94 | switch (blendMode) { | ||
| 95 | case SDL_BLENDMODE_BLEND: | ||
| 96 | DLINE(Uint16, DRAW_SETPIXEL_BLEND_RGB, draw_end); | ||
| 97 | break; | ||
| 98 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 99 | DLINE(Uint16, DRAW_SETPIXEL_BLEND_CLAMPED_RGB, draw_end); | ||
| 100 | break; | ||
| 101 | case SDL_BLENDMODE_ADD: | ||
| 102 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 103 | DLINE(Uint16, DRAW_SETPIXEL_ADD_RGB, draw_end); | ||
| 104 | break; | ||
| 105 | case SDL_BLENDMODE_MOD: | ||
| 106 | DLINE(Uint16, DRAW_SETPIXEL_MOD_RGB, draw_end); | ||
| 107 | break; | ||
| 108 | case SDL_BLENDMODE_MUL: | ||
| 109 | DLINE(Uint16, DRAW_SETPIXEL_MUL_RGB, draw_end); | ||
| 110 | break; | ||
| 111 | default: | ||
| 112 | DLINE(Uint16, DRAW_SETPIXEL_RGB, draw_end); | ||
| 113 | break; | ||
| 114 | } | ||
| 115 | } else { | ||
| 116 | switch (blendMode) { | ||
| 117 | case SDL_BLENDMODE_BLEND: | ||
| 118 | AALINE(x1, y1, x2, y2, | ||
| 119 | DRAW_SETPIXELXY2_BLEND_RGB, DRAW_SETPIXELXY2_BLEND_RGB, | ||
| 120 | draw_end); | ||
| 121 | break; | ||
| 122 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 123 | AALINE(x1, y1, x2, y2, | ||
| 124 | DRAW_SETPIXELXY2_BLEND_CLAMPED_RGB, DRAW_SETPIXELXY2_BLEND_CLAMPED_RGB, | ||
| 125 | draw_end); | ||
| 126 | break; | ||
| 127 | case SDL_BLENDMODE_ADD: | ||
| 128 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 129 | AALINE(x1, y1, x2, y2, | ||
| 130 | DRAW_SETPIXELXY2_ADD_RGB, DRAW_SETPIXELXY2_ADD_RGB, | ||
| 131 | draw_end); | ||
| 132 | break; | ||
| 133 | case SDL_BLENDMODE_MOD: | ||
| 134 | AALINE(x1, y1, x2, y2, | ||
| 135 | DRAW_SETPIXELXY2_MOD_RGB, DRAW_SETPIXELXY2_MOD_RGB, | ||
| 136 | draw_end); | ||
| 137 | break; | ||
| 138 | case SDL_BLENDMODE_MUL: | ||
| 139 | AALINE(x1, y1, x2, y2, | ||
| 140 | DRAW_SETPIXELXY2_MUL_RGB, DRAW_SETPIXELXY2_MUL_RGB, | ||
| 141 | draw_end); | ||
| 142 | break; | ||
| 143 | default: | ||
| 144 | AALINE(x1, y1, x2, y2, | ||
| 145 | DRAW_SETPIXELXY2_RGB, DRAW_SETPIXELXY2_BLEND_RGB, | ||
| 146 | draw_end); | ||
| 147 | break; | ||
| 148 | } | ||
| 149 | } | ||
| 150 | } | ||
| 151 | |||
| 152 | static void SDL_BlendLine_RGB555(SDL_Surface *dst, int x1, int y1, int x2, int y2, | ||
| 153 | SDL_BlendMode blendMode, Uint8 _r, Uint8 _g, Uint8 _b, Uint8 _a, | ||
| 154 | bool draw_end) | ||
| 155 | { | ||
| 156 | unsigned r, g, b, a, inva; | ||
| 157 | |||
| 158 | if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) { | ||
| 159 | r = DRAW_MUL(_r, _a); | ||
| 160 | g = DRAW_MUL(_g, _a); | ||
| 161 | b = DRAW_MUL(_b, _a); | ||
| 162 | a = _a; | ||
| 163 | } else { | ||
| 164 | r = _r; | ||
| 165 | g = _g; | ||
| 166 | b = _b; | ||
| 167 | a = _a; | ||
| 168 | } | ||
| 169 | inva = (a ^ 0xff); | ||
| 170 | |||
| 171 | if (y1 == y2) { | ||
| 172 | switch (blendMode) { | ||
| 173 | case SDL_BLENDMODE_BLEND: | ||
| 174 | HLINE(Uint16, DRAW_SETPIXEL_BLEND_RGB555, draw_end); | ||
| 175 | break; | ||
| 176 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 177 | HLINE(Uint16, DRAW_SETPIXEL_BLEND_CLAMPED_RGB555, draw_end); | ||
| 178 | break; | ||
| 179 | case SDL_BLENDMODE_ADD: | ||
| 180 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 181 | HLINE(Uint16, DRAW_SETPIXEL_ADD_RGB555, draw_end); | ||
| 182 | break; | ||
| 183 | case SDL_BLENDMODE_MOD: | ||
| 184 | HLINE(Uint16, DRAW_SETPIXEL_MOD_RGB555, draw_end); | ||
| 185 | break; | ||
| 186 | case SDL_BLENDMODE_MUL: | ||
| 187 | HLINE(Uint16, DRAW_SETPIXEL_MUL_RGB555, draw_end); | ||
| 188 | break; | ||
| 189 | default: | ||
| 190 | HLINE(Uint16, DRAW_SETPIXEL_RGB555, draw_end); | ||
| 191 | break; | ||
| 192 | } | ||
| 193 | } else if (x1 == x2) { | ||
| 194 | switch (blendMode) { | ||
| 195 | case SDL_BLENDMODE_BLEND: | ||
| 196 | VLINE(Uint16, DRAW_SETPIXEL_BLEND_RGB555, draw_end); | ||
| 197 | break; | ||
| 198 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 199 | VLINE(Uint16, DRAW_SETPIXEL_BLEND_CLAMPED_RGB555, draw_end); | ||
| 200 | break; | ||
| 201 | case SDL_BLENDMODE_ADD: | ||
| 202 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 203 | VLINE(Uint16, DRAW_SETPIXEL_ADD_RGB555, draw_end); | ||
| 204 | break; | ||
| 205 | case SDL_BLENDMODE_MOD: | ||
| 206 | VLINE(Uint16, DRAW_SETPIXEL_MOD_RGB555, draw_end); | ||
| 207 | break; | ||
| 208 | case SDL_BLENDMODE_MUL: | ||
| 209 | VLINE(Uint16, DRAW_SETPIXEL_MUL_RGB555, draw_end); | ||
| 210 | break; | ||
| 211 | default: | ||
| 212 | VLINE(Uint16, DRAW_SETPIXEL_RGB555, draw_end); | ||
| 213 | break; | ||
| 214 | } | ||
| 215 | } else if (ABS(x1 - x2) == ABS(y1 - y2)) { | ||
| 216 | switch (blendMode) { | ||
| 217 | case SDL_BLENDMODE_BLEND: | ||
| 218 | DLINE(Uint16, DRAW_SETPIXEL_BLEND_RGB555, draw_end); | ||
| 219 | break; | ||
| 220 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 221 | DLINE(Uint16, DRAW_SETPIXEL_BLEND_CLAMPED_RGB555, draw_end); | ||
| 222 | break; | ||
| 223 | case SDL_BLENDMODE_ADD: | ||
| 224 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 225 | DLINE(Uint16, DRAW_SETPIXEL_ADD_RGB555, draw_end); | ||
| 226 | break; | ||
| 227 | case SDL_BLENDMODE_MOD: | ||
| 228 | DLINE(Uint16, DRAW_SETPIXEL_MOD_RGB555, draw_end); | ||
| 229 | break; | ||
| 230 | case SDL_BLENDMODE_MUL: | ||
| 231 | DLINE(Uint16, DRAW_SETPIXEL_MUL_RGB555, draw_end); | ||
| 232 | break; | ||
| 233 | default: | ||
| 234 | DLINE(Uint16, DRAW_SETPIXEL_RGB555, draw_end); | ||
| 235 | break; | ||
| 236 | } | ||
| 237 | } else { | ||
| 238 | switch (blendMode) { | ||
| 239 | case SDL_BLENDMODE_BLEND: | ||
| 240 | AALINE(x1, y1, x2, y2, | ||
| 241 | DRAW_SETPIXELXY_BLEND_RGB555, DRAW_SETPIXELXY_BLEND_RGB555, | ||
| 242 | draw_end); | ||
| 243 | break; | ||
| 244 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 245 | AALINE(x1, y1, x2, y2, | ||
| 246 | DRAW_SETPIXELXY_BLEND_CLAMPED_RGB555, DRAW_SETPIXELXY_BLEND_CLAMPED_RGB555, | ||
| 247 | draw_end); | ||
| 248 | break; | ||
| 249 | case SDL_BLENDMODE_ADD: | ||
| 250 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 251 | AALINE(x1, y1, x2, y2, | ||
| 252 | DRAW_SETPIXELXY_ADD_RGB555, DRAW_SETPIXELXY_ADD_RGB555, | ||
| 253 | draw_end); | ||
| 254 | break; | ||
| 255 | case SDL_BLENDMODE_MOD: | ||
| 256 | AALINE(x1, y1, x2, y2, | ||
| 257 | DRAW_SETPIXELXY_MOD_RGB555, DRAW_SETPIXELXY_MOD_RGB555, | ||
| 258 | draw_end); | ||
| 259 | break; | ||
| 260 | case SDL_BLENDMODE_MUL: | ||
| 261 | AALINE(x1, y1, x2, y2, | ||
| 262 | DRAW_SETPIXELXY_MUL_RGB555, DRAW_SETPIXELXY_MUL_RGB555, | ||
| 263 | draw_end); | ||
| 264 | break; | ||
| 265 | default: | ||
| 266 | AALINE(x1, y1, x2, y2, | ||
| 267 | DRAW_SETPIXELXY_RGB555, DRAW_SETPIXELXY_BLEND_RGB555, | ||
| 268 | draw_end); | ||
| 269 | break; | ||
| 270 | } | ||
| 271 | } | ||
| 272 | } | ||
| 273 | |||
| 274 | static void SDL_BlendLine_RGB565(SDL_Surface *dst, int x1, int y1, int x2, int y2, | ||
| 275 | SDL_BlendMode blendMode, Uint8 _r, Uint8 _g, Uint8 _b, Uint8 _a, | ||
| 276 | bool draw_end) | ||
| 277 | { | ||
| 278 | unsigned r, g, b, a, inva; | ||
| 279 | |||
| 280 | if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) { | ||
| 281 | r = DRAW_MUL(_r, _a); | ||
| 282 | g = DRAW_MUL(_g, _a); | ||
| 283 | b = DRAW_MUL(_b, _a); | ||
| 284 | a = _a; | ||
| 285 | } else { | ||
| 286 | r = _r; | ||
| 287 | g = _g; | ||
| 288 | b = _b; | ||
| 289 | a = _a; | ||
| 290 | } | ||
| 291 | inva = (a ^ 0xff); | ||
| 292 | |||
| 293 | if (y1 == y2) { | ||
| 294 | switch (blendMode) { | ||
| 295 | case SDL_BLENDMODE_BLEND: | ||
| 296 | HLINE(Uint16, DRAW_SETPIXEL_BLEND_RGB565, draw_end); | ||
| 297 | break; | ||
| 298 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 299 | HLINE(Uint16, DRAW_SETPIXEL_BLEND_CLAMPED_RGB565, draw_end); | ||
| 300 | break; | ||
| 301 | case SDL_BLENDMODE_ADD: | ||
| 302 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 303 | HLINE(Uint16, DRAW_SETPIXEL_ADD_RGB565, draw_end); | ||
| 304 | break; | ||
| 305 | case SDL_BLENDMODE_MOD: | ||
| 306 | HLINE(Uint16, DRAW_SETPIXEL_MOD_RGB565, draw_end); | ||
| 307 | break; | ||
| 308 | case SDL_BLENDMODE_MUL: | ||
| 309 | HLINE(Uint16, DRAW_SETPIXEL_MUL_RGB565, draw_end); | ||
| 310 | break; | ||
| 311 | default: | ||
| 312 | HLINE(Uint16, DRAW_SETPIXEL_RGB565, draw_end); | ||
| 313 | break; | ||
| 314 | } | ||
| 315 | } else if (x1 == x2) { | ||
| 316 | switch (blendMode) { | ||
| 317 | case SDL_BLENDMODE_BLEND: | ||
| 318 | VLINE(Uint16, DRAW_SETPIXEL_BLEND_RGB565, draw_end); | ||
| 319 | break; | ||
| 320 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 321 | VLINE(Uint16, DRAW_SETPIXEL_BLEND_CLAMPED_RGB565, draw_end); | ||
| 322 | break; | ||
| 323 | case SDL_BLENDMODE_ADD: | ||
| 324 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 325 | VLINE(Uint16, DRAW_SETPIXEL_ADD_RGB565, draw_end); | ||
| 326 | break; | ||
| 327 | case SDL_BLENDMODE_MOD: | ||
| 328 | VLINE(Uint16, DRAW_SETPIXEL_MOD_RGB565, draw_end); | ||
| 329 | break; | ||
| 330 | case SDL_BLENDMODE_MUL: | ||
| 331 | VLINE(Uint16, DRAW_SETPIXEL_MUL_RGB565, draw_end); | ||
| 332 | break; | ||
| 333 | default: | ||
| 334 | VLINE(Uint16, DRAW_SETPIXEL_RGB565, draw_end); | ||
| 335 | break; | ||
| 336 | } | ||
| 337 | } else if (ABS(x1 - x2) == ABS(y1 - y2)) { | ||
| 338 | switch (blendMode) { | ||
| 339 | case SDL_BLENDMODE_BLEND: | ||
| 340 | DLINE(Uint16, DRAW_SETPIXEL_BLEND_RGB565, draw_end); | ||
| 341 | break; | ||
| 342 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 343 | DLINE(Uint16, DRAW_SETPIXEL_BLEND_CLAMPED_RGB565, draw_end); | ||
| 344 | break; | ||
| 345 | case SDL_BLENDMODE_ADD: | ||
| 346 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 347 | DLINE(Uint16, DRAW_SETPIXEL_ADD_RGB565, draw_end); | ||
| 348 | break; | ||
| 349 | case SDL_BLENDMODE_MOD: | ||
| 350 | DLINE(Uint16, DRAW_SETPIXEL_MOD_RGB565, draw_end); | ||
| 351 | break; | ||
| 352 | case SDL_BLENDMODE_MUL: | ||
| 353 | DLINE(Uint16, DRAW_SETPIXEL_MUL_RGB565, draw_end); | ||
| 354 | break; | ||
| 355 | default: | ||
| 356 | DLINE(Uint16, DRAW_SETPIXEL_RGB565, draw_end); | ||
| 357 | break; | ||
| 358 | } | ||
| 359 | } else { | ||
| 360 | switch (blendMode) { | ||
| 361 | case SDL_BLENDMODE_BLEND: | ||
| 362 | AALINE(x1, y1, x2, y2, | ||
| 363 | DRAW_SETPIXELXY_BLEND_RGB565, DRAW_SETPIXELXY_BLEND_RGB565, | ||
| 364 | draw_end); | ||
| 365 | break; | ||
| 366 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 367 | AALINE(x1, y1, x2, y2, | ||
| 368 | DRAW_SETPIXELXY_BLEND_CLAMPED_RGB565, DRAW_SETPIXELXY_BLEND_CLAMPED_RGB565, | ||
| 369 | draw_end); | ||
| 370 | break; | ||
| 371 | case SDL_BLENDMODE_ADD: | ||
| 372 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 373 | AALINE(x1, y1, x2, y2, | ||
| 374 | DRAW_SETPIXELXY_ADD_RGB565, DRAW_SETPIXELXY_ADD_RGB565, | ||
| 375 | draw_end); | ||
| 376 | break; | ||
| 377 | case SDL_BLENDMODE_MOD: | ||
| 378 | AALINE(x1, y1, x2, y2, | ||
| 379 | DRAW_SETPIXELXY_MOD_RGB565, DRAW_SETPIXELXY_MOD_RGB565, | ||
| 380 | draw_end); | ||
| 381 | break; | ||
| 382 | case SDL_BLENDMODE_MUL: | ||
| 383 | AALINE(x1, y1, x2, y2, | ||
| 384 | DRAW_SETPIXELXY_MUL_RGB565, DRAW_SETPIXELXY_MUL_RGB565, | ||
| 385 | draw_end); | ||
| 386 | break; | ||
| 387 | default: | ||
| 388 | AALINE(x1, y1, x2, y2, | ||
| 389 | DRAW_SETPIXELXY_RGB565, DRAW_SETPIXELXY_BLEND_RGB565, | ||
| 390 | draw_end); | ||
| 391 | break; | ||
| 392 | } | ||
| 393 | } | ||
| 394 | } | ||
| 395 | |||
| 396 | static void SDL_BlendLine_RGB4(SDL_Surface *dst, int x1, int y1, int x2, int y2, | ||
| 397 | SDL_BlendMode blendMode, Uint8 _r, Uint8 _g, Uint8 _b, Uint8 _a, | ||
| 398 | bool draw_end) | ||
| 399 | { | ||
| 400 | const SDL_PixelFormatDetails *fmt = dst->fmt; | ||
| 401 | unsigned r, g, b, a, inva; | ||
| 402 | |||
| 403 | if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) { | ||
| 404 | r = DRAW_MUL(_r, _a); | ||
| 405 | g = DRAW_MUL(_g, _a); | ||
| 406 | b = DRAW_MUL(_b, _a); | ||
| 407 | a = _a; | ||
| 408 | } else { | ||
| 409 | r = _r; | ||
| 410 | g = _g; | ||
| 411 | b = _b; | ||
| 412 | a = _a; | ||
| 413 | } | ||
| 414 | inva = (a ^ 0xff); | ||
| 415 | |||
| 416 | if (y1 == y2) { | ||
| 417 | switch (blendMode) { | ||
| 418 | case SDL_BLENDMODE_BLEND: | ||
| 419 | HLINE(Uint32, DRAW_SETPIXEL_BLEND_RGB, draw_end); | ||
| 420 | break; | ||
| 421 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 422 | HLINE(Uint32, DRAW_SETPIXEL_BLEND_CLAMPED_RGB, draw_end); | ||
| 423 | break; | ||
| 424 | case SDL_BLENDMODE_ADD: | ||
| 425 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 426 | HLINE(Uint32, DRAW_SETPIXEL_ADD_RGB, draw_end); | ||
| 427 | break; | ||
| 428 | case SDL_BLENDMODE_MOD: | ||
| 429 | HLINE(Uint32, DRAW_SETPIXEL_MOD_RGB, draw_end); | ||
| 430 | break; | ||
| 431 | case SDL_BLENDMODE_MUL: | ||
| 432 | HLINE(Uint32, DRAW_SETPIXEL_MUL_RGB, draw_end); | ||
| 433 | break; | ||
| 434 | default: | ||
| 435 | HLINE(Uint32, DRAW_SETPIXEL_RGB, draw_end); | ||
| 436 | break; | ||
| 437 | } | ||
| 438 | } else if (x1 == x2) { | ||
| 439 | switch (blendMode) { | ||
| 440 | case SDL_BLENDMODE_BLEND: | ||
| 441 | VLINE(Uint32, DRAW_SETPIXEL_BLEND_RGB, draw_end); | ||
| 442 | break; | ||
| 443 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 444 | VLINE(Uint32, DRAW_SETPIXEL_BLEND_CLAMPED_RGB, draw_end); | ||
| 445 | break; | ||
| 446 | case SDL_BLENDMODE_ADD: | ||
| 447 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 448 | VLINE(Uint32, DRAW_SETPIXEL_ADD_RGB, draw_end); | ||
| 449 | break; | ||
| 450 | case SDL_BLENDMODE_MOD: | ||
| 451 | VLINE(Uint32, DRAW_SETPIXEL_MOD_RGB, draw_end); | ||
| 452 | break; | ||
| 453 | case SDL_BLENDMODE_MUL: | ||
| 454 | VLINE(Uint32, DRAW_SETPIXEL_MUL_RGB, draw_end); | ||
| 455 | break; | ||
| 456 | default: | ||
| 457 | VLINE(Uint32, DRAW_SETPIXEL_RGB, draw_end); | ||
| 458 | break; | ||
| 459 | } | ||
| 460 | } else if (ABS(x1 - x2) == ABS(y1 - y2)) { | ||
| 461 | switch (blendMode) { | ||
| 462 | case SDL_BLENDMODE_BLEND: | ||
| 463 | DLINE(Uint32, DRAW_SETPIXEL_BLEND_RGB, draw_end); | ||
| 464 | break; | ||
| 465 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 466 | DLINE(Uint32, DRAW_SETPIXEL_BLEND_CLAMPED_RGB, draw_end); | ||
| 467 | break; | ||
| 468 | case SDL_BLENDMODE_ADD: | ||
| 469 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 470 | DLINE(Uint32, DRAW_SETPIXEL_ADD_RGB, draw_end); | ||
| 471 | break; | ||
| 472 | case SDL_BLENDMODE_MOD: | ||
| 473 | DLINE(Uint32, DRAW_SETPIXEL_MOD_RGB, draw_end); | ||
| 474 | break; | ||
| 475 | case SDL_BLENDMODE_MUL: | ||
| 476 | DLINE(Uint32, DRAW_SETPIXEL_MUL_RGB, draw_end); | ||
| 477 | break; | ||
| 478 | default: | ||
| 479 | DLINE(Uint32, DRAW_SETPIXEL_RGB, draw_end); | ||
| 480 | break; | ||
| 481 | } | ||
| 482 | } else { | ||
| 483 | switch (blendMode) { | ||
| 484 | case SDL_BLENDMODE_BLEND: | ||
| 485 | AALINE(x1, y1, x2, y2, | ||
| 486 | DRAW_SETPIXELXY4_BLEND_RGB, DRAW_SETPIXELXY4_BLEND_RGB, | ||
| 487 | draw_end); | ||
| 488 | break; | ||
| 489 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 490 | AALINE(x1, y1, x2, y2, | ||
| 491 | DRAW_SETPIXELXY4_BLEND_CLAMPED_RGB, DRAW_SETPIXELXY4_BLEND_CLAMPED_RGB, | ||
| 492 | draw_end); | ||
| 493 | break; | ||
| 494 | case SDL_BLENDMODE_ADD: | ||
| 495 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 496 | AALINE(x1, y1, x2, y2, | ||
| 497 | DRAW_SETPIXELXY4_ADD_RGB, DRAW_SETPIXELXY4_ADD_RGB, | ||
| 498 | draw_end); | ||
| 499 | break; | ||
| 500 | case SDL_BLENDMODE_MOD: | ||
| 501 | AALINE(x1, y1, x2, y2, | ||
| 502 | DRAW_SETPIXELXY4_MOD_RGB, DRAW_SETPIXELXY4_MOD_RGB, | ||
| 503 | draw_end); | ||
| 504 | break; | ||
| 505 | case SDL_BLENDMODE_MUL: | ||
| 506 | AALINE(x1, y1, x2, y2, | ||
| 507 | DRAW_SETPIXELXY4_MUL_RGB, DRAW_SETPIXELXY4_MUL_RGB, | ||
| 508 | draw_end); | ||
| 509 | break; | ||
| 510 | default: | ||
| 511 | AALINE(x1, y1, x2, y2, | ||
| 512 | DRAW_SETPIXELXY4_RGB, DRAW_SETPIXELXY4_BLEND_RGB, | ||
| 513 | draw_end); | ||
| 514 | break; | ||
| 515 | } | ||
| 516 | } | ||
| 517 | } | ||
| 518 | |||
| 519 | static void SDL_BlendLine_RGBA4(SDL_Surface *dst, int x1, int y1, int x2, int y2, | ||
| 520 | SDL_BlendMode blendMode, Uint8 _r, Uint8 _g, Uint8 _b, Uint8 _a, | ||
| 521 | bool draw_end) | ||
| 522 | { | ||
| 523 | const SDL_PixelFormatDetails *fmt = dst->fmt; | ||
| 524 | unsigned r, g, b, a, inva; | ||
| 525 | |||
| 526 | if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) { | ||
| 527 | r = DRAW_MUL(_r, _a); | ||
| 528 | g = DRAW_MUL(_g, _a); | ||
| 529 | b = DRAW_MUL(_b, _a); | ||
| 530 | a = _a; | ||
| 531 | } else { | ||
| 532 | r = _r; | ||
| 533 | g = _g; | ||
| 534 | b = _b; | ||
| 535 | a = _a; | ||
| 536 | } | ||
| 537 | inva = (a ^ 0xff); | ||
| 538 | |||
| 539 | if (y1 == y2) { | ||
| 540 | switch (blendMode) { | ||
| 541 | case SDL_BLENDMODE_BLEND: | ||
| 542 | HLINE(Uint32, DRAW_SETPIXEL_BLEND_RGBA, draw_end); | ||
| 543 | break; | ||
| 544 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 545 | HLINE(Uint32, DRAW_SETPIXEL_BLEND_CLAMPED_RGBA, draw_end); | ||
| 546 | break; | ||
| 547 | case SDL_BLENDMODE_ADD: | ||
| 548 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 549 | HLINE(Uint32, DRAW_SETPIXEL_ADD_RGBA, draw_end); | ||
| 550 | break; | ||
| 551 | case SDL_BLENDMODE_MOD: | ||
| 552 | HLINE(Uint32, DRAW_SETPIXEL_MOD_RGBA, draw_end); | ||
| 553 | break; | ||
| 554 | case SDL_BLENDMODE_MUL: | ||
| 555 | HLINE(Uint32, DRAW_SETPIXEL_MUL_RGBA, draw_end); | ||
| 556 | break; | ||
| 557 | default: | ||
| 558 | HLINE(Uint32, DRAW_SETPIXEL_RGBA, draw_end); | ||
| 559 | break; | ||
| 560 | } | ||
| 561 | } else if (x1 == x2) { | ||
| 562 | switch (blendMode) { | ||
| 563 | case SDL_BLENDMODE_BLEND: | ||
| 564 | VLINE(Uint32, DRAW_SETPIXEL_BLEND_RGBA, draw_end); | ||
| 565 | break; | ||
| 566 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 567 | VLINE(Uint32, DRAW_SETPIXEL_BLEND_CLAMPED_RGBA, draw_end); | ||
| 568 | break; | ||
| 569 | case SDL_BLENDMODE_ADD: | ||
| 570 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 571 | VLINE(Uint32, DRAW_SETPIXEL_ADD_RGBA, draw_end); | ||
| 572 | break; | ||
| 573 | case SDL_BLENDMODE_MOD: | ||
| 574 | VLINE(Uint32, DRAW_SETPIXEL_MOD_RGBA, draw_end); | ||
| 575 | break; | ||
| 576 | case SDL_BLENDMODE_MUL: | ||
| 577 | VLINE(Uint32, DRAW_SETPIXEL_MUL_RGBA, draw_end); | ||
| 578 | break; | ||
| 579 | default: | ||
| 580 | VLINE(Uint32, DRAW_SETPIXEL_RGBA, draw_end); | ||
| 581 | break; | ||
| 582 | } | ||
| 583 | } else if (ABS(x1 - x2) == ABS(y1 - y2)) { | ||
| 584 | switch (blendMode) { | ||
| 585 | case SDL_BLENDMODE_BLEND: | ||
| 586 | DLINE(Uint32, DRAW_SETPIXEL_BLEND_RGBA, draw_end); | ||
| 587 | break; | ||
| 588 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 589 | DLINE(Uint32, DRAW_SETPIXEL_BLEND_CLAMPED_RGBA, draw_end); | ||
| 590 | break; | ||
| 591 | case SDL_BLENDMODE_ADD: | ||
| 592 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 593 | DLINE(Uint32, DRAW_SETPIXEL_ADD_RGBA, draw_end); | ||
| 594 | break; | ||
| 595 | case SDL_BLENDMODE_MOD: | ||
| 596 | DLINE(Uint32, DRAW_SETPIXEL_MOD_RGBA, draw_end); | ||
| 597 | break; | ||
| 598 | case SDL_BLENDMODE_MUL: | ||
| 599 | DLINE(Uint32, DRAW_SETPIXEL_MUL_RGBA, draw_end); | ||
| 600 | break; | ||
| 601 | default: | ||
| 602 | DLINE(Uint32, DRAW_SETPIXEL_RGBA, draw_end); | ||
| 603 | break; | ||
| 604 | } | ||
| 605 | } else { | ||
| 606 | switch (blendMode) { | ||
| 607 | case SDL_BLENDMODE_BLEND: | ||
| 608 | AALINE(x1, y1, x2, y2, | ||
| 609 | DRAW_SETPIXELXY4_BLEND_RGBA, DRAW_SETPIXELXY4_BLEND_RGBA, | ||
| 610 | draw_end); | ||
| 611 | break; | ||
| 612 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 613 | AALINE(x1, y1, x2, y2, | ||
| 614 | DRAW_SETPIXELXY4_BLEND_CLAMPED_RGBA, DRAW_SETPIXELXY4_BLEND_CLAMPED_RGBA, | ||
| 615 | draw_end); | ||
| 616 | break; | ||
| 617 | case SDL_BLENDMODE_ADD: | ||
| 618 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 619 | AALINE(x1, y1, x2, y2, | ||
| 620 | DRAW_SETPIXELXY4_ADD_RGBA, DRAW_SETPIXELXY4_ADD_RGBA, | ||
| 621 | draw_end); | ||
| 622 | break; | ||
| 623 | case SDL_BLENDMODE_MOD: | ||
| 624 | AALINE(x1, y1, x2, y2, | ||
| 625 | DRAW_SETPIXELXY4_MOD_RGBA, DRAW_SETPIXELXY4_MOD_RGBA, | ||
| 626 | draw_end); | ||
| 627 | break; | ||
| 628 | case SDL_BLENDMODE_MUL: | ||
| 629 | AALINE(x1, y1, x2, y2, | ||
| 630 | DRAW_SETPIXELXY4_MUL_RGBA, DRAW_SETPIXELXY4_MUL_RGBA, | ||
| 631 | draw_end); | ||
| 632 | break; | ||
| 633 | default: | ||
| 634 | AALINE(x1, y1, x2, y2, | ||
| 635 | DRAW_SETPIXELXY4_RGBA, DRAW_SETPIXELXY4_BLEND_RGBA, | ||
| 636 | draw_end); | ||
| 637 | break; | ||
| 638 | } | ||
| 639 | } | ||
| 640 | } | ||
| 641 | |||
| 642 | static void SDL_BlendLine_XRGB8888(SDL_Surface *dst, int x1, int y1, int x2, int y2, | ||
| 643 | SDL_BlendMode blendMode, Uint8 _r, Uint8 _g, Uint8 _b, Uint8 _a, | ||
| 644 | bool draw_end) | ||
| 645 | { | ||
| 646 | unsigned r, g, b, a, inva; | ||
| 647 | |||
| 648 | if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) { | ||
| 649 | r = DRAW_MUL(_r, _a); | ||
| 650 | g = DRAW_MUL(_g, _a); | ||
| 651 | b = DRAW_MUL(_b, _a); | ||
| 652 | a = _a; | ||
| 653 | } else { | ||
| 654 | r = _r; | ||
| 655 | g = _g; | ||
| 656 | b = _b; | ||
| 657 | a = _a; | ||
| 658 | } | ||
| 659 | inva = (a ^ 0xff); | ||
| 660 | |||
| 661 | if (y1 == y2) { | ||
| 662 | switch (blendMode) { | ||
| 663 | case SDL_BLENDMODE_BLEND: | ||
| 664 | HLINE(Uint32, DRAW_SETPIXEL_BLEND_XRGB8888, draw_end); | ||
| 665 | break; | ||
| 666 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 667 | HLINE(Uint32, DRAW_SETPIXEL_BLEND_CLAMPED_XRGB8888, draw_end); | ||
| 668 | break; | ||
| 669 | case SDL_BLENDMODE_ADD: | ||
| 670 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 671 | HLINE(Uint32, DRAW_SETPIXEL_ADD_XRGB8888, draw_end); | ||
| 672 | break; | ||
| 673 | case SDL_BLENDMODE_MOD: | ||
| 674 | HLINE(Uint32, DRAW_SETPIXEL_MOD_XRGB8888, draw_end); | ||
| 675 | break; | ||
| 676 | case SDL_BLENDMODE_MUL: | ||
| 677 | HLINE(Uint32, DRAW_SETPIXEL_MUL_XRGB8888, draw_end); | ||
| 678 | break; | ||
| 679 | default: | ||
| 680 | HLINE(Uint32, DRAW_SETPIXEL_XRGB8888, draw_end); | ||
| 681 | break; | ||
| 682 | } | ||
| 683 | } else if (x1 == x2) { | ||
| 684 | switch (blendMode) { | ||
| 685 | case SDL_BLENDMODE_BLEND: | ||
| 686 | VLINE(Uint32, DRAW_SETPIXEL_BLEND_XRGB8888, draw_end); | ||
| 687 | break; | ||
| 688 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 689 | VLINE(Uint32, DRAW_SETPIXEL_BLEND_CLAMPED_XRGB8888, draw_end); | ||
| 690 | break; | ||
| 691 | case SDL_BLENDMODE_ADD: | ||
| 692 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 693 | VLINE(Uint32, DRAW_SETPIXEL_ADD_XRGB8888, draw_end); | ||
| 694 | break; | ||
| 695 | case SDL_BLENDMODE_MOD: | ||
| 696 | VLINE(Uint32, DRAW_SETPIXEL_MOD_XRGB8888, draw_end); | ||
| 697 | break; | ||
| 698 | case SDL_BLENDMODE_MUL: | ||
| 699 | VLINE(Uint32, DRAW_SETPIXEL_MUL_XRGB8888, draw_end); | ||
| 700 | break; | ||
| 701 | default: | ||
| 702 | VLINE(Uint32, DRAW_SETPIXEL_XRGB8888, draw_end); | ||
| 703 | break; | ||
| 704 | } | ||
| 705 | } else if (ABS(x1 - x2) == ABS(y1 - y2)) { | ||
| 706 | switch (blendMode) { | ||
| 707 | case SDL_BLENDMODE_BLEND: | ||
| 708 | DLINE(Uint32, DRAW_SETPIXEL_BLEND_XRGB8888, draw_end); | ||
| 709 | break; | ||
| 710 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 711 | DLINE(Uint32, DRAW_SETPIXEL_BLEND_CLAMPED_XRGB8888, draw_end); | ||
| 712 | break; | ||
| 713 | case SDL_BLENDMODE_ADD: | ||
| 714 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 715 | DLINE(Uint32, DRAW_SETPIXEL_ADD_XRGB8888, draw_end); | ||
| 716 | break; | ||
| 717 | case SDL_BLENDMODE_MOD: | ||
| 718 | DLINE(Uint32, DRAW_SETPIXEL_MOD_XRGB8888, draw_end); | ||
| 719 | break; | ||
| 720 | case SDL_BLENDMODE_MUL: | ||
| 721 | DLINE(Uint32, DRAW_SETPIXEL_MUL_XRGB8888, draw_end); | ||
| 722 | break; | ||
| 723 | default: | ||
| 724 | DLINE(Uint32, DRAW_SETPIXEL_XRGB8888, draw_end); | ||
| 725 | break; | ||
| 726 | } | ||
| 727 | } else { | ||
| 728 | switch (blendMode) { | ||
| 729 | case SDL_BLENDMODE_BLEND: | ||
| 730 | AALINE(x1, y1, x2, y2, | ||
| 731 | DRAW_SETPIXELXY_BLEND_XRGB8888, DRAW_SETPIXELXY_BLEND_XRGB8888, | ||
| 732 | draw_end); | ||
| 733 | break; | ||
| 734 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 735 | AALINE(x1, y1, x2, y2, | ||
| 736 | DRAW_SETPIXELXY_BLEND_CLAMPED_XRGB8888, DRAW_SETPIXELXY_BLEND_CLAMPED_XRGB8888, | ||
| 737 | draw_end); | ||
| 738 | break; | ||
| 739 | case SDL_BLENDMODE_ADD: | ||
| 740 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 741 | AALINE(x1, y1, x2, y2, | ||
| 742 | DRAW_SETPIXELXY_ADD_XRGB8888, DRAW_SETPIXELXY_ADD_XRGB8888, | ||
| 743 | draw_end); | ||
| 744 | break; | ||
| 745 | case SDL_BLENDMODE_MOD: | ||
| 746 | AALINE(x1, y1, x2, y2, | ||
| 747 | DRAW_SETPIXELXY_MOD_XRGB8888, DRAW_SETPIXELXY_MOD_XRGB8888, | ||
| 748 | draw_end); | ||
| 749 | break; | ||
| 750 | case SDL_BLENDMODE_MUL: | ||
| 751 | AALINE(x1, y1, x2, y2, | ||
| 752 | DRAW_SETPIXELXY_MUL_XRGB8888, DRAW_SETPIXELXY_MUL_XRGB8888, | ||
| 753 | draw_end); | ||
| 754 | break; | ||
| 755 | default: | ||
| 756 | AALINE(x1, y1, x2, y2, | ||
| 757 | DRAW_SETPIXELXY_XRGB8888, DRAW_SETPIXELXY_BLEND_XRGB8888, | ||
| 758 | draw_end); | ||
| 759 | break; | ||
| 760 | } | ||
| 761 | } | ||
| 762 | } | ||
| 763 | |||
| 764 | static void SDL_BlendLine_ARGB8888(SDL_Surface *dst, int x1, int y1, int x2, int y2, | ||
| 765 | SDL_BlendMode blendMode, Uint8 _r, Uint8 _g, Uint8 _b, Uint8 _a, | ||
| 766 | bool draw_end) | ||
| 767 | { | ||
| 768 | unsigned r, g, b, a, inva; | ||
| 769 | |||
| 770 | if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) { | ||
| 771 | r = DRAW_MUL(_r, _a); | ||
| 772 | g = DRAW_MUL(_g, _a); | ||
| 773 | b = DRAW_MUL(_b, _a); | ||
| 774 | a = _a; | ||
| 775 | } else { | ||
| 776 | r = _r; | ||
| 777 | g = _g; | ||
| 778 | b = _b; | ||
| 779 | a = _a; | ||
| 780 | } | ||
| 781 | inva = (a ^ 0xff); | ||
| 782 | |||
| 783 | if (y1 == y2) { | ||
| 784 | switch (blendMode) { | ||
| 785 | case SDL_BLENDMODE_BLEND: | ||
| 786 | HLINE(Uint32, DRAW_SETPIXEL_BLEND_ARGB8888, draw_end); | ||
| 787 | break; | ||
| 788 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 789 | HLINE(Uint32, DRAW_SETPIXEL_BLEND_CLAMPED_ARGB8888, draw_end); | ||
| 790 | break; | ||
| 791 | case SDL_BLENDMODE_ADD: | ||
| 792 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 793 | HLINE(Uint32, DRAW_SETPIXEL_ADD_ARGB8888, draw_end); | ||
| 794 | break; | ||
| 795 | case SDL_BLENDMODE_MOD: | ||
| 796 | HLINE(Uint32, DRAW_SETPIXEL_MOD_ARGB8888, draw_end); | ||
| 797 | break; | ||
| 798 | case SDL_BLENDMODE_MUL: | ||
| 799 | HLINE(Uint32, DRAW_SETPIXEL_MUL_ARGB8888, draw_end); | ||
| 800 | break; | ||
| 801 | default: | ||
| 802 | HLINE(Uint32, DRAW_SETPIXEL_ARGB8888, draw_end); | ||
| 803 | break; | ||
| 804 | } | ||
| 805 | } else if (x1 == x2) { | ||
| 806 | switch (blendMode) { | ||
| 807 | case SDL_BLENDMODE_BLEND: | ||
| 808 | VLINE(Uint32, DRAW_SETPIXEL_BLEND_ARGB8888, draw_end); | ||
| 809 | break; | ||
| 810 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 811 | VLINE(Uint32, DRAW_SETPIXEL_BLEND_CLAMPED_ARGB8888, draw_end); | ||
| 812 | break; | ||
| 813 | case SDL_BLENDMODE_ADD: | ||
| 814 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 815 | VLINE(Uint32, DRAW_SETPIXEL_ADD_ARGB8888, draw_end); | ||
| 816 | break; | ||
| 817 | case SDL_BLENDMODE_MOD: | ||
| 818 | VLINE(Uint32, DRAW_SETPIXEL_MOD_ARGB8888, draw_end); | ||
| 819 | break; | ||
| 820 | case SDL_BLENDMODE_MUL: | ||
| 821 | VLINE(Uint32, DRAW_SETPIXEL_MUL_ARGB8888, draw_end); | ||
| 822 | break; | ||
| 823 | default: | ||
| 824 | VLINE(Uint32, DRAW_SETPIXEL_ARGB8888, draw_end); | ||
| 825 | break; | ||
| 826 | } | ||
| 827 | } else if (ABS(x1 - x2) == ABS(y1 - y2)) { | ||
| 828 | switch (blendMode) { | ||
| 829 | case SDL_BLENDMODE_BLEND: | ||
| 830 | DLINE(Uint32, DRAW_SETPIXEL_BLEND_ARGB8888, draw_end); | ||
| 831 | break; | ||
| 832 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 833 | DLINE(Uint32, DRAW_SETPIXEL_BLEND_CLAMPED_ARGB8888, draw_end); | ||
| 834 | break; | ||
| 835 | case SDL_BLENDMODE_ADD: | ||
| 836 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 837 | DLINE(Uint32, DRAW_SETPIXEL_ADD_ARGB8888, draw_end); | ||
| 838 | break; | ||
| 839 | case SDL_BLENDMODE_MOD: | ||
| 840 | DLINE(Uint32, DRAW_SETPIXEL_MOD_ARGB8888, draw_end); | ||
| 841 | break; | ||
| 842 | case SDL_BLENDMODE_MUL: | ||
| 843 | DLINE(Uint32, DRAW_SETPIXEL_MUL_ARGB8888, draw_end); | ||
| 844 | break; | ||
| 845 | default: | ||
| 846 | DLINE(Uint32, DRAW_SETPIXEL_ARGB8888, draw_end); | ||
| 847 | break; | ||
| 848 | } | ||
| 849 | } else { | ||
| 850 | switch (blendMode) { | ||
| 851 | case SDL_BLENDMODE_BLEND: | ||
| 852 | AALINE(x1, y1, x2, y2, | ||
| 853 | DRAW_SETPIXELXY_BLEND_ARGB8888, DRAW_SETPIXELXY_BLEND_ARGB8888, | ||
| 854 | draw_end); | ||
| 855 | break; | ||
| 856 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 857 | AALINE(x1, y1, x2, y2, | ||
| 858 | DRAW_SETPIXELXY_BLEND_CLAMPED_ARGB8888, DRAW_SETPIXELXY_BLEND_CLAMPED_ARGB8888, | ||
| 859 | draw_end); | ||
| 860 | break; | ||
| 861 | case SDL_BLENDMODE_ADD: | ||
| 862 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 863 | AALINE(x1, y1, x2, y2, | ||
| 864 | DRAW_SETPIXELXY_ADD_ARGB8888, DRAW_SETPIXELXY_ADD_ARGB8888, | ||
| 865 | draw_end); | ||
| 866 | break; | ||
| 867 | case SDL_BLENDMODE_MOD: | ||
| 868 | AALINE(x1, y1, x2, y2, | ||
| 869 | DRAW_SETPIXELXY_MOD_ARGB8888, DRAW_SETPIXELXY_MOD_ARGB8888, | ||
| 870 | draw_end); | ||
| 871 | break; | ||
| 872 | case SDL_BLENDMODE_MUL: | ||
| 873 | AALINE(x1, y1, x2, y2, | ||
| 874 | DRAW_SETPIXELXY_MUL_ARGB8888, DRAW_SETPIXELXY_MUL_ARGB8888, | ||
| 875 | draw_end); | ||
| 876 | break; | ||
| 877 | default: | ||
| 878 | AALINE(x1, y1, x2, y2, | ||
| 879 | DRAW_SETPIXELXY_ARGB8888, DRAW_SETPIXELXY_BLEND_ARGB8888, | ||
| 880 | draw_end); | ||
| 881 | break; | ||
| 882 | } | ||
| 883 | } | ||
| 884 | } | ||
| 885 | |||
| 886 | typedef void (*BlendLineFunc)(SDL_Surface *dst, | ||
| 887 | int x1, int y1, int x2, int y2, | ||
| 888 | SDL_BlendMode blendMode, | ||
| 889 | Uint8 r, Uint8 g, Uint8 b, Uint8 a, | ||
| 890 | bool draw_end); | ||
| 891 | |||
| 892 | static BlendLineFunc SDL_CalculateBlendLineFunc(const SDL_PixelFormatDetails *fmt) | ||
| 893 | { | ||
| 894 | switch (fmt->bytes_per_pixel) { | ||
| 895 | case 2: | ||
| 896 | if (fmt->Rmask == 0x7C00) { | ||
| 897 | return SDL_BlendLine_RGB555; | ||
| 898 | } else if (fmt->Rmask == 0xF800) { | ||
| 899 | return SDL_BlendLine_RGB565; | ||
| 900 | } else { | ||
| 901 | return SDL_BlendLine_RGB2; | ||
| 902 | } | ||
| 903 | // break; -Wunreachable-code-break | ||
| 904 | case 4: | ||
| 905 | if (fmt->Rmask == 0x00FF0000) { | ||
| 906 | if (fmt->Amask) { | ||
| 907 | return SDL_BlendLine_ARGB8888; | ||
| 908 | } else { | ||
| 909 | return SDL_BlendLine_XRGB8888; | ||
| 910 | } | ||
| 911 | } else { | ||
| 912 | if (fmt->Amask) { | ||
| 913 | return SDL_BlendLine_RGBA4; | ||
| 914 | } else { | ||
| 915 | return SDL_BlendLine_RGB4; | ||
| 916 | } | ||
| 917 | } | ||
| 918 | } | ||
| 919 | return NULL; | ||
| 920 | } | ||
| 921 | |||
| 922 | bool SDL_BlendLine(SDL_Surface *dst, int x1, int y1, int x2, int y2, SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) | ||
| 923 | { | ||
| 924 | BlendLineFunc func; | ||
| 925 | |||
| 926 | if (!SDL_SurfaceValid(dst)) { | ||
| 927 | return SDL_InvalidParamError("SDL_BlendLine(): dst"); | ||
| 928 | } | ||
| 929 | |||
| 930 | func = SDL_CalculateBlendLineFunc(dst->fmt); | ||
| 931 | if (!func) { | ||
| 932 | return SDL_SetError("SDL_BlendLine(): Unsupported surface format"); | ||
| 933 | } | ||
| 934 | |||
| 935 | // Perform clipping | ||
| 936 | // FIXME: We don't actually want to clip, as it may change line slope | ||
| 937 | if (!SDL_GetRectAndLineIntersection(&dst->clip_rect, &x1, &y1, &x2, &y2)) { | ||
| 938 | return true; | ||
| 939 | } | ||
| 940 | |||
| 941 | func(dst, x1, y1, x2, y2, blendMode, r, g, b, a, true); | ||
| 942 | return true; | ||
| 943 | } | ||
| 944 | |||
| 945 | bool SDL_BlendLines(SDL_Surface *dst, const SDL_Point *points, int count, SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) | ||
| 946 | { | ||
| 947 | int i; | ||
| 948 | int x1, y1; | ||
| 949 | int x2, y2; | ||
| 950 | bool draw_end; | ||
| 951 | BlendLineFunc func; | ||
| 952 | |||
| 953 | if (!SDL_SurfaceValid(dst)) { | ||
| 954 | return SDL_SetError("SDL_BlendLines(): Passed NULL destination surface"); | ||
| 955 | } | ||
| 956 | |||
| 957 | func = SDL_CalculateBlendLineFunc(dst->fmt); | ||
| 958 | if (!func) { | ||
| 959 | return SDL_SetError("SDL_BlendLines(): Unsupported surface format"); | ||
| 960 | } | ||
| 961 | |||
| 962 | for (i = 1; i < count; ++i) { | ||
| 963 | x1 = points[i - 1].x; | ||
| 964 | y1 = points[i - 1].y; | ||
| 965 | x2 = points[i].x; | ||
| 966 | y2 = points[i].y; | ||
| 967 | |||
| 968 | // Perform clipping | ||
| 969 | // FIXME: We don't actually want to clip, as it may change line slope | ||
| 970 | if (!SDL_GetRectAndLineIntersection(&dst->clip_rect, &x1, &y1, &x2, &y2)) { | ||
| 971 | continue; | ||
| 972 | } | ||
| 973 | |||
| 974 | // Draw the end if it was clipped | ||
| 975 | draw_end = (x2 != points[i].x || y2 != points[i].y); | ||
| 976 | |||
| 977 | func(dst, x1, y1, x2, y2, blendMode, r, g, b, a, draw_end); | ||
| 978 | } | ||
| 979 | if (points[0].x != points[count - 1].x || points[0].y != points[count - 1].y) { | ||
| 980 | SDL_BlendPoint(dst, points[count - 1].x, points[count - 1].y, | ||
| 981 | blendMode, r, g, b, a); | ||
| 982 | } | ||
| 983 | return true; | ||
| 984 | } | ||
| 985 | |||
| 986 | #endif // SDL_VIDEO_RENDER_SW | ||
diff --git a/contrib/SDL-3.2.8/src/render/software/SDL_blendline.h b/contrib/SDL-3.2.8/src/render/software/SDL_blendline.h new file mode 100644 index 0000000..c9a8b20 --- /dev/null +++ b/contrib/SDL-3.2.8/src/render/software/SDL_blendline.h | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | /* | ||
| 2 | Simple DirectMedia Layer | ||
| 3 | Copyright (C) 1997-2025 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 | |||
| 22 | #ifndef SDL_blendline_h_ | ||
| 23 | #define SDL_blendline_h_ | ||
| 24 | |||
| 25 | #include "SDL_internal.h" | ||
| 26 | |||
| 27 | extern bool SDL_BlendLine(SDL_Surface *dst, int x1, int y1, int x2, int y2, SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a); | ||
| 28 | extern bool SDL_BlendLines(SDL_Surface *dst, const SDL_Point *points, int count, SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a); | ||
| 29 | |||
| 30 | #endif // SDL_blendline_h_ | ||
diff --git a/contrib/SDL-3.2.8/src/render/software/SDL_blendpoint.c b/contrib/SDL-3.2.8/src/render/software/SDL_blendpoint.c new file mode 100644 index 0000000..e408453 --- /dev/null +++ b/contrib/SDL-3.2.8/src/render/software/SDL_blendpoint.c | |||
| @@ -0,0 +1,376 @@ | |||
| 1 | /* | ||
| 2 | Simple DirectMedia Layer | ||
| 3 | Copyright (C) 1997-2025 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 | #ifdef SDL_VIDEO_RENDER_SW | ||
| 24 | |||
| 25 | #include "SDL_draw.h" | ||
| 26 | #include "SDL_blendpoint.h" | ||
| 27 | |||
| 28 | static bool SDL_BlendPoint_RGB555(SDL_Surface *dst, int x, int y, SDL_BlendMode blendMode, Uint8 r, | ||
| 29 | Uint8 g, Uint8 b, Uint8 a) | ||
| 30 | { | ||
| 31 | unsigned inva = 0xff - a; | ||
| 32 | |||
| 33 | switch (blendMode) { | ||
| 34 | case SDL_BLENDMODE_BLEND: | ||
| 35 | DRAW_SETPIXELXY_BLEND_RGB555(x, y); | ||
| 36 | break; | ||
| 37 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 38 | DRAW_SETPIXELXY_BLEND_CLAMPED_RGB555(x, y); | ||
| 39 | break; | ||
| 40 | case SDL_BLENDMODE_ADD: | ||
| 41 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 42 | DRAW_SETPIXELXY_ADD_RGB555(x, y); | ||
| 43 | break; | ||
| 44 | case SDL_BLENDMODE_MOD: | ||
| 45 | DRAW_SETPIXELXY_MOD_RGB555(x, y); | ||
| 46 | break; | ||
| 47 | case SDL_BLENDMODE_MUL: | ||
| 48 | DRAW_SETPIXELXY_MUL_RGB555(x, y); | ||
| 49 | break; | ||
| 50 | default: | ||
| 51 | DRAW_SETPIXELXY_RGB555(x, y); | ||
| 52 | break; | ||
| 53 | } | ||
| 54 | return true; | ||
| 55 | } | ||
| 56 | |||
| 57 | static bool SDL_BlendPoint_RGB565(SDL_Surface *dst, int x, int y, SDL_BlendMode blendMode, Uint8 r, | ||
| 58 | Uint8 g, Uint8 b, Uint8 a) | ||
| 59 | { | ||
| 60 | unsigned inva = 0xff - a; | ||
| 61 | |||
| 62 | switch (blendMode) { | ||
| 63 | case SDL_BLENDMODE_BLEND: | ||
| 64 | DRAW_SETPIXELXY_BLEND_RGB565(x, y); | ||
| 65 | break; | ||
| 66 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 67 | DRAW_SETPIXELXY_BLEND_CLAMPED_RGB565(x, y); | ||
| 68 | break; | ||
| 69 | case SDL_BLENDMODE_ADD: | ||
| 70 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 71 | DRAW_SETPIXELXY_ADD_RGB565(x, y); | ||
| 72 | break; | ||
| 73 | case SDL_BLENDMODE_MOD: | ||
| 74 | DRAW_SETPIXELXY_MOD_RGB565(x, y); | ||
| 75 | break; | ||
| 76 | case SDL_BLENDMODE_MUL: | ||
| 77 | DRAW_SETPIXELXY_MUL_RGB565(x, y); | ||
| 78 | break; | ||
| 79 | default: | ||
| 80 | DRAW_SETPIXELXY_RGB565(x, y); | ||
| 81 | break; | ||
| 82 | } | ||
| 83 | return true; | ||
| 84 | } | ||
| 85 | |||
| 86 | static bool SDL_BlendPoint_XRGB8888(SDL_Surface *dst, int x, int y, SDL_BlendMode blendMode, Uint8 r, | ||
| 87 | Uint8 g, Uint8 b, Uint8 a) | ||
| 88 | { | ||
| 89 | unsigned inva = 0xff - a; | ||
| 90 | |||
| 91 | switch (blendMode) { | ||
| 92 | case SDL_BLENDMODE_BLEND: | ||
| 93 | DRAW_SETPIXELXY_BLEND_XRGB8888(x, y); | ||
| 94 | break; | ||
| 95 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 96 | DRAW_SETPIXELXY_BLEND_CLAMPED_XRGB8888(x, y); | ||
| 97 | break; | ||
| 98 | case SDL_BLENDMODE_ADD: | ||
| 99 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 100 | DRAW_SETPIXELXY_ADD_XRGB8888(x, y); | ||
| 101 | break; | ||
| 102 | case SDL_BLENDMODE_MOD: | ||
| 103 | DRAW_SETPIXELXY_MOD_XRGB8888(x, y); | ||
| 104 | break; | ||
| 105 | case SDL_BLENDMODE_MUL: | ||
| 106 | DRAW_SETPIXELXY_MUL_XRGB8888(x, y); | ||
| 107 | break; | ||
| 108 | default: | ||
| 109 | DRAW_SETPIXELXY_XRGB8888(x, y); | ||
| 110 | break; | ||
| 111 | } | ||
| 112 | return true; | ||
| 113 | } | ||
| 114 | |||
| 115 | static bool SDL_BlendPoint_ARGB8888(SDL_Surface *dst, int x, int y, SDL_BlendMode blendMode, | ||
| 116 | Uint8 r, Uint8 g, Uint8 b, Uint8 a) | ||
| 117 | { | ||
| 118 | unsigned inva = 0xff - a; | ||
| 119 | |||
| 120 | switch (blendMode) { | ||
| 121 | case SDL_BLENDMODE_BLEND: | ||
| 122 | DRAW_SETPIXELXY_BLEND_ARGB8888(x, y); | ||
| 123 | break; | ||
| 124 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 125 | DRAW_SETPIXELXY_BLEND_CLAMPED_ARGB8888(x, y); | ||
| 126 | break; | ||
| 127 | case SDL_BLENDMODE_ADD: | ||
| 128 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 129 | DRAW_SETPIXELXY_ADD_ARGB8888(x, y); | ||
| 130 | break; | ||
| 131 | case SDL_BLENDMODE_MOD: | ||
| 132 | DRAW_SETPIXELXY_MOD_ARGB8888(x, y); | ||
| 133 | break; | ||
| 134 | case SDL_BLENDMODE_MUL: | ||
| 135 | DRAW_SETPIXELXY_MUL_ARGB8888(x, y); | ||
| 136 | break; | ||
| 137 | default: | ||
| 138 | DRAW_SETPIXELXY_ARGB8888(x, y); | ||
| 139 | break; | ||
| 140 | } | ||
| 141 | return true; | ||
| 142 | } | ||
| 143 | |||
| 144 | static bool SDL_BlendPoint_RGB(SDL_Surface *dst, int x, int y, SDL_BlendMode blendMode, Uint8 r, | ||
| 145 | Uint8 g, Uint8 b, Uint8 a) | ||
| 146 | { | ||
| 147 | const SDL_PixelFormatDetails *fmt = dst->fmt; | ||
| 148 | unsigned inva = 0xff - a; | ||
| 149 | |||
| 150 | switch (fmt->bytes_per_pixel) { | ||
| 151 | case 2: | ||
| 152 | switch (blendMode) { | ||
| 153 | case SDL_BLENDMODE_BLEND: | ||
| 154 | DRAW_SETPIXELXY2_BLEND_RGB(x, y); | ||
| 155 | break; | ||
| 156 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 157 | DRAW_SETPIXELXY2_BLEND_CLAMPED_RGB(x, y); | ||
| 158 | break; | ||
| 159 | case SDL_BLENDMODE_ADD: | ||
| 160 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 161 | DRAW_SETPIXELXY2_ADD_RGB(x, y); | ||
| 162 | break; | ||
| 163 | case SDL_BLENDMODE_MOD: | ||
| 164 | DRAW_SETPIXELXY2_MOD_RGB(x, y); | ||
| 165 | break; | ||
| 166 | case SDL_BLENDMODE_MUL: | ||
| 167 | DRAW_SETPIXELXY2_MUL_RGB(x, y); | ||
| 168 | break; | ||
| 169 | default: | ||
| 170 | DRAW_SETPIXELXY2_RGB(x, y); | ||
| 171 | break; | ||
| 172 | } | ||
| 173 | return true; | ||
| 174 | case 4: | ||
| 175 | switch (blendMode) { | ||
| 176 | case SDL_BLENDMODE_BLEND: | ||
| 177 | DRAW_SETPIXELXY4_BLEND_RGB(x, y); | ||
| 178 | break; | ||
| 179 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 180 | DRAW_SETPIXELXY4_BLEND_CLAMPED_RGB(x, y); | ||
| 181 | break; | ||
| 182 | case SDL_BLENDMODE_ADD: | ||
| 183 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 184 | DRAW_SETPIXELXY4_ADD_RGB(x, y); | ||
| 185 | break; | ||
| 186 | case SDL_BLENDMODE_MOD: | ||
| 187 | DRAW_SETPIXELXY4_MOD_RGB(x, y); | ||
| 188 | break; | ||
| 189 | case SDL_BLENDMODE_MUL: | ||
| 190 | DRAW_SETPIXELXY4_MUL_RGB(x, y); | ||
| 191 | break; | ||
| 192 | default: | ||
| 193 | DRAW_SETPIXELXY4_RGB(x, y); | ||
| 194 | break; | ||
| 195 | } | ||
| 196 | return true; | ||
| 197 | default: | ||
| 198 | return SDL_Unsupported(); | ||
| 199 | } | ||
| 200 | } | ||
| 201 | |||
| 202 | static bool SDL_BlendPoint_RGBA(SDL_Surface *dst, int x, int y, SDL_BlendMode blendMode, Uint8 r, | ||
| 203 | Uint8 g, Uint8 b, Uint8 a) | ||
| 204 | { | ||
| 205 | const SDL_PixelFormatDetails *fmt = dst->fmt; | ||
| 206 | unsigned inva = 0xff - a; | ||
| 207 | |||
| 208 | switch (fmt->bytes_per_pixel) { | ||
| 209 | case 4: | ||
| 210 | switch (blendMode) { | ||
| 211 | case SDL_BLENDMODE_BLEND: | ||
| 212 | DRAW_SETPIXELXY4_BLEND_RGBA(x, y); | ||
| 213 | break; | ||
| 214 | case SDL_BLENDMODE_BLEND_PREMULTIPLIED: | ||
| 215 | DRAW_SETPIXELXY4_BLEND_CLAMPED_RGBA(x, y); | ||
| 216 | break; | ||
| 217 | case SDL_BLENDMODE_ADD: | ||
| 218 | case SDL_BLENDMODE_ADD_PREMULTIPLIED: | ||
| 219 | DRAW_SETPIXELXY4_ADD_RGBA(x, y); | ||
| 220 | break; | ||
| 221 | case SDL_BLENDMODE_MOD: | ||
| 222 | DRAW_SETPIXELXY4_MOD_RGBA(x, y); | ||
| 223 | break; | ||
| 224 | case SDL_BLENDMODE_MUL: | ||
| 225 | DRAW_SETPIXELXY4_MUL_RGBA(x, y); | ||
| 226 | break; | ||
| 227 | default: | ||
| 228 | DRAW_SETPIXELXY4_RGBA(x, y); | ||
| 229 | break; | ||
| 230 | } | ||
| 231 | return true; | ||
| 232 | default: | ||
| 233 | return SDL_Unsupported(); | ||
| 234 | } | ||
| 235 | } | ||
| 236 | |||
| 237 | bool SDL_BlendPoint(SDL_Surface *dst, int x, int y, SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) | ||
| 238 | { | ||
| 239 | if (!SDL_SurfaceValid(dst)) { | ||
| 240 | return SDL_InvalidParamError("SDL_BlendPoint(): dst"); | ||
| 241 | } | ||
| 242 | |||
| 243 | // This function doesn't work on surfaces < 8 bpp | ||
| 244 | if (SDL_BITSPERPIXEL(dst->format) < 8) { | ||
| 245 | return SDL_SetError("SDL_BlendPoint(): Unsupported surface format"); | ||
| 246 | } | ||
| 247 | |||
| 248 | // Perform clipping | ||
| 249 | if (x < dst->clip_rect.x || y < dst->clip_rect.y || | ||
| 250 | x >= (dst->clip_rect.x + dst->clip_rect.w) || | ||
| 251 | y >= (dst->clip_rect.y + dst->clip_rect.h)) { | ||
| 252 | return true; | ||
| 253 | } | ||
| 254 | |||
| 255 | if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) { | ||
| 256 | r = DRAW_MUL(r, a); | ||
| 257 | g = DRAW_MUL(g, a); | ||
| 258 | b = DRAW_MUL(b, a); | ||
| 259 | } | ||
| 260 | |||
| 261 | switch (dst->fmt->bits_per_pixel) { | ||
| 262 | case 15: | ||
| 263 | switch (dst->fmt->Rmask) { | ||
| 264 | case 0x7C00: | ||
| 265 | return SDL_BlendPoint_RGB555(dst, x, y, blendMode, r, g, b, a); | ||
| 266 | } | ||
| 267 | break; | ||
| 268 | case 16: | ||
| 269 | switch (dst->fmt->Rmask) { | ||
| 270 | case 0xF800: | ||
| 271 | return SDL_BlendPoint_RGB565(dst, x, y, blendMode, r, g, b, a); | ||
| 272 | } | ||
| 273 | break; | ||
| 274 | case 32: | ||
| 275 | switch (dst->fmt->Rmask) { | ||
| 276 | case 0x00FF0000: | ||
| 277 | if (!dst->fmt->Amask) { | ||
| 278 | return SDL_BlendPoint_XRGB8888(dst, x, y, blendMode, r, g, b, a); | ||
| 279 | } else { | ||
| 280 | return SDL_BlendPoint_ARGB8888(dst, x, y, blendMode, r, g, b, a); | ||
| 281 | } | ||
| 282 | // break; -Wunreachable-code-break | ||
| 283 | } | ||
| 284 | break; | ||
| 285 | default: | ||
| 286 | break; | ||
| 287 | } | ||
| 288 | |||
| 289 | if (!dst->fmt->Amask) { | ||
| 290 | return SDL_BlendPoint_RGB(dst, x, y, blendMode, r, g, b, a); | ||
| 291 | } else { | ||
| 292 | return SDL_BlendPoint_RGBA(dst, x, y, blendMode, r, g, b, a); | ||
| 293 | } | ||
| 294 | } | ||
| 295 | |||
| 296 | bool SDL_BlendPoints(SDL_Surface *dst, const SDL_Point *points, int count, SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) | ||
| 297 | { | ||
| 298 | int minx, miny; | ||
| 299 | int maxx, maxy; | ||
| 300 | int i; | ||
| 301 | int x, y; | ||
| 302 | bool (*func)(SDL_Surface * dst, int x, int y, SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) = NULL; | ||
| 303 | bool result = true; | ||
| 304 | |||
| 305 | if (!SDL_SurfaceValid(dst)) { | ||
| 306 | return SDL_InvalidParamError("SDL_BlendPoints(): dst"); | ||
| 307 | } | ||
| 308 | |||
| 309 | // This function doesn't work on surfaces < 8 bpp | ||
| 310 | if (dst->fmt->bits_per_pixel < 8) { | ||
| 311 | return SDL_SetError("SDL_BlendPoints(): Unsupported surface format"); | ||
| 312 | } | ||
| 313 | |||
| 314 | if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) { | ||
| 315 | r = DRAW_MUL(r, a); | ||
| 316 | g = DRAW_MUL(g, a); | ||
| 317 | b = DRAW_MUL(b, a); | ||
| 318 | } | ||
| 319 | |||
| 320 | // FIXME: Does this function pointer slow things down significantly? | ||
| 321 | switch (dst->fmt->bits_per_pixel) { | ||
| 322 | case 15: | ||
| 323 | switch (dst->fmt->Rmask) { | ||
| 324 | case 0x7C00: | ||
| 325 | func = SDL_BlendPoint_RGB555; | ||
| 326 | break; | ||
| 327 | } | ||
| 328 | break; | ||
| 329 | case 16: | ||
| 330 | switch (dst->fmt->Rmask) { | ||
| 331 | case 0xF800: | ||
| 332 | func = SDL_BlendPoint_RGB565; | ||
| 333 | break; | ||
| 334 | } | ||
| 335 | break; | ||
| 336 | case 32: | ||
| 337 | switch (dst->fmt->Rmask) { | ||
| 338 | case 0x00FF0000: | ||
| 339 | if (!dst->fmt->Amask) { | ||
| 340 | func = SDL_BlendPoint_XRGB8888; | ||
| 341 | } else { | ||
| 342 | func = SDL_BlendPoint_ARGB8888; | ||
| 343 | } | ||
| 344 | break; | ||
| 345 | } | ||
| 346 | break; | ||
| 347 | default: | ||
| 348 | break; | ||
| 349 | } | ||
| 350 | |||
| 351 | if (!func) { | ||
| 352 | if (!dst->fmt->Amask) { | ||
| 353 | func = SDL_BlendPoint_RGB; | ||
| 354 | } else { | ||
| 355 | func = SDL_BlendPoint_RGBA; | ||
| 356 | } | ||
| 357 | } | ||
| 358 | |||
| 359 | minx = dst->clip_rect.x; | ||
| 360 | maxx = dst->clip_rect.x + dst->clip_rect.w - 1; | ||
| 361 | miny = dst->clip_rect.y; | ||
| 362 | maxy = dst->clip_rect.y + dst->clip_rect.h - 1; | ||
| 363 | |||
| 364 | for (i = 0; i < count; ++i) { | ||
| 365 | x = points[i].x; | ||
| 366 | y = points[i].y; | ||
| 367 | |||
| 368 | if (x < minx || x > maxx || y < miny || y > maxy) { | ||
| 369 | continue; | ||
| 370 | } | ||
| 371 | result = func(dst, x, y, blendMode, r, g, b, a); | ||
| 372 | } | ||
| 373 | return result; | ||
| 374 | } | ||
| 375 | |||
| 376 | #endif // SDL_VIDEO_RENDER_SW | ||
diff --git a/contrib/SDL-3.2.8/src/render/software/SDL_blendpoint.h b/contrib/SDL-3.2.8/src/render/software/SDL_blendpoint.h new file mode 100644 index 0000000..6dfe49a --- /dev/null +++ b/contrib/SDL-3.2.8/src/render/software/SDL_blendpoint.h | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | /* | ||
| 2 | Simple DirectMedia Layer | ||
| 3 | Copyright (C) 1997-2025 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 | |||
| 22 | #ifndef SDL_blendpoint_h_ | ||
| 23 | #define SDL_blendpoint_h_ | ||
| 24 | |||
| 25 | #include "SDL_internal.h" | ||
| 26 | |||
| 27 | extern bool SDL_BlendPoint(SDL_Surface *dst, int x, int y, SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a); | ||
| 28 | extern bool SDL_BlendPoints(SDL_Surface *dst, const SDL_Point *points, int count, SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a); | ||
| 29 | |||
| 30 | #endif // SDL_blendpoint_h_ | ||
diff --git a/contrib/SDL-3.2.8/src/render/software/SDL_draw.h b/contrib/SDL-3.2.8/src/render/software/SDL_draw.h new file mode 100644 index 0000000..ec77527 --- /dev/null +++ b/contrib/SDL-3.2.8/src/render/software/SDL_draw.h | |||
| @@ -0,0 +1,723 @@ | |||
| 1 | /* | ||
| 2 | Simple DirectMedia Layer | ||
| 3 | Copyright (C) 1997-2025 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 | #include "../../video/SDL_surface_c.h" | ||
| 24 | |||
| 25 | /* This code assumes that r, g, b, a are the source color, | ||
| 26 | * and in the blend and add case, the RGB values are premultiplied by a. | ||
| 27 | */ | ||
| 28 | |||
| 29 | #define DRAW_MUL(_a, _b) (((unsigned)(_a) * (_b)) / 255) | ||
| 30 | |||
| 31 | #define DRAW_FASTSETPIXEL(type) \ | ||
| 32 | *pixel = (type)color | ||
| 33 | |||
| 34 | #define DRAW_FASTSETPIXEL1 DRAW_FASTSETPIXEL(Uint8) | ||
| 35 | #define DRAW_FASTSETPIXEL2 DRAW_FASTSETPIXEL(Uint16) | ||
| 36 | #define DRAW_FASTSETPIXEL4 DRAW_FASTSETPIXEL(Uint32) | ||
| 37 | |||
| 38 | #define DRAW_FASTSETPIXELXY(x, y, type, bpp, color) \ | ||
| 39 | *(type *)((Uint8 *)dst->pixels + (y)*dst->pitch + (x)*bpp) = (type)color | ||
| 40 | |||
| 41 | #define DRAW_FASTSETPIXELXY1(x, y) DRAW_FASTSETPIXELXY(x, y, Uint8, 1, color) | ||
| 42 | #define DRAW_FASTSETPIXELXY2(x, y) DRAW_FASTSETPIXELXY(x, y, Uint16, 2, color) | ||
| 43 | #define DRAW_FASTSETPIXELXY4(x, y) DRAW_FASTSETPIXELXY(x, y, Uint32, 4, color) | ||
| 44 | |||
| 45 | #define DRAW_SETPIXEL(setpixel) \ | ||
| 46 | do { \ | ||
| 47 | unsigned sr = r, sg = g, sb = b, sa = a; \ | ||
| 48 | (void)sa; \ | ||
| 49 | setpixel; \ | ||
| 50 | } while (0) | ||
| 51 | |||
| 52 | #define DRAW_SETPIXEL_BLEND(getpixel, setpixel) \ | ||
| 53 | do { \ | ||
| 54 | unsigned sr, sg, sb, sa = 0xFF; \ | ||
| 55 | getpixel; \ | ||
| 56 | sr = DRAW_MUL(inva, sr) + r; \ | ||
| 57 | sg = DRAW_MUL(inva, sg) + g; \ | ||
| 58 | sb = DRAW_MUL(inva, sb) + b; \ | ||
| 59 | sa = DRAW_MUL(inva, sa) + a; \ | ||
| 60 | setpixel; \ | ||
| 61 | } while (0) | ||
| 62 | |||
| 63 | #define DRAW_SETPIXEL_BLEND_CLAMPED(getpixel, setpixel) \ | ||
| 64 | do { \ | ||
| 65 | unsigned sr, sg, sb, sa = 0xFF; \ | ||
| 66 | getpixel; \ | ||
| 67 | sr = DRAW_MUL(inva, sr) + r; \ | ||
| 68 | if (sr > 0xff) \ | ||
| 69 | sr = 0xff; \ | ||
| 70 | sg = DRAW_MUL(inva, sg) + g; \ | ||
| 71 | if (sg > 0xff) \ | ||
| 72 | sg = 0xff; \ | ||
| 73 | sb = DRAW_MUL(inva, sb) + b; \ | ||
| 74 | if (sb > 0xff) \ | ||
| 75 | sb = 0xff; \ | ||
| 76 | sa = DRAW_MUL(inva, sa) + a; \ | ||
| 77 | if (sa > 0xff) \ | ||
| 78 | sa = 0xff; \ | ||
| 79 | setpixel; \ | ||
| 80 | } while (0) | ||
| 81 | |||
| 82 | #define DRAW_SETPIXEL_ADD(getpixel, setpixel) \ | ||
| 83 | do { \ | ||
| 84 | unsigned sr, sg, sb, sa; \ | ||
| 85 | (void)sa; \ | ||
| 86 | getpixel; \ | ||
| 87 | sr += r; \ | ||
| 88 | if (sr > 0xff) \ | ||
| 89 | sr = 0xff; \ | ||
| 90 | sg += g; \ | ||
| 91 | if (sg > 0xff) \ | ||
| 92 | sg = 0xff; \ | ||
| 93 | sb += b; \ | ||
| 94 | if (sb > 0xff) \ | ||
| 95 | sb = 0xff; \ | ||
| 96 | setpixel; \ | ||
| 97 | } while (0) | ||
| 98 | |||
| 99 | #define DRAW_SETPIXEL_MOD(getpixel, setpixel) \ | ||
| 100 | do { \ | ||
| 101 | unsigned sr, sg, sb, sa; \ | ||
| 102 | (void)sa; \ | ||
| 103 | getpixel; \ | ||
| 104 | sr = DRAW_MUL(sr, r); \ | ||
| 105 | sg = DRAW_MUL(sg, g); \ | ||
| 106 | sb = DRAW_MUL(sb, b); \ | ||
| 107 | setpixel; \ | ||
| 108 | } while (0) | ||
| 109 | |||
| 110 | #define DRAW_SETPIXEL_MUL(getpixel, setpixel) \ | ||
| 111 | do { \ | ||
| 112 | unsigned sr, sg, sb, sa; \ | ||
| 113 | (void)sa; \ | ||
| 114 | getpixel; \ | ||
| 115 | sr = DRAW_MUL(sr, r) + DRAW_MUL(inva, sr); \ | ||
| 116 | if (sr > 0xff) \ | ||
| 117 | sr = 0xff; \ | ||
| 118 | sg = DRAW_MUL(sg, g) + DRAW_MUL(inva, sg); \ | ||
| 119 | if (sg > 0xff) \ | ||
| 120 | sg = 0xff; \ | ||
| 121 | sb = DRAW_MUL(sb, b) + DRAW_MUL(inva, sb); \ | ||
| 122 | if (sb > 0xff) \ | ||
| 123 | sb = 0xff; \ | ||
| 124 | setpixel; \ | ||
| 125 | } while (0) | ||
| 126 | |||
| 127 | #define DRAW_SETPIXELXY(x, y, type, bpp, op) \ | ||
| 128 | do { \ | ||
| 129 | type *pixel = (type *)((Uint8 *)dst->pixels + (y)*dst->pitch + (x)*bpp); \ | ||
| 130 | op; \ | ||
| 131 | } while (0) | ||
| 132 | |||
| 133 | /* | ||
| 134 | * Define draw operators for RGB555 | ||
| 135 | */ | ||
| 136 | |||
| 137 | #define DRAW_SETPIXEL_RGB555 \ | ||
| 138 | DRAW_SETPIXEL(RGB555_FROM_RGB(*pixel, sr, sg, sb)) | ||
| 139 | |||
| 140 | #define DRAW_SETPIXEL_BLEND_RGB555 \ | ||
| 141 | DRAW_SETPIXEL_BLEND(RGB_FROM_RGB555(*pixel, sr, sg, sb), \ | ||
| 142 | RGB555_FROM_RGB(*pixel, sr, sg, sb)) | ||
| 143 | |||
| 144 | #define DRAW_SETPIXEL_BLEND_CLAMPED_RGB555 \ | ||
| 145 | DRAW_SETPIXEL_BLEND_CLAMPED(RGB_FROM_RGB555(*pixel, sr, sg, sb), \ | ||
| 146 | RGB555_FROM_RGB(*pixel, sr, sg, sb)) | ||
| 147 | |||
| 148 | #define DRAW_SETPIXEL_ADD_RGB555 \ | ||
| 149 | DRAW_SETPIXEL_ADD(RGB_FROM_RGB555(*pixel, sr, sg, sb), \ | ||
| 150 | RGB555_FROM_RGB(*pixel, sr, sg, sb)) | ||
| 151 | |||
| 152 | #define DRAW_SETPIXEL_MOD_RGB555 \ | ||
| 153 | DRAW_SETPIXEL_MOD(RGB_FROM_RGB555(*pixel, sr, sg, sb), \ | ||
| 154 | RGB555_FROM_RGB(*pixel, sr, sg, sb)) | ||
| 155 | |||
| 156 | #define DRAW_SETPIXEL_MUL_RGB555 \ | ||
| 157 | DRAW_SETPIXEL_MUL(RGB_FROM_RGB555(*pixel, sr, sg, sb), \ | ||
| 158 | RGB555_FROM_RGB(*pixel, sr, sg, sb)) | ||
| 159 | |||
| 160 | #define DRAW_SETPIXELXY_RGB555(x, y) \ | ||
| 161 | DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_RGB555) | ||
| 162 | |||
| 163 | #define DRAW_SETPIXELXY_BLEND_RGB555(x, y) \ | ||
| 164 | DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_BLEND_RGB555) | ||
| 165 | |||
| 166 | #define DRAW_SETPIXELXY_BLEND_CLAMPED_RGB555(x, y) \ | ||
| 167 | DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_BLEND_CLAMPED_RGB555) | ||
| 168 | |||
| 169 | #define DRAW_SETPIXELXY_ADD_RGB555(x, y) \ | ||
| 170 | DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_ADD_RGB555) | ||
| 171 | |||
| 172 | #define DRAW_SETPIXELXY_MOD_RGB555(x, y) \ | ||
| 173 | DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_MOD_RGB555) | ||
| 174 | |||
| 175 | #define DRAW_SETPIXELXY_MUL_RGB555(x, y) \ | ||
| 176 | DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_MUL_RGB555) | ||
| 177 | |||
| 178 | /* | ||
| 179 | * Define draw operators for RGB565 | ||
| 180 | */ | ||
| 181 | |||
| 182 | #define DRAW_SETPIXEL_RGB565 \ | ||
| 183 | DRAW_SETPIXEL(RGB565_FROM_RGB(*pixel, sr, sg, sb)) | ||
| 184 | |||
| 185 | #define DRAW_SETPIXEL_BLEND_RGB565 \ | ||
| 186 | DRAW_SETPIXEL_BLEND(RGB_FROM_RGB565(*pixel, sr, sg, sb), \ | ||
| 187 | RGB565_FROM_RGB(*pixel, sr, sg, sb)) | ||
| 188 | |||
| 189 | #define DRAW_SETPIXEL_BLEND_CLAMPED_RGB565 \ | ||
| 190 | DRAW_SETPIXEL_BLEND_CLAMPED(RGB_FROM_RGB565(*pixel, sr, sg, sb), \ | ||
| 191 | RGB565_FROM_RGB(*pixel, sr, sg, sb)) | ||
| 192 | |||
| 193 | #define DRAW_SETPIXEL_ADD_RGB565 \ | ||
| 194 | DRAW_SETPIXEL_ADD(RGB_FROM_RGB565(*pixel, sr, sg, sb), \ | ||
| 195 | RGB565_FROM_RGB(*pixel, sr, sg, sb)) | ||
| 196 | |||
| 197 | #define DRAW_SETPIXEL_MOD_RGB565 \ | ||
| 198 | DRAW_SETPIXEL_MOD(RGB_FROM_RGB565(*pixel, sr, sg, sb), \ | ||
| 199 | RGB565_FROM_RGB(*pixel, sr, sg, sb)) | ||
| 200 | |||
| 201 | #define DRAW_SETPIXEL_MUL_RGB565 \ | ||
| 202 | DRAW_SETPIXEL_MUL(RGB_FROM_RGB565(*pixel, sr, sg, sb), \ | ||
| 203 | RGB565_FROM_RGB(*pixel, sr, sg, sb)) | ||
| 204 | |||
| 205 | #define DRAW_SETPIXELXY_RGB565(x, y) \ | ||
| 206 | DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_RGB565) | ||
| 207 | |||
| 208 | #define DRAW_SETPIXELXY_BLEND_RGB565(x, y) \ | ||
| 209 | DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_BLEND_RGB565) | ||
| 210 | |||
| 211 | #define DRAW_SETPIXELXY_BLEND_CLAMPED_RGB565(x, y) \ | ||
| 212 | DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_BLEND_CLAMPED_RGB565) | ||
| 213 | |||
| 214 | #define DRAW_SETPIXELXY_ADD_RGB565(x, y) \ | ||
| 215 | DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_ADD_RGB565) | ||
| 216 | |||
| 217 | #define DRAW_SETPIXELXY_MOD_RGB565(x, y) \ | ||
| 218 | DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_MOD_RGB565) | ||
| 219 | |||
| 220 | #define DRAW_SETPIXELXY_MUL_RGB565(x, y) \ | ||
| 221 | DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_MUL_RGB565) | ||
| 222 | |||
| 223 | /* | ||
| 224 | * Define draw operators for RGB888 | ||
| 225 | */ | ||
| 226 | |||
| 227 | #define DRAW_SETPIXEL_XRGB8888 \ | ||
| 228 | DRAW_SETPIXEL(XRGB8888_FROM_RGB(*pixel, sr, sg, sb)) | ||
| 229 | |||
| 230 | #define DRAW_SETPIXEL_BLEND_XRGB8888 \ | ||
| 231 | DRAW_SETPIXEL_BLEND(RGB_FROM_XRGB8888(*pixel, sr, sg, sb), \ | ||
| 232 | XRGB8888_FROM_RGB(*pixel, sr, sg, sb)) | ||
| 233 | |||
| 234 | #define DRAW_SETPIXEL_BLEND_CLAMPED_XRGB8888 \ | ||
| 235 | DRAW_SETPIXEL_BLEND_CLAMPED(RGB_FROM_XRGB8888(*pixel, sr, sg, sb), \ | ||
| 236 | XRGB8888_FROM_RGB(*pixel, sr, sg, sb)) | ||
| 237 | |||
| 238 | #define DRAW_SETPIXEL_ADD_XRGB8888 \ | ||
| 239 | DRAW_SETPIXEL_ADD(RGB_FROM_XRGB8888(*pixel, sr, sg, sb), \ | ||
| 240 | XRGB8888_FROM_RGB(*pixel, sr, sg, sb)) | ||
| 241 | |||
| 242 | #define DRAW_SETPIXEL_MOD_XRGB8888 \ | ||
| 243 | DRAW_SETPIXEL_MOD(RGB_FROM_XRGB8888(*pixel, sr, sg, sb), \ | ||
| 244 | XRGB8888_FROM_RGB(*pixel, sr, sg, sb)) | ||
| 245 | |||
| 246 | #define DRAW_SETPIXEL_MUL_XRGB8888 \ | ||
| 247 | DRAW_SETPIXEL_MUL(RGB_FROM_XRGB8888(*pixel, sr, sg, sb), \ | ||
| 248 | XRGB8888_FROM_RGB(*pixel, sr, sg, sb)) | ||
| 249 | |||
| 250 | #define DRAW_SETPIXELXY_XRGB8888(x, y) \ | ||
| 251 | DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_XRGB8888) | ||
| 252 | |||
| 253 | #define DRAW_SETPIXELXY_BLEND_XRGB8888(x, y) \ | ||
| 254 | DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_BLEND_XRGB8888) | ||
| 255 | |||
| 256 | #define DRAW_SETPIXELXY_BLEND_CLAMPED_XRGB8888(x, y) \ | ||
| 257 | DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_BLEND_CLAMPED_XRGB8888) | ||
| 258 | |||
| 259 | #define DRAW_SETPIXELXY_ADD_XRGB8888(x, y) \ | ||
| 260 | DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_ADD_XRGB8888) | ||
| 261 | |||
| 262 | #define DRAW_SETPIXELXY_MOD_XRGB8888(x, y) \ | ||
| 263 | DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_MOD_XRGB8888) | ||
| 264 | |||
| 265 | #define DRAW_SETPIXELXY_MUL_XRGB8888(x, y) \ | ||
| 266 | DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_MUL_XRGB8888) | ||
| 267 | |||
| 268 | /* | ||
| 269 | * Define draw operators for ARGB8888 | ||
| 270 | */ | ||
| 271 | |||
| 272 | #define DRAW_SETPIXEL_ARGB8888 \ | ||
| 273 | DRAW_SETPIXEL(ARGB8888_FROM_RGBA(*pixel, sr, sg, sb, sa)) | ||
| 274 | |||
| 275 | #define DRAW_SETPIXEL_BLEND_ARGB8888 \ | ||
| 276 | DRAW_SETPIXEL_BLEND(RGBA_FROM_ARGB8888(*pixel, sr, sg, sb, sa), \ | ||
| 277 | ARGB8888_FROM_RGBA(*pixel, sr, sg, sb, sa)) | ||
| 278 | |||
| 279 | #define DRAW_SETPIXEL_BLEND_CLAMPED_ARGB8888 \ | ||
| 280 | DRAW_SETPIXEL_BLEND_CLAMPED(RGBA_FROM_ARGB8888(*pixel, sr, sg, sb, sa), \ | ||
| 281 | ARGB8888_FROM_RGBA(*pixel, sr, sg, sb, sa)) | ||
| 282 | |||
| 283 | #define DRAW_SETPIXEL_ADD_ARGB8888 \ | ||
| 284 | DRAW_SETPIXEL_ADD(RGBA_FROM_ARGB8888(*pixel, sr, sg, sb, sa), \ | ||
| 285 | ARGB8888_FROM_RGBA(*pixel, sr, sg, sb, sa)) | ||
| 286 | |||
| 287 | #define DRAW_SETPIXEL_MOD_ARGB8888 \ | ||
| 288 | DRAW_SETPIXEL_MOD(RGBA_FROM_ARGB8888(*pixel, sr, sg, sb, sa), \ | ||
| 289 | ARGB8888_FROM_RGBA(*pixel, sr, sg, sb, sa)) | ||
| 290 | |||
| 291 | #define DRAW_SETPIXEL_MUL_ARGB8888 \ | ||
| 292 | DRAW_SETPIXEL_MUL(RGBA_FROM_ARGB8888(*pixel, sr, sg, sb, sa), \ | ||
| 293 | ARGB8888_FROM_RGBA(*pixel, sr, sg, sb, sa)) | ||
| 294 | |||
| 295 | #define DRAW_SETPIXELXY_ARGB8888(x, y) \ | ||
| 296 | DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_ARGB8888) | ||
| 297 | |||
| 298 | #define DRAW_SETPIXELXY_BLEND_ARGB8888(x, y) \ | ||
| 299 | DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_BLEND_ARGB8888) | ||
| 300 | |||
| 301 | #define DRAW_SETPIXELXY_BLEND_CLAMPED_ARGB8888(x, y) \ | ||
| 302 | DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_BLEND_CLAMPED_ARGB8888) | ||
| 303 | |||
| 304 | #define DRAW_SETPIXELXY_ADD_ARGB8888(x, y) \ | ||
| 305 | DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_ADD_ARGB8888) | ||
| 306 | |||
| 307 | #define DRAW_SETPIXELXY_MOD_ARGB8888(x, y) \ | ||
| 308 | DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_MOD_ARGB8888) | ||
| 309 | |||
| 310 | #define DRAW_SETPIXELXY_MUL_ARGB8888(x, y) \ | ||
| 311 | DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_MUL_ARGB8888) | ||
| 312 | |||
| 313 | /* | ||
| 314 | * Define draw operators for general RGB | ||
| 315 | */ | ||
| 316 | |||
| 317 | #define DRAW_SETPIXEL_RGB \ | ||
| 318 | DRAW_SETPIXEL(PIXEL_FROM_RGB(*pixel, fmt, sr, sg, sb)) | ||
| 319 | |||
| 320 | #define DRAW_SETPIXEL_BLEND_RGB \ | ||
| 321 | DRAW_SETPIXEL_BLEND(RGB_FROM_PIXEL(*pixel, fmt, sr, sg, sb), \ | ||
| 322 | PIXEL_FROM_RGB(*pixel, fmt, sr, sg, sb)) | ||
| 323 | |||
| 324 | #define DRAW_SETPIXEL_BLEND_CLAMPED_RGB \ | ||
| 325 | DRAW_SETPIXEL_BLEND_CLAMPED(RGB_FROM_PIXEL(*pixel, fmt, sr, sg, sb), \ | ||
| 326 | PIXEL_FROM_RGB(*pixel, fmt, sr, sg, sb)) | ||
| 327 | |||
| 328 | #define DRAW_SETPIXEL_ADD_RGB \ | ||
| 329 | DRAW_SETPIXEL_ADD(RGB_FROM_PIXEL(*pixel, fmt, sr, sg, sb), \ | ||
| 330 | PIXEL_FROM_RGB(*pixel, fmt, sr, sg, sb)) | ||
| 331 | |||
| 332 | #define DRAW_SETPIXEL_MOD_RGB \ | ||
| 333 | DRAW_SETPIXEL_MOD(RGB_FROM_PIXEL(*pixel, fmt, sr, sg, sb), \ | ||
| 334 | PIXEL_FROM_RGB(*pixel, fmt, sr, sg, sb)) | ||
| 335 | |||
| 336 | #define DRAW_SETPIXEL_MUL_RGB \ | ||
| 337 | DRAW_SETPIXEL_MUL(RGB_FROM_PIXEL(*pixel, fmt, sr, sg, sb), \ | ||
| 338 | PIXEL_FROM_RGB(*pixel, fmt, sr, sg, sb)) | ||
| 339 | |||
| 340 | #define DRAW_SETPIXELXY2_RGB(x, y) \ | ||
| 341 | DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_RGB) | ||
| 342 | |||
| 343 | #define DRAW_SETPIXELXY4_RGB(x, y) \ | ||
| 344 | DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_RGB) | ||
| 345 | |||
| 346 | #define DRAW_SETPIXELXY2_BLEND_RGB(x, y) \ | ||
| 347 | DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_BLEND_RGB) | ||
| 348 | |||
| 349 | #define DRAW_SETPIXELXY2_BLEND_CLAMPED_RGB(x, y) \ | ||
| 350 | DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_BLEND_CLAMPED_RGB) | ||
| 351 | |||
| 352 | #define DRAW_SETPIXELXY4_BLEND_RGB(x, y) \ | ||
| 353 | DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_BLEND_RGB) | ||
| 354 | |||
| 355 | #define DRAW_SETPIXELXY4_BLEND_CLAMPED_RGB(x, y) \ | ||
| 356 | DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_BLEND_CLAMPED_RGB) | ||
| 357 | |||
| 358 | #define DRAW_SETPIXELXY2_ADD_RGB(x, y) \ | ||
| 359 | DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_ADD_RGB) | ||
| 360 | |||
| 361 | #define DRAW_SETPIXELXY4_ADD_RGB(x, y) \ | ||
| 362 | DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_ADD_RGB) | ||
| 363 | |||
| 364 | #define DRAW_SETPIXELXY2_MOD_RGB(x, y) \ | ||
| 365 | DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_MOD_RGB) | ||
| 366 | |||
| 367 | #define DRAW_SETPIXELXY4_MOD_RGB(x, y) \ | ||
| 368 | DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_MOD_RGB) | ||
| 369 | |||
| 370 | #define DRAW_SETPIXELXY2_MUL_RGB(x, y) \ | ||
| 371 | DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_MUL_RGB) | ||
| 372 | |||
| 373 | #define DRAW_SETPIXELXY4_MUL_RGB(x, y) \ | ||
| 374 | DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_MUL_RGB) | ||
| 375 | |||
| 376 | /* | ||
| 377 | * Define draw operators for general RGBA | ||
| 378 | */ | ||
| 379 | |||
| 380 | #define DRAW_SETPIXEL_RGBA \ | ||
| 381 | DRAW_SETPIXEL(PIXEL_FROM_RGBA(*pixel, fmt, sr, sg, sb, sa)) | ||
| 382 | |||
| 383 | #define DRAW_SETPIXEL_BLEND_RGBA \ | ||
| 384 | DRAW_SETPIXEL_BLEND(RGBA_FROM_PIXEL(*pixel, fmt, sr, sg, sb, sa), \ | ||
| 385 | PIXEL_FROM_RGBA(*pixel, fmt, sr, sg, sb, sa)) | ||
| 386 | |||
| 387 | #define DRAW_SETPIXEL_BLEND_CLAMPED_RGBA \ | ||
| 388 | DRAW_SETPIXEL_BLEND_CLAMPED(RGBA_FROM_PIXEL(*pixel, fmt, sr, sg, sb, sa), \ | ||
| 389 | PIXEL_FROM_RGBA(*pixel, fmt, sr, sg, sb, sa)) | ||
| 390 | |||
| 391 | #define DRAW_SETPIXEL_ADD_RGBA \ | ||
| 392 | DRAW_SETPIXEL_ADD(RGBA_FROM_PIXEL(*pixel, fmt, sr, sg, sb, sa), \ | ||
| 393 | PIXEL_FROM_RGBA(*pixel, fmt, sr, sg, sb, sa)) | ||
| 394 | |||
| 395 | #define DRAW_SETPIXEL_MOD_RGBA \ | ||
| 396 | DRAW_SETPIXEL_MOD(RGBA_FROM_PIXEL(*pixel, fmt, sr, sg, sb, sa), \ | ||
| 397 | PIXEL_FROM_RGBA(*pixel, fmt, sr, sg, sb, sa)) | ||
| 398 | |||
| 399 | #define DRAW_SETPIXEL_MUL_RGBA \ | ||
| 400 | DRAW_SETPIXEL_MUL(RGBA_FROM_PIXEL(*pixel, fmt, sr, sg, sb, sa), \ | ||
| 401 | PIXEL_FROM_RGBA(*pixel, fmt, sr, sg, sb, sa)) | ||
| 402 | |||
| 403 | #define DRAW_SETPIXELXY4_RGBA(x, y) \ | ||
| 404 | DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_RGBA) | ||
| 405 | |||
| 406 | #define DRAW_SETPIXELXY4_BLEND_RGBA(x, y) \ | ||
| 407 | DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_BLEND_RGBA) | ||
| 408 | |||
| 409 | #define DRAW_SETPIXELXY4_BLEND_CLAMPED_RGBA(x, y) \ | ||
| 410 | DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_BLEND_CLAMPED_RGBA) | ||
| 411 | |||
| 412 | #define DRAW_SETPIXELXY4_ADD_RGBA(x, y) \ | ||
| 413 | DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_ADD_RGBA) | ||
| 414 | |||
| 415 | #define DRAW_SETPIXELXY4_MOD_RGBA(x, y) \ | ||
| 416 | DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_MOD_RGBA) | ||
| 417 | |||
| 418 | #define DRAW_SETPIXELXY4_MUL_RGBA(x, y) \ | ||
| 419 | DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_MUL_RGBA) | ||
| 420 | |||
| 421 | /* | ||
| 422 | * Define line drawing macro | ||
| 423 | */ | ||
| 424 | |||
| 425 | #define ABS(_x) ((_x) < 0 ? -(_x) : (_x)) | ||
| 426 | |||
| 427 | // Horizontal line | ||
| 428 | #define HLINE(type, op, draw_end) \ | ||
| 429 | { \ | ||
| 430 | int length; \ | ||
| 431 | int pitch = (dst->pitch / dst->fmt->bytes_per_pixel); \ | ||
| 432 | type *pixel; \ | ||
| 433 | if (x1 <= x2) { \ | ||
| 434 | pixel = (type *)dst->pixels + y1 * pitch + x1; \ | ||
| 435 | length = draw_end ? (x2 - x1 + 1) : (x2 - x1); \ | ||
| 436 | } else { \ | ||
| 437 | pixel = (type *)dst->pixels + y1 * pitch + x2; \ | ||
| 438 | if (!draw_end) { \ | ||
| 439 | ++pixel; \ | ||
| 440 | } \ | ||
| 441 | length = draw_end ? (x1 - x2 + 1) : (x1 - x2); \ | ||
| 442 | } \ | ||
| 443 | while (length--) { \ | ||
| 444 | op; \ | ||
| 445 | ++pixel; \ | ||
| 446 | } \ | ||
| 447 | } | ||
| 448 | |||
| 449 | // Vertical line | ||
| 450 | #define VLINE(type, op, draw_end) \ | ||
| 451 | { \ | ||
| 452 | int length; \ | ||
| 453 | int pitch = (dst->pitch / dst->fmt->bytes_per_pixel); \ | ||
| 454 | type *pixel; \ | ||
| 455 | if (y1 <= y2) { \ | ||
| 456 | pixel = (type *)dst->pixels + y1 * pitch + x1; \ | ||
| 457 | length = draw_end ? (y2 - y1 + 1) : (y2 - y1); \ | ||
| 458 | } else { \ | ||
| 459 | pixel = (type *)dst->pixels + y2 * pitch + x1; \ | ||
| 460 | if (!draw_end) { \ | ||
| 461 | pixel += pitch; \ | ||
| 462 | } \ | ||
| 463 | length = draw_end ? (y1 - y2 + 1) : (y1 - y2); \ | ||
| 464 | } \ | ||
| 465 | while (length--) { \ | ||
| 466 | op; \ | ||
| 467 | pixel += pitch; \ | ||
| 468 | } \ | ||
| 469 | } | ||
| 470 | |||
| 471 | // Diagonal line | ||
| 472 | #define DLINE(type, op, draw_end) \ | ||
| 473 | { \ | ||
| 474 | int length; \ | ||
| 475 | int pitch = (dst->pitch / dst->fmt->bytes_per_pixel); \ | ||
| 476 | type *pixel; \ | ||
| 477 | if (y1 <= y2) { \ | ||
| 478 | pixel = (type *)dst->pixels + y1 * pitch + x1; \ | ||
| 479 | if (x1 <= x2) { \ | ||
| 480 | ++pitch; \ | ||
| 481 | } else { \ | ||
| 482 | --pitch; \ | ||
| 483 | } \ | ||
| 484 | length = (y2 - y1); \ | ||
| 485 | } else { \ | ||
| 486 | pixel = (type *)dst->pixels + y2 * pitch + x2; \ | ||
| 487 | if (x2 <= x1) { \ | ||
| 488 | ++pitch; \ | ||
| 489 | } else { \ | ||
| 490 | --pitch; \ | ||
| 491 | } \ | ||
| 492 | if (!draw_end) { \ | ||
| 493 | pixel += pitch; \ | ||
| 494 | } \ | ||
| 495 | length = (y1 - y2); \ | ||
| 496 | } \ | ||
| 497 | if (draw_end) { \ | ||
| 498 | ++length; \ | ||
| 499 | } \ | ||
| 500 | while (length--) { \ | ||
| 501 | op; \ | ||
| 502 | pixel += pitch; \ | ||
| 503 | } \ | ||
| 504 | } | ||
| 505 | |||
| 506 | // Bresenham's line algorithm | ||
| 507 | #define BLINE(x1, y1, x2, y2, op, draw_end) \ | ||
| 508 | { \ | ||
| 509 | int i, deltax, deltay, numpixels; \ | ||
| 510 | int d, dinc1, dinc2; \ | ||
| 511 | int x, xinc1, xinc2; \ | ||
| 512 | int y, yinc1, yinc2; \ | ||
| 513 | \ | ||
| 514 | deltax = ABS(x2 - x1); \ | ||
| 515 | deltay = ABS(y2 - y1); \ | ||
| 516 | \ | ||
| 517 | if (deltax >= deltay) { \ | ||
| 518 | numpixels = deltax + 1; \ | ||
| 519 | d = (2 * deltay) - deltax; \ | ||
| 520 | dinc1 = deltay * 2; \ | ||
| 521 | dinc2 = (deltay - deltax) * 2; \ | ||
| 522 | xinc1 = 1; \ | ||
| 523 | xinc2 = 1; \ | ||
| 524 | yinc1 = 0; \ | ||
| 525 | yinc2 = 1; \ | ||
| 526 | } else { \ | ||
| 527 | numpixels = deltay + 1; \ | ||
| 528 | d = (2 * deltax) - deltay; \ | ||
| 529 | dinc1 = deltax * 2; \ | ||
| 530 | dinc2 = (deltax - deltay) * 2; \ | ||
| 531 | xinc1 = 0; \ | ||
| 532 | xinc2 = 1; \ | ||
| 533 | yinc1 = 1; \ | ||
| 534 | yinc2 = 1; \ | ||
| 535 | } \ | ||
| 536 | \ | ||
| 537 | if (x1 > x2) { \ | ||
| 538 | xinc1 = -xinc1; \ | ||
| 539 | xinc2 = -xinc2; \ | ||
| 540 | } \ | ||
| 541 | if (y1 > y2) { \ | ||
| 542 | yinc1 = -yinc1; \ | ||
| 543 | yinc2 = -yinc2; \ | ||
| 544 | } \ | ||
| 545 | \ | ||
| 546 | x = x1; \ | ||
| 547 | y = y1; \ | ||
| 548 | \ | ||
| 549 | if (!draw_end) { \ | ||
| 550 | --numpixels; \ | ||
| 551 | } \ | ||
| 552 | for (i = 0; i < numpixels; ++i) { \ | ||
| 553 | op(x, y); \ | ||
| 554 | if (d < 0) { \ | ||
| 555 | d += dinc1; \ | ||
| 556 | x += xinc1; \ | ||
| 557 | y += yinc1; \ | ||
| 558 | } else { \ | ||
| 559 | d += dinc2; \ | ||
| 560 | x += xinc2; \ | ||
| 561 | y += yinc2; \ | ||
| 562 | } \ | ||
| 563 | } \ | ||
| 564 | } | ||
| 565 | |||
| 566 | // Xiaolin Wu's line algorithm, based on Michael Abrash's implementation | ||
| 567 | #define WULINE(x1, y1, x2, y2, opaque_op, blend_op, draw_end) \ | ||
| 568 | { \ | ||
| 569 | Uint16 ErrorAdj, ErrorAcc; \ | ||
| 570 | Uint16 ErrorAccTemp, Weighting; \ | ||
| 571 | int DeltaX, DeltaY, Temp, XDir; \ | ||
| 572 | unsigned r, g, b, a, inva; \ | ||
| 573 | \ | ||
| 574 | /* Draw the initial pixel, which is always exactly intersected by \ | ||
| 575 | the line and so needs no weighting */ \ | ||
| 576 | opaque_op(x1, y1); \ | ||
| 577 | \ | ||
| 578 | /* Draw the final pixel, which is always exactly intersected by the line \ | ||
| 579 | and so needs no weighting */ \ | ||
| 580 | if (draw_end) { \ | ||
| 581 | opaque_op(x2, y2); \ | ||
| 582 | } \ | ||
| 583 | \ | ||
| 584 | /* Make sure the line runs top to bottom */ \ | ||
| 585 | if (y1 > y2) { \ | ||
| 586 | Temp = y1; \ | ||
| 587 | y1 = y2; \ | ||
| 588 | y2 = Temp; \ | ||
| 589 | Temp = x1; \ | ||
| 590 | x1 = x2; \ | ||
| 591 | x2 = Temp; \ | ||
| 592 | } \ | ||
| 593 | DeltaY = y2 - y1; \ | ||
| 594 | \ | ||
| 595 | if ((DeltaX = x2 - x1) >= 0) { \ | ||
| 596 | XDir = 1; \ | ||
| 597 | } else { \ | ||
| 598 | XDir = -1; \ | ||
| 599 | DeltaX = -DeltaX; /* make DeltaX positive */ \ | ||
| 600 | } \ | ||
| 601 | \ | ||
| 602 | /* line is not horizontal, diagonal, or vertical */ \ | ||
| 603 | ErrorAcc = 0; /* initialize the line error accumulator to 0 */ \ | ||
| 604 | \ | ||
| 605 | /* Is this an X-major or Y-major line? */ \ | ||
| 606 | if (DeltaY > DeltaX) { \ | ||
| 607 | /* Y-major line; calculate 16-bit fixed-point fractional part of a \ | ||
| 608 | pixel that X advances each time Y advances 1 pixel, truncating the \ | ||
| 609 | result so that we won't overrun the endpoint along the X axis */ \ | ||
| 610 | ErrorAdj = ((unsigned long)DeltaX << 16) / (unsigned long)DeltaY; \ | ||
| 611 | /* Draw all pixels other than the first and last */ \ | ||
| 612 | while (--DeltaY) { \ | ||
| 613 | ErrorAccTemp = ErrorAcc; /* remember current accumulated error */ \ | ||
| 614 | ErrorAcc += ErrorAdj; /* calculate error for next pixel */ \ | ||
| 615 | if (ErrorAcc <= ErrorAccTemp) { \ | ||
| 616 | /* The error accumulator turned over, so advance the X coord */ \ | ||
| 617 | x1 += XDir; \ | ||
| 618 | } \ | ||
| 619 | y1++; /* Y-major, so always advance Y */ \ | ||
| 620 | /* The IntensityBits most significant bits of ErrorAcc give us the \ | ||
| 621 | intensity weighting for this pixel, and the complement of the \ | ||
| 622 | weighting for the paired pixel */ \ | ||
| 623 | Weighting = ErrorAcc >> 8; \ | ||
| 624 | { \ | ||
| 625 | a = DRAW_MUL(_a, (Weighting ^ 255)); \ | ||
| 626 | r = DRAW_MUL(_r, a); \ | ||
| 627 | g = DRAW_MUL(_g, a); \ | ||
| 628 | b = DRAW_MUL(_b, a); \ | ||
| 629 | inva = (a ^ 0xFF); \ | ||
| 630 | blend_op(x1, y1); \ | ||
| 631 | } \ | ||
| 632 | { \ | ||
| 633 | a = DRAW_MUL(_a, Weighting); \ | ||
| 634 | r = DRAW_MUL(_r, a); \ | ||
| 635 | g = DRAW_MUL(_g, a); \ | ||
| 636 | b = DRAW_MUL(_b, a); \ | ||
| 637 | inva = (a ^ 0xFF); \ | ||
| 638 | blend_op(x1 + XDir, y1); \ | ||
| 639 | } \ | ||
| 640 | } \ | ||
| 641 | } else { \ | ||
| 642 | /* X-major line; calculate 16-bit fixed-point fractional part of a \ | ||
| 643 | pixel that Y advances each time X advances 1 pixel, truncating the \ | ||
| 644 | result to avoid overrunning the endpoint along the X axis */ \ | ||
| 645 | ErrorAdj = ((unsigned long)DeltaY << 16) / (unsigned long)DeltaX; \ | ||
| 646 | /* Draw all pixels other than the first and last */ \ | ||
| 647 | while (--DeltaX) { \ | ||
| 648 | ErrorAccTemp = ErrorAcc; /* remember current accumulated error */ \ | ||
| 649 | ErrorAcc += ErrorAdj; /* calculate error for next pixel */ \ | ||
| 650 | if (ErrorAcc <= ErrorAccTemp) { \ | ||
| 651 | /* The error accumulator turned over, so advance the Y coord */ \ | ||
| 652 | y1++; \ | ||
| 653 | } \ | ||
| 654 | x1 += XDir; /* X-major, so always advance X */ \ | ||
| 655 | /* The IntensityBits most significant bits of ErrorAcc give us the \ | ||
| 656 | intensity weighting for this pixel, and the complement of the \ | ||
| 657 | weighting for the paired pixel */ \ | ||
| 658 | Weighting = ErrorAcc >> 8; \ | ||
| 659 | { \ | ||
| 660 | a = DRAW_MUL(_a, (Weighting ^ 255)); \ | ||
| 661 | r = DRAW_MUL(_r, a); \ | ||
| 662 | g = DRAW_MUL(_g, a); \ | ||
| 663 | b = DRAW_MUL(_b, a); \ | ||
| 664 | inva = (a ^ 0xFF); \ | ||
| 665 | blend_op(x1, y1); \ | ||
| 666 | } \ | ||
| 667 | { \ | ||
| 668 | a = DRAW_MUL(_a, Weighting); \ | ||
| 669 | r = DRAW_MUL(_r, a); \ | ||
| 670 | g = DRAW_MUL(_g, a); \ | ||
| 671 | b = DRAW_MUL(_b, a); \ | ||
| 672 | inva = (a ^ 0xFF); \ | ||
| 673 | blend_op(x1, y1 + 1); \ | ||
| 674 | } \ | ||
| 675 | } \ | ||
| 676 | } \ | ||
| 677 | } | ||
| 678 | |||
| 679 | #ifdef AA_LINES | ||
| 680 | #define AALINE(x1, y1, x2, y2, opaque_op, blend_op, draw_end) \ | ||
| 681 | WULINE(x1, y1, x2, y2, opaque_op, blend_op, draw_end) | ||
| 682 | #else | ||
| 683 | #define AALINE(x1, y1, x2, y2, opaque_op, blend_op, draw_end) \ | ||
| 684 | BLINE(x1, y1, x2, y2, opaque_op, draw_end) | ||
| 685 | #endif | ||
| 686 | |||
| 687 | /* | ||
| 688 | * Define fill rect macro | ||
| 689 | */ | ||
| 690 | |||
| 691 | #define FILLRECT(type, op) \ | ||
| 692 | do { \ | ||
| 693 | int width = rect->w; \ | ||
| 694 | int height = rect->h; \ | ||
| 695 | int pitch = (dst->pitch / dst->fmt->bytes_per_pixel); \ | ||
| 696 | int skip = pitch - width; \ | ||
| 697 | type *pixel = (type *)dst->pixels + rect->y * pitch + rect->x; \ | ||
| 698 | while (height--) { \ | ||
| 699 | { \ | ||
| 700 | int n = (width + 3) / 4; \ | ||
| 701 | switch (width & 3) { \ | ||
| 702 | case 0: \ | ||
| 703 | do { \ | ||
| 704 | op; \ | ||
| 705 | pixel++; \ | ||
| 706 | SDL_FALLTHROUGH; \ | ||
| 707 | case 3: \ | ||
| 708 | op; \ | ||
| 709 | pixel++; \ | ||
| 710 | SDL_FALLTHROUGH; \ | ||
| 711 | case 2: \ | ||
| 712 | op; \ | ||
| 713 | pixel++; \ | ||
| 714 | SDL_FALLTHROUGH; \ | ||
| 715 | case 1: \ | ||
| 716 | op; \ | ||
| 717 | pixel++; \ | ||
| 718 | } while (--n > 0); \ | ||
| 719 | } \ | ||
| 720 | } \ | ||
| 721 | pixel += skip; \ | ||
| 722 | } \ | ||
| 723 | } while (0) | ||
diff --git a/contrib/SDL-3.2.8/src/render/software/SDL_drawline.c b/contrib/SDL-3.2.8/src/render/software/SDL_drawline.c new file mode 100644 index 0000000..59ba268 --- /dev/null +++ b/contrib/SDL-3.2.8/src/render/software/SDL_drawline.c | |||
| @@ -0,0 +1,199 @@ | |||
| 1 | /* | ||
| 2 | Simple DirectMedia Layer | ||
| 3 | Copyright (C) 1997-2025 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 | #ifdef SDL_VIDEO_RENDER_SW | ||
| 24 | |||
| 25 | #include "SDL_draw.h" | ||
| 26 | #include "SDL_drawline.h" | ||
| 27 | #include "SDL_drawpoint.h" | ||
| 28 | |||
| 29 | static void SDL_DrawLine1(SDL_Surface *dst, int x1, int y1, int x2, int y2, Uint32 color, | ||
| 30 | bool draw_end) | ||
| 31 | { | ||
| 32 | if (y1 == y2) { | ||
| 33 | int length; | ||
| 34 | int pitch = (dst->pitch / dst->fmt->bytes_per_pixel); | ||
| 35 | Uint8 *pixel; | ||
| 36 | if (x1 <= x2) { | ||
| 37 | pixel = (Uint8 *)dst->pixels + y1 * pitch + x1; | ||
| 38 | length = draw_end ? (x2 - x1 + 1) : (x2 - x1); | ||
| 39 | } else { | ||
| 40 | pixel = (Uint8 *)dst->pixels + y1 * pitch + x2; | ||
| 41 | if (!draw_end) { | ||
| 42 | ++pixel; | ||
| 43 | } | ||
| 44 | length = draw_end ? (x1 - x2 + 1) : (x1 - x2); | ||
| 45 | } | ||
| 46 | SDL_memset(pixel, color, length); | ||
| 47 | } else if (x1 == x2) { | ||
| 48 | VLINE(Uint8, DRAW_FASTSETPIXEL1, draw_end); | ||
| 49 | } else if (ABS(x1 - x2) == ABS(y1 - y2)) { | ||
| 50 | DLINE(Uint8, DRAW_FASTSETPIXEL1, draw_end); | ||
| 51 | } else { | ||
| 52 | BLINE(x1, y1, x2, y2, DRAW_FASTSETPIXELXY1, draw_end); | ||
| 53 | } | ||
| 54 | } | ||
| 55 | |||
| 56 | static void SDL_DrawLine2(SDL_Surface *dst, int x1, int y1, int x2, int y2, Uint32 color, | ||
| 57 | bool draw_end) | ||
| 58 | { | ||
| 59 | if (y1 == y2) { | ||
| 60 | HLINE(Uint16, DRAW_FASTSETPIXEL2, draw_end); | ||
| 61 | } else if (x1 == x2) { | ||
| 62 | VLINE(Uint16, DRAW_FASTSETPIXEL2, draw_end); | ||
| 63 | } else if (ABS(x1 - x2) == ABS(y1 - y2)) { | ||
| 64 | DLINE(Uint16, DRAW_FASTSETPIXEL2, draw_end); | ||
| 65 | } else { | ||
| 66 | Uint8 _r, _g, _b, _a; | ||
| 67 | const SDL_PixelFormatDetails *fmt = dst->fmt; | ||
| 68 | SDL_GetRGBA(color, fmt, dst->palette, &_r, &_g, &_b, &_a); | ||
| 69 | if (fmt->Rmask == 0x7C00) { | ||
| 70 | AALINE(x1, y1, x2, y2, | ||
| 71 | DRAW_FASTSETPIXELXY2, DRAW_SETPIXELXY_BLEND_RGB555, | ||
| 72 | draw_end); | ||
| 73 | } else if (fmt->Rmask == 0xF800) { | ||
| 74 | AALINE(x1, y1, x2, y2, | ||
| 75 | DRAW_FASTSETPIXELXY2, DRAW_SETPIXELXY_BLEND_RGB565, | ||
| 76 | draw_end); | ||
| 77 | } else { | ||
| 78 | AALINE(x1, y1, x2, y2, | ||
| 79 | DRAW_FASTSETPIXELXY2, DRAW_SETPIXELXY2_BLEND_RGB, | ||
| 80 | draw_end); | ||
| 81 | } | ||
| 82 | } | ||
| 83 | } | ||
| 84 | |||
| 85 | static void SDL_DrawLine4(SDL_Surface *dst, int x1, int y1, int x2, int y2, Uint32 color, | ||
| 86 | bool draw_end) | ||
| 87 | { | ||
| 88 | if (y1 == y2) { | ||
| 89 | HLINE(Uint32, DRAW_FASTSETPIXEL4, draw_end); | ||
| 90 | } else if (x1 == x2) { | ||
| 91 | VLINE(Uint32, DRAW_FASTSETPIXEL4, draw_end); | ||
| 92 | } else if (ABS(x1 - x2) == ABS(y1 - y2)) { | ||
| 93 | DLINE(Uint32, DRAW_FASTSETPIXEL4, draw_end); | ||
| 94 | } else { | ||
| 95 | Uint8 _r, _g, _b, _a; | ||
| 96 | const SDL_PixelFormatDetails *fmt = dst->fmt; | ||
| 97 | SDL_GetRGBA(color, fmt, dst->palette, &_r, &_g, &_b, &_a); | ||
| 98 | if (fmt->Rmask == 0x00FF0000) { | ||
| 99 | if (!fmt->Amask) { | ||
| 100 | AALINE(x1, y1, x2, y2, | ||
| 101 | DRAW_FASTSETPIXELXY4, DRAW_SETPIXELXY_BLEND_XRGB8888, | ||
| 102 | draw_end); | ||
| 103 | } else { | ||
| 104 | AALINE(x1, y1, x2, y2, | ||
| 105 | DRAW_FASTSETPIXELXY4, DRAW_SETPIXELXY_BLEND_ARGB8888, | ||
| 106 | draw_end); | ||
| 107 | } | ||
| 108 | } else { | ||
| 109 | AALINE(x1, y1, x2, y2, | ||
| 110 | DRAW_FASTSETPIXELXY4, DRAW_SETPIXELXY4_BLEND_RGB, | ||
| 111 | draw_end); | ||
| 112 | } | ||
| 113 | } | ||
| 114 | } | ||
| 115 | |||
| 116 | typedef void (*DrawLineFunc)(SDL_Surface *dst, | ||
| 117 | int x1, int y1, int x2, int y2, | ||
| 118 | Uint32 color, bool draw_end); | ||
| 119 | |||
| 120 | static DrawLineFunc SDL_CalculateDrawLineFunc(const SDL_PixelFormatDetails *fmt) | ||
| 121 | { | ||
| 122 | switch (fmt->bytes_per_pixel) { | ||
| 123 | case 1: | ||
| 124 | if (fmt->bits_per_pixel < 8) { | ||
| 125 | break; | ||
| 126 | } | ||
| 127 | return SDL_DrawLine1; | ||
| 128 | case 2: | ||
| 129 | return SDL_DrawLine2; | ||
| 130 | case 4: | ||
| 131 | return SDL_DrawLine4; | ||
| 132 | } | ||
| 133 | return NULL; | ||
| 134 | } | ||
| 135 | |||
| 136 | bool SDL_DrawLine(SDL_Surface *dst, int x1, int y1, int x2, int y2, Uint32 color) | ||
| 137 | { | ||
| 138 | DrawLineFunc func; | ||
| 139 | |||
| 140 | if (!SDL_SurfaceValid(dst)) { | ||
| 141 | return SDL_InvalidParamError("SDL_DrawLine(): dst"); | ||
| 142 | } | ||
| 143 | |||
| 144 | func = SDL_CalculateDrawLineFunc(dst->fmt); | ||
| 145 | if (!func) { | ||
| 146 | return SDL_SetError("SDL_DrawLine(): Unsupported surface format"); | ||
| 147 | } | ||
| 148 | |||
| 149 | // Perform clipping | ||
| 150 | // FIXME: We don't actually want to clip, as it may change line slope | ||
| 151 | if (!SDL_GetRectAndLineIntersection(&dst->clip_rect, &x1, &y1, &x2, &y2)) { | ||
| 152 | return true; | ||
| 153 | } | ||
| 154 | |||
| 155 | func(dst, x1, y1, x2, y2, color, true); | ||
| 156 | return true; | ||
| 157 | } | ||
| 158 | |||
| 159 | bool SDL_DrawLines(SDL_Surface *dst, const SDL_Point *points, int count, Uint32 color) | ||
| 160 | { | ||
| 161 | int i; | ||
| 162 | int x1, y1; | ||
| 163 | int x2, y2; | ||
| 164 | bool draw_end; | ||
| 165 | DrawLineFunc func; | ||
| 166 | |||
| 167 | if (!SDL_SurfaceValid(dst)) { | ||
| 168 | return SDL_InvalidParamError("SDL_DrawLines(): dst"); | ||
| 169 | } | ||
| 170 | |||
| 171 | func = SDL_CalculateDrawLineFunc(dst->fmt); | ||
| 172 | if (!func) { | ||
| 173 | return SDL_SetError("SDL_DrawLines(): Unsupported surface format"); | ||
| 174 | } | ||
| 175 | |||
| 176 | for (i = 1; i < count; ++i) { | ||
| 177 | x1 = points[i - 1].x; | ||
| 178 | y1 = points[i - 1].y; | ||
| 179 | x2 = points[i].x; | ||
| 180 | y2 = points[i].y; | ||
| 181 | |||
| 182 | // Perform clipping | ||
| 183 | // FIXME: We don't actually want to clip, as it may change line slope | ||
| 184 | if (!SDL_GetRectAndLineIntersection(&dst->clip_rect, &x1, &y1, &x2, &y2)) { | ||
| 185 | continue; | ||
| 186 | } | ||
| 187 | |||
| 188 | // Draw the end if the whole line is a single point or it was clipped | ||
| 189 | draw_end = ((x1 == x2) && (y1 == y2)) || (x2 != points[i].x || y2 != points[i].y); | ||
| 190 | |||
| 191 | func(dst, x1, y1, x2, y2, color, draw_end); | ||
| 192 | } | ||
| 193 | if (points[0].x != points[count - 1].x || points[0].y != points[count - 1].y) { | ||
| 194 | SDL_DrawPoint(dst, points[count - 1].x, points[count - 1].y, color); | ||
| 195 | } | ||
| 196 | return true; | ||
| 197 | } | ||
| 198 | |||
| 199 | #endif // SDL_VIDEO_RENDER_SW | ||
diff --git a/contrib/SDL-3.2.8/src/render/software/SDL_drawline.h b/contrib/SDL-3.2.8/src/render/software/SDL_drawline.h new file mode 100644 index 0000000..e88b2c3 --- /dev/null +++ b/contrib/SDL-3.2.8/src/render/software/SDL_drawline.h | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | /* | ||
| 2 | Simple DirectMedia Layer | ||
| 3 | Copyright (C) 1997-2025 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 | |||
| 22 | #ifndef SDL_drawline_h_ | ||
| 23 | #define SDL_drawline_h_ | ||
| 24 | |||
| 25 | #include "SDL_internal.h" | ||
| 26 | |||
| 27 | extern bool SDL_DrawLine(SDL_Surface *dst, int x1, int y1, int x2, int y2, Uint32 color); | ||
| 28 | extern bool SDL_DrawLines(SDL_Surface *dst, const SDL_Point *points, int count, Uint32 color); | ||
| 29 | |||
| 30 | #endif // SDL_drawline_h_ | ||
diff --git a/contrib/SDL-3.2.8/src/render/software/SDL_drawpoint.c b/contrib/SDL-3.2.8/src/render/software/SDL_drawpoint.c new file mode 100644 index 0000000..5aa28b3 --- /dev/null +++ b/contrib/SDL-3.2.8/src/render/software/SDL_drawpoint.c | |||
| @@ -0,0 +1,108 @@ | |||
| 1 | /* | ||
| 2 | Simple DirectMedia Layer | ||
| 3 | Copyright (C) 1997-2025 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 | #ifdef SDL_VIDEO_RENDER_SW | ||
| 24 | |||
| 25 | #include "SDL_draw.h" | ||
| 26 | #include "SDL_drawpoint.h" | ||
| 27 | |||
| 28 | bool SDL_DrawPoint(SDL_Surface *dst, int x, int y, Uint32 color) | ||
| 29 | { | ||
| 30 | if (!SDL_SurfaceValid(dst)) { | ||
| 31 | return SDL_InvalidParamError("SDL_DrawPoint(): dst"); | ||
| 32 | } | ||
| 33 | |||
| 34 | // This function doesn't work on surfaces < 8 bpp | ||
| 35 | if (dst->fmt->bits_per_pixel < 8) { | ||
| 36 | return SDL_SetError("SDL_DrawPoint(): Unsupported surface format"); | ||
| 37 | } | ||
| 38 | |||
| 39 | // Perform clipping | ||
| 40 | if (x < dst->clip_rect.x || y < dst->clip_rect.y || | ||
| 41 | x >= (dst->clip_rect.x + dst->clip_rect.w) || | ||
| 42 | y >= (dst->clip_rect.y + dst->clip_rect.h)) { | ||
| 43 | return true; | ||
| 44 | } | ||
| 45 | |||
| 46 | switch (dst->fmt->bytes_per_pixel) { | ||
| 47 | case 1: | ||
| 48 | DRAW_FASTSETPIXELXY1(x, y); | ||
| 49 | break; | ||
| 50 | case 2: | ||
| 51 | DRAW_FASTSETPIXELXY2(x, y); | ||
| 52 | break; | ||
| 53 | case 3: | ||
| 54 | return SDL_Unsupported(); | ||
| 55 | case 4: | ||
| 56 | DRAW_FASTSETPIXELXY4(x, y); | ||
| 57 | break; | ||
| 58 | } | ||
| 59 | return true; | ||
| 60 | } | ||
| 61 | |||
| 62 | bool SDL_DrawPoints(SDL_Surface *dst, const SDL_Point *points, int count, Uint32 color) | ||
| 63 | { | ||
| 64 | int minx, miny; | ||
| 65 | int maxx, maxy; | ||
| 66 | int i; | ||
| 67 | int x, y; | ||
| 68 | |||
| 69 | if (!SDL_SurfaceValid(dst)) { | ||
| 70 | return SDL_InvalidParamError("SDL_DrawPoints(): dst"); | ||
| 71 | } | ||
| 72 | |||
| 73 | // This function doesn't work on surfaces < 8 bpp | ||
| 74 | if (dst->fmt->bits_per_pixel < 8) { | ||
| 75 | return SDL_SetError("SDL_DrawPoints(): Unsupported surface format"); | ||
| 76 | } | ||
| 77 | |||
| 78 | minx = dst->clip_rect.x; | ||
| 79 | maxx = dst->clip_rect.x + dst->clip_rect.w - 1; | ||
| 80 | miny = dst->clip_rect.y; | ||
| 81 | maxy = dst->clip_rect.y + dst->clip_rect.h - 1; | ||
| 82 | |||
| 83 | for (i = 0; i < count; ++i) { | ||
| 84 | x = points[i].x; | ||
| 85 | y = points[i].y; | ||
| 86 | |||
| 87 | if (x < minx || x > maxx || y < miny || y > maxy) { | ||
| 88 | continue; | ||
| 89 | } | ||
| 90 | |||
| 91 | switch (dst->fmt->bytes_per_pixel) { | ||
| 92 | case 1: | ||
| 93 | DRAW_FASTSETPIXELXY1(x, y); | ||
| 94 | break; | ||
| 95 | case 2: | ||
| 96 | DRAW_FASTSETPIXELXY2(x, y); | ||
| 97 | break; | ||
| 98 | case 3: | ||
| 99 | return SDL_Unsupported(); | ||
| 100 | case 4: | ||
| 101 | DRAW_FASTSETPIXELXY4(x, y); | ||
| 102 | break; | ||
| 103 | } | ||
| 104 | } | ||
| 105 | return true; | ||
| 106 | } | ||
| 107 | |||
| 108 | #endif // SDL_VIDEO_RENDER_SW | ||
diff --git a/contrib/SDL-3.2.8/src/render/software/SDL_drawpoint.h b/contrib/SDL-3.2.8/src/render/software/SDL_drawpoint.h new file mode 100644 index 0000000..631e7aa --- /dev/null +++ b/contrib/SDL-3.2.8/src/render/software/SDL_drawpoint.h | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | /* | ||
| 2 | Simple DirectMedia Layer | ||
| 3 | Copyright (C) 1997-2025 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 | |||
| 22 | #ifndef SDL_drawpoint_h_ | ||
| 23 | #define SDL_drawpoint_h_ | ||
| 24 | |||
| 25 | #include "SDL_internal.h" | ||
| 26 | |||
| 27 | extern bool SDL_DrawPoint(SDL_Surface *dst, int x, int y, Uint32 color); | ||
| 28 | extern bool SDL_DrawPoints(SDL_Surface *dst, const SDL_Point *points, int count, Uint32 color); | ||
| 29 | |||
| 30 | #endif // SDL_drawpoint_h_ | ||
diff --git a/contrib/SDL-3.2.8/src/render/software/SDL_render_sw.c b/contrib/SDL-3.2.8/src/render/software/SDL_render_sw.c new file mode 100644 index 0000000..2231724 --- /dev/null +++ b/contrib/SDL-3.2.8/src/render/software/SDL_render_sw.c | |||
| @@ -0,0 +1,1202 @@ | |||
| 1 | /* | ||
| 2 | Simple DirectMedia Layer | ||
| 3 | Copyright (C) 1997-2025 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 | #ifdef SDL_VIDEO_RENDER_SW | ||
| 24 | |||
| 25 | #include "../SDL_sysrender.h" | ||
| 26 | #include "SDL_render_sw_c.h" | ||
| 27 | |||
| 28 | #include "SDL_draw.h" | ||
| 29 | #include "SDL_blendfillrect.h" | ||
| 30 | #include "SDL_blendline.h" | ||
| 31 | #include "SDL_blendpoint.h" | ||
| 32 | #include "SDL_drawline.h" | ||
| 33 | #include "SDL_drawpoint.h" | ||
| 34 | #include "SDL_rotate.h" | ||
| 35 | #include "SDL_triangle.h" | ||
| 36 | #include "../../video/SDL_pixels_c.h" | ||
| 37 | |||
| 38 | // SDL surface based renderer implementation | ||
| 39 | |||
| 40 | typedef struct | ||
| 41 | { | ||
| 42 | const SDL_Rect *viewport; | ||
| 43 | const SDL_Rect *cliprect; | ||
| 44 | bool surface_cliprect_dirty; | ||
| 45 | SDL_Color color; | ||
| 46 | } SW_DrawStateCache; | ||
| 47 | |||
| 48 | typedef struct | ||
| 49 | { | ||
| 50 | SDL_Surface *surface; | ||
| 51 | SDL_Surface *window; | ||
| 52 | } SW_RenderData; | ||
| 53 | |||
| 54 | static SDL_Surface *SW_ActivateRenderer(SDL_Renderer *renderer) | ||
| 55 | { | ||
| 56 | SW_RenderData *data = (SW_RenderData *)renderer->internal; | ||
| 57 | |||
| 58 | if (!data->surface) { | ||
| 59 | data->surface = data->window; | ||
| 60 | } | ||
| 61 | if (!data->surface) { | ||
| 62 | SDL_Surface *surface = SDL_GetWindowSurface(renderer->window); | ||
| 63 | if (surface) { | ||
| 64 | data->surface = data->window = surface; | ||
| 65 | } | ||
| 66 | } | ||
| 67 | return data->surface; | ||
| 68 | } | ||
| 69 | |||
| 70 | static void SW_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event) | ||
| 71 | { | ||
| 72 | SW_RenderData *data = (SW_RenderData *)renderer->internal; | ||
| 73 | |||
| 74 | if (event->type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED) { | ||
| 75 | data->surface = NULL; | ||
| 76 | data->window = NULL; | ||
| 77 | } | ||
| 78 | } | ||
| 79 | |||
| 80 | static bool SW_GetOutputSize(SDL_Renderer *renderer, int *w, int *h) | ||
| 81 | { | ||
| 82 | SW_RenderData *data = (SW_RenderData *)renderer->internal; | ||
| 83 | |||
| 84 | if (data->surface) { | ||
| 85 | if (w) { | ||
| 86 | *w = data->surface->w; | ||
| 87 | } | ||
| 88 | if (h) { | ||
| 89 | *h = data->surface->h; | ||
| 90 | } | ||
| 91 | return true; | ||
| 92 | } | ||
| 93 | |||
| 94 | if (renderer->window) { | ||
| 95 | SDL_GetWindowSizeInPixels(renderer->window, w, h); | ||
| 96 | return true; | ||
| 97 | } | ||
| 98 | |||
| 99 | return SDL_SetError("Software renderer doesn't have an output surface"); | ||
| 100 | } | ||
| 101 | |||
| 102 | static bool SW_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props) | ||
| 103 | { | ||
| 104 | SDL_Surface *surface = SDL_CreateSurface(texture->w, texture->h, texture->format); | ||
| 105 | Uint8 r, g, b, a; | ||
| 106 | |||
| 107 | if (!SDL_SurfaceValid(surface)) { | ||
| 108 | return SDL_SetError("Cannot create surface"); | ||
| 109 | } | ||
| 110 | texture->internal = surface; | ||
| 111 | r = (Uint8)SDL_roundf(SDL_clamp(texture->color.r, 0.0f, 1.0f) * 255.0f); | ||
| 112 | g = (Uint8)SDL_roundf(SDL_clamp(texture->color.g, 0.0f, 1.0f) * 255.0f); | ||
| 113 | b = (Uint8)SDL_roundf(SDL_clamp(texture->color.b, 0.0f, 1.0f) * 255.0f); | ||
| 114 | a = (Uint8)SDL_roundf(SDL_clamp(texture->color.a, 0.0f, 1.0f) * 255.0f); | ||
| 115 | SDL_SetSurfaceColorMod(surface, r, g, b); | ||
| 116 | SDL_SetSurfaceAlphaMod(surface, a); | ||
| 117 | SDL_SetSurfaceBlendMode(surface, texture->blendMode); | ||
| 118 | |||
| 119 | /* Only RLE encode textures without an alpha channel since the RLE coder | ||
| 120 | * discards the color values of pixels with an alpha value of zero. | ||
| 121 | */ | ||
| 122 | if (texture->access == SDL_TEXTUREACCESS_STATIC && !SDL_ISPIXELFORMAT_ALPHA(surface->format)) { | ||
| 123 | SDL_SetSurfaceRLE(surface, 1); | ||
| 124 | } | ||
| 125 | |||
| 126 | return true; | ||
| 127 | } | ||
| 128 | |||
| 129 | static bool SW_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, | ||
| 130 | const SDL_Rect *rect, const void *pixels, int pitch) | ||
| 131 | { | ||
| 132 | SDL_Surface *surface = (SDL_Surface *)texture->internal; | ||
| 133 | Uint8 *src, *dst; | ||
| 134 | int row; | ||
| 135 | size_t length; | ||
| 136 | |||
| 137 | if (SDL_MUSTLOCK(surface)) { | ||
| 138 | if (!SDL_LockSurface(surface)) { | ||
| 139 | return false; | ||
| 140 | } | ||
| 141 | } | ||
| 142 | src = (Uint8 *)pixels; | ||
| 143 | dst = (Uint8 *)surface->pixels + | ||
| 144 | rect->y * surface->pitch + | ||
| 145 | rect->x * surface->fmt->bytes_per_pixel; | ||
| 146 | length = (size_t)rect->w * surface->fmt->bytes_per_pixel; | ||
| 147 | for (row = 0; row < rect->h; ++row) { | ||
| 148 | SDL_memcpy(dst, src, length); | ||
| 149 | src += pitch; | ||
| 150 | dst += surface->pitch; | ||
| 151 | } | ||
| 152 | if (SDL_MUSTLOCK(surface)) { | ||
| 153 | SDL_UnlockSurface(surface); | ||
| 154 | } | ||
| 155 | return true; | ||
| 156 | } | ||
| 157 | |||
| 158 | static bool SW_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, | ||
| 159 | const SDL_Rect *rect, void **pixels, int *pitch) | ||
| 160 | { | ||
| 161 | SDL_Surface *surface = (SDL_Surface *)texture->internal; | ||
| 162 | |||
| 163 | *pixels = | ||
| 164 | (void *)((Uint8 *)surface->pixels + rect->y * surface->pitch + | ||
| 165 | rect->x * surface->fmt->bytes_per_pixel); | ||
| 166 | *pitch = surface->pitch; | ||
| 167 | return true; | ||
| 168 | } | ||
| 169 | |||
| 170 | static void SW_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture) | ||
| 171 | { | ||
| 172 | } | ||
| 173 | |||
| 174 | static void SW_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode) | ||
| 175 | { | ||
| 176 | } | ||
| 177 | |||
| 178 | static bool SW_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) | ||
| 179 | { | ||
| 180 | SW_RenderData *data = (SW_RenderData *)renderer->internal; | ||
| 181 | |||
| 182 | if (texture) { | ||
| 183 | data->surface = (SDL_Surface *)texture->internal; | ||
| 184 | } else { | ||
| 185 | data->surface = data->window; | ||
| 186 | } | ||
| 187 | return true; | ||
| 188 | } | ||
| 189 | |||
| 190 | static bool SW_QueueNoOp(SDL_Renderer *renderer, SDL_RenderCommand *cmd) | ||
| 191 | { | ||
| 192 | return true; // nothing to do in this backend. | ||
| 193 | } | ||
| 194 | |||
| 195 | static bool SW_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count) | ||
| 196 | { | ||
| 197 | SDL_Point *verts = (SDL_Point *)SDL_AllocateRenderVertices(renderer, count * sizeof(SDL_Point), 0, &cmd->data.draw.first); | ||
| 198 | int i; | ||
| 199 | |||
| 200 | if (!verts) { | ||
| 201 | return false; | ||
| 202 | } | ||
| 203 | |||
| 204 | cmd->data.draw.count = count; | ||
| 205 | |||
| 206 | for (i = 0; i < count; i++, verts++, points++) { | ||
| 207 | verts->x = (int)points->x; | ||
| 208 | verts->y = (int)points->y; | ||
| 209 | } | ||
| 210 | |||
| 211 | return true; | ||
| 212 | } | ||
| 213 | |||
| 214 | static bool SW_QueueFillRects(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FRect *rects, int count) | ||
| 215 | { | ||
| 216 | SDL_Rect *verts = (SDL_Rect *)SDL_AllocateRenderVertices(renderer, count * sizeof(SDL_Rect), 0, &cmd->data.draw.first); | ||
| 217 | int i; | ||
| 218 | |||
| 219 | if (!verts) { | ||
| 220 | return false; | ||
| 221 | } | ||
| 222 | |||
| 223 | cmd->data.draw.count = count; | ||
| 224 | |||
| 225 | for (i = 0; i < count; i++, verts++, rects++) { | ||
| 226 | verts->x = (int)rects->x; | ||
| 227 | verts->y = (int)rects->y; | ||
| 228 | verts->w = SDL_max((int)rects->w, 1); | ||
| 229 | verts->h = SDL_max((int)rects->h, 1); | ||
| 230 | } | ||
| 231 | |||
| 232 | return true; | ||
| 233 | } | ||
| 234 | |||
| 235 | static bool SW_QueueCopy(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture, | ||
| 236 | const SDL_FRect *srcrect, const SDL_FRect *dstrect) | ||
| 237 | { | ||
| 238 | SDL_Rect *verts = (SDL_Rect *)SDL_AllocateRenderVertices(renderer, 2 * sizeof(SDL_Rect), 0, &cmd->data.draw.first); | ||
| 239 | |||
| 240 | if (!verts) { | ||
| 241 | return false; | ||
| 242 | } | ||
| 243 | |||
| 244 | cmd->data.draw.count = 1; | ||
| 245 | |||
| 246 | verts->x = (int)srcrect->x; | ||
| 247 | verts->y = (int)srcrect->y; | ||
| 248 | verts->w = (int)srcrect->w; | ||
| 249 | verts->h = (int)srcrect->h; | ||
| 250 | verts++; | ||
| 251 | |||
| 252 | verts->x = (int)dstrect->x; | ||
| 253 | verts->y = (int)dstrect->y; | ||
| 254 | verts->w = (int)dstrect->w; | ||
| 255 | verts->h = (int)dstrect->h; | ||
| 256 | |||
| 257 | return true; | ||
| 258 | } | ||
| 259 | |||
| 260 | typedef struct CopyExData | ||
| 261 | { | ||
| 262 | SDL_Rect srcrect; | ||
| 263 | SDL_Rect dstrect; | ||
| 264 | double angle; | ||
| 265 | SDL_FPoint center; | ||
| 266 | SDL_FlipMode flip; | ||
| 267 | float scale_x; | ||
| 268 | float scale_y; | ||
| 269 | } CopyExData; | ||
| 270 | |||
| 271 | static bool SW_QueueCopyEx(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture, | ||
| 272 | const SDL_FRect *srcrect, const SDL_FRect *dstrect, | ||
| 273 | const double angle, const SDL_FPoint *center, const SDL_FlipMode flip, float scale_x, float scale_y) | ||
| 274 | { | ||
| 275 | CopyExData *verts = (CopyExData *)SDL_AllocateRenderVertices(renderer, sizeof(CopyExData), 0, &cmd->data.draw.first); | ||
| 276 | |||
| 277 | if (!verts) { | ||
| 278 | return false; | ||
| 279 | } | ||
| 280 | |||
| 281 | cmd->data.draw.count = 1; | ||
| 282 | |||
| 283 | verts->srcrect.x = (int)srcrect->x; | ||
| 284 | verts->srcrect.y = (int)srcrect->y; | ||
| 285 | verts->srcrect.w = (int)srcrect->w; | ||
| 286 | verts->srcrect.h = (int)srcrect->h; | ||
| 287 | verts->dstrect.x = (int)dstrect->x; | ||
| 288 | verts->dstrect.y = (int)dstrect->y; | ||
| 289 | verts->dstrect.w = (int)dstrect->w; | ||
| 290 | verts->dstrect.h = (int)dstrect->h; | ||
| 291 | verts->angle = angle; | ||
| 292 | SDL_copyp(&verts->center, center); | ||
| 293 | verts->flip = flip; | ||
| 294 | verts->scale_x = scale_x; | ||
| 295 | verts->scale_y = scale_y; | ||
| 296 | |||
| 297 | return true; | ||
| 298 | } | ||
| 299 | |||
| 300 | static bool Blit_to_Screen(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *surface, SDL_Rect *dstrect, | ||
| 301 | float scale_x, float scale_y, SDL_ScaleMode scaleMode) | ||
| 302 | { | ||
| 303 | bool result; | ||
| 304 | // Renderer scaling, if needed | ||
| 305 | if (scale_x != 1.0f || scale_y != 1.0f) { | ||
| 306 | SDL_Rect r; | ||
| 307 | r.x = (int)((float)dstrect->x * scale_x); | ||
| 308 | r.y = (int)((float)dstrect->y * scale_y); | ||
| 309 | r.w = (int)((float)dstrect->w * scale_x); | ||
| 310 | r.h = (int)((float)dstrect->h * scale_y); | ||
| 311 | result = SDL_BlitSurfaceScaled(src, srcrect, surface, &r, scaleMode); | ||
| 312 | } else { | ||
| 313 | result = SDL_BlitSurface(src, srcrect, surface, dstrect); | ||
| 314 | } | ||
| 315 | return result; | ||
| 316 | } | ||
| 317 | |||
| 318 | static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Texture *texture, | ||
| 319 | const SDL_Rect *srcrect, const SDL_Rect *final_rect, | ||
| 320 | const double angle, const SDL_FPoint *center, const SDL_FlipMode flip, float scale_x, float scale_y) | ||
| 321 | { | ||
| 322 | SDL_Surface *src = (SDL_Surface *)texture->internal; | ||
| 323 | SDL_Rect tmp_rect; | ||
| 324 | SDL_Surface *src_clone, *src_rotated, *src_scaled; | ||
| 325 | SDL_Surface *mask = NULL, *mask_rotated = NULL; | ||
| 326 | bool result = true; | ||
| 327 | SDL_BlendMode blendmode; | ||
| 328 | Uint8 alphaMod, rMod, gMod, bMod; | ||
| 329 | int applyModulation = false; | ||
| 330 | int blitRequired = false; | ||
| 331 | int isOpaque = false; | ||
| 332 | |||
| 333 | if (!SDL_SurfaceValid(surface)) { | ||
| 334 | return false; | ||
| 335 | } | ||
| 336 | |||
| 337 | tmp_rect.x = 0; | ||
| 338 | tmp_rect.y = 0; | ||
| 339 | tmp_rect.w = final_rect->w; | ||
| 340 | tmp_rect.h = final_rect->h; | ||
| 341 | |||
| 342 | /* It is possible to encounter an RLE encoded surface here and locking it is | ||
| 343 | * necessary because this code is going to access the pixel buffer directly. | ||
| 344 | */ | ||
| 345 | if (SDL_MUSTLOCK(src)) { | ||
| 346 | if (!SDL_LockSurface(src)) { | ||
| 347 | return false; | ||
| 348 | } | ||
| 349 | } | ||
| 350 | |||
| 351 | /* Clone the source surface but use its pixel buffer directly. | ||
| 352 | * The original source surface must be treated as read-only. | ||
| 353 | */ | ||
| 354 | src_clone = SDL_CreateSurfaceFrom(src->w, src->h, src->format, src->pixels, src->pitch); | ||
| 355 | if (!src_clone) { | ||
| 356 | if (SDL_MUSTLOCK(src)) { | ||
| 357 | SDL_UnlockSurface(src); | ||
| 358 | } | ||
| 359 | return false; | ||
| 360 | } | ||
| 361 | |||
| 362 | SDL_GetSurfaceBlendMode(src, &blendmode); | ||
| 363 | SDL_GetSurfaceAlphaMod(src, &alphaMod); | ||
| 364 | SDL_GetSurfaceColorMod(src, &rMod, &gMod, &bMod); | ||
| 365 | |||
| 366 | // SDLgfx_rotateSurface only accepts 32-bit surfaces with a 8888 layout. Everything else has to be converted. | ||
| 367 | if (src->fmt->bits_per_pixel != 32 || SDL_PIXELLAYOUT(src->format) != SDL_PACKEDLAYOUT_8888 || !SDL_ISPIXELFORMAT_ALPHA(src->format)) { | ||
| 368 | blitRequired = true; | ||
| 369 | } | ||
| 370 | |||
| 371 | // If scaling and cropping is necessary, it has to be taken care of before the rotation. | ||
| 372 | if (!(srcrect->w == final_rect->w && srcrect->h == final_rect->h && srcrect->x == 0 && srcrect->y == 0)) { | ||
| 373 | blitRequired = true; | ||
| 374 | } | ||
| 375 | |||
| 376 | // srcrect is not selecting the whole src surface, so cropping is needed | ||
| 377 | if (!(srcrect->w == src->w && srcrect->h == src->h && srcrect->x == 0 && srcrect->y == 0)) { | ||
| 378 | blitRequired = true; | ||
| 379 | } | ||
| 380 | |||
| 381 | // The color and alpha modulation has to be applied before the rotation when using the NONE, MOD or MUL blend modes. | ||
| 382 | if ((blendmode == SDL_BLENDMODE_NONE || blendmode == SDL_BLENDMODE_MOD || blendmode == SDL_BLENDMODE_MUL) && (alphaMod & rMod & gMod & bMod) != 255) { | ||
| 383 | applyModulation = true; | ||
| 384 | SDL_SetSurfaceAlphaMod(src_clone, alphaMod); | ||
| 385 | SDL_SetSurfaceColorMod(src_clone, rMod, gMod, bMod); | ||
| 386 | } | ||
| 387 | |||
| 388 | // Opaque surfaces are much easier to handle with the NONE blend mode. | ||
| 389 | if (blendmode == SDL_BLENDMODE_NONE && !SDL_ISPIXELFORMAT_ALPHA(src->format) && alphaMod == 255) { | ||
| 390 | isOpaque = true; | ||
| 391 | } | ||
| 392 | |||
| 393 | /* The NONE blend mode requires a mask for non-opaque surfaces. This mask will be used | ||
| 394 | * to clear the pixels in the destination surface. The other steps are explained below. | ||
| 395 | */ | ||
| 396 | if (blendmode == SDL_BLENDMODE_NONE && !isOpaque) { | ||
| 397 | mask = SDL_CreateSurface(final_rect->w, final_rect->h, SDL_PIXELFORMAT_ARGB8888); | ||
| 398 | if (!mask) { | ||
| 399 | result = false; | ||
| 400 | } else { | ||
| 401 | SDL_SetSurfaceBlendMode(mask, SDL_BLENDMODE_MOD); | ||
| 402 | } | ||
| 403 | } | ||
| 404 | |||
| 405 | /* Create a new surface should there be a format mismatch or if scaling, cropping, | ||
| 406 | * or modulation is required. It's possible to use the source surface directly otherwise. | ||
| 407 | */ | ||
| 408 | if (result && (blitRequired || applyModulation)) { | ||
| 409 | SDL_Rect scale_rect = tmp_rect; | ||
| 410 | src_scaled = SDL_CreateSurface(final_rect->w, final_rect->h, SDL_PIXELFORMAT_ARGB8888); | ||
| 411 | if (!src_scaled) { | ||
| 412 | result = false; | ||
| 413 | } else { | ||
| 414 | SDL_SetSurfaceBlendMode(src_clone, SDL_BLENDMODE_NONE); | ||
| 415 | result = SDL_BlitSurfaceScaled(src_clone, srcrect, src_scaled, &scale_rect, texture->scaleMode); | ||
| 416 | SDL_DestroySurface(src_clone); | ||
| 417 | src_clone = src_scaled; | ||
| 418 | src_scaled = NULL; | ||
| 419 | } | ||
| 420 | } | ||
| 421 | |||
| 422 | // SDLgfx_rotateSurface is going to make decisions depending on the blend mode. | ||
| 423 | SDL_SetSurfaceBlendMode(src_clone, blendmode); | ||
| 424 | |||
| 425 | if (result) { | ||
| 426 | SDL_Rect rect_dest; | ||
| 427 | double cangle, sangle; | ||
| 428 | |||
| 429 | SDLgfx_rotozoomSurfaceSizeTrig(tmp_rect.w, tmp_rect.h, angle, center, | ||
| 430 | &rect_dest, &cangle, &sangle); | ||
| 431 | src_rotated = SDLgfx_rotateSurface(src_clone, angle, | ||
| 432 | (texture->scaleMode == SDL_SCALEMODE_NEAREST) ? 0 : 1, flip & SDL_FLIP_HORIZONTAL, flip & SDL_FLIP_VERTICAL, | ||
| 433 | &rect_dest, cangle, sangle, center); | ||
| 434 | if (!src_rotated) { | ||
| 435 | result = false; | ||
| 436 | } | ||
| 437 | if (result && mask) { | ||
| 438 | // The mask needed for the NONE blend mode gets rotated with the same parameters. | ||
| 439 | mask_rotated = SDLgfx_rotateSurface(mask, angle, | ||
| 440 | false, 0, 0, | ||
| 441 | &rect_dest, cangle, sangle, center); | ||
| 442 | if (!mask_rotated) { | ||
| 443 | result = false; | ||
| 444 | } | ||
| 445 | } | ||
| 446 | if (result) { | ||
| 447 | |||
| 448 | tmp_rect.x = final_rect->x + rect_dest.x; | ||
| 449 | tmp_rect.y = final_rect->y + rect_dest.y; | ||
| 450 | tmp_rect.w = rect_dest.w; | ||
| 451 | tmp_rect.h = rect_dest.h; | ||
| 452 | |||
| 453 | /* The NONE blend mode needs some special care with non-opaque surfaces. | ||
| 454 | * Other blend modes or opaque surfaces can be blitted directly. | ||
| 455 | */ | ||
| 456 | if (blendmode != SDL_BLENDMODE_NONE || isOpaque) { | ||
| 457 | if (applyModulation == false) { | ||
| 458 | // If the modulation wasn't already applied, make it happen now. | ||
| 459 | SDL_SetSurfaceAlphaMod(src_rotated, alphaMod); | ||
| 460 | SDL_SetSurfaceColorMod(src_rotated, rMod, gMod, bMod); | ||
| 461 | } | ||
| 462 | // Renderer scaling, if needed | ||
| 463 | result = Blit_to_Screen(src_rotated, NULL, surface, &tmp_rect, scale_x, scale_y, texture->scaleMode); | ||
| 464 | } else { | ||
| 465 | /* The NONE blend mode requires three steps to get the pixels onto the destination surface. | ||
| 466 | * First, the area where the rotated pixels will be blitted to get set to zero. | ||
| 467 | * This is accomplished by simply blitting a mask with the NONE blend mode. | ||
| 468 | * The colorkey set by the rotate function will discard the correct pixels. | ||
| 469 | */ | ||
| 470 | SDL_Rect mask_rect = tmp_rect; | ||
| 471 | SDL_SetSurfaceBlendMode(mask_rotated, SDL_BLENDMODE_NONE); | ||
| 472 | // Renderer scaling, if needed | ||
| 473 | result = Blit_to_Screen(mask_rotated, NULL, surface, &mask_rect, scale_x, scale_y, texture->scaleMode); | ||
| 474 | if (result) { | ||
| 475 | /* The next step copies the alpha value. This is done with the BLEND blend mode and | ||
| 476 | * by modulating the source colors with 0. Since the destination is all zeros, this | ||
| 477 | * will effectively set the destination alpha to the source alpha. | ||
| 478 | */ | ||
| 479 | SDL_SetSurfaceColorMod(src_rotated, 0, 0, 0); | ||
| 480 | mask_rect = tmp_rect; | ||
| 481 | // Renderer scaling, if needed | ||
| 482 | result = Blit_to_Screen(src_rotated, NULL, surface, &mask_rect, scale_x, scale_y, texture->scaleMode); | ||
| 483 | if (result) { | ||
| 484 | /* The last step gets the color values in place. The ADD blend mode simply adds them to | ||
| 485 | * the destination (where the color values are all zero). However, because the ADD blend | ||
| 486 | * mode modulates the colors with the alpha channel, a surface without an alpha mask needs | ||
| 487 | * to be created. This makes all source pixels opaque and the colors get copied correctly. | ||
| 488 | */ | ||
| 489 | SDL_Surface *src_rotated_rgb = SDL_CreateSurfaceFrom(src_rotated->w, src_rotated->h, src_rotated->format, src_rotated->pixels, src_rotated->pitch); | ||
| 490 | if (!src_rotated_rgb) { | ||
| 491 | result = false; | ||
| 492 | } else { | ||
| 493 | SDL_SetSurfaceBlendMode(src_rotated_rgb, SDL_BLENDMODE_ADD); | ||
| 494 | // Renderer scaling, if needed | ||
| 495 | result = Blit_to_Screen(src_rotated_rgb, NULL, surface, &tmp_rect, scale_x, scale_y, texture->scaleMode); | ||
| 496 | SDL_DestroySurface(src_rotated_rgb); | ||
| 497 | } | ||
| 498 | } | ||
| 499 | } | ||
| 500 | SDL_DestroySurface(mask_rotated); | ||
| 501 | } | ||
| 502 | if (src_rotated) { | ||
| 503 | SDL_DestroySurface(src_rotated); | ||
| 504 | } | ||
| 505 | } | ||
| 506 | } | ||
| 507 | |||
| 508 | if (SDL_MUSTLOCK(src)) { | ||
| 509 | SDL_UnlockSurface(src); | ||
| 510 | } | ||
| 511 | if (mask) { | ||
| 512 | SDL_DestroySurface(mask); | ||
| 513 | } | ||
| 514 | if (src_clone) { | ||
| 515 | SDL_DestroySurface(src_clone); | ||
| 516 | } | ||
| 517 | return result; | ||
| 518 | } | ||
| 519 | |||
| 520 | typedef struct GeometryFillData | ||
| 521 | { | ||
| 522 | SDL_Point dst; | ||
| 523 | SDL_Color color; | ||
| 524 | } GeometryFillData; | ||
| 525 | |||
| 526 | typedef struct GeometryCopyData | ||
| 527 | { | ||
| 528 | SDL_Point src; | ||
| 529 | SDL_Point dst; | ||
| 530 | SDL_Color color; | ||
| 531 | } GeometryCopyData; | ||
| 532 | |||
| 533 | static bool SW_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture, | ||
| 534 | const float *xy, int xy_stride, const SDL_FColor *color, int color_stride, const float *uv, int uv_stride, | ||
| 535 | int num_vertices, const void *indices, int num_indices, int size_indices, | ||
| 536 | float scale_x, float scale_y) | ||
| 537 | { | ||
| 538 | int i; | ||
| 539 | int count = indices ? num_indices : num_vertices; | ||
| 540 | void *verts; | ||
| 541 | size_t sz = texture ? sizeof(GeometryCopyData) : sizeof(GeometryFillData); | ||
| 542 | const float color_scale = cmd->data.draw.color_scale; | ||
| 543 | |||
| 544 | verts = SDL_AllocateRenderVertices(renderer, count * sz, 0, &cmd->data.draw.first); | ||
| 545 | if (!verts) { | ||
| 546 | return false; | ||
| 547 | } | ||
| 548 | |||
| 549 | cmd->data.draw.count = count; | ||
| 550 | size_indices = indices ? size_indices : 0; | ||
| 551 | |||
| 552 | if (texture) { | ||
| 553 | GeometryCopyData *ptr = (GeometryCopyData *)verts; | ||
| 554 | for (i = 0; i < count; i++) { | ||
| 555 | int j; | ||
| 556 | float *xy_; | ||
| 557 | SDL_FColor col_; | ||
| 558 | float *uv_; | ||
| 559 | if (size_indices == 4) { | ||
| 560 | j = ((const Uint32 *)indices)[i]; | ||
| 561 | } else if (size_indices == 2) { | ||
| 562 | j = ((const Uint16 *)indices)[i]; | ||
| 563 | } else if (size_indices == 1) { | ||
| 564 | j = ((const Uint8 *)indices)[i]; | ||
| 565 | } else { | ||
| 566 | j = i; | ||
| 567 | } | ||
| 568 | |||
| 569 | xy_ = (float *)((char *)xy + j * xy_stride); | ||
| 570 | col_ = *(SDL_FColor *)((char *)color + j * color_stride); | ||
| 571 | |||
| 572 | uv_ = (float *)((char *)uv + j * uv_stride); | ||
| 573 | |||
| 574 | ptr->src.x = (int)(uv_[0] * texture->w); | ||
| 575 | ptr->src.y = (int)(uv_[1] * texture->h); | ||
| 576 | |||
| 577 | ptr->dst.x = (int)(xy_[0] * scale_x); | ||
| 578 | ptr->dst.y = (int)(xy_[1] * scale_y); | ||
| 579 | trianglepoint_2_fixedpoint(&ptr->dst); | ||
| 580 | |||
| 581 | ptr->color.r = (Uint8)SDL_roundf(SDL_clamp(col_.r * color_scale, 0.0f, 1.0f) * 255.0f); | ||
| 582 | ptr->color.g = (Uint8)SDL_roundf(SDL_clamp(col_.g * color_scale, 0.0f, 1.0f) * 255.0f); | ||
| 583 | ptr->color.b = (Uint8)SDL_roundf(SDL_clamp(col_.b * color_scale, 0.0f, 1.0f) * 255.0f); | ||
| 584 | ptr->color.a = (Uint8)SDL_roundf(SDL_clamp(col_.a, 0.0f, 1.0f) * 255.0f); | ||
| 585 | |||
| 586 | ptr++; | ||
| 587 | } | ||
| 588 | } else { | ||
| 589 | GeometryFillData *ptr = (GeometryFillData *)verts; | ||
| 590 | |||
| 591 | for (i = 0; i < count; i++) { | ||
| 592 | int j; | ||
| 593 | float *xy_; | ||
| 594 | SDL_FColor col_; | ||
| 595 | if (size_indices == 4) { | ||
| 596 | j = ((const Uint32 *)indices)[i]; | ||
| 597 | } else if (size_indices == 2) { | ||
| 598 | j = ((const Uint16 *)indices)[i]; | ||
| 599 | } else if (size_indices == 1) { | ||
| 600 | j = ((const Uint8 *)indices)[i]; | ||
| 601 | } else { | ||
| 602 | j = i; | ||
| 603 | } | ||
| 604 | |||
| 605 | xy_ = (float *)((char *)xy + j * xy_stride); | ||
| 606 | col_ = *(SDL_FColor *)((char *)color + j * color_stride); | ||
| 607 | |||
| 608 | ptr->dst.x = (int)(xy_[0] * scale_x); | ||
| 609 | ptr->dst.y = (int)(xy_[1] * scale_y); | ||
| 610 | trianglepoint_2_fixedpoint(&ptr->dst); | ||
| 611 | |||
| 612 | ptr->color.r = (Uint8)SDL_roundf(SDL_clamp(col_.r * color_scale, 0.0f, 1.0f) * 255.0f); | ||
| 613 | ptr->color.g = (Uint8)SDL_roundf(SDL_clamp(col_.g * color_scale, 0.0f, 1.0f) * 255.0f); | ||
| 614 | ptr->color.b = (Uint8)SDL_roundf(SDL_clamp(col_.b * color_scale, 0.0f, 1.0f) * 255.0f); | ||
| 615 | ptr->color.a = (Uint8)SDL_roundf(SDL_clamp(col_.a, 0.0f, 1.0f) * 255.0f); | ||
| 616 | |||
| 617 | ptr++; | ||
| 618 | } | ||
| 619 | } | ||
| 620 | return true; | ||
| 621 | } | ||
| 622 | |||
| 623 | static void PrepTextureForCopy(const SDL_RenderCommand *cmd, SW_DrawStateCache *drawstate) | ||
| 624 | { | ||
| 625 | const Uint8 r = drawstate->color.r; | ||
| 626 | const Uint8 g = drawstate->color.g; | ||
| 627 | const Uint8 b = drawstate->color.b; | ||
| 628 | const Uint8 a = drawstate->color.a; | ||
| 629 | const SDL_BlendMode blend = cmd->data.draw.blend; | ||
| 630 | SDL_Texture *texture = cmd->data.draw.texture; | ||
| 631 | SDL_Surface *surface = (SDL_Surface *)texture->internal; | ||
| 632 | const bool colormod = ((r & g & b) != 0xFF); | ||
| 633 | const bool alphamod = (a != 0xFF); | ||
| 634 | const bool blending = ((blend == SDL_BLENDMODE_ADD) || (blend == SDL_BLENDMODE_MOD) || (blend == SDL_BLENDMODE_MUL)); | ||
| 635 | |||
| 636 | if (colormod || alphamod || blending) { | ||
| 637 | SDL_SetSurfaceRLE(surface, 0); | ||
| 638 | } | ||
| 639 | |||
| 640 | // !!! FIXME: we can probably avoid some of these calls. | ||
| 641 | SDL_SetSurfaceColorMod(surface, r, g, b); | ||
| 642 | SDL_SetSurfaceAlphaMod(surface, a); | ||
| 643 | SDL_SetSurfaceBlendMode(surface, blend); | ||
| 644 | } | ||
| 645 | |||
| 646 | static void SetDrawState(SDL_Surface *surface, SW_DrawStateCache *drawstate) | ||
| 647 | { | ||
| 648 | if (drawstate->surface_cliprect_dirty) { | ||
| 649 | const SDL_Rect *viewport = drawstate->viewport; | ||
| 650 | const SDL_Rect *cliprect = drawstate->cliprect; | ||
| 651 | SDL_assert_release(viewport != NULL); // the higher level should have forced a SDL_RENDERCMD_SETVIEWPORT | ||
| 652 | |||
| 653 | if (cliprect && viewport) { | ||
| 654 | SDL_Rect clip_rect; | ||
| 655 | clip_rect.x = cliprect->x + viewport->x; | ||
| 656 | clip_rect.y = cliprect->y + viewport->y; | ||
| 657 | clip_rect.w = cliprect->w; | ||
| 658 | clip_rect.h = cliprect->h; | ||
| 659 | SDL_GetRectIntersection(viewport, &clip_rect, &clip_rect); | ||
| 660 | SDL_SetSurfaceClipRect(surface, &clip_rect); | ||
| 661 | } else { | ||
| 662 | SDL_SetSurfaceClipRect(surface, drawstate->viewport); | ||
| 663 | } | ||
| 664 | drawstate->surface_cliprect_dirty = false; | ||
| 665 | } | ||
| 666 | } | ||
| 667 | |||
| 668 | static void SW_InvalidateCachedState(SDL_Renderer *renderer) | ||
| 669 | { | ||
| 670 | // SW_DrawStateCache only lives during SW_RunCommandQueue, so nothing to do here! | ||
| 671 | } | ||
| 672 | |||
| 673 | |||
| 674 | static bool SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize) | ||
| 675 | { | ||
| 676 | SDL_Surface *surface = SW_ActivateRenderer(renderer); | ||
| 677 | SW_DrawStateCache drawstate; | ||
| 678 | |||
| 679 | if (!SDL_SurfaceValid(surface)) { | ||
| 680 | return false; | ||
| 681 | } | ||
| 682 | |||
| 683 | drawstate.viewport = NULL; | ||
| 684 | drawstate.cliprect = NULL; | ||
| 685 | drawstate.surface_cliprect_dirty = true; | ||
| 686 | drawstate.color.r = 0; | ||
| 687 | drawstate.color.g = 0; | ||
| 688 | drawstate.color.b = 0; | ||
| 689 | drawstate.color.a = 0; | ||
| 690 | |||
| 691 | while (cmd) { | ||
| 692 | switch (cmd->command) { | ||
| 693 | case SDL_RENDERCMD_SETDRAWCOLOR: | ||
| 694 | { | ||
| 695 | drawstate.color.r = (Uint8)SDL_roundf(SDL_clamp(cmd->data.color.color.r * cmd->data.color.color_scale, 0.0f, 1.0f) * 255.0f); | ||
| 696 | drawstate.color.g = (Uint8)SDL_roundf(SDL_clamp(cmd->data.color.color.g * cmd->data.color.color_scale, 0.0f, 1.0f) * 255.0f); | ||
| 697 | drawstate.color.b = (Uint8)SDL_roundf(SDL_clamp(cmd->data.color.color.b * cmd->data.color.color_scale, 0.0f, 1.0f) * 255.0f); | ||
| 698 | drawstate.color.a = (Uint8)SDL_roundf(SDL_clamp(cmd->data.color.color.a, 0.0f, 1.0f) * 255.0f); | ||
| 699 | break; | ||
| 700 | } | ||
| 701 | |||
| 702 | case SDL_RENDERCMD_SETVIEWPORT: | ||
| 703 | { | ||
| 704 | drawstate.viewport = &cmd->data.viewport.rect; | ||
| 705 | drawstate.surface_cliprect_dirty = true; | ||
| 706 | break; | ||
| 707 | } | ||
| 708 | |||
| 709 | case SDL_RENDERCMD_SETCLIPRECT: | ||
| 710 | { | ||
| 711 | drawstate.cliprect = cmd->data.cliprect.enabled ? &cmd->data.cliprect.rect : NULL; | ||
| 712 | drawstate.surface_cliprect_dirty = true; | ||
| 713 | break; | ||
| 714 | } | ||
| 715 | |||
| 716 | case SDL_RENDERCMD_CLEAR: | ||
| 717 | { | ||
| 718 | const Uint8 r = (Uint8)SDL_roundf(SDL_clamp(cmd->data.color.color.r * cmd->data.color.color_scale, 0.0f, 1.0f) * 255.0f); | ||
| 719 | const Uint8 g = (Uint8)SDL_roundf(SDL_clamp(cmd->data.color.color.g * cmd->data.color.color_scale, 0.0f, 1.0f) * 255.0f); | ||
| 720 | const Uint8 b = (Uint8)SDL_roundf(SDL_clamp(cmd->data.color.color.b * cmd->data.color.color_scale, 0.0f, 1.0f) * 255.0f); | ||
| 721 | const Uint8 a = (Uint8)SDL_roundf(SDL_clamp(cmd->data.color.color.a, 0.0f, 1.0f) * 255.0f); | ||
| 722 | // By definition the clear ignores the clip rect | ||
| 723 | SDL_SetSurfaceClipRect(surface, NULL); | ||
| 724 | SDL_FillSurfaceRect(surface, NULL, SDL_MapSurfaceRGBA(surface, r, g, b, a)); | ||
| 725 | drawstate.surface_cliprect_dirty = true; | ||
| 726 | break; | ||
| 727 | } | ||
| 728 | |||
| 729 | case SDL_RENDERCMD_DRAW_POINTS: | ||
| 730 | { | ||
| 731 | const Uint8 r = drawstate.color.r; | ||
| 732 | const Uint8 g = drawstate.color.g; | ||
| 733 | const Uint8 b = drawstate.color.b; | ||
| 734 | const Uint8 a = drawstate.color.a; | ||
| 735 | const int count = (int)cmd->data.draw.count; | ||
| 736 | SDL_Point *verts = (SDL_Point *)(((Uint8 *)vertices) + cmd->data.draw.first); | ||
| 737 | const SDL_BlendMode blend = cmd->data.draw.blend; | ||
| 738 | SetDrawState(surface, &drawstate); | ||
| 739 | |||
| 740 | // Apply viewport | ||
| 741 | if (drawstate.viewport && (drawstate.viewport->x || drawstate.viewport->y)) { | ||
| 742 | int i; | ||
| 743 | for (i = 0; i < count; i++) { | ||
| 744 | verts[i].x += drawstate.viewport->x; | ||
| 745 | verts[i].y += drawstate.viewport->y; | ||
| 746 | } | ||
| 747 | } | ||
| 748 | |||
| 749 | if (blend == SDL_BLENDMODE_NONE) { | ||
| 750 | SDL_DrawPoints(surface, verts, count, SDL_MapSurfaceRGBA(surface, r, g, b, a)); | ||
| 751 | } else { | ||
| 752 | SDL_BlendPoints(surface, verts, count, blend, r, g, b, a); | ||
| 753 | } | ||
| 754 | break; | ||
| 755 | } | ||
| 756 | |||
| 757 | case SDL_RENDERCMD_DRAW_LINES: | ||
| 758 | { | ||
| 759 | const Uint8 r = drawstate.color.r; | ||
| 760 | const Uint8 g = drawstate.color.g; | ||
| 761 | const Uint8 b = drawstate.color.b; | ||
| 762 | const Uint8 a = drawstate.color.a; | ||
| 763 | const int count = (int)cmd->data.draw.count; | ||
| 764 | SDL_Point *verts = (SDL_Point *)(((Uint8 *)vertices) + cmd->data.draw.first); | ||
| 765 | const SDL_BlendMode blend = cmd->data.draw.blend; | ||
| 766 | SetDrawState(surface, &drawstate); | ||
| 767 | |||
| 768 | // Apply viewport | ||
| 769 | if (drawstate.viewport && (drawstate.viewport->x || drawstate.viewport->y)) { | ||
| 770 | int i; | ||
| 771 | for (i = 0; i < count; i++) { | ||
| 772 | verts[i].x += drawstate.viewport->x; | ||
| 773 | verts[i].y += drawstate.viewport->y; | ||
| 774 | } | ||
| 775 | } | ||
| 776 | |||
| 777 | if (blend == SDL_BLENDMODE_NONE) { | ||
| 778 | SDL_DrawLines(surface, verts, count, SDL_MapSurfaceRGBA(surface, r, g, b, a)); | ||
| 779 | } else { | ||
| 780 | SDL_BlendLines(surface, verts, count, blend, r, g, b, a); | ||
| 781 | } | ||
| 782 | break; | ||
| 783 | } | ||
| 784 | |||
| 785 | case SDL_RENDERCMD_FILL_RECTS: | ||
| 786 | { | ||
| 787 | const Uint8 r = drawstate.color.r; | ||
| 788 | const Uint8 g = drawstate.color.g; | ||
| 789 | const Uint8 b = drawstate.color.b; | ||
| 790 | const Uint8 a = drawstate.color.a; | ||
| 791 | const int count = (int)cmd->data.draw.count; | ||
| 792 | SDL_Rect *verts = (SDL_Rect *)(((Uint8 *)vertices) + cmd->data.draw.first); | ||
| 793 | const SDL_BlendMode blend = cmd->data.draw.blend; | ||
| 794 | SetDrawState(surface, &drawstate); | ||
| 795 | |||
| 796 | // Apply viewport | ||
| 797 | if (drawstate.viewport && (drawstate.viewport->x || drawstate.viewport->y)) { | ||
| 798 | int i; | ||
| 799 | for (i = 0; i < count; i++) { | ||
| 800 | verts[i].x += drawstate.viewport->x; | ||
| 801 | verts[i].y += drawstate.viewport->y; | ||
| 802 | } | ||
| 803 | } | ||
| 804 | |||
| 805 | if (blend == SDL_BLENDMODE_NONE) { | ||
| 806 | SDL_FillSurfaceRects(surface, verts, count, SDL_MapSurfaceRGBA(surface, r, g, b, a)); | ||
| 807 | } else { | ||
| 808 | SDL_BlendFillRects(surface, verts, count, blend, r, g, b, a); | ||
| 809 | } | ||
| 810 | break; | ||
| 811 | } | ||
| 812 | |||
| 813 | case SDL_RENDERCMD_COPY: | ||
| 814 | { | ||
| 815 | SDL_Rect *verts = (SDL_Rect *)(((Uint8 *)vertices) + cmd->data.draw.first); | ||
| 816 | const SDL_Rect *srcrect = verts; | ||
| 817 | SDL_Rect *dstrect = verts + 1; | ||
| 818 | SDL_Texture *texture = cmd->data.draw.texture; | ||
| 819 | SDL_Surface *src = (SDL_Surface *)texture->internal; | ||
| 820 | |||
| 821 | SetDrawState(surface, &drawstate); | ||
| 822 | |||
| 823 | PrepTextureForCopy(cmd, &drawstate); | ||
| 824 | |||
| 825 | // Apply viewport | ||
| 826 | if (drawstate.viewport && (drawstate.viewport->x || drawstate.viewport->y)) { | ||
| 827 | dstrect->x += drawstate.viewport->x; | ||
| 828 | dstrect->y += drawstate.viewport->y; | ||
| 829 | } | ||
| 830 | |||
| 831 | if (srcrect->w == dstrect->w && srcrect->h == dstrect->h) { | ||
| 832 | SDL_BlitSurface(src, srcrect, surface, dstrect); | ||
| 833 | } else { | ||
| 834 | /* If scaling is ever done, permanently disable RLE (which doesn't support scaling) | ||
| 835 | * to avoid potentially frequent RLE encoding/decoding. | ||
| 836 | */ | ||
| 837 | SDL_SetSurfaceRLE(surface, 0); | ||
| 838 | |||
| 839 | // Prevent to do scaling + clipping on viewport boundaries as it may lose proportion | ||
| 840 | if (dstrect->x < 0 || dstrect->y < 0 || dstrect->x + dstrect->w > surface->w || dstrect->y + dstrect->h > surface->h) { | ||
| 841 | SDL_Surface *tmp = SDL_CreateSurface(dstrect->w, dstrect->h, src->format); | ||
| 842 | // Scale to an intermediate surface, then blit | ||
| 843 | if (tmp) { | ||
| 844 | SDL_Rect r; | ||
| 845 | SDL_BlendMode blendmode; | ||
| 846 | Uint8 alphaMod, rMod, gMod, bMod; | ||
| 847 | |||
| 848 | SDL_GetSurfaceBlendMode(src, &blendmode); | ||
| 849 | SDL_GetSurfaceAlphaMod(src, &alphaMod); | ||
| 850 | SDL_GetSurfaceColorMod(src, &rMod, &gMod, &bMod); | ||
| 851 | |||
| 852 | r.x = 0; | ||
| 853 | r.y = 0; | ||
| 854 | r.w = dstrect->w; | ||
| 855 | r.h = dstrect->h; | ||
| 856 | |||
| 857 | SDL_SetSurfaceBlendMode(src, SDL_BLENDMODE_NONE); | ||
| 858 | SDL_SetSurfaceColorMod(src, 255, 255, 255); | ||
| 859 | SDL_SetSurfaceAlphaMod(src, 255); | ||
| 860 | |||
| 861 | SDL_BlitSurfaceScaled(src, srcrect, tmp, &r, texture->scaleMode); | ||
| 862 | |||
| 863 | SDL_SetSurfaceColorMod(tmp, rMod, gMod, bMod); | ||
| 864 | SDL_SetSurfaceAlphaMod(tmp, alphaMod); | ||
| 865 | SDL_SetSurfaceBlendMode(tmp, blendmode); | ||
| 866 | |||
| 867 | SDL_BlitSurface(tmp, NULL, surface, dstrect); | ||
| 868 | SDL_DestroySurface(tmp); | ||
| 869 | // No need to set back r/g/b/a/blendmode to 'src' since it's done in PrepTextureForCopy() | ||
| 870 | } | ||
| 871 | } else { | ||
| 872 | SDL_BlitSurfaceScaled(src, srcrect, surface, dstrect, texture->scaleMode); | ||
| 873 | } | ||
| 874 | } | ||
| 875 | break; | ||
| 876 | } | ||
| 877 | |||
| 878 | case SDL_RENDERCMD_COPY_EX: | ||
| 879 | { | ||
| 880 | CopyExData *copydata = (CopyExData *)(((Uint8 *)vertices) + cmd->data.draw.first); | ||
| 881 | SetDrawState(surface, &drawstate); | ||
| 882 | PrepTextureForCopy(cmd, &drawstate); | ||
| 883 | |||
| 884 | // Apply viewport | ||
| 885 | if (drawstate.viewport && (drawstate.viewport->x || drawstate.viewport->y)) { | ||
| 886 | copydata->dstrect.x += drawstate.viewport->x; | ||
| 887 | copydata->dstrect.y += drawstate.viewport->y; | ||
| 888 | } | ||
| 889 | |||
| 890 | SW_RenderCopyEx(renderer, surface, cmd->data.draw.texture, ©data->srcrect, | ||
| 891 | ©data->dstrect, copydata->angle, ©data->center, copydata->flip, | ||
| 892 | copydata->scale_x, copydata->scale_y); | ||
| 893 | break; | ||
| 894 | } | ||
| 895 | |||
| 896 | case SDL_RENDERCMD_GEOMETRY: | ||
| 897 | { | ||
| 898 | int i; | ||
| 899 | SDL_Rect *verts = (SDL_Rect *)(((Uint8 *)vertices) + cmd->data.draw.first); | ||
| 900 | const int count = (int)cmd->data.draw.count; | ||
| 901 | SDL_Texture *texture = cmd->data.draw.texture; | ||
| 902 | const SDL_BlendMode blend = cmd->data.draw.blend; | ||
| 903 | |||
| 904 | SetDrawState(surface, &drawstate); | ||
| 905 | |||
| 906 | if (texture) { | ||
| 907 | SDL_Surface *src = (SDL_Surface *)texture->internal; | ||
| 908 | |||
| 909 | GeometryCopyData *ptr = (GeometryCopyData *)verts; | ||
| 910 | |||
| 911 | PrepTextureForCopy(cmd, &drawstate); | ||
| 912 | |||
| 913 | // Apply viewport | ||
| 914 | if (drawstate.viewport && (drawstate.viewport->x || drawstate.viewport->y)) { | ||
| 915 | SDL_Point vp; | ||
| 916 | vp.x = drawstate.viewport->x; | ||
| 917 | vp.y = drawstate.viewport->y; | ||
| 918 | trianglepoint_2_fixedpoint(&vp); | ||
| 919 | for (i = 0; i < count; i++) { | ||
| 920 | ptr[i].dst.x += vp.x; | ||
| 921 | ptr[i].dst.y += vp.y; | ||
| 922 | } | ||
| 923 | } | ||
| 924 | |||
| 925 | for (i = 0; i < count; i += 3, ptr += 3) { | ||
| 926 | SDL_SW_BlitTriangle( | ||
| 927 | src, | ||
| 928 | &(ptr[0].src), &(ptr[1].src), &(ptr[2].src), | ||
| 929 | surface, | ||
| 930 | &(ptr[0].dst), &(ptr[1].dst), &(ptr[2].dst), | ||
| 931 | ptr[0].color, ptr[1].color, ptr[2].color, | ||
| 932 | cmd->data.draw.texture_address_mode); | ||
| 933 | } | ||
| 934 | } else { | ||
| 935 | GeometryFillData *ptr = (GeometryFillData *)verts; | ||
| 936 | |||
| 937 | // Apply viewport | ||
| 938 | if (drawstate.viewport && (drawstate.viewport->x || drawstate.viewport->y)) { | ||
| 939 | SDL_Point vp; | ||
| 940 | vp.x = drawstate.viewport->x; | ||
| 941 | vp.y = drawstate.viewport->y; | ||
| 942 | trianglepoint_2_fixedpoint(&vp); | ||
| 943 | for (i = 0; i < count; i++) { | ||
| 944 | ptr[i].dst.x += vp.x; | ||
| 945 | ptr[i].dst.y += vp.y; | ||
| 946 | } | ||
| 947 | } | ||
| 948 | |||
| 949 | for (i = 0; i < count; i += 3, ptr += 3) { | ||
| 950 | SDL_SW_FillTriangle(surface, &(ptr[0].dst), &(ptr[1].dst), &(ptr[2].dst), blend, ptr[0].color, ptr[1].color, ptr[2].color); | ||
| 951 | } | ||
| 952 | } | ||
| 953 | break; | ||
| 954 | } | ||
| 955 | |||
| 956 | case SDL_RENDERCMD_NO_OP: | ||
| 957 | break; | ||
| 958 | } | ||
| 959 | |||
| 960 | cmd = cmd->next; | ||
| 961 | } | ||
| 962 | |||
| 963 | return true; | ||
| 964 | } | ||
| 965 | |||
| 966 | static SDL_Surface *SW_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect) | ||
| 967 | { | ||
| 968 | SDL_Surface *surface = SW_ActivateRenderer(renderer); | ||
| 969 | void *pixels; | ||
| 970 | |||
| 971 | if (!SDL_SurfaceValid(surface)) { | ||
| 972 | return NULL; | ||
| 973 | } | ||
| 974 | |||
| 975 | /* NOTE: The rect is already adjusted according to the viewport by | ||
| 976 | * SDL_RenderReadPixels. | ||
| 977 | */ | ||
| 978 | |||
| 979 | if (rect->x < 0 || rect->x + rect->w > surface->w || | ||
| 980 | rect->y < 0 || rect->y + rect->h > surface->h) { | ||
| 981 | SDL_SetError("Tried to read outside of surface bounds"); | ||
| 982 | return NULL; | ||
| 983 | } | ||
| 984 | |||
| 985 | pixels = (void *)((Uint8 *)surface->pixels + | ||
| 986 | rect->y * surface->pitch + | ||
| 987 | rect->x * surface->fmt->bytes_per_pixel); | ||
| 988 | |||
| 989 | return SDL_DuplicatePixels(rect->w, rect->h, surface->format, SDL_COLORSPACE_SRGB, pixels, surface->pitch); | ||
| 990 | } | ||
| 991 | |||
| 992 | static bool SW_RenderPresent(SDL_Renderer *renderer) | ||
| 993 | { | ||
| 994 | SDL_Window *window = renderer->window; | ||
| 995 | |||
| 996 | if (!window) { | ||
| 997 | return false; | ||
| 998 | } | ||
| 999 | return SDL_UpdateWindowSurface(window); | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | static void SW_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture) | ||
| 1003 | { | ||
| 1004 | SDL_Surface *surface = (SDL_Surface *)texture->internal; | ||
| 1005 | |||
| 1006 | SDL_DestroySurface(surface); | ||
| 1007 | } | ||
| 1008 | |||
| 1009 | static void SW_DestroyRenderer(SDL_Renderer *renderer) | ||
| 1010 | { | ||
| 1011 | SDL_Window *window = renderer->window; | ||
| 1012 | SW_RenderData *data = (SW_RenderData *)renderer->internal; | ||
| 1013 | |||
| 1014 | if (window) { | ||
| 1015 | SDL_DestroyWindowSurface(window); | ||
| 1016 | } | ||
| 1017 | SDL_free(data); | ||
| 1018 | } | ||
| 1019 | |||
| 1020 | static void SW_SelectBestFormats(SDL_Renderer *renderer, SDL_PixelFormat format) | ||
| 1021 | { | ||
| 1022 | // Prefer the format used by the framebuffer by default. | ||
| 1023 | SDL_AddSupportedTextureFormat(renderer, format); | ||
| 1024 | |||
| 1025 | switch (format) { | ||
| 1026 | case SDL_PIXELFORMAT_XRGB4444: | ||
| 1027 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ARGB4444); | ||
| 1028 | break; | ||
| 1029 | case SDL_PIXELFORMAT_XBGR4444: | ||
| 1030 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ABGR4444); | ||
| 1031 | break; | ||
| 1032 | case SDL_PIXELFORMAT_ARGB4444: | ||
| 1033 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XRGB4444); | ||
| 1034 | break; | ||
| 1035 | case SDL_PIXELFORMAT_ABGR4444: | ||
| 1036 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XBGR4444); | ||
| 1037 | break; | ||
| 1038 | |||
| 1039 | case SDL_PIXELFORMAT_XRGB1555: | ||
| 1040 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ARGB1555); | ||
| 1041 | break; | ||
| 1042 | case SDL_PIXELFORMAT_XBGR1555: | ||
| 1043 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ABGR1555); | ||
| 1044 | break; | ||
| 1045 | case SDL_PIXELFORMAT_ARGB1555: | ||
| 1046 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XRGB1555); | ||
| 1047 | break; | ||
| 1048 | case SDL_PIXELFORMAT_ABGR1555: | ||
| 1049 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XBGR1555); | ||
| 1050 | break; | ||
| 1051 | |||
| 1052 | case SDL_PIXELFORMAT_XRGB8888: | ||
| 1053 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ARGB8888); | ||
| 1054 | break; | ||
| 1055 | case SDL_PIXELFORMAT_RGBX8888: | ||
| 1056 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBA8888); | ||
| 1057 | break; | ||
| 1058 | case SDL_PIXELFORMAT_XBGR8888: | ||
| 1059 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ABGR8888); | ||
| 1060 | break; | ||
| 1061 | case SDL_PIXELFORMAT_BGRX8888: | ||
| 1062 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_BGRA8888); | ||
| 1063 | break; | ||
| 1064 | case SDL_PIXELFORMAT_ARGB8888: | ||
| 1065 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XRGB8888); | ||
| 1066 | break; | ||
| 1067 | case SDL_PIXELFORMAT_RGBA8888: | ||
| 1068 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBX8888); | ||
| 1069 | break; | ||
| 1070 | case SDL_PIXELFORMAT_ABGR8888: | ||
| 1071 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XBGR8888); | ||
| 1072 | break; | ||
| 1073 | case SDL_PIXELFORMAT_BGRA8888: | ||
| 1074 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_BGRX8888); | ||
| 1075 | break; | ||
| 1076 | default: | ||
| 1077 | break; | ||
| 1078 | } | ||
| 1079 | |||
| 1080 | /* Ensure that we always have a SDL_PACKEDLAYOUT_8888 format. Having a matching component order increases the | ||
| 1081 | * chances of getting a fast path for blitting. | ||
| 1082 | */ | ||
| 1083 | if (SDL_ISPIXELFORMAT_PACKED(format)) { | ||
| 1084 | if (SDL_PIXELLAYOUT(format) != SDL_PACKEDLAYOUT_8888) { | ||
| 1085 | switch (SDL_PIXELORDER(format)) { | ||
| 1086 | case SDL_PACKEDORDER_BGRX: | ||
| 1087 | case SDL_PACKEDORDER_BGRA: | ||
| 1088 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_BGRX8888); | ||
| 1089 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_BGRA8888); | ||
| 1090 | break; | ||
| 1091 | case SDL_PACKEDORDER_RGBX: | ||
| 1092 | case SDL_PACKEDORDER_RGBA: | ||
| 1093 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBX8888); | ||
| 1094 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBA8888); | ||
| 1095 | break; | ||
| 1096 | case SDL_PACKEDORDER_XBGR: | ||
| 1097 | case SDL_PACKEDORDER_ABGR: | ||
| 1098 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XBGR8888); | ||
| 1099 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ABGR8888); | ||
| 1100 | break; | ||
| 1101 | case SDL_PACKEDORDER_XRGB: | ||
| 1102 | case SDL_PACKEDORDER_ARGB: | ||
| 1103 | default: | ||
| 1104 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XRGB8888); | ||
| 1105 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ARGB8888); | ||
| 1106 | break; | ||
| 1107 | } | ||
| 1108 | } | ||
| 1109 | } else { | ||
| 1110 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XRGB8888); | ||
| 1111 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ARGB8888); | ||
| 1112 | } | ||
| 1113 | } | ||
| 1114 | |||
| 1115 | bool SW_CreateRendererForSurface(SDL_Renderer *renderer, SDL_Surface *surface, SDL_PropertiesID create_props) | ||
| 1116 | { | ||
| 1117 | SW_RenderData *data; | ||
| 1118 | |||
| 1119 | if (!SDL_SurfaceValid(surface)) { | ||
| 1120 | return SDL_InvalidParamError("surface"); | ||
| 1121 | } | ||
| 1122 | |||
| 1123 | renderer->software = true; | ||
| 1124 | |||
| 1125 | data = (SW_RenderData *)SDL_calloc(1, sizeof(*data)); | ||
| 1126 | if (!data) { | ||
| 1127 | return false; | ||
| 1128 | } | ||
| 1129 | data->surface = surface; | ||
| 1130 | data->window = surface; | ||
| 1131 | |||
| 1132 | renderer->WindowEvent = SW_WindowEvent; | ||
| 1133 | renderer->GetOutputSize = SW_GetOutputSize; | ||
| 1134 | renderer->CreateTexture = SW_CreateTexture; | ||
| 1135 | renderer->UpdateTexture = SW_UpdateTexture; | ||
| 1136 | renderer->LockTexture = SW_LockTexture; | ||
| 1137 | renderer->UnlockTexture = SW_UnlockTexture; | ||
| 1138 | renderer->SetTextureScaleMode = SW_SetTextureScaleMode; | ||
| 1139 | renderer->SetRenderTarget = SW_SetRenderTarget; | ||
| 1140 | renderer->QueueSetViewport = SW_QueueNoOp; | ||
| 1141 | renderer->QueueSetDrawColor = SW_QueueNoOp; | ||
| 1142 | renderer->QueueDrawPoints = SW_QueueDrawPoints; | ||
| 1143 | renderer->QueueDrawLines = SW_QueueDrawPoints; // lines and points queue vertices the same way. | ||
| 1144 | renderer->QueueFillRects = SW_QueueFillRects; | ||
| 1145 | renderer->QueueCopy = SW_QueueCopy; | ||
| 1146 | renderer->QueueCopyEx = SW_QueueCopyEx; | ||
| 1147 | renderer->QueueGeometry = SW_QueueGeometry; | ||
| 1148 | renderer->InvalidateCachedState = SW_InvalidateCachedState; | ||
| 1149 | renderer->RunCommandQueue = SW_RunCommandQueue; | ||
| 1150 | renderer->RenderReadPixels = SW_RenderReadPixels; | ||
| 1151 | renderer->RenderPresent = SW_RenderPresent; | ||
| 1152 | renderer->DestroyTexture = SW_DestroyTexture; | ||
| 1153 | renderer->DestroyRenderer = SW_DestroyRenderer; | ||
| 1154 | renderer->internal = data; | ||
| 1155 | SW_InvalidateCachedState(renderer); | ||
| 1156 | |||
| 1157 | renderer->name = SW_RenderDriver.name; | ||
| 1158 | |||
| 1159 | SW_SelectBestFormats(renderer, surface->format); | ||
| 1160 | |||
| 1161 | SDL_SetupRendererColorspace(renderer, create_props); | ||
| 1162 | |||
| 1163 | if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) { | ||
| 1164 | return SDL_SetError("Unsupported output colorspace"); | ||
| 1165 | } | ||
| 1166 | |||
| 1167 | return true; | ||
| 1168 | } | ||
| 1169 | |||
| 1170 | static bool SW_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_PropertiesID create_props) | ||
| 1171 | { | ||
| 1172 | // Set the vsync hint based on our flags, if it's not already set | ||
| 1173 | const char *hint = SDL_GetHint(SDL_HINT_RENDER_VSYNC); | ||
| 1174 | const bool no_hint_set = (!hint || !*hint); | ||
| 1175 | |||
| 1176 | if (no_hint_set) { | ||
| 1177 | if (SDL_GetBooleanProperty(create_props, SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_NUMBER, 0)) { | ||
| 1178 | SDL_SetHint(SDL_HINT_RENDER_VSYNC, "1"); | ||
| 1179 | } else { | ||
| 1180 | SDL_SetHint(SDL_HINT_RENDER_VSYNC, "0"); | ||
| 1181 | } | ||
| 1182 | } | ||
| 1183 | |||
| 1184 | SDL_Surface *surface = SDL_GetWindowSurface(window); | ||
| 1185 | |||
| 1186 | // Reset the vsync hint if we set it above | ||
| 1187 | if (no_hint_set) { | ||
| 1188 | SDL_SetHint(SDL_HINT_RENDER_VSYNC, ""); | ||
| 1189 | } | ||
| 1190 | |||
| 1191 | if (!SDL_SurfaceValid(surface)) { | ||
| 1192 | return false; | ||
| 1193 | } | ||
| 1194 | |||
| 1195 | return SW_CreateRendererForSurface(renderer, surface, create_props); | ||
| 1196 | } | ||
| 1197 | |||
| 1198 | SDL_RenderDriver SW_RenderDriver = { | ||
| 1199 | SW_CreateRenderer, SDL_SOFTWARE_RENDERER | ||
| 1200 | }; | ||
| 1201 | |||
| 1202 | #endif // SDL_VIDEO_RENDER_SW | ||
diff --git a/contrib/SDL-3.2.8/src/render/software/SDL_render_sw_c.h b/contrib/SDL-3.2.8/src/render/software/SDL_render_sw_c.h new file mode 100644 index 0000000..40d3c3a --- /dev/null +++ b/contrib/SDL-3.2.8/src/render/software/SDL_render_sw_c.h | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | /* | ||
| 2 | Simple DirectMedia Layer | ||
| 3 | Copyright (C) 1997-2025 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 | |||
| 22 | #ifndef SDL_render_sw_c_h_ | ||
| 23 | #define SDL_render_sw_c_h_ | ||
| 24 | |||
| 25 | extern bool SW_CreateRendererForSurface(SDL_Renderer *renderer, SDL_Surface *surface, SDL_PropertiesID create_props); | ||
| 26 | |||
| 27 | #endif // SDL_render_sw_c_h_ | ||
diff --git a/contrib/SDL-3.2.8/src/render/software/SDL_rotate.c b/contrib/SDL-3.2.8/src/render/software/SDL_rotate.c new file mode 100644 index 0000000..516ba8a --- /dev/null +++ b/contrib/SDL-3.2.8/src/render/software/SDL_rotate.c | |||
| @@ -0,0 +1,612 @@ | |||
| 1 | /* | ||
| 2 | |||
| 3 | SDL_rotate.c: rotates 32bit or 8bit surfaces | ||
| 4 | |||
| 5 | Shamelessly stolen from SDL_gfx by Andreas Schiffler. Original copyright follows: | ||
| 6 | |||
| 7 | Copyright (C) 2001-2011 Andreas Schiffler | ||
| 8 | |||
| 9 | This software is provided 'as-is', without any express or implied | ||
| 10 | warranty. In no event will the authors be held liable for any damages | ||
| 11 | arising from the use of this software. | ||
| 12 | |||
| 13 | Permission is granted to anyone to use this software for any purpose, | ||
| 14 | including commercial applications, and to alter it and redistribute it | ||
| 15 | freely, subject to the following restrictions: | ||
| 16 | |||
| 17 | 1. The origin of this software must not be misrepresented; you must not | ||
| 18 | claim that you wrote the original software. If you use this software | ||
| 19 | in a product, an acknowledgment in the product documentation would be | ||
| 20 | appreciated but is not required. | ||
| 21 | |||
| 22 | 2. Altered source versions must be plainly marked as such, and must not be | ||
| 23 | misrepresented as being the original software. | ||
| 24 | |||
| 25 | 3. This notice may not be removed or altered from any source | ||
| 26 | distribution. | ||
| 27 | |||
| 28 | Andreas Schiffler -- aschiffler at ferzkopp dot net | ||
| 29 | |||
| 30 | */ | ||
| 31 | #include "SDL_internal.h" | ||
| 32 | |||
| 33 | #ifdef SDL_VIDEO_RENDER_SW | ||
| 34 | |||
| 35 | #if defined(SDL_PLATFORM_WINDOWS) | ||
| 36 | #include "../../core/windows/SDL_windows.h" | ||
| 37 | #endif | ||
| 38 | |||
| 39 | #include "SDL_rotate.h" | ||
| 40 | |||
| 41 | #include "../../video/SDL_surface_c.h" | ||
| 42 | |||
| 43 | // ---- Internally used structures | ||
| 44 | |||
| 45 | /** | ||
| 46 | A 32 bit RGBA pixel. | ||
| 47 | */ | ||
| 48 | typedef struct tColorRGBA | ||
| 49 | { | ||
| 50 | Uint8 r; | ||
| 51 | Uint8 g; | ||
| 52 | Uint8 b; | ||
| 53 | Uint8 a; | ||
| 54 | } tColorRGBA; | ||
| 55 | |||
| 56 | /** | ||
| 57 | A 8bit Y/palette pixel. | ||
| 58 | */ | ||
| 59 | typedef struct tColorY | ||
| 60 | { | ||
| 61 | Uint8 y; | ||
| 62 | } tColorY; | ||
| 63 | |||
| 64 | /** | ||
| 65 | Number of guard rows added to destination surfaces. | ||
| 66 | |||
| 67 | This is a simple but effective workaround for observed issues. | ||
| 68 | These rows allocate extra memory and are then hidden from the surface. | ||
| 69 | Rows are added to the end of destination surfaces when they are allocated. | ||
| 70 | This catches any potential overflows which seem to happen with | ||
| 71 | just the right src image dimensions and scale/rotation and can lead | ||
| 72 | to a situation where the program can segfault. | ||
| 73 | */ | ||
| 74 | #define GUARD_ROWS (2) | ||
| 75 | |||
| 76 | /** | ||
| 77 | Returns colorkey info for a surface | ||
| 78 | */ | ||
| 79 | static Uint32 get_colorkey(SDL_Surface *src) | ||
| 80 | { | ||
| 81 | Uint32 key = 0; | ||
| 82 | if (SDL_SurfaceHasColorKey(src)) { | ||
| 83 | SDL_GetSurfaceColorKey(src, &key); | ||
| 84 | } | ||
| 85 | return key; | ||
| 86 | } | ||
| 87 | |||
| 88 | // rotate (sx, sy) by (angle, center) into (dx, dy) | ||
| 89 | static void rotate(double sx, double sy, double sinangle, double cosangle, const SDL_FPoint *center, double *dx, double *dy) | ||
| 90 | { | ||
| 91 | sx -= center->x; | ||
| 92 | sy -= center->y; | ||
| 93 | |||
| 94 | *dx = cosangle * sx - sinangle * sy; | ||
| 95 | *dy = sinangle * sx + cosangle * sy; | ||
| 96 | |||
| 97 | *dx += center->x; | ||
| 98 | *dy += center->y; | ||
| 99 | } | ||
| 100 | |||
| 101 | /** | ||
| 102 | Internal target surface sizing function for rotations with trig result return. | ||
| 103 | |||
| 104 | \param width The source surface width. | ||
| 105 | \param height The source surface height. | ||
| 106 | \param angle The angle to rotate in degrees. | ||
| 107 | \param center The center of ratation | ||
| 108 | \param rect_dest Bounding box of rotated rectangle | ||
| 109 | \param cangle The sine of the angle | ||
| 110 | \param sangle The cosine of the angle | ||
| 111 | |||
| 112 | */ | ||
| 113 | void SDLgfx_rotozoomSurfaceSizeTrig(int width, int height, double angle, const SDL_FPoint *center, | ||
| 114 | SDL_Rect *rect_dest, double *cangle, double *sangle) | ||
| 115 | { | ||
| 116 | int minx, maxx, miny, maxy; | ||
| 117 | double radangle; | ||
| 118 | double x0, x1, x2, x3; | ||
| 119 | double y0, y1, y2, y3; | ||
| 120 | double sinangle; | ||
| 121 | double cosangle; | ||
| 122 | |||
| 123 | radangle = angle * (SDL_PI_D / 180.0); | ||
| 124 | sinangle = SDL_sin(radangle); | ||
| 125 | cosangle = SDL_cos(radangle); | ||
| 126 | |||
| 127 | /* | ||
| 128 | * Determine destination width and height by rotating a source box, at pixel center | ||
| 129 | */ | ||
| 130 | rotate(0.5, 0.5, sinangle, cosangle, center, &x0, &y0); | ||
| 131 | rotate(width - 0.5, 0.5, sinangle, cosangle, center, &x1, &y1); | ||
| 132 | rotate(0.5, height - 0.5, sinangle, cosangle, center, &x2, &y2); | ||
| 133 | rotate(width - 0.5, height - 0.5, sinangle, cosangle, center, &x3, &y3); | ||
| 134 | |||
| 135 | minx = (int)SDL_floor(SDL_min(SDL_min(x0, x1), SDL_min(x2, x3))); | ||
| 136 | maxx = (int)SDL_ceil(SDL_max(SDL_max(x0, x1), SDL_max(x2, x3))); | ||
| 137 | |||
| 138 | miny = (int)SDL_floor(SDL_min(SDL_min(y0, y1), SDL_min(y2, y3))); | ||
| 139 | maxy = (int)SDL_ceil(SDL_max(SDL_max(y0, y1), SDL_max(y2, y3))); | ||
| 140 | |||
| 141 | rect_dest->w = maxx - minx; | ||
| 142 | rect_dest->h = maxy - miny; | ||
| 143 | rect_dest->x = minx; | ||
| 144 | rect_dest->y = miny; | ||
| 145 | |||
| 146 | // reverse the angle because our rotations are clockwise | ||
| 147 | *sangle = -sinangle; | ||
| 148 | *cangle = cosangle; | ||
| 149 | |||
| 150 | { | ||
| 151 | // The trig code below gets the wrong size (due to FP inaccuracy?) when angle is a multiple of 90 degrees | ||
| 152 | int angle90 = (int)(angle / 90); | ||
| 153 | if (angle90 == angle / 90) { // if the angle is a multiple of 90 degrees | ||
| 154 | angle90 %= 4; | ||
| 155 | if (angle90 < 0) { | ||
| 156 | angle90 += 4; // 0:0 deg, 1:90 deg, 2:180 deg, 3:270 deg | ||
| 157 | } | ||
| 158 | |||
| 159 | if (angle90 & 1) { | ||
| 160 | rect_dest->w = height; | ||
| 161 | rect_dest->h = width; | ||
| 162 | *cangle = 0; | ||
| 163 | *sangle = angle90 == 1 ? -1 : 1; // reversed because our rotations are clockwise | ||
| 164 | } else { | ||
| 165 | rect_dest->w = width; | ||
| 166 | rect_dest->h = height; | ||
| 167 | *cangle = angle90 == 0 ? 1 : -1; | ||
| 168 | *sangle = 0; | ||
| 169 | } | ||
| 170 | } | ||
| 171 | } | ||
| 172 | } | ||
| 173 | |||
| 174 | // Computes source pointer X/Y increments for a rotation that's a multiple of 90 degrees. | ||
| 175 | static void computeSourceIncrements90(SDL_Surface *src, int bpp, int angle, int flipx, int flipy, | ||
| 176 | int *sincx, int *sincy, int *signx, int *signy) | ||
| 177 | { | ||
| 178 | int pitch = flipy ? -src->pitch : src->pitch; | ||
| 179 | if (flipx) { | ||
| 180 | bpp = -bpp; | ||
| 181 | } | ||
| 182 | switch (angle) { // 0:0 deg, 1:90 deg, 2:180 deg, 3:270 deg | ||
| 183 | case 0: | ||
| 184 | *sincx = bpp; | ||
| 185 | *sincy = pitch - src->w * *sincx; | ||
| 186 | *signx = *signy = 1; | ||
| 187 | break; | ||
| 188 | case 1: | ||
| 189 | *sincx = -pitch; | ||
| 190 | *sincy = bpp - *sincx * src->h; | ||
| 191 | *signx = 1; | ||
| 192 | *signy = -1; | ||
| 193 | break; | ||
| 194 | case 2: | ||
| 195 | *sincx = -bpp; | ||
| 196 | *sincy = -src->w * *sincx - pitch; | ||
| 197 | *signx = *signy = -1; | ||
| 198 | break; | ||
| 199 | case 3: | ||
| 200 | default: | ||
| 201 | *sincx = pitch; | ||
| 202 | *sincy = -*sincx * src->h - bpp; | ||
| 203 | *signx = -1; | ||
| 204 | *signy = 1; | ||
| 205 | break; | ||
| 206 | } | ||
| 207 | if (flipx) { | ||
| 208 | *signx = -*signx; | ||
| 209 | } | ||
| 210 | if (flipy) { | ||
| 211 | *signy = -*signy; | ||
| 212 | } | ||
| 213 | } | ||
| 214 | |||
| 215 | // Performs a relatively fast rotation/flip when the angle is a multiple of 90 degrees. | ||
| 216 | #define TRANSFORM_SURFACE_90(pixelType) \ | ||
| 217 | int dy, dincy = dst->pitch - dst->w * sizeof(pixelType), sincx, sincy, signx, signy; \ | ||
| 218 | Uint8 *sp = (Uint8 *)src->pixels, *dp = (Uint8 *)dst->pixels, *de; \ | ||
| 219 | \ | ||
| 220 | computeSourceIncrements90(src, sizeof(pixelType), angle, flipx, flipy, &sincx, &sincy, &signx, &signy); \ | ||
| 221 | if (signx < 0) \ | ||
| 222 | sp += (src->w - 1) * sizeof(pixelType); \ | ||
| 223 | if (signy < 0) \ | ||
| 224 | sp += (src->h - 1) * src->pitch; \ | ||
| 225 | \ | ||
| 226 | for (dy = 0; dy < dst->h; sp += sincy, dp += dincy, dy++) { \ | ||
| 227 | if (sincx == sizeof(pixelType)) { /* if advancing src and dest equally, use SDL_memcpy */ \ | ||
| 228 | SDL_memcpy(dp, sp, dst->w * sizeof(pixelType)); \ | ||
| 229 | sp += dst->w * sizeof(pixelType); \ | ||
| 230 | dp += dst->w * sizeof(pixelType); \ | ||
| 231 | } else { \ | ||
| 232 | for (de = dp + dst->w * sizeof(pixelType); dp != de; sp += sincx, dp += sizeof(pixelType)) { \ | ||
| 233 | *(pixelType *)dp = *(pixelType *)sp; \ | ||
| 234 | } \ | ||
| 235 | } \ | ||
| 236 | } | ||
| 237 | |||
| 238 | static void transformSurfaceRGBA90(SDL_Surface *src, SDL_Surface *dst, int angle, int flipx, int flipy) | ||
| 239 | { | ||
| 240 | TRANSFORM_SURFACE_90(tColorRGBA); | ||
| 241 | } | ||
| 242 | |||
| 243 | static void transformSurfaceY90(SDL_Surface *src, SDL_Surface *dst, int angle, int flipx, int flipy) | ||
| 244 | { | ||
| 245 | TRANSFORM_SURFACE_90(tColorY); | ||
| 246 | } | ||
| 247 | |||
| 248 | #undef TRANSFORM_SURFACE_90 | ||
| 249 | |||
| 250 | /** | ||
| 251 | Internal 32 bit rotozoomer with optional anti-aliasing. | ||
| 252 | |||
| 253 | Rotates and zooms 32 bit RGBA/ABGR 'src' surface to 'dst' surface based on the control | ||
| 254 | parameters by scanning the destination surface and applying optionally anti-aliasing | ||
| 255 | by bilinear interpolation. | ||
| 256 | Assumes src and dst surfaces are of 32 bit depth. | ||
| 257 | Assumes dst surface was allocated with the correct dimensions. | ||
| 258 | |||
| 259 | \param src Source surface. | ||
| 260 | \param dst Destination surface. | ||
| 261 | \param isin Integer version of sine of angle. | ||
| 262 | \param icos Integer version of cosine of angle. | ||
| 263 | \param flipx Flag indicating horizontal mirroring should be applied. | ||
| 264 | \param flipy Flag indicating vertical mirroring should be applied. | ||
| 265 | \param smooth Flag indicating anti-aliasing should be used. | ||
| 266 | \param rect_dest destination coordinates | ||
| 267 | \param center true center. | ||
| 268 | */ | ||
| 269 | static void transformSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst, int isin, int icos, | ||
| 270 | int flipx, int flipy, int smooth, | ||
| 271 | const SDL_Rect *rect_dest, | ||
| 272 | const SDL_FPoint *center) | ||
| 273 | { | ||
| 274 | int sw, sh; | ||
| 275 | int cx, cy; | ||
| 276 | tColorRGBA c00, c01, c10, c11, cswap; | ||
| 277 | tColorRGBA *pc, *sp; | ||
| 278 | int gap; | ||
| 279 | const int fp_half = (1 << 15); | ||
| 280 | |||
| 281 | /* | ||
| 282 | * Variable setup | ||
| 283 | */ | ||
| 284 | sw = src->w - 1; | ||
| 285 | sh = src->h - 1; | ||
| 286 | pc = (tColorRGBA *)dst->pixels; | ||
| 287 | gap = dst->pitch - dst->w * 4; | ||
| 288 | cx = (int)(center->x * 65536.0); | ||
| 289 | cy = (int)(center->y * 65536.0); | ||
| 290 | |||
| 291 | /* | ||
| 292 | * Switch between interpolating and non-interpolating code | ||
| 293 | */ | ||
| 294 | if (smooth) { | ||
| 295 | int y; | ||
| 296 | for (y = 0; y < dst->h; y++) { | ||
| 297 | int x; | ||
| 298 | double src_x = ((double)rect_dest->x + 0 + 0.5 - center->x); | ||
| 299 | double src_y = ((double)rect_dest->y + y + 0.5 - center->y); | ||
| 300 | int sdx = (int)((icos * src_x - isin * src_y) + cx - fp_half); | ||
| 301 | int sdy = (int)((isin * src_x + icos * src_y) + cy - fp_half); | ||
| 302 | for (x = 0; x < dst->w; x++) { | ||
| 303 | int dx = (sdx >> 16); | ||
| 304 | int dy = (sdy >> 16); | ||
| 305 | if (flipx) { | ||
| 306 | dx = sw - dx; | ||
| 307 | } | ||
| 308 | if (flipy) { | ||
| 309 | dy = sh - dy; | ||
| 310 | } | ||
| 311 | if ((dx > -1) && (dy > -1) && (dx < (src->w - 1)) && (dy < (src->h - 1))) { | ||
| 312 | int ex, ey; | ||
| 313 | int t1, t2; | ||
| 314 | sp = (tColorRGBA *)((Uint8 *)src->pixels + src->pitch * dy) + dx; | ||
| 315 | c00 = *sp; | ||
| 316 | sp += 1; | ||
| 317 | c01 = *sp; | ||
| 318 | sp += (src->pitch / 4); | ||
| 319 | c11 = *sp; | ||
| 320 | sp -= 1; | ||
| 321 | c10 = *sp; | ||
| 322 | if (flipx) { | ||
| 323 | cswap = c00; | ||
| 324 | c00 = c01; | ||
| 325 | c01 = cswap; | ||
| 326 | cswap = c10; | ||
| 327 | c10 = c11; | ||
| 328 | c11 = cswap; | ||
| 329 | } | ||
| 330 | if (flipy) { | ||
| 331 | cswap = c00; | ||
| 332 | c00 = c10; | ||
| 333 | c10 = cswap; | ||
| 334 | cswap = c01; | ||
| 335 | c01 = c11; | ||
| 336 | c11 = cswap; | ||
| 337 | } | ||
| 338 | /* | ||
| 339 | * Interpolate colors | ||
| 340 | */ | ||
| 341 | ex = (sdx & 0xffff); | ||
| 342 | ey = (sdy & 0xffff); | ||
| 343 | t1 = ((((c01.r - c00.r) * ex) >> 16) + c00.r) & 0xff; | ||
| 344 | t2 = ((((c11.r - c10.r) * ex) >> 16) + c10.r) & 0xff; | ||
| 345 | pc->r = (Uint8)((((t2 - t1) * ey) >> 16) + t1); | ||
| 346 | t1 = ((((c01.g - c00.g) * ex) >> 16) + c00.g) & 0xff; | ||
| 347 | t2 = ((((c11.g - c10.g) * ex) >> 16) + c10.g) & 0xff; | ||
| 348 | pc->g = (Uint8)((((t2 - t1) * ey) >> 16) + t1); | ||
| 349 | t1 = ((((c01.b - c00.b) * ex) >> 16) + c00.b) & 0xff; | ||
| 350 | t2 = ((((c11.b - c10.b) * ex) >> 16) + c10.b) & 0xff; | ||
| 351 | pc->b = (Uint8)((((t2 - t1) * ey) >> 16) + t1); | ||
| 352 | t1 = ((((c01.a - c00.a) * ex) >> 16) + c00.a) & 0xff; | ||
| 353 | t2 = ((((c11.a - c10.a) * ex) >> 16) + c10.a) & 0xff; | ||
| 354 | pc->a = (Uint8)((((t2 - t1) * ey) >> 16) + t1); | ||
| 355 | } | ||
| 356 | sdx += icos; | ||
| 357 | sdy += isin; | ||
| 358 | pc++; | ||
| 359 | } | ||
| 360 | pc = (tColorRGBA *)((Uint8 *)pc + gap); | ||
| 361 | } | ||
| 362 | } else { | ||
| 363 | int y; | ||
| 364 | for (y = 0; y < dst->h; y++) { | ||
| 365 | int x; | ||
| 366 | double src_x = ((double)rect_dest->x + 0 + 0.5 - center->x); | ||
| 367 | double src_y = ((double)rect_dest->y + y + 0.5 - center->y); | ||
| 368 | int sdx = (int)((icos * src_x - isin * src_y) + cx - fp_half); | ||
| 369 | int sdy = (int)((isin * src_x + icos * src_y) + cy - fp_half); | ||
| 370 | for (x = 0; x < dst->w; x++) { | ||
| 371 | int dx = (sdx >> 16); | ||
| 372 | int dy = (sdy >> 16); | ||
| 373 | if ((unsigned)dx < (unsigned)src->w && (unsigned)dy < (unsigned)src->h) { | ||
| 374 | if (flipx) { | ||
| 375 | dx = sw - dx; | ||
| 376 | } | ||
| 377 | if (flipy) { | ||
| 378 | dy = sh - dy; | ||
| 379 | } | ||
| 380 | *pc = *((tColorRGBA *)((Uint8 *)src->pixels + src->pitch * dy) + dx); | ||
| 381 | } | ||
| 382 | sdx += icos; | ||
| 383 | sdy += isin; | ||
| 384 | pc++; | ||
| 385 | } | ||
| 386 | pc = (tColorRGBA *)((Uint8 *)pc + gap); | ||
| 387 | } | ||
| 388 | } | ||
| 389 | } | ||
| 390 | |||
| 391 | /** | ||
| 392 | |||
| 393 | Rotates and zooms 8 bit palette/Y 'src' surface to 'dst' surface without smoothing. | ||
| 394 | |||
| 395 | Rotates and zooms 8 bit RGBA/ABGR 'src' surface to 'dst' surface based on the control | ||
| 396 | parameters by scanning the destination surface. | ||
| 397 | Assumes src and dst surfaces are of 8 bit depth. | ||
| 398 | Assumes dst surface was allocated with the correct dimensions. | ||
| 399 | |||
| 400 | \param src Source surface. | ||
| 401 | \param dst Destination surface. | ||
| 402 | \param isin Integer version of sine of angle. | ||
| 403 | \param icos Integer version of cosine of angle. | ||
| 404 | \param flipx Flag indicating horizontal mirroring should be applied. | ||
| 405 | \param flipy Flag indicating vertical mirroring should be applied. | ||
| 406 | \param rect_dest destination coordinates | ||
| 407 | \param center true center. | ||
| 408 | */ | ||
| 409 | static void transformSurfaceY(SDL_Surface *src, SDL_Surface *dst, int isin, int icos, int flipx, int flipy, | ||
| 410 | const SDL_Rect *rect_dest, | ||
| 411 | const SDL_FPoint *center) | ||
| 412 | { | ||
| 413 | int sw, sh; | ||
| 414 | int cx, cy; | ||
| 415 | tColorY *pc; | ||
| 416 | int gap; | ||
| 417 | const int fp_half = (1 << 15); | ||
| 418 | int y; | ||
| 419 | |||
| 420 | /* | ||
| 421 | * Variable setup | ||
| 422 | */ | ||
| 423 | sw = src->w - 1; | ||
| 424 | sh = src->h - 1; | ||
| 425 | pc = (tColorY *)dst->pixels; | ||
| 426 | gap = dst->pitch - dst->w; | ||
| 427 | cx = (int)(center->x * 65536.0); | ||
| 428 | cy = (int)(center->y * 65536.0); | ||
| 429 | |||
| 430 | /* | ||
| 431 | * Clear surface to colorkey | ||
| 432 | */ | ||
| 433 | SDL_memset(pc, (int)(get_colorkey(src) & 0xff), (size_t)dst->pitch * dst->h); | ||
| 434 | /* | ||
| 435 | * Iterate through destination surface | ||
| 436 | */ | ||
| 437 | for (y = 0; y < dst->h; y++) { | ||
| 438 | int x; | ||
| 439 | double src_x = ((double)rect_dest->x + 0 + 0.5 - center->x); | ||
| 440 | double src_y = ((double)rect_dest->y + y + 0.5 - center->y); | ||
| 441 | int sdx = (int)((icos * src_x - isin * src_y) + cx - fp_half); | ||
| 442 | int sdy = (int)((isin * src_x + icos * src_y) + cy - fp_half); | ||
| 443 | for (x = 0; x < dst->w; x++) { | ||
| 444 | int dx = (sdx >> 16); | ||
| 445 | int dy = (sdy >> 16); | ||
| 446 | if ((unsigned)dx < (unsigned)src->w && (unsigned)dy < (unsigned)src->h) { | ||
| 447 | if (flipx) { | ||
| 448 | dx = sw - dx; | ||
| 449 | } | ||
| 450 | if (flipy) { | ||
| 451 | dy = sh - dy; | ||
| 452 | } | ||
| 453 | *pc = *((tColorY *)src->pixels + src->pitch * dy + dx); | ||
| 454 | } | ||
| 455 | sdx += icos; | ||
| 456 | sdy += isin; | ||
| 457 | pc++; | ||
| 458 | } | ||
| 459 | pc += gap; | ||
| 460 | } | ||
| 461 | } | ||
| 462 | |||
| 463 | /** | ||
| 464 | Rotates and zooms a surface with different horizontal and vertival scaling factors and optional anti-aliasing. | ||
| 465 | |||
| 466 | Rotates a 32-bit or 8-bit 'src' surface to newly created 'dst' surface. | ||
| 467 | 'angle' is the rotation in degrees, 'center' the rotation center. If 'smooth' is set | ||
| 468 | then the destination 32-bit surface is anti-aliased. 8-bit surfaces must have a colorkey. 32-bit | ||
| 469 | surfaces must have a 8888 layout with red, green, blue and alpha masks (any ordering goes). | ||
| 470 | The blend mode of the 'src' surface has some effects on generation of the 'dst' surface: The NONE | ||
| 471 | mode will set the BLEND mode on the 'dst' surface. The MOD mode either generates a white 'dst' | ||
| 472 | surface and sets the colorkey or fills the it with the colorkey before copying the pixels. | ||
| 473 | When using the NONE and MOD modes, color and alpha modulation must be applied before using this function. | ||
| 474 | |||
| 475 | \param src The surface to rotozoom. | ||
| 476 | \param angle The angle to rotate in degrees. | ||
| 477 | \param smooth Antialiasing flag; set to SMOOTHING_ON to enable. | ||
| 478 | \param flipx Set to 1 to flip the image horizontally | ||
| 479 | \param flipy Set to 1 to flip the image vertically | ||
| 480 | \param rect_dest The destination rect bounding box | ||
| 481 | \param cangle The angle cosine | ||
| 482 | \param sangle The angle sine | ||
| 483 | \param center The true coordinate of the center of rotation | ||
| 484 | \return The new rotated surface. | ||
| 485 | |||
| 486 | */ | ||
| 487 | |||
| 488 | SDL_Surface *SDLgfx_rotateSurface(SDL_Surface *src, double angle, int smooth, int flipx, int flipy, | ||
| 489 | const SDL_Rect *rect_dest, double cangle, double sangle, const SDL_FPoint *center) | ||
| 490 | { | ||
| 491 | SDL_Surface *rz_dst; | ||
| 492 | int is8bit, angle90; | ||
| 493 | SDL_BlendMode blendmode; | ||
| 494 | Uint32 colorkey = 0; | ||
| 495 | bool colorKeyAvailable = false; | ||
| 496 | double sangleinv, cangleinv; | ||
| 497 | |||
| 498 | // Sanity check | ||
| 499 | if (!SDL_SurfaceValid(src)) { | ||
| 500 | return NULL; | ||
| 501 | } | ||
| 502 | |||
| 503 | if (SDL_SurfaceHasColorKey(src)) { | ||
| 504 | if (SDL_GetSurfaceColorKey(src, &colorkey)) { | ||
| 505 | colorKeyAvailable = true; | ||
| 506 | } | ||
| 507 | } | ||
| 508 | // This function requires a 32-bit surface or 8-bit surface with a colorkey | ||
| 509 | is8bit = src->fmt->bits_per_pixel == 8 && colorKeyAvailable; | ||
| 510 | if (!(is8bit || (src->fmt->bits_per_pixel == 32 && SDL_ISPIXELFORMAT_ALPHA(src->format)))) { | ||
| 511 | return NULL; | ||
| 512 | } | ||
| 513 | |||
| 514 | // Calculate target factors from sine/cosine and zoom | ||
| 515 | sangleinv = sangle * 65536.0; | ||
| 516 | cangleinv = cangle * 65536.0; | ||
| 517 | |||
| 518 | // Alloc space to completely contain the rotated surface | ||
| 519 | rz_dst = NULL; | ||
| 520 | if (is8bit) { | ||
| 521 | // Target surface is 8 bit | ||
| 522 | rz_dst = SDL_CreateSurface(rect_dest->w, rect_dest->h + GUARD_ROWS, src->format); | ||
| 523 | if (rz_dst) { | ||
| 524 | SDL_SetSurfacePalette(rz_dst, src->palette); | ||
| 525 | } | ||
| 526 | } else { | ||
| 527 | // Target surface is 32 bit with source RGBA ordering | ||
| 528 | rz_dst = SDL_CreateSurface(rect_dest->w, rect_dest->h + GUARD_ROWS, src->format); | ||
| 529 | } | ||
| 530 | |||
| 531 | // Check target | ||
| 532 | if (!rz_dst) { | ||
| 533 | return NULL; | ||
| 534 | } | ||
| 535 | |||
| 536 | // Adjust for guard rows | ||
| 537 | rz_dst->h = rect_dest->h; | ||
| 538 | |||
| 539 | SDL_GetSurfaceBlendMode(src, &blendmode); | ||
| 540 | |||
| 541 | if (colorKeyAvailable) { | ||
| 542 | // If available, the colorkey will be used to discard the pixels that are outside of the rotated area. | ||
| 543 | SDL_SetSurfaceColorKey(rz_dst, true, colorkey); | ||
| 544 | SDL_FillSurfaceRect(rz_dst, NULL, colorkey); | ||
| 545 | } else if (blendmode == SDL_BLENDMODE_NONE) { | ||
| 546 | blendmode = SDL_BLENDMODE_BLEND; | ||
| 547 | } else if (blendmode == SDL_BLENDMODE_MOD || blendmode == SDL_BLENDMODE_MUL) { | ||
| 548 | /* Without a colorkey, the target texture has to be white for the MOD and MUL blend mode so | ||
| 549 | * that the pixels outside the rotated area don't affect the destination surface. | ||
| 550 | */ | ||
| 551 | colorkey = SDL_MapSurfaceRGBA(rz_dst, 255, 255, 255, 0); | ||
| 552 | SDL_FillSurfaceRect(rz_dst, NULL, colorkey); | ||
| 553 | /* Setting a white colorkey for the destination surface makes the final blit discard | ||
| 554 | * all pixels outside of the rotated area. This doesn't interfere with anything because | ||
| 555 | * white pixels are already a no-op and the MOD blend mode does not interact with alpha. | ||
| 556 | */ | ||
| 557 | SDL_SetSurfaceColorKey(rz_dst, true, colorkey); | ||
| 558 | } | ||
| 559 | |||
| 560 | SDL_SetSurfaceBlendMode(rz_dst, blendmode); | ||
| 561 | |||
| 562 | // Lock source surface | ||
| 563 | if (SDL_MUSTLOCK(src)) { | ||
| 564 | if (!SDL_LockSurface(src)) { | ||
| 565 | SDL_DestroySurface(rz_dst); | ||
| 566 | return NULL; | ||
| 567 | } | ||
| 568 | } | ||
| 569 | |||
| 570 | /* check if the rotation is a multiple of 90 degrees so we can take a fast path and also somewhat reduce | ||
| 571 | * the off-by-one problem in transformSurfaceRGBA that expresses itself when the rotation is near | ||
| 572 | * multiples of 90 degrees. | ||
| 573 | */ | ||
| 574 | angle90 = (int)(angle / 90); | ||
| 575 | if (angle90 == angle / 90) { | ||
| 576 | angle90 %= 4; | ||
| 577 | if (angle90 < 0) { | ||
| 578 | angle90 += 4; // 0:0 deg, 1:90 deg, 2:180 deg, 3:270 deg | ||
| 579 | } | ||
| 580 | |||
| 581 | } else { | ||
| 582 | angle90 = -1; | ||
| 583 | } | ||
| 584 | |||
| 585 | if (is8bit) { | ||
| 586 | // Call the 8-bit transformation routine to do the rotation | ||
| 587 | if (angle90 >= 0) { | ||
| 588 | transformSurfaceY90(src, rz_dst, angle90, flipx, flipy); | ||
| 589 | } else { | ||
| 590 | transformSurfaceY(src, rz_dst, (int)sangleinv, (int)cangleinv, | ||
| 591 | flipx, flipy, rect_dest, center); | ||
| 592 | } | ||
| 593 | } else { | ||
| 594 | // Call the 32-bit transformation routine to do the rotation | ||
| 595 | if (angle90 >= 0) { | ||
| 596 | transformSurfaceRGBA90(src, rz_dst, angle90, flipx, flipy); | ||
| 597 | } else { | ||
| 598 | transformSurfaceRGBA(src, rz_dst, (int)sangleinv, (int)cangleinv, | ||
| 599 | flipx, flipy, smooth, rect_dest, center); | ||
| 600 | } | ||
| 601 | } | ||
| 602 | |||
| 603 | // Unlock source surface | ||
| 604 | if (SDL_MUSTLOCK(src)) { | ||
| 605 | SDL_UnlockSurface(src); | ||
| 606 | } | ||
| 607 | |||
| 608 | // Return rotated surface | ||
| 609 | return rz_dst; | ||
| 610 | } | ||
| 611 | |||
| 612 | #endif // SDL_VIDEO_RENDER_SW | ||
diff --git a/contrib/SDL-3.2.8/src/render/software/SDL_rotate.h b/contrib/SDL-3.2.8/src/render/software/SDL_rotate.h new file mode 100644 index 0000000..ecf84f7 --- /dev/null +++ b/contrib/SDL-3.2.8/src/render/software/SDL_rotate.h | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | /* | ||
| 2 | Simple DirectMedia Layer | ||
| 3 | Copyright (C) 1997-2025 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 | |||
| 22 | #ifndef SDL_rotate_h_ | ||
| 23 | #define SDL_rotate_h_ | ||
| 24 | |||
| 25 | extern SDL_Surface *SDLgfx_rotateSurface(SDL_Surface *src, double angle, int smooth, int flipx, int flipy, | ||
| 26 | const SDL_Rect *rect_dest, double cangle, double sangle, const SDL_FPoint *center); | ||
| 27 | extern void SDLgfx_rotozoomSurfaceSizeTrig(int width, int height, double angle, const SDL_FPoint *center, | ||
| 28 | SDL_Rect *rect_dest, double *cangle, double *sangle); | ||
| 29 | |||
| 30 | #endif // SDL_rotate_h_ | ||
diff --git a/contrib/SDL-3.2.8/src/render/software/SDL_triangle.c b/contrib/SDL-3.2.8/src/render/software/SDL_triangle.c new file mode 100644 index 0000000..c4e16d1 --- /dev/null +++ b/contrib/SDL-3.2.8/src/render/software/SDL_triangle.c | |||
| @@ -0,0 +1,945 @@ | |||
| 1 | /* | ||
| 2 | Simple DirectMedia Layer | ||
| 3 | Copyright (C) 1997-2025 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 | #ifdef SDL_VIDEO_RENDER_SW | ||
| 24 | |||
| 25 | #include <limits.h> | ||
| 26 | |||
| 27 | #include "SDL_triangle.h" | ||
| 28 | |||
| 29 | #include "../../video/SDL_surface_c.h" | ||
| 30 | |||
| 31 | /* fixed points bits precision | ||
| 32 | * Set to 1, so that it can start rendering with middle of a pixel precision. | ||
| 33 | * It doesn't need to be increased. | ||
| 34 | * But, if increased too much, it overflows (srcx, srcy) coordinates used for filling with texture. | ||
| 35 | * (which could be turned to int64). | ||
| 36 | */ | ||
| 37 | #define FP_BITS 1 | ||
| 38 | |||
| 39 | #define COLOR_EQ(c1, c2) ((c1).r == (c2).r && (c1).g == (c2).g && (c1).b == (c2).b && (c1).a == (c2).a) | ||
| 40 | |||
| 41 | static void SDL_BlitTriangle_Slow(SDL_BlitInfo *info, | ||
| 42 | SDL_Point s2_x_area, SDL_Rect dstrect, int area, int bias_w0, int bias_w1, int bias_w2, | ||
| 43 | int d2d1_y, int d1d2_x, int d0d2_y, int d2d0_x, int d1d0_y, int d0d1_x, | ||
| 44 | int s2s0_x, int s2s1_x, int s2s0_y, int s2s1_y, int w0_row, int w1_row, int w2_row, | ||
| 45 | SDL_Color c0, SDL_Color c1, SDL_Color c2, bool is_uniform, SDL_TextureAddressMode texture_address_mode); | ||
| 46 | |||
| 47 | #if 0 | ||
| 48 | bool SDL_BlitTriangle(SDL_Surface *src, const SDL_Point srcpoints[3], SDL_Surface *dst, const SDL_Point dstpoints[3]) | ||
| 49 | { | ||
| 50 | int i; | ||
| 51 | SDL_Point points[6]; | ||
| 52 | |||
| 53 | if (src == NULL || dst == NULL) { | ||
| 54 | return false; | ||
| 55 | } | ||
| 56 | |||
| 57 | for (i = 0; i < 3; i++) { | ||
| 58 | if (srcpoints[i].x < 0 || srcpoints[i].y < 0 || srcpoints[i].x >= src->w || srcpoints[i].y >= src->h) { | ||
| 59 | return SDL_SetError("Values of 'srcpoints' out of bounds"); | ||
| 60 | } | ||
| 61 | } | ||
| 62 | |||
| 63 | points[0] = srcpoints[0]; | ||
| 64 | points[1] = dstpoints[0]; | ||
| 65 | points[2] = srcpoints[1]; | ||
| 66 | points[3] = dstpoints[1]; | ||
| 67 | points[4] = srcpoints[2]; | ||
| 68 | points[5] = dstpoints[2]; | ||
| 69 | for (i = 0; i < 3; i++) { | ||
| 70 | trianglepoint_2_fixedpoint(&points[2 * i + 1]); | ||
| 71 | } | ||
| 72 | return SDL_SW_BlitTriangle(src, dst, points); | ||
| 73 | } | ||
| 74 | |||
| 75 | bool SDL_FillTriangle(SDL_Surface *dst, const SDL_Point points[3], Uint32 color) | ||
| 76 | { | ||
| 77 | int i; | ||
| 78 | SDL_Point points_tmp[3]; | ||
| 79 | if (dst == NULL) { | ||
| 80 | return false; | ||
| 81 | } | ||
| 82 | for (i = 0; i < 3; i++) { | ||
| 83 | points_tmp[i] = points[i]; | ||
| 84 | trianglepoint_2_fixedpoint(&points_tmp[i]); | ||
| 85 | } | ||
| 86 | return SDL_SW_FillTriangle(dst, points_tmp, SDL_BLENDMODE_NONE, color); | ||
| 87 | } | ||
| 88 | #endif | ||
| 89 | |||
| 90 | // cross product AB x AC | ||
| 91 | static Sint64 cross_product(const SDL_Point *a, const SDL_Point *b, int c_x, int c_y) | ||
| 92 | { | ||
| 93 | return ((Sint64)(b->x - a->x)) * ((Sint64)(c_y - a->y)) - ((Sint64)(b->y - a->y)) * ((Sint64)(c_x - a->x)); | ||
| 94 | } | ||
| 95 | |||
| 96 | // check for top left rules | ||
| 97 | static bool is_top_left(const SDL_Point *a, const SDL_Point *b, int is_clockwise) | ||
| 98 | { | ||
| 99 | if (is_clockwise) { | ||
| 100 | if (a->y == b->y && a->x < b->x) { | ||
| 101 | return true; | ||
| 102 | } | ||
| 103 | if (b->y < a->y) { | ||
| 104 | return true; | ||
| 105 | } | ||
| 106 | } else { | ||
| 107 | if (a->y == b->y && b->x < a->x) { | ||
| 108 | return true; | ||
| 109 | } | ||
| 110 | if (a->y < b->y) { | ||
| 111 | return true; | ||
| 112 | } | ||
| 113 | } | ||
| 114 | return false; | ||
| 115 | } | ||
| 116 | |||
| 117 | // x = (y << FP_BITS) | ||
| 118 | // prevent runtime error: left shift of negative value | ||
| 119 | #define PRECOMP(x, y) \ | ||
| 120 | val = y; \ | ||
| 121 | if (val >= 0) { \ | ||
| 122 | x = val << FP_BITS; \ | ||
| 123 | } else { \ | ||
| 124 | val *= -1; \ | ||
| 125 | x = val << FP_BITS; \ | ||
| 126 | x *= -1; \ | ||
| 127 | } | ||
| 128 | |||
| 129 | void trianglepoint_2_fixedpoint(SDL_Point *a) | ||
| 130 | { | ||
| 131 | int val; | ||
| 132 | PRECOMP(a->x, a->x); | ||
| 133 | PRECOMP(a->y, a->y); | ||
| 134 | } | ||
| 135 | |||
| 136 | // bounding rect of three points (in fixed point) | ||
| 137 | static void bounding_rect_fixedpoint(const SDL_Point *a, const SDL_Point *b, const SDL_Point *c, SDL_Rect *r) | ||
| 138 | { | ||
| 139 | int min_x = SDL_min(a->x, SDL_min(b->x, c->x)); | ||
| 140 | int max_x = SDL_max(a->x, SDL_max(b->x, c->x)); | ||
| 141 | int min_y = SDL_min(a->y, SDL_min(b->y, c->y)); | ||
| 142 | int max_y = SDL_max(a->y, SDL_max(b->y, c->y)); | ||
| 143 | // points are in fixed point, shift back | ||
| 144 | r->x = min_x >> FP_BITS; | ||
| 145 | r->y = min_y >> FP_BITS; | ||
| 146 | r->w = (max_x - min_x) >> FP_BITS; | ||
| 147 | r->h = (max_y - min_y) >> FP_BITS; | ||
| 148 | } | ||
| 149 | |||
| 150 | // bounding rect of three points | ||
| 151 | static void bounding_rect(const SDL_Point *a, const SDL_Point *b, const SDL_Point *c, SDL_Rect *r) | ||
| 152 | { | ||
| 153 | int min_x = SDL_min(a->x, SDL_min(b->x, c->x)); | ||
| 154 | int max_x = SDL_max(a->x, SDL_max(b->x, c->x)); | ||
| 155 | int min_y = SDL_min(a->y, SDL_min(b->y, c->y)); | ||
| 156 | int max_y = SDL_max(a->y, SDL_max(b->y, c->y)); | ||
| 157 | r->x = min_x; | ||
| 158 | r->y = min_y; | ||
| 159 | r->w = (max_x - min_x); | ||
| 160 | r->h = (max_y - min_y); | ||
| 161 | } | ||
| 162 | |||
| 163 | /* Triangle rendering, using Barycentric coordinates (w0, w1, w2) | ||
| 164 | * | ||
| 165 | * The cross product isn't computed from scratch at each iteration, | ||
| 166 | * but optimized using constant step increments | ||
| 167 | * | ||
| 168 | */ | ||
| 169 | |||
| 170 | #define TRIANGLE_BEGIN_LOOP \ | ||
| 171 | { \ | ||
| 172 | int x, y; \ | ||
| 173 | for (y = 0; y < dstrect.h; y++) { \ | ||
| 174 | /* y start */ \ | ||
| 175 | Sint64 w0 = w0_row; \ | ||
| 176 | Sint64 w1 = w1_row; \ | ||
| 177 | Sint64 w2 = w2_row; \ | ||
| 178 | for (x = 0; x < dstrect.w; x++) { \ | ||
| 179 | /* In triangle */ \ | ||
| 180 | if (w0 + bias_w0 >= 0 && w1 + bias_w1 >= 0 && w2 + bias_w2 >= 0) { \ | ||
| 181 | Uint8 *dptr = (Uint8 *)dst_ptr + x * dstbpp; | ||
| 182 | |||
| 183 | // Use 64 bits precision to prevent overflow when interpolating color / texture with wide triangles | ||
| 184 | #define TRIANGLE_GET_TEXTCOORD \ | ||
| 185 | int srcx = (int)(((Sint64)w0 * s2s0_x + (Sint64)w1 * s2s1_x + s2_x_area.x) / area); \ | ||
| 186 | int srcy = (int)(((Sint64)w0 * s2s0_y + (Sint64)w1 * s2s1_y + s2_x_area.y) / area); \ | ||
| 187 | if (texture_address_mode == SDL_TEXTURE_ADDRESS_WRAP) { \ | ||
| 188 | srcx %= src_surface->w; \ | ||
| 189 | if (srcx < 0) { \ | ||
| 190 | srcx += (src_surface->w - 1); \ | ||
| 191 | } \ | ||
| 192 | srcy %= src_surface->h; \ | ||
| 193 | if (srcy < 0) { \ | ||
| 194 | srcy += (src_surface->h - 1); \ | ||
| 195 | } \ | ||
| 196 | } | ||
| 197 | |||
| 198 | #define TRIANGLE_GET_MAPPED_COLOR \ | ||
| 199 | Uint8 r = (Uint8)(((Sint64)w0 * c0.r + (Sint64)w1 * c1.r + (Sint64)w2 * c2.r) / area); \ | ||
| 200 | Uint8 g = (Uint8)(((Sint64)w0 * c0.g + (Sint64)w1 * c1.g + (Sint64)w2 * c2.g) / area); \ | ||
| 201 | Uint8 b = (Uint8)(((Sint64)w0 * c0.b + (Sint64)w1 * c1.b + (Sint64)w2 * c2.b) / area); \ | ||
| 202 | Uint8 a = (Uint8)(((Sint64)w0 * c0.a + (Sint64)w1 * c1.a + (Sint64)w2 * c2.a) / area); \ | ||
| 203 | Uint32 color = SDL_MapRGBA(format, palette, r, g, b, a); | ||
| 204 | |||
| 205 | #define TRIANGLE_GET_COLOR \ | ||
| 206 | int r = (int)(((Sint64)w0 * c0.r + (Sint64)w1 * c1.r + (Sint64)w2 * c2.r) / area); \ | ||
| 207 | int g = (int)(((Sint64)w0 * c0.g + (Sint64)w1 * c1.g + (Sint64)w2 * c2.g) / area); \ | ||
| 208 | int b = (int)(((Sint64)w0 * c0.b + (Sint64)w1 * c1.b + (Sint64)w2 * c2.b) / area); \ | ||
| 209 | int a = (int)(((Sint64)w0 * c0.a + (Sint64)w1 * c1.a + (Sint64)w2 * c2.a) / area); | ||
| 210 | |||
| 211 | #define TRIANGLE_END_LOOP \ | ||
| 212 | } \ | ||
| 213 | /* x += 1 */ \ | ||
| 214 | w0 += d2d1_y; \ | ||
| 215 | w1 += d0d2_y; \ | ||
| 216 | w2 += d1d0_y; \ | ||
| 217 | } \ | ||
| 218 | /* y += 1 */ \ | ||
| 219 | w0_row += d1d2_x; \ | ||
| 220 | w1_row += d2d0_x; \ | ||
| 221 | w2_row += d0d1_x; \ | ||
| 222 | dst_ptr += dst_pitch; \ | ||
| 223 | } \ | ||
| 224 | } | ||
| 225 | |||
| 226 | bool SDL_SW_FillTriangle(SDL_Surface *dst, SDL_Point *d0, SDL_Point *d1, SDL_Point *d2, SDL_BlendMode blend, SDL_Color c0, SDL_Color c1, SDL_Color c2) | ||
| 227 | { | ||
| 228 | bool result = true; | ||
| 229 | int dst_locked = 0; | ||
| 230 | |||
| 231 | SDL_Rect dstrect; | ||
| 232 | |||
| 233 | int dstbpp; | ||
| 234 | Uint8 *dst_ptr; | ||
| 235 | int dst_pitch; | ||
| 236 | |||
| 237 | Sint64 area; | ||
| 238 | int is_clockwise; | ||
| 239 | |||
| 240 | int d2d1_y, d1d2_x, d0d2_y, d2d0_x, d1d0_y, d0d1_x; | ||
| 241 | Sint64 w0_row, w1_row, w2_row; | ||
| 242 | int bias_w0, bias_w1, bias_w2; | ||
| 243 | |||
| 244 | bool is_uniform; | ||
| 245 | |||
| 246 | SDL_Surface *tmp = NULL; | ||
| 247 | |||
| 248 | if (!SDL_SurfaceValid(dst)) { | ||
| 249 | return false; | ||
| 250 | } | ||
| 251 | |||
| 252 | area = cross_product(d0, d1, d2->x, d2->y); | ||
| 253 | |||
| 254 | is_uniform = COLOR_EQ(c0, c1) && COLOR_EQ(c1, c2); | ||
| 255 | |||
| 256 | // Flat triangle | ||
| 257 | if (area == 0) { | ||
| 258 | return true; | ||
| 259 | } | ||
| 260 | |||
| 261 | // Lock the destination, if needed | ||
| 262 | if (SDL_MUSTLOCK(dst)) { | ||
| 263 | if (!SDL_LockSurface(dst)) { | ||
| 264 | result = false; | ||
| 265 | goto end; | ||
| 266 | } else { | ||
| 267 | dst_locked = 1; | ||
| 268 | } | ||
| 269 | } | ||
| 270 | |||
| 271 | bounding_rect_fixedpoint(d0, d1, d2, &dstrect); | ||
| 272 | |||
| 273 | { | ||
| 274 | // Clip triangle rect with surface rect | ||
| 275 | SDL_Rect rect; | ||
| 276 | rect.x = 0; | ||
| 277 | rect.y = 0; | ||
| 278 | rect.w = dst->w; | ||
| 279 | rect.h = dst->h; | ||
| 280 | SDL_GetRectIntersection(&dstrect, &rect, &dstrect); | ||
| 281 | } | ||
| 282 | |||
| 283 | { | ||
| 284 | // Clip triangle with surface clip rect | ||
| 285 | SDL_Rect rect; | ||
| 286 | SDL_GetSurfaceClipRect(dst, &rect); | ||
| 287 | SDL_GetRectIntersection(&dstrect, &rect, &dstrect); | ||
| 288 | } | ||
| 289 | |||
| 290 | if (blend != SDL_BLENDMODE_NONE) { | ||
| 291 | SDL_PixelFormat format = dst->format; | ||
| 292 | |||
| 293 | // need an alpha format | ||
| 294 | if (!SDL_ISPIXELFORMAT_ALPHA(format)) { | ||
| 295 | format = SDL_PIXELFORMAT_ARGB8888; | ||
| 296 | } | ||
| 297 | |||
| 298 | // Use an intermediate surface | ||
| 299 | tmp = SDL_CreateSurface(dstrect.w, dstrect.h, format); | ||
| 300 | if (!tmp) { | ||
| 301 | result = false; | ||
| 302 | goto end; | ||
| 303 | } | ||
| 304 | |||
| 305 | if (blend == SDL_BLENDMODE_MOD) { | ||
| 306 | Uint32 c = SDL_MapSurfaceRGBA(tmp, 255, 255, 255, 255); | ||
| 307 | SDL_FillSurfaceRect(tmp, NULL, c); | ||
| 308 | } | ||
| 309 | |||
| 310 | SDL_SetSurfaceBlendMode(tmp, blend); | ||
| 311 | |||
| 312 | dstbpp = tmp->fmt->bytes_per_pixel; | ||
| 313 | dst_ptr = (Uint8 *)tmp->pixels; | ||
| 314 | dst_pitch = tmp->pitch; | ||
| 315 | |||
| 316 | } else { | ||
| 317 | // Write directly to destination surface | ||
| 318 | dstbpp = dst->fmt->bytes_per_pixel; | ||
| 319 | dst_ptr = (Uint8 *)dst->pixels + dstrect.x * dstbpp + dstrect.y * dst->pitch; | ||
| 320 | dst_pitch = dst->pitch; | ||
| 321 | } | ||
| 322 | |||
| 323 | is_clockwise = area > 0; | ||
| 324 | if (area < 0) { | ||
| 325 | area = -area; | ||
| 326 | } | ||
| 327 | |||
| 328 | { | ||
| 329 | int val; | ||
| 330 | PRECOMP(d2d1_y, d1->y - d2->y) | ||
| 331 | PRECOMP(d0d2_y, d2->y - d0->y) | ||
| 332 | PRECOMP(d1d0_y, d0->y - d1->y) | ||
| 333 | PRECOMP(d1d2_x, d2->x - d1->x) | ||
| 334 | PRECOMP(d2d0_x, d0->x - d2->x) | ||
| 335 | PRECOMP(d0d1_x, d1->x - d0->x) | ||
| 336 | } | ||
| 337 | |||
| 338 | // Starting point for rendering, at the middle of a pixel | ||
| 339 | { | ||
| 340 | SDL_Point p; | ||
| 341 | p.x = dstrect.x; | ||
| 342 | p.y = dstrect.y; | ||
| 343 | trianglepoint_2_fixedpoint(&p); | ||
| 344 | p.x += (1 << FP_BITS) / 2; | ||
| 345 | p.y += (1 << FP_BITS) / 2; | ||
| 346 | w0_row = cross_product(d1, d2, p.x, p.y); | ||
| 347 | w1_row = cross_product(d2, d0, p.x, p.y); | ||
| 348 | w2_row = cross_product(d0, d1, p.x, p.y); | ||
| 349 | } | ||
| 350 | |||
| 351 | // Handle anti-clockwise triangles | ||
| 352 | if (!is_clockwise) { | ||
| 353 | d2d1_y *= -1; | ||
| 354 | d0d2_y *= -1; | ||
| 355 | d1d0_y *= -1; | ||
| 356 | d1d2_x *= -1; | ||
| 357 | d2d0_x *= -1; | ||
| 358 | d0d1_x *= -1; | ||
| 359 | w0_row *= -1; | ||
| 360 | w1_row *= -1; | ||
| 361 | w2_row *= -1; | ||
| 362 | } | ||
| 363 | |||
| 364 | // Add a bias to respect top-left rasterization rule | ||
| 365 | bias_w0 = (is_top_left(d1, d2, is_clockwise) ? 0 : -1); | ||
| 366 | bias_w1 = (is_top_left(d2, d0, is_clockwise) ? 0 : -1); | ||
| 367 | bias_w2 = (is_top_left(d0, d1, is_clockwise) ? 0 : -1); | ||
| 368 | |||
| 369 | if (is_uniform) { | ||
| 370 | Uint32 color; | ||
| 371 | if (tmp) { | ||
| 372 | color = SDL_MapSurfaceRGBA(tmp, c0.r, c0.g, c0.b, c0.a); | ||
| 373 | } else { | ||
| 374 | color = SDL_MapSurfaceRGBA(dst, c0.r, c0.g, c0.b, c0.a); | ||
| 375 | } | ||
| 376 | |||
| 377 | if (dstbpp == 4) { | ||
| 378 | TRIANGLE_BEGIN_LOOP | ||
| 379 | { | ||
| 380 | *(Uint32 *)dptr = color; | ||
| 381 | } | ||
| 382 | TRIANGLE_END_LOOP | ||
| 383 | } else if (dstbpp == 3) { | ||
| 384 | TRIANGLE_BEGIN_LOOP | ||
| 385 | { | ||
| 386 | Uint8 *s = (Uint8 *)&color; | ||
| 387 | dptr[0] = s[0]; | ||
| 388 | dptr[1] = s[1]; | ||
| 389 | dptr[2] = s[2]; | ||
| 390 | } | ||
| 391 | TRIANGLE_END_LOOP | ||
| 392 | } else if (dstbpp == 2) { | ||
| 393 | TRIANGLE_BEGIN_LOOP | ||
| 394 | { | ||
| 395 | *(Uint16 *)dptr = (Uint16)color; | ||
| 396 | } | ||
| 397 | TRIANGLE_END_LOOP | ||
| 398 | } else if (dstbpp == 1) { | ||
| 399 | TRIANGLE_BEGIN_LOOP | ||
| 400 | { | ||
| 401 | *dptr = (Uint8)color; | ||
| 402 | } | ||
| 403 | TRIANGLE_END_LOOP | ||
| 404 | } | ||
| 405 | } else { | ||
| 406 | const SDL_PixelFormatDetails *format; | ||
| 407 | SDL_Palette *palette; | ||
| 408 | if (tmp) { | ||
| 409 | format = tmp->fmt; | ||
| 410 | palette = tmp->palette; | ||
| 411 | } else { | ||
| 412 | format = dst->fmt; | ||
| 413 | palette = dst->palette; | ||
| 414 | } | ||
| 415 | if (dstbpp == 4) { | ||
| 416 | TRIANGLE_BEGIN_LOOP | ||
| 417 | { | ||
| 418 | TRIANGLE_GET_MAPPED_COLOR | ||
| 419 | *(Uint32 *)dptr = color; | ||
| 420 | } | ||
| 421 | TRIANGLE_END_LOOP | ||
| 422 | } else if (dstbpp == 3) { | ||
| 423 | TRIANGLE_BEGIN_LOOP | ||
| 424 | { | ||
| 425 | TRIANGLE_GET_MAPPED_COLOR | ||
| 426 | Uint8 *s = (Uint8 *)&color; | ||
| 427 | dptr[0] = s[0]; | ||
| 428 | dptr[1] = s[1]; | ||
| 429 | dptr[2] = s[2]; | ||
| 430 | } | ||
| 431 | TRIANGLE_END_LOOP | ||
| 432 | } else if (dstbpp == 2) { | ||
| 433 | TRIANGLE_BEGIN_LOOP | ||
| 434 | { | ||
| 435 | TRIANGLE_GET_MAPPED_COLOR | ||
| 436 | *(Uint16 *)dptr = (Uint16)color; | ||
| 437 | } | ||
| 438 | TRIANGLE_END_LOOP | ||
| 439 | } else if (dstbpp == 1) { | ||
| 440 | TRIANGLE_BEGIN_LOOP | ||
| 441 | { | ||
| 442 | TRIANGLE_GET_MAPPED_COLOR | ||
| 443 | *dptr = (Uint8)color; | ||
| 444 | } | ||
| 445 | TRIANGLE_END_LOOP | ||
| 446 | } | ||
| 447 | } | ||
| 448 | |||
| 449 | if (tmp) { | ||
| 450 | SDL_BlitSurface(tmp, NULL, dst, &dstrect); | ||
| 451 | SDL_DestroySurface(tmp); | ||
| 452 | } | ||
| 453 | |||
| 454 | end: | ||
| 455 | if (dst_locked) { | ||
| 456 | SDL_UnlockSurface(dst); | ||
| 457 | } | ||
| 458 | |||
| 459 | return result; | ||
| 460 | } | ||
| 461 | |||
| 462 | bool SDL_SW_BlitTriangle( | ||
| 463 | SDL_Surface *src, | ||
| 464 | SDL_Point *s0, SDL_Point *s1, SDL_Point *s2, | ||
| 465 | SDL_Surface *dst, | ||
| 466 | SDL_Point *d0, SDL_Point *d1, SDL_Point *d2, | ||
| 467 | SDL_Color c0, SDL_Color c1, SDL_Color c2, | ||
| 468 | SDL_TextureAddressMode texture_address_mode) | ||
| 469 | { | ||
| 470 | bool result = true; | ||
| 471 | SDL_Surface *src_surface = src; | ||
| 472 | int src_locked = 0; | ||
| 473 | int dst_locked = 0; | ||
| 474 | |||
| 475 | SDL_BlendMode blend; | ||
| 476 | |||
| 477 | SDL_Rect dstrect; | ||
| 478 | |||
| 479 | SDL_Point s2_x_area; | ||
| 480 | |||
| 481 | int dstbpp; | ||
| 482 | Uint8 *dst_ptr; | ||
| 483 | int dst_pitch; | ||
| 484 | |||
| 485 | const int *src_ptr; | ||
| 486 | int src_pitch; | ||
| 487 | |||
| 488 | Sint64 area, tmp64; | ||
| 489 | int is_clockwise; | ||
| 490 | |||
| 491 | int d2d1_y, d1d2_x, d0d2_y, d2d0_x, d1d0_y, d0d1_x; | ||
| 492 | int s2s0_x, s2s1_x, s2s0_y, s2s1_y; | ||
| 493 | |||
| 494 | Sint64 w0_row, w1_row, w2_row; | ||
| 495 | int bias_w0, bias_w1, bias_w2; | ||
| 496 | |||
| 497 | bool is_uniform; | ||
| 498 | |||
| 499 | bool has_modulation; | ||
| 500 | |||
| 501 | if (!SDL_SurfaceValid(src)) { | ||
| 502 | return SDL_InvalidParamError("src"); | ||
| 503 | } | ||
| 504 | if (!SDL_SurfaceValid(dst)) { | ||
| 505 | return SDL_InvalidParamError("dst"); | ||
| 506 | } | ||
| 507 | |||
| 508 | area = cross_product(d0, d1, d2->x, d2->y); | ||
| 509 | |||
| 510 | // Flat triangle | ||
| 511 | if (area == 0) { | ||
| 512 | return true; | ||
| 513 | } | ||
| 514 | |||
| 515 | // Lock the destination, if needed | ||
| 516 | if (SDL_MUSTLOCK(dst)) { | ||
| 517 | if (!SDL_LockSurface(dst)) { | ||
| 518 | result = false; | ||
| 519 | goto end; | ||
| 520 | } else { | ||
| 521 | dst_locked = 1; | ||
| 522 | } | ||
| 523 | } | ||
| 524 | |||
| 525 | // Lock the source, if needed | ||
| 526 | if (SDL_MUSTLOCK(src)) { | ||
| 527 | if (!SDL_LockSurface(src)) { | ||
| 528 | result = false; | ||
| 529 | goto end; | ||
| 530 | } else { | ||
| 531 | src_locked = 1; | ||
| 532 | } | ||
| 533 | } | ||
| 534 | |||
| 535 | is_uniform = COLOR_EQ(c0, c1) && COLOR_EQ(c1, c2); | ||
| 536 | |||
| 537 | bounding_rect_fixedpoint(d0, d1, d2, &dstrect); | ||
| 538 | |||
| 539 | SDL_GetSurfaceBlendMode(src, &blend); | ||
| 540 | |||
| 541 | // TRIANGLE_GET_TEXTCOORD interpolates up to the max values included, so reduce by 1 | ||
| 542 | if (texture_address_mode == SDL_TEXTURE_ADDRESS_CLAMP) { | ||
| 543 | SDL_Rect srcrect; | ||
| 544 | int maxx, maxy; | ||
| 545 | bounding_rect(s0, s1, s2, &srcrect); | ||
| 546 | maxx = srcrect.x + srcrect.w; | ||
| 547 | maxy = srcrect.y + srcrect.h; | ||
| 548 | if (srcrect.w > 0) { | ||
| 549 | if (s0->x == maxx) { | ||
| 550 | s0->x--; | ||
| 551 | } | ||
| 552 | if (s1->x == maxx) { | ||
| 553 | s1->x--; | ||
| 554 | } | ||
| 555 | if (s2->x == maxx) { | ||
| 556 | s2->x--; | ||
| 557 | } | ||
| 558 | } | ||
| 559 | if (srcrect.h > 0) { | ||
| 560 | if (s0->y == maxy) { | ||
| 561 | s0->y--; | ||
| 562 | } | ||
| 563 | if (s1->y == maxy) { | ||
| 564 | s1->y--; | ||
| 565 | } | ||
| 566 | if (s2->y == maxy) { | ||
| 567 | s2->y--; | ||
| 568 | } | ||
| 569 | } | ||
| 570 | } | ||
| 571 | |||
| 572 | if (is_uniform) { | ||
| 573 | // SDL_GetSurfaceColorMod(src, &r, &g, &b); | ||
| 574 | has_modulation = c0.r != 255 || c0.g != 255 || c0.b != 255 || c0.a != 255; | ||
| 575 | } else { | ||
| 576 | has_modulation = true; | ||
| 577 | } | ||
| 578 | |||
| 579 | { | ||
| 580 | // Clip triangle with surface clip rect | ||
| 581 | SDL_Rect rect; | ||
| 582 | SDL_GetSurfaceClipRect(dst, &rect); | ||
| 583 | SDL_GetRectIntersection(&dstrect, &rect, &dstrect); | ||
| 584 | } | ||
| 585 | |||
| 586 | // Set destination pointer | ||
| 587 | dstbpp = dst->fmt->bytes_per_pixel; | ||
| 588 | dst_ptr = (Uint8 *)dst->pixels + dstrect.x * dstbpp + dstrect.y * dst->pitch; | ||
| 589 | dst_pitch = dst->pitch; | ||
| 590 | |||
| 591 | // Set source pointer | ||
| 592 | src_ptr = (const int *)src->pixels; | ||
| 593 | src_pitch = src->pitch; | ||
| 594 | |||
| 595 | is_clockwise = area > 0; | ||
| 596 | if (area < 0) { | ||
| 597 | area = -area; | ||
| 598 | } | ||
| 599 | |||
| 600 | { | ||
| 601 | int val; | ||
| 602 | PRECOMP(d2d1_y, d1->y - d2->y) | ||
| 603 | PRECOMP(d0d2_y, d2->y - d0->y) | ||
| 604 | PRECOMP(d1d0_y, d0->y - d1->y) | ||
| 605 | PRECOMP(d1d2_x, d2->x - d1->x) | ||
| 606 | PRECOMP(d2d0_x, d0->x - d2->x) | ||
| 607 | PRECOMP(d0d1_x, d1->x - d0->x) | ||
| 608 | } | ||
| 609 | |||
| 610 | s2s0_x = s0->x - s2->x; | ||
| 611 | s2s1_x = s1->x - s2->x; | ||
| 612 | s2s0_y = s0->y - s2->y; | ||
| 613 | s2s1_y = s1->y - s2->y; | ||
| 614 | |||
| 615 | // Starting point for rendering, at the middle of a pixel | ||
| 616 | { | ||
| 617 | SDL_Point p; | ||
| 618 | p.x = dstrect.x; | ||
| 619 | p.y = dstrect.y; | ||
| 620 | trianglepoint_2_fixedpoint(&p); | ||
| 621 | p.x += (1 << FP_BITS) / 2; | ||
| 622 | p.y += (1 << FP_BITS) / 2; | ||
| 623 | w0_row = cross_product(d1, d2, p.x, p.y); | ||
| 624 | w1_row = cross_product(d2, d0, p.x, p.y); | ||
| 625 | w2_row = cross_product(d0, d1, p.x, p.y); | ||
| 626 | } | ||
| 627 | |||
| 628 | // Handle anti-clockwise triangles | ||
| 629 | if (!is_clockwise) { | ||
| 630 | d2d1_y *= -1; | ||
| 631 | d0d2_y *= -1; | ||
| 632 | d1d0_y *= -1; | ||
| 633 | d1d2_x *= -1; | ||
| 634 | d2d0_x *= -1; | ||
| 635 | d0d1_x *= -1; | ||
| 636 | w0_row *= -1; | ||
| 637 | w1_row *= -1; | ||
| 638 | w2_row *= -1; | ||
| 639 | } | ||
| 640 | |||
| 641 | // Add a bias to respect top-left rasterization rule | ||
| 642 | bias_w0 = (is_top_left(d1, d2, is_clockwise) ? 0 : -1); | ||
| 643 | bias_w1 = (is_top_left(d2, d0, is_clockwise) ? 0 : -1); | ||
| 644 | bias_w2 = (is_top_left(d0, d1, is_clockwise) ? 0 : -1); | ||
| 645 | |||
| 646 | /* precompute constant 's2->x * area' used in TRIANGLE_GET_TEXTCOORD */ | ||
| 647 | tmp64 = s2->x * area; | ||
| 648 | if (tmp64 >= INT_MIN && tmp64 <= INT_MAX) { | ||
| 649 | s2_x_area.x = (int)tmp64; | ||
| 650 | } else { | ||
| 651 | result = SDL_SetError("triangle area overflow"); | ||
| 652 | goto end; | ||
| 653 | } | ||
| 654 | tmp64 = s2->y * area; | ||
| 655 | if (tmp64 >= INT_MIN && tmp64 <= INT_MAX) { | ||
| 656 | s2_x_area.y = (int)tmp64; | ||
| 657 | } else { | ||
| 658 | result = SDL_SetError("triangle area overflow"); | ||
| 659 | goto end; | ||
| 660 | } | ||
| 661 | |||
| 662 | if (blend != SDL_BLENDMODE_NONE || src->format != dst->format || has_modulation || !is_uniform) { | ||
| 663 | // Use SDL_BlitTriangle_Slow | ||
| 664 | |||
| 665 | SDL_BlitInfo *info = &src->map.info; | ||
| 666 | SDL_BlitInfo tmp_info; | ||
| 667 | |||
| 668 | SDL_zero(tmp_info); | ||
| 669 | |||
| 670 | tmp_info.src_fmt = src->fmt; | ||
| 671 | tmp_info.dst_fmt = dst->fmt; | ||
| 672 | tmp_info.flags = info->flags; | ||
| 673 | /* | ||
| 674 | tmp_info.r = info->r; | ||
| 675 | tmp_info.g = info->g; | ||
| 676 | tmp_info.b = info->b; | ||
| 677 | tmp_info.a = info->a; | ||
| 678 | */ | ||
| 679 | tmp_info.r = c0.r; | ||
| 680 | tmp_info.g = c0.g; | ||
| 681 | tmp_info.b = c0.b; | ||
| 682 | tmp_info.a = c0.a; | ||
| 683 | |||
| 684 | tmp_info.flags &= ~(SDL_COPY_MODULATE_COLOR | SDL_COPY_MODULATE_ALPHA); | ||
| 685 | |||
| 686 | if (c0.r != 255 || c1.r != 255 || c2.r != 255 || | ||
| 687 | c0.g != 255 || c1.g != 255 || c2.g != 255 || | ||
| 688 | c0.b != 255 || c1.b != 255 || c2.b != 255) { | ||
| 689 | tmp_info.flags |= SDL_COPY_MODULATE_COLOR; | ||
| 690 | } | ||
| 691 | |||
| 692 | if (c0.a != 255 || c1.a != 255 || c2.a != 255) { | ||
| 693 | tmp_info.flags |= SDL_COPY_MODULATE_ALPHA; | ||
| 694 | } | ||
| 695 | |||
| 696 | tmp_info.colorkey = info->colorkey; | ||
| 697 | |||
| 698 | // src | ||
| 699 | tmp_info.src_surface = src_surface; | ||
| 700 | tmp_info.src = (Uint8 *)src_ptr; | ||
| 701 | tmp_info.src_pitch = src_pitch; | ||
| 702 | |||
| 703 | // dst | ||
| 704 | tmp_info.dst = dst_ptr; | ||
| 705 | tmp_info.dst_pitch = dst_pitch; | ||
| 706 | |||
| 707 | #define CHECK_INT_RANGE(X) \ | ||
| 708 | if ((X) < INT_MIN || (X) > INT_MAX) { \ | ||
| 709 | result = SDL_SetError("integer overflow (%s = %" SDL_PRIs64 ")", #X, X); \ | ||
| 710 | goto end; \ | ||
| 711 | } | ||
| 712 | CHECK_INT_RANGE(area); | ||
| 713 | CHECK_INT_RANGE(w0_row); | ||
| 714 | CHECK_INT_RANGE(w1_row); | ||
| 715 | CHECK_INT_RANGE(w2_row); | ||
| 716 | SDL_BlitTriangle_Slow(&tmp_info, s2_x_area, dstrect, (int)area, bias_w0, bias_w1, bias_w2, | ||
| 717 | d2d1_y, d1d2_x, d0d2_y, d2d0_x, d1d0_y, d0d1_x, | ||
| 718 | s2s0_x, s2s1_x, s2s0_y, s2s1_y, (int)w0_row, (int)w1_row, (int)w2_row, | ||
| 719 | c0, c1, c2, is_uniform, texture_address_mode); | ||
| 720 | |||
| 721 | goto end; | ||
| 722 | } | ||
| 723 | |||
| 724 | if (dstbpp == 4) { | ||
| 725 | TRIANGLE_BEGIN_LOOP | ||
| 726 | { | ||
| 727 | TRIANGLE_GET_TEXTCOORD | ||
| 728 | Uint32 *sptr = (Uint32 *)((Uint8 *)src_ptr + srcy * src_pitch); | ||
| 729 | *(Uint32 *)dptr = sptr[srcx]; | ||
| 730 | } | ||
| 731 | TRIANGLE_END_LOOP | ||
| 732 | } else if (dstbpp == 3) { | ||
| 733 | TRIANGLE_BEGIN_LOOP | ||
| 734 | { | ||
| 735 | TRIANGLE_GET_TEXTCOORD | ||
| 736 | Uint8 *sptr = (Uint8 *)src_ptr + srcy * src_pitch; | ||
| 737 | dptr[0] = sptr[3 * srcx]; | ||
| 738 | dptr[1] = sptr[3 * srcx + 1]; | ||
| 739 | dptr[2] = sptr[3 * srcx + 2]; | ||
| 740 | } | ||
| 741 | TRIANGLE_END_LOOP | ||
| 742 | } else if (dstbpp == 2) { | ||
| 743 | TRIANGLE_BEGIN_LOOP | ||
| 744 | { | ||
| 745 | TRIANGLE_GET_TEXTCOORD | ||
| 746 | Uint16 *sptr = (Uint16 *)((Uint8 *)src_ptr + srcy * src_pitch); | ||
| 747 | *(Uint16 *)dptr = sptr[srcx]; | ||
| 748 | } | ||
| 749 | TRIANGLE_END_LOOP | ||
| 750 | } else if (dstbpp == 1) { | ||
| 751 | TRIANGLE_BEGIN_LOOP | ||
| 752 | { | ||
| 753 | TRIANGLE_GET_TEXTCOORD | ||
| 754 | Uint8 *sptr = (Uint8 *)src_ptr + srcy * src_pitch; | ||
| 755 | *dptr = sptr[srcx]; | ||
| 756 | } | ||
| 757 | TRIANGLE_END_LOOP | ||
| 758 | } | ||
| 759 | |||
| 760 | end: | ||
| 761 | if (dst_locked) { | ||
| 762 | SDL_UnlockSurface(dst); | ||
| 763 | } | ||
| 764 | if (src_locked) { | ||
| 765 | SDL_UnlockSurface(src); | ||
| 766 | } | ||
| 767 | |||
| 768 | return result; | ||
| 769 | } | ||
| 770 | |||
| 771 | #define FORMAT_ALPHA 0 | ||
| 772 | #define FORMAT_NO_ALPHA -1 | ||
| 773 | #define FORMAT_2101010 1 | ||
| 774 | #define FORMAT_HAS_ALPHA(format) format == 0 | ||
| 775 | #define FORMAT_HAS_NO_ALPHA(format) format < 0 | ||
| 776 | static int detect_format(const SDL_PixelFormatDetails *pf) | ||
| 777 | { | ||
| 778 | if (pf->format == SDL_PIXELFORMAT_ARGB2101010) { | ||
| 779 | return FORMAT_2101010; | ||
| 780 | } else if (pf->Amask) { | ||
| 781 | return FORMAT_ALPHA; | ||
| 782 | } else { | ||
| 783 | return FORMAT_NO_ALPHA; | ||
| 784 | } | ||
| 785 | } | ||
| 786 | |||
| 787 | static void SDL_BlitTriangle_Slow(SDL_BlitInfo *info, | ||
| 788 | SDL_Point s2_x_area, SDL_Rect dstrect, int area, int bias_w0, int bias_w1, int bias_w2, | ||
| 789 | int d2d1_y, int d1d2_x, int d0d2_y, int d2d0_x, int d1d0_y, int d0d1_x, | ||
| 790 | int s2s0_x, int s2s1_x, int s2s0_y, int s2s1_y, int w0_row, int w1_row, int w2_row, | ||
| 791 | SDL_Color c0, SDL_Color c1, SDL_Color c2, bool is_uniform, SDL_TextureAddressMode texture_address_mode) | ||
| 792 | { | ||
| 793 | SDL_Surface *src_surface = info->src_surface; | ||
| 794 | const int flags = info->flags; | ||
| 795 | Uint32 modulateR = info->r; | ||
| 796 | Uint32 modulateG = info->g; | ||
| 797 | Uint32 modulateB = info->b; | ||
| 798 | Uint32 modulateA = info->a; | ||
| 799 | Uint32 srcpixel; | ||
| 800 | Uint32 srcR, srcG, srcB, srcA; | ||
| 801 | Uint32 dstpixel; | ||
| 802 | Uint32 dstR, dstG, dstB, dstA; | ||
| 803 | const SDL_PixelFormatDetails *src_fmt = info->src_fmt; | ||
| 804 | const SDL_PixelFormatDetails *dst_fmt = info->dst_fmt; | ||
| 805 | int srcbpp = src_fmt->bytes_per_pixel; | ||
| 806 | int dstbpp = dst_fmt->bytes_per_pixel; | ||
| 807 | int srcfmt_val; | ||
| 808 | int dstfmt_val; | ||
| 809 | Uint32 rgbmask = ~src_fmt->Amask; | ||
| 810 | Uint32 ckey = info->colorkey & rgbmask; | ||
| 811 | |||
| 812 | Uint8 *dst_ptr = info->dst; | ||
| 813 | int dst_pitch = info->dst_pitch; | ||
| 814 | |||
| 815 | srcfmt_val = detect_format(src_fmt); | ||
| 816 | dstfmt_val = detect_format(dst_fmt); | ||
| 817 | |||
| 818 | TRIANGLE_BEGIN_LOOP | ||
| 819 | { | ||
| 820 | Uint8 *src; | ||
| 821 | Uint8 *dst = dptr; | ||
| 822 | TRIANGLE_GET_TEXTCOORD | ||
| 823 | src = (info->src + (srcy * info->src_pitch) + (srcx * srcbpp)); | ||
| 824 | if (FORMAT_HAS_ALPHA(srcfmt_val)) { | ||
| 825 | DISEMBLE_RGBA(src, srcbpp, src_fmt, srcpixel, srcR, srcG, srcB, srcA); | ||
| 826 | } else if (FORMAT_HAS_NO_ALPHA(srcfmt_val)) { | ||
| 827 | DISEMBLE_RGB(src, srcbpp, src_fmt, srcpixel, srcR, srcG, srcB); | ||
| 828 | srcA = 0xFF; | ||
| 829 | } else { | ||
| 830 | // SDL_PIXELFORMAT_ARGB2101010 | ||
| 831 | srcpixel = *((Uint32 *)(src)); | ||
| 832 | RGBA_FROM_ARGB2101010(srcpixel, srcR, srcG, srcB, srcA); | ||
| 833 | } | ||
| 834 | if (flags & SDL_COPY_COLORKEY) { | ||
| 835 | // srcpixel isn't set for 24 bpp | ||
| 836 | if (srcbpp == 3) { | ||
| 837 | srcpixel = (srcR << src_fmt->Rshift) | | ||
| 838 | (srcG << src_fmt->Gshift) | (srcB << src_fmt->Bshift); | ||
| 839 | } | ||
| 840 | if ((srcpixel & rgbmask) == ckey) { | ||
| 841 | continue; | ||
| 842 | } | ||
| 843 | } | ||
| 844 | if ((flags & (SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL))) { | ||
| 845 | if (FORMAT_HAS_ALPHA(dstfmt_val)) { | ||
| 846 | DISEMBLE_RGBA(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG, dstB, dstA); | ||
| 847 | } else if (FORMAT_HAS_NO_ALPHA(dstfmt_val)) { | ||
| 848 | DISEMBLE_RGB(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG, dstB); | ||
| 849 | dstA = 0xFF; | ||
| 850 | } else { | ||
| 851 | // SDL_PIXELFORMAT_ARGB2101010 | ||
| 852 | dstpixel = *((Uint32 *) (dst)); | ||
| 853 | RGBA_FROM_ARGB2101010(dstpixel, dstR, dstG, dstB, dstA); | ||
| 854 | } | ||
| 855 | } else { | ||
| 856 | // don't care | ||
| 857 | dstR = dstG = dstB = dstA = 0; | ||
| 858 | } | ||
| 859 | |||
| 860 | if (!is_uniform) { | ||
| 861 | TRIANGLE_GET_COLOR | ||
| 862 | modulateR = r; | ||
| 863 | modulateG = g; | ||
| 864 | modulateB = b; | ||
| 865 | modulateA = a; | ||
| 866 | } | ||
| 867 | |||
| 868 | if (flags & SDL_COPY_MODULATE_COLOR) { | ||
| 869 | srcR = (srcR * modulateR) / 255; | ||
| 870 | srcG = (srcG * modulateG) / 255; | ||
| 871 | srcB = (srcB * modulateB) / 255; | ||
| 872 | } | ||
| 873 | if (flags & SDL_COPY_MODULATE_ALPHA) { | ||
| 874 | srcA = (srcA * modulateA) / 255; | ||
| 875 | } | ||
| 876 | if (flags & (SDL_COPY_BLEND | SDL_COPY_ADD)) { | ||
| 877 | // This goes away if we ever use premultiplied alpha | ||
| 878 | if (srcA < 255) { | ||
| 879 | srcR = (srcR * srcA) / 255; | ||
| 880 | srcG = (srcG * srcA) / 255; | ||
| 881 | srcB = (srcB * srcA) / 255; | ||
| 882 | } | ||
| 883 | } | ||
| 884 | switch (flags & (SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL)) { | ||
| 885 | case 0: | ||
| 886 | dstR = srcR; | ||
| 887 | dstG = srcG; | ||
| 888 | dstB = srcB; | ||
| 889 | dstA = srcA; | ||
| 890 | break; | ||
| 891 | case SDL_COPY_BLEND: | ||
| 892 | dstR = srcR + ((255 - srcA) * dstR) / 255; | ||
| 893 | dstG = srcG + ((255 - srcA) * dstG) / 255; | ||
| 894 | dstB = srcB + ((255 - srcA) * dstB) / 255; | ||
| 895 | dstA = srcA + ((255 - srcA) * dstA) / 255; | ||
| 896 | break; | ||
| 897 | case SDL_COPY_ADD: | ||
| 898 | dstR = srcR + dstR; | ||
| 899 | if (dstR > 255) { | ||
| 900 | dstR = 255; | ||
| 901 | } | ||
| 902 | dstG = srcG + dstG; | ||
| 903 | if (dstG > 255) { | ||
| 904 | dstG = 255; | ||
| 905 | } | ||
| 906 | dstB = srcB + dstB; | ||
| 907 | if (dstB > 255) { | ||
| 908 | dstB = 255; | ||
| 909 | } | ||
| 910 | break; | ||
| 911 | case SDL_COPY_MOD: | ||
| 912 | dstR = (srcR * dstR) / 255; | ||
| 913 | dstG = (srcG * dstG) / 255; | ||
| 914 | dstB = (srcB * dstB) / 255; | ||
| 915 | break; | ||
| 916 | case SDL_COPY_MUL: | ||
| 917 | dstR = ((srcR * dstR) + (dstR * (255 - srcA))) / 255; | ||
| 918 | if (dstR > 255) { | ||
| 919 | dstR = 255; | ||
| 920 | } | ||
| 921 | dstG = ((srcG * dstG) + (dstG * (255 - srcA))) / 255; | ||
| 922 | if (dstG > 255) { | ||
| 923 | dstG = 255; | ||
| 924 | } | ||
| 925 | dstB = ((srcB * dstB) + (dstB * (255 - srcA))) / 255; | ||
| 926 | if (dstB > 255) { | ||
| 927 | dstB = 255; | ||
| 928 | } | ||
| 929 | break; | ||
| 930 | } | ||
| 931 | if (FORMAT_HAS_ALPHA(dstfmt_val)) { | ||
| 932 | ASSEMBLE_RGBA(dst, dstbpp, dst_fmt, dstR, dstG, dstB, dstA); | ||
| 933 | } else if (FORMAT_HAS_NO_ALPHA(dstfmt_val)) { | ||
| 934 | ASSEMBLE_RGB(dst, dstbpp, dst_fmt, dstR, dstG, dstB); | ||
| 935 | } else { | ||
| 936 | // SDL_PIXELFORMAT_ARGB2101010 | ||
| 937 | Uint32 pixel; | ||
| 938 | ARGB2101010_FROM_RGBA(pixel, dstR, dstG, dstB, dstA); | ||
| 939 | *(Uint32 *)dst = pixel; | ||
| 940 | } | ||
| 941 | } | ||
| 942 | TRIANGLE_END_LOOP | ||
| 943 | } | ||
| 944 | |||
| 945 | #endif // SDL_VIDEO_RENDER_SW | ||
diff --git a/contrib/SDL-3.2.8/src/render/software/SDL_triangle.h b/contrib/SDL-3.2.8/src/render/software/SDL_triangle.h new file mode 100644 index 0000000..1c5504c --- /dev/null +++ b/contrib/SDL-3.2.8/src/render/software/SDL_triangle.h | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | /* | ||
| 2 | Simple DirectMedia Layer | ||
| 3 | Copyright (C) 1997-2025 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 | |||
| 22 | #ifndef SDL_triangle_h_ | ||
| 23 | #define SDL_triangle_h_ | ||
| 24 | |||
| 25 | #include "SDL_internal.h" | ||
| 26 | |||
| 27 | #include "../SDL_sysrender.h" // For SDL_TextureAddressMode | ||
| 28 | |||
| 29 | extern bool SDL_SW_FillTriangle(SDL_Surface *dst, | ||
| 30 | SDL_Point *d0, SDL_Point *d1, SDL_Point *d2, | ||
| 31 | SDL_BlendMode blend, SDL_Color c0, SDL_Color c1, SDL_Color c2); | ||
| 32 | |||
| 33 | extern bool SDL_SW_BlitTriangle(SDL_Surface *src, | ||
| 34 | SDL_Point *s0, SDL_Point *s1, SDL_Point *s2, | ||
| 35 | SDL_Surface *dst, | ||
| 36 | SDL_Point *d0, SDL_Point *d1, SDL_Point *d2, | ||
| 37 | SDL_Color c0, SDL_Color c1, SDL_Color c2, | ||
| 38 | SDL_TextureAddressMode texture_address_mode); | ||
| 39 | |||
| 40 | extern void trianglepoint_2_fixedpoint(SDL_Point *a); | ||
| 41 | |||
| 42 | #endif // SDL_triangle_h_ | ||
