comparison src/render/software/SDL_draw.h @ 5166:d72793305335

Making the API simpler, moved the surface drawing functions to the software renderer.
author Sam Lantinga <slouken@libsdl.org>
date Thu, 03 Feb 2011 02:45:29 -0800
parents src/video/SDL_draw.h@e743b9c3f6d6
children d976b67150c5
comparison
equal deleted inserted replaced
5165:e2b3f003e085 5166:d72793305335
1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2010 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21 */
22 #include "SDL_config.h"
23
24 #include "../../video/SDL_blit.h"
25
26 /* This code assumes that r, g, b, a are the source color,
27 * and in the blend and add case, the RGB values are premultiplied by a.
28 */
29
30 #define DRAW_MUL(_a, _b) (((unsigned)(_a)*(_b))/255)
31
32 #define DRAW_FASTSETPIXEL(type) \
33 *pixel = (type) color
34
35 #define DRAW_FASTSETPIXEL1 DRAW_FASTSETPIXEL(Uint8)
36 #define DRAW_FASTSETPIXEL2 DRAW_FASTSETPIXEL(Uint16)
37 #define DRAW_FASTSETPIXEL4 DRAW_FASTSETPIXEL(Uint32)
38
39 #define DRAW_FASTSETPIXELXY(x, y, type, bpp, color) \
40 *(type *)((Uint8 *)dst->pixels + (y) * dst->pitch \
41 + (x) * bpp) = (type) color
42
43 #define DRAW_FASTSETPIXELXY1(x, y) DRAW_FASTSETPIXELXY(x, y, Uint8, 1, color)
44 #define DRAW_FASTSETPIXELXY2(x, y) DRAW_FASTSETPIXELXY(x, y, Uint16, 2, color)
45 #define DRAW_FASTSETPIXELXY4(x, y) DRAW_FASTSETPIXELXY(x, y, Uint32, 4, color)
46
47 #define DRAW_SETPIXEL(setpixel) \
48 do { \
49 unsigned sr = r, sg = g, sb = b, sa = a; \
50 setpixel; \
51 } while (0)
52
53 #define DRAW_SETPIXEL_BLEND(getpixel, setpixel) \
54 do { \
55 unsigned sr, sg, sb, sa; sa; \
56 getpixel; \
57 sr = DRAW_MUL(inva, sr) + r; \
58 sg = DRAW_MUL(inva, sg) + g; \
59 sb = DRAW_MUL(inva, sb) + b; \
60 setpixel; \
61 } while (0)
62
63 #define DRAW_SETPIXEL_ADD(getpixel, setpixel) \
64 do { \
65 unsigned sr, sg, sb, sa; sa; \
66 getpixel; \
67 sr += r; if (sr > 0xff) sr = 0xff; \
68 sg += g; if (sg > 0xff) sg = 0xff; \
69 sb += b; if (sb > 0xff) sb = 0xff; \
70 setpixel; \
71 } while (0)
72
73 #define DRAW_SETPIXELXY(x, y, type, bpp, op) \
74 do { \
75 type *pixel = (type *)((Uint8 *)dst->pixels + (y) * dst->pitch \
76 + (x) * bpp); \
77 op; \
78 } while (0)
79
80 /*
81 * Define draw operators for RGB555
82 */
83
84 #define DRAW_SETPIXEL_RGB555 \
85 DRAW_SETPIXEL(RGB555_FROM_RGB(*pixel, sr, sg, sb))
86
87 #define DRAW_SETPIXEL_BLEND_RGB555 \
88 DRAW_SETPIXEL_BLEND(RGB_FROM_RGB555(*pixel, sr, sg, sb), \
89 RGB555_FROM_RGB(*pixel, sr, sg, sb))
90
91 #define DRAW_SETPIXEL_ADD_RGB555 \
92 DRAW_SETPIXEL_ADD(RGB_FROM_RGB555(*pixel, sr, sg, sb), \
93 RGB555_FROM_RGB(*pixel, sr, sg, sb))
94
95 #define DRAW_SETPIXELXY_RGB555(x, y) \
96 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_RGB555)
97
98 #define DRAW_SETPIXELXY_BLEND_RGB555(x, y) \
99 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_BLEND_RGB555)
100
101 #define DRAW_SETPIXELXY_ADD_RGB555(x, y) \
102 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_ADD_RGB555)
103
104 /*
105 * Define draw operators for RGB565
106 */
107
108 #define DRAW_SETPIXEL_RGB565 \
109 DRAW_SETPIXEL(RGB565_FROM_RGB(*pixel, sr, sg, sb))
110
111 #define DRAW_SETPIXEL_BLEND_RGB565 \
112 DRAW_SETPIXEL_BLEND(RGB_FROM_RGB565(*pixel, sr, sg, sb), \
113 RGB565_FROM_RGB(*pixel, sr, sg, sb))
114
115 #define DRAW_SETPIXEL_ADD_RGB565 \
116 DRAW_SETPIXEL_ADD(RGB_FROM_RGB565(*pixel, sr, sg, sb), \
117 RGB565_FROM_RGB(*pixel, sr, sg, sb))
118
119 #define DRAW_SETPIXELXY_RGB565(x, y) \
120 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_RGB565)
121
122 #define DRAW_SETPIXELXY_BLEND_RGB565(x, y) \
123 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_BLEND_RGB565)
124
125 #define DRAW_SETPIXELXY_ADD_RGB565(x, y) \
126 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_ADD_RGB565)
127
128 /*
129 * Define draw operators for RGB888
130 */
131
132 #define DRAW_SETPIXEL_RGB888 \
133 DRAW_SETPIXEL(RGB888_FROM_RGB(*pixel, sr, sg, sb))
134
135 #define DRAW_SETPIXEL_BLEND_RGB888 \
136 DRAW_SETPIXEL_BLEND(RGB_FROM_RGB888(*pixel, sr, sg, sb), \
137 RGB888_FROM_RGB(*pixel, sr, sg, sb))
138
139 #define DRAW_SETPIXEL_ADD_RGB888 \
140 DRAW_SETPIXEL_ADD(RGB_FROM_RGB888(*pixel, sr, sg, sb), \
141 RGB888_FROM_RGB(*pixel, sr, sg, sb))
142
143 #define DRAW_SETPIXELXY_RGB888(x, y) \
144 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_RGB888)
145
146 #define DRAW_SETPIXELXY_BLEND_RGB888(x, y) \
147 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_BLEND_RGB888)
148
149 #define DRAW_SETPIXELXY_ADD_RGB888(x, y) \
150 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_ADD_RGB888)
151
152 /*
153 * Define draw operators for ARGB8888
154 */
155
156 #define DRAW_SETPIXEL_ARGB8888 \
157 DRAW_SETPIXEL(ARGB8888_FROM_RGBA(*pixel, sr, sg, sb, sa))
158
159 #define DRAW_SETPIXEL_BLEND_ARGB8888 \
160 DRAW_SETPIXEL_BLEND(RGBA_FROM_ARGB8888(*pixel, sr, sg, sb, sa), \
161 ARGB8888_FROM_RGBA(*pixel, sr, sg, sb, sa))
162
163 #define DRAW_SETPIXEL_ADD_ARGB8888 \
164 DRAW_SETPIXEL_ADD(RGBA_FROM_ARGB8888(*pixel, sr, sg, sb, sa), \
165 ARGB8888_FROM_RGBA(*pixel, sr, sg, sb, sa))
166
167 #define DRAW_SETPIXELXY_ARGB8888(x, y) \
168 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_ARGB8888)
169
170 #define DRAW_SETPIXELXY_BLEND_ARGB8888(x, y) \
171 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_BLEND_ARGB8888)
172
173 #define DRAW_SETPIXELXY_ADD_ARGB8888(x, y) \
174 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_ADD_ARGB8888)
175
176 /*
177 * Define draw operators for general RGB
178 */
179
180 #define DRAW_SETPIXEL_RGB \
181 DRAW_SETPIXEL(PIXEL_FROM_RGB(*pixel, fmt, sr, sg, sb))
182
183 #define DRAW_SETPIXEL_BLEND_RGB \
184 DRAW_SETPIXEL_BLEND(RGB_FROM_PIXEL(*pixel, fmt, sr, sg, sb), \
185 PIXEL_FROM_RGB(*pixel, fmt, sr, sg, sb))
186
187 #define DRAW_SETPIXEL_ADD_RGB \
188 DRAW_SETPIXEL_ADD(RGB_FROM_PIXEL(*pixel, fmt, sr, sg, sb), \
189 PIXEL_FROM_RGB(*pixel, fmt, sr, sg, sb))
190
191 #define DRAW_SETPIXELXY2_RGB(x, y) \
192 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_RGB)
193
194 #define DRAW_SETPIXELXY4_RGB(x, y) \
195 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_RGB)
196
197 #define DRAW_SETPIXELXY2_BLEND_RGB(x, y) \
198 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_BLEND_RGB)
199
200 #define DRAW_SETPIXELXY4_BLEND_RGB(x, y) \
201 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_BLEND_RGB)
202
203 #define DRAW_SETPIXELXY2_ADD_RGB(x, y) \
204 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_ADD_RGB)
205
206 #define DRAW_SETPIXELXY4_ADD_RGB(x, y) \
207 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_ADD_RGB)
208
209
210 /*
211 * Define draw operators for general RGBA
212 */
213
214 #define DRAW_SETPIXEL_RGBA \
215 DRAW_SETPIXEL(PIXEL_FROM_RGBA(*pixel, fmt, sr, sg, sb, sa))
216
217 #define DRAW_SETPIXEL_BLEND_RGBA \
218 DRAW_SETPIXEL_BLEND(RGBA_FROM_PIXEL(*pixel, fmt, sr, sg, sb, sa), \
219 PIXEL_FROM_RGBA(*pixel, fmt, sr, sg, sb, sa))
220
221 #define DRAW_SETPIXEL_ADD_RGBA \
222 DRAW_SETPIXEL_ADD(RGBA_FROM_PIXEL(*pixel, fmt, sr, sg, sb, sa), \
223 PIXEL_FROM_RGBA(*pixel, fmt, sr, sg, sb, sa))
224
225 #define DRAW_SETPIXELXY4_RGBA(x, y) \
226 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_RGBA)
227
228 #define DRAW_SETPIXELXY4_BLEND_RGBA(x, y) \
229 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_BLEND_RGBA)
230
231 #define DRAW_SETPIXELXY4_ADD_RGBA(x, y) \
232 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_ADD_RGBA)
233
234 /*
235 * Define line drawing macro
236 */
237
238 #define ABS(_x) ((_x) < 0 ? -(_x) : (_x))
239
240 /* Horizontal line */
241 #define HLINE(type, op, draw_end) \
242 { \
243 int length; \
244 int pitch = (dst->pitch / dst->format->BytesPerPixel); \
245 type *pixel; \
246 if (x1 <= x2) { \
247 pixel = (type *)dst->pixels + y1 * pitch + x1; \
248 length = draw_end ? (x2-x1+1) : (x2-x1); \
249 } else { \
250 pixel = (type *)dst->pixels + y1 * pitch + x2; \
251 if (!draw_end) { \
252 ++pixel; \
253 } \
254 length = draw_end ? (x1-x2+1) : (x1-x2); \
255 } \
256 while (length--) { \
257 op; \
258 ++pixel; \
259 } \
260 }
261
262 /* Vertical line */
263 #define VLINE(type, op, draw_end) \
264 { \
265 int length; \
266 int pitch = (dst->pitch / dst->format->BytesPerPixel); \
267 type *pixel; \
268 if (y1 <= y2) { \
269 pixel = (type *)dst->pixels + y1 * pitch + x1; \
270 length = draw_end ? (y2-y1+1) : (y2-y1); \
271 } else { \
272 pixel = (type *)dst->pixels + y2 * pitch + x1; \
273 if (!draw_end) { \
274 pixel += pitch; \
275 } \
276 length = draw_end ? (y1-y2+1) : (y1-y2); \
277 } \
278 while (length--) { \
279 op; \
280 pixel += pitch; \
281 } \
282 }
283
284 /* Diagonal line */
285 #define DLINE(type, op, draw_end) \
286 { \
287 int length; \
288 int pitch = (dst->pitch / dst->format->BytesPerPixel); \
289 type *pixel; \
290 if (y1 <= y2) { \
291 pixel = (type *)dst->pixels + y1 * pitch + x1; \
292 if (x1 <= x2) { \
293 ++pitch; \
294 } else { \
295 --pitch; \
296 } \
297 length = (y2-y1); \
298 } else { \
299 pixel = (type *)dst->pixels + y2 * pitch + x2; \
300 if (x2 <= x1) { \
301 ++pitch; \
302 } else { \
303 --pitch; \
304 } \
305 if (!draw_end) { \
306 pixel += pitch; \
307 } \
308 length = (y1-y2); \
309 } \
310 if (draw_end) { \
311 ++length; \
312 } \
313 while (length--) { \
314 op; \
315 pixel += pitch; \
316 } \
317 }
318
319 /* Bresenham's line algorithm */
320 #define BLINE(x1, y1, x2, y2, op, draw_end) \
321 { \
322 int i, deltax, deltay, numpixels; \
323 int d, dinc1, dinc2; \
324 int x, xinc1, xinc2; \
325 int y, yinc1, yinc2; \
326 \
327 deltax = ABS(x2 - x1); \
328 deltay = ABS(y2 - y1); \
329 \
330 if (deltax >= deltay) { \
331 numpixels = deltax + 1; \
332 d = (2 * deltay) - deltax; \
333 dinc1 = deltay * 2; \
334 dinc2 = (deltay - deltax) * 2; \
335 xinc1 = 1; \
336 xinc2 = 1; \
337 yinc1 = 0; \
338 yinc2 = 1; \
339 } else { \
340 numpixels = deltay + 1; \
341 d = (2 * deltax) - deltay; \
342 dinc1 = deltax * 2; \
343 dinc2 = (deltax - deltay) * 2; \
344 xinc1 = 0; \
345 xinc2 = 1; \
346 yinc1 = 1; \
347 yinc2 = 1; \
348 } \
349 \
350 if (x1 > x2) { \
351 xinc1 = -xinc1; \
352 xinc2 = -xinc2; \
353 } \
354 if (y1 > y2) { \
355 yinc1 = -yinc1; \
356 yinc2 = -yinc2; \
357 } \
358 \
359 x = x1; \
360 y = y1; \
361 \
362 if (!draw_end) { \
363 --numpixels; \
364 } \
365 for (i = 0; i < numpixels; ++i) { \
366 op(x, y); \
367 if (d < 0) { \
368 d += dinc1; \
369 x += xinc1; \
370 y += yinc1; \
371 } else { \
372 d += dinc2; \
373 x += xinc2; \
374 y += yinc2; \
375 } \
376 } \
377 }
378
379 /* Xiaolin Wu's line algorithm, based on Michael Abrash's implementation */
380 #define WULINE(x1, y1, x2, y2, opaque_op, blend_op, draw_end) \
381 { \
382 Uint16 ErrorAdj, ErrorAcc; \
383 Uint16 ErrorAccTemp, Weighting; \
384 int DeltaX, DeltaY, Temp, XDir; \
385 unsigned r, g, b, a, inva; \
386 \
387 /* Draw the initial pixel, which is always exactly intersected by \
388 the line and so needs no weighting */ \
389 opaque_op(x1, y1); \
390 \
391 /* Draw the final pixel, which is always exactly intersected by the line \
392 and so needs no weighting */ \
393 if (draw_end) { \
394 opaque_op(x2, y2); \
395 } \
396 \
397 /* Make sure the line runs top to bottom */ \
398 if (y1 > y2) { \
399 Temp = y1; y1 = y2; y2 = Temp; \
400 Temp = x1; x1 = x2; x2 = Temp; \
401 } \
402 DeltaY = y2 - y1; \
403 \
404 if ((DeltaX = x2 - x1) >= 0) { \
405 XDir = 1; \
406 } else { \
407 XDir = -1; \
408 DeltaX = -DeltaX; /* make DeltaX positive */ \
409 } \
410 \
411 /* line is not horizontal, diagonal, or vertical */ \
412 ErrorAcc = 0; /* initialize the line error accumulator to 0 */ \
413 \
414 /* Is this an X-major or Y-major line? */ \
415 if (DeltaY > DeltaX) { \
416 /* Y-major line; calculate 16-bit fixed-point fractional part of a \
417 pixel that X advances each time Y advances 1 pixel, truncating the \
418 result so that we won't overrun the endpoint along the X axis */ \
419 ErrorAdj = ((unsigned long) DeltaX << 16) / (unsigned long) DeltaY; \
420 /* Draw all pixels other than the first and last */ \
421 while (--DeltaY) { \
422 ErrorAccTemp = ErrorAcc; /* remember currrent accumulated error */ \
423 ErrorAcc += ErrorAdj; /* calculate error for next pixel */ \
424 if (ErrorAcc <= ErrorAccTemp) { \
425 /* The error accumulator turned over, so advance the X coord */ \
426 x1 += XDir; \
427 } \
428 y1++; /* Y-major, so always advance Y */ \
429 /* The IntensityBits most significant bits of ErrorAcc give us the \
430 intensity weighting for this pixel, and the complement of the \
431 weighting for the paired pixel */ \
432 Weighting = ErrorAcc >> 8; \
433 { \
434 a = DRAW_MUL(_a, (Weighting ^ 255)); \
435 r = DRAW_MUL(_r, a); \
436 g = DRAW_MUL(_g, a); \
437 b = DRAW_MUL(_b, a); \
438 inva = (a ^ 0xFF); \
439 blend_op(x1, y1); \
440 } \
441 { \
442 a = DRAW_MUL(_a, Weighting); \
443 r = DRAW_MUL(_r, a); \
444 g = DRAW_MUL(_g, a); \
445 b = DRAW_MUL(_b, a); \
446 inva = (a ^ 0xFF); \
447 blend_op(x1 + XDir, y1); \
448 } \
449 } \
450 } else { \
451 /* X-major line; calculate 16-bit fixed-point fractional part of a \
452 pixel that Y advances each time X advances 1 pixel, truncating the \
453 result to avoid overrunning the endpoint along the X axis */ \
454 ErrorAdj = ((unsigned long) DeltaY << 16) / (unsigned long) DeltaX; \
455 /* Draw all pixels other than the first and last */ \
456 while (--DeltaX) { \
457 ErrorAccTemp = ErrorAcc; /* remember currrent accumulated error */ \
458 ErrorAcc += ErrorAdj; /* calculate error for next pixel */ \
459 if (ErrorAcc <= ErrorAccTemp) { \
460 /* The error accumulator turned over, so advance the Y coord */ \
461 y1++; \
462 } \
463 x1 += XDir; /* X-major, so always advance X */ \
464 /* The IntensityBits most significant bits of ErrorAcc give us the \
465 intensity weighting for this pixel, and the complement of the \
466 weighting for the paired pixel */ \
467 Weighting = ErrorAcc >> 8; \
468 { \
469 a = DRAW_MUL(_a, (Weighting ^ 255)); \
470 r = DRAW_MUL(_r, a); \
471 g = DRAW_MUL(_g, a); \
472 b = DRAW_MUL(_b, a); \
473 inva = (a ^ 0xFF); \
474 blend_op(x1, y1); \
475 } \
476 { \
477 a = DRAW_MUL(_a, Weighting); \
478 r = DRAW_MUL(_r, a); \
479 g = DRAW_MUL(_g, a); \
480 b = DRAW_MUL(_b, a); \
481 inva = (a ^ 0xFF); \
482 blend_op(x1, y1 + 1); \
483 } \
484 } \
485 } \
486 }
487
488 #ifdef AA_LINES
489 #define AALINE(x1, y1, x2, y2, opaque_op, blend_op, draw_end) \
490 WULINE(x1, y1, x2, y2, opaque_op, blend_op, draw_end)
491 #else
492 #define AALINE(x1, y1, x2, y2, opaque_op, blend_op, draw_end) \
493 BLINE(x1, y1, x2, y2, opaque_op, draw_end)
494 #endif
495
496 /*
497 * Define fill rect macro
498 */
499
500 #define FILLRECT(type, op) \
501 do { \
502 int width = rect->w; \
503 int height = rect->h; \
504 int pitch = (dst->pitch / dst->format->BytesPerPixel); \
505 int skip = pitch - width; \
506 type *pixel = (type *)dst->pixels + rect->y * pitch + rect->x; \
507 while (height--) { \
508 { int n = (width+3)/4; \
509 switch (width & 3) { \
510 case 0: do { op; pixel++; \
511 case 3: op; pixel++; \
512 case 2: op; pixel++; \
513 case 1: op; pixel++; \
514 } while ( --n > 0 ); \
515 } \
516 } \
517 pixel += skip; \
518 } \
519 } while (0)
520
521 /* vi: set ts=4 sw=4 expandtab: */