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