Mercurial > sdl-ios-xcode
annotate src/video/SDL_blit_1.c @ 4216:5b99971a27b4 SDL-1.2
Fixed bug #698
Hans de Goede 2009-02-13 01:10:52 PST
Since the new "glitch free" version of pulseaudio (used in Fedora 10 amongst
others), the sound of SDL using apps (like a simple playmus call) has been
crackling.
While looking in to fixing this I noticed that the current pulseaudio code in
SDL uses pa_simple. However pa_simple uses a thread to pump pulseaudio events
and ipc, given that SDL already has its own thread for audio handling this is
clearly suboptimal, leading to unnecessary context switching IPC, etc. Also
pa_simple does not allow one to implement the WaitAudio() callback for SDL
audiodrivers properly.
Given that my work is mostly a rewrite (although some original pieces remain)
I'm attaching the new .c and .h file, as that is easier to review then the huge
diff.
Let me know if you also want the diff.
This new version has the following features:
-no longer use an additional thread next to the SDL sound thread
-do not crackle with glitch free audio
-when used with a newer pulse, which does glitch free audio, the total latency
is
the same as with the alsa driver
-proper WaitAudio() implementation, saving another mixlen worth of latency
-adds a WaitDone() implementation
This patch has been written in consultancy with Lennart Poetering (the
pulseaudio author) and has been reviewed by him for correct use of the pa API.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 21 Sep 2009 09:27:08 +0000 |
parents | a1b03ba2fcd0 |
children |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
4159 | 3 Copyright (C) 1997-2009 Sam Lantinga |
0 | 4 |
5 This library is free software; you can redistribute it and/or | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
6 modify it under the terms of the GNU Lesser General Public |
0 | 7 License as published by the Free Software Foundation; either |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
8 version 2.1 of the License, or (at your option) any later version. |
0 | 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 | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
13 Lesser General Public License for more details. |
0 | 14 |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
15 You should have received a copy of the GNU Lesser General Public |
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
16 License along with this library; if not, write to the Free Software |
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
0 | 18 |
19 Sam Lantinga | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
91
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
1402
d910939febfa
Use consistent identifiers for the various platforms we support.
Sam Lantinga <slouken@libsdl.org>
parents:
1358
diff
changeset
|
22 #include "SDL_config.h" |
0 | 23 |
24 #include "SDL_video.h" | |
25 #include "SDL_blit.h" | |
26 #include "SDL_sysvideo.h" | |
27 #include "SDL_endian.h" | |
28 | |
29 /* Functions to blit from 8-bit surfaces to other surfaces */ | |
30 | |
31 static void Blit1to1(SDL_BlitInfo *info) | |
32 { | |
33 #ifndef USE_DUFFS_LOOP | |
34 int c; | |
35 #endif | |
36 int width, height; | |
37 Uint8 *src, *map, *dst; | |
38 int srcskip, dstskip; | |
39 | |
40 /* Set up some basic variables */ | |
41 width = info->d_width; | |
42 height = info->d_height; | |
43 src = info->s_pixels; | |
44 srcskip = info->s_skip; | |
45 dst = info->d_pixels; | |
46 dstskip = info->d_skip; | |
47 map = info->table; | |
48 | |
49 while ( height-- ) { | |
50 #ifdef USE_DUFFS_LOOP | |
51 DUFFS_LOOP( | |
52 { | |
53 *dst = map[*src]; | |
54 } | |
55 dst++; | |
56 src++; | |
57 , width); | |
58 #else | |
59 for ( c=width; c; --c ) { | |
60 *dst = map[*src]; | |
61 dst++; | |
62 src++; | |
63 } | |
64 #endif | |
65 src += srcskip; | |
66 dst += dstskip; | |
67 } | |
68 } | |
69 /* This is now endian dependent */ | |
70 #if ( SDL_BYTEORDER == SDL_LIL_ENDIAN ) | |
71 #define HI 1 | |
72 #define LO 0 | |
73 #else /* ( SDL_BYTEORDER == SDL_BIG_ENDIAN ) */ | |
74 #define HI 0 | |
75 #define LO 1 | |
76 #endif | |
77 static void Blit1to2(SDL_BlitInfo *info) | |
78 { | |
79 #ifndef USE_DUFFS_LOOP | |
80 int c; | |
81 #endif | |
82 int width, height; | |
83 Uint8 *src, *dst; | |
84 Uint16 *map; | |
85 int srcskip, dstskip; | |
86 | |
87 /* Set up some basic variables */ | |
88 width = info->d_width; | |
89 height = info->d_height; | |
90 src = info->s_pixels; | |
91 srcskip = info->s_skip; | |
92 dst = info->d_pixels; | |
93 dstskip = info->d_skip; | |
94 map = (Uint16 *)info->table; | |
95 | |
96 #ifdef USE_DUFFS_LOOP | |
97 while ( height-- ) { | |
98 DUFFS_LOOP( | |
99 { | |
100 *(Uint16 *)dst = map[*src++]; | |
101 dst += 2; | |
102 }, | |
103 width); | |
104 src += srcskip; | |
105 dst += dstskip; | |
106 } | |
107 #else | |
108 /* Memory align at 4-byte boundary, if necessary */ | |
109 if ( (long)dst & 0x03 ) { | |
110 /* Don't do anything if width is 0 */ | |
111 if ( width == 0 ) { | |
112 return; | |
113 } | |
114 --width; | |
115 | |
116 while ( height-- ) { | |
117 /* Perform copy alignment */ | |
118 *(Uint16 *)dst = map[*src++]; | |
119 dst += 2; | |
120 | |
121 /* Copy in 4 pixel chunks */ | |
122 for ( c=width/4; c; --c ) { | |
123 *(Uint32 *)dst = | |
124 (map[src[HI]]<<16)|(map[src[LO]]); | |
125 src += 2; | |
126 dst += 4; | |
127 *(Uint32 *)dst = | |
128 (map[src[HI]]<<16)|(map[src[LO]]); | |
129 src += 2; | |
130 dst += 4; | |
131 } | |
132 /* Get any leftovers */ | |
91
e85e03f195b4
From: "Markus F.X.J. Oberhumer"
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
133 switch (width & 3) { |
0 | 134 case 3: |
135 *(Uint16 *)dst = map[*src++]; | |
136 dst += 2; | |
137 case 2: | |
138 *(Uint32 *)dst = | |
139 (map[src[HI]]<<16)|(map[src[LO]]); | |
140 src += 2; | |
141 dst += 4; | |
142 break; | |
143 case 1: | |
144 *(Uint16 *)dst = map[*src++]; | |
145 dst += 2; | |
146 break; | |
147 } | |
148 src += srcskip; | |
149 dst += dstskip; | |
150 } | |
151 } else { | |
152 while ( height-- ) { | |
153 /* Copy in 4 pixel chunks */ | |
154 for ( c=width/4; c; --c ) { | |
155 *(Uint32 *)dst = | |
156 (map[src[HI]]<<16)|(map[src[LO]]); | |
157 src += 2; | |
158 dst += 4; | |
159 *(Uint32 *)dst = | |
160 (map[src[HI]]<<16)|(map[src[LO]]); | |
161 src += 2; | |
162 dst += 4; | |
163 } | |
164 /* Get any leftovers */ | |
91
e85e03f195b4
From: "Markus F.X.J. Oberhumer"
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
165 switch (width & 3) { |
0 | 166 case 3: |
167 *(Uint16 *)dst = map[*src++]; | |
168 dst += 2; | |
169 case 2: | |
170 *(Uint32 *)dst = | |
171 (map[src[HI]]<<16)|(map[src[LO]]); | |
172 src += 2; | |
173 dst += 4; | |
174 break; | |
175 case 1: | |
176 *(Uint16 *)dst = map[*src++]; | |
177 dst += 2; | |
178 break; | |
179 } | |
180 src += srcskip; | |
181 dst += dstskip; | |
182 } | |
183 } | |
184 #endif /* USE_DUFFS_LOOP */ | |
185 } | |
186 static void Blit1to3(SDL_BlitInfo *info) | |
187 { | |
188 #ifndef USE_DUFFS_LOOP | |
189 int c; | |
190 #endif | |
191 int o; | |
192 int width, height; | |
193 Uint8 *src, *map, *dst; | |
194 int srcskip, dstskip; | |
195 | |
196 /* Set up some basic variables */ | |
197 width = info->d_width; | |
198 height = info->d_height; | |
199 src = info->s_pixels; | |
200 srcskip = info->s_skip; | |
201 dst = info->d_pixels; | |
202 dstskip = info->d_skip; | |
203 map = info->table; | |
204 | |
205 while ( height-- ) { | |
206 #ifdef USE_DUFFS_LOOP | |
207 DUFFS_LOOP( | |
208 { | |
209 o = *src * 4; | |
210 dst[0] = map[o++]; | |
211 dst[1] = map[o++]; | |
212 dst[2] = map[o++]; | |
213 } | |
214 src++; | |
215 dst += 3; | |
216 , width); | |
217 #else | |
218 for ( c=width; c; --c ) { | |
219 o = *src * 4; | |
220 dst[0] = map[o++]; | |
221 dst[1] = map[o++]; | |
222 dst[2] = map[o++]; | |
223 src++; | |
224 dst += 3; | |
225 } | |
226 #endif /* USE_DUFFS_LOOP */ | |
227 src += srcskip; | |
228 dst += dstskip; | |
229 } | |
230 } | |
231 static void Blit1to4(SDL_BlitInfo *info) | |
232 { | |
233 #ifndef USE_DUFFS_LOOP | |
234 int c; | |
235 #endif | |
236 int width, height; | |
237 Uint8 *src; | |
238 Uint32 *map, *dst; | |
239 int srcskip, dstskip; | |
240 | |
241 /* Set up some basic variables */ | |
242 width = info->d_width; | |
243 height = info->d_height; | |
244 src = info->s_pixels; | |
245 srcskip = info->s_skip; | |
246 dst = (Uint32 *)info->d_pixels; | |
247 dstskip = info->d_skip/4; | |
248 map = (Uint32 *)info->table; | |
249 | |
250 while ( height-- ) { | |
251 #ifdef USE_DUFFS_LOOP | |
252 DUFFS_LOOP( | |
253 *dst++ = map[*src++]; | |
254 , width); | |
255 #else | |
256 for ( c=width/4; c; --c ) { | |
257 *dst++ = map[*src++]; | |
258 *dst++ = map[*src++]; | |
259 *dst++ = map[*src++]; | |
260 *dst++ = map[*src++]; | |
261 } | |
91
e85e03f195b4
From: "Markus F.X.J. Oberhumer"
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
262 switch ( width & 3 ) { |
0 | 263 case 3: |
264 *dst++ = map[*src++]; | |
265 case 2: | |
266 *dst++ = map[*src++]; | |
267 case 1: | |
268 *dst++ = map[*src++]; | |
269 } | |
270 #endif /* USE_DUFFS_LOOP */ | |
271 src += srcskip; | |
272 dst += dstskip; | |
273 } | |
274 } | |
275 | |
276 static void Blit1to1Key(SDL_BlitInfo *info) | |
277 { | |
278 int width = info->d_width; | |
279 int height = info->d_height; | |
280 Uint8 *src = info->s_pixels; | |
281 int srcskip = info->s_skip; | |
282 Uint8 *dst = info->d_pixels; | |
283 int dstskip = info->d_skip; | |
284 Uint8 *palmap = info->table; | |
285 Uint32 ckey = info->src->colorkey; | |
286 | |
287 if ( palmap ) { | |
288 while ( height-- ) { | |
289 DUFFS_LOOP( | |
290 { | |
291 if ( *src != ckey ) { | |
292 *dst = palmap[*src]; | |
293 } | |
294 dst++; | |
295 src++; | |
296 }, | |
297 width); | |
298 src += srcskip; | |
299 dst += dstskip; | |
300 } | |
301 } else { | |
302 while ( height-- ) { | |
303 DUFFS_LOOP( | |
304 { | |
305 if ( *src != ckey ) { | |
306 *dst = *src; | |
307 } | |
308 dst++; | |
309 src++; | |
310 }, | |
311 width); | |
312 src += srcskip; | |
313 dst += dstskip; | |
314 } | |
315 } | |
316 } | |
317 | |
318 static void Blit1to2Key(SDL_BlitInfo *info) | |
319 { | |
320 int width = info->d_width; | |
321 int height = info->d_height; | |
322 Uint8 *src = info->s_pixels; | |
323 int srcskip = info->s_skip; | |
324 Uint16 *dstp = (Uint16 *)info->d_pixels; | |
325 int dstskip = info->d_skip; | |
326 Uint16 *palmap = (Uint16 *)info->table; | |
327 Uint32 ckey = info->src->colorkey; | |
328 | |
329 /* Set up some basic variables */ | |
330 dstskip /= 2; | |
331 | |
332 while ( height-- ) { | |
333 DUFFS_LOOP( | |
334 { | |
335 if ( *src != ckey ) { | |
336 *dstp=palmap[*src]; | |
337 } | |
338 src++; | |
339 dstp++; | |
340 }, | |
341 width); | |
342 src += srcskip; | |
343 dstp += dstskip; | |
344 } | |
345 } | |
346 | |
347 static void Blit1to3Key(SDL_BlitInfo *info) | |
348 { | |
349 int width = info->d_width; | |
350 int height = info->d_height; | |
351 Uint8 *src = info->s_pixels; | |
352 int srcskip = info->s_skip; | |
353 Uint8 *dst = info->d_pixels; | |
354 int dstskip = info->d_skip; | |
355 Uint8 *palmap = info->table; | |
356 Uint32 ckey = info->src->colorkey; | |
357 int o; | |
358 | |
359 while ( height-- ) { | |
360 DUFFS_LOOP( | |
361 { | |
362 if ( *src != ckey ) { | |
363 o = *src * 4; | |
364 dst[0] = palmap[o++]; | |
365 dst[1] = palmap[o++]; | |
366 dst[2] = palmap[o++]; | |
367 } | |
368 src++; | |
369 dst += 3; | |
370 }, | |
371 width); | |
372 src += srcskip; | |
373 dst += dstskip; | |
374 } | |
375 } | |
376 | |
377 static void Blit1to4Key(SDL_BlitInfo *info) | |
378 { | |
379 int width = info->d_width; | |
380 int height = info->d_height; | |
381 Uint8 *src = info->s_pixels; | |
382 int srcskip = info->s_skip; | |
383 Uint32 *dstp = (Uint32 *)info->d_pixels; | |
384 int dstskip = info->d_skip; | |
385 Uint32 *palmap = (Uint32 *)info->table; | |
386 Uint32 ckey = info->src->colorkey; | |
387 | |
388 /* Set up some basic variables */ | |
389 dstskip /= 4; | |
390 | |
391 while ( height-- ) { | |
392 DUFFS_LOOP( | |
393 { | |
394 if ( *src != ckey ) { | |
395 *dstp = palmap[*src]; | |
396 } | |
397 src++; | |
398 dstp++; | |
399 }, | |
400 width); | |
401 src += srcskip; | |
402 dstp += dstskip; | |
403 } | |
404 } | |
405 | |
406 static void Blit1toNAlpha(SDL_BlitInfo *info) | |
407 { | |
408 int width = info->d_width; | |
409 int height = info->d_height; | |
410 Uint8 *src = info->s_pixels; | |
411 int srcskip = info->s_skip; | |
412 Uint8 *dst = info->d_pixels; | |
413 int dstskip = info->d_skip; | |
414 SDL_PixelFormat *dstfmt = info->dst; | |
415 const SDL_Color *srcpal = info->src->palette->colors; | |
416 int dstbpp; | |
417 const int A = info->src->alpha; | |
418 | |
419 /* Set up some basic variables */ | |
420 dstbpp = dstfmt->BytesPerPixel; | |
421 | |
422 while ( height-- ) { | |
423 int sR, sG, sB; | |
424 int dR, dG, dB; | |
425 DUFFS_LOOP4( | |
426 { | |
427 Uint32 pixel; | |
428 sR = srcpal[*src].r; | |
429 sG = srcpal[*src].g; | |
430 sB = srcpal[*src].b; | |
431 DISEMBLE_RGB(dst, dstbpp, dstfmt, | |
432 pixel, dR, dG, dB); | |
433 ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB); | |
434 ASSEMBLE_RGB(dst, dstbpp, dstfmt, dR, dG, dB); | |
435 src++; | |
436 dst += dstbpp; | |
437 }, | |
438 width); | |
439 src += srcskip; | |
440 dst += dstskip; | |
441 } | |
442 } | |
443 | |
444 static void Blit1toNAlphaKey(SDL_BlitInfo *info) | |
445 { | |
446 int width = info->d_width; | |
447 int height = info->d_height; | |
448 Uint8 *src = info->s_pixels; | |
449 int srcskip = info->s_skip; | |
450 Uint8 *dst = info->d_pixels; | |
451 int dstskip = info->d_skip; | |
452 SDL_PixelFormat *srcfmt = info->src; | |
453 SDL_PixelFormat *dstfmt = info->dst; | |
454 const SDL_Color *srcpal = info->src->palette->colors; | |
455 Uint32 ckey = srcfmt->colorkey; | |
456 int dstbpp; | |
457 const int A = srcfmt->alpha; | |
458 | |
459 /* Set up some basic variables */ | |
460 dstbpp = dstfmt->BytesPerPixel; | |
461 | |
462 while ( height-- ) { | |
463 int sR, sG, sB; | |
464 int dR, dG, dB; | |
465 DUFFS_LOOP( | |
466 { | |
467 if ( *src != ckey ) { | |
468 Uint32 pixel; | |
469 sR = srcpal[*src].r; | |
470 sG = srcpal[*src].g; | |
471 sB = srcpal[*src].b; | |
472 DISEMBLE_RGB(dst, dstbpp, dstfmt, | |
473 pixel, dR, dG, dB); | |
474 ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB); | |
475 ASSEMBLE_RGB(dst, dstbpp, dstfmt, dR, dG, dB); | |
476 } | |
477 src++; | |
478 dst += dstbpp; | |
479 }, | |
480 width); | |
481 src += srcskip; | |
482 dst += dstskip; | |
483 } | |
484 } | |
485 | |
486 static SDL_loblit one_blit[] = { | |
487 NULL, Blit1to1, Blit1to2, Blit1to3, Blit1to4 | |
488 }; | |
489 | |
490 static SDL_loblit one_blitkey[] = { | |
491 NULL, Blit1to1Key, Blit1to2Key, Blit1to3Key, Blit1to4Key | |
492 }; | |
493 | |
494 SDL_loblit SDL_CalculateBlit1(SDL_Surface *surface, int blit_index) | |
495 { | |
496 int which; | |
497 SDL_PixelFormat *dstfmt; | |
498 | |
499 dstfmt = surface->map->dst->format; | |
500 if ( dstfmt->BitsPerPixel < 8 ) { | |
501 which = 0; | |
502 } else { | |
503 which = dstfmt->BytesPerPixel; | |
504 } | |
505 switch(blit_index) { | |
506 case 0: /* copy */ | |
507 return one_blit[which]; | |
508 | |
509 case 1: /* colorkey */ | |
510 return one_blitkey[which]; | |
511 | |
512 case 2: /* alpha */ | |
513 /* Supporting 8bpp->8bpp alpha is doable but requires lots of | |
514 tables which consume space and takes time to precompute, | |
515 so is better left to the user */ | |
516 return which >= 2 ? Blit1toNAlpha : NULL; | |
517 | |
518 case 3: /* alpha + colorkey */ | |
519 return which >= 2 ? Blit1toNAlphaKey : NULL; | |
520 | |
521 } | |
522 return NULL; | |
523 } |