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
29static 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
152static 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
274static 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
396static 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
519static 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
642static 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
764static 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
886typedef 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
892static 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
922bool 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
945bool 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
987