diff options
Diffstat (limited to 'apps/plugins/sdl/src/video/SDL_blit.c')
-rw-r--r-- | apps/plugins/sdl/src/video/SDL_blit.c | 360 |
1 files changed, 360 insertions, 0 deletions
diff --git a/apps/plugins/sdl/src/video/SDL_blit.c b/apps/plugins/sdl/src/video/SDL_blit.c new file mode 100644 index 0000000000..e3f194aee4 --- /dev/null +++ b/apps/plugins/sdl/src/video/SDL_blit.c | |||
@@ -0,0 +1,360 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 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 "SDL_video.h" | ||
25 | #include "SDL_sysvideo.h" | ||
26 | #include "SDL_blit.h" | ||
27 | #include "SDL_RLEaccel_c.h" | ||
28 | #include "SDL_pixels_c.h" | ||
29 | |||
30 | #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && SDL_ASSEMBLY_ROUTINES | ||
31 | #define MMX_ASMBLIT | ||
32 | #if (__GNUC__ > 2) /* SSE instructions aren't in GCC 2. */ | ||
33 | #define SSE_ASMBLIT | ||
34 | #endif | ||
35 | #endif | ||
36 | |||
37 | #if defined(MMX_ASMBLIT) | ||
38 | #include "SDL_cpuinfo.h" | ||
39 | #include "mmx.h" | ||
40 | #endif | ||
41 | |||
42 | /* The general purpose software blit routine */ | ||
43 | static int SDL_SoftBlit(SDL_Surface *src, SDL_Rect *srcrect, | ||
44 | SDL_Surface *dst, SDL_Rect *dstrect) | ||
45 | { | ||
46 | int okay; | ||
47 | int src_locked; | ||
48 | int dst_locked; | ||
49 | |||
50 | /* Everything is okay at the beginning... */ | ||
51 | okay = 1; | ||
52 | |||
53 | /* Lock the destination if it's in hardware */ | ||
54 | dst_locked = 0; | ||
55 | if ( SDL_MUSTLOCK(dst) ) { | ||
56 | if ( SDL_LockSurface(dst) < 0 ) { | ||
57 | okay = 0; | ||
58 | } else { | ||
59 | dst_locked = 1; | ||
60 | } | ||
61 | } | ||
62 | /* Lock the source if it's in hardware */ | ||
63 | src_locked = 0; | ||
64 | if ( SDL_MUSTLOCK(src) ) { | ||
65 | if ( SDL_LockSurface(src) < 0 ) { | ||
66 | okay = 0; | ||
67 | } else { | ||
68 | src_locked = 1; | ||
69 | } | ||
70 | } | ||
71 | |||
72 | /* Set up source and destination buffer pointers, and BLIT! */ | ||
73 | if ( okay && srcrect->w && srcrect->h ) { | ||
74 | SDL_BlitInfo info; | ||
75 | SDL_loblit RunBlit; | ||
76 | |||
77 | /* Set up the blit information */ | ||
78 | info.s_pixels = (Uint8 *)src->pixels + | ||
79 | (Uint16)srcrect->y*src->pitch + | ||
80 | (Uint16)srcrect->x*src->format->BytesPerPixel; | ||
81 | info.s_width = srcrect->w; | ||
82 | info.s_height = srcrect->h; | ||
83 | info.s_skip=src->pitch-info.s_width*src->format->BytesPerPixel; | ||
84 | info.d_pixels = (Uint8 *)dst->pixels + | ||
85 | (Uint16)dstrect->y*dst->pitch + | ||
86 | (Uint16)dstrect->x*dst->format->BytesPerPixel; | ||
87 | info.d_width = dstrect->w; | ||
88 | info.d_height = dstrect->h; | ||
89 | info.d_skip=dst->pitch-info.d_width*dst->format->BytesPerPixel; | ||
90 | info.aux_data = src->map->sw_data->aux_data; | ||
91 | info.src = src->format; | ||
92 | info.table = src->map->table; | ||
93 | info.dst = dst->format; | ||
94 | RunBlit = src->map->sw_data->blit; | ||
95 | |||
96 | /* Run the actual software blit */ | ||
97 | RunBlit(&info); | ||
98 | } | ||
99 | |||
100 | /* We need to unlock the surfaces if they're locked */ | ||
101 | if ( dst_locked ) { | ||
102 | SDL_UnlockSurface(dst); | ||
103 | } | ||
104 | if ( src_locked ) { | ||
105 | SDL_UnlockSurface(src); | ||
106 | } | ||
107 | /* Blit is done! */ | ||
108 | return(okay ? 0 : -1); | ||
109 | } | ||
110 | |||
111 | #ifdef MMX_ASMBLIT | ||
112 | static __inline__ void SDL_memcpyMMX(Uint8 *to, const Uint8 *from, int len) | ||
113 | { | ||
114 | int i; | ||
115 | |||
116 | for(i=0; i<len/8; i++) { | ||
117 | __asm__ __volatile__ ( | ||
118 | " movq (%0), %%mm0\n" | ||
119 | " movq %%mm0, (%1)\n" | ||
120 | : : "r" (from), "r" (to) : "memory"); | ||
121 | from+=8; | ||
122 | to+=8; | ||
123 | } | ||
124 | if (len&7) | ||
125 | SDL_memcpy(to, from, len&7); | ||
126 | } | ||
127 | |||
128 | #ifdef SSE_ASMBLIT | ||
129 | static __inline__ void SDL_memcpySSE(Uint8 *to, const Uint8 *from, int len) | ||
130 | { | ||
131 | int i; | ||
132 | |||
133 | __asm__ __volatile__ ( | ||
134 | " prefetchnta (%0)\n" | ||
135 | " prefetchnta 64(%0)\n" | ||
136 | " prefetchnta 128(%0)\n" | ||
137 | " prefetchnta 192(%0)\n" | ||
138 | : : "r" (from) ); | ||
139 | |||
140 | for(i=0; i<len/8; i++) { | ||
141 | __asm__ __volatile__ ( | ||
142 | " prefetchnta 256(%0)\n" | ||
143 | " movq (%0), %%mm0\n" | ||
144 | " movntq %%mm0, (%1)\n" | ||
145 | : : "r" (from), "r" (to) : "memory"); | ||
146 | from+=8; | ||
147 | to+=8; | ||
148 | } | ||
149 | if (len&7) | ||
150 | SDL_memcpy(to, from, len&7); | ||
151 | } | ||
152 | #endif | ||
153 | #endif | ||
154 | |||
155 | static void SDL_BlitCopy(SDL_BlitInfo *info) | ||
156 | { | ||
157 | Uint8 *src, *dst; | ||
158 | int w, h; | ||
159 | int srcskip, dstskip; | ||
160 | |||
161 | w = info->d_width*info->dst->BytesPerPixel; | ||
162 | h = info->d_height; | ||
163 | src = info->s_pixels; | ||
164 | dst = info->d_pixels; | ||
165 | srcskip = w+info->s_skip; | ||
166 | dstskip = w+info->d_skip; | ||
167 | |||
168 | #ifdef SSE_ASMBLIT | ||
169 | if(SDL_HasSSE()) | ||
170 | { | ||
171 | while ( h-- ) { | ||
172 | SDL_memcpySSE(dst, src, w); | ||
173 | src += srcskip; | ||
174 | dst += dstskip; | ||
175 | } | ||
176 | __asm__ __volatile__ ( | ||
177 | " emms\n" | ||
178 | ::); | ||
179 | } | ||
180 | else | ||
181 | #endif | ||
182 | #ifdef MMX_ASMBLIT | ||
183 | if(SDL_HasMMX()) | ||
184 | { | ||
185 | while ( h-- ) { | ||
186 | SDL_memcpyMMX(dst, src, w); | ||
187 | src += srcskip; | ||
188 | dst += dstskip; | ||
189 | } | ||
190 | __asm__ __volatile__ ( | ||
191 | " emms\n" | ||
192 | ::); | ||
193 | } | ||
194 | else | ||
195 | #endif | ||
196 | while ( h-- ) { | ||
197 | SDL_memcpy(dst, src, w); | ||
198 | src += srcskip; | ||
199 | dst += dstskip; | ||
200 | } | ||
201 | } | ||
202 | |||
203 | static void SDL_BlitCopyOverlap(SDL_BlitInfo *info) | ||
204 | { | ||
205 | Uint8 *src, *dst; | ||
206 | int w, h; | ||
207 | int srcskip, dstskip; | ||
208 | |||
209 | w = info->d_width*info->dst->BytesPerPixel; | ||
210 | h = info->d_height; | ||
211 | src = info->s_pixels; | ||
212 | dst = info->d_pixels; | ||
213 | srcskip = w+info->s_skip; | ||
214 | dstskip = w+info->d_skip; | ||
215 | if ( dst < src ) { | ||
216 | while ( h-- ) { | ||
217 | SDL_memmove(dst, src, w); | ||
218 | src += srcskip; | ||
219 | dst += dstskip; | ||
220 | } | ||
221 | } else { | ||
222 | src += ((h-1) * srcskip); | ||
223 | dst += ((h-1) * dstskip); | ||
224 | while ( h-- ) { | ||
225 | SDL_revcpy(dst, src, w); | ||
226 | src -= srcskip; | ||
227 | dst -= dstskip; | ||
228 | } | ||
229 | } | ||
230 | } | ||
231 | |||
232 | /* Figure out which of many blit routines to set up on a surface */ | ||
233 | int SDL_CalculateBlit(SDL_Surface *surface) | ||
234 | { | ||
235 | int blit_index; | ||
236 | |||
237 | /* Clean everything out to start */ | ||
238 | if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) { | ||
239 | SDL_UnRLESurface(surface, 1); | ||
240 | } | ||
241 | surface->map->sw_blit = NULL; | ||
242 | |||
243 | /* Figure out if an accelerated hardware blit is possible */ | ||
244 | surface->flags &= ~SDL_HWACCEL; | ||
245 | if ( surface->map->identity ) { | ||
246 | int hw_blit_ok; | ||
247 | |||
248 | if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) { | ||
249 | /* We only support accelerated blitting to hardware */ | ||
250 | if ( surface->map->dst->flags & SDL_HWSURFACE ) { | ||
251 | hw_blit_ok = current_video->info.blit_hw; | ||
252 | } else { | ||
253 | hw_blit_ok = 0; | ||
254 | } | ||
255 | if (hw_blit_ok && (surface->flags & SDL_SRCCOLORKEY)) { | ||
256 | hw_blit_ok = current_video->info.blit_hw_CC; | ||
257 | } | ||
258 | if ( hw_blit_ok && (surface->flags & SDL_SRCALPHA) ) { | ||
259 | hw_blit_ok = current_video->info.blit_hw_A; | ||
260 | } | ||
261 | } else { | ||
262 | /* We only support accelerated blitting to hardware */ | ||
263 | if ( surface->map->dst->flags & SDL_HWSURFACE ) { | ||
264 | hw_blit_ok = current_video->info.blit_sw; | ||
265 | } else { | ||
266 | hw_blit_ok = 0; | ||
267 | } | ||
268 | if (hw_blit_ok && (surface->flags & SDL_SRCCOLORKEY)) { | ||
269 | hw_blit_ok = current_video->info.blit_sw_CC; | ||
270 | } | ||
271 | if ( hw_blit_ok && (surface->flags & SDL_SRCALPHA) ) { | ||
272 | hw_blit_ok = current_video->info.blit_sw_A; | ||
273 | } | ||
274 | } | ||
275 | if ( hw_blit_ok ) { | ||
276 | SDL_VideoDevice *video = current_video; | ||
277 | SDL_VideoDevice *this = current_video; | ||
278 | video->CheckHWBlit(this, surface, surface->map->dst); | ||
279 | } | ||
280 | } | ||
281 | |||
282 | /* if an alpha pixel format is specified, we can accelerate alpha blits */ | ||
283 | if (((surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE )&&(current_video->displayformatalphapixel)) | ||
284 | { | ||
285 | if ( (surface->flags & SDL_SRCALPHA) ) | ||
286 | if ( current_video->info.blit_hw_A ) { | ||
287 | SDL_VideoDevice *video = current_video; | ||
288 | SDL_VideoDevice *this = current_video; | ||
289 | video->CheckHWBlit(this, surface, surface->map->dst); | ||
290 | } | ||
291 | } | ||
292 | |||
293 | /* Get the blit function index, based on surface mode */ | ||
294 | /* { 0 = nothing, 1 = colorkey, 2 = alpha, 3 = colorkey+alpha } */ | ||
295 | blit_index = 0; | ||
296 | blit_index |= (!!(surface->flags & SDL_SRCCOLORKEY)) << 0; | ||
297 | if ( surface->flags & SDL_SRCALPHA | ||
298 | && (surface->format->alpha != SDL_ALPHA_OPAQUE | ||
299 | || surface->format->Amask) ) { | ||
300 | blit_index |= 2; | ||
301 | } | ||
302 | |||
303 | /* Check for special "identity" case -- copy blit */ | ||
304 | if ( surface->map->identity && blit_index == 0 ) { | ||
305 | surface->map->sw_data->blit = SDL_BlitCopy; | ||
306 | |||
307 | /* Handle overlapping blits on the same surface */ | ||
308 | if ( surface == surface->map->dst ) { | ||
309 | surface->map->sw_data->blit = SDL_BlitCopyOverlap; | ||
310 | } | ||
311 | } else { | ||
312 | if ( surface->format->BitsPerPixel < 8 ) { | ||
313 | surface->map->sw_data->blit = | ||
314 | SDL_CalculateBlit0(surface, blit_index); | ||
315 | } else { | ||
316 | switch ( surface->format->BytesPerPixel ) { | ||
317 | case 1: | ||
318 | surface->map->sw_data->blit = | ||
319 | SDL_CalculateBlit1(surface, blit_index); | ||
320 | break; | ||
321 | case 2: | ||
322 | case 3: | ||
323 | case 4: | ||
324 | surface->map->sw_data->blit = | ||
325 | SDL_CalculateBlitN(surface, blit_index); | ||
326 | break; | ||
327 | default: | ||
328 | surface->map->sw_data->blit = NULL; | ||
329 | break; | ||
330 | } | ||
331 | } | ||
332 | } | ||
333 | /* Make sure we have a blit function */ | ||
334 | if ( surface->map->sw_data->blit == NULL ) { | ||
335 | SDL_InvalidateMap(surface->map); | ||
336 | SDL_SetError("Blit combination not supported"); | ||
337 | return(-1); | ||
338 | } | ||
339 | |||
340 | /* Choose software blitting function */ | ||
341 | if(surface->flags & SDL_RLEACCELOK | ||
342 | && (surface->flags & SDL_HWACCEL) != SDL_HWACCEL) { | ||
343 | |||
344 | if(surface->map->identity | ||
345 | && (blit_index == 1 | ||
346 | || (blit_index == 3 && !surface->format->Amask))) { | ||
347 | if ( SDL_RLESurface(surface) == 0 ) | ||
348 | surface->map->sw_blit = SDL_RLEBlit; | ||
349 | } else if(blit_index == 2 && surface->format->Amask) { | ||
350 | if ( SDL_RLESurface(surface) == 0 ) | ||
351 | surface->map->sw_blit = SDL_RLEAlphaBlit; | ||
352 | } | ||
353 | } | ||
354 | |||
355 | if ( surface->map->sw_blit == NULL ) { | ||
356 | surface->map->sw_blit = SDL_SoftBlit; | ||
357 | } | ||
358 | return(0); | ||
359 | } | ||
360 | |||